mapserver-6.4.1/0000755002461700001440000000000012261257216013315 5ustar tbonfortusersmapserver-6.4.1/maptile.c0000644002461700001440000004142512261257215015121 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapServer Tile Access API * Author: Paul Ramsey * ****************************************************************************** * Copyright (c) 2008, Paul Ramsey * * 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. ****************************************************************************/ #include "maptile.h" #include "mapproject.h" #ifdef USE_TILE_API static void msTileResetMetatileLevel(mapObj *map) { hashTableObj *meta = &(map->web.metadata); const char *zero = "0"; const char *value = NULL; /* Is the tile_metatile_levetl set... */ if((value = msLookupHashTable(meta, "tile_metatile_level")) != NULL) { msRemoveHashTable(meta, "tile_metatile_level"); msInsertHashTable(meta, "tile_metatile_level", zero); } /* No tile_metatile_level value. */ else { msInsertHashTable(meta, "tile_metatile_level", zero); } } #endif /************************************************************************ * msTileGetGMapCoords * ************************************************************************/ static int msTileGetGMapCoords(const char *coordstring, int *x, int *y, int *zoom) { int num_coords = 0; char **coords = NULL; if( coordstring ) { coords = msStringSplit(coordstring, ' ', &(num_coords)); if( num_coords != 3 ) { msSetError(MS_WEBERR, "Invalid number of tile coordinates (should be three).", "msTileSetup()"); return MS_FAILURE; } } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return MS_FAILURE; } if( x ) *x = strtol(coords[0], NULL, 10); if( y ) *y = strtol(coords[1], NULL, 10); if( zoom ) *zoom = strtol(coords[2], NULL, 10); return MS_SUCCESS; } /************************************************************************ * msTileSetParams * ************************************************************************/ static void msTileGetParams(mapObj *map, tileParams *params) { const char *value = NULL; hashTableObj *meta = &(map->web.metadata); params->tile_size = SPHEREMERC_IMAGE_SIZE; /* Check for tile buffer, set to buffer==0 as default */ if((value = msLookupHashTable(meta, "tile_map_edge_buffer")) != NULL) { params->map_edge_buffer = atoi(value); if(map->debug) msDebug("msTileSetParams(): tile_map_edge_buffer = %d\n", params->map_edge_buffer); } else params->map_edge_buffer = 0; /* Check for metatile size, set to tile==metatile as default */ if((value = msLookupHashTable(meta, "tile_metatile_level")) != NULL) { params->metatile_level = atoi(value); /* Quietly force metatile_level to be sane */ if( params->metatile_level < 0 ) params->metatile_level = 0; if( params->metatile_level > 2 ) params->metatile_level = 2; if(map->debug) msDebug("msTileSetParams(): tile_metatile_level = %d\n", params->metatile_level); } else params->metatile_level = 0; } /************************************************************************ * msTileExtractSubTile * * * ************************************************************************/ static imageObj* msTileExtractSubTile(const mapservObj *msObj, const imageObj *img) { int width, mini, minj; int zoom = 2; imageObj* imgOut = NULL; tileParams params; rendererVTableObj *renderer; rasterBufferObj imgBuffer; if( !MS_RENDERER_PLUGIN(msObj->map->outputformat) || msObj->map->outputformat->renderer != img->format->renderer || ! MS_MAP_RENDERER(msObj->map)->supports_pixel_buffer ) { msSetError(MS_MISCERR,"unsupported or mixed renderers","msTileExtractSubTile()"); return NULL; } renderer = MS_MAP_RENDERER(msObj->map); if (renderer->getRasterBufferHandle((imageObj*)img,&imgBuffer) != MS_SUCCESS) { return NULL; } /* ** Load the metatiling information from the map file. */ msTileGetParams(msObj->map, ¶ms); /* ** Initialize values for the metatile clip area. */ width = img->width - 2*params.map_edge_buffer; mini = params.map_edge_buffer; minj = params.map_edge_buffer; if( msObj->TileMode == TILE_GMAP ) { int x, y, zoom; if( msObj->TileCoords ) { if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE ) return NULL; } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return NULL; } if(msObj->map->debug) msDebug("msTileExtractSubTile(): gmaps coords (x: %d, y: %d)\n",x,y); /* ** The bottom N bits of the coordinates give us the subtile ** location relative to the metatile. */ x = (0xffff ^ (0xffff << params.metatile_level)) & x; y = (0xffff ^ (0xffff << params.metatile_level)) & y; if(msObj->map->debug) msDebug("msTileExtractSubTile(): gmaps image coords (x: %d, y: %d)\n",x,y); mini = mini + x * params.tile_size; minj = minj + y * params.tile_size; } else if( msObj->TileMode == TILE_VE ) { int tsize; int i = 0; char j = 0; if( (int)strlen( msObj->TileCoords ) - params.metatile_level < 0 ) { return(NULL); } /* ** Process the last elements of the VE coordinate string to place the ** requested tile in the context of the metatile */ for( i = strlen( msObj->TileCoords ) - params.metatile_level; i < strlen( msObj->TileCoords ); i++ ) { j = msObj->TileCoords[i]; tsize = width / zoom; if( j == '1' || j == '3' ) mini += tsize; if( j == '2' || j == '3' ) minj += tsize; zoom *= 2; } } else { return(NULL); /* Huh? Should have a mode. */ } imgOut = msImageCreate(params.tile_size, params.tile_size, msObj->map->outputformat, NULL, NULL, msObj->map->resolution, msObj->map->defresolution, NULL); if( imgOut == NULL ) { return NULL; } if(msObj->map->debug) msDebug("msTileExtractSubTile(): extracting (%d x %d) tile, top corner (%d, %d)\n",params.tile_size,params.tile_size,mini,minj); renderer->mergeRasterBuffer(imgOut,&imgBuffer,1.0,mini, minj,0, 0,params.tile_size, params.tile_size); return imgOut; } /************************************************************************ * msTileSetup * * * * Called from mapserv.c, this is where the fun begins * * Set up projections and test the parameters for legality. * ************************************************************************/ int msTileSetup(mapservObj* msObj) { #ifdef USE_TILE_API char *outProjStr = NULL; tileParams params; /* ** Load the metatiling information from the map file. */ msTileGetParams(msObj->map, ¶ms); /* ** Ensure all the LAYERs have a projection. */ if( msMapSetLayerProjections(msObj->map) != 0 ) { return(MS_FAILURE); } /* ** Set the projection string for this mode. */ if( msObj->TileMode == TILE_GMAP || msObj->TileMode == TILE_VE ) { outProjStr = SPHEREMERC_PROJ4; } else { return MS_FAILURE; /* Huh? No mode? */ } if( msLoadProjectionString(&(msObj->map->projection), outProjStr) != 0 ) { msSetError(MS_CGIERR, "Unable to load projection string.", "msTileSetup()"); return MS_FAILURE; } /* ** Set up the output extents for this tilemode and tile coordinates */ if( msObj->TileMode == TILE_GMAP ) { int x, y, zoom; double zoomfactor; if( msObj->TileCoords ) { if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE ) return MS_FAILURE; } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return MS_FAILURE; } if( params.metatile_level >= zoom ) { msTileResetMetatileLevel(msObj->map); } zoomfactor = pow(2.0, (double)zoom); /* ** Check the input request for sanity. */ if( x >= zoomfactor || y >= zoomfactor ) { msSetError(MS_CGIERR, "GMap tile coordinates are too large for supplied zoom.", "msTileSetup()"); return(MS_FAILURE); } if( x < 0 || y < 0 ) { msSetError(MS_CGIERR, "GMap tile coordinates should not be less than zero.", "msTileSetup()"); return(MS_FAILURE); } } else if ( msObj->TileMode == TILE_VE ) { if( strspn( msObj->TileCoords, "0123" ) < strlen( msObj->TileCoords ) ) { msSetError(MS_CGIERR, "VE tile name should only include characters 0, 1, 2 and 3.", "msTileSetup()"); return(MS_FAILURE); } if( params.metatile_level >= strlen(msObj->TileCoords) ) { msTileResetMetatileLevel(msObj->map); } } else { return(MS_FAILURE); /* Huh? Should have a mode. */ } return MS_SUCCESS; #else msSetError(MS_CGIERR, "Tile API is not available.", "msTileSetup()"); return(MS_FAILURE); #endif } /************************************************************************ * msTileSetExtent * * * * Based on the input parameters, set the output extent for this * * tile. * ************************************************************************/ int msTileSetExtent(mapservObj* msObj) { #ifdef USE_TILE_API mapObj *map = msObj->map; double dx, dy, buffer; tileParams params; /* Read the tile-mode map file parameters */ msTileGetParams(msObj->map, ¶ms); if( msObj->TileMode == TILE_GMAP ) { int x, y, zoom; double zoomfactor, tilesize, xmin, xmax, ymin, ymax; if( msObj->TileCoords ) { if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE ) return MS_FAILURE; } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return MS_FAILURE; } if(map->debug) msDebug("msTileSetExtent(): gmaps coords (x: %d, y: %d, z: %d)\n",x,y,zoom); /* ** If we are metatiling, adjust the zoom level appropriately, ** then scale back the x/y coordinates to match the new level. */ if( params.metatile_level > 0 ) { zoom = zoom - params.metatile_level; x = x >> params.metatile_level; y = y >> params.metatile_level; } if(map->debug) msDebug("msTileSetExtent(): gmaps metacoords (x: %d, y: %d, z: %d)\n",x,y,zoom); zoomfactor = pow(2.0, (double)zoom); /* ** Calculate the ground extents of the tile request. */ /* printf("X: %i Y: %i Z: %i\n",x,y,zoom); */ tilesize = SPHEREMERC_GROUND_SIZE / zoomfactor; xmin = (x * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0); xmax = ((x + 1) * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0); ymin = (SPHEREMERC_GROUND_SIZE / 2.0) - ((y + 1) * tilesize); ymax = (SPHEREMERC_GROUND_SIZE / 2.0) - (y * tilesize); map->extent.minx = xmin; map->extent.maxx = xmax; map->extent.miny = ymin; map->extent.maxy = ymax; } else if( msObj->TileMode == TILE_VE ) { double minx = SPHEREMERC_GROUND_SIZE / -2.0; double miny = SPHEREMERC_GROUND_SIZE / -2.0; double maxx = SPHEREMERC_GROUND_SIZE / 2.0; double maxy = SPHEREMERC_GROUND_SIZE / 2.0; double zoom = 2.0; double tsize; int i = 0; char j = 0; /* ** Walk down the VE URL string, adjusting the extent each time. ** For meta-tiling cases, we stop early, to draw a larger image. */ for( i = 0; i < strlen( msObj->TileCoords ) - params.metatile_level; i++ ) { j = msObj->TileCoords[i]; tsize = SPHEREMERC_GROUND_SIZE / zoom; if( j == '1' || j == '3' ) minx += tsize; if( j == '0' || j == '2' ) maxx -= tsize; if( j == '2' || j == '3' ) maxy -= tsize; if( j == '0' || j == '1' ) miny += tsize; zoom *= 2.0; } map->extent.minx = minx; map->extent.maxx = maxx; map->extent.miny = miny; map->extent.maxy = maxy; } else { return(MS_FAILURE); /* Huh? Should have a mode. */ } /* ** Set the output tile size. */ msObj->ImgCols = SPHEREMERC_IMAGE_SIZE << params.metatile_level; msObj->ImgRows = SPHEREMERC_IMAGE_SIZE << params.metatile_level; map->width = SPHEREMERC_IMAGE_SIZE << params.metatile_level; map->height = SPHEREMERC_IMAGE_SIZE << params.metatile_level; if(map->debug) msDebug("msTileSetExtent(): base image size (%d x %d)\n",map->width,map->height); /* ** Add the gutters ** First calculate ground units in the buffer at current extent */ buffer = params.map_edge_buffer * (map->extent.maxx - map->extent.minx) / (double)map->width; /* ** Then adjust the map extents out by that amount */ map->extent.minx -= buffer; map->extent.maxx += buffer; map->extent.miny -= buffer; map->extent.maxy += buffer; /* ** Finally adjust the map image size by the pixel buffer */ map->width += 2 * params.map_edge_buffer; map->height += 2 * params.map_edge_buffer; msObj->ImgCols += 2 * params.map_edge_buffer; msObj->ImgRows += 2 * params.map_edge_buffer; if(map->debug) msDebug("msTileSetExtent(): buffered image size (%d x %d)\n",map->width,map->height); /* ** Adjust the extents inwards by 1/2 pixel so they are from ** center-of-pixel to center-of-pixel, instead of edge-to-edge. ** This is the way mapserver does it. */ dx = (map->extent.maxx - map->extent.minx) / map->width; map->extent.minx += dx*0.5; map->extent.maxx -= dx*0.5; dy = (map->extent.maxy - map->extent.miny) / map->height; map->extent.miny += dy*0.5; map->extent.maxy -= dy*0.5; /* ** Ensure the labelcache buffer is greater than the tile buffer. */ if( params.map_edge_buffer > 0 ) { const char *value; hashTableObj *meta = &(map->web.metadata); char tilebufferstr[64]; /* Write the tile buffer to a string */ snprintf(tilebufferstr, sizeof(tilebufferstr), "-%d", params.map_edge_buffer); /* Hm, the labelcache buffer is set... */ if((value = msLookupHashTable(meta, "labelcache_map_edge_buffer")) != NULL) { /* If it's too small, replace with a bigger one */ if( params.map_edge_buffer > abs(atoi(value)) ) { msRemoveHashTable(meta, "labelcache_map_edge_buffer"); msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr); } } /* No labelcache buffer value? Then we use the tile buffer. */ else { msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr); } } if(map->debug) { msDebug( "msTileSetExtent (%f, %f) (%f, %f)\n", map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy); } return MS_SUCCESS; #else msSetError(MS_CGIERR, "Tile API is not available.", "msTileSetExtent()"); return(MS_FAILURE); #endif } /************************************************************************ * msDrawTile * * * * Draw the tile once with gutters, metatiling and buffers, then * * clip out the final tile. * * WARNING: Call msTileSetExtent() first or this will be a pointless * * fucnction call. * ************************************************************************/ imageObj* msTileDraw(mapservObj *msObj) { imageObj *img; tileParams params; msTileGetParams(msObj->map, ¶ms); img = msDrawMap(msObj->map, MS_FALSE); if( img == NULL ) return NULL; if( params.metatile_level > 0 || params.map_edge_buffer > 0 ) { imageObj *tmp = msTileExtractSubTile(msObj, img); msFreeImage(img); if( tmp == NULL ) return NULL; img = tmp; } return img; } mapserver-6.4.1/mapraster.c0000644002461700001440000011244112261257215015461 0ustar tbonfortusers/****************************************************************************** * $id: mapraster.c 10772 2010-11-29 18:27:02Z aboudreault $ * * Project: MapServer * Purpose: msDrawRasterLayer(): generic raster layer drawing. * Author: Frank Warmerdam, warmerdam@pobox.com * Pete Olson (LMIC) * Steve Lime * ****************************************************************************** * Copyright (c) 1996-2010 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. ****************************************************************************/ #include #include "mapserver.h" #include "mapfile.h" #include "mapresample.h" #include "mapthread.h" extern int msyylex_destroy(void); extern int yyparse(parseObj *); extern parseResultObj yypresult; /* result of parsing, true/false */ #ifdef USE_GDAL #include "gdal.h" #include "cpl_string.h" #endif #include "mapraster.h" #define MAXCOLORS 256 #define BUFLEN 1024 #define HDRLEN 8 #define CVT(x) ((x) >> 8) /* converts to 8-bit color value */ #define NUMGRAYS 16 /************************************************************************/ /* msGetClass_String() */ /************************************************************************/ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value ) { int i; const char *tmpstr1=NULL; int numitems; char *item_names[4] = { "pixel", "red", "green", "blue" }; char *item_values[4]; char red_value[8], green_value[8], blue_value[8]; /* -------------------------------------------------------------------- */ /* No need to do a lookup in the case of one default class. */ /* -------------------------------------------------------------------- */ if((layer->numclasses == 1) && !(layer->class[0]->expression.string)) /* no need to do lookup */ return(0); /* -------------------------------------------------------------------- */ /* Setup values list for expressions. */ /* -------------------------------------------------------------------- */ numitems = 4; sprintf( red_value, "%d", color->red ); sprintf( green_value, "%d", color->green ); sprintf( blue_value, "%d", color->blue ); item_values[0] = (char *)pixel_value; item_values[1] = red_value; item_values[2] = green_value; item_values[3] = blue_value; /* -------------------------------------------------------------------- */ /* Loop over classes till we find a match. */ /* -------------------------------------------------------------------- */ for(i=0; inumclasses; i++) { /* check for correct classgroup, if set */ if ( layer->class[i]->group && layer->classgroup && strcasecmp(layer->class[i]->group, layer->classgroup) != 0 ) continue; /* Empty expression - always matches */ if (layer->class[i]->expression.string == NULL) return(i); switch(layer->class[i]->expression.type) { /* -------------------------------------------------------------------- */ /* Simple string match */ /* -------------------------------------------------------------------- */ case(MS_STRING): /* trim junk white space */ tmpstr1= pixel_value; while( *tmpstr1 == ' ' ) tmpstr1++; if(strcmp(layer->class[i]->expression.string, tmpstr1) == 0) return(i); /* matched */ break; /* -------------------------------------------------------------------- */ /* Regular expression. Rarely used for raster. */ /* -------------------------------------------------------------------- */ case(MS_REGEX): if(!layer->class[i]->expression.compiled) { if(ms_regcomp(&(layer->class[i]->expression.regex), layer->class[i]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msGetClass()"); return(-1); } layer->class[i]->expression.compiled = MS_TRUE; } if(ms_regexec(&(layer->class[i]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(i); /* got a match */ break; /* -------------------------------------------------------------------- */ /* Parsed expression. */ /* -------------------------------------------------------------------- */ case(MS_EXPRESSION): { int status; parseObj p; shapeObj dummy_shape; expressionObj *expression = &(layer->class[i]->expression); dummy_shape.numvalues = numitems; dummy_shape.values = item_values; if( expression->tokens == NULL ) msTokenizeExpression( expression, item_names, &numitems ); p.shape = &dummy_shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse expression: %s", "msGetClass_FloatRGB", expression->string); return -1; } if( p.result.intval ) return i; break; } } } return(-1); /* not found */ } /************************************************************************/ /* msGetClass() */ /************************************************************************/ int msGetClass(layerObj *layer, colorObj *color, int colormap_index) { char pixel_value[12]; snprintf( pixel_value, sizeof(pixel_value), "%d", colormap_index ); return msGetClass_String( layer, color, pixel_value ); } /************************************************************************/ /* msGetClass_FloatRGB() */ /* */ /* Returns the class based on classification of a floating */ /* pixel value. */ /************************************************************************/ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue ) { char pixel_value[100]; colorObj color; color.red = red; color.green = green; color.blue = blue; snprintf( pixel_value, sizeof(pixel_value), "%18g", fValue ); return msGetClass_String( layer, &color, pixel_value ); } #ifdef USE_GD /************************************************************************/ /* msAddColorGD() */ /* */ /* Function to add a color to an existing color map. It first */ /* looks for an exact match, then tries to add it to the end of */ /* the existing color map, and if all else fails it finds the */ /* closest color. */ /************************************************************************/ int msAddColorGD(mapObj *map, gdImagePtr img, int cmt, int r, int g, int b) { int c; int ct = -1; int op = -1; long rd, gd, bd, dist; long mindist = 3*255*255; /* init to max poss dist */ if( gdImageTrueColor( img ) ) return gdTrueColor( r, g, b ); /* ** We want to avoid using a color that matches a transparent background ** color exactly. If this is the case, we will permute the value slightly. ** When perterbing greyscale images we try to keep them greyscale, otherwise ** we just perterb the red component. */ if( map->outputformat && map->outputformat->transparent && map->imagecolor.red == r && map->imagecolor.green == g && map->imagecolor.blue == b ) { if( r == 0 && g == 0 && b == 0 ) { r = g = b = 1; } else if( r == g && r == b ) { r = g = b = r-1; } else if( r == 0 ) { r = 1; } else { r = r-1; } } /* ** Find the nearest color in the color table. If we get an exact match ** return it right away. */ for (c = 0; c < img->colorsTotal; c++) { if (img->open[c]) { op = c; /* Save open slot */ continue; /* Color not in use */ } /* don't try to use the transparent color */ if (map->outputformat && map->outputformat->transparent && img->red [c] == map->imagecolor.red && img->green[c] == map->imagecolor.green && img->blue [c] == map->imagecolor.blue ) continue; rd = (long)(img->red [c] - r); gd = (long)(img->green[c] - g); bd = (long)(img->blue [c] - b); /* -------------------------------------------------------------------- */ /* special case for grey colors (r=g=b). we will try to find */ /* either the nearest grey or a color that is almost grey. */ /* -------------------------------------------------------------------- */ if (r == g && r == b) { if (img->red == img->green && img->red == img->blue) dist = rd*rd; else dist = rd * rd + gd * gd + bd * bd; } else dist = rd * rd + gd * gd + bd * bd; if (dist < mindist) { if (dist == 0) { return c; /* Return exact match color */ } mindist = dist; ct = c; } } /* no exact match, is the closest within our "color match threshold"? */ if( mindist <= cmt*cmt ) return ct; /* no exact match. If there are no open colors we return the closest color found. */ if (op == -1) { op = img->colorsTotal; if (op == gdMaxColors) { /* No room for more colors */ return ct; /* Return closest available color */ } img->colorsTotal++; } /* allocate a new exact match */ img->red [op] = r; img->green[op] = g; img->blue [op] = b; img->open [op] = 0; return op; /* Return newly allocated color */ } #endif #if defined(USE_GDAL) /************************************************************************/ /* msRasterSetupTileLayer() */ /* */ /* Setup the tile layer. */ /************************************************************************/ int msDrawRasterSetupTileLayer(mapObj *map, layerObj *layer, rectObj* psearchrect, int is_query, int* ptilelayerindex, /* output */ int* ptileitemindex, /* output */ int* ptilesrsindex, /* output */ layerObj **ptlp /* output */ ) { int i; char* requested_fields; int status; layerObj* tlp = NULL; *ptilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); if(*ptilelayerindex == -1) { /* the tileindex references a file, not a layer */ /* so we create a temporary layer */ tlp = (layerObj *) malloc(sizeof(layerObj)); MS_CHECK_ALLOC(tlp, sizeof(layerObj), MS_FAILURE); initLayer(tlp, map); *ptlp = tlp; /* set a few parameters for a very basic shapefile-based layer */ tlp->name = msStrdup("TILE"); tlp->type = MS_LAYER_TILEINDEX; tlp->data = msStrdup(layer->tileindex); if( is_query ) { tlp->map = map; /*needed when scaletokens are applied, to extract current map scale */ for(i = 0; i < layer->numscaletokens; i++) { if(msGrowLayerScaletokens(tlp) == NULL) { return MS_FAILURE; } initScaleToken(&tlp->scaletokens[i]); msCopyScaleToken(&layer->scaletokens[i],&tlp->scaletokens[i]); tlp->numscaletokens++; } } if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { tlp->projection.numargs = 1; tlp->projection.args[0] = msStrdup("auto"); } if (layer->filteritem) tlp->filteritem = msStrdup(layer->filteritem); if (layer->filter.string) { if (layer->filter.type == MS_EXPRESSION) { char* pszTmp = (char *)msSmallMalloc(sizeof(char)*(strlen(layer->filter.string)+3)); sprintf(pszTmp,"(%s)",layer->filter.string); msLoadExpressionString(&tlp->filter, pszTmp); free(pszTmp); } else if (layer->filter.type == MS_REGEX || layer->filter.type == MS_IREGEX) { char* pszTmp = (char *)msSmallMalloc(sizeof(char)*(strlen(layer->filter.string)+3)); sprintf(pszTmp,"/%s/",layer->filter.string); msLoadExpressionString(&tlp->filter, pszTmp); free(pszTmp); } else msLoadExpressionString(&tlp->filter, layer->filter.string); tlp->filter.type = layer->filter.type; } } else { if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tlp = (GET_LAYER(layer->map, *ptilelayerindex)); *ptlp = tlp; } status = msLayerOpen(tlp); if(status != MS_SUCCESS) { return status; } /* fetch tileitem and tilesrs fields */ requested_fields = (char*) msSmallMalloc(sizeof(char)*(strlen(layer->tileitem)+1+ (layer->tilesrs ? strlen(layer->tilesrs) : 0) + 1)); if( layer->tilesrs != NULL ) sprintf(requested_fields, "%s,%s", layer->tileitem, layer->tilesrs); else strcpy(requested_fields, layer->tileitem); status = msLayerWhichItems(tlp, MS_FALSE, requested_fields); msFree(requested_fields); if(status != MS_SUCCESS) { return status; } /* get the tileitem and tilesrs index */ for(i=0; inumitems; i++) { if(strcasecmp(tlp->items[i], layer->tileitem) == 0) { *ptileitemindex = i; } if(layer->tilesrs != NULL && strcasecmp(tlp->items[i], layer->tilesrs) == 0) { *ptilesrsindex = i; } } if(*ptileitemindex < 0) { /* didn't find it */ msSetError(MS_MEMERR, "Could not find attribute %s in tileindex.", "msDrawRasterLayerLow()", layer->tileitem); return MS_FAILURE; } if(layer->tilesrs != NULL && *ptilesrsindex < 0) { /* didn't find it */ msSetError(MS_MEMERR, "Could not find attribute %s in tileindex.", "msDrawRasterLayerLow()", layer->tilesrs); return MS_FAILURE; } #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if((map->projection.numargs > 0) && (layer->projection.numargs > 0) && !EQUAL(layer->projection.args[0], "auto")) { if( msProjectRect(&map->projection, &layer->projection, psearchrect) != MS_SUCCESS ) { msDebug( "msDrawRasterLayerLow(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name ); return MS_FAILURE; } } else if((map->projection.numargs > 0) && (tlp->projection.numargs > 0) && !EQUAL(tlp->projection.args[0], "auto")) { if( msProjectRect(&map->projection, &tlp->projection, psearchrect) != MS_SUCCESS ) { msDebug( "msDrawRasterLayerLow(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name ); return MS_FAILURE; } } #endif return msLayerWhichShapes(tlp, *psearchrect, MS_FALSE); } /************************************************************************/ /* msDrawRasterCleanupTileLayer() */ /* */ /* Cleanup the tile layer. */ /************************************************************************/ void msDrawRasterCleanupTileLayer(layerObj* tlp, int tilelayerindex) { msLayerClose(tlp); if(tilelayerindex == -1) { freeLayer(tlp); free(tlp); } } /************************************************************************/ /* msDrawRasterIterateTileIndex() */ /* */ /* Iterate over the tile layer. */ /************************************************************************/ int msDrawRasterIterateTileIndex(layerObj *layer, layerObj* tlp, shapeObj* ptshp, /* input-output */ int tileitemindex, int tilesrsindex, char* tilename, /* output */ size_t sizeof_tilename, char* tilesrsname, /* output */ size_t sizeof_tilesrsname) { int status; status = msLayerNextShape(tlp, ptshp); if( status == MS_FAILURE || status == MS_DONE ) { return status; } if(layer->data == NULL || strlen(layer->data) == 0 ) { /* assume whole filename is in attribute field */ strlcpy( tilename, ptshp->values[tileitemindex], sizeof_tilename); } else snprintf(tilename, sizeof_tilename, "%s/%s", ptshp->values[tileitemindex], layer->data); tilesrsname[0] = '\0'; if( tilesrsindex >= 0 ) { if(ptshp->values[tilesrsindex] != NULL ) strlcpy( tilesrsname, ptshp->values[tilesrsindex], sizeof_tilesrsname ); } msFreeShape(ptshp); /* done with the shape */ return status; } /************************************************************************/ /* msDrawRasterBuildRasterPath() */ /* */ /* Build the path of the raster to open. */ /************************************************************************/ int msDrawRasterBuildRasterPath(mapObj *map, layerObj *layer, const char* filename, char szPath[MS_MAXPATHLEN] /* output */) { /* ** If using a tileindex then build the path relative to that file if SHAPEPATH is not set. */ if(layer->tileindex && !map->shapepath) { char tiAbsFilePath[MS_MAXPATHLEN]; char *tiAbsDirPath = NULL; msTryBuildPath(tiAbsFilePath, map->mappath, layer->tileindex); /* absolute path to tileindex file */ tiAbsDirPath = msGetPath(tiAbsFilePath); /* tileindex file's directory */ msBuildPath(szPath, tiAbsDirPath, filename); free(tiAbsDirPath); } else { msTryBuildPath3(szPath, map->mappath, map->shapepath, filename); } return MS_SUCCESS; } /************************************************************************/ /* msDrawRasterGetCPLErrorMsg() */ /* */ /* Return the CPL error message, and filter out sensitive info. */ /************************************************************************/ const char* msDrawRasterGetCPLErrorMsg(const char* decrypted_path, const char* szPath) { const char *cpl_error_msg = CPLGetLastErrorMsg(); /* we wish to avoid reporting decrypted paths */ if( cpl_error_msg != NULL && strstr(cpl_error_msg,decrypted_path) != NULL && strcmp(decrypted_path,szPath) != 0 ) cpl_error_msg = NULL; /* we wish to avoid reporting the stock GDALOpen error messages */ if( cpl_error_msg != NULL && (strstr(cpl_error_msg,"not recognised as a supported") != NULL || strstr(cpl_error_msg,"does not exist") != NULL) ) cpl_error_msg = NULL; if( cpl_error_msg == NULL ) cpl_error_msg = ""; return cpl_error_msg; } /************************************************************************/ /* msDrawRasterLoadProjection() */ /* */ /* Handle TILESRS or PROJECTION AUTO for each tile. */ /************************************************************************/ int msDrawRasterLoadProjection(layerObj *layer, GDALDatasetH hDS, const char* filename, int tilesrsindex, const char* tilesrsname) { /* ** Generate the projection information if using TILESRS. */ if( tilesrsindex >= 0 ) { const char *pszWKT; if( tilesrsname[0] != '\0' ) pszWKT = tilesrsname; else pszWKT = GDALGetProjectionRef( hDS ); if( pszWKT != NULL && strlen(pszWKT) > 0 ) { if( msOGCWKT2ProjectionObj(pszWKT, &(layer->projection), layer->debug ) != MS_SUCCESS ) { char szLongMsg[MESSAGELENGTH*2]; errorObj *ms_error = msGetErrorObj(); snprintf( szLongMsg, sizeof(szLongMsg), "%s\n" "PROJECTION '%s' cannot be used for this " "GDAL raster (`%s').", ms_error->message, pszWKT, filename); szLongMsg[MESSAGELENGTH-1] = '\0'; msSetError(MS_OGRERR, "%s","msDrawRasterLayer()", szLongMsg); return MS_FAILURE; } } } /* ** Generate the projection information if using AUTO. */ else if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { const char *pszWKT; pszWKT = GDALGetProjectionRef( hDS ); if( pszWKT != NULL && strlen(pszWKT) > 0 ) { if( msOGCWKT2ProjectionObj(pszWKT, &(layer->projection), layer->debug ) != MS_SUCCESS ) { char szLongMsg[MESSAGELENGTH*2]; errorObj *ms_error = msGetErrorObj(); snprintf( szLongMsg, sizeof(szLongMsg), "%s\n" "PROJECTION AUTO cannot be used for this " "GDAL raster (`%s').", ms_error->message, filename); szLongMsg[MESSAGELENGTH-1] = '\0'; msSetError(MS_OGRERR, "%s","msDrawRasterLayer()", szLongMsg); return MS_FAILURE; } } } return MS_SUCCESS; } #endif // defined(USE_GDAL) /************************************************************************/ /* msDrawRasterLayerLow() */ /* */ /* Check for various file types and act appropriately. Handle */ /* tile indexing. */ /************************************************************************/ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb ) { /* -------------------------------------------------------------------- */ /* As of MapServer 6.0 GDAL is required for rendering raster */ /* imagery. */ /* -------------------------------------------------------------------- */ #if !defined(USE_GDAL) msSetError(MS_MISCERR, "Attempt to render a RASTER (or WMS) layer but without\n" "GDAL support enabled. Raster rendering requires GDAL.", "msDrawRasterLayerLow()" ); return MS_FAILURE; #else /* defined(USE_GDAL) */ int status, i, done; char *filename=NULL, tilename[MS_MAXPATHLEN], tilesrsname[1024]; layerObj *tlp=NULL; /* pointer to the tile layer either real or temporary */ int tileitemindex=-1, tilelayerindex=-1, tilesrsindex=-1; shapeObj tshp; char szPath[MS_MAXPATHLEN]; char *decrypted_path; int final_status = MS_SUCCESS; rectObj searchrect; GDALDatasetH hDS; double adfGeoTransform[6]; const char *close_connection; msGDALInitialize(); if(layer->debug > 0 || map->debug > 1) msDebug( "msDrawRasterLayerLow(%s): entering.\n", layer->name ); if(!layer->data && !layer->tileindex) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): layer data and tileindex NULL ... doing nothing.", layer->name ); return(0); } if((layer->status != MS_ON) && (layer->status != MS_DEFAULT)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): not status ON or DEFAULT, doing nothing.", layer->name ); return(0); } if(map->scaledenom > 0) { if((layer->maxscaledenom > 0) && (map->scaledenom > layer->maxscaledenom)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map scale %.2g > MAXSCALEDENOM=%g\n", layer->name, map->scaledenom, layer->maxscaledenom ); return(0); } if((layer->minscaledenom > 0) && (map->scaledenom <= layer->minscaledenom)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map scale %.2g < MINSCALEDENOM=%g\n", layer->name, map->scaledenom, layer->minscaledenom ); return(0); } } if(layer->maxscaledenom <= 0 && layer->minscaledenom <= 0) { if((layer->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > layer->maxgeowidth)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map width %.2g > MAXSCALEDENOM=%g\n", layer->name, (map->extent.maxx - map->extent.minx), layer->maxgeowidth ); return(0); } if((layer->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < layer->mingeowidth)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map width %.2g < MINSCALEDENOM=%g\n", layer->name, (map->extent.maxx - map->extent.minx), layer->mingeowidth ); return(0); } } if(layer->tileindex) { /* we have an index file */ msInitShape(&tshp); searchrect = map->extent; status = msDrawRasterSetupTileLayer(map, layer, &searchrect, MS_FALSE, &tilelayerindex, &tileitemindex, &tilesrsindex, &tlp); if(status != MS_SUCCESS) { if (status != MS_DONE) final_status = status; goto cleanup; } } done = MS_FALSE; while(done != MS_TRUE) { if(layer->tileindex) { status = msDrawRasterIterateTileIndex(layer, tlp, &tshp, tileitemindex, tilesrsindex, tilename, sizeof(tilename), tilesrsname, sizeof(tilesrsname)); if( status == MS_FAILURE) { final_status = MS_FAILURE; break; } if(status == MS_DONE) break; /* no more tiles/images */ filename = tilename; } else { filename = layer->data; done = MS_TRUE; /* only one image so we're done after this */ } if(strlen(filename) == 0) continue; if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): Filename is: %s\n", layer->name, filename); msDrawRasterBuildRasterPath(map, layer, filename, szPath); if(layer->debug == MS_TRUE) msDebug("msDrawRasterLayerLow(%s): Path is: %s\n", layer->name, szPath); /* ** Note: because we do decryption after the above path expansion ** which depends on actually finding a file, it essentially means that ** fancy path manipulation is essentially disabled when using encrypted ** components. But that is mostly ok, since stuff like sde,postgres and ** oracle georaster do not use real paths. */ decrypted_path = msDecryptStringTokens( map, szPath ); if( decrypted_path == NULL ) return MS_FAILURE; msAcquireLock( TLOCK_GDAL ); hDS = GDALOpenShared( decrypted_path, GA_ReadOnly ); /* ** If GDAL doesn't recognise it, and it wasn't successfully opened ** Generate an error. */ if(hDS == NULL) { int ignore_missing = msMapIgnoreMissingData(map); const char *cpl_error_msg = msDrawRasterGetCPLErrorMsg(decrypted_path, szPath); msFree( decrypted_path ); decrypted_path = NULL; msReleaseLock( TLOCK_GDAL ); if(ignore_missing == MS_MISSING_DATA_FAIL) { msSetError(MS_IOERR, "Corrupt, empty or missing file '%s' for layer '%s'. %s", "msDrawRasterLayerLow()", szPath, layer->name, cpl_error_msg ); return(MS_FAILURE); } else if( ignore_missing == MS_MISSING_DATA_LOG ) { if( layer->debug || layer->map->debug ) { msDebug( "Corrupt, empty or missing file '%s' for layer '%s' ... ignoring this missing data. %s\n", szPath, layer->name, cpl_error_msg ); } continue; } else if( ignore_missing == MS_MISSING_DATA_IGNORE ) { continue; } else { /* never get here */ msSetError(MS_IOERR, "msIgnoreMissingData returned unexpected value.", "msDrawRasterLayerLow()"); return(MS_FAILURE); } } msFree( decrypted_path ); decrypted_path = NULL; if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS ) { msReleaseLock( TLOCK_GDAL ); final_status = MS_FAILURE; break; } msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform ); /* ** We want to resample if the source image is rotated, if ** the projections differ or if resampling has been explicitly ** requested, or if the image has north-down instead of north-up. */ #ifdef USE_PROJ if( ((adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] > 0.0 || adfGeoTransform[1] < 0.0 ) && layer->transform ) || msProjectionsDiffer( &(map->projection), &(layer->projection) ) || CSLFetchNameValue( layer->processing, "RESAMPLE" ) != NULL ) { status = msResampleGDALToMap( map, layer, image, rb, hDS ); } else #endif { if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 ) { if( layer->debug || map->debug ) msDebug( "Layer %s has rotational coefficients but we\n" "are unable to use them, projections support\n" "needs to be built in.", layer->name ); } status = msDrawRasterLayerGDAL(map, layer, image, rb, hDS ); } if( status == -1 ) { GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); final_status = MS_FAILURE; break; } /* ** Should we keep this file open for future use? ** default to keeping open for single data files, and ** to closing for tile indexes */ close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); if( close_connection == NULL && layer->tileindex == NULL ) close_connection = "DEFER"; if( close_connection != NULL && strcasecmp(close_connection,"DEFER") == 0 ) { GDALDereferenceDataset( hDS ); } else { GDALClose( hDS ); } msReleaseLock( TLOCK_GDAL ); } /* next tile */ cleanup: if(layer->tileindex) { /* tiling clean-up */ msDrawRasterCleanupTileLayer(tlp, tilelayerindex); } return final_status; #endif /* defined(USE_GDAL) */ } /************************************************************************/ /* msDrawReferenceMap() */ /************************************************************************/ imageObj *msDrawReferenceMap(mapObj *map) { double cellsize; int x1,y1,x2,y2; char szPath[MS_MAXPATHLEN]; imageObj *image = NULL; styleObj style; rendererVTableObj *renderer = MS_MAP_RENDERER(map); rasterBufferObj *refImage = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(refImage, sizeof(rasterBufferObj), NULL); if(MS_SUCCESS != renderer->loadImageFromFile(msBuildPath(szPath, map->mappath, map->reference.image),refImage)) { msSetError(MS_MISCERR,"error loading reference image %s","msDrawREferenceMap()",szPath); return NULL; } image = msImageCreate(refImage->width, refImage->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &(map->reference.color)); renderer->mergeRasterBuffer(image,refImage,1.0,0,0,0,0,refImage->width, refImage->height); msFreeRasterBuffer(refImage); free(refImage); /* make sure the extent given in mapfile fits the image */ cellsize = msAdjustExtent(&(map->reference.extent), image->width, image->height); /* convert map extent to reference image coordinates */ x1 = MS_MAP2IMAGE_X(map->extent.minx, map->reference.extent.minx, cellsize); x2 = MS_MAP2IMAGE_X(map->extent.maxx, map->reference.extent.minx, cellsize); y1 = MS_MAP2IMAGE_Y(map->extent.maxy, map->reference.extent.maxy, cellsize); y2 = MS_MAP2IMAGE_Y(map->extent.miny, map->reference.extent.maxy, cellsize); initStyle(&style); style.color = map->reference.color; style.outlinecolor = map->reference.outlinecolor; /* if extent are smaller than minbox size */ /* draw that extent on the reference image */ if( (abs(x2 - x1) > map->reference.minboxsize) || (abs(y2 - y1) > map->reference.minboxsize) ) { shapeObj rect; lineObj line; pointObj points[5]; msInitShape(&rect); line.point = points; line.numpoints = 5; rect.line = &line; rect.numlines = 1; rect.type = MS_SHAPE_POLYGON; line.point[0].x = x1; line.point[0].y = y1; line.point[1].x = x1; line.point[1].y = y2; line.point[2].x = x2; line.point[2].y = y2; line.point[3].x = x2; line.point[3].y = y1; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; if( map->reference.maxboxsize == 0 || ((abs(x2 - x1) < map->reference.maxboxsize) && (abs(y2 - y1) < map->reference.maxboxsize)) ) { msDrawShadeSymbol(&(map->symbolset), image, &rect, &style, 1.0); } } else { /* else draw the marker symbol */ if( map->reference.maxboxsize == 0 || ((abs(x2 - x1) < map->reference.maxboxsize) && (abs(y2 - y1) < map->reference.maxboxsize)) ) { style.size = map->reference.markersize; /* if the marker symbol is specify draw this symbol else draw a cross */ if(map->reference.marker != 0) { pointObj *point = NULL; point = msSmallMalloc(sizeof(pointObj)); point->x = (double)(x1 + x2)/2; point->y = (double)(y1 + y2)/2; style.symbol = map->reference.marker; msDrawMarkerSymbol(&map->symbolset, image, point, &style, 1.0); free(point); } else if(map->reference.markername != NULL) { pointObj *point = NULL; point = msSmallMalloc(sizeof(pointObj)); point->x = (double)(x1 + x2)/2; point->y = (double)(y1 + y2)/2; style.symbol = msGetSymbolIndex(&map->symbolset, map->reference.markername, MS_TRUE); msDrawMarkerSymbol(&map->symbolset, image, point, &style, 1.0); free(point); } else { int x21, y21; shapeObj cross; lineObj lines[4]; pointObj point[8]; int i; /* determine the center point */ x21 = MS_NINT((x1 + x2)/2); y21 = MS_NINT((y1 + y2)/2); msInitShape(&cross); cross.numlines = 4; cross.line = lines; for(i=0; i<4; i++) { cross.line[i].numpoints = 2; cross.line[i].point = &(point[2*i]); } /* draw a cross */ cross.line[0].point[0].x = x21-8; cross.line[0].point[0].y = y21; cross.line[0].point[1].x = x21-3; cross.line[0].point[1].y = y21; cross.line[1].point[0].x = x21; cross.line[1].point[0].y = y21-8; cross.line[1].point[1].x = x21; cross.line[1].point[1].y = y21-3; cross.line[2].point[0].x = x21; cross.line[2].point[0].y = y21+3; cross.line[2].point[1].x = x21; cross.line[2].point[1].y = y21+8; cross.line[3].point[0].x = x21+3; cross.line[3].point[0].y = y21; cross.line[3].point[1].x = x21+8; cross.line[3].point[1].y = y21; msDrawLineSymbol(&(map->symbolset),image,&cross,&style,1.0); } } } return(image); } mapserver-6.4.1/maptree.c0000644002461700001440000006237112261257215015126 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: .qix spatial index implementation. Derived from shapelib, and * relicensed with permission of Frank Warmerdam (shapelib author). * Author: Steve Lime * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maptree.h" /* -------------------------------------------------------------------- */ /* If the following is 0.5, nodes will be split in half. If it */ /* is 0.6 then each subnode will contain 60% of the parent */ /* node, with 20% representing overlap. This can be help to */ /* prevent small objects on a boundary from shifting too high */ /* up the tree. */ /* -------------------------------------------------------------------- */ #define SPLITRATIO 0.55 static int treeAddShapeId(treeObj *tree, int id, rectObj rect); static void SwapWord( int length, void * wordP ) { int i; uchar temp; for( i=0; i < length/2; i++ ) { temp = ((uchar *) wordP)[i]; ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1]; ((uchar *) wordP)[length-i-1] = temp; } } static void * SfRealloc( void * pMem, int nNewSize ) { if( pMem == NULL ) return( (void *) malloc(nNewSize) ); else return( (void *) realloc(pMem,nNewSize) ); } static treeNodeObj *treeNodeCreate(rectObj rect) { treeNodeObj *node; node = (treeNodeObj *) msSmallMalloc(sizeof(treeNodeObj)); node->numshapes = 0; node->ids = NULL; node->numsubnodes = 0; memcpy(&(node->rect), &(rect), sizeof(rectObj)); return node; } SHPTreeHandle msSHPDiskTreeOpen(const char * pszTree, int debug) { char *pszFullname, *pszBasename; SHPTreeHandle psTree; char pabyBuf[16]; int i; char bBigEndian; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Initialize the info structure. */ /* -------------------------------------------------------------------- */ psTree = (SHPTreeHandle) msSmallMalloc(sizeof(SHPTreeInfo)); /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszTree)+5); strcpy( pszBasename, pszTree ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, MS_INDEX_EXTENSION); psTree->fp = fopen(pszFullname, "rb" ); if( psTree->fp == NULL ) { sprintf( pszFullname, "%s.QIX", pszBasename); psTree->fp = fopen(pszFullname, "rb" ); } msFree(pszBasename); /* don't need these any more */ msFree(pszFullname); if( psTree->fp == NULL ) { msFree(psTree); return( NULL ); } fread( pabyBuf, 8, 1, psTree->fp ); memcpy( &psTree->signature, pabyBuf, 3 ); if( strncmp(psTree->signature,"SQT",3) ) { /* ---------------------------------------------------------------------- */ /* must check if the 2 first bytes equal 0 of max depth that cannot */ /* be more than 65535. If yes, we must swap all value. The problem */ /* here is if there's no Depth (bytea 5,6,7,8 in the file) all bytes */ /* will be set to 0. So,we will test with the number of shapes (bytes */ /* 1,2,3,4) that cannot be more than 65535 too. */ /* ---------------------------------------------------------------------- */ if (debug) { msDebug("WARNING in msSHPDiskTreeOpen(): %s is in old index format " "which has been deprecated. It is strongly recommended to " "regenerate it in new format.\n", pszTree); } if((pabyBuf[4] == 0 && pabyBuf[5] == 0 && pabyBuf[6] == 0 && pabyBuf[7] == 0)) { psTree->LSB_order = !(pabyBuf[0] == 0 && pabyBuf[1] == 0); } else { psTree->LSB_order = !(pabyBuf[4] == 0 && pabyBuf[5] == 0); } psTree->needswap = ((psTree->LSB_order) != (!bBigEndian)); /* ---------------------------------------------------------------------- */ /* poor hack to see if this quadtree was created by a computer with a */ /* different Endian */ /* ---------------------------------------------------------------------- */ psTree->version = 0; } else { psTree->needswap = (( pabyBuf[3] == MS_NEW_MSB_ORDER ) ^ ( bBigEndian )); psTree->LSB_order = ( pabyBuf[3] == MS_NEW_LSB_ORDER ); memcpy( &psTree->version, pabyBuf+4, 1 ); memcpy( &psTree->flags, pabyBuf+5, 3 ); fread( pabyBuf, 8, 1, psTree->fp ); } if( psTree->needswap ) SwapWord( 4, pabyBuf ); memcpy( &psTree->nShapes, pabyBuf, 4 ); if( psTree->needswap ) SwapWord( 4, pabyBuf+4 ); memcpy( &psTree->nDepth, pabyBuf+4, 4 ); return( psTree ); } void msSHPDiskTreeClose(SHPTreeHandle disktree) { fclose( disktree->fp ); free( disktree ); } treeObj *msCreateTree(shapefileObj *shapefile, int maxdepth) { int i; treeObj *tree; rectObj bounds; if(!shapefile) return NULL; /* -------------------------------------------------------------------- */ /* Allocate the tree object */ /* -------------------------------------------------------------------- */ tree = (treeObj *) msSmallMalloc(sizeof(treeObj)); tree->numshapes = shapefile->numshapes; tree->maxdepth = maxdepth; /* -------------------------------------------------------------------- */ /* If no max depth was defined, try to select a reasonable one */ /* that implies approximately 8 shapes per node. */ /* -------------------------------------------------------------------- */ if( tree->maxdepth == 0 ) { int numnodes = 1; while(numnodes*4 < shapefile->numshapes) { tree->maxdepth += 1; numnodes = numnodes * 2; } } /* -------------------------------------------------------------------- */ /* Allocate the root node. */ /* -------------------------------------------------------------------- */ tree->root = treeNodeCreate(shapefile->bounds); for(i=0; inumshapes; i++) { if(msSHPReadBounds(shapefile->hSHP, i, &bounds) == MS_SUCCESS) treeAddShapeId(tree, i, bounds); } return tree; } static void destroyTreeNode(treeNodeObj *node) { int i; for(i=0; inumsubnodes; i++ ) { if(node->subnode[i]) destroyTreeNode(node->subnode[i]); } if(node->ids) free(node->ids); free(node); } void msDestroyTree(treeObj *tree) { destroyTreeNode(tree->root); free(tree); } static void treeSplitBounds( rectObj *in, rectObj *out1, rectObj *out2) { double range; /* -------------------------------------------------------------------- */ /* The output bounds will be very similar to the input bounds, */ /* so just copy over to start. */ /* -------------------------------------------------------------------- */ memcpy(out1, in, sizeof(rectObj)); memcpy(out2, in, sizeof(rectObj)); /* -------------------------------------------------------------------- */ /* Split in X direction. */ /* -------------------------------------------------------------------- */ if((in->maxx - in->minx) > (in->maxy - in->miny)) { range = in->maxx - in->minx; out1->maxx = in->minx + range * SPLITRATIO; out2->minx = in->maxx - range * SPLITRATIO; } /* -------------------------------------------------------------------- */ /* Otherwise split in Y direction. */ /* -------------------------------------------------------------------- */ else { range = in->maxy - in->miny; out1->maxy = in->miny + range * SPLITRATIO; out2->miny = in->maxy - range * SPLITRATIO; } } static int treeNodeAddShapeId( treeNodeObj *node, int id, rectObj rect, int maxdepth) { int i; /* -------------------------------------------------------------------- */ /* If there are subnodes, then consider whether this object */ /* will fit in them. */ /* -------------------------------------------------------------------- */ if( maxdepth > 1 && node->numsubnodes > 0 ) { for(i=0; inumsubnodes; i++ ) { if( msRectContained(&rect, &node->subnode[i]->rect)) { return treeNodeAddShapeId( node->subnode[i], id, rect, maxdepth-1); } } } /* -------------------------------------------------------------------- */ /* Otherwise, consider creating four subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ #if MAX_SUBNODES == 4 else if( maxdepth > 1 && node->numsubnodes == 0 ) { rectObj half1, half2, quad1, quad2, quad3, quad4; treeSplitBounds(&node->rect, &half1, &half2); treeSplitBounds(&half1, &quad1, &quad2); treeSplitBounds(&half2, &quad3, &quad4); if(msRectContained(&rect, &quad1) || msRectContained(&rect, &quad2) || msRectContained(&rect, &quad3) || msRectContained(&rect, &quad4)) { node->numsubnodes = 4; node->subnode[0] = treeNodeCreate(quad1); node->subnode[1] = treeNodeCreate(quad2); node->subnode[2] = treeNodeCreate(quad3); node->subnode[3] = treeNodeCreate(quad4); /* recurse back on this node now that it has subnodes */ return(treeNodeAddShapeId(node, id, rect, maxdepth)); } } #endif /* -------------------------------------------------------------------- */ /* Otherwise, consider creating two subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ #if MAX_SUBNODE == 2 else if( maxdepth > 1 && node->numsubnodes == 0 ) { rectObj half1, half2; treeSplitBounds(&node->rect, &half1, &half2); if( msRectContained(&rect, &half1)) { node->numsubnodes = 2; node->subnode[0] = treeNodeCreate(half1); node->subnode[1] = treeNodeCreate(half2); return(treeNodeAddShapeId(node->subnode[0], id, rect, maxdepth-1)); } else if(msRectContained(&rect, &half2)) { node->numsubnodes = 2; node->subnode[0] = treeNodeCreate(&half1); node->subnode[1] = treeNodeCreate(&half2); return(treeNodeAddShapeId(node->subnode[1], id, rect, maxdepth-1)); } } #endif /* MAX_SUBNODE == 2 */ /* -------------------------------------------------------------------- */ /* If none of that worked, just add it to this nodes list. */ /* -------------------------------------------------------------------- */ node->numshapes++; node->ids = SfRealloc( node->ids, sizeof(ms_int32) * node->numshapes ); node->ids[node->numshapes-1] = id; return MS_TRUE; } static int treeAddShapeId(treeObj *tree, int id, rectObj rect) { return(treeNodeAddShapeId(tree->root, id, rect, tree->maxdepth)); } static void treeCollectShapeIds(treeNodeObj *node, rectObj aoi, ms_bitarray status) { int i; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, &aoi)) return; /* -------------------------------------------------------------------- */ /* Add the local nodes shapeids to the list. */ /* -------------------------------------------------------------------- */ for(i=0; inumshapes; i++) msSetBit(status, node->ids[i], 1); /* -------------------------------------------------------------------- */ /* Recurse to subnodes if they exist. */ /* -------------------------------------------------------------------- */ for(i=0; inumsubnodes; i++) { if(node->subnode[i]) treeCollectShapeIds(node->subnode[i], aoi, status); } } ms_bitarray msSearchTree(treeObj *tree, rectObj aoi) { ms_bitarray status=NULL; status = msAllocBitArray(tree->numshapes); if(!status) { msSetError(MS_MEMERR, NULL, "msSearchTree()"); return(NULL); } treeCollectShapeIds(tree->root, aoi, status); return(status); } static int treeNodeTrim( treeNodeObj *node ) { int i; /* -------------------------------------------------------------------- */ /* Trim subtrees, and free subnodes that come back empty. */ /* -------------------------------------------------------------------- */ for(i=0; inumsubnodes; i++ ) { if(treeNodeTrim(node->subnode[i])) { destroyTreeNode(node->subnode[i]); node->subnode[i] = node->subnode[node->numsubnodes-1]; node->numsubnodes--; i--; /* process the new occupant of this subnode entry */ } } /* -------------------------------------------------------------------- */ /* If the current node has 1 subnode and no shapes, promote that */ /* subnode to the current node position. */ /* -------------------------------------------------------------------- */ if( node->numsubnodes == 1 && node->numshapes == 0) { treeNodeObj* psSubNode = node->subnode[0]; memcpy(&node->rect, &psSubNode->rect, sizeof(psSubNode->rect)); node->numshapes = psSubNode->numshapes; assert(node->ids == NULL); node->ids = psSubNode->ids; node->numsubnodes = psSubNode->numsubnodes; for( i = 0; i < psSubNode->numsubnodes; i++ ) node->subnode[i] = psSubNode->subnode[i]; free(psSubNode); } /* -------------------------------------------------------------------- */ /* We should be trimmed if we have no subnodes, and no shapes. */ /* -------------------------------------------------------------------- */ return(node->numsubnodes == 0 && node->numshapes == 0); } void msTreeTrim(treeObj *tree) { treeNodeTrim(tree->root); } static void searchDiskTreeNode(SHPTreeHandle disktree, rectObj aoi, ms_bitarray status) { int i; ms_int32 offset; ms_int32 numshapes, numsubnodes; rectObj rect; int *ids=NULL; fread( &offset, 4, 1, disktree->fp ); if ( disktree->needswap ) SwapWord ( 4, &offset ); fread( &rect, sizeof(rectObj), 1, disktree->fp ); if ( disktree->needswap ) SwapWord ( 8, &rect.minx ); if ( disktree->needswap ) SwapWord ( 8, &rect.miny ); if ( disktree->needswap ) SwapWord ( 8, &rect.maxx ); if ( disktree->needswap ) SwapWord ( 8, &rect.maxy ); fread( &numshapes, 4, 1, disktree->fp ); if ( disktree->needswap ) SwapWord ( 4, &numshapes ); if(!msRectOverlap(&rect, &aoi)) { /* skip rest of this node and sub-nodes */ offset += numshapes*sizeof(ms_int32) + sizeof(ms_int32); fseek(disktree->fp, offset, SEEK_CUR); return; } if(numshapes > 0) { ids = (int *)msSmallMalloc(numshapes*sizeof(ms_int32)); fread( ids, numshapes*sizeof(ms_int32), 1, disktree->fp ); if (disktree->needswap ) { for( i=0; ifp ); if ( disktree->needswap ) SwapWord ( 4, &numsubnodes ); for(i=0; inShapes); if(!status) { msSetError(MS_MEMERR, NULL, "msSearchDiskTree()"); msSHPDiskTreeClose( disktree ); return(NULL); } searchDiskTreeNode(disktree, aoi, status); msSHPDiskTreeClose( disktree ); return(status); } treeNodeObj *readTreeNode( SHPTreeHandle disktree ) { int i,res; ms_int32 offset; treeNodeObj *node; node = (treeNodeObj *) msSmallMalloc(sizeof(treeNodeObj)); node->ids = NULL; res = fread( &offset, 4, 1, disktree->fp ); if ( !res ) return NULL; if ( disktree->needswap ) SwapWord ( 4, &offset ); fread( &node->rect, sizeof(rectObj), 1, disktree->fp ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.minx ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.miny ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.maxx ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.maxy ); fread( &node->numshapes, 4, 1, disktree->fp ); if ( disktree->needswap ) SwapWord ( 4, &node->numshapes ); if( node->numshapes > 0 ) node->ids = (ms_int32 *)msSmallMalloc(sizeof(ms_int32)*node->numshapes); fread( node->ids, node->numshapes*4, 1, disktree->fp ); for( i=0; i < node->numshapes; i++ ) { if ( disktree->needswap ) SwapWord ( 4, &node->ids[i] ); } fread( &node->numsubnodes, 4, 1, disktree->fp ); if ( disktree->needswap ) SwapWord ( 4, &node->numsubnodes ); return node; } treeObj *msReadTree(char *filename, int debug) { treeObj *tree=NULL; SHPTreeHandle disktree; disktree = msSHPDiskTreeOpen( filename, debug ); if(!disktree) { msSetError(MS_IOERR, NULL, "msReadTree()"); return(NULL); } tree = (treeObj *) malloc(sizeof(treeObj)); MS_CHECK_ALLOC(tree, sizeof(treeObj), NULL); tree->numshapes = disktree->nShapes; tree->maxdepth = disktree->nDepth; tree->root = readTreeNode( disktree ); return(tree); } static ms_int32 getSubNodeOffset(treeNodeObj *node) { int i; ms_int32 offset=0; for(i=0; inumsubnodes; i++ ) { if(node->subnode[i]) { offset += sizeof(rectObj) + (node->subnode[i]->numshapes+3)*sizeof(int); offset += getSubNodeOffset(node->subnode[i]); } } /* offset is the disk offset in the index file on disk */ /* that format is (per node) */ /* int offset 4 bytes */ /* rectObj rect 4 * 8 bytes */ /* int numShapes 4 bytes */ /* int ids[numShapes] 4 * numShapes bytes */ /* int numSubNodes 4 bytes */ /* */ return(offset); } static void writeTreeNode(SHPTreeHandle disktree, treeNodeObj *node) { int i,j; ms_int32 offset; char *pabyRec = NULL; offset = getSubNodeOffset(node); pabyRec = msSmallMalloc(sizeof(rectObj) + (3 * sizeof(ms_int32)) + (node->numshapes * sizeof(ms_int32)) ); memcpy( pabyRec, &offset, 4); if( disktree->needswap ) SwapWord( 4, pabyRec ); memcpy( pabyRec+4, &node->rect, sizeof(rectObj)); for (i=0; i < 4; i++) if( disktree->needswap ) SwapWord( 8, pabyRec+4+(8*i) ); memcpy( pabyRec+36, &node->numshapes, 4); if( disktree->needswap ) SwapWord( 4, pabyRec+36 ); j = node->numshapes*sizeof(ms_int32); memcpy( pabyRec+40, node->ids, j); for (i=0; inumshapes; i++) if( disktree->needswap ) SwapWord( 4, pabyRec+40+(4*i)); memcpy( pabyRec+j+40, &node->numsubnodes, 4); if( disktree->needswap ) SwapWord( 4, pabyRec+40+j ); fwrite( pabyRec, 44+j, 1, disktree->fp); free (pabyRec); for(i=0; inumsubnodes; i++ ) { if(node->subnode[i]) writeTreeNode(disktree, node->subnode[i]); } return; } int msWriteTree(treeObj *tree, char *filename, int B_order) { char signature[3] = "SQT"; char version = 1; char reserved[3] = {0,0,0}; SHPTreeHandle disktree; int i; char mtBigEndian; char pabyBuf[32]; char *pszBasename, *pszFullname; disktree = (SHPTreeHandle) malloc(sizeof(SHPTreeInfo)); MS_CHECK_ALLOC(disktree, sizeof(SHPTreeInfo), MS_FALSE); /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(filename)+5); strcpy( pszBasename, filename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, MS_INDEX_EXTENSION); disktree->fp = fopen(pszFullname, "wb"); msFree(pszBasename); /* not needed */ msFree(pszFullname); if(!disktree->fp) { msFree(disktree); msSetError(MS_IOERR, NULL, "msWriteTree()"); return(MS_FALSE); } /* for efficiency, trim the tree */ msTreeTrim(tree); /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) mtBigEndian = MS_FALSE; else mtBigEndian = MS_TRUE; if( !(mtBigEndian ^ ( B_order == MS_LSB_ORDER || B_order == MS_NEW_LSB_ORDER )) ) disktree->needswap = 1; else disktree->needswap = 0; if( B_order == MS_NATIVE_ORDER ) disktree->needswap = 0; /* write the header */ if ( B_order > 0 ) { memcpy( pabyBuf, &signature, 3 ); memcpy (&disktree->signature, &signature, 3); pabyBuf[3] = B_order; memcpy( pabyBuf+4, &version, 1); memcpy( pabyBuf+5, &reserved, 3); memcpy( &disktree->version, &version, 1); memcpy( &disktree->flags, &reserved, 3); fwrite( pabyBuf, 8, 1, disktree->fp ); } memcpy( pabyBuf, &tree->numshapes, 4 ); if( disktree->needswap ) SwapWord( 4, pabyBuf ); memcpy( pabyBuf+4, &tree->maxdepth, 4 ); if( disktree->needswap ) SwapWord( 4, pabyBuf+4 ); i = fwrite( pabyBuf, 8, 1, disktree->fp ); if( !i ) { fprintf (stderr, "unable to write to index file ... exiting \n"); return (MS_FALSE); } writeTreeNode(disktree, tree->root); msSHPDiskTreeClose( disktree ); return(MS_TRUE); } /* Function to filter search results further against feature bboxes */ void msFilterTreeSearch(shapefileObj *shp, ms_bitarray status, rectObj search_rect) { int i; rectObj shape_rect; i = msGetNextBit(status, 0, shp->numshapes); while(i >= 0) { if(msSHPReadBounds(shp->hSHP, i, &shape_rect) == MS_SUCCESS) { if(msRectOverlap(&shape_rect, &search_rect) != MS_TRUE) { msSetBit(status, i, 0); } } i = msGetNextBit(status, i+1, shp->numshapes); } } mapserver-6.4.1/mapdrawgdal.c0000644002461700001440000025566612261257215015767 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Code for drawing GDAL raster layers. Called from * msDrawRasterLayerLow() in mapraster.c. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include #include "mapserver.h" #include "mapresample.h" #include "mapthread.h" extern int InvGeoTransform( double *gt_in, double *gt_out ); #define MAXCOLORS 256 #define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y)) #define SKIP_MASK(x,y) (mask_rb && !*(mask_rb->data.rgba.a+(y)*mask_rb->data.rgba.row_step+(x)*mask_rb->data.rgba.pixel_step)) #if defined(USE_GDAL) #include "gdal.h" #include "cpl_string.h" #include "gdal_alg.h" static int LoadGDALImages( GDALDatasetH hDS, int band_numbers[4], int band_count, layerObj *layer, int src_xoff, int src_yoff, int src_xsize, int src_ysize, GByte *pabyBuffer, int dst_xsize, int dst_ysize, int *pbHaveRGBNoData, int *pnNoData1, int *pnNoData2, int *pnNoData3 ); static int msDrawRasterLayerGDAL_RawMode( mapObj *map, layerObj *layer, imageObj *image, GDALDatasetH hDS, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ); static int msDrawRasterLayerGDAL_16BitClassification( mapObj *map, layerObj *layer, rasterBufferObj *rb, GDALDatasetH hDS, GDALRasterBandH hBand, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ); #ifdef USE_GD static void Dither24to8( GByte *pabyRed, GByte *pabyGreen, GByte *pabyBlue, GByte *pabyDithered, int xsize, int ysize, int bTransparent, colorObj transparentColor, gdImagePtr gdImg ); /* * Stuff for allocating color cubes, and mapping between RGB values and * the corresponding color cube index. */ static int allocColorCube(mapObj *map, gdImagePtr img, int *panColorCube); #endif #define RED_LEVELS 5 #define RED_DIV 52 /* #define GREEN_LEVELS 7 */ #define GREEN_LEVELS 5 /* #define GREEN_DIV 37 */ #define GREEN_DIV 52 #define BLUE_LEVELS 5 #define BLUE_DIV 52 #define RGB_LEVEL_INDEX(r,g,b) ((r)*GREEN_LEVELS*BLUE_LEVELS + (g)*BLUE_LEVELS+(b)) #define RGB_INDEX(r,g,b) RGB_LEVEL_INDEX(((r)/RED_DIV),((g)/GREEN_DIV),((b)/BLUE_DIV)) /* * rasterBufferObj setting macros. */ /************************************************************************/ /* msDrawRasterLayerGDAL() */ /************************************************************************/ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid ) { int i,j, k; /* loop counters */ int cmap[MAXCOLORS]; #ifndef NDEBUG int cmap_set = FALSE; #endif unsigned char rb_cmap[4][MAXCOLORS]; double adfGeoTransform[6], adfInvGeoTransform[6]; int dst_xoff, dst_yoff, dst_xsize, dst_ysize; int src_xoff, src_yoff, src_xsize, src_ysize; double llx, lly, urx, ury; rectObj copyRect, mapRect; unsigned char *pabyRaw1=NULL, *pabyRaw2=NULL, *pabyRaw3=NULL, *pabyRawAlpha = NULL; int classified = FALSE; int red_band=0, green_band=0, blue_band=0, alpha_band=0; int band_count, band_numbers[4]; GDALDatasetH hDS = hDSVoid; GDALColorTableH hColorMap; GDALRasterBandH hBand1=NULL, hBand2=NULL, hBand3=NULL, hBandAlpha=NULL; int bHaveRGBNoData = FALSE; int nNoData1=-1,nNoData2=-1,nNoData3=-1; rasterBufferObj *mask_rb = NULL; #ifdef USE_GD int anColorCube[256]; int cmt=0; /*make sure we don't have a truecolor gd image*/ assert(!rb || rb->type != MS_BUFFER_GD || !gdImageTrueColor(rb->data.gd_img)); #endif if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) return -1; } /*only support rawdata and pluggable renderers*/ assert(MS_RENDERER_RAWDATA(image->format) || (MS_RENDERER_PLUGIN(image->format) && rb)); memset( cmap, 0xff, MAXCOLORS * sizeof(int) ); memset( rb_cmap, 0, sizeof(rb_cmap) ); /* -------------------------------------------------------------------- */ /* Test the image format instead of the map format. */ /* Normally the map format and the image format should be the */ /* same but In somes cases like swf and pdf support, a temporary */ /* GD image object is created and used to render raster layers */ /* and then dumped into the SWF or the PDF file. */ /* -------------------------------------------------------------------- */ src_xsize = GDALGetRasterXSize( hDS ); src_ysize = GDALGetRasterYSize( hDS ); /* * If the RAW_WINDOW attribute is set, use that to establish what to * load. This is normally just set by the mapresample.c module to avoid * problems with rotated maps. */ if( CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) != NULL ) { char **papszTokens = CSLTokenizeString( CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) ); if( layer->debug ) msDebug( "msDrawGDAL(%s): using RAW_WINDOW=%s, dst=0,0,%d,%d\n", layer->name, CSLFetchNameValue( layer->processing, "RAW_WINDOW" ), image->width, image->height ); if( CSLCount(papszTokens) != 4 ) { CSLDestroy( papszTokens ); msSetError( MS_IMGERR, "RAW_WINDOW PROCESSING directive corrupt.", "msDrawGDAL()" ); return -1; } src_xoff = atoi(papszTokens[0]); src_yoff = atoi(papszTokens[1]); src_xsize = atoi(papszTokens[2]); src_ysize = atoi(papszTokens[3]); dst_xoff = 0; dst_yoff = 0; dst_xsize = image->width; dst_ysize = image->height; CSLDestroy( papszTokens ); } /* * Compute the georeferenced window of overlap, and do nothing if there * is no overlap between the map extents, and the file we are operating on. */ else if( layer->transform ) { int dst_lrx, dst_lry; if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): Entering transform.\n" ); msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform ); InvGeoTransform( adfGeoTransform, adfInvGeoTransform ); mapRect = map->extent; mapRect.minx -= map->cellsize*0.5; mapRect.maxx += map->cellsize*0.5; mapRect.miny -= map->cellsize*0.5; mapRect.maxy += map->cellsize*0.5; copyRect = mapRect; if( copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize) ) copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize); if( copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0) ) copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0); if( copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize) ) copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize); if( copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0) ) copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0); if( copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy ) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): Error in overlap calculation.\n" ); return 0; } /* * Copy the source and destination raster coordinates. */ llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny); lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny); urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy); ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy); src_xoff = MAX(0,(int) floor(llx+0.5)); src_yoff = MAX(0,(int) floor(ury+0.5)); src_xsize = MIN(MAX(0,(int) (urx - llx + 0.5)), GDALGetRasterXSize(hDS) - src_xoff); src_ysize = MIN(MAX(0,(int) (lly - ury + 0.5)), GDALGetRasterYSize(hDS) - src_yoff); /* We want very small windows to use at least one source pixel (#4172) */ if( src_xsize == 0 && (urx - llx) > 0.0 ) { src_xsize = 1; src_xoff = MIN(src_xoff,GDALGetRasterXSize(hDS)-1); } if( src_ysize == 0 && (lly - ury) > 0.0 ) { src_ysize = 1; src_yoff = MIN(src_yoff,GDALGetRasterYSize(hDS)-1); } if( src_xsize == 0 || src_ysize == 0 ) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): no apparent overlap between map view and this window(1).\n" ); return 0; } if (map->cellsize == 0) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): Cellsize can't be 0.\n" ); return 0; } dst_xoff = (int) ((copyRect.minx - mapRect.minx) / map->cellsize); dst_yoff = (int) ((mapRect.maxy - copyRect.maxy) / map->cellsize); dst_lrx = (int) ((copyRect.maxx - mapRect.minx) / map->cellsize + 0.5); dst_lry = (int) ((mapRect.maxy - copyRect.miny) / map->cellsize + 0.5); dst_lrx = MAX(0,MIN(image->width,dst_lrx)); dst_lry = MAX(0,MIN(image->height,dst_lry)); dst_xsize = MAX(0,MIN(image->width,dst_lrx - dst_xoff)); dst_ysize = MAX(0,MIN(image->height,dst_lry - dst_yoff)); if( dst_xsize == 0 || dst_ysize == 0 ) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): no apparent overlap between map view and this window(2).\n" ); return 0; } if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n", src_xoff, src_yoff, src_xsize, src_ysize, dst_xoff, dst_yoff, dst_xsize, dst_ysize ); #ifndef notdef if( layer->debug ) { double d_src_xoff, d_src_yoff, geo_x, geo_y; geo_x = mapRect.minx + dst_xoff * map->cellsize; geo_y = mapRect.maxy - dst_yoff * map->cellsize; d_src_xoff = (geo_x - adfGeoTransform[0]) / adfGeoTransform[1]; d_src_yoff = (geo_y - adfGeoTransform[3]) / adfGeoTransform[5]; msDebug( "msDrawRasterLayerGDAL(): source raster PL (%.3f,%.3f) for dst PL (%d,%d).\n", d_src_xoff, d_src_yoff, dst_xoff, dst_yoff ); } #endif } /* * If layer transforms are turned off, just map 1:1. */ else { dst_xoff = src_xoff = 0; dst_yoff = src_yoff = 0; dst_xsize = src_xsize = MIN(image->width,src_xsize); dst_ysize = src_ysize = MIN(image->height,src_ysize); } /* * In RAWDATA mode we don't fool with colors. Do the raw processing, * and return from the function early. */ if( MS_RENDERER_RAWDATA( image->format ) ) { return msDrawRasterLayerGDAL_RawMode( map, layer, image, hDS, src_xoff, src_yoff, src_xsize, src_ysize, dst_xoff, dst_yoff, dst_xsize, dst_ysize ); } /* * Is this image classified? We consider it classified if there are * classes with an expression string *or* a color range. We don't want * to treat the raster as classified if there is just a bogus class here * to force inclusion in the legend. */ for( i = 0; i < layer->numclasses; i++ ) { int s; /* change colour based on colour range? */ for(s=0; sclass[i]->numstyles; s++) { if( MS_VALID_COLOR(layer->class[i]->styles[s]->mincolor) && MS_VALID_COLOR(layer->class[i]->styles[s]->maxcolor) ) { classified = TRUE; break; } } if( layer->class[i]->expression.string != NULL ) { classified = TRUE; break; } } /* * Set up the band selection. We look for a BANDS directive in the * the PROCESSING options. If not found we default to red=1 or * red=1,green=2,blue=3 or red=1,green=2,blue=3,alpha=4. */ if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { red_band = 1; if( GDALGetRasterCount( hDS ) >= 4 && GDALGetRasterColorInterpretation( GDALGetRasterBand( hDS, 4 ) ) == GCI_AlphaBand ) alpha_band = 4; if( GDALGetRasterCount( hDS ) >= 3 ) { green_band = 2; blue_band = 3; } if( GDALGetRasterCount( hDS ) == 2 && GDALGetRasterColorInterpretation( GDALGetRasterBand( hDS, 2 ) ) == GCI_AlphaBand ) alpha_band = 2; hBand1 = GDALGetRasterBand( hDS, red_band ); if( classified || GDALGetRasterColorTable( hBand1 ) != NULL ) { alpha_band = 0; green_band = 0; blue_band = 0; } } else { int *band_list; band_list = msGetGDALBandList( layer, hDS, 4, &band_count ); if( band_list == NULL ) return -1; if( band_count > 0 ) red_band = band_list[0]; else red_band = 0; if( band_count > 2 ) { green_band = band_list[1]; blue_band = band_list[2]; } else { green_band = 0; blue_band = 0; } if( band_count > 3 ) alpha_band = band_list[3]; else alpha_band = 0; free( band_list ); } band_numbers[0] = red_band; band_numbers[1] = green_band; band_numbers[2] = blue_band; band_numbers[3] = 0; if( blue_band != 0 && alpha_band != 0 ) { band_numbers[3] = alpha_band; band_count = 4; } else if( blue_band != 0 && alpha_band == 0 ) band_count = 3; else if( alpha_band != 0 ) { band_numbers[1] = alpha_band; band_count = 2; } else band_count = 1; if( layer->debug > 1 || (layer->debug > 0 && green_band != 0) ) { msDebug( "msDrawRasterLayerGDAL(): red,green,blue,alpha bands = %d,%d,%d,%d\n", red_band, green_band, blue_band, alpha_band ); } /* * Get band handles for PC256, RGB or RGBA cases. */ hBand1 = GDALGetRasterBand( hDS, red_band ); if( hBand1 == NULL ) return -1; hBand2 = hBand3 = hBandAlpha = NULL; if( green_band != 0 ) { hBand1 = GDALGetRasterBand( hDS, red_band ); hBand2 = GDALGetRasterBand( hDS, green_band ); hBand3 = GDALGetRasterBand( hDS, blue_band ); if( hBand1 == NULL || hBand2 == NULL || hBand3 == NULL ) return -1; } if( alpha_band != 0 ) hBandAlpha = GDALGetRasterBand( hDS, alpha_band ); #ifdef USE_GD /* * Wipe pen indicators for all our layer class colors if they exist. * Sometimes temporary gdImg'es are used in which case previously allocated * pens won't generally apply. See Bug 504. */ if( rb->type == MS_BUFFER_GD ) { int iClass; int iStyle; for( iClass = 0; iClass < layer->numclasses; iClass++ ) { for (iStyle=0; iStyleclass[iClass]->numstyles; iStyle++) layer->class[iClass]->styles[iStyle]->color.pen = MS_PEN_UNSET; } } #endif /* * The logic for a classification rendering of non-8bit raster bands * is sufficiently different than the normal mechanism of loading * into an 8bit buffer, that we isolate it into it's own subfunction. */ if( classified && hBand1 != NULL && GDALGetRasterDataType( hBand1 ) != GDT_Byte ) { return msDrawRasterLayerGDAL_16BitClassification( map, layer, rb, hDS, hBand1, src_xoff, src_yoff, src_xsize, src_ysize, dst_xoff, dst_yoff, dst_xsize, dst_ysize ); } /* * Get colormap for this image. If there isn't one, and we have only * one band create a greyscale colormap. */ if( hBand2 != NULL ) hColorMap = NULL; else { hColorMap = GDALGetRasterColorTable( hBand1 ); if( hColorMap != NULL ) hColorMap = GDALCloneColorTable( hColorMap ); else if( hBand2 == NULL ) { hColorMap = GDALCreateColorTable( GPI_RGB ); for( i = 0; i < 256; i++ ) { colorObj pixel; GDALColorEntry sEntry; pixel.red = i; pixel.green = i; pixel.blue = i; #ifdef USE_GD pixel.pen = i; #endif if(MS_COMPARE_COLORS(pixel, layer->offsite)) { sEntry.c1 = 0; sEntry.c2 = 0; sEntry.c3 = 0; sEntry.c4 = 0; /* alpha set to zero */ } else if( rb->type != MS_BUFFER_GD ) { sEntry.c1 = i; sEntry.c2 = i; sEntry.c3 = i; sEntry.c4 = 255; } else { /* ** This special calculation is intended to use only 128 ** unique colors for greyscale in non-truecolor mode. */ sEntry.c1 = i - i%2; sEntry.c2 = i - i%2; sEntry.c3 = i - i%2; sEntry.c4 = 255; } GDALSetColorEntry( hColorMap, i, &sEntry ); } } /* ** If we have a known NODATA value, mark it now as transparent. */ { int bGotNoData; double dfNoDataValue = msGetGDALNoDataValue( layer, hBand1, &bGotNoData); if( bGotNoData && dfNoDataValue >= 0 && dfNoDataValue < GDALGetColorEntryCount( hColorMap ) ) { GDALColorEntry sEntry; memcpy( &sEntry, GDALGetColorEntry( hColorMap, (int) dfNoDataValue ), sizeof(GDALColorEntry) ); sEntry.c4 = 0; GDALSetColorEntry( hColorMap, (int) dfNoDataValue, &sEntry ); } } } /* * Setup the mapping between source eight bit pixel values, and the * output images color table. There are two general cases, where the * class colors are provided by the MAP file, or where we use the native * color table. */ if( classified ) { int c, color_count; #ifndef NDEBUG cmap_set = TRUE; #endif if( hColorMap == NULL ) { msSetError(MS_IOERR, "Attempt to classify 24bit image, this is unsupported.", "drawGDAL()"); return -1; } color_count = MIN(256,GDALGetColorEntryCount(hColorMap)); for(i=0; i < color_count; i++) { colorObj pixel; int colormap_index; GDALColorEntry sEntry; GDALGetColorEntryAsRGB( hColorMap, i, &sEntry ); pixel.red = sEntry.c1; pixel.green = sEntry.c2; pixel.blue = sEntry.c3; colormap_index = i; if(!MS_COMPARE_COLORS(pixel, layer->offsite)) { c = msGetClass(layer, &pixel, colormap_index); if(c == -1) { /* doesn't belong to any class, so handle like offsite*/ if( rb->type == MS_BUFFER_GD ) cmap[i] = -1; } else { int s; /* change colour based on colour range? Currently we only address the greyscale case properly. */ for(s=0; sclass[c]->numstyles; s++) { if( MS_VALID_COLOR(layer->class[c]->styles[s]->mincolor) && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor) ) msValueToRange(layer->class[c]->styles[s], sEntry.c1 ); } #ifdef USE_GD if( rb->type == MS_BUFFER_GD ) { RESOLVE_PEN_GD(rb->data.gd_img, layer->class[c]->styles[0]->color); if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) ) cmap[i] = -1; else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { /* use class color */ cmap[i] = layer->class[c]->styles[0]->color.pen; } else /* Use raster color */ cmap[i] = msAddColorGD(map, rb->data.gd_img, cmt, pixel.red, pixel.green, pixel.blue); } else if( rb->type == MS_BUFFER_BYTE_RGBA ) #endif { if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color)) /* leave it transparent */; else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { rb_cmap[0][i] = layer->class[c]->styles[0]->color.red; rb_cmap[1][i] = layer->class[c]->styles[0]->color.green; rb_cmap[2][i] = layer->class[c]->styles[0]->color.blue; rb_cmap[3][i] = (255*layer->class[c]->styles[0]->opacity / 100); } else { /* Use raster color */ rb_cmap[0][i] = pixel.red; rb_cmap[1][i] = pixel.green; rb_cmap[2][i] = pixel.blue; rb_cmap[3][i] = 255; } } } #ifdef USE_GD } else { if( rb->type == MS_BUFFER_GD ) cmap[i] = -1; #endif } } #ifdef USE_GD } else if( hColorMap != NULL && rb->type == MS_BUFFER_GD ) { int color_count; #ifndef NDEBUG cmap_set = TRUE; #endif color_count = MIN(256,GDALGetColorEntryCount(hColorMap)); for(i=0; i < color_count; i++) { GDALColorEntry sEntry; GDALGetColorEntryAsRGB( hColorMap, i, &sEntry ); if( sEntry.c4 != 0 && (!MS_VALID_COLOR( layer->offsite ) || layer->offsite.red != sEntry.c1 || layer->offsite.green != sEntry.c2 || layer->offsite.blue != sEntry.c3 ) ) cmap[i] = msAddColorGD(map, rb->data.gd_img, cmt, sEntry.c1, sEntry.c2, sEntry.c3); else cmap[i] = -1; } #endif } else if( hBand2 == NULL && hColorMap != NULL && rb->type == MS_BUFFER_BYTE_RGBA ) { int color_count; #ifndef NDEBUG cmap_set = TRUE; #endif color_count = MIN(256,GDALGetColorEntryCount(hColorMap)); for(i=0; i < color_count; i++) { GDALColorEntry sEntry; GDALGetColorEntryAsRGB( hColorMap, i, &sEntry ); if( sEntry.c4 != 0 && (!MS_VALID_COLOR( layer->offsite ) || layer->offsite.red != sEntry.c1 || layer->offsite.green != sEntry.c2 || layer->offsite.blue != sEntry.c3 ) ) { rb_cmap[0][i] = sEntry.c1; rb_cmap[1][i] = sEntry.c2; rb_cmap[2][i] = sEntry.c3; rb_cmap[3][i] = sEntry.c4; } } } #ifdef USE_GD else if( rb->type == MS_BUFFER_GD ) { allocColorCube( map, rb->data.gd_img, anColorCube ); } #endif /* * Allocate imagery buffers. */ pabyRaw1 = (unsigned char *) malloc(dst_xsize * dst_ysize * band_count); if( pabyRaw1 == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); return -1; } if( hBand2 != NULL && hBand3 != NULL ) { pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1; pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2; } if( hBandAlpha != NULL ) { if( hBand2 != NULL ) pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3; else pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1; } /* * Load image data into buffers with scaling, etc. */ if( LoadGDALImages( hDS, band_numbers, band_count, layer, src_xoff, src_yoff, src_xsize, src_ysize, pabyRaw1, dst_xsize, dst_ysize, &bHaveRGBNoData, &nNoData1, &nNoData2, &nNoData3 ) == -1 ) { free( pabyRaw1 ); return -1; } if( bHaveRGBNoData && layer->debug ) msDebug( "msDrawGDAL(): using RGB nodata values from GDAL dataset.\n" ); /* -------------------------------------------------------------------- */ /* If there was no alpha band, but we have a dataset level mask */ /* load it as massage it so it will function as our alpha for */ /* transparency purposes. */ /* -------------------------------------------------------------------- */ if( hBandAlpha == NULL ) { int nMaskFlags = GDALGetMaskFlags(hBand1); if( (CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) && (nMaskFlags & GMF_PER_DATASET) != 0 && (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 ) { CPLErr eErr; if( layer->debug ) msDebug( "msDrawGDAL(): using GDAL mask band for alpha.\n" ); band_count++; pabyRaw1 = (unsigned char *) realloc(pabyRaw1,dst_xsize * dst_ysize * band_count); if( pabyRaw1 == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); return -1; } if( hBand2 != NULL ) { pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1; pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2; pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3; } else { pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1; } hBandAlpha = GDALGetMaskBand(hBand1); eErr = GDALRasterIO( hBandAlpha, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pabyRawAlpha, dst_xsize, dst_ysize, GDT_Byte, 0,0); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "drawGDAL()", CPLGetLastErrorMsg() ); free( pabyRaw1 ); return -1; } /* In case the mask is not an alpha channel, expand values of 1 to 255, */ /* so we can deal as it was an alpha band afterwards */ if ((nMaskFlags & GMF_ALPHA) == 0) { for(i=0; itype == MS_BUFFER_GD && hBandAlpha != NULL ) { assert( cmap_set ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { int result, alpha; for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { alpha = pabyRawAlpha[k]; result = cmap[pabyRaw1[k++]]; if(SKIP_MASK(j,i)) { continue; } /* ** We don't do alpha blending in non-truecolor mode, just ** threshold the point on/off at alpha=128. */ if( result != -1 && alpha >= 128 ) rb->data.gd_img->pixels[i][j] = result; } } assert( k == dst_xsize * dst_ysize ); } /* -------------------------------------------------------------------- */ /* Single band plus colormap (no alpha) to 8bit. */ /* -------------------------------------------------------------------- */ else if( hBand2 == NULL && rb->type == MS_BUFFER_GD ) { assert( cmap_set ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { int result; for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { result = cmap[pabyRaw1[k++]]; if(SKIP_MASK(j,i)) { continue; } if( result != -1 ) { rb->data.gd_img->pixels[i][j] = result; } } } assert( k == dst_xsize * dst_ysize ); } else #endif /* -------------------------------------------------------------------- */ /* Single band plus colormap and alpha to truecolor. (RB) */ /* -------------------------------------------------------------------- */ if( hBand2 == NULL && rb->type == MS_BUFFER_BYTE_RGBA && hBandAlpha != NULL ) { assert( cmap_set ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int src_pixel, src_alpha, cmap_alpha, merged_alpha; if(SKIP_MASK(j,i)) { k++; continue; } src_pixel = pabyRaw1[k]; src_alpha = pabyRawAlpha[k]; cmap_alpha = rb_cmap[3][src_pixel]; merged_alpha = (src_alpha * cmap_alpha) / 255; if( merged_alpha < 2 ) /* do nothing - transparent */; else if( merged_alpha > 253 ) { RB_SET_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], cmap_alpha ); } else { RB_MIX_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], merged_alpha ); } k++; } } } /* -------------------------------------------------------------------- */ /* Single band plus colormap (no alpha) to truecolor (RB) */ /* -------------------------------------------------------------------- */ else if( hBand2 == NULL && rb->type == MS_BUFFER_BYTE_RGBA ) { assert( cmap_set ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int src_pixel = pabyRaw1[k++]; if(SKIP_MASK(j,i)) { continue; } if( rb_cmap[3][src_pixel] > 253 ) { RB_SET_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], rb_cmap[3][src_pixel] ); } else if( rb_cmap[3][src_pixel] > 1 ) { RB_MIX_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], rb_cmap[3][src_pixel] ); } } } } /* -------------------------------------------------------------------- */ /* Input is 3 band RGB. Alpha blending is mixed into the loop */ /* since this case is less commonly used and has lots of other */ /* overhead. (RB) */ /* -------------------------------------------------------------------- */ else if( hBand3 != NULL && rb->type == MS_BUFFER_BYTE_RGBA ) { k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ ) { if(SKIP_MASK(j,i)) { continue; } if( MS_VALID_COLOR( layer->offsite ) && pabyRaw1[k] == layer->offsite.red && pabyRaw2[k] == layer->offsite.green && pabyRaw3[k] == layer->offsite.blue ) continue; if( bHaveRGBNoData && pabyRaw1[k] == nNoData1 && pabyRaw2[k] == nNoData2 && pabyRaw3[k] == nNoData3 ) continue; if( pabyRawAlpha == NULL || pabyRawAlpha[k] == 255 ) { RB_SET_PIXEL( rb, j, i, pabyRaw1[k], pabyRaw2[k], pabyRaw3[k], 255 ); } else if( pabyRawAlpha[k] != 0 ) { RB_MIX_PIXEL( rb, j, i, pabyRaw1[k], pabyRaw2[k], pabyRaw3[k], pabyRawAlpha[k] ); } } } } #ifdef USE_GD /* -------------------------------------------------------------------- */ /* Input is 3 band RGB. Alpha blending is mixed into the loop */ /* since this case is less commonly used and has lots of other */ /* overhead. (GD) */ /* -------------------------------------------------------------------- */ else if( hBand3 != NULL && rb->type == MS_BUFFER_GD ) { /* Dithered 24bit to 8bit conversion */ if( CSLFetchBoolean( layer->processing, "DITHER", FALSE ) ) { unsigned char *pabyDithered; pabyDithered = (unsigned char *) malloc(dst_xsize * dst_ysize); if( pabyDithered == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize ); return -1; } Dither24to8( pabyRaw1, pabyRaw2, pabyRaw3, pabyDithered, dst_xsize, dst_ysize, image->format->transparent, map->imagecolor, rb->data.gd_img ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ ) { if(SKIP_MASK(j,i)) { continue; } if( MS_VALID_COLOR( layer->offsite ) && pabyRaw1[k] == layer->offsite.red && pabyRaw2[k] == layer->offsite.green && pabyRaw3[k] == layer->offsite.blue ) continue; if( bHaveRGBNoData && pabyRaw1[k] == nNoData1 && pabyRaw2[k] == nNoData2 && pabyRaw3[k] == nNoData3 ) continue; if( pabyRawAlpha != NULL && pabyRawAlpha[k] == 0 ) continue; rb->data.gd_img->pixels[i][j] = pabyDithered[k]; } } free( pabyDithered ); } /* Color cubed 24bit to 8bit conversion. */ else if( rb->type == MS_BUFFER_GD ) { k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ ) { int cc_index; if(SKIP_MASK(j,i)) { continue; } if( MS_VALID_COLOR( layer->offsite ) && pabyRaw1[k] == layer->offsite.red && pabyRaw2[k] == layer->offsite.green && pabyRaw3[k] == layer->offsite.blue ) continue; if( bHaveRGBNoData && pabyRaw1[k] == nNoData1 && pabyRaw2[k] == nNoData2 && pabyRaw3[k] == nNoData3 ) continue; if( pabyRawAlpha != NULL && pabyRawAlpha[k] == 0 ) continue; cc_index= RGB_INDEX(pabyRaw1[k],pabyRaw2[k],pabyRaw3[k]); rb->data.gd_img->pixels[i][j] = anColorCube[cc_index]; } } } else { msSetError(MS_MISCERR,"Unsupported raster configuration","msDrawRasterLayerGDAL()"); return MS_FAILURE; } } #endif /* ** Cleanup */ msFree( mask_rb ); free( pabyRaw1 ); if( hColorMap != NULL ) GDALDestroyColorTable( hColorMap ); return 0; } /************************************************************************/ /* ParseDefaultLUT() */ /************************************************************************/ static int ParseDefaultLUT( const char *lut_def, GByte *lut ) { const char *lut_read; int last_in=0, last_out=0, all_done=FALSE; /* -------------------------------------------------------------------- */ /* Parse definition, applying to lut on the fly. */ /* -------------------------------------------------------------------- */ lut_read = lut_def; while( !all_done ) { int this_in=0, this_out=0; int lut_i; while( isspace(*lut_read) ) lut_read++; /* if we are at end, assum 255:255 */ if( *lut_read == '\0' ) { all_done = TRUE; if ( last_in != 255 ) { this_in = 255; this_out = 255; } } /* otherwise read "in:out", and skip past */ else { this_in = atoi(lut_read); while( *lut_read != ':' && *lut_read ) lut_read++; if( *lut_read == ':' ) lut_read++; while( isspace(*lut_read) ) lut_read++; this_out = atoi(lut_read); while( *lut_read && *lut_read != ',' && *lut_read != '\n' ) lut_read++; if( *lut_read == ',' || *lut_read == '\n' ) lut_read++; while( isspace(*lut_read) ) lut_read++; } this_in = MAX(0,MIN(255,this_in)); this_out = MAX(0,MIN(255,this_out)); /* apply linear values from last in:out to this in:out */ for( lut_i = last_in; lut_i <= this_in; lut_i++ ) { double ratio; if( last_in == this_in ) ratio = 1.0; else ratio = (lut_i - last_in) / (double) (this_in - last_in); lut[lut_i] = (int) floor(((1.0 - ratio)*last_out + ratio*this_out) + 0.5); } last_in = this_in; last_out = this_out; } return 0; } /************************************************************************/ /* LutFromGimpLine() */ /************************************************************************/ static int LutFromGimpLine( char *lut_line, GByte *lut ) { char wrkLUTDef[1000]; int i, count = 0; char **tokens; /* cleanup white space at end of line (DOS LF, etc) */ i = strlen(lut_line) - 1; while( i > 0 && isspace(lut_line[i]) ) lut_line[i--] = '\0'; while( *lut_line == 10 || *lut_line == 13 ) lut_line++; /* tokenize line */ tokens = CSLTokenizeString( lut_line ); if( CSLCount(tokens) != 17 * 2 ) { CSLDestroy( tokens ); msSetError(MS_MISCERR, "GIMP curve file appears corrupt.", "LutFromGimpLine()" ); return -1; } /* Convert to our own format */ wrkLUTDef[0] = '\0'; for( i = 0; i < 17; i++ ) { if( atoi(tokens[i*2]) >= 0 ) { if( count++ > 0 ) strlcat( wrkLUTDef, ",", sizeof(wrkLUTDef)); snprintf( wrkLUTDef + strlen(wrkLUTDef), sizeof(wrkLUTDef)-strlen(wrkLUTDef), "%s:%s", tokens[i*2], tokens[i*2+1] ); } } CSLDestroy( tokens ); return ParseDefaultLUT( wrkLUTDef, lut ); } /************************************************************************/ /* ParseGimpLUT() */ /* */ /* Parse a Gimp style LUT. */ /************************************************************************/ static int ParseGimpLUT( const char *lut_def, GByte *lut, int iColorIndex ) { int i; GByte lutValue[256]; GByte lutColorBand[256]; char **lines = CSLTokenizeStringComplex( lut_def, "\n", FALSE, FALSE ); if( !EQUALN(lines[0],"# GIMP Curves File",18) || CSLCount(lines) < 6 ) { msSetError(MS_MISCERR, "GIMP curve file appears corrupt.", "ParseGimpLUT()" ); return -1; } /* * Convert the overall curve, and the color band specific curve into LUTs. */ if( LutFromGimpLine( lines[1], lutValue ) != 0 || LutFromGimpLine( lines[iColorIndex + 1], lutColorBand ) != 0 ) { CSLDestroy( lines ); return -1; } CSLDestroy( lines ); /* * Compose the two luts as if the raw value passed through the color band * specific lut, and then the general value lut. Usually one or the * other will be the identity mapping, but not always. */ for( i = 0; i < 256; i++ ) { lut[i] = lutValue[lutColorBand[i]]; } return 0; } /************************************************************************/ /* ApplyLUT() */ /* */ /* Apply a LUT according to RFC 21. */ /************************************************************************/ static int ApplyLUT( int iColorIndex, layerObj *layer, GByte *buffer, int buf_xsize, int buf_ysize ) { const char *lut_def; char key[20], lut_def_fromfile[2500]; GByte lut[256]; int err, i; /* -------------------------------------------------------------------- */ /* Get lut specifier from processing directives. Do nothing if */ /* none are found. */ /* -------------------------------------------------------------------- */ sprintf( key, "LUT_%d", iColorIndex ); lut_def = msLayerGetProcessingKey( layer, key ); if( lut_def == NULL ) lut_def = msLayerGetProcessingKey( layer, "LUT" ); if( lut_def == NULL ) return 0; /* -------------------------------------------------------------------- */ /* Does this look like a file? If so, read it into memory. */ /* -------------------------------------------------------------------- */ if( strspn(lut_def,"0123456789:, ") != strlen(lut_def) ) { FILE *fp; char path[MS_MAXPATHLEN]; int len; msBuildPath(path, layer->map->mappath, lut_def); fp = fopen( path, "rb" ); if( fp == NULL ) { msSetError(MS_IOERR, "Failed to open LUT file '%s'.", "drawGDAL()", path ); return -1; } len = fread( lut_def_fromfile, 1, sizeof(lut_def_fromfile), fp ); fclose( fp ); if( len == sizeof(lut_def_fromfile) ) { msSetError(MS_IOERR, "LUT definition from file %s longer than maximum buffer size (%d bytes).", "drawGDAL()", path, (int)sizeof(lut_def_fromfile) ); return -1; } lut_def_fromfile[len] = '\0'; lut_def = lut_def_fromfile; } /* -------------------------------------------------------------------- */ /* Parse the LUT description. */ /* -------------------------------------------------------------------- */ if( EQUALN(lut_def,"# GIMP",6) ) { err = ParseGimpLUT( lut_def, lut, iColorIndex ); } else { err = ParseDefaultLUT( lut_def, lut ); } if( err != 0 ) return err; /* -------------------------------------------------------------------- */ /* Apply LUT. */ /* -------------------------------------------------------------------- */ for( i = buf_xsize * buf_ysize - 1; i >= 0; i-- ) buffer[i] = lut[buffer[i]]; return 0; } /************************************************************************/ /* LoadGDALImages() */ /* */ /* This call will load and process 1-4 bands of input for the */ /* selected rectangle, loading the result into the passed 8bit */ /* buffer. The processing options include scaling. */ /************************************************************************/ static int LoadGDALImages( GDALDatasetH hDS, int band_numbers[4], int band_count, layerObj *layer, int src_xoff, int src_yoff, int src_xsize, int src_ysize, GByte *pabyWholeBuffer, int dst_xsize, int dst_ysize, int *pbHaveRGBNoData, int *pnNoData1, int *pnNoData2, int *pnNoData3 ) { int iColorIndex, result_code=0; CPLErr eErr; float *pafWholeRawData; /* -------------------------------------------------------------------- */ /* If we have no alpha band, but we do have three input */ /* bands, then check for nodata values. If we only have one */ /* input band, then nodata will already have been adderssed as */ /* part of the real or manufactured color table. */ /* -------------------------------------------------------------------- */ if( band_count == 3 ) { *pnNoData1 = (int) msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_numbers[0]), pbHaveRGBNoData); if( *pbHaveRGBNoData ) *pnNoData2 = (int) msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_numbers[1]), pbHaveRGBNoData); if( *pbHaveRGBNoData ) *pnNoData3 = (int) msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_numbers[2]), pbHaveRGBNoData); } /* -------------------------------------------------------------------- */ /* Are we doing a simple, non-scaling case? If so, read directly */ /* and return. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( layer->processing, "SCALE" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_1" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_2" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_3" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_4" ) == NULL ) { eErr = GDALDatasetRasterIO( hDS, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pabyWholeBuffer, dst_xsize, dst_ysize, GDT_Byte, band_count, band_numbers, 0,0,0); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", "drawGDAL()", CPLGetLastErrorMsg() ); return -1; } for( iColorIndex = 0; iColorIndex < band_count && result_code == 0; iColorIndex++ ) { result_code = ApplyLUT( iColorIndex+1, layer, pabyWholeBuffer + dst_xsize*dst_ysize*iColorIndex, dst_xsize, dst_ysize ); } return result_code; } /* -------------------------------------------------------------------- */ /* Disable use of nodata if we are doing scaling. */ /* -------------------------------------------------------------------- */ *pbHaveRGBNoData = FALSE; /* -------------------------------------------------------------------- */ /* We need to do some scaling. Will load into either a 16bit */ /* unsigned or a floating point buffer depending on the source */ /* data. We offer a special case for 16U data because it is */ /* common and it is a substantial win to avoid alot of floating */ /* point operations on it. */ /* -------------------------------------------------------------------- */ /* TODO */ /* -------------------------------------------------------------------- */ /* Allocate the raw imagery buffer, and load into it (band */ /* interleaved). */ /* -------------------------------------------------------------------- */ pafWholeRawData = (float *) malloc(sizeof(float) * dst_xsize * dst_ysize * band_count ); if( pafWholeRawData == NULL ) { msSetError(MS_MEMERR, "Allocating work float image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); return -1; } eErr = GDALDatasetRasterIO( hDS, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pafWholeRawData, dst_xsize, dst_ysize, GDT_Float32, band_count, band_numbers, 0, 0, 0 ); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", "drawGDAL()", CPLGetLastErrorMsg() ); free( pafWholeRawData ); return -1; } /* -------------------------------------------------------------------- */ /* Fetch the scale processing option. */ /* -------------------------------------------------------------------- */ for( iColorIndex = 0; iColorIndex < band_count; iColorIndex++ ) { unsigned char *pabyBuffer; double dfScaleMin=0.0, dfScaleMax=255.0, dfScaleRatio, dfNoDataValue; const char *pszScaleInfo; float *pafRawData; int nPixelCount = dst_xsize * dst_ysize, i, bGotNoData = FALSE; GDALRasterBandH hBand =GDALGetRasterBand(hDS,band_numbers[iColorIndex]); pszScaleInfo = CSLFetchNameValue( layer->processing, "SCALE" ); if( pszScaleInfo == NULL ) { char szBandScalingName[20]; sprintf( szBandScalingName, "SCALE_%d", iColorIndex+1 ); pszScaleInfo = CSLFetchNameValue( layer->processing, szBandScalingName); } if( pszScaleInfo != NULL ) { char **papszTokens; papszTokens = CSLTokenizeStringComplex( pszScaleInfo, " ,", FALSE, FALSE ); if( CSLCount(papszTokens) == 1 && EQUAL(papszTokens[0],"AUTO") ) { dfScaleMin = dfScaleMax = 0.0; } else if( CSLCount(papszTokens) != 2 ) { free( pafWholeRawData ); msSetError( MS_MISCERR, "SCALE PROCESSING option unparsable for layer %s.", "msDrawGDAL()", layer->name ); return -1; } else { dfScaleMin = atof(papszTokens[0]); dfScaleMax = atof(papszTokens[1]); } CSLDestroy( papszTokens ); } /* -------------------------------------------------------------------- */ /* If we are using autoscaling, then compute the max and min */ /* now. Perhaps we should eventually honour the offsite value */ /* as a nodata value, or get it from GDAL. */ /* -------------------------------------------------------------------- */ pafRawData = pafWholeRawData + iColorIndex * dst_xsize * dst_ysize; dfNoDataValue = msGetGDALNoDataValue( layer, hBand, &bGotNoData ); if( dfScaleMin == dfScaleMax ) { int bMinMaxSet = 0; /* we force assignment to a float rather than letting pafRawData[i] get promoted to double later to avoid float precision issues. */ float fNoDataValue = (float) dfNoDataValue; for( i = 0; i < nPixelCount; i++ ) { if( bGotNoData && pafRawData[i] == fNoDataValue ) continue; if( !bMinMaxSet ) { dfScaleMin = dfScaleMax = pafRawData[i]; bMinMaxSet = TRUE; } dfScaleMin = MIN(dfScaleMin,pafRawData[i]); dfScaleMax = MAX(dfScaleMax,pafRawData[i]); } if( dfScaleMin == dfScaleMax ) dfScaleMax = dfScaleMin + 1.0; } if( layer->debug > 0 ) msDebug( "msDrawGDAL(%s): scaling to 8bit, src range=%g,%g\n", layer->name, dfScaleMin, dfScaleMax ); /* -------------------------------------------------------------------- */ /* Now process the data. */ /* -------------------------------------------------------------------- */ dfScaleRatio = 256.0 / (dfScaleMax - dfScaleMin); pabyBuffer = pabyWholeBuffer + iColorIndex * nPixelCount; for( i = 0; i < nPixelCount; i++ ) { float fScaledValue = (float) ((pafRawData[i]-dfScaleMin)*dfScaleRatio); if( fScaledValue < 0.0 ) pabyBuffer[i] = 0; else if( fScaledValue > 255.0 ) pabyBuffer[i] = 255; else pabyBuffer[i] = (int) fScaledValue; } /* -------------------------------------------------------------------- */ /* Report a warning if NODATA keyword was applied. We are */ /* unable to utilize it since we can't return any pixels marked */ /* as nodata from this function. Need to fix someday. */ /* -------------------------------------------------------------------- */ if( bGotNoData ) msDebug( "LoadGDALImage(%s): NODATA value %g in GDAL\n" "file or PROCESSING directive largely ignored. Not yet fully supported for\n" "unclassified scaled data. The NODATA value is excluded from auto-scaling\n" "min/max computation, but will not be transparent.\n", layer->name, dfNoDataValue ); /* -------------------------------------------------------------------- */ /* Apply LUT if there is one. */ /* -------------------------------------------------------------------- */ result_code = ApplyLUT( iColorIndex+1, layer, pabyBuffer, dst_xsize, dst_ysize );; if( result_code == -1 ) { free( pafWholeRawData ); return result_code; } } free( pafWholeRawData ); return result_code; } #ifdef USE_GD /************************************************************************/ /* allocColorCube() */ /* */ /* Allocate color table entries as best possible for a color */ /* cube. */ /************************************************************************/ static int allocColorCube(mapObj *map, gdImagePtr img, int *panColorCube) { int r, g, b; int i = 0; int nGreyColors = 32; int nSpaceGreyColors = 8; int iColors = 0; int red, green, blue; for( r = 0; r < RED_LEVELS; r++ ) { for( g = 0; g < GREEN_LEVELS; g++ ) { for( b = 0; b < BLUE_LEVELS; b++ ) { red = MS_MIN(255,r * (255 / (RED_LEVELS-1))); green = MS_MIN(255,g * (255 / (GREEN_LEVELS-1))); blue = MS_MIN(255,b * (255 / (BLUE_LEVELS-1))); panColorCube[RGB_LEVEL_INDEX(r,g,b)] = msAddColorGD(map, img, 1, red, green, blue ); iColors++; } } } /* -------------------------------------------------------------------- */ /* Adding 32 grey colors */ /* -------------------------------------------------------------------- */ for (i=0; icolorsTotal; c++) { GDALColorEntry sEntry; sEntry.c1 = gdImg->red[c]; sEntry.c2 = gdImg->green[c]; sEntry.c3 = gdImg->blue[c]; if( bTransparent && transparent.red == sEntry.c1 && transparent.green == sEntry.c2 && transparent.blue == sEntry.c3 ) sEntry.c4 = 0; else sEntry.c4 = 255; GDALSetColorEntry( hCT, c, &sEntry ); } /* -------------------------------------------------------------------- */ /* Perform dithering. */ /* -------------------------------------------------------------------- */ GDALDitherRGB2PCT( GDALGetRasterBand( hDS, 1 ), GDALGetRasterBand( hDS, 2 ), GDALGetRasterBand( hDS, 3 ), GDALGetRasterBand( hDS, 4 ), hCT, NULL, NULL ); /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ GDALDestroyColorTable( hCT ); GDALClose( hDS ); } #endif /************************************************************************/ /* msGetGDALGeoTransform() */ /* */ /* Cover function that tries GDALGetGeoTransform(), a world */ /* file or OWS extents. It is assumed that TLOCK_GDAL is held */ /* before this function is called. */ /************************************************************************/ int msGetGDALGeoTransform( GDALDatasetH hDS, mapObj *map, layerObj *layer, double *padfGeoTransform ) { const char *extent_priority = NULL; const char *value; const char *gdalDesc; const char *fullPath; char *fileExtension = NULL; char szPath[MS_MAXPATHLEN]; int fullPathLen; int success = 0; rectObj rect; /* -------------------------------------------------------------------- */ /* some GDAL drivers (ie. GIF) don't set geotransform on failure. */ /* -------------------------------------------------------------------- */ padfGeoTransform[0] = 0.0; padfGeoTransform[1] = 1.0; padfGeoTransform[2] = 0.0; padfGeoTransform[3] = GDALGetRasterYSize(hDS); padfGeoTransform[4] = 0.0; padfGeoTransform[5] = -1.0; /* -------------------------------------------------------------------- */ /* Do we want to override GDAL with a worldfile if one is present? */ /* -------------------------------------------------------------------- */ extent_priority = CSLFetchNameValue( layer->processing, "EXTENT_PRIORITY" ); if( extent_priority != NULL && EQUALN(extent_priority,"WORLD",5) ) { /* is there a user configured worldfile? */ value = CSLFetchNameValue( layer->processing, "WORLDFILE" ); if( value != NULL ) { /* at this point, fullPath may be a filePath or path only */ fullPath = msBuildPath(szPath, map->mappath, value); /* fullPath is a path only, so let's append the dataset filename */ if( strrchr(szPath,'.') == NULL ) { fullPathLen = strlen(fullPath); gdalDesc = msStripPath((char*)GDALGetDescription(hDS)); if ( (fullPathLen + strlen(gdalDesc)) < MS_MAXPATHLEN ) { strcpy((char*)(fullPath + fullPathLen), gdalDesc); } else { msDebug("Path length to alternative worldfile exceeds MS_MAXPATHLEN.\n"); fullPath = NULL; } } /* fullPath has a filename included, so get the extension */ else { fileExtension = msStrdup(strrchr(szPath,'.') + 1); } } /* common behaviour with worldfile generated from basename + .wld */ else { fullPath = GDALGetDescription(hDS); fileExtension = msStrdup("wld"); } if( fullPath ) success = GDALReadWorldFile(fullPath, fileExtension, padfGeoTransform); if( success && layer->debug >= MS_DEBUGLEVEL_VVV ) { msDebug("Worldfile location: %s.\n", fullPath); } else if( layer->debug >= MS_DEBUGLEVEL_VVV ) { msDebug("Failed using worldfile location: %s.\n", fullPath); } msFree(fileExtension); if( success ) return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Try GDAL. */ /* */ /* Make sure that ymax is always at the top, and ymin at the */ /* bottom ... that is flip any files without the usual */ /* orientation. This is intended to enable display of "raw" */ /* files with no coordinate system otherwise they break down in */ /* many ways. */ /* -------------------------------------------------------------------- */ if (GDALGetGeoTransform( hDS, padfGeoTransform ) == CE_None ) { if( padfGeoTransform[5] == 1.0 && padfGeoTransform[3] == 0.0 ) { padfGeoTransform[5] = -1.0; padfGeoTransform[3] = GDALGetRasterYSize(hDS); } return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Try worldfile. */ /* -------------------------------------------------------------------- */ if( GDALGetDescription(hDS) != NULL && GDALReadWorldFile(GDALGetDescription(hDS), "wld", padfGeoTransform) ) { return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Do we have the extent keyword on the layer? We only use */ /* this if we have a single raster associated with the layer as */ /* opposed to a tile index. */ /* */ /* Arguably this ought to take priority over all the other */ /* stuff. */ /* -------------------------------------------------------------------- */ if (MS_VALID_EXTENT(layer->extent) && layer->data != NULL) { rect = layer->extent; padfGeoTransform[0] = rect.minx; padfGeoTransform[1] = (rect.maxx - rect.minx) / (double) GDALGetRasterXSize( hDS ); padfGeoTransform[2] = 0; padfGeoTransform[3] = rect.maxy; padfGeoTransform[4] = 0; padfGeoTransform[5] = (rect.miny - rect.maxy) / (double) GDALGetRasterYSize( hDS ); return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* We didn't find any info ... use the default. */ /* Reset our default geotransform. GDALGetGeoTransform() may */ /* have altered it even if GDALGetGeoTransform() failed. */ /* -------------------------------------------------------------------- */ padfGeoTransform[0] = 0.0; padfGeoTransform[1] = 1.0; padfGeoTransform[2] = 0.0; padfGeoTransform[3] = GDALGetRasterYSize(hDS); padfGeoTransform[4] = 0.0; padfGeoTransform[5] = -1.0; return MS_FAILURE; } /************************************************************************/ /* msDrawRasterLayerGDAL_RawMode() */ /* */ /* Handle the loading and application of data in rawmode. */ /************************************************************************/ static int msDrawRasterLayerGDAL_RawMode( mapObj *map, layerObj *layer, imageObj *image, GDALDatasetH hDS, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ) { void *pBuffer; GDALDataType eDataType; int *band_list, band_count; int i, j, k, band; CPLErr eErr; float *f_nodatas = NULL; unsigned char *b_nodatas = NULL; GInt16 *i_nodatas = NULL; int got_nodata=FALSE; rasterBufferObj *mask_rb = NULL; if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) return -1; } if( image->format->bands > 256 ) { msSetError( MS_IMGERR, "Too many bands (more than 256).", "msDrawRasterLayerGDAL_RawMode()" ); return -1; } /* -------------------------------------------------------------------- */ /* What data type do we need? */ /* -------------------------------------------------------------------- */ if( image->format->imagemode == MS_IMAGEMODE_INT16 ) eDataType = GDT_Int16; else if( image->format->imagemode == MS_IMAGEMODE_FLOAT32 ) eDataType = GDT_Float32; else if( image->format->imagemode == MS_IMAGEMODE_BYTE ) eDataType = GDT_Byte; else return -1; /* -------------------------------------------------------------------- */ /* Work out the band list. */ /* -------------------------------------------------------------------- */ band_list = msGetGDALBandList( layer, hDS, image->format->bands, &band_count ); if( band_list == NULL ) return -1; if( band_count != image->format->bands ) { free( band_list ); msSetError( MS_IMGERR, "BANDS PROCESSING directive has wrong number of bands, expected %d, got %d.", "msDrawRasterLayerGDAL_RawMode()", image->format->bands, band_count ); return -1; } /* -------------------------------------------------------------------- */ /* Do we have nodata values? */ /* -------------------------------------------------------------------- */ f_nodatas = (float *) calloc(sizeof(float),band_count); if (f_nodatas == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawRasterLayerGDAL_RawMode()", __FILE__, __LINE__, (unsigned int)(sizeof(float)*band_count)); free( band_list ); return -1; } if( band_count <= 3 && (layer->offsite.red != -1 || layer->offsite.green != -1 || layer->offsite.blue != -1) ) { if( band_count > 0 ) f_nodatas[0] = layer->offsite.red; if( band_count > 1 ) f_nodatas[1] = layer->offsite.green; if( band_count > 2 ) f_nodatas[2] = layer->offsite.blue; got_nodata = TRUE; } if( !got_nodata ) { got_nodata = TRUE; for( band = 0; band < band_count && got_nodata; band++ ) { f_nodatas[band] = msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_list[band]), &got_nodata ); } } if( !got_nodata ) { msFree( f_nodatas ); f_nodatas = NULL; } else if( eDataType == GDT_Byte ) { b_nodatas = (unsigned char *) f_nodatas; for( band = 0; band < band_count; band++ ) b_nodatas[band] = (unsigned char) f_nodatas[band]; } else if( eDataType == GDT_Int16 ) { i_nodatas = (GInt16 *) f_nodatas; for( band = 0; band < band_count; band++ ) i_nodatas[band] = (GInt16) f_nodatas[band]; } /* -------------------------------------------------------------------- */ /* Allocate buffer, and read data into it. */ /* -------------------------------------------------------------------- */ pBuffer = malloc(dst_xsize * dst_ysize * image->format->bands * (GDALGetDataTypeSize(eDataType)/8) ); if( pBuffer == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize ); return -1; } eErr = GDALDatasetRasterIO( hDS, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pBuffer, dst_xsize, dst_ysize, eDataType, image->format->bands, band_list, 0, 0, 0 ); free( band_list ); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "msDrawRasterLayerGDAL_RawMode()", CPLGetLastErrorMsg() ); free( pBuffer ); free( f_nodatas ); return -1; } /* -------------------------------------------------------------------- */ /* Transfer the data to the imageObj. */ /* -------------------------------------------------------------------- */ k = 0; for( band = 0; band < image->format->bands; band++ ) { for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { if( image->format->imagemode == MS_IMAGEMODE_INT16 ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int off = j + i * image->width + band*image->width*image->height; int off_mask = j + i * image->width; if( ( i_nodatas && ((GInt16 *) pBuffer)[k] == i_nodatas[band] ) || SKIP_MASK(j,i)) { k++; continue; } image->img.raw_16bit[off] = ((GInt16 *) pBuffer)[k++]; MS_SET_BIT(image->img_mask,off_mask); } } else if( image->format->imagemode == MS_IMAGEMODE_FLOAT32 ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int off = j + i * image->width + band*image->width*image->height; int off_mask = j + i * image->width; if( ( f_nodatas && ((float *) pBuffer)[k] == f_nodatas[band] ) || SKIP_MASK(j,i)) { k++; continue; } image->img.raw_float[off] = ((float *) pBuffer)[k++]; MS_SET_BIT(image->img_mask,off_mask); } } else if( image->format->imagemode == MS_IMAGEMODE_BYTE ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int off = j + i * image->width + band*image->width*image->height; int off_mask = j + i * image->width; if( ( b_nodatas && ((unsigned char *) pBuffer)[k] == b_nodatas[band] ) || SKIP_MASK(j,i)) { k++; continue; } image->img.raw_byte[off] = ((unsigned char *) pBuffer)[k++]; MS_SET_BIT(image->img_mask,off_mask); } } } } msFree( mask_rb ); free( pBuffer ); free( f_nodatas ); return 0; } /************************************************************************/ /* msDrawRasterLayerGDAL_16BitClassifcation() */ /* */ /* Handle the rendering of rasters going through a 16bit */ /* classification lookup instead of the more common 8bit one. */ /* */ /* Currently we are using one data path where we load the */ /* raster into a floating point buffer, and then scale to */ /* 16bit. Eventually we could add optimizations for some of */ /* the 16bit cases at the cost of some complication. */ /************************************************************************/ static int msDrawRasterLayerGDAL_16BitClassification( mapObj *map, layerObj *layer, rasterBufferObj *rb, GDALDatasetH hDS, GDALRasterBandH hBand, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ) { float *pafRawData; double dfScaleMin=0.0, dfScaleMax=0.0, dfScaleRatio; int nPixelCount = dst_xsize * dst_ysize, i, nBucketCount=0; GDALDataType eDataType; float fDataMin=0.0, fDataMax=255.0, fNoDataValue; const char *pszScaleInfo; const char *pszBuckets; int *cmap, c, j, k, bGotNoData = FALSE, bGotFirstValue; unsigned char *rb_cmap[4]; CPLErr eErr; rasterBufferObj *mask_rb = NULL; if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) return -1; } assert( rb->type == MS_BUFFER_GD || rb->type == MS_BUFFER_BYTE_RGBA ); /* ==================================================================== */ /* Read the requested data in one gulp into a floating point */ /* buffer. */ /* ==================================================================== */ pafRawData = (float *) malloc(sizeof(float) * dst_xsize * dst_ysize ); if( pafRawData == NULL ) { msSetError( MS_MEMERR, "Out of memory allocating working buffer.", "msDrawRasterLayerGDAL_16BitClassification()" ); return -1; } eErr = GDALRasterIO( hBand, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pafRawData, dst_xsize, dst_ysize, GDT_Float32, 0, 0 ); if( eErr != CE_None ) { free( pafRawData ); msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "msDrawRasterLayerGDAL_16BitClassification()", CPLGetLastErrorMsg() ); return -1; } fNoDataValue = (float) msGetGDALNoDataValue( layer, hBand, &bGotNoData ); /* ==================================================================== */ /* Determine scaling. */ /* ==================================================================== */ eDataType = GDALGetRasterDataType( hBand ); /* -------------------------------------------------------------------- */ /* Scan for absolute min/max of this block. */ /* -------------------------------------------------------------------- */ bGotFirstValue = FALSE; for( i = 1; i < nPixelCount; i++ ) { if( bGotNoData && pafRawData[i] == fNoDataValue ) continue; if( !bGotFirstValue ) { fDataMin = fDataMax = pafRawData[i]; bGotFirstValue = TRUE; } else { fDataMin = MIN(fDataMin,pafRawData[i]); fDataMax = MAX(fDataMax,pafRawData[i]); } } /* -------------------------------------------------------------------- */ /* Fetch the scale processing option. */ /* -------------------------------------------------------------------- */ pszBuckets = CSLFetchNameValue( layer->processing, "SCALE_BUCKETS" ); pszScaleInfo = CSLFetchNameValue( layer->processing, "SCALE" ); if( pszScaleInfo != NULL ) { char **papszTokens; papszTokens = CSLTokenizeStringComplex( pszScaleInfo, " ,", FALSE, FALSE ); if( CSLCount(papszTokens) == 1 && EQUAL(papszTokens[0],"AUTO") ) { dfScaleMin = dfScaleMax = 0.0; } else if( CSLCount(papszTokens) != 2 ) { free( pafRawData ); msSetError( MS_MISCERR, "SCALE PROCESSING option unparsable for layer %s.", "msDrawGDAL()", layer->name ); return -1; } else { dfScaleMin = atof(papszTokens[0]); dfScaleMax = atof(papszTokens[1]); } CSLDestroy( papszTokens ); } /* -------------------------------------------------------------------- */ /* Special integer cases for scaling. */ /* */ /* TODO: Treat Int32 and UInt32 case the same way *if* the min */ /* and max are less than 65536 apart. */ /* -------------------------------------------------------------------- */ if( eDataType == GDT_Byte || eDataType == GDT_Int16 || eDataType == GDT_UInt16 ) { if( pszScaleInfo == NULL ) { dfScaleMin = fDataMin - 0.5; dfScaleMax = fDataMax + 0.5; } if( pszBuckets == NULL ) { nBucketCount = (int) floor(fDataMax - fDataMin + 1.1); } } /* -------------------------------------------------------------------- */ /* General case if no scaling values provided in mapfile. */ /* -------------------------------------------------------------------- */ else if( dfScaleMin == 0.0 && dfScaleMax == 0.0 ) { double dfEpsilon = (fDataMax - fDataMin) / (65536*2); dfScaleMin = fDataMin - dfEpsilon; dfScaleMax = fDataMax + dfEpsilon; } /* -------------------------------------------------------------------- */ /* How many buckets? Only set if we don't already have a value. */ /* -------------------------------------------------------------------- */ if( pszBuckets == NULL ) { if( nBucketCount == 0 ) nBucketCount = 65536; } else { nBucketCount = atoi(pszBuckets); if( nBucketCount < 2 ) { free( pafRawData ); msSetError( MS_MISCERR, "SCALE_BUCKETS PROCESSING option is not a value of 2 or more: %s.", "msDrawRasterLayerGDAL_16BitClassification()", pszBuckets ); return -1; } } /* -------------------------------------------------------------------- */ /* Compute scaling ratio. */ /* -------------------------------------------------------------------- */ if( dfScaleMax == dfScaleMin ) dfScaleMax = dfScaleMin + 1.0; dfScaleRatio = nBucketCount / (dfScaleMax - dfScaleMin); if( layer->debug > 0 ) msDebug( "msDrawRasterGDAL_16BitClassification(%s):\n" " scaling to %d buckets from range=%g,%g.\n", layer->name, nBucketCount, dfScaleMin, dfScaleMax ); /* ==================================================================== */ /* Compute classification lookup table. */ /* ==================================================================== */ cmap = (int *) msSmallCalloc(sizeof(int),nBucketCount); rb_cmap[0] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[1] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount); for(i=0; i < nBucketCount; i++) { double dfOriginalValue; cmap[i] = -1; dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin; c = msGetClass_FloatRGB(layer, (float) dfOriginalValue, -1, -1, -1); if( c != -1 ) { int s; /* change colour based on colour range? */ for(s=0; sclass[c]->numstyles; s++) { if( MS_VALID_COLOR(layer->class[c]->styles[s]->mincolor) && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor) ) msValueToRange(layer->class[c]->styles[s],dfOriginalValue); } #ifdef USE_GD if(rb->type == MS_BUFFER_GD) { RESOLVE_PEN_GD(rb->data.gd_img, layer->class[c]->styles[0]->color); if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) ) cmap[i] = -1; else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { /* use class color */ cmap[i] = layer->class[c]->styles[0]->color.pen; } } else #endif if( rb->type == MS_BUFFER_BYTE_RGBA ) { if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) ) { /* leave it transparent */ } else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { /* use class color */ rb_cmap[0][i] = layer->class[c]->styles[0]->color.red; rb_cmap[1][i] = layer->class[c]->styles[0]->color.green; rb_cmap[2][i] = layer->class[c]->styles[0]->color.blue; rb_cmap[3][i] = (255*layer->class[c]->styles[0]->opacity / 100); } } } } /* ==================================================================== */ /* Now process the data, applying to the working imageObj. */ /* ==================================================================== */ k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { float fRawValue = pafRawData[k++]; int iMapIndex; /* * Skip nodata pixels ... no processing. */ if( bGotNoData && fRawValue == fNoDataValue ) { continue; } if(SKIP_MASK(j,i)) continue; /* * The funny +1/-1 is to avoid odd rounding around zero. * We could use floor() but sometimes it is expensive. */ iMapIndex = (int) ((fRawValue - dfScaleMin) * dfScaleRatio+1)-1; if( iMapIndex >= nBucketCount || iMapIndex < 0 ) { continue; } #ifdef USE_GD if( rb->type == MS_BUFFER_GD ) { int result = cmap[iMapIndex]; if( result == -1 ) continue; rb->data.gd_img->pixels[i][j] = result; } else #endif if( rb->type == MS_BUFFER_BYTE_RGBA ) { /* currently we never have partial alpha so keep simple */ if( rb_cmap[3][iMapIndex] > 0 ) RB_SET_PIXEL( rb, j, i, rb_cmap[0][iMapIndex], rb_cmap[1][iMapIndex], rb_cmap[2][iMapIndex], rb_cmap[3][iMapIndex] ); } } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ free( pafRawData ); free( cmap ); free( rb_cmap[0] ); free( rb_cmap[1] ); free( rb_cmap[2] ); free( rb_cmap[3] ); msFree( mask_rb ); assert( k == dst_xsize * dst_ysize ); return 0; } /************************************************************************/ /* msGetGDALNoDataValue() */ /************************************************************************/ double msGetGDALNoDataValue( layerObj *layer, void *hBand, int *pbGotNoData ) { const char *pszNODATAOpt; *pbGotNoData = FALSE; /* -------------------------------------------------------------------- */ /* Check for a NODATA setting in the .map file. */ /* -------------------------------------------------------------------- */ pszNODATAOpt = CSLFetchNameValue(layer->processing,"NODATA"); if( pszNODATAOpt != NULL ) { if( EQUAL(pszNODATAOpt,"OFF") || strlen(pszNODATAOpt) == 0 ) return -1234567.0; if( !EQUAL(pszNODATAOpt,"AUTO") ) { *pbGotNoData = TRUE; return atof(pszNODATAOpt); } } /* -------------------------------------------------------------------- */ /* Check for a NODATA setting on the raw file. */ /* -------------------------------------------------------------------- */ if( hBand == NULL ) return -1234567.0; else return GDALGetRasterNoDataValue( hBand, pbGotNoData ); } /************************************************************************/ /* msGetGDALBandList() */ /* */ /* max_bands - pass zero for no limit. */ /* band_count - location in which length of the return band */ /* list is placed. */ /* */ /* returns malloc() list of band numbers (*band_count long). */ /************************************************************************/ int *msGetGDALBandList( layerObj *layer, void *hDS, int max_bands, int *band_count ) { int i, file_bands; int *band_list = NULL; file_bands = GDALGetRasterCount( hDS ); if( file_bands == 0 ) { msSetError( MS_IMGERR, "Attempt to operate on GDAL file with no bands, layer=%s.", "msGetGDALBandList()", layer->name ); return NULL; } /* -------------------------------------------------------------------- */ /* Use all (or first) bands. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { if( max_bands > 0 ) *band_count = MIN(file_bands,max_bands); else *band_count = file_bands; band_list = (int *) malloc(sizeof(int) * *band_count ); MS_CHECK_ALLOC(band_list, sizeof(int) * *band_count, NULL); for( i = 0; i < *band_count; i++ ) band_list[i] = i+1; return band_list; } /* -------------------------------------------------------------------- */ /* get bands from BANDS processing directive. */ /* -------------------------------------------------------------------- */ else { char **papszItems = CSLTokenizeStringComplex( CSLFetchNameValue(layer->processing,"BANDS"), " ,", FALSE, FALSE ); if( CSLCount(papszItems) == 0 ) { CSLDestroy( papszItems ); msSetError( MS_IMGERR, "BANDS PROCESSING directive has no items.", "msGetGDALBandList()" ); return NULL; } else if( max_bands != 0 && CSLCount(papszItems) > max_bands ) { msSetError( MS_IMGERR, "BANDS PROCESSING directive has wrong number of bands, expected at most %d, got %d.", "msGetGDALBandList()", max_bands, CSLCount(papszItems) ); CSLDestroy( papszItems ); return NULL; } *band_count = CSLCount(papszItems); band_list = (int *) malloc(sizeof(int) * *band_count); MS_CHECK_ALLOC(band_list, sizeof(int) * *band_count, NULL); for( i = 0; i < *band_count; i++ ) { band_list[i] = atoi(papszItems[i]); if( band_list[i] < 1 || band_list[i] > GDALGetRasterCount(hDS) ) { msSetError( MS_IMGERR, "BANDS PROCESSING directive includes illegal band '%s', should be from 1 to %d.", "msGetGDALBandList()", papszItems[i], GDALGetRasterCount(hDS) ); CSLDestroy( papszItems ); free( band_list ); return NULL; } } CSLDestroy( papszItems ); return band_list; } } #endif /* def USE_GDAL */ mapserver-6.4.1/mapshape.h0000644002461700001440000001665712261257215015302 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Shapefile access API * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPSHAPE_H #define MAPSHAPE_H #include #include "mapprimitive.h" #ifdef __cplusplus extern "C" { #endif #define SHX_BUFFER_PAGE 1024 #ifndef SWIG #define MS_PATH_LENGTH 1024 /* Shapefile types */ #define SHP_POINT 1 #define SHP_ARC 3 #define SHP_POLYGON 5 #define SHP_MULTIPOINT 8 #define SHP_POINTZ 11 #define SHP_ARCZ 13 #define SHP_POLYGONZ 15 #define SHP_MULTIPOINTZ 18 #define SHP_POINTM 21 #define SHP_ARCM 23 #define SHP_POLYGONM 25 #define SHP_MULTIPOINTM 28 #endif #define MS_SHAPEFILE_POINT 1 #define MS_SHAPEFILE_ARC 3 #define MS_SHAPEFILE_POLYGON 5 #define MS_SHAPEFILE_MULTIPOINT 8 #define MS_SHP_POINTZ 11 #define MS_SHP_ARCZ 13 #define MS_SHP_POLYGONZ 15 #define MS_SHP_MULTIPOINTZ 18 #define MS_SHP_POINTM 21 #define MS_SHP_ARCM 23 #define MS_SHP_POLYGONM 25 #define MS_SHP_MULTIPOINTM 28 #ifndef SWIG typedef unsigned char uchar; typedef struct { FILE *fpSHP; FILE *fpSHX; int nShapeType; /* SHPT_* */ int nFileSize; /* SHP file */ int nRecords; int nMaxRecords; int *panRecOffset; int *panRecSize; ms_bitarray panRecLoaded; int panRecAllLoaded; double adBoundsMin[4]; double adBoundsMax[4]; int bUpdated; int nBufSize; /* these used static vars in shape readers, moved to be thread-safe */ uchar *pabyRec; int nPartMax; int *panParts; } SHPInfo; typedef SHPInfo * SHPHandle; #endif typedef struct { #ifdef SWIG %immutable; #endif FILE *fp; int nRecords; unsigned int nRecordLength; int nHeaderLength; int nFields; int *panFieldOffset; int *panFieldSize; int *panFieldDecimals; char *pachFieldType; char *pszHeader; int nCurrentRecord; int bCurrentRecordModified; char *pszCurrentRecord; int bNoHeader; int bUpdated; char *pszStringField; int nStringFieldLen; #ifdef SWIG %mutable; #endif } DBFInfo; typedef DBFInfo * DBFHandle; typedef enum {FTString, FTInteger, FTDouble, FTInvalid} DBFFieldType; /* Shapefile object, no write access via scripts */ typedef struct { #ifdef SWIG %immutable; #endif char source[MS_PATH_LENGTH]; /* full path to this file data */ #ifndef SWIG SHPHandle hSHP; /* SHP/SHX file pointer */ #endif int type; /* shapefile type */ int numshapes; /* number of shapes */ rectObj bounds; /* shape extent */ #ifndef SWIG DBFHandle hDBF; /* DBF file pointer */ #endif int lastshape; ms_bitarray status; rectObj statusbounds; /* holds extent associated with the status vector */ int isopen; #ifdef SWIG %mutable; #endif } shapefileObj; #ifndef SWIG /* layerInfo structure for tiled shapefiles */ typedef struct { shapefileObj *shpfile; shapefileObj *tileshpfile; int tilelayerindex; } msTiledSHPLayerInfo; /* shapefileObj function prototypes */ MS_DLL_EXPORT int msShapefileOpen(shapefileObj *shpfile, char *mode, char *filename, int log_failures); MS_DLL_EXPORT int msShapefileCreate(shapefileObj *shpfile, char *filename, int type); MS_DLL_EXPORT void msShapefileClose(shapefileObj *shpfile); MS_DLL_EXPORT int msShapefileWhichShapes(shapefileObj *shpfile, rectObj rect, int debug); /* SHP/SHX function prototypes */ MS_DLL_EXPORT SHPHandle msSHPOpen( const char * pszShapeFile, const char * pszAccess ); MS_DLL_EXPORT SHPHandle msSHPCreate( const char * pszShapeFile, int nShapeType ); MS_DLL_EXPORT void msSHPClose( SHPHandle hSHP ); MS_DLL_EXPORT void msSHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType ); MS_DLL_EXPORT int msSHPReadBounds( SHPHandle psSHP, int hEntity, rectObj *padBounds ); MS_DLL_EXPORT void msSHPReadShape( SHPHandle psSHP, int hEntity, shapeObj *shape ); MS_DLL_EXPORT int msSHPReadPoint(SHPHandle psSHP, int hEntity, pointObj *point ); MS_DLL_EXPORT int msSHPWriteShape( SHPHandle psSHP, shapeObj *shape ); MS_DLL_EXPORT int msSHPWritePoint(SHPHandle psSHP, pointObj *point ); /* SHX reading */ MS_DLL_EXPORT int msSHXLoadAll( SHPHandle psSHP ); MS_DLL_EXPORT int msSHXLoadPage( SHPHandle psSHP, int shxBufferPage ); MS_DLL_EXPORT int msSHXReadOffset( SHPHandle psSHP, int hEntity ); MS_DLL_EXPORT int msSHXReadSize( SHPHandle psSHP, int hEntity ); /* tiledShapefileObj function prototypes are in mapserver.h */ /* XBase function prototypes */ MS_DLL_EXPORT DBFHandle msDBFOpen( const char * pszDBFFile, const char * pszAccess ); MS_DLL_EXPORT void msDBFClose( DBFHandle hDBF ); MS_DLL_EXPORT DBFHandle msDBFCreate( const char * pszDBFFile ); MS_DLL_EXPORT int msDBFGetFieldCount( DBFHandle psDBF ); MS_DLL_EXPORT int msDBFGetRecordCount( DBFHandle psDBF ); MS_DLL_EXPORT int msDBFAddField( DBFHandle hDBF, const char * pszFieldName, DBFFieldType eType, int nWidth, int nDecimals ); MS_DLL_EXPORT DBFFieldType msDBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName, int * pnWidth, int * pnDecimals ); MS_DLL_EXPORT int msDBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField ); MS_DLL_EXPORT double msDBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField ); MS_DLL_EXPORT const char *msDBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField ); MS_DLL_EXPORT int msDBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, int nFieldValue ); MS_DLL_EXPORT int msDBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField, double dFieldValue ); MS_DLL_EXPORT int msDBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField, const char * pszFieldValue ); MS_DLL_EXPORT char **msDBFGetItems(DBFHandle dbffile); MS_DLL_EXPORT char **msDBFGetValues(DBFHandle dbffile, int record); MS_DLL_EXPORT char **msDBFGetValueList(DBFHandle dbffile, int record, int *itemindexes, int numitems); MS_DLL_EXPORT int *msDBFGetItemIndexes(DBFHandle dbffile, char **items, int numitems); MS_DLL_EXPORT int msDBFGetItemIndex(DBFHandle dbffile, char *name); #endif #ifdef __cplusplus } #endif #endif /* MAPSHAPE_H */ mapserver-6.4.1/INSTALL0000644002461700001440000000066612261257215014355 0ustar tbonfortusersVisit http://www.mapserver.org/ for full documentation and installation instructions. Unix compilation instructions ----------------------------- See INSTALL.CMAKE or the document on the MapServer website at Win32 compilation instructions ------------------------------ See README.WIN32 or the document on the MapServer website at mapserver-6.4.1/mapgraticule.c0000644002461700001440000012271312261257215016143 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Graticule Renderer * Author: John Novak, Novacell Technologies (jnovak@novacell.com) * ********************************************************************** * Copyright (c) 2003, John Novak, Novacell Technologies * * 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 ****************************************************************************/ #include "mapserver.h" #include #include "mapproject.h" /********************************************************************************************************************** * */ typedef enum { posBottom = 1, posTop, posLeft, posRight } msGraticulePosition; typedef enum { lpDefault = 0, lpDDMMSS = 1, lpDDMM, lpDD } msLabelProcessingType; void DefineAxis( int iTickCountTarget, double *Min, double *Max, double *Inc ); static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticulePosition ePosition ); static void _FormatLabel( layerObj *pLayer, shapeObj *pShape, double dDataToFormat ); int msGraticuleLayerInitItemInfo(layerObj *layer); #define MAPGRATICULE_ARC_SUBDIVISION_DEFAULT (256) #define MAPGRATICULE_ARC_MINIMUM (16) #define MAPGRATICULE_FORMAT_STRING_DEFAULT "%5.2g" #define MAPGRATICULE_FORMAT_STRING_DDMMSS "%3d %02d %02d" #define MAPGRATICULE_FORMAT_STRING_DDMM "%3d %02d" #define MAPGRATICULE_FORMAT_STRING_DD "%3d" /********************************************************************************************************************** * */ int msGraticuleLayerOpen(layerObj *layer) { graticuleObj *pInfo = (graticuleObj *) layer->layerinfo; if( pInfo == NULL ) return MS_FAILURE; pInfo->dincrementlatitude = 15.0; pInfo->dincrementlongitude = 15.0; pInfo->dwhichlatitude = -90.0; pInfo->dwhichlongitude = -180.0; pInfo->bvertical = 1; if( layer->numclasses == 0 ) msDebug( "GRID layer has no classes, nothing will be rendered.\n" ); if( layer->numclasses > 0 && layer->class[0]->numlabels > 0 ) pInfo->blabelaxes = 1; else pInfo->blabelaxes = 0; if( pInfo->labelformat == NULL ) { pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DEFAULT ) + 1 ); pInfo->ilabeltype = (int) lpDefault; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DEFAULT ); } else if( strcmp( pInfo->labelformat, "DDMMSS" ) == 0 ) { msFree(pInfo->labelformat); pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DDMMSS ) + 1 ); pInfo->ilabeltype = (int) lpDDMMSS; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DDMMSS ); } else if( strcmp( pInfo->labelformat, "DDMM" ) == 0 ) { msFree(pInfo->labelformat); pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DDMM ) + 1 ); pInfo->ilabeltype = (int) lpDDMM; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DDMM ); } else if( strcmp( pInfo->labelformat, "DD" ) == 0 ) { msFree(pInfo->labelformat); pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DD ) + 1 ); pInfo->ilabeltype = (int) lpDD; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DD ); } return MS_SUCCESS; } /********************************************************************************************************************** * Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msGraticuleLayerIsOpen(layerObj *layer) { if(layer->layerinfo) return MS_TRUE; return MS_FALSE; } /********************************************************************************************************************** * */ int msGraticuleLayerClose(layerObj *layer) { graticuleObj *pInfo = (graticuleObj *) layer->layerinfo; if( pInfo->labelformat ) { free( pInfo->labelformat ); pInfo->labelformat = NULL; } if( pInfo->pboundingpoints ) { free( pInfo->pboundingpoints ); pInfo->pboundingpoints = NULL; } if( pInfo->pboundinglines ) { free( pInfo->pboundinglines ); pInfo->pboundinglines = NULL; } free(layer->layerinfo); layer->layerinfo=NULL; return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { graticuleObj *pInfo = (graticuleObj *) layer->layerinfo; int iAxisTickCount = 0; rectObj rectMapCoordinates; if(msCheckParentPointer(layer->map,"map") == MS_FAILURE) return MS_FAILURE; pInfo->dstartlatitude = rect.miny; pInfo->dstartlongitude = rect.minx; pInfo->dendlatitude = rect.maxy; pInfo->dendlongitude = rect.maxx; pInfo->bvertical = 1; pInfo->extent = rect; if( pInfo->minincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->minincrement; pInfo->dincrementlatitude = pInfo->minincrement; } else if( pInfo->maxincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->maxincrement; pInfo->dincrementlatitude = pInfo->maxincrement; } else { pInfo->dincrementlongitude = 0; pInfo->dincrementlatitude = 0; } if( pInfo->maxarcs > 0 ) iAxisTickCount = (int) pInfo->maxarcs; else if( pInfo->minarcs > 0 ) iAxisTickCount = (int) pInfo->minarcs; DefineAxis( iAxisTickCount, &pInfo->dstartlongitude, &pInfo->dendlongitude, &pInfo->dincrementlongitude); DefineAxis( iAxisTickCount, &pInfo->dstartlatitude, &pInfo->dendlatitude, &pInfo->dincrementlatitude); pInfo->dwhichlatitude = pInfo->dstartlatitude; pInfo->dwhichlongitude = pInfo->dstartlongitude; if( pInfo->minincrement > 0.0 && pInfo->maxincrement > 0.0 && pInfo->minincrement == pInfo->maxincrement ) { pInfo->dincrementlongitude = pInfo->minincrement; pInfo->dincrementlatitude = pInfo->minincrement; } else if( pInfo->minincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->minincrement; pInfo->dincrementlatitude = pInfo->minincrement; } else if( pInfo->maxincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->maxincrement; pInfo->dincrementlatitude = pInfo->maxincrement; } /* * If using PROJ, project rect back into map system, and generate rect corner points in native system. * These lines will be used when generating labels to get correct placement at arc/rect edge intersections. */ rectMapCoordinates = layer->map->extent; pInfo->pboundinglines = (lineObj *) msSmallMalloc( sizeof( lineObj ) * 4 ); pInfo->pboundingpoints = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 8 ); { /* * top */ pInfo->pboundinglines[0].numpoints = 2; pInfo->pboundinglines[0].point = &pInfo->pboundingpoints[0]; pInfo->pboundinglines[0].point[0].x = rectMapCoordinates.minx; pInfo->pboundinglines[0].point[0].y = rectMapCoordinates.maxy; pInfo->pboundinglines[0].point[1].x = rectMapCoordinates.maxx; pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]); else layer->project = MS_FALSE; #endif /* * bottom */ pInfo->pboundinglines[1].numpoints = 2; pInfo->pboundinglines[1].point = &pInfo->pboundingpoints[2]; pInfo->pboundinglines[1].point[0].x = rectMapCoordinates.minx; pInfo->pboundinglines[1].point[0].y = rectMapCoordinates.miny; pInfo->pboundinglines[1].point[1].x = rectMapCoordinates.maxx; pInfo->pboundinglines[1].point[1].y = rectMapCoordinates.miny; #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[1]); else layer->project = MS_FALSE; #endif /* * left */ pInfo->pboundinglines[2].numpoints = 2; pInfo->pboundinglines[2].point = &pInfo->pboundingpoints[4]; pInfo->pboundinglines[2].point[0].x = rectMapCoordinates.minx; pInfo->pboundinglines[2].point[0].y = rectMapCoordinates.miny; pInfo->pboundinglines[2].point[1].x = rectMapCoordinates.minx; pInfo->pboundinglines[2].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[2]); else layer->project = MS_FALSE; #endif /* * right */ pInfo->pboundinglines[3].numpoints = 2; pInfo->pboundinglines[3].point = &pInfo->pboundingpoints[6]; pInfo->pboundinglines[3].point[0].x = rectMapCoordinates.maxx; pInfo->pboundinglines[3].point[0].y = rectMapCoordinates.miny; pInfo->pboundinglines[3].point[1].x = rectMapCoordinates.maxx; pInfo->pboundinglines[3].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[3]); else layer->project = MS_FALSE; #endif } return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) { graticuleObj *pInfo = (graticuleObj *) layer->layerinfo; if( pInfo->minsubdivides <= 0.0 || pInfo->maxsubdivides <= 0.0 ) pInfo->minsubdivides = pInfo->maxsubdivides = MAPGRATICULE_ARC_SUBDIVISION_DEFAULT; shape->numlines = 1; shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) msSmallMalloc(sizeof( lineObj )); shape->line->numpoints = (int) pInfo->maxsubdivides; /* * Subdivide and draw current arc, rendering the arc labels first */ if( pInfo->bvertical ) { int iPointIndex; double dArcDelta = (pInfo->dendlatitude - pInfo->dstartlatitude) / (double) shape->line->numpoints; double dArcPosition = pInfo->dstartlatitude + dArcDelta; double dStartY, dDeltaX; switch( pInfo->ilabelstate ) { case 0: if(!pInfo->blabelaxes) { /* Bottom */ pInfo->ilabelstate++; shape->numlines = 0; return MS_SUCCESS; } dDeltaX = (pInfo->dwhichlongitude - pInfo->pboundinglines[1].point[0].x) / (pInfo->pboundinglines[1].point[1].x - pInfo->pboundinglines[1].point[0].x); if (dDeltaX < 0) dDeltaX=dDeltaX*-1; dStartY = (pInfo->pboundinglines[1].point[1].y - pInfo->pboundinglines[1].point[0].y) * dDeltaX + pInfo->pboundinglines[1].point[0].y; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = pInfo->dwhichlongitude; shape->line->point[0].y = dStartY; shape->line->point[1].x = pInfo->dwhichlongitude; shape->line->point[1].y = dStartY + dArcDelta; _FormatLabel( layer, shape, shape->line->point[0].x ); if(_AdjustLabelPosition( layer, shape, posBottom ) != MS_SUCCESS) return MS_FAILURE; pInfo->ilabelstate++; return MS_SUCCESS; case 1: if(!pInfo->blabelaxes) { /* Top */ pInfo->ilabelstate++; shape->numlines = 0; return MS_SUCCESS; } dDeltaX = (pInfo->dwhichlongitude - pInfo->pboundinglines[0].point[0].x) / (pInfo->pboundinglines[0].point[1].x - pInfo->pboundinglines[0].point[0].x ); if (dDeltaX < 0) dDeltaX=dDeltaX*-1; dStartY = (pInfo->pboundinglines[0].point[1].y - pInfo->pboundinglines[0].point[0].y) * dDeltaX + pInfo->pboundinglines[0].point[1].y; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = pInfo->dwhichlongitude; shape->line->point[0].y = dStartY - dArcDelta; shape->line->point[1].x = pInfo->dwhichlongitude; shape->line->point[1].y = dStartY; _FormatLabel( layer, shape, shape->line->point[0].x ); if(_AdjustLabelPosition( layer, shape, posTop ) != MS_SUCCESS) return MS_FAILURE; pInfo->ilabelstate++; return MS_SUCCESS; case 2: shape->line->numpoints = (int) shape->line->numpoints + 1; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * shape->line->numpoints ); shape->line->point[0].x = pInfo->dwhichlongitude; shape->line->point[0].y = pInfo->dstartlatitude; for( iPointIndex = 1; iPointIndex < shape->line->numpoints; iPointIndex++ ) { shape->line->point[iPointIndex].x = pInfo->dwhichlongitude; shape->line->point[iPointIndex].y = dArcPosition; dArcPosition += dArcDelta; } pInfo->ilabelstate = 0; pInfo->dwhichlongitude += pInfo->dincrementlongitude; break; default: pInfo->ilabelstate = 0; break; } } else { /*horizontal*/ int iPointIndex; double dArcDelta = (pInfo->dendlongitude - pInfo->dstartlongitude) / (double) shape->line->numpoints; double dArcPosition = pInfo->dstartlongitude + dArcDelta; double dStartX, dDeltaY; switch( pInfo->ilabelstate ) { case 0: if(!pInfo->blabelaxes) { /* Left side */ pInfo->ilabelstate++; shape->numlines = 0; return MS_SUCCESS; } dDeltaY = (pInfo->dwhichlatitude - pInfo->pboundinglines[2].point[0].y) / (pInfo->pboundinglines[2].point[1].y - pInfo->pboundinglines[2].point[0].y ); if (dDeltaY < 0) dDeltaY= dDeltaY*-1; dStartX = (pInfo->pboundinglines[2].point[1].x - pInfo->pboundinglines[2].point[0].x) * dDeltaY + pInfo->pboundinglines[2].point[0].x; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = dStartX; shape->line->point[0].y = pInfo->dwhichlatitude; shape->line->point[1].x = dStartX + dArcDelta; shape->line->point[1].y = pInfo->dwhichlatitude; _FormatLabel( layer, shape, shape->line->point[0].y ); if(_AdjustLabelPosition( layer, shape, posLeft ) != MS_SUCCESS) return MS_FAILURE; pInfo->ilabelstate++; return MS_SUCCESS; case 1: if(!pInfo->blabelaxes) { /* Right side */ pInfo->ilabelstate++; shape->numlines = 0; return MS_SUCCESS; } dDeltaY = (pInfo->dwhichlatitude - pInfo->pboundinglines[3].point[0].y) / (pInfo->pboundinglines[3].point[1].y - pInfo->pboundinglines[3].point[0].y ); if (dDeltaY < 0) dDeltaY= dDeltaY*-1; dStartX = (pInfo->pboundinglines[3].point[1].x - pInfo->pboundinglines[3].point[0].x) * dDeltaY + pInfo->pboundinglines[3].point[0].x; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = dStartX - dArcDelta; shape->line->point[0].y = pInfo->dwhichlatitude; shape->line->point[1].x = dStartX; shape->line->point[1].y = pInfo->dwhichlatitude; _FormatLabel( layer, shape, shape->line->point[0].y ); if(_AdjustLabelPosition( layer, shape, posRight ) != MS_SUCCESS) return MS_FAILURE; pInfo->ilabelstate++; return MS_SUCCESS; case 2: shape->line->numpoints = (int) shape->line->numpoints + 1; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * shape->line->numpoints ); shape->line->point[0].x = pInfo->dstartlongitude; shape->line->point[0].y = pInfo->dwhichlatitude; for(iPointIndex = 1; iPointIndex < shape->line->numpoints; iPointIndex++) { shape->line->point[iPointIndex].x = dArcPosition; shape->line->point[iPointIndex].y = pInfo->dwhichlatitude; dArcPosition += dArcDelta; } pInfo->ilabelstate = 0; pInfo->dwhichlatitude += pInfo->dincrementlatitude; break; default: pInfo->ilabelstate = 0; break; } } /* * Increment and move to next arc */ if( pInfo->bvertical && pInfo->dwhichlongitude > pInfo->dendlongitude ) { pInfo->dwhichlatitude = pInfo->dstartlatitude; pInfo->bvertical = 0; } if (pInfo->dwhichlatitude > pInfo->dendlatitude) { /* free the lineObj and pointObj that have been erroneously allocated beforehand */ msFreeShape(shape); return MS_DONE; } return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerGetItems(layerObj *layer) { char **ppItemName = (char **) msSmallMalloc( sizeof( char * ) ); *ppItemName = (char *) msSmallMalloc( 64 ); /* why is this necessary? */ strcpy( *ppItemName, "Graticule" ); layer->numitems = 1; layer->items = ppItemName; return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerInitItemInfo(layerObj *layer) { return MS_SUCCESS; } /********************************************************************************************************************** * */ void msGraticuleLayerFreeItemInfo(layerObj *layer) { return; } /********************************************************************************************************************** * */ int msGraticuleLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { return MS_FAILURE; } /********************************************************************************************************************** * */ int msGraticuleLayerGetExtent(layerObj *layer, rectObj *extent) { graticuleObj *pInfo = (graticuleObj *) layer->layerinfo; if(pInfo) { *extent = pInfo->extent; return MS_SUCCESS; } return MS_FAILURE; } /********************************************************************************************************************** * */ int msGraticuleLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { return MS_SUCCESS; } /************************************************************************/ /* msGraticuleLayerFreeIntersectionPoints */ /* */ /* Free intersection object. */ /************************************************************************/ void msGraticuleLayerFreeIntersectionPoints( graticuleIntersectionObj *psValue) { int i=0; if (psValue) { for (i=0; inTop; i++) msFree(psValue->papszTopLabels[i]); msFree(psValue->papszTopLabels); msFree(psValue->pasTop); for (i=0; inBottom; i++) msFree(psValue->papszBottomLabels[i]); msFree(psValue->papszBottomLabels); msFree(psValue->pasBottom); for (i=0; inLeft; i++) msFree(psValue->papszLeftLabels[i]); msFree(psValue->papszLeftLabels); msFree(psValue->pasLeft); for (i=0; inRight; i++) msFree(psValue->papszRightLabels[i]); msFree(psValue->papszRightLabels); msFree(psValue->pasRight); msFree(psValue); } } /************************************************************************/ /* msGraticuleLayerInitIntersectionPoints */ /* */ /* init intersection object. */ /************************************************************************/ static void msGraticuleLayerInitIntersectionPoints( graticuleIntersectionObj *psValue) { if (psValue) { psValue->nTop = 0; psValue->pasTop = NULL; psValue->papszTopLabels = NULL; psValue->nBottom = 0; psValue->pasBottom = NULL; psValue->papszBottomLabels = NULL; psValue->nLeft = 0; psValue->pasLeft = NULL; psValue->papszLeftLabels = NULL; psValue->nRight = 0; psValue->pasRight = NULL; psValue->papszRightLabels = NULL; } } /************************************************************************/ /* msGraticuleLayerGetIntersectionPoints */ /* */ /* Utility function thar returns all intersection positions and */ /* labels (4 sides of the map) for a grid layer. */ /************************************************************************/ graticuleIntersectionObj *msGraticuleLayerGetIntersectionPoints(mapObj *map, layerObj *layer) { shapeObj shapegrid, tmpshape; rectObj searchrect; int status; pointObj oFirstPoint; pointObj oLastPoint; lineObj oLineObj; rectObj cliprect; graticuleObj *pInfo = NULL; double dfTmp; graticuleIntersectionObj *psValues = NULL; int i=0; if (layer->connectiontype != MS_GRATICULE) return NULL; pInfo = (graticuleObj *) layer->layerinfo; /*set cellsize if bnot already set*/ if (map->cellsize == 0) map->cellsize = msAdjustExtent(&(map->extent),map->width,map->height); psValues = (graticuleIntersectionObj *)msSmallMalloc(sizeof(graticuleIntersectionObj)); msGraticuleLayerInitIntersectionPoints(psValues); if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif msLayerOpen(layer); status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); return NULL; } else if(status != MS_SUCCESS) { msLayerClose(layer); return NULL; } /* step through the target shapes */ msInitShape(&shapegrid); cliprect.minx = map->extent.minx- map->cellsize; cliprect.miny = map->extent.miny- map->cellsize; cliprect.maxx = map->extent.maxx + map->cellsize; cliprect.maxy = map->extent.maxy + map->cellsize; /* clip using the layer projection */ /* msProjectRect(&map->projection , &layer->projection, &cliprect); */ while((status = msLayerNextShape(layer, &shapegrid)) == MS_SUCCESS) { /*don't really need a class here*/ /* shapegrid.classindex = msShapeGetClass(layer, &shapegrid, map->scaledenom, NULL, 0); if((shapegrid.classindex == -1) || (layer->class[shapegrid.classindex]->status == MS_OFF)) { msFreeShape(&shapegrid); continue; } */ msInitShape(&tmpshape); msCopyShape(&shapegrid, &tmpshape); /* status = msDrawShape(map, layer, &tmpshape, image, -1); */ if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection))) msProjectShape(&layer->projection, &map->projection, &shapegrid); msClipPolylineRect(&shapegrid, cliprect); msTransformShapeToPixelRound(&shapegrid, map->extent, map->cellsize); if(shapegrid.numlines <= 0 || shapegrid.line[0].numpoints < 2) { /* once clipped the shape didn't need to be drawn */ msFreeShape(&shapegrid); msFreeShape(&tmpshape); continue; } if(shapegrid.numlines >= 1 && shapegrid.line[0].numpoints >=2) { /* && shapegrid.text) */ int iTmpLine = 0; int nNumPoints = 0; /*grid code seems to retunr lines that can double cross the extenst??*/ /*creating a more than one clipped shape. Take the shape that has the most points, which should be the most likley to be correct*/ if (shapegrid.numlines > 1) { for (i=0; i nNumPoints) { nNumPoints = shapegrid.line[i].numpoints; iTmpLine = i; } } } /* get the first and last point*/ oFirstPoint.x = shapegrid.line[iTmpLine].point[0].x; oFirstPoint.y = shapegrid.line[iTmpLine].point[0].y; oLineObj = shapegrid.line[iTmpLine]; oLastPoint.x = oLineObj.point[oLineObj.numpoints-1].x; oLastPoint.y = oLineObj.point[oLineObj.numpoints-1].y; if ( pInfo->bvertical) { /*vertical*/ /*SHAPES ARE DRAWN FROM BOTTOM TO TOP.*/ /*Normally lines are drawn FROM BOTTOM TO TOP but not always for some reason, so make sure that firstpoint < lastpoint in y, We are in pixel coordinates so y increases as we we go down*/ if (oFirstPoint.y < oLastPoint.y) { dfTmp = oFirstPoint.x; oFirstPoint.x = oLastPoint.x; oLastPoint.x = dfTmp; dfTmp = oFirstPoint.y; oFirstPoint.y = oLastPoint.y; oLastPoint.y = dfTmp; } /*first point should cross the BOTTOM base where y== map->height*/ if (abs ((int)oFirstPoint.y - map->height) <=1) { char *pszLabel=NULL; oFirstPoint.y = map->height; /*validate point is in map width/height*/ if (oFirstPoint.x < 0 || oFirstPoint.x > map->width) continue; /*validate point is in map width/height*/ if (oLastPoint.x < 0 || oLastPoint.x > map->width) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].x ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate that the value is not already in the array*/ if ( psValues->nBottom > 0) { /* if (psValues->pasBottom[psValues->nBottom-1].x == oFirstPoint.x) continue; */ for (i=0; inBottom; i++) { if (psValues->pasBottom[i].x == oFirstPoint.x) break; } if (i < psValues->nBottom) continue; } if (psValues->pasBottom == NULL) { psValues->pasBottom = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszBottomLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nBottom = 1; } else { psValues->nBottom++; psValues->pasBottom = (pointObj *)msSmallRealloc(psValues->pasBottom, sizeof(pointObj)*psValues->nBottom); psValues->papszBottomLabels = (char **)msSmallRealloc(psValues->papszBottomLabels, sizeof(char *)*psValues->nBottom); } psValues->pasBottom[psValues->nBottom-1].x = oFirstPoint.x; psValues->pasBottom[psValues->nBottom-1].y = oFirstPoint.y; psValues->papszBottomLabels[psValues->nBottom-1] = msStrdup(pszLabel); msFree(pszLabel); } /*first point should cross the TOP base where y==0*/ if (abs((int)oLastPoint.y) <=1) { char *pszLabel=NULL; oLastPoint.y = 0; /*validate point is in map width/height*/ if (oLastPoint.x < 0 || oLastPoint.x > map->width) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].x ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate if same value is not already there*/ if ( psValues->nTop > 0) { /* if (psValues->pasTop[psValues->nTop-1].x == oLastPoint.x) continue; */ for (i=0; inTop; i++) { if (psValues->pasTop[i].x == oLastPoint.x || strcasecmp(pszLabel, psValues->papszTopLabels[i]) == 0) break; } if (i < psValues->nTop) continue; } if (psValues->pasTop == NULL) { psValues->pasTop = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszTopLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nTop = 1; } else { psValues->nTop++; psValues->pasTop = (pointObj *)msSmallRealloc(psValues->pasTop, sizeof(pointObj)*psValues->nTop); psValues->papszTopLabels = (char **)msSmallRealloc(psValues->papszTopLabels, sizeof(char *)*psValues->nTop); } psValues->pasTop[psValues->nTop-1].x = oLastPoint.x; psValues->pasTop[psValues->nTop-1].y = oLastPoint.y; psValues->papszTopLabels[psValues->nTop-1] = msStrdup(pszLabel); msFree(pszLabel); } } else { /*horzontal*/ /*Normally lines are drawn from left to right but not always for some reason, so make sure that firstpoint < lastpoint in x*/ if (oFirstPoint.x > oLastPoint.x) { dfTmp = oFirstPoint.x; oFirstPoint.x = oLastPoint.x; oLastPoint.x = dfTmp; dfTmp = oFirstPoint.y; oFirstPoint.y = oLastPoint.y; oLastPoint.y = dfTmp; } /*first point should cross the LEFT base where x=0 axis*/ if (abs((int)oFirstPoint.x) <=1) { char *pszLabel=NULL; oFirstPoint.x = 0; /*validate point is in map width/height*/ if (oFirstPoint.y < 0 || oFirstPoint.y > map->height) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].y ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate that the previous value is not the same*/ if ( psValues->nLeft > 0) { /* if (psValues->pasLeft[psValues->nLeft-1].y == oFirstPoint.y) continue; */ for (i=0; inLeft; i++) { if (psValues->pasLeft[i].y == oFirstPoint.y) break; } if (i < psValues->nLeft) continue; } if (psValues->pasLeft == NULL) { psValues->pasLeft = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszLeftLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nLeft = 1; } else { psValues->nLeft++; psValues->pasLeft = (pointObj *)msSmallRealloc(psValues->pasLeft, sizeof(pointObj)*psValues->nLeft); psValues->papszLeftLabels = (char **)msSmallRealloc(psValues->papszLeftLabels, sizeof(char *)*psValues->nLeft); } psValues->pasLeft[psValues->nLeft-1].x = oFirstPoint.x; psValues->pasLeft[psValues->nLeft-1].y = oFirstPoint.y; psValues->papszLeftLabels[psValues->nLeft-1] = msStrdup(pszLabel); msFree(pszLabel); } /*first point should cross the RIGHT base where x=map=>width axis*/ if (abs((int)oLastPoint.x - map->width) <=1) { char *pszLabel=NULL; oLastPoint.x = map->width; /*validate point is in map width/height*/ if (oLastPoint.y < 0 || oLastPoint.y > map->height) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].y ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate that the previous value is not the same*/ if ( psValues->nRight > 0) { /* if (psValues->pasRight[psValues->nRight-1].y == oLastPoint.y) continue; */ for (i=0; inRight; i++) { if (psValues->pasRight[i].y == oLastPoint.y) break; } if (i < psValues->nRight) continue; } if (psValues->pasRight == NULL) { psValues->pasRight = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszRightLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nRight = 1; } else { psValues->nRight++; psValues->pasRight = (pointObj *)msSmallRealloc(psValues->pasRight, sizeof(pointObj)*psValues->nRight); psValues->papszRightLabels = (char **)msSmallRealloc(psValues->papszRightLabels, sizeof(char *)*psValues->nRight); } psValues->pasRight[psValues->nRight-1].x = oLastPoint.x; psValues->pasRight[psValues->nRight-1].y = oLastPoint.y; psValues->papszRightLabels[psValues->nRight-1] = msStrdup(pszLabel); msFree(pszLabel); } } msFreeShape(&shapegrid); msFreeShape(&tmpshape); } msInitShape(&shapegrid); } msLayerClose(layer); return psValues; } /********************************************************************************************************************** * */ int msGraticuleLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msGraticuleLayerInitItemInfo; /* should use defaults for item info functions */ layer->vtable->LayerFreeItemInfo = msGraticuleLayerFreeItemInfo; layer->vtable->LayerOpen = msGraticuleLayerOpen; layer->vtable->LayerIsOpen = msGraticuleLayerIsOpen; layer->vtable->LayerWhichShapes = msGraticuleLayerWhichShapes; layer->vtable->LayerNextShape = msGraticuleLayerNextShape; /* layer->vtable->LayerResultsGetShape, use default */ layer->vtable->LayerGetShape = msGraticuleLayerGetShape; layer->vtable->LayerClose = msGraticuleLayerClose; layer->vtable->LayerGetItems = msGraticuleLayerGetItems; layer->vtable->LayerGetExtent = msGraticuleLayerGetExtent; layer->vtable->LayerGetAutoStyle = msGraticuleLayerGetAutoStyle; /* layer->vtable->LayerCloseConnection, use default */; layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } /********************************************************************************************************************** * */ static void _FormatLabel( layerObj *pLayer, shapeObj *pShape, double dDataToFormat ) { graticuleObj *pInfo = (graticuleObj *) pLayer->layerinfo; char cBuffer[32]; int iDegrees, iMinutes; switch( pInfo->ilabeltype ) { case lpDDMMSS: iDegrees = (int) dDataToFormat; dDataToFormat = fabs( dDataToFormat - (double) iDegrees ); iMinutes = (int) (dDataToFormat * 60.0); dDataToFormat = dDataToFormat - (((double) iMinutes) / 60.0); sprintf( cBuffer, pInfo->labelformat, iDegrees, iMinutes, (int) (dDataToFormat * 3600.0) ); break; case lpDDMM: iDegrees = (int) dDataToFormat; dDataToFormat = fabs( dDataToFormat - (double) iDegrees ); sprintf( cBuffer, pInfo->labelformat, iDegrees, (int) (dDataToFormat * 60.0) ); break; case lpDD: iDegrees = (int) dDataToFormat; sprintf( cBuffer, pInfo->labelformat, iDegrees); break; case lpDefault: default: sprintf( cBuffer, pInfo->labelformat, dDataToFormat ); } pShape->text = msStrdup( cBuffer ); } /********************************************************************************************************************** * * Move label position into display area by adjusting underlying shape line. */ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticulePosition ePosition ) { graticuleObj *pInfo = (graticuleObj *) pLayer->layerinfo; rectObj rectLabel; pointObj ptPoint; double size = -1; if( pInfo == NULL || pShape == NULL ) { msSetError(MS_MISCERR, "Assertion failed: Null shape or layerinfo!, ", "_AdjustLabelPosition()"); return MS_FAILURE; } if(msCheckParentPointer(pLayer->map,"map")==MS_FAILURE) return MS_FAILURE; ptPoint = pShape->line->point[0]; #ifdef USE_PROJ if(pLayer->project && msProjectionsDiffer( &pLayer->projection, &pLayer->map->projection )) msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape ); #endif if(pLayer->transform) { msTransformShapeToPixelRound(pShape, pLayer->map->extent, pLayer->map->cellsize); } size = pLayer->class[0]->labels[0]->size; /* TODO TBT: adjust minsize/maxsize/resolution. TODO RFC 77: ok to use first label? */ if(msGetLabelSize(pLayer->map, pLayer->class[0]->labels[0], pShape->text, size, &rectLabel, NULL) != MS_SUCCESS) return MS_FAILURE; /* msSetError already called */ switch( ePosition ) { case posBottom: pShape->line->point[1].y = pLayer->map->height; pShape->line->point[0].y = pLayer->map->height - (fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5); break; case posTop: pShape->line->point[1].y = 0; pShape->line->point[0].y = fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5; break; case posLeft: pShape->line->point[1].x = 0; pShape->line->point[0].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5; break; case posRight: pShape->line->point[1].x = pLayer->map->width; pShape->line->point[0].x = pLayer->map->width - (fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5); break; } if(pLayer->transform) msTransformPixelToShape( pShape, pLayer->map->extent, pLayer->map->cellsize ); #ifdef USE_PROJ if(pLayer->project && msProjectionsDiffer( &pLayer->map->projection, &pLayer->projection )) msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape ); #endif switch( ePosition ) { case posBottom: case posTop: pShape->line->point[1].x = ptPoint.x; pShape->line->point[0].x = ptPoint.x; break; case posLeft: case posRight: pShape->line->point[1].y = ptPoint.y; pShape->line->point[0].y = ptPoint.y; break; } return MS_SUCCESS; } /********************************************************************************************************************** ********************************************************************************************************************** * DefineAxes - Copyright (c) 2000, Michael P.D. Bramley. * * Permission is granted to use this code without restriction as long as * this copyright notice appears in all source files. * * Minor tweaks to incrment calculations - jnovak */ void DefineAxis( int iTickCountTarget, double *Min, double *Max, double *Inc ) { /* define local variables... */ double Test_inc, /* candidate increment value */ Test_min, /* minimum scale value */ Test_max, /* maximum scale value */ Range = *Max - *Min ; /* range of data */ int i = 0 ; /* counter */ /* don't create problems -- solve them */ if( Range < 0 ) { *Inc = 0 ; return ; } /* handle special case of repeated values */ else if( Range == 0) { *Min = ceil(*Max) - 1 ; *Max = *Min + 1 ; *Inc = 1 ; return ; } /* compute candidate for increment */ Test_inc = pow( 10.0, ceil( log10( Range/10 ) ) ) ; if(*Inc > 0 && ( Test_inc < *Inc || Test_inc > *Inc )) Test_inc = *Inc; /* establish maximum scale value... */ Test_max = ( (long)(*Max / Test_inc)) * Test_inc ; if( Test_max < *Max ) Test_max += Test_inc ; /* establish minimum scale value... */ Test_min = Test_max ; do { ++i ; Test_min -= Test_inc ; } while( Test_min > *Min ) ; /* subtracting small values can screw up the scale limits, */ /* eg: if DefineAxis is called with (min,max)=(0.01, 0.1), */ /* then the calculated scale is 1.0408E17 TO 0.05 BY 0.01. */ /* the following if statment corrects for this... */ /* if(fabs(Test_min) < 1E-10) */ /* Test_min = 0 ; */ /* adjust for too few tick marks */ if(iTickCountTarget <= 0) iTickCountTarget = MAPGRATICULE_ARC_MINIMUM; while(i < iTickCountTarget) { Test_inc /= 2 ; i *= 2 ; } if(i < 6 && 0) { Test_inc /= 2 ; if((Test_min + Test_inc) <= *Min) Test_min += Test_inc ; if((Test_max - Test_inc) >= *Max) Test_max -= Test_inc ; } /* pass back axis definition to caller */ *Min = Test_min; *Max = Test_max; *Inc = Test_inc; } /********************************************************************************************************************** **********************************************************************************************************************/ mapserver-6.4.1/mapresample.c0000644002461700001440000016513612261257215016002 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Assorted code related to resampling rasters. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include #include "mapresample.h" #include "mapthread.h" #ifndef MAX # define MIN(a,b) ((ab) ? a : b) #endif #define SKIP_MASK(x,y) (mask_rb && !*(mask_rb->data.rgba.a+(y)*mask_rb->data.rgba.row_step+(x)*mask_rb->data.rgba.pixel_step)) /************************************************************************/ /* InvGeoTransform() */ /* */ /* Invert a standard 3x2 "GeoTransform" style matrix with an */ /* implicit [1 0 0] final row. */ /************************************************************************/ int InvGeoTransform( double *gt_in, double *gt_out ) { double det, inv_det; /* we assume a 3rd row that is [1 0 0] */ /* Compute determinate */ det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4]; if( fabs(det) < 0.000000000000001 ) return 0; inv_det = 1.0 / det; /* compute adjoint, and devide by determinate */ gt_out[1] = gt_in[5] * inv_det; gt_out[4] = -gt_in[4] * inv_det; gt_out[2] = -gt_in[2] * inv_det; gt_out[5] = gt_in[1] * inv_det; gt_out[0] = ( gt_in[2] * gt_in[3] - gt_in[0] * gt_in[5]) * inv_det; gt_out[3] = (-gt_in[1] * gt_in[3] + gt_in[0] * gt_in[4]) * inv_det; return 1; } #if defined(USE_PROJ) && defined(USE_GDAL) /************************************************************************/ /* msNearestRasterResample() */ /************************************************************************/ static int msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, int debug, rasterBufferObj *mask_rb ) { double *x, *y; int nDstX, nDstY; int *panSuccess; int nDstXSize = psDstImage->width; int nDstYSize = psDstImage->height; int nSrcXSize = psSrcImage->width; int nSrcYSize = psSrcImage->height; int nFailedPoints = 0, nSetPoints = 0; #ifndef USE_GD assert(!MS_RENDERER_PLUGIN(psSrcImage->format) || src_rb->type != MS_BUFFER_GD); #endif x = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); y = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); panSuccess = (int *) msSmallMalloc( sizeof(int) * nDstXSize ); for( nDstY = 0; nDstY < nDstYSize; nDstY++ ) { for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { x[nDstX] = nDstX + 0.5; y[nDstX] = nDstY + 0.5; } pfnTransform( pCBData, nDstXSize, x, y, panSuccess ); for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { int nSrcX, nSrcY; if(SKIP_MASK(nDstX,nDstY)) continue; if( !panSuccess[nDstX] ) { nFailedPoints++; continue; } nSrcX = (int) x[nDstX]; nSrcY = (int) y[nDstX]; /* * We test the original floating point values to * avoid errors related to asymmetric rounding around zero. * (Also note bug #3120 regarding nearly redundent x/y < 0 checks). */ if( x[nDstX] < 0.0 || y[nDstX] < 0.0 || nSrcX < 0 || nSrcY < 0 || nSrcX >= nSrcXSize || nSrcY >= nSrcYSize ) { continue; } if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { #ifdef USE_GD if(src_rb->type == MS_BUFFER_GD) { int nValue = 0; assert(!gdImageTrueColor(src_rb->data.gd_img)); nValue = panCMap[src_rb->data.gd_img->pixels[nSrcY][nSrcX]]; if( nValue == -1 ) continue; nSetPoints++; dst_rb->data.gd_img->pixels[nDstY][nDstX] = nValue; } else #endif if( src_rb->type == MS_BUFFER_BYTE_RGBA ) { int src_rb_off; rgbaArrayObj *src = &src_rb->data.rgba, *dst = &dst_rb->data.rgba; assert( src_rb && dst_rb ); src_rb_off = nSrcX * src->pixel_step + nSrcY * src->row_step; if( src->a == NULL || src->a[src_rb_off] == 255 ) { int dst_rb_off; dst_rb_off = nDstX * dst->pixel_step + nDstY * dst->row_step; nSetPoints++; dst->r[dst_rb_off] = src->r[src_rb_off]; dst->g[dst_rb_off] = src->g[src_rb_off]; dst->b[dst_rb_off] = src->b[src_rb_off]; if( dst->a ) dst->a[dst_rb_off] = 255; } else if( src->a[src_rb_off] != 0 ) { int dst_rb_off; dst_rb_off = nDstX * dst->pixel_step + nDstY * dst->row_step; nSetPoints++; /* actual alpha blending is required */ msAlphaBlendPM( src->r[src_rb_off], src->g[src_rb_off], src->b[src_rb_off], src->a[src_rb_off], dst->r + dst_rb_off, dst->g + dst_rb_off, dst->b + dst_rb_off, dst->a ? dst->a + dst_rb_off : NULL ); } } } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band, src_off, dst_off; src_off = nSrcX + nSrcY * psSrcImage->width; if( !MS_GET_BIT(psSrcImage->img_mask,src_off) ) continue; nSetPoints++; dst_off = nDstX + nDstY * psDstImage->width; MS_SET_BIT(psDstImage->img_mask,dst_off); for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { psDstImage->img.raw_16bit[dst_off] = psSrcImage->img.raw_16bit[src_off]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { psDstImage->img.raw_float[dst_off] = psSrcImage->img.raw_float[src_off]; } else if(psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE) { psDstImage->img.raw_byte[dst_off] = psSrcImage->img.raw_byte[src_off]; } else { assert( 0 ); } src_off += psSrcImage->width * psSrcImage->height; dst_off += psDstImage->width * psDstImage->height; } } } } free( panSuccess ); free( x ); free( y ); msFree(mask_rb); /* -------------------------------------------------------------------- */ /* Some debugging output. */ /* -------------------------------------------------------------------- */ if( nFailedPoints > 0 && debug ) { msDebug( "msNearestRasterResampler: " "%d failed to transform, %d actually set.\n", nFailedPoints, nSetPoints ); } return 0; } /************************************************************************/ /* msSourceSample() */ /************************************************************************/ static void msSourceSample( imageObj *psSrcImage, rasterBufferObj *rb, int iSrcX, int iSrcY, double *padfPixelSum, double dfWeight, double *pdfWeightSum ) { if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { rgbaArrayObj *rgba; int rb_off; assert(rb); #ifdef USE_GD if(rb->type == MS_BUFFER_GD) { assert(!gdImageTrueColor(rb->data.gd_img) ); padfPixelSum[0] += (dfWeight * rb->data.gd_img->pixels[iSrcY][iSrcX]); *pdfWeightSum += dfWeight; return; } #endif assert(rb->type == MS_BUFFER_BYTE_RGBA); rgba = &(rb->data.rgba); rb_off = iSrcX * rgba->pixel_step + iSrcY * rgba->row_step; if( rgba->a == NULL || rgba->a[rb_off] > 1 ) { padfPixelSum[0] += rgba->r[rb_off] * dfWeight; padfPixelSum[1] += rgba->g[rb_off] * dfWeight; padfPixelSum[2] += rgba->b[rb_off] * dfWeight; if( rgba->a == NULL ) *pdfWeightSum += dfWeight; else *pdfWeightSum += dfWeight * (rgba->a[rb_off] / 255.0); } } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band; int src_off; src_off = iSrcX + iSrcY * psSrcImage->width; if( !MS_GET_BIT(psSrcImage->img_mask,src_off) ) return; for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { int nValue; nValue = psSrcImage->img.raw_16bit[src_off]; padfPixelSum[band] += dfWeight * nValue; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { float fValue; fValue = psSrcImage->img.raw_float[src_off]; padfPixelSum[band] += fValue * dfWeight; } else if(psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE) { int nValue; nValue = psSrcImage->img.raw_byte[src_off]; padfPixelSum[band] += nValue * dfWeight; } else { assert( 0 ); return; } src_off += psSrcImage->width * psSrcImage->height; } *pdfWeightSum += dfWeight; } } /************************************************************************/ /* msBilinearRasterResample() */ /************************************************************************/ static int msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, int debug, rasterBufferObj *mask_rb ) { double *x, *y; int nDstX, nDstY, i; int *panSuccess; int nDstXSize = psDstImage->width; int nDstYSize = psDstImage->height; int nSrcXSize = psSrcImage->width; int nSrcYSize = psSrcImage->height; int nFailedPoints = 0, nSetPoints = 0; double *padfPixelSum; int bandCount = MAX(4,psSrcImage->format->bands); padfPixelSum = (double *) msSmallMalloc(sizeof(double) * bandCount); x = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); y = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); panSuccess = (int *) msSmallMalloc( sizeof(int) * nDstXSize ); for( nDstY = 0; nDstY < nDstYSize; nDstY++ ) { for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { x[nDstX] = nDstX + 0.5; y[nDstX] = nDstY + 0.5; } pfnTransform( pCBData, nDstXSize, x, y, panSuccess ); for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { int nSrcX, nSrcY, nSrcX2, nSrcY2; double dfRatioX2, dfRatioY2, dfWeightSum = 0.0; if(SKIP_MASK(nDstX,nDstY)) continue; if( !panSuccess[nDstX] ) { nFailedPoints++; continue; } /* ** Offset to treat TL pixel corners as pixel location instead ** of the center. */ x[nDstX] -= 0.5; y[nDstX] -= 0.5; nSrcX = (int) floor(x[nDstX]); nSrcY = (int) floor(y[nDstX]); nSrcX2 = nSrcX+1; nSrcY2 = nSrcY+1; dfRatioX2 = x[nDstX] - nSrcX; dfRatioY2 = y[nDstX] - nSrcY; /* If we are right off the source, skip this pixel */ if( nSrcX2 < 0 || nSrcX >= nSrcXSize || nSrcY2 < 0 || nSrcY >= nSrcYSize ) continue; /* Trim in stuff one pixel off the edge */ nSrcX = MAX(nSrcX,0); nSrcY = MAX(nSrcY,0); nSrcX2 = MIN(nSrcX2,nSrcXSize-1); nSrcY2 = MIN(nSrcY2,nSrcYSize-1); memset( padfPixelSum, 0, sizeof(double) * bandCount); msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY, padfPixelSum, (1.0 - dfRatioX2) * (1.0 - dfRatioY2), &dfWeightSum ); msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY, padfPixelSum, (dfRatioX2) * (1.0 - dfRatioY2), &dfWeightSum ); msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY2, padfPixelSum, (1.0 - dfRatioX2) * (dfRatioY2), &dfWeightSum ); msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY2, padfPixelSum, (dfRatioX2) * (dfRatioY2), &dfWeightSum ); if( dfWeightSum == 0.0 ) continue; for( i = 0; i < bandCount; i++ ) padfPixelSum[i] /= dfWeightSum; if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { assert(src_rb && dst_rb); #ifdef USE_GD if(src_rb->type == MS_BUFFER_GD) { int nResult; assert( !gdImageTrueColor(src_rb->data.gd_img) && !gdImageTrueColor(dst_rb->data.gd_img)); nResult = panCMap[(int) padfPixelSum[0]]; if( nResult != -1 ) { nSetPoints++; dst_rb->data.gd_img->pixels[nDstY][nDstX] = nResult; } } else #endif #ifdef USE_GD if( src_rb->type == MS_BUFFER_BYTE_RGBA ) { #else assert( src_rb->type == MS_BUFFER_BYTE_RGBA ); #endif assert( src_rb->type == dst_rb->type ); nSetPoints++; if( dfWeightSum > 0.001 ) { int dst_rb_off = nDstX * dst_rb->data.rgba.pixel_step + nDstY * dst_rb->data.rgba.row_step; unsigned char red, green, blue, alpha; red = (unsigned char) MAX(0,MIN(255,padfPixelSum[0])); green = (unsigned char) MAX(0,MIN(255,padfPixelSum[1])); blue = (unsigned char) MAX(0,MIN(255,padfPixelSum[2])); alpha = (unsigned char)MAX(0,MIN(255,255.5*dfWeightSum)); msAlphaBlendPM( red, green, blue, alpha, dst_rb->data.rgba.r + dst_rb_off, dst_rb->data.rgba.g + dst_rb_off, dst_rb->data.rgba.b + dst_rb_off, (dst_rb->data.rgba.a == NULL) ? NULL : dst_rb->data.rgba.a + dst_rb_off ); } #ifdef USE_GD } #endif } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band; int dst_off = nDstX + nDstY * psDstImage->width; MS_SET_BIT(psDstImage->img_mask,dst_off); for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { psDstImage->img.raw_16bit[dst_off] = (short) padfPixelSum[band]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { psDstImage->img.raw_float[dst_off] = (float) padfPixelSum[band]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE ) { psDstImage->img.raw_byte[dst_off] = (unsigned char)MAX(0,MIN(255,padfPixelSum[band])); } dst_off += psDstImage->width*psDstImage->height; } } } } free( padfPixelSum ); free( panSuccess ); free( x ); free( y ); msFree(mask_rb); /* -------------------------------------------------------------------- */ /* Some debugging output. */ /* -------------------------------------------------------------------- */ if( nFailedPoints > 0 && debug ) { msDebug( "msBilinearRasterResampler: " "%d failed to transform, %d actually set.\n", nFailedPoints, nSetPoints ); } return 0; } /************************************************************************/ /* msAverageSample() */ /************************************************************************/ static int msAverageSample( imageObj *psSrcImage, rasterBufferObj *src_rb, double dfXMin, double dfYMin, double dfXMax, double dfYMax, double *padfPixelSum, double *pdfAlpha01 ) { int nXMin, nXMax, nYMin, nYMax, iX, iY; double dfWeightSum = 0.0; double dfMaxWeight = 0.0; nXMin = (int) dfXMin; nYMin = (int) dfYMin; nXMax = (int) ceil(dfXMax); nYMax = (int) ceil(dfYMax); *pdfAlpha01 = 0.0; for( iY = nYMin; iY < nYMax; iY++ ) { double dfYCellMin, dfYCellMax; dfYCellMin = MAX(iY,dfYMin); dfYCellMax = MIN(iY+1,dfYMax); for( iX = nXMin; iX < nXMax; iX++ ) { double dfXCellMin, dfXCellMax, dfWeight; dfXCellMin = MAX(iX,dfXMin); dfXCellMax = MIN(iX+1,dfXMax); dfWeight = (dfXCellMax-dfXCellMin) * (dfYCellMax-dfYCellMin); msSourceSample( psSrcImage, src_rb, iX, iY, padfPixelSum, dfWeight, &dfWeightSum ); dfMaxWeight += dfWeight; } } if( dfWeightSum == 0.0 ) return MS_FALSE; for( iX = 0; iX < 4; iX++ ) padfPixelSum[iX] /= dfWeightSum; *pdfAlpha01 = dfWeightSum / dfMaxWeight; return MS_TRUE; } /************************************************************************/ /* msAverageRasterResample() */ /************************************************************************/ static int msAverageRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, int debug, rasterBufferObj *mask_rb ) { double *x1, *y1, *x2, *y2; int nDstX, nDstY; int *panSuccess1, *panSuccess2; int nDstXSize = psDstImage->width; int nDstYSize = psDstImage->height; int nFailedPoints = 0, nSetPoints = 0; double *padfPixelSum; int bandCount = MAX(4,psSrcImage->format->bands); padfPixelSum = (double *) msSmallMalloc(sizeof(double) * bandCount); x1 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); y1 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); x2 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); y2 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); panSuccess1 = (int *) msSmallMalloc( sizeof(int) * (nDstXSize+1) ); panSuccess2 = (int *) msSmallMalloc( sizeof(int) * (nDstXSize+1) ); for( nDstY = 0; nDstY < nDstYSize; nDstY++ ) { for( nDstX = 0; nDstX <= nDstXSize; nDstX++ ) { x1[nDstX] = nDstX; y1[nDstX] = nDstY; x2[nDstX] = nDstX; y2[nDstX] = nDstY+1; } pfnTransform( pCBData, nDstXSize+1, x1, y1, panSuccess1 ); pfnTransform( pCBData, nDstXSize+1, x2, y2, panSuccess2 ); for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { double dfXMin, dfYMin, dfXMax, dfYMax; double dfAlpha01; if(SKIP_MASK(nDstX,nDstY)) continue; /* Do not generate a pixel unless all four corners transformed */ if( !panSuccess1[nDstX] || !panSuccess1[nDstX+1] || !panSuccess2[nDstX] || !panSuccess2[nDstX+1] ) { nFailedPoints++; continue; } dfXMin = MIN(MIN(x1[nDstX],x1[nDstX+1]), MIN(x2[nDstX],x2[nDstX+1])); dfYMin = MIN(MIN(y1[nDstX],y1[nDstX+1]), MIN(y2[nDstX],y2[nDstX+1])); dfXMax = MAX(MAX(x1[nDstX],x1[nDstX+1]), MAX(x2[nDstX],x2[nDstX+1])); dfYMax = MAX(MAX(y1[nDstX],y1[nDstX+1]), MAX(y2[nDstX],y2[nDstX+1])); dfXMin = MIN(MAX(dfXMin,0),psSrcImage->width+1); dfYMin = MIN(MAX(dfYMin,0),psSrcImage->height+1); dfXMax = MIN(MAX(-1,dfXMax),psSrcImage->width); dfYMax = MIN(MAX(-1,dfYMax),psSrcImage->height); memset( padfPixelSum, 0, sizeof(double)*bandCount ); if( !msAverageSample( psSrcImage, src_rb, dfXMin, dfYMin, dfXMax, dfYMax, padfPixelSum, &dfAlpha01 ) ) continue; if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { assert(dst_rb && src_rb); #ifdef USE_GD if(dst_rb->type == MS_BUFFER_GD) { int nResult = panCMap[(int) padfPixelSum[0]]; assert( !gdImageTrueColor(dst_rb->data.gd_img) ); if( nResult != -1 ) { nSetPoints++; dst_rb->data.gd_img->pixels[nDstY][nDstX] = nResult; } } else #endif #ifdef USE_GD if( dst_rb->type == MS_BUFFER_BYTE_RGBA ) { #else assert( dst_rb->type == MS_BUFFER_BYTE_RGBA ); #endif assert( src_rb->type == dst_rb ->type ); nSetPoints++; if( dfAlpha01 > 0 ) { unsigned char red, green, blue, alpha; red = (unsigned char) MAX(0,MIN(255,padfPixelSum[0]+0.5)); green = (unsigned char) MAX(0,MIN(255,padfPixelSum[1]+0.5)); blue = (unsigned char) MAX(0,MIN(255,padfPixelSum[2]+0.5)); alpha = (unsigned char) MAX(0,MIN(255,255*dfAlpha01+0.5)); RB_SET_PIXEL(dst_rb,nDstX,nDstY, red, green, blue, alpha ); } #ifdef USE_GD } #endif } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band; int dst_off = nDstX + nDstY * psDstImage->width; MS_SET_BIT(psDstImage->img_mask,dst_off); for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { psDstImage->img.raw_16bit[dst_off] = (short) (padfPixelSum[band]+0.5); } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { psDstImage->img.raw_float[dst_off] = (float) padfPixelSum[band]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE ) { psDstImage->img.raw_byte[dst_off] = (unsigned char) padfPixelSum[band]; } dst_off += psDstImage->width * psDstImage->height; } } } } free( padfPixelSum ); free( panSuccess1 ); free( x1 ); free( y1 ); free( panSuccess2 ); free( x2 ); free( y2 ); msFree(mask_rb); /* -------------------------------------------------------------------- */ /* Some debugging output. */ /* -------------------------------------------------------------------- */ if( nFailedPoints > 0 && debug ) { msDebug( "msAverageRasterResampler: " "%d failed to transform, %d actually set.\n", nFailedPoints, nSetPoints ); } return 0; } /************************************************************************/ /* ==================================================================== */ /* PROJ.4 based transformer. */ /* ==================================================================== */ /************************************************************************/ typedef struct { projectionObj *psSrcProjObj; projPJ psSrcProj; int bSrcIsGeographic; double adfInvSrcGeoTransform[6]; projectionObj *psDstProjObj; projPJ psDstProj; int bDstIsGeographic; double adfDstGeoTransform[6]; int bUseProj; } msProjTransformInfo; /************************************************************************/ /* msInitProjTransformer() */ /************************************************************************/ void *msInitProjTransformer( projectionObj *psSrc, double *padfSrcGeoTransform, projectionObj *psDst, double *padfDstGeoTransform ) { msProjTransformInfo *psPTInfo; psPTInfo = (msProjTransformInfo *) msSmallCalloc(1,sizeof(msProjTransformInfo)); /* -------------------------------------------------------------------- */ /* We won't even use PROJ.4 if either coordinate system is */ /* NULL. */ /* -------------------------------------------------------------------- */ psPTInfo->bUseProj = (psSrc->proj != NULL && psDst->proj != NULL && msProjectionsDiffer( psSrc, psDst ) ); /* -------------------------------------------------------------------- */ /* Record source image information. We invert the source */ /* transformation for more convenient inverse application in */ /* the transformer. */ /* -------------------------------------------------------------------- */ psPTInfo->psSrcProj = psSrc->proj; if( psPTInfo->bUseProj ) psPTInfo->bSrcIsGeographic = pj_is_latlong(psSrc->proj); else psPTInfo->bSrcIsGeographic = MS_FALSE; if( !InvGeoTransform(padfSrcGeoTransform, psPTInfo->adfInvSrcGeoTransform) ) return NULL; /* -------------------------------------------------------------------- */ /* Record destination image information. */ /* -------------------------------------------------------------------- */ psPTInfo->psDstProj = psDst->proj; if( psPTInfo->bUseProj ) psPTInfo->bDstIsGeographic = pj_is_latlong(psDst->proj); else psPTInfo->bDstIsGeographic = MS_FALSE; memcpy( psPTInfo->adfDstGeoTransform, padfDstGeoTransform, sizeof(double) * 6 ); return psPTInfo; } /************************************************************************/ /* msFreeProjTransformer() */ /************************************************************************/ void msFreeProjTransformer( void * pCBData ) { free( pCBData ); } /************************************************************************/ /* msProjTransformer */ /************************************************************************/ int msProjTransformer( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ) { int i; msProjTransformInfo *psPTInfo = (msProjTransformInfo*) pCBData; double x_out; /* -------------------------------------------------------------------- */ /* Transform into destination georeferenced space. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { x_out = psPTInfo->adfDstGeoTransform[0] + psPTInfo->adfDstGeoTransform[1] * x[i] + psPTInfo->adfDstGeoTransform[2] * y[i]; y[i] = psPTInfo->adfDstGeoTransform[3] + psPTInfo->adfDstGeoTransform[4] * x[i] + psPTInfo->adfDstGeoTransform[5] * y[i]; x[i] = x_out; panSuccess[i] = 1; } /* -------------------------------------------------------------------- */ /* Transform from degrees to radians if geographic. */ /* -------------------------------------------------------------------- */ if( psPTInfo->bDstIsGeographic ) { for( i = 0; i < nPoints; i++ ) { x[i] = x[i] * DEG_TO_RAD; y[i] = y[i] * DEG_TO_RAD; } } /* -------------------------------------------------------------------- */ /* Transform back to source projection space. */ /* -------------------------------------------------------------------- */ if( psPTInfo->bUseProj ) { double *z; int tr_result; z = (double *) msSmallCalloc(sizeof(double),nPoints); msAcquireLock( TLOCK_PROJ ); tr_result = pj_transform( psPTInfo->psDstProj, psPTInfo->psSrcProj, nPoints, 1, x, y, z); msReleaseLock( TLOCK_PROJ ); if( tr_result != 0 ) { free( z ); for( i = 0; i < nPoints; i++ ) panSuccess[i] = 0; return MS_FALSE; } free( z ); for( i = 0; i < nPoints; i++ ) { if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) panSuccess[i] = 0; } } /* -------------------------------------------------------------------- */ /* Transform back to degrees if source is geographic. */ /* -------------------------------------------------------------------- */ if( psPTInfo->bSrcIsGeographic ) { for( i = 0; i < nPoints; i++ ) { if( panSuccess[i] ) { x[i] = x[i] * RAD_TO_DEG; y[i] = y[i] * RAD_TO_DEG; } } } /* -------------------------------------------------------------------- */ /* Transform to source raster space. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { if( panSuccess[i] ) { x_out = psPTInfo->adfInvSrcGeoTransform[0] + psPTInfo->adfInvSrcGeoTransform[1] * x[i] + psPTInfo->adfInvSrcGeoTransform[2] * y[i]; y[i] = psPTInfo->adfInvSrcGeoTransform[3] + psPTInfo->adfInvSrcGeoTransform[4] * x[i] + psPTInfo->adfInvSrcGeoTransform[5] * y[i]; x[i] = x_out; } else { x[i] = -1; y[i] = -1; } } return 1; } /************************************************************************/ /* ==================================================================== */ /* Approximate transformer. */ /* ==================================================================== */ /************************************************************************/ typedef struct { SimpleTransformer pfnBaseTransformer; void *pBaseCBData; double dfMaxError; } msApproxTransformInfo; /************************************************************************/ /* msInitApproxTransformer() */ /************************************************************************/ static void *msInitApproxTransformer( SimpleTransformer pfnBaseTransformer, void *pBaseCBData, double dfMaxError ) { msApproxTransformInfo *psATInfo; psATInfo = (msApproxTransformInfo *) msSmallMalloc(sizeof(msApproxTransformInfo)); psATInfo->pfnBaseTransformer = pfnBaseTransformer; psATInfo->pBaseCBData = pBaseCBData; psATInfo->dfMaxError = dfMaxError; return psATInfo; } /************************************************************************/ /* msFreeApproxTransformer() */ /************************************************************************/ static void msFreeApproxTransformer( void * pCBData ) { free( pCBData ); } /************************************************************************/ /* msApproxTransformer */ /************************************************************************/ static int msApproxTransformer( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ) { msApproxTransformInfo *psATInfo = (msApproxTransformInfo *) pCBData; double x2[3], y2[3], dfDeltaX, dfDeltaY, dfError, dfDist; int nMiddle, anSuccess2[3], i, bSuccess; nMiddle = (nPoints-1)/2; /* -------------------------------------------------------------------- */ /* Bail if our preconditions are not met, or if error is not */ /* acceptable. */ /* -------------------------------------------------------------------- */ if( y[0] != y[nPoints-1] || y[0] != y[nMiddle] || x[0] == x[nPoints-1] || x[0] == x[nMiddle] || psATInfo->dfMaxError == 0.0 || nPoints <= 5 ) { return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); } /* -------------------------------------------------------------------- */ /* Transform first, last and middle point. */ /* -------------------------------------------------------------------- */ x2[0] = x[0]; y2[0] = y[0]; x2[1] = x[nMiddle]; y2[1] = y[nMiddle]; x2[2] = x[nPoints-1]; y2[2] = y[nPoints-1]; bSuccess = psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, 3, x2, y2, anSuccess2 ); if( !bSuccess || !anSuccess2[0] || !anSuccess2[1] || !anSuccess2[2] ) return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); /* -------------------------------------------------------------------- */ /* Is the error at the middle acceptable relative to an */ /* interpolation of the middle position? */ /* -------------------------------------------------------------------- */ dfDeltaX = (x2[2] - x2[0]) / (x[nPoints-1] - x[0]); dfDeltaY = (y2[2] - y2[0]) / (x[nPoints-1] - x[0]); dfError = fabs((x2[0] + dfDeltaX * (x[nMiddle] - x[0])) - x2[1]) + fabs((y2[0] + dfDeltaY * (x[nMiddle] - x[0])) - y2[1]); if( dfError > psATInfo->dfMaxError ) { bSuccess = msApproxTransformer( psATInfo, nMiddle, x, y, panSuccess ); if( !bSuccess ) { return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); } bSuccess = msApproxTransformer( psATInfo, nPoints - nMiddle, x+nMiddle, y+nMiddle, panSuccess+nMiddle ); if( !bSuccess ) { return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); } return 1; } /* -------------------------------------------------------------------- */ /* Error is OK, linearly interpolate all points along line. */ /* -------------------------------------------------------------------- */ for( i = nPoints-1; i >= 0; i-- ) { dfDist = (x[i] - x[0]); y[i] = y2[0] + dfDeltaY * dfDist; x[i] = x2[0] + dfDeltaX * dfDist; panSuccess[i] = 1; } return 1; } /************************************************************************/ /* msTransformMapToSource() */ /* */ /* Compute the extents of the current map view if transformed */ /* onto the source raster. */ /************************************************************************/ static int msTransformMapToSource( int nDstXSize, int nDstYSize, double * adfDstGeoTransform, projectionObj *psDstProj, int nSrcXSize, int nSrcYSize, double * adfInvSrcGeoTransform, projectionObj *psSrcProj, rectObj *psSrcExtent, int bUseGrid ) { int nFailures = 0; #define EDGE_STEPS 10 #define MAX_SIZE ((EDGE_STEPS+1)*(EDGE_STEPS+1)) int i, nSamples = 0, bOutInit = 0; double dfRatio; double x[MAX_SIZE], y[MAX_SIZE], z[MAX_SIZE]; /* -------------------------------------------------------------------- */ /* Collect edges in map image pixel/line coordinates */ /* -------------------------------------------------------------------- */ if( !bUseGrid ) { for( dfRatio = 0.0; dfRatio <= 1.001; dfRatio += (1.0/EDGE_STEPS) ) { assert( nSamples < MAX_SIZE ); x[nSamples ] = dfRatio * nDstXSize; y[nSamples++] = 0.0; x[nSamples ] = dfRatio * nDstXSize; y[nSamples++] = nDstYSize; x[nSamples ] = 0.0; y[nSamples++] = dfRatio * nDstYSize; x[nSamples ] = nDstXSize; y[nSamples++] = dfRatio * nDstYSize; } } /* -------------------------------------------------------------------- */ /* Collect a grid in the hopes of a more accurate region. */ /* -------------------------------------------------------------------- */ else { double dfRatio2; for( dfRatio = 0.0; dfRatio <= 1.001; dfRatio += (1.0/EDGE_STEPS) ) { for( dfRatio2=0.0; dfRatio2 <= 1.001; dfRatio2 += (1.0/EDGE_STEPS)) { assert( nSamples < MAX_SIZE ); x[nSamples ] = dfRatio2 * nDstXSize; y[nSamples++] = dfRatio * nDstYSize; } } } /* -------------------------------------------------------------------- */ /* transform to map georeferenced units */ /* -------------------------------------------------------------------- */ for( i = 0; i < nSamples; i++ ) { double x_out, y_out; x_out = adfDstGeoTransform[0] + x[i] * adfDstGeoTransform[1] + y[i] * adfDstGeoTransform[2]; y_out = adfDstGeoTransform[3] + x[i] * adfDstGeoTransform[4] + y[i] * adfDstGeoTransform[5]; x[i] = x_out; y[i] = y_out; z[i] = 0.0; } /* -------------------------------------------------------------------- */ /* Transform to layer georeferenced coordinates. */ /* -------------------------------------------------------------------- */ if( psDstProj->proj && psSrcProj->proj ) { int tr_result; if( pj_is_latlong(psDstProj->proj) ) { for( i = 0; i < nSamples; i++ ) { x[i] = x[i] * DEG_TO_RAD; y[i] = y[i] * DEG_TO_RAD; } } msAcquireLock( TLOCK_PROJ ); tr_result = pj_transform( psDstProj->proj, psSrcProj->proj, nSamples, 1, x, y, z ); msReleaseLock( TLOCK_PROJ ); if( tr_result != 0 ) return MS_FALSE; if( pj_is_latlong(psSrcProj->proj) ) { for( i = 0; i < nSamples; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { x[i] = x[i] * RAD_TO_DEG; y[i] = y[i] * RAD_TO_DEG; } } } } /* -------------------------------------------------------------------- */ /* If we just using the edges (not a grid) and we go some */ /* errors, then we need to restart using a grid pattern. */ /* -------------------------------------------------------------------- */ if( !bUseGrid ) { for( i = 0; i < nSamples; i++ ) { if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) { return msTransformMapToSource( nDstXSize, nDstYSize, adfDstGeoTransform, psDstProj, nSrcXSize, nSrcYSize, adfInvSrcGeoTransform,psSrcProj, psSrcExtent, 1 ); } } } /* -------------------------------------------------------------------- */ /* transform to layer raster coordinates, and collect bounds. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nSamples; i++ ) { double x_out, y_out; if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) { nFailures++; continue; } x_out = adfInvSrcGeoTransform[0] + x[i]*adfInvSrcGeoTransform[1] + y[i]*adfInvSrcGeoTransform[2]; y_out = adfInvSrcGeoTransform[3] + x[i]*adfInvSrcGeoTransform[4] + y[i]*adfInvSrcGeoTransform[5]; if( !bOutInit ) { psSrcExtent->minx = psSrcExtent->maxx = x_out; psSrcExtent->miny = psSrcExtent->maxy = y_out; bOutInit = 1; } else { psSrcExtent->minx = MIN(psSrcExtent->minx, x_out); psSrcExtent->maxx = MAX(psSrcExtent->maxx, x_out); psSrcExtent->miny = MIN(psSrcExtent->miny, y_out); psSrcExtent->maxy = MAX(psSrcExtent->maxy, y_out); } } if( !bOutInit ) return MS_FALSE; /* -------------------------------------------------------------------- */ /* If we had some failures, we need to expand the region to */ /* represent our very coarse sampling grid. */ /* -------------------------------------------------------------------- */ if( nFailures > 0 ) { int nGrowAmountX = (int) (psSrcExtent->maxx - psSrcExtent->minx)/EDGE_STEPS + 1; int nGrowAmountY = (int) (psSrcExtent->maxy - psSrcExtent->miny)/EDGE_STEPS + 1; psSrcExtent->minx = MAX(psSrcExtent->minx - nGrowAmountX,0); psSrcExtent->miny = MAX(psSrcExtent->miny - nGrowAmountY,0); psSrcExtent->maxx = MIN(psSrcExtent->maxx + nGrowAmountX,nSrcXSize); psSrcExtent->maxy = MIN(psSrcExtent->maxy + nGrowAmountY,nSrcYSize); } return MS_TRUE; } #endif /* def USE_PROJ */ #ifdef USE_GDAL /************************************************************************/ /* msResampleGDALToMap() */ /************************************************************************/ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, GDALDatasetH hDS ) { /* -------------------------------------------------------------------- */ /* We require PROJ.4 4.4.2 or later. Earlier versions don't */ /* have PJD_GRIDSHIFT. */ /* -------------------------------------------------------------------- */ #if !defined(PJD_GRIDSHIFT) && !defined(PJ_VERSION) msSetError(MS_PROJERR, "Projection support is not available, so msResampleGDALToMap() fails.", "msProjectRect()"); return(MS_FAILURE); #else int nSrcXSize, nSrcYSize, nDstXSize, nDstYSize; int result, bSuccess; double adfSrcGeoTransform[6], adfDstGeoTransform[6]; double adfInvSrcGeoTransform[6], dfNominalCellSize; rectObj sSrcExtent, sOrigSrcExtent; mapObj sDummyMap; imageObj *srcImage; void *pTCBData; void *pACBData; int anCMap[256]; char **papszAlteredProcessing = NULL; int nLoadImgXSize, nLoadImgYSize; double dfOversampleRatio; rasterBufferObj src_rb, *psrc_rb = NULL, *mask_rb = NULL; const char *resampleMode = CSLFetchNameValue( layer->processing, "RESAMPLE" ); if( resampleMode == NULL ) resampleMode = "NEAREST"; if(layer->mask) { int ret, maskLayerIdx; layerObj *maskLayer; maskLayerIdx = msGetLayerIndex(map,layer->mask); if(maskLayerIdx == -1) { msSetError(MS_MISCERR, "Invalid mask layer specified", "msResampleGDALToMap()"); return -1; } maskLayer = GET_LAYER(map, maskLayerIdx); mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) { free(mask_rb); return -1; } } /* -------------------------------------------------------------------- */ /* We will require source and destination to have a valid */ /* projection object. */ /* -------------------------------------------------------------------- */ if( map->projection.proj == NULL || layer->projection.proj == NULL ) { if( layer->debug ) msDebug( "msResampleGDALToMap(): " "Either map or layer projection is NULL, assuming compatible.\n" ); } /* -------------------------------------------------------------------- */ /* Initialize some information. */ /* -------------------------------------------------------------------- */ nDstXSize = image->width; nDstYSize = image->height; memcpy( adfDstGeoTransform, map->gt.geotransform, sizeof(double)*6 ); msGetGDALGeoTransform( hDS, map, layer, adfSrcGeoTransform ); nSrcXSize = GDALGetRasterXSize( hDS ); nSrcYSize = GDALGetRasterYSize( hDS ); InvGeoTransform( adfSrcGeoTransform, adfInvSrcGeoTransform ); /* -------------------------------------------------------------------- */ /* We need to find the extents in the source layer projection */ /* of the output requested region. We will accomplish this by */ /* collecting the extents of a region around the edge of the */ /* destination chunk. */ /* -------------------------------------------------------------------- */ if( CSLFetchBoolean( layer->processing, "LOAD_WHOLE_IMAGE", FALSE ) ) bSuccess = FALSE; else bSuccess = msTransformMapToSource( nDstXSize, nDstYSize, adfDstGeoTransform, &(map->projection), nSrcXSize, nSrcYSize,adfInvSrcGeoTransform, &(layer->projection), &sSrcExtent, FALSE ); /* -------------------------------------------------------------------- */ /* If the transformation failed, it is likely that we have such */ /* broad extents that the projection transformation failed at */ /* points around the extents. If so, we will assume we need */ /* the whole raster. This and later assumptions are likely to */ /* result in the raster being loaded at a higher resolution */ /* than really needed but should give decent results. */ /* -------------------------------------------------------------------- */ if( !bSuccess ) { if( layer->debug ) { if( CSLFetchBoolean( layer->processing, "LOAD_WHOLE_IMAGE", FALSE )) msDebug( "msResampleGDALToMap(): " "LOAD_WHOLE_IMAGE set, loading whole image.\n" ); else msDebug( "msTransformMapToSource(): " "pj_transform() failed. Out of bounds? Loading whole image.\n" ); } sSrcExtent.minx = 0; sSrcExtent.maxx = nSrcXSize; sSrcExtent.miny = 0; sSrcExtent.maxy = nSrcYSize; } /* -------------------------------------------------------------------- */ /* Project desired extents out by 2 pixels, and then strip to */ /* available data. */ /* -------------------------------------------------------------------- */ memcpy( &sOrigSrcExtent, &sSrcExtent, sizeof(sSrcExtent) ); sSrcExtent.minx = floor(sSrcExtent.minx-1.0); sSrcExtent.maxx = ceil (sSrcExtent.maxx+1.0); sSrcExtent.miny = floor(sSrcExtent.miny-1.0); sSrcExtent.maxy = ceil (sSrcExtent.maxy+1.0); sSrcExtent.minx = MAX(0,sSrcExtent.minx); sSrcExtent.maxx = MIN(sSrcExtent.maxx, nSrcXSize ); sSrcExtent.miny = MAX(sSrcExtent.miny, 0 ); sSrcExtent.maxy = MIN(sSrcExtent.maxy, nSrcYSize ); if( sSrcExtent.maxx <= sSrcExtent.minx || sSrcExtent.maxy <= sSrcExtent.miny ) { if( layer->debug ) msDebug( "msResampleGDALToMap(): no overlap ... no result.\n" ); return 0; } /* -------------------------------------------------------------------- */ /* Determine desired oversampling ratio. Default to 2.0 if not */ /* otherwise set. */ /* -------------------------------------------------------------------- */ dfOversampleRatio = 2.0; if( CSLFetchNameValue( layer->processing, "OVERSAMPLE_RATIO" ) != NULL ) { dfOversampleRatio = atof(CSLFetchNameValue( layer->processing, "OVERSAMPLE_RATIO" )); } /* -------------------------------------------------------------------- */ /* Decide on a resolution to read from the source image at. We */ /* will operate from full resolution data, if we are requesting */ /* at near to full resolution. Otherwise we will read the data */ /* at twice the resolution of the eventual map. */ /* -------------------------------------------------------------------- */ dfNominalCellSize = sqrt(adfSrcGeoTransform[1] * adfSrcGeoTransform[1] + adfSrcGeoTransform[2] * adfSrcGeoTransform[2]); if( (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize && !CSLFetchBoolean( layer->processing, "LOAD_FULL_RES_IMAGE", FALSE )) sDummyMap.cellsize = (dfNominalCellSize * (sOrigSrcExtent.maxx - sOrigSrcExtent.minx)) / (dfOversampleRatio * nDstXSize); else sDummyMap.cellsize = dfNominalCellSize; nLoadImgXSize = MAX(1, (int) (sSrcExtent.maxx - sSrcExtent.minx) * (dfNominalCellSize / sDummyMap.cellsize)); nLoadImgYSize = MAX(1, (int) (sSrcExtent.maxy - sSrcExtent.miny) * (dfNominalCellSize / sDummyMap.cellsize)); /* ** Because the previous calculation involved some round off, we need ** to fixup the cellsize to ensure the map region represents the whole ** RAW_WINDOW (at least in X). Re: bug 1715. */ sDummyMap.cellsize = ((sSrcExtent.maxx - sSrcExtent.minx) * dfNominalCellSize) / nLoadImgXSize; if( layer->debug ) msDebug( "msResampleGDALToMap in effect: cellsize = %f\n", sDummyMap.cellsize ); adfSrcGeoTransform[0] += + adfSrcGeoTransform[1] * sSrcExtent.minx + adfSrcGeoTransform[2] * sSrcExtent.miny; adfSrcGeoTransform[1] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[2] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[3] += + adfSrcGeoTransform[4] * sSrcExtent.minx + adfSrcGeoTransform[5] * sSrcExtent.miny; adfSrcGeoTransform[4] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[5] *= (sDummyMap.cellsize / dfNominalCellSize); papszAlteredProcessing = CSLDuplicate( layer->processing ); papszAlteredProcessing = CSLSetNameValue( papszAlteredProcessing, "RAW_WINDOW", CPLSPrintf( "%d %d %d %d", (int) sSrcExtent.minx, (int) sSrcExtent.miny, (int) (sSrcExtent.maxx-sSrcExtent.minx), (int) (sSrcExtent.maxy-sSrcExtent.miny))); /* -------------------------------------------------------------------- */ /* We clone this without referencing it knowing that the */ /* srcImage will take a reference on it. The sDummyMap is */ /* destroyed off the stack, so the missing map reference is */ /* never a problem. The image's dereference of the */ /* outputformat during the msFreeImage() calls will result in */ /* the output format being cleaned up. */ /* */ /* We make a copy so we can easily modify the outputformat used */ /* for the temporary image to include transparentency support. */ /* -------------------------------------------------------------------- */ sDummyMap.outputformat = msCloneOutputFormat( image->format ); sDummyMap.width = nLoadImgXSize; sDummyMap.height = nLoadImgYSize; sDummyMap.mappath = map->mappath; sDummyMap.shapepath = map->shapepath; /* -------------------------------------------------------------------- */ /* If we are working in 256 color GD mode, allocate 0 as the */ /* transparent color on the temporary image so it will be */ /* initialized to see-through. We pick an arbitrary rgb tuple */ /* as our transparent color, but ensure it is initalized in the */ /* map so that normal transparent avoidance will apply. */ /* -------------------------------------------------------------------- */ if( MS_RENDERER_PLUGIN(sDummyMap.outputformat) ) { assert(rb); msInitializeRendererVTable(sDummyMap.outputformat); #ifdef USE_GD if( rb->type == MS_BUFFER_GD ) { assert( !gdImageTrueColor( rb->data.gd_img ) ); sDummyMap.outputformat->transparent = MS_TRUE; sDummyMap.imagecolor.red = 117; sDummyMap.imagecolor.green = 17; sDummyMap.imagecolor.blue = 191; } /* -------------------------------------------------------------------- */ /* If we are working in RGB mode ensure we produce an RGBA */ /* image so the transparency can be preserved. */ /* -------------------------------------------------------------------- */ else #endif { assert( sDummyMap.outputformat->imagemode == MS_IMAGEMODE_RGB || sDummyMap.outputformat->imagemode == MS_IMAGEMODE_RGBA ); sDummyMap.outputformat->transparent = MS_TRUE; sDummyMap.outputformat->imagemode = MS_IMAGEMODE_RGBA; MS_INIT_COLOR(sDummyMap.imagecolor,-1,-1,-1,255); } } /* -------------------------------------------------------------------- */ /* Setup a dummy map object we can use to read from the source */ /* raster, with the newly established extents, and resolution. */ /* -------------------------------------------------------------------- */ srcImage = msImageCreate( nLoadImgXSize, nLoadImgYSize, sDummyMap.outputformat, NULL, NULL, map->resolution, map->defresolution, &(sDummyMap.imagecolor)); if (srcImage == NULL) return -1; /* msSetError() should have been called already */ if( MS_RENDERER_PLUGIN( srcImage->format ) ) { psrc_rb = &src_rb; memset( psrc_rb, 0, sizeof(rasterBufferObj) ); if( srcImage->format->vtable->supports_pixel_buffer ) { srcImage->format->vtable->getRasterBufferHandle( srcImage, psrc_rb ); } else { srcImage->format->vtable->initializeRasterBuffer(psrc_rb,nLoadImgXSize, nLoadImgYSize,MS_IMAGEMODE_RGBA); } } /* -------------------------------------------------------------------- */ /* Draw into the temporary image. Temporarily replace the */ /* layer processing directive so that we use our RAW_WINDOW. */ /* -------------------------------------------------------------------- */ { char **papszSavedProcessing = layer->processing; char* origMask = layer->mask; layer->mask = NULL; layer->processing = papszAlteredProcessing; result = msDrawRasterLayerGDAL( &sDummyMap, layer, srcImage, psrc_rb, hDS ); layer->processing = papszSavedProcessing; layer->mask = origMask; CSLDestroy( papszAlteredProcessing ); if( result ) { if( MS_RENDERER_PLUGIN( srcImage->format ) && !srcImage->format->vtable->supports_pixel_buffer) msFreeRasterBuffer(psrc_rb); msFreeImage( srcImage ); return result; } } #ifdef USE_GD /* -------------------------------------------------------------------- */ /* Do we need to generate a colormap remapping, potentially */ /* allocating new colors on the destination color map? */ /* -------------------------------------------------------------------- */ if( psrc_rb && psrc_rb->type == MS_BUFFER_GD ) { int iColor, nColorCount; anCMap[0] = -1; /* color zero is always transparent */ nColorCount = gdImageColorsTotal( psrc_rb->data.gd_img ); for( iColor = 1; iColor < nColorCount; iColor++ ) { anCMap[iColor] = msAddColorGD( map, rb->data.gd_img, 0, gdImageRed( psrc_rb->data.gd_img, iColor ), gdImageGreen( psrc_rb->data.gd_img, iColor ), gdImageBlue( psrc_rb->data.gd_img, iColor ) ); } for( iColor = nColorCount; iColor < 256; iColor++ ) anCMap[iColor] = -1; } #endif /* -------------------------------------------------------------------- */ /* Setup transformations between our source image, and the */ /* target map image. */ /* -------------------------------------------------------------------- */ pTCBData = msInitProjTransformer( &(layer->projection), adfSrcGeoTransform, &(map->projection), adfDstGeoTransform ); if( pTCBData == NULL ) { if( layer->debug ) msDebug( "msInitProjTransformer() returned NULL.\n" ); if( MS_RENDERER_PLUGIN( srcImage->format ) && !srcImage->format->vtable->supports_pixel_buffer) msFreeRasterBuffer(psrc_rb); msFreeImage( srcImage ); return MS_PROJERR; } /* -------------------------------------------------------------------- */ /* It is cheaper to use linear approximations as long as our */ /* error is modest (less than 0.333 pixels). */ /* -------------------------------------------------------------------- */ pACBData = msInitApproxTransformer( msProjTransformer, pTCBData, 0.333 ); /* -------------------------------------------------------------------- */ /* Perform the resampling. */ /* -------------------------------------------------------------------- */ if( EQUAL(resampleMode,"AVERAGE") ) result = msAverageRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, layer->debug, mask_rb ); else if( EQUAL(resampleMode,"BILINEAR") ) result = msBilinearRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, layer->debug, mask_rb ); else result = msNearestRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, layer->debug, mask_rb ); /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ if( MS_RENDERER_PLUGIN( srcImage->format ) && !srcImage->format->vtable->supports_pixel_buffer) msFreeRasterBuffer(psrc_rb); msFreeImage( srcImage ); msFreeProjTransformer( pTCBData ); msFreeApproxTransformer( pACBData ); return result; #endif } #endif /* def USE_GDAL */ mapserver-6.4.1/maphash.c0000644002461700001440000001426112261257215015105 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implement hashTableObj class. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include "mapserver.h" #include "maphash.h" static unsigned hash(const char *key) { unsigned hashval; for(hashval=0; *key!='\0'; key++) hashval = tolower(*key) + 31 * hashval; return(hashval % MS_HASHSIZE); } hashTableObj *msCreateHashTable() { int i; hashTableObj *table; table = (hashTableObj *) msSmallMalloc(sizeof(hashTableObj)); table->items = (struct hashObj **) msSmallMalloc(sizeof(struct hashObj *)*MS_HASHSIZE); for (i=0; iitems[i] = NULL; table->numitems = 0; return table; } int initHashTable( hashTableObj *table ) { int i; table->items = (struct hashObj **) malloc(sizeof(struct hashObj *)*MS_HASHSIZE); MS_CHECK_ALLOC(table->items, sizeof(struct hashObj *)*MS_HASHSIZE, MS_FAILURE); for (i=0; iitems[i] = NULL; table->numitems = 0; return MS_SUCCESS; } void msFreeHashTable( hashTableObj *table ) { if( table != NULL ) { msFreeHashItems(table); free(table); table = NULL; } } int msHashIsEmpty( hashTableObj *table ) { if (table->numitems == 0 ) return MS_TRUE; else return MS_FALSE; } void msFreeHashItems( hashTableObj *table ) { int i; struct hashObj *tp=NULL; struct hashObj *prev_tp=NULL; if (table) { if(table->items) { for (i=0; iitems[i] != NULL) { for (tp=table->items[i]; tp!=NULL; prev_tp=tp,tp=tp->next,free(prev_tp)) { msFree(tp->key); msFree(tp->data); } } if (tp) free(tp); } free(table->items); table->items = NULL; } else { msSetError(MS_HASHERR, "No items allocated.", "msFreeHashItems()"); } } else { msSetError(MS_HASHERR, "Can't free NULL table", "msFreeHashItems()"); } } struct hashObj *msInsertHashTable(hashTableObj *table, const char *key, const char *value) { struct hashObj *tp; unsigned hashval; if (!table || !key || !value) { msSetError(MS_HASHERR, "Invalid hash table or key", "msInsertHashTable"); return NULL; } for (tp=table->items[hash(key)]; tp!=NULL; tp=tp->next) if(strcasecmp(key, tp->key) == 0) break; if (tp == NULL) { /* not found */ tp = (struct hashObj *) malloc(sizeof(*tp)); MS_CHECK_ALLOC(tp, sizeof(*tp), NULL); tp->key = msStrdup(key); hashval = hash(key); tp->next = table->items[hashval]; table->items[hashval] = tp; table->numitems++; } else { free(tp->data); } if ((tp->data = msStrdup(value)) == NULL) return NULL; return tp; } char *msLookupHashTable(hashTableObj *table, const char *key) { struct hashObj *tp; if (!table || !key) { return(NULL); } for (tp=table->items[hash(key)]; tp!=NULL; tp=tp->next) if (strcasecmp(key, tp->key) == 0) return(tp->data); return NULL; } int msRemoveHashTable(hashTableObj *table, const char *key) { struct hashObj *tp; struct hashObj *prev_tp=NULL; int status = MS_FAILURE; if (!table || !key) { msSetError(MS_HASHERR, "No hash table", "msRemoveHashTable"); return MS_FAILURE; } tp=table->items[hash(key)]; if (!tp) { msSetError(MS_HASHERR, "No such hash entry", "msRemoveHashTable"); return MS_FAILURE; } prev_tp = NULL; while (tp != NULL) { if (strcasecmp(key, tp->key) == 0) { status = MS_SUCCESS; if (prev_tp) { prev_tp->next = tp->next; free(tp); break; } else { table->items[hash(key)] = tp->next; free(tp); break; } } prev_tp = tp; tp = tp->next; } if (status == MS_SUCCESS) table->numitems--; return status; } const char *msFirstKeyFromHashTable( hashTableObj *table ) { int hash_index; if (!table) { msSetError(MS_HASHERR, "No hash table", "msFirstKeyFromHashTable"); return NULL; } for (hash_index = 0; hash_index < MS_HASHSIZE; hash_index++ ) { if (table->items[hash_index] != NULL ) return table->items[hash_index]->key; } return NULL; } const char *msNextKeyFromHashTable( hashTableObj *table, const char *lastKey ) { int hash_index; struct hashObj *link; if (!table) { msSetError(MS_HASHERR, "No hash table", "msNextKeyFromHashTable"); return NULL; } if ( lastKey == NULL ) return msFirstKeyFromHashTable( table ); hash_index = hash(lastKey); for ( link = table->items[hash_index]; link != NULL && strcasecmp(lastKey,link->key) != 0; link = link->next ) {} if ( link != NULL && link->next != NULL ) return link->next->key; while ( ++hash_index < MS_HASHSIZE ) { if ( table->items[hash_index] != NULL ) return table->items[hash_index]->key; } return NULL; } mapserver-6.4.1/mapserver-api.h0000644002461700001440000000133712261257215016244 0ustar tbonfortusers/* * File: mapserver-api.h * Author: tbonfort * * Created on March 14, 2013, 1:12 PM */ #ifndef MAPSERVER_API_H #define MAPSERVER_API_H #include "mapserver-version.h" #ifdef __cplusplus extern "C" { #endif typedef struct mapObj mapObj; typedef struct layerObj layerObj; typedef struct classObj classObj; typedef struct styleObj styleObj; typedef struct labelObj labelObj; typedef struct symbolObj symbolObj; typedef struct imageObj imageObj; mapObj* umnms_new_map(char *filename); layerObj* umnms_new_layer(mapObj *map); classObj* umnms_new_class(layerObj *layer); styleObj* umnms_new_style(classObj *theclass); labelObj* umnms_new_label(classObj *theclass); #ifdef __cplusplus } #endif #endif /* MAPSERVER_API_H */ mapserver-6.4.1/maphttp.h0000644002461700001440000001062612261257215015147 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: http requests related functions * Author: MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPHTTP_H #define MAPHTTP_H #include "mapprimitive.h" #include #ifdef __cplusplus extern "C" { #endif #define MS_HTTP_SUCCESS(status) (status == 200 || status == 242) enum MS_HTTP_PROXY_TYPE { MS_HTTP, MS_SOCKS5 }; enum MS_HTTP_AUTH_TYPE { MS_BASIC, MS_DIGEST, MS_NTLM, MS_ANY, MS_ANYSAFE }; typedef struct http_request_info { int nLayerId; char *pszGetUrl; char *pszOutputFile; int nTimeout; int nMaxBytes; rectObj bbox; int width; int height; int nStatus; /* 200=success, value < 0 if request failed */ char *pszContentType; /* Content-Type of the response */ char *pszErrBuf; /* Buffer where curl can write errors */ char *pszPostRequest; /* post request content (NULL for GET) */ char *pszPostContentType;/* post request MIME type */ char *pszUserAgent; /* User-Agent, auto-generated if not set */ char *pszHTTPCookieData; /* HTTP Cookie data */ char *pszProxyAddress; /* The address (IP or hostname) of proxy svr */ long nProxyPort; /* The proxy's port */ enum MS_HTTP_PROXY_TYPE eProxyType; /* The type of proxy */ enum MS_HTTP_AUTH_TYPE eProxyAuthType; /* Auth method against proxy */ char *pszProxyUsername; /* Proxy authentication username */ char *pszProxyPassword; /* Proxy authentication password */ enum MS_HTTP_AUTH_TYPE eHttpAuthType; /* HTTP Authentication type */ char *pszHttpUsername; /* HTTP Authentication username */ char *pszHttpPassword; /* HTTP Authentication password */ /* For debugging/profiling */ int debug; /* Debug mode? MS_TRUE/MS_FALSE */ /* Private members */ void * curl_handle; /* CURLM * handle */ FILE * fp; /* FILE * used during download */ char * result_data; /* output if pszOutputFile is NULL */ int result_size; int result_buf_size; } httpRequestObj; #ifdef USE_CURL int msHTTPInit(void); void msHTTPCleanup(void); void msHTTPInitRequestObj(httpRequestObj *pasReqInfo, int numRequests); void msHTTPFreeRequestObj(httpRequestObj *pasReqInfo, int numRequests); int msHTTPExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, int bCheckLocalCache); int msHTTPGetFile(const char *pszGetUrl, const char *pszOutputFile, int *pnHTTPStatus, int nTimeout, int bCheckLocalCache, int bDebug, int nMaxBytes); int msHTTPAuthProxySetup(hashTableObj *mapmd, hashTableObj *lyrmd, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, const char* namespaces); #endif /*USE_CURL*/ #ifdef __cplusplus } #endif #endif /* MAPHTTP_H */ mapserver-6.4.1/mapxml.c0000644002461700001440000000560412261257215014763 0ustar tbonfortusers/****************************************************************************** * $id: mapfile.c 7854 2008-08-14 19:22:48Z dmorissette $ * * Project: MapServer * Purpose: High level Map file parsing code. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #ifdef USE_XMLMAPFILE #include #include "libexslt/exslt.h" #include #include #include #include extern int xmlLoadExtDtdDefaultValue; int msTransformXmlMapfile(const char *stylesheet, const char *xmlMapfile, FILE *tmpfile) { xsltStylesheetPtr cur = NULL; int status = MS_FAILURE; xmlDocPtr doc, res; exsltRegisterAll(); xsltRegisterTestModule(); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; cur = xsltParseStylesheetFile((const xmlChar *)stylesheet); if (cur == NULL) { msSetError(MS_MISCERR, "Failed to load xslt stylesheet", "msTransformXmlMapfile()"); goto done; } doc = xmlParseFile(xmlMapfile); if (doc == NULL) { msSetError(MS_MISCERR, "Failed to load xml mapfile", "msTransformXmlMapfile()"); goto done; } res = xsltApplyStylesheet(cur, doc, NULL); if (res == NULL) { msSetError(MS_MISCERR, "Failed to apply style sheet to %s", "msTransformXmlMapfile()", xmlMapfile); goto done; } if ( xsltSaveResultToFile(tmpfile, res, cur) != -1 ) status = MS_SUCCESS; done: if (cur) xsltFreeStylesheet(cur); if (res) xmlFreeDoc(res); if (doc) xmlFreeDoc(doc); xsltCleanupGlobals(); xmlCleanupParser(); return status; } #endif mapserver-6.4.1/mapgd.c0000644002461700001440000010061612261257215014554 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: GD rendering functions (using renderer plugin API) * Author: Stephen Lime, Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2009 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. *****************************************************************************/ #include "mapserver-config.h" #ifdef USE_GD #include "mapserver.h" #include "mapthread.h" #include #include #include #include #include #include #ifdef _WIN32 #include #include #endif int msGDSetup() { #ifdef USE_GD_FREETYPE if (gdFontCacheSetup() != 0) { return MS_FAILURE; } #endif return MS_SUCCESS; } void msGDCleanup(int signal) { #ifdef USE_GD_FREETYPE if(!signal) { /* there's a potential deadlock if we're killed by a signal and the font cache is already locked. We don't tear down the fontcache in this case to avoid it (issue 4093)*/ gdFontCacheShutdown(); } #endif } #define MS_IMAGE_GET_GDIMAGEPTR(image) ((gdImagePtr) image->img.plugin) fontMetrics bitmapFontMetricsGD[5]; gdFontPtr msGetBitmapFont(int size) { switch(size) { /* set the font to use */ case MS_TINY: return gdFontGetTiny(); break; case MS_SMALL: return gdFontGetSmall(); break; case MS_MEDIUM: return gdFontGetMediumBold(); break; case MS_LARGE: return gdFontGetLarge(); break; case MS_GIANT: return gdFontGetGiant(); break; default: msSetError(MS_GDERR,"Invalid bitmap font. Must be one of tiny, small, medium, large or giant." , "msGetBitmapFont()"); return(NULL); } } int msImageSetPenGD(gdImagePtr img, colorObj *color) { if(MS_VALID_COLOR(*color)) color->pen = gdImageColorResolve(img, color->red, color->green, color->blue); else color->pen = -1; return(MS_SUCCESS); } int startNewLayerGD(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int closeNewLayerGD(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } /* ** GD driver-specific image handling functions. */ imageObj *createImageGD(int width, int height, outputFormatObj *format, colorObj* bg) { imageObj *img = NULL; gdImagePtr ip; img = (imageObj *) calloc(1, sizeof (imageObj)); MS_CHECK_ALLOC(img, sizeof (imageObj), NULL); /* we're only doing PC256 for the moment */ ip = gdImageCreate(width, height); if(bg && MS_VALID_COLOR(*bg)) { gdImageColorAllocate(ip, bg->red, bg->green, bg->blue); /* set the background color */ } else { gdImageColorAllocate(ip,117,17,91); /*random bg color (same one as picked in msResampleGDALToMap) */ } if(format->transparent || !bg || !MS_VALID_COLOR(*bg)) { gdImageColorTransparent(ip, 0); } img->img.plugin = (void *) ip; return img; } int saveImageGD(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { gdImagePtr ip; if(!img || !fp) return MS_FAILURE; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; return saveGdImage(ip,fp,format); } int freeImageGD(imageObj *img) { gdImagePtr ip; if(img) { ip = MS_IMAGE_GET_GDIMAGEPTR(img); if(ip) gdImageDestroy(ip); } return MS_SUCCESS; } /* ** GD driver-specific rendering functions. */ #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) #define SETPEN(ip, c) if(c && c->pen == MS_PEN_UNSET) c->pen = gdImageColorResolve(ip, c->red, c->green, c->blue) static void imageScanline(gdImagePtr im, int x1, int x2, int y, int c) { int x; /* TO DO: This fix (adding if/then) was to address circumstances in the polygon fill code */ /* where x2 < x1. There may be something wrong in that code, but at any rate this is safer. */ if(x1 < x2) for(x=x1; x<=x2; x++) gdImageSetPixel(im, x, y, c); else for(x=x2; x<=x1; x++) gdImageSetPixel(im, x, y, c); } /* ** Polygon fill. Based on "Concave Polygon Scan Conversion" by Paul ** Heckbert from "Graphics Gems", Academic Press, 1990. ** */ static void imageFilledPolygon(gdImagePtr im, shapeObj *p, int c) { typedef struct { /* a polygon edge */ double x; /* x coordinate of edge's intersection with current scanline */ double dx; /* change in x with respect to y */ int i; /* point index */ int l; /* line number */ int s; /* scanline */ } pEdge; pointObj *point1, *point2; int k, l, i, j, xl, xr, ymin, ymax, y, n,nvert, nact, m; int wrong_order; pEdge *edge, *temp; pEdge **active; int *yhist, *edgeindex; if(p->numlines == 0) return; n=0; for(i=0; inumlines; i++) { n += p->line[i].numpoints; } if(n == 0) return; edge = (pEdge *) msSmallCalloc(n,sizeof(pEdge)); /* All edges in the polygon */ edgeindex = (int *) msSmallCalloc(n,sizeof(int)); /* Index to edges sorted by scanline */ active = (pEdge **) msSmallCalloc(n,sizeof(pEdge*)); /* Pointers to active edges for current scanline */ nvert=0; ymin= (int) ceil(p->line[0].point[0].y-0.5); ymax= (int) floor(p->line[0].point[0].y-0.5); /* populate the edge table */ for(l=0; lnumlines; l++) { for(i=0; i < p->line[l].numpoints; i++) { j = i < p->line[l].numpoints -1 ? i+1 : 0; if (p->line[l].point[i].y < p->line[l].point[j].y ) { point1 = &(p->line[l].point[i]); point2 = &(p->line[l].point[j]); } else { point2 = &(p->line[l].point[i]); point1 = &(p->line[l].point[j]); } edge[nvert].dx = point2->y == point1->y ? 0 : (point2->x - point1->x) / (point2->y - point1->y); edge[nvert].s = MS_NINT( p->line[l].point[i].y ); /* ceil( p->line[l].point[i].y - 0.5 ); */ edge[nvert].x = point1->x; edge[nvert].i = nvert; edge[nvert].l = l; ymin = MS_MIN(ymin,edge[nvert].s); ymax = MS_MAX(ymax,edge[nvert].s); nvert++; } } /* Use histogram sort to create a bucket-sorted edgeindex by scanline */ yhist = (int*) msSmallCalloc(ymax - ymin + 2, sizeof(int)); for(i=0; iline[edge[i].l].numpoints - 1; else j = i - 1; if (edge[j].s <= y ) { /* old edge, remove from active list */ for (m=0; mi!=j; m++); if (m y) { /* new edge, insert into active list */ active[nact]= & edge[j]; nact++; } /* vertex next after i */ if(i==nvert-1 || edge[i].l != edge[i+1].l) j = i - p->line[edge[i].l].numpoints + 1; else j = i + 1; if (edge[j].s <= y - 1 ) { /* old edge, remove from active list */ for (m=0; mi!=i; m++); if (m y ) { /* new edge, insert into active list */ active[nact]= & edge[i]; nact++; } } /* Sort active edges by x */ do { wrong_order = 0; for(i=0; i < nact-1; i++) { if(active[i]->x > active[i+1]->x) { wrong_order = 1; SWAP(active[i], active[i+1], temp); } } } while(wrong_order); /* draw horizontal spans for scanline y */ for (j=0; j j+1 is inside, j+1 -> j+2 is outside */ xl = (int) MS_NINT(active[j]->x ); xr = (int) (active[j+1]->x - 0.5) ; if(active[j]->x != active[j+1]->x) imageScanline(im, xl, xr, y, c); active[j]->x += active[j]->dx; /* increment edge coords */ active[j+1]->x += active[j+1]->dx; } } free(active); free(edgeindex); free(edge); } static void imagePolyline(gdImagePtr im, shapeObj *p, int c) { int i, j; for (i=0; i < p->numlines; i++) { lineObj *line = &(p->line[i]); for(j=1; jnumpoints; j++) { pointObj *point1 = &line->point[j-1]; pointObj *point2 = &line->point[j]; gdImageLine(im, (int) point1->x, (int) point1->y, (int) point2->x, (int) point2->y, c); } } } int renderLineGD(imageObj *img, shapeObj *p, strokeStyleObj *stroke) { gdImagePtr ip; int c; gdImagePtr brush=NULL; if(!img || !p || !stroke) return MS_FAILURE; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; SETPEN(ip, stroke->color); c = stroke->color->pen; if(stroke->patternlength > 0) { int *style; int i, j, k=0; int sc; for(i=0; ipatternlength; i++) k += MS_NINT(stroke->pattern[i]); style = (int *) malloc (k * sizeof(int)); MS_CHECK_ALLOC(style, k * sizeof(int), MS_FAILURE); sc = c; /* start with the color */ k=0; for(i=0; ipatternlength; i++) { for(j=0; jpattern[i]); j++, k++) { style[k] = sc; } sc = ((sc==c)?gdTransparent:c); } gdImageSetStyle(ip, style, k); free(style); c = gdStyled; } if(stroke->width > 1) { int brush_fc; brush = gdImageCreate(ceil(stroke->width), ceil(stroke->width)); gdImageColorAllocate(brush, gdImageRed(ip,0), gdImageGreen(ip, 0), gdImageBlue(ip, 0)); gdImageColorTransparent(brush,0); brush_fc = gdImageColorAllocate(brush, gdImageRed(ip,stroke->color->pen), gdImageGreen(ip,stroke->color->pen), gdImageBlue(ip,stroke->color->pen)); gdImageFilledEllipse(brush,MS_NINT(brush->sx/2),MS_NINT(brush->sy/2), MS_NINT(stroke->width),MS_NINT(stroke->width), brush_fc); gdImageSetBrush(ip, brush); if(stroke->patternlength > 0) { c = gdStyledBrushed; } else { c = gdBrushed; } } /* finally draw something */ imagePolyline(ip, p, c); /* clean up */ if(stroke->width>1) { gdImageDestroy(brush); } return MS_SUCCESS; } int renderPolygonGD(imageObj *img, shapeObj *p, colorObj *color) { gdImagePtr ip; if(!img || !p || !color) return MS_FAILURE; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; SETPEN(ip, color); imageFilledPolygon(ip, p, color->pen); return MS_SUCCESS; } int renderGlyphsLineGD(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text) { return MS_SUCCESS; } int renderGlyphsGD(imageObj *img, double x, double y, labelStyleObj *style, char *text) { #ifdef USE_GD_FREETYPE gdImagePtr ip; char *error=NULL; int bbox[8]; int c = 0,oc = 0; x = MS_NINT(x); y = MS_NINT(y); if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; if(!text || !strlen(text)) return(MS_SUCCESS); /* not errors, just don't want to do anything */ SETPEN(ip, style->color); SETPEN(ip, style->outlinecolor); if(style->antialias) { if(style->color) c = style->color->pen; if(style->outlinewidth > 0) oc = style->outlinecolor->pen; } else { if(style->color) c = -style->color->pen; if(style->outlinewidth > 0) oc = -style->outlinecolor->pen; } if(style->outlinewidth > 0) { /* handle the outline color */ error = gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x, y-1, text); if(error) { msSetError(MS_TTFERR, "%s", "msDrawTextGD()", error); return(MS_FAILURE); } gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x, y+1, text); gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x+1, y, text); gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x-1, y, text); gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x-1, y-1, text); gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x-1, y+1, text); gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x+1, y-1, text); gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x+1, y+1, text); } if(style->color) gdImageStringFT(ip, bbox, c, style->fonts[0], style->size, style->rotation, x, y, text); return MS_SUCCESS; #else msSetError(MS_TTFERR, "Freetype support not enabled in this GD build", "renderGlyphsGD()"); return MS_FAILURE; #endif } int renderEllipseSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { /* check for trivial cases - 1x1 and 2x2, GD does not do these well */ gdImagePtr ip; int w,h,fc,oc; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; SETPEN(ip, style->color); SETPEN(ip, style->outlinecolor); fc = style->color ? style->color->pen : -1; oc = style->outlinecolor ? style->outlinecolor->pen : -1; if(oc==-1 && fc ==-1) { return MS_SUCCESS; } w = symbol->sizex * style->scale; h = symbol->sizey * style->scale; if(w==1 && h==1) { if(fc >= 0) gdImageSetPixel(ip, x, y, fc); else gdImageSetPixel(ip, x, y, oc); return MS_SUCCESS; } if(w==2 && h==2) { if(oc >= 0) { gdImageSetPixel(ip, x, y, oc); gdImageSetPixel(ip, x, y+1, oc); gdImageSetPixel(ip, x+1, y, oc); gdImageSetPixel(ip, x+1, y+1, oc); } else { gdImageSetPixel(ip, x, y, fc); gdImageSetPixel(ip, x, y+1, fc); gdImageSetPixel(ip, x+1, y, fc); gdImageSetPixel(ip, x+1, y+1, fc); } return MS_SUCCESS; } if(symbol->filled) { if(fc >= 0) gdImageFilledEllipse(ip, x, y, w, h, fc); if(oc >= 0) gdImageArc(ip, x, y, w, h, 0, 360, oc); } else { if(fc < 0) fc = oc; /* try the outline color */ gdImageArc(ip, x, y, w, h, 0, 360, fc); } return MS_SUCCESS; } static void get_bbox(pointObj *poiList, int numpoints, double *minx, double *miny, double *maxx, double *maxy) { int j; *minx = *maxx = poiList[0].x; *miny = *maxy = poiList[0].y; for(j=1; jsizex * .5; /* get the shift vector at 0,0 */ dp_y = symbol->sizey * .5; /* center at 0,0 and rotate; then move back */ for( i=0; i < symbol->numpoints; i++) { /* don't rotate PENUP commands (TODO: should use a constant here) */ if ((symbol->points[i].x == -99.0) && (symbol->points[i].x == -99.0) ) { newSymbol->points[i].x = -99.0; newSymbol->points[i].y = -99.0; continue; } newSymbol->points[i].x = dp_x + ((symbol->points[i].x-dp_x)*cos_a - (symbol->points[i].y-dp_y)*sin_a); newSymbol->points[i].y = dp_y + ((symbol->points[i].x-dp_x)*sin_a + (symbol->points[i].y-dp_y)*cos_a); } /* get the new bbox of the symbol, because we need it to get the new dimensions of the new symbol */ get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy); if ( (fabs(minx)>TOL) || (fabs(miny)>TOL) ) { xcor = minx*-1.0; /* symbols always start at 0,0 so get the shift vector */ ycor = miny*-1.0; for( i=0; i < newSymbol->numpoints; i++) { if ((newSymbol->points[i].x == -99.0) && (newSymbol->points[i].x == -99.0)) continue; newSymbol->points[i].x = newSymbol->points[i].x + xcor; newSymbol->points[i].y = newSymbol->points[i].y + ycor; } /* update the bbox to get the final dimension values for the symbol */ get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy); } newSymbol->sizex = maxx; newSymbol->sizey = maxy; return newSymbol; } int renderVectorSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { int bRotated = MS_FALSE; int j,k; gdImagePtr ip; gdPoint mPoints[MS_MAXVECTORPOINTS]; gdPoint oldpnt,newpnt; int fc,oc; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; SETPEN(ip, style->color); SETPEN(ip, style->outlinecolor); fc = style->color ? style->color->pen : -1; oc = style->outlinecolor ? style->outlinecolor->pen : -1; if(oc==-1 && fc ==-1) { return MS_SUCCESS; } if (style->rotation != 0.0) { bRotated = MS_TRUE; symbol = rotateVectorSymbolPoints(symbol, style->rotation); if(!symbol) { return MS_FAILURE; } } /* We avoid MS_NINT in this context because the potentially variable handling of 0.5 rounding is often a problem for symbols which are often an odd size (ie. 7pixels) and so if "p" is integral the value is always on a 0.5 boundary - bug 1716 */ x -= style->scale*.5*symbol->sizex; y -= style->scale*.5*symbol->sizey; if(symbol->filled) { /* if filled */ k = 0; /* point counter */ for(j=0; j < symbol->numpoints; j++) { if((symbol->points[j].x == -99) && (symbol->points[j].x == -99)) { /* new polygon (PENUP) */ if(k>2) { if(fc >= 0) gdImageFilledPolygon(ip, mPoints, k, fc); if(oc >= 0) gdImagePolygon(ip, mPoints, k, oc); } k = 0; /* reset point counter */ } else { mPoints[k].x = MS_NINT(style->scale*symbol->points[j].x + x); mPoints[k].y = MS_NINT(style->scale*symbol->points[j].y + y); k++; } } if(fc >= 0) gdImageFilledPolygon(ip, mPoints, k, fc); if(oc >= 0) gdImagePolygon(ip, mPoints, k, oc); } else { /* NOT filled */ if(oc >= 0) fc = oc; /* try the outline color (reference maps sometimes do this when combining a box and a custom vector marker */ oldpnt.x = MS_NINT(style->scale*symbol->points[0].x + x); /* convert first point in marker */ oldpnt.y = MS_NINT(style->scale*symbol->points[0].y + y); gdImageSetThickness(ip, style->outlinewidth); for(j=1; j < symbol->numpoints; j++) { /* step through the marker */ if((symbol->points[j].x != -99) || (symbol->points[j].x != -99)) { if((symbol->points[j-1].x == -99) && (symbol->points[j-1].y == -99)) { /* Last point was PENUP, now a new beginning */ oldpnt.x = MS_NINT(style->scale*symbol->points[j].x + x); oldpnt.y = MS_NINT(style->scale*symbol->points[j].y + y); } else { newpnt.x = MS_NINT(style->scale*symbol->points[j].x + x); newpnt.y = MS_NINT(style->scale*symbol->points[j].y + y); gdImageLine(ip, oldpnt.x, oldpnt.y, newpnt.x, newpnt.y, fc); oldpnt = newpnt; } } } /* end for loop */ gdImageSetThickness(ip, 1); /* restore thinkness */ } /* end if-then-else */ if(bRotated) { msFreeSymbol(symbol); /* clean up */ msFree(symbol); } return MS_SUCCESS; } int renderTruetypeSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *s) { #ifdef USE_GD_FREETYPE int bbox[8]; char *error; int c,oc = 0; gdImagePtr ip; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; SETPEN(ip, s->color); SETPEN(ip, s->outlinecolor); if(s->style->antialias) { c = s->color->pen; if(s->outlinecolor) oc = s->outlinecolor->pen; } else { c = -s->color->pen; if(s->outlinecolor) oc = -s->outlinecolor->pen; } gdImageStringFT(NULL, bbox, c, symbol->full_font_path, s->scale, s->rotation, 0,0, symbol->character); x -= (bbox[2] - bbox[0])/2 + bbox[0]; y += (bbox[1] - bbox[5])/2 - bbox[1]; if( s->outlinecolor ) { error = gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x, y-1, symbol->character); if(error) { msSetError(MS_TTFERR, "%s", "renderTruetypeSymbolGD()", error); return MS_FAILURE; } gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x, y+1, symbol->character); gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x+1, y, symbol->character); gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x-1, y, symbol->character); gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x+1, y+1, symbol->character); gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x+1, y-1, symbol->character); gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x-1, y+1, symbol->character); gdImageStringFT(ip, bbox, oc, symbol->full_font_path, s->scale, s->rotation, x-1, y-1, symbol->character); } if(s->color) gdImageStringFT(ip, bbox, c, symbol->full_font_path, s->scale, s->rotation, x, y, symbol->character); return MS_SUCCESS; #else msSetError(MS_TTFERR, "Freetype support not enabled in this GD build", "renderTruetypeSymbolGD()"); return MS_FAILURE; #endif } gdImagePtr rotatePixmapGD(gdImagePtr img, double angle_rad) { gdImagePtr rimg = NULL; double cos_a, sin_a; double x1 = 0.0, y1 = 0.0; /* destination rectangle */ double x2 = 0.0, y2 = 0.0; double x3 = 0.0, y3 = 0.0; double x4 = 0.0, y4 = 0.0; long minx, miny, maxx, maxy; int width=0, height=0; /* int color; */ sin_a = sin(angle_rad); cos_a = cos(angle_rad); /* compute distination rectangle (x1,y1 is known) */ x1 = 0 ; y1 = 0 ; x2 = img->sy * sin_a; y2 = -img->sy * cos_a; x3 = (img->sx * cos_a) + (img->sy * sin_a); y3 = (img->sx * sin_a) - (img->sy * cos_a); x4 = (img->sx * cos_a); y4 = (img->sx * sin_a); minx = (long) MS_MIN(x1,MS_MIN(x2,MS_MIN(x3,x4))); miny = (long) MS_MIN(y1,MS_MIN(y2,MS_MIN(y3,y4))); maxx = (long) MS_MAX(x1,MS_MAX(x2,MS_MAX(x3,x4))); maxy = (long) MS_MAX(y1,MS_MAX(y2,MS_MAX(y3,y4))); width = (int)ceil(maxx-minx); height = (int)ceil(maxy-miny); /* create the new image based on the computed width/height */ if (gdImageTrueColor(img)) { rimg = gdImageCreateTrueColor(width, height); gdImageAlphaBlending(rimg, 0); gdImageFilledRectangle(rimg, 0, 0, width, height, gdImageColorAllocateAlpha(rimg, 0, 0, 0, gdAlphaTransparent)); } else { int tc = gdImageGetTransparent(img); rimg = gdImageCreate(width, height); if(tc != -1) gdImageColorTransparent(rimg, gdImageColorAllocate(rimg, gdImageRed(img, tc), gdImageGreen(img, tc), gdImageBlue(img, tc))); } if(!rimg) { msSetError(MS_GDERR,"failed to create rotated pixmap","rotatePixmapGD()"); return NULL; } gdImageCopyRotated (rimg, img, width*0.5, height*0.5, 0, 0, gdImageSX(img), gdImageSY(img), angle_rad*MS_RAD_TO_DEG); return rimg; } int renderPixmapSymbolGD(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { gdImagePtr ip,pp; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; assert(symbol->pixmap_buffer && symbol->pixmap_buffer->type == MS_BUFFER_GD); pp = symbol->pixmap_buffer->data.gd_img; /* gdImageAlphaBlending(ip,1); */ /* gdImageAlphaBlending(pp,1); */ if(symbol->transparent) gdImageColorTransparent(pp,symbol->transparentcolor); if(style->scale == 1.0 && style->rotation == 0.0) { /* don't scale */ x -= .5*symbol->pixmap_buffer->width; y -= .5*symbol->pixmap_buffer->height; gdImageCopy(ip, pp, x, y, 0, 0, symbol->pixmap_buffer->width,symbol->pixmap_buffer->height); } else { int bRotated = MS_FALSE; if(style->rotation) { bRotated = MS_TRUE; pp = rotatePixmapGD(pp,style->rotation); } x -= .5*gdImageSX(pp)*style->scale; y -= .5*gdImageSY(pp)*style->scale; gdImageCopyResampled(ip, pp, x, y, 0, 0, (int)(gdImageSX(pp) * style->scale), (int)(gdImageSY(pp) * style->scale), gdImageSX(pp),gdImageSY(pp)); if(bRotated) { gdImageDestroy(pp); } } /* gdImageAlphaBlending(ip,0); */ return MS_SUCCESS; } int renderTileGD(imageObj *img, imageObj *tile, double x, double y) { return MS_SUCCESS; } int renderPolygonTiledGD(imageObj *img, shapeObj *p, imageObj *tile) { gdImagePtr ip, tp; if(!img || !p || !tile) return MS_FAILURE; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; if(!(tp = MS_IMAGE_GET_GDIMAGEPTR(tile))) return MS_FAILURE; gdImageColorTransparent(tp,0); gdImageSetTile(ip, tp); imageFilledPolygon(ip, p, gdTiled); return MS_SUCCESS; } int initializeRasterBufferGD(rasterBufferObj *rb, int width, int height, int mode) { rb->type = MS_BUFFER_GD; rb->data.gd_img = gdImageCreate(width, height); if(!rb->data.gd_img) return MS_FAILURE; rb->width = width; rb->height= height; return MS_SUCCESS; } /* ** GD driver-specific raster buffer functions. */ int getRasterBufferHandleGD(imageObj *img, rasterBufferObj *rb) { gdImagePtr gdImg = MS_IMAGE_GET_GDIMAGEPTR(img); rb->type = MS_BUFFER_GD; rb->data.gd_img = gdImg; rb->width = gdImg->sx; rb->height = gdImg->sy; return MS_SUCCESS; } int getRasterBufferCopyGD(imageObj *img, rasterBufferObj *rb) { gdImagePtr gdImg = MS_IMAGE_GET_GDIMAGEPTR(img); int row; rb->type = MS_BUFFER_GD; rb->width = gdImg->sx; rb->height = gdImg->sy; rb->data.gd_img = gdImageCreate(gdImg->sx,gdImg->sy); rb->data.gd_img->transparent = gdImg->transparent; gdImagePaletteCopy(rb->data.gd_img,gdImg); for(row=0; rowsy; row++) memcpy(rb->data.gd_img->pixels[row],gdImg->pixels[row],gdImg->sx); return MS_SUCCESS; } int mergeRasterBufferGD(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { assert(dest && overlay); assert(overlay->type == MS_BUFFER_GD); gdImageCopyMerge(MS_IMAGE_GET_GDIMAGEPTR(dest),overlay->data.gd_img,dstX,dstY,srcX,srcY,width,height,opacity*100); return MS_SUCCESS; } int getTruetypeTextBBoxGD(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline) { #ifdef USE_GD_FREETYPE int bbox[8]; char *error; if(advances) { char *s; int k; gdFTStringExtra strex; strex.flags = gdFTEX_XSHOW; error = gdImageStringFTEx(NULL, bbox, 0, fonts[0], size, 0, 0, 0, string, &strex); if(error) { msSetError(MS_TTFERR, "%s", "gdImageStringFTEx()", error); return(MS_FAILURE); } *advances = (double*)malloc( strlen(string) * sizeof(double) ); MS_CHECK_ALLOC(*advances, strlen(string) * sizeof(double), MS_FAILURE); s = strex.xshow; k = 0; /* TODO this smells buggy and can cause errors at a higher level. strlen NOK here*/ while ( *s && k < strlen(string) ) { (*advances)[k++] = atof(s); while ( *s && *s != ' ') s++; if ( *s == ' ' ) s++; } gdFree(strex.xshow); /* done with character advances */ rect->minx = bbox[0]; rect->miny = bbox[5]; rect->maxx = bbox[2]; rect->maxy = bbox[1]; return MS_SUCCESS; } else { error = gdImageStringFT(NULL, bbox, 0, fonts[0], size, 0, 0, 0, string); if(error) { msSetError(MS_TTFERR, "%s", "msGetTruetypeTextBBoxGD()", error); return(MS_FAILURE); } rect->minx = bbox[0]; rect->miny = bbox[5]; rect->maxx = bbox[2]; rect->maxy = bbox[1]; return MS_SUCCESS; } #else msSetError(MS_TTFERR, "Freetype support not enabled in this GD build", "getTruetypeTextBBoxGD()"); return MS_FAILURE; #endif } int renderBitmapGlyphsGD(imageObj *img, double x, double y, labelStyleObj *style, char *text) { int size = MS_NINT(style->size); gdFontPtr fontPtr; gdImagePtr ip; int numlines=0,t; char **lines; if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE; if(size<0 || size>4 || (fontPtr = msGetBitmapFont(size))==NULL) { msSetError(MS_RENDERERERR,"invalid bitmap font size", "renderBitmapGlyphsGD()"); return MS_FAILURE; } SETPEN(ip, style->color); SETPEN(ip, style->outlinecolor); if(msCountChars(text,'\n')) { if((lines = msStringSplit((const char*)text, '\n', &(numlines))) == NULL) return(-1); } else { lines = &text; numlines = 1; } y -= fontPtr->h; for(t=0; toutlinewidth > 0) { gdImageString(ip, fontPtr, x, y-1, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x, y+1, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x+1, y, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x-1, y, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x+1, y-1, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x+1, y+1, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x-1, y-1, (unsigned char *) lines[t], style->outlinecolor->pen); gdImageString(ip, fontPtr, x-1, y+1, (unsigned char *) lines[t], style->outlinecolor->pen); } if(style->color->pen != -1) { gdImageString(ip, fontPtr, x, y, (unsigned char *) lines[t], style->color->pen); } y += fontPtr->h; /* shift down */ } if(*lines != text) msFreeCharArray(lines, numlines); return MS_SUCCESS; } /* ** Misc. cleanup functions for GD driver. */ int freeSymbolGD(symbolObj *s) { return MS_SUCCESS; } int msPopulateRendererVTableGD( rendererVTableObj *renderer ) { int i; renderer->use_imagecache=0; renderer->supports_pixel_buffer=1; renderer->supports_transparent_layers = 0; renderer->supports_bitmap_fonts = 1; renderer->default_transform_mode = MS_TRANSFORM_ROUND; for(i=0; i<5; i++) { gdFontPtr f = msGetBitmapFont(i); bitmapFontMetricsGD[i].charWidth = f->w; bitmapFontMetricsGD[i].charHeight = f->h; renderer->bitmapFontMetrics[i] = &bitmapFontMetricsGD[i]; } renderer->startLayer = startNewLayerGD; renderer->endLayer = closeNewLayerGD; renderer->renderLineTiled = NULL; renderer->renderLine = &renderLineGD; renderer->createImage = &createImageGD; renderer->saveImage = &saveImageGD; renderer->getRasterBufferHandle = &getRasterBufferHandleGD; renderer->getRasterBufferCopy = &getRasterBufferCopyGD; renderer->initializeRasterBuffer = initializeRasterBufferGD; renderer->loadImageFromFile = msLoadGDRasterBufferFromFile; renderer->renderPolygon = &renderPolygonGD; renderer->renderGlyphs = &renderGlyphsGD; renderer->renderBitmapGlyphs = &renderBitmapGlyphsGD; renderer->freeImage = &freeImageGD; renderer->renderEllipseSymbol = &renderEllipseSymbolGD; renderer->renderVectorSymbol = &renderVectorSymbolGD; renderer->renderTruetypeSymbol = &renderTruetypeSymbolGD; renderer->renderPixmapSymbol = &renderPixmapSymbolGD; renderer->mergeRasterBuffer = &mergeRasterBufferGD; renderer->getTruetypeTextBBox = &getTruetypeTextBBoxGD; renderer->renderTile = &renderTileGD; renderer->renderPolygonTiled = &renderPolygonTiledGD; renderer->freeSymbol = &freeSymbolGD; return MS_SUCCESS; } #endif mapserver-6.4.1/sortshp.c0000644002461700001440000002043112261257215015162 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Command line utility to sort a shapefile based on a single * attribute in ascending or decending order. Useful for * prioritizing drawing or labeling of shapes. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include #include #include #include "mapserver.h" typedef struct { double number; char string[255]; int index; } sortStruct; static int compare_string_descending(const void *a, const void *b) { const sortStruct *i = a, *j = b; return(strcmp(j->string, i->string)); } static int compare_string_ascending(const void *a, const void *b) { const sortStruct *i = a, *j = b; return(strcmp(i->string, j->string)); } static int compare_number_descending(const void *a, const void *b) { const sortStruct *i = a, *j = b; if(i->number > j->number) return(-1); if(i->number < j->number) return(1); return(0); } static int compare_number_ascending(const void *a, const void *b) { const sortStruct *i = a, *j = b; if(i->number > j->number) return(1); if(i->number < j->number) return(-1); return(0); } int main(int argc, char *argv[]) { SHPHandle inSHP,outSHP; /* ---- Shapefile file pointers ---- */ DBFHandle inDBF,outDBF; /* ---- DBF file pointers ---- */ sortStruct *array; shapeObj shape; int shpType, nShapes; int fieldNumber=-1; /* ---- Field number of item to be sorted on ---- */ DBFFieldType dbfField; char fName[20]; int fWidth,fnDecimals; char buffer[1024]; int i,j; int num_fields, num_records; if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } /* ------------------------------------------------------------------------------- */ /* Check the number of arguments, return syntax if not correct */ /* ------------------------------------------------------------------------------- */ if( argc != 5 ) { fprintf(stderr,"Syntax: sortshp [infile] [outfile] [item] [ascending|descending]\n" ); exit(1); } msSetErrorFile("stderr", NULL); /* ------------------------------------------------------------------------------- */ /* Open the shapefile */ /* ------------------------------------------------------------------------------- */ inSHP = msSHPOpen(argv[1], "rb" ); if( !inSHP ) { fprintf(stderr,"Unable to open %s shapefile.\n",argv[1]); exit(1); } msSHPGetInfo(inSHP, &nShapes, &shpType); /* ------------------------------------------------------------------------------- */ /* Open the dbf file */ /* ------------------------------------------------------------------------------- */ snprintf(buffer, sizeof(buffer), "%s.dbf",argv[1]); inDBF = msDBFOpen(buffer,"rb"); if( inDBF == NULL ) { fprintf(stderr,"Unable to open %s XBASE file.\n",buffer); exit(1); } num_fields = msDBFGetFieldCount(inDBF); num_records = msDBFGetRecordCount(inDBF); for(i=0; irefcount); */ if(MS_REFCNT_DECR_IS_NOT_ZERO(map)) { return; } if(map->debug >= MS_DEBUGLEVEL_VV) msDebug("msFreeMap(): freeing map at %p.\n",map); msCloseConnections(map); msFree(map->name); msFree(map->shapepath); msFree(map->mappath); msFreeProjection(&(map->projection)); msFreeProjection(&(map->latlon)); msFreeLabelCache(&(map->labelcache)); msFree(map->imagetype); msFreeFontSet(&(map->fontset)); msFreeSymbolSet(&map->symbolset); /* free symbols */ msFree(map->symbolset.filename); freeWeb(&(map->web)); freeScalebar(&(map->scalebar)); freeReferenceMap(&(map->reference)); freeLegend(&(map->legend)); for(i=0; imaxlayers; i++) { if(GET_LAYER(map, i) != NULL) { GET_LAYER(map, i)->map = NULL; if(freeLayer((GET_LAYER(map, i))) == MS_SUCCESS) free(GET_LAYER(map, i)); } } msFree(map->layers); if(map->layerorder) free(map->layerorder); msFree(map->templatepattern); msFree(map->datapattern); msFreeHashItems(&(map->configoptions)); if(map->outputformat && map->outputformat->refcount > 0 && --map->outputformat->refcount < 1) msFreeOutputFormat(map->outputformat); for(i=0; inumoutputformats; i++ ) { if(map->outputformatlist[i]->refcount > 0 && --map->outputformatlist[i]->refcount < 1) msFreeOutputFormat(map->outputformatlist[i]); } if(map->outputformatlist != NULL) msFree(map->outputformatlist); msFreeQuery(&(map->query)); msFree(map); } /************************************************************************/ /* msGetConfigOption() */ /************************************************************************/ const char *msGetConfigOption( mapObj *map, const char *key) { return msLookupHashTable( &(map->configoptions), key ); } /************************************************************************/ /* msSetConfigOption() */ /************************************************************************/ int msSetConfigOption( mapObj *map, const char *key, const char *value) { /* We have special "early" handling of this so that it will be */ /* in effect when the projection blocks are parsed and pj_init is called. */ if( strcasecmp(key,"PROJ_LIB") == 0 ) { /* value may be relative to map path */ msSetPROJ_LIB( value, map->mappath ); } /* Same for MS_ERRORFILE, we want it to kick in as early as possible * to catch parsing errors. * Value can be relative to mapfile, unless it's already absolute */ if( strcasecmp(key,"MS_ERRORFILE") == 0 ) { if (msSetErrorFile( value, map->mappath ) != MS_SUCCESS) return MS_FAILURE; } if( msLookupHashTable( &(map->configoptions), key ) != NULL ) msRemoveHashTable( &(map->configoptions), key ); msInsertHashTable( &(map->configoptions), key, value ); return MS_SUCCESS; } /************************************************************************/ /* msTestConfigOption() */ /************************************************************************/ int msTestConfigOption( mapObj *map, const char *key, int default_result ) { const char *result = msGetConfigOption( map, key ); if( result == NULL ) return default_result; if( strcasecmp(result,"YES") == 0 || strcasecmp(result,"ON") == 0 || strcasecmp(result,"TRUE") == 0 ) return MS_TRUE; else return MS_FALSE; } /************************************************************************/ /* msApplyMapConfigOptions() */ /************************************************************************/ void msApplyMapConfigOptions( mapObj *map ) { const char *key; for( key = msFirstKeyFromHashTable( &(map->configoptions) ); key != NULL; key = msNextKeyFromHashTable( &(map->configoptions), key ) ) { const char *value = msLookupHashTable( &(map->configoptions), key ); if( strcasecmp(key,"PROJ_LIB") == 0 ) { msSetPROJ_LIB( value, map->mappath ); } else if( strcasecmp(key,"MS_ERRORFILE") == 0 ) { msSetErrorFile( value, map->mappath ); } else { #if defined(USE_GDAL) && GDAL_RELEASE_DATE > 20030601 CPLSetConfigOption( key, value ); #endif } } } /************************************************************************/ /* msMapIgnoreMissingData() */ /************************************************************************/ int msMapIgnoreMissingData( mapObj *map ) { const char *result = msGetConfigOption( map, "ON_MISSING_DATA" ); const int default_result = #ifndef IGNORE_MISSING_DATA MS_MISSING_DATA_FAIL; #else MS_MISSING_DATA_LOG; #endif if( result == NULL ) return default_result; if( strcasecmp(result,"FAIL") == 0 ) return MS_MISSING_DATA_FAIL; else if( strcasecmp(result,"LOG") == 0 ) return MS_MISSING_DATA_LOG; else if( strcasecmp(result,"IGNORE") == 0 ) return MS_MISSING_DATA_IGNORE; return default_result; } /************************************************************************/ /* msMapSetExtent() */ /************************************************************************/ int msMapSetExtent( mapObj *map, double minx, double miny, double maxx, double maxy) { map->extent.minx = minx; map->extent.miny = miny; map->extent.maxx = maxx; map->extent.maxy = maxy; if (!MS_VALID_EXTENT(map->extent)) { msSetError(MS_MISCERR, "Given map extent is invalid. Check that it " \ "is in the form: minx, miny, maxx, maxy", "setExtent()"); return MS_FAILURE; } map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); /* if the map size is also set, recompute scale, ignore errors? */ if( map->width != -1 || map->height != -1 ) msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &(map->scaledenom)); return msMapComputeGeotransform( map ); } /************************************************************************/ /* msMapOffsetExtent() */ /************************************************************************/ int msMapOffsetExtent( mapObj *map, double x, double y) { return msMapSetExtent( map, map->extent.minx + x, map->extent.miny + y, map->extent.maxx + x, map->extent.maxy + y); } /************************************************************************/ /* msMapScaleExtent() */ /************************************************************************/ int msMapScaleExtent( mapObj *map, double zoomfactor, double minscaledenom, double maxscaledenom) { double geo_width, geo_height, center_x, center_y, md; if (zoomfactor <= 0.0) { msSetError(MS_MISCERR, "The given zoomfactor is invalid", "msMapScaleExtent()"); } geo_width = map->extent.maxx - map->extent.minx; geo_height = map->extent.maxy - map->extent.miny; center_x = map->extent.minx + geo_width * 0.5; center_y = map->extent.miny + geo_height * 0.5; geo_width *= zoomfactor; if (minscaledenom > 0 || maxscaledenom > 0) { /* ensure we are within the valid scale domain */ md = (map->width-1)/(map->resolution * msInchesPerUnit(map->units, center_y)); if (minscaledenom > 0 && geo_width < minscaledenom * md) geo_width = minscaledenom * md; if (maxscaledenom > 0 && geo_width > maxscaledenom * md) geo_width = maxscaledenom * md; } geo_width *= 0.5; geo_height = geo_width * map->height / map->width; return msMapSetExtent( map, center_x - geo_width, center_y - geo_height, center_x + geo_width, center_y + geo_height); } /************************************************************************/ /* msMapSetCenter() */ /************************************************************************/ int msMapSetCenter( mapObj *map, pointObj *center) { return msMapOffsetExtent(map, center->x - (map->extent.minx + map->extent.maxx) * 0.5, center->y - (map->extent.miny + map->extent.maxy) * 0.5); } /************************************************************************/ /* msMapSetRotation() */ /************************************************************************/ int msMapSetRotation( mapObj *map, double rotation_angle ) { map->gt.rotation_angle = rotation_angle; if( map->gt.rotation_angle != 0.0 ) map->gt.need_geotransform = MS_TRUE; else map->gt.need_geotransform = MS_FALSE; return msMapComputeGeotransform( map ); } /************************************************************************/ /* msMapSetSize() */ /************************************************************************/ int msMapSetSize( mapObj *map, int width, int height ) { map->width = width; map->height = height; return msMapComputeGeotransform( map ); /* like SetRotation -- sean */ } /************************************************************************/ /* msMapComputeGeotransform() */ /************************************************************************/ extern int InvGeoTransform( double *gt_in, double *gt_out ); int msMapComputeGeotransform( mapObj * map ) { double rot_angle; double geo_width, geo_height, center_x, center_y; map->saved_extent = map->extent; /* Do we have all required parameters? */ if( map->extent.minx == map->extent.maxx || map->width == 0 || map->height == 0 ) return MS_FAILURE; rot_angle = map->gt.rotation_angle * MS_PI / 180.0; geo_width = map->extent.maxx - map->extent.minx; geo_height = map->extent.maxy - map->extent.miny; center_x = map->extent.minx + geo_width*0.5; center_y = map->extent.miny + geo_height*0.5; /* ** Per bug 1916 we have to adjust for the fact that map extents ** are based on the center of the edge pixels, not the outer ** edges as is expected in a geotransform. */ map->gt.geotransform[1] = cos(rot_angle) * geo_width / (map->width-1); map->gt.geotransform[2] = sin(rot_angle) * geo_height / (map->height-1); map->gt.geotransform[0] = center_x - (map->width * 0.5) * map->gt.geotransform[1] - (map->height * 0.5) * map->gt.geotransform[2]; map->gt.geotransform[4] = sin(rot_angle) * geo_width / (map->width-1); map->gt.geotransform[5] = - cos(rot_angle) * geo_height / (map->height-1); map->gt.geotransform[3] = center_y - (map->width * 0.5) * map->gt.geotransform[4] - (map->height * 0.5) * map->gt.geotransform[5]; if( InvGeoTransform( map->gt.geotransform, map->gt.invgeotransform ) ) return MS_SUCCESS; else return MS_FAILURE; } /************************************************************************/ /* msMapPixelToGeoref() */ /************************************************************************/ void msMapPixelToGeoref( mapObj *map, double *x, double *y ) { msSetError(MS_MISCERR, NULL, "msMapPixelToGeoref() not yet implemented"); } /************************************************************************/ /* msMapGeorefToPixel() */ /************************************************************************/ void msMapGeorefToPixel( mapObj *map, double *x, double *y ) { msSetError(MS_MISCERR, NULL, "msMapGeorefToPixel() not yet implemented"); } /************************************************************************/ /* msMapSetFakedExtent() */ /************************************************************************/ int msMapSetFakedExtent( mapObj *map ) { int i; /* -------------------------------------------------------------------- */ /* Remember the original map extents so we can restore them */ /* later. */ /* -------------------------------------------------------------------- */ map->saved_extent = map->extent; /* -------------------------------------------------------------------- */ /* Set extents such that the bottom left corner is 0,0 and the */ /* top right is width,height. Note this is upside down from */ /* the normal sense of pixel/line coordiantes, but we do this */ /* so that the normal "extent" concept of coordinates */ /* increasing to the right, and up is maintained (like in */ /* georeferenced coordinate systems). */ /* -------------------------------------------------------------------- */ map->extent.minx = 0; map->extent.maxx = map->width; map->extent.miny = 0; map->extent.maxy = map->height; map->cellsize = 1.0; /* -------------------------------------------------------------------- */ /* When we copy the geotransform into the projection object we */ /* have to flip it to account for the preceeding upside-down */ /* coordinate system. */ /* -------------------------------------------------------------------- */ map->projection.gt = map->gt; map->projection.gt.geotransform[0] += map->height * map->gt.geotransform[2]; map->projection.gt.geotransform[3] += map->height * map->gt.geotransform[5]; map->projection.gt.geotransform[2] *= -1; map->projection.gt.geotransform[5] *= -1; for(i=0; inumlayers; i++) GET_LAYER(map, i)->project = MS_TRUE; return InvGeoTransform( map->projection.gt.geotransform, map->projection.gt.invgeotransform ); } /************************************************************************/ /* msMapRestoreRealExtent() */ /************************************************************************/ int msMapRestoreRealExtent( mapObj *map ) { map->projection.gt.need_geotransform = MS_FALSE; map->extent = map->saved_extent; map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); return MS_SUCCESS; } /************************************************************************/ /* msInsertLayer() */ /************************************************************************/ /* Returns the index at which the layer was inserted */ int msInsertLayer(mapObj *map, layerObj *layer, int nIndex) { if (!layer) { msSetError(MS_CHILDERR, "Can't insert a NULL Layer", "msInsertLayer()"); return -1; } /* Ensure there is room for a new layer */ if (map->numlayers == map->maxlayers) { if (msGrowMapLayers(map) == NULL) return -1; } /* msGrowMapLayers allocates the new layer which we don't need to do since we have 1 that we are inserting not sure if it is possible for this to be non null otherwise, but better to check since this function replaces the value */ if (map->layers[map->numlayers]!=NULL) free(map->layers[map->numlayers]); /* Catch attempt to insert past end of layers array */ if (nIndex >= map->numlayers) { msSetError(MS_CHILDERR, "Cannot insert layer beyond index %d", "msInsertLayer()", map->numlayers-1); return -1; } else if (nIndex < 0) { /* Insert at the end by default */ map->layerorder[map->numlayers] = map->numlayers; GET_LAYER(map, map->numlayers) = layer; GET_LAYER(map, map->numlayers)->index = map->numlayers; GET_LAYER(map, map->numlayers)->map = map; MS_REFCNT_INCR(layer); map->numlayers++; return map->numlayers-1; } else if (nIndex >= 0 && nIndex < map->numlayers) { /* Move existing layers at the specified nIndex or greater */ /* to an index one higher */ int i; for (i=map->numlayers; i>nIndex; i--) { GET_LAYER(map, i)=GET_LAYER(map, i-1); GET_LAYER(map, i)->index = i; } /* assign new layer to specified index */ GET_LAYER(map, nIndex)=layer; GET_LAYER(map, nIndex)->index = nIndex; GET_LAYER(map, nIndex)->map = map; /* adjust layers drawing order */ for (i=map->numlayers; i>nIndex; i--) { map->layerorder[i] = map->layerorder[i-1]; if (map->layerorder[i] >= nIndex) map->layerorder[i]++; } for (i=0; ilayerorder[i] >= nIndex) map->layerorder[i]++; } map->layerorder[nIndex] = nIndex; /* increment number of layers and return */ MS_REFCNT_INCR(layer); map->numlayers++; return nIndex; } else { msSetError(MS_CHILDERR, "Invalid index", "msInsertLayer()"); return -1; } } /************************************************************************/ /* msRemoveLayer() */ /************************************************************************/ layerObj *msRemoveLayer(mapObj *map, int nIndex) { int i; int order_index; layerObj *layer; if (nIndex < 0 || nIndex >= map->numlayers) { msSetError(MS_CHILDERR, "Cannot remove Layer, invalid index %d", "msRemoveLayer()", nIndex); return NULL; } else { layer=GET_LAYER(map, nIndex); /* msCopyLayer(layer, (GET_LAYER(map, nIndex))); */ /* Iteratively copy the higher index layers down one index */ for (i=nIndex; inumlayers-1; i++) { /* freeLayer((GET_LAYER(map, i))); */ /* initLayer((GET_LAYER(map, i)), map); */ /* msCopyLayer(GET_LAYER(map, i), GET_LAYER(map, i+1)); */ GET_LAYER(map, i)=GET_LAYER(map, i+1); GET_LAYER(map, i)->index = i; } /* Free the extra layer at the end */ /* freeLayer((GET_LAYER(map, map->numlayers-1))); */ GET_LAYER(map, map->numlayers-1)=NULL; /* Adjust drawing order */ order_index = 0; for (i=0; inumlayers; i++) { if (map->layerorder[i] > nIndex) map->layerorder[i]--; if (map->layerorder[i] == nIndex) { order_index = i; break; } } for (i=order_index; inumlayers-1; i++) { map->layerorder[i] = map->layerorder[i+1]; if (map->layerorder[i] > nIndex) map->layerorder[i]--; } /* decrement number of layers and return copy of removed layer */ map->numlayers--; layer->map=NULL; MS_REFCNT_DECR(layer); return layer; } } /* ** Move the layer's order for drawing purpose. Moving it up here ** will have the effect of drawing the layer earlier. */ int msMoveLayerUp(mapObj *map, int nLayerIndex) { int iCurrentIndex = -1; int i = 0; if (map && nLayerIndex < map->numlayers && nLayerIndex >=0) { for (i=0; inumlayers; i++) { if ( map->layerorder[i] == nLayerIndex) { iCurrentIndex = i; break; } } if (iCurrentIndex >=0) { /* we do not need to promote if it is the first one. */ if (iCurrentIndex == 0) return MS_FAILURE; map->layerorder[iCurrentIndex] = map->layerorder[iCurrentIndex-1]; map->layerorder[iCurrentIndex-1] = nLayerIndex; return MS_SUCCESS; } } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLayerUp()", nLayerIndex); return MS_FAILURE; } /* ** Move the layer's order for drawing purpose. Moving it down here ** will have the effect of drawing the layer later. */ int msMoveLayerDown(mapObj *map, int nLayerIndex) { int iCurrentIndex = -1; int i = 0; if (map && nLayerIndex < map->numlayers && nLayerIndex >=0) { for (i=0; inumlayers; i++) { if ( map->layerorder[i] == nLayerIndex) { iCurrentIndex = i; break; } } if (iCurrentIndex >=0) { /* we do not need to demote if it is the last one. */ if (iCurrentIndex == map->numlayers-1) return MS_FAILURE; map->layerorder[iCurrentIndex] = map->layerorder[iCurrentIndex+1]; map->layerorder[iCurrentIndex+1] = nLayerIndex; return MS_SUCCESS; } } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLayerDown()", nLayerIndex); return MS_FAILURE; } /* ** Set the array used for the drawing order. The array passed must contain ** all the layer's index ordered by the drawing priority. ** Ex : for 3 layers in the map file, if ** panIndexes[0] = 2 ** panIndexes[1] = 0 ** panIndexes[2] = 1 ** will set the darwing order to layer 2, layer 0, ** and then layer 1. ** ** Note : It is assumed that the index panIndexes has the same number of ** of elements as the number of layers in the map. ** Return TRUE on success else FALSE. */ int msSetLayersdrawingOrder(mapObj *self, int *panIndexes) { int nElements = 0; int i, j = 0; int bFound = 0; if (self && panIndexes) { nElements = self->numlayers; for (i=0; ilayerorder[i] = panIndexes[i]; } return 1; } return 0; } /* ========================================================================= msMapLoadOWSParameters Function to support mapscript mapObj::loadOWSParameters ========================================================================= */ int msMapLoadOWSParameters(mapObj *map, cgiRequestObj *request, const char *wmtver) { #ifdef USE_WMS_SVR int version; char *wms_exception_format = NULL; const char *wms_request= NULL; int result, i = 0; owsRequestObj ows_request; ows_request.numlayers = 0; ows_request.enabled_layers = NULL; version = msOWSParseVersionString(wmtver); for(i=0; iNumParams; i++) { if (strcasecmp(request->ParamNames[i], "EXCEPTIONS") == 0) wms_exception_format = request->ParamValues[i]; else if (strcasecmp(request->ParamNames[i], "REQUEST") == 0) wms_request = request->ParamValues[i]; } msOWSRequestLayersEnabled(map, "M", wms_request, &ows_request); result = msWMSLoadGetMapParams(map, version, request->ParamNames, request->ParamValues, request->NumParams, wms_exception_format, wms_request, &ows_request); if (ows_request.numlayers > 0) msFree(ows_request.enabled_layers); return result; #else msSetError(MS_WMSERR, "WMS server support is not available.", "msMapLoadOWSParameters()"); return MS_FAILURE; #endif } mapserver-6.4.1/HISTORY.TXT0000644002461700001440000045071712261257215015074 0ustar tbonfortusers MapServer Revision History ========================== $Id$ This is a human-readable revision history which will attempt to document required changes for users to migrate from one version of MapServer to the next. Developers are strongly encouraged to document their changes and their impacts on the users here. (Please add the most recent changes to the top of the list.) For a complete change history, please see the Git log comments. 6.4 release (2013/09/xx) --------------------------- - RFC 101: Support for Content Dependant Legend Rendering - Add Support for librsvg as an alternative to libsvg-cairo - RFC100: Add support for raster tile index with tiles of mixed SRS (TILESRS keyword) - RFC94: Shape Smoothing - RFC95 : add EXPRESSION {value1,value2,...} support to parser (#4648) - RFC92: Migration from autotools to cmake (#4617) - RFC88: Saving MapServer Objects to Strings (#4563) - RFC90: Enable/Disable Layers in OGC Web Services by IP Lists - RFC85,89 Added Simplify,SimplityPT and Generalize geomtransform, implementation of geomtransform at the layer level - RFC86: Scale-dependant token replacements (#4538) - Fix symbol scaling for vector symbols with no height (#4497,#3511) - Implementation of layer masking for WCS coverages (#4469) - Implementation of offsets on follow labels (#4399) 6.2.0 release (git branch-6-2) 2012/11/14: -------------------------------------------------- - Fix WFS GetFeature result bounds are not written in requested projection (#4494) - Fixed wrong size in LegendURL of root layer (#4441) - Fixed wms_style_name in GetMap requests (#4439) - Fix segfault in queryByFilter function in MapScript - Adjusted WCS 2.0 to WCS Core 2.0.1 and GMLCOV 1.0.1 corrigenda (#4003) - Adjusted mediatype to multipart/related in WCS 2.0 (#4003) - Fix symbolObj.getImage seg fault in PHP/MapScript - Fix bad handling of startindex in some drivers (#4011) WFSGetFeature also now uses a global maxfeatures and startindex to support maxfeatures across layers rather than within layers - Fixed bugs with WCS 1.1/2.0 with VSIMEM (#4369) - Add notable changes here. Less important changes should go only in the commit message and not appear here. - Fixed the OGR driver to use point or line spatial filter geometries in degenerated cases (#4420) - implement OFFSET x -99 on ANGLE FOLLOW labels (#4399) Version 6.2 (beta1: 20120629): ------------------------------------------------- - Fix WFS filter is produced as non-standard XML (#4171) - Fix pixmap symbol loading issue (#4329) - Added INSPIRE ExtendedCapabilities and DOCTYPE definition to WMS 1.1.1 (#3608) - Fix wms_enable_request-related errors are not properly tagged (#4187) - Fixed "msGetMarkerSize() called on unloaded pixmap symbol" in mapsymbol.c (#4225) - Fixed PHP MapScript support for PHP 5.4 (#4309) - Fix msOGREscapeSQLParam could return random data (#4335) - Fixed locations of supported and native formats in Capabilities and CoverageDescriptions for WCS 2.0 (#4003) - Made format parameter for WCS 2.0 GetCoverage requests optional (#4003) - Swig mapscript for multi-label support (#4310) - Fix creation of a vector symbolObj in mapscript (#4318) - Added coverage metadata in WCS (#4306) - Ignore unknown requets parameteres in WCS 2.0 (#4307). - Fixed getFeature request with custom output format fails on filter encoding (#4190) - Fixed resolution when UoM changes in WCS 2.0 (#4283) - Added missing DEFRESOLUTION parameter to msCopyMap() function (#4272) - Migrated svn to git, and issue tracking from trac to github - Fixed mapscript is unusable in a web application due to memory leaks (#4262) - Fixed legend image problem with annotation layers with label offsets (#4147) - Add support for mutiple labels per feature (RFC81) - Add support for INSPIRE view service (RFC 75) - Drop support for GDAL/OGR older than 1.5.0 (#4224) - PDF backend: add support for generating geospatial PDF, when GDAL 2.0 with PDF driver is used, and the GEO_ENCODING FORMATOPTION (set to ISO32000 or OGC_BP) is added to the OUTPUTFORMAT definition. (#4216) - Python mapscript: fix swig mappings to work with both python 2.5.and 2.6 (#3940) - Added classgroup CGI parameter support (#4207) - Java mapscript: renamed shared library and completed libtool support (#2595) - Fixed WCS 2.0 axis order (#4191) - Added MS_CJC_* constants in PHP/MapScript (#4183) - Fixed Memory Leak with Fribidi Strings (#4188) - Allow multiple label definitions within a class (RFC 77/#4127) - shp2img: make it possible to specify layers (with -l option) that match GROUP names. - reuse a pre-parsed mapfile across fastcgi loops in case the mapfile is specified with the MS_MAPFILE env variable. (#4018) - Ability to do use PropertyIsLike with a column of a different type than text (postgis) (#4176) - Fixed SLD with FILTER doesn't apply properly to database layers (#4112) - Fixed lexer buffer size issue with single quotes in a string (#4175) - WFS Quote Escape issue (#4087) - Raster layer fails to be drawn if the window is less than half a pixel (#4172) - shptree: Improvement to reduce size of .qix files (#4169) - avoid potential gd fontcache deadlock on fastcgi exit signals(#4093) - Adjusted WCS GetCapabilities for an empty list of layers (#4140) - Adjusted WMS GetCapabilities for an empty list of layers (#3755) - Refactor cgi masperv to not call exit on argument errors (#3099) - Add --with-apache-module configure option to build an apache dso module (#2565) - Use libtool to build object files and libraries - Dynamically link libmapserver to the created binaries by default (requires the make install step to be run) - Python mapscript builds with make instead of setuptools - Fix LABELPNT geomtransform position for non-cached labels (#4121) - Add RFC80 font fallback support (#4114) - Added POLAROFFSET style option for a different symbol transform (#4117) - automatically translate vector symbol points (#4116) - Add RFC79 Layer masking (#4111) - Fixed single pixel coverages in WCS 2.0 (#4110) - Add svg symbols support (#3671) - Fixed subsetting in WCS 2.0 (#4099) - Upgrade clipper library to 4.6.3 - Make openlayers wms template request images with mimetype of outputformat defined in the mapfile's imagetype - Fix memory leak in msSLDParseRasterSymbolizer() - Fix compilation error with clang in renderers/agg/include/agg_renderer_outline_aa.h - Add stable hatch rendering (#3847) - Added vector field rendering (#4094) - Add wms dimensions support (#3466) - Fixed segfault when calling classObj::updateFromString() with SYMBOL (#4062) - Use a renderer native follow text implementation if available. - Fixed layer with inline feature to support multiple classes (#4070) - Add support for rfc45 anchorpoint on marker symbols (#4066) - Add initial gap support for line marker symbols (#3879) - Fix center to center computation of gaps for line marker symbols and polygon tile patterns (#3867) - Add initial gap support for line patterns (#3879) - Fixed grid of thin lines in polygon symbol fills (#3868) - Fixed cannot add a style to a label in PHP/SWIG Mapscript (#4038) - Fixed schema validity issue for WCS 1.1 GetCoverage responses (#4047) - remove default compiler search paths from the GD CFLAGS/LDFLAGS (#4046) - Fixed Python Mapscript does not write COLOR to reference map (#4042) - Added XMP support for metadata embedding, RFC 76, (#3932) - Added GetLegendGraphic Cascading support (#3923) - Rewrite postgres TIME queries to take advantage of indexes (#3374) - Unified OWS requests and applied to WCS (defaults to version 2.0 now) (#3925) - WCS 1.0: Fix crash with some _rangeset_axes values (#4020) - WCS 2.0: Adjusted offset vector and origin (#4006) - Added addParameter() method to MapScript (#3973) - Changed msDrawVectorLayer() not to cache shapes if attribute binding is present after the first style (#3976) - Fix mapscript to build when TRUE macro is not defined (#3926) - Fix mapscript php build issues with MSVC (#4004) - PHP MapScript is missing many styleObj properties (#3901) - PHP/Mapscript: Segmentation fault when getting complex object using PHP 5.2 (#3930) - PHP/Mapscript: Fixed webObj->metadata returns a webObj (#3971) - WCS 1.1: Added check for imageCRS in msOWSCommonBoundingBox() (#3966) - Fixed contains operator in logical expresions (#3974) - WCS 1.0: WCS Exceptions raise mapscript exceptions (#3972) - WMS: LAYERS parameter is optional when sld is given (#1166) - Add runtime substitution for "filename" output format option (#3571) and allow setting defaults in either metadata or validation (preferred) blocks for both layer and output format. - Add non antialiased text rendering for GD (#3896) - Fixed OGC filter using expressions (#3481) - Fix incorrect rendering of GD lines between 1 and 2 pixels wide (#3962) - Add gamma correction to AGG polygon rendering (#3165) - Initialize the scalebar image color to transparent by default (#3957) - Do not divide by zero in io read/write funcs (#4135) IMPORTANT SECURITY FIX: - Fixes to prevent SQL injections through OGC filter encoding (in WMS, WFS and SOS), as well as a potential SQL injection in WMS time support. Your system may be vulnerable if it has MapServer with OGC protocols enabled, with layers connecting to an SQL RDBMS backend, either natively or via OGR (#3903) - Fix performance issue with Oracle and scrollable cursors (#3905) - Fix attribute binding for layer styles (#3941) - Added missing fclose() when writing query files (#3943) - Fix double-free in msAddImageSymbol() when filename is a http resource (#3939) - Fix rendering of lines with outlinewidth set if not on first style (#3935) - Correct SLD with spatial filters bbox and intersects (#3929) - Applied patch for ticket (symbol writing issues) (#3589) - Added WMS GetFeatureInfo Cascading (#3764) - Fixed png lib is not found on multiarch systems (#3921) - Fixed PHP MapScript opacity property of StyleObj no longer works (#3920) - Fixed Using STYLEITEM AUTO, loadExpression fails when the label text contains a space or begins with a double quote (#3481) - Fix for the cluster processing if the shape bounds doesn't overlap with the given extent (#3913) - Add support for dashes on polygon hatches (#3912) - Union layer 3 new processing options added (#3900) - Changed msRemoveStyle to allow removing all styles (#3895) - Fixed mssql2008 to return correct geometries with chart layer type (#3894) - Ensure msLayerSetProcessingKey() supports setting a NULL value to clear a processing key. - Write SYMBOLSET/END tags when saving a symbol file (#3885) - Make java threadtests work again (#3887) - Fix segfault on malformed filters (#3888) - Fixed the query handling problem with the Oracle spatial driver (#3878) - Fixed potential crash with AVERAGE resampling and crazy reprojection (#3886) - Adjusted OperationsMetadata for POST in WCS 2.0 GetCapabilities response - Fix for the warnings in mapunion.c (#3880) - SLD: correct when same layer is used with multiple styles (#1602) - Fixed the build problem in mapunion.c (#3877) - Implement to get all shapes with the clustered layer (#3873) - Union layer: Fixed the crash when styling source layers using attributes (#3870) - Added GEOS difference operator to expression support (#3871) - Improve rangeset item checking so that Bands=1,2,3 is supported with WCS 1.0 (#3919). - Fix GetMapserverUnitUsingProj() for proj=latlong (#3883) - Add support for OGR output of 2.5D geometries (#3906) Version 6.0.0 (2011-05-11) -------------------------- - apply fix for #3834 on legend icon rendering (#3866) - Union layer: Fixed a potential seg fault in msUnionLayerNextShape (#3859) - Cluster layer: Fixed the problem when returning undefined attribute (#3700) - Union layer: Fix for the item initialization at the source layer (#3859) - Union layer: Fixed the potential seg fault when STYLEITEM AUTO is used (#3859) Version 6.0.0-rc2 (2011-05-05) ------------------------------ - Fixed seg fault with [shpxy] tag... (#3860) - Removed obsolete msQueryByOperator() function - Call msLayerClose() before msLayerOpen() in the various query functions (#3692) - Fix WMS 1.3.0 to use full list of epsg codes with inverted axis (#3582) - PHP/Mapscript: Added getResultsBounds() method in layer object (#2967) - Fix SLD containing a PropertyIsLike filter (#3855) - Fixed msUnionLayerNextShape to return correct values (#3859) - Union layer: fix for the failure if one or more of the source layers are not in the current extent (#3858) - Fix memory leak in msResampleGDALToMap() (#3857) - Fix missing initialization of default formats in WCS 1.x. - Fix maxoverlapangle when value is set to 0 (#3856) Version 6.0.0-rc1 (2011-04-27) ------------------------------ - Fix for the styleitem handling with union layer (#3674) - Fixed mindistance label test to check layer indexes. (#3851) - Fixed segmentation fault in PHP/MapScript and improved the php object method calls (#3730) - Fix build issue related to unnecessary use of gdal-config --dep-libs (#3316) Version 6.0.0-beta7 (2011-04-20) -------------------------------- - Union Layer: fix for the STYLEITEM AUTO option (#3674) - Union Layer: Add support for the layer FILTER expressions, add "Union:SourceLayerVisible" predefined attribute (#3674) - fix circle layer drawing for edge case when point1.x==point2.x (#1356) - fix incorrect quantization for images with very large number of colors (#3848) - fix poor performance of polygon hatching (#3846) - upgrade clipper library to 4.2 (related to #3846) - Fix configure output for "WFS Client" (was reporting WMS info, #3842) - KML: latlon bbox for raster layers could end up being wrong for non-square requests (#3840) Version 6.0.0-beta6 (2011-04-13) -------------------------------- - define EQUAL/EQUALN macros if cpl_port.h was not included (#3844) - add configurable PNG/ZLIB compression level (#3841) - SLD: use pixmap size when parameter size is not specified (#2305) - fix memory leaks in mapgraticule.c (#3831) - fix runtime sub validation against web metadata, was using wrong lookup key - clean up the symbolset if we've used an alternate renderer for a layer (#3834,#3616) - fix crash on embeded legend with cairo raster renderer - fix crashes in SVG renderer on polygon symbol fills (#3837) - fix crash/corruptions with raster layers in pdf outputs (#3799) - fix memory leak in msFreeLabelCacheSlot (#3829) - use a circle brush for wide GD lines (#3835) - fix segmentation fault with transparent layers containing symbols (#3834) - fix memory leak on tiled vector polygons - fix segfault with marker symbols on short lines (#3823) - wms_getmap_formatlist causes first defined outputformat to be returned by getmap (#3826) - fix building of mapcluster.c when OGR support is disabled - fix some valgrind found memory leaks (offset symbols, and gd io contexts) - skip marker symbol with no defined SYMBOL (caused some memory leaks with uninitialized vector points) - fix crash in GD lines with floating point dash patterns (#3823) - Check renderer before using it when calculating label size (#3822) - allow palette file path to be relative to mapfile (#2115) - use supplied offset for brushed lines (#3825, #3792) - fix division by 0 error in bar charts for some ill-defined cases (#3218) - add GAP, POSITION and CAPS/JOINS to mapfile writer (#3797) - fix GEOMTRANSFORM rotation orientation for vector symbols (#3802) - GD Driver broken in FastCGI (#3813) - configure: look for libexslt.so under lib64 as well - Coding style and formatting fixes (#3819, #3820, #3821, and more) - More improvements to OpenGL error handling (#3791) - Added WMS GetFeatureInfo RADIUS=bbox vendor-specific option (#3561) Version 6.0.0-beta5 (2011-04-06) -------------------------------- - Fix setting of top-level mapObj member variables in PHP MapScript (#3815) - More robust OpenGL context creation on older video cards and drivers (#3791) - Allow users to set the maximum number of vector features to be drawn (#3739) - Fixed FCGI on Windows problem related to lexer (#3812) - KML: Add ows/kml_exclude_items (#3560) - Removed all refs left to MS_SYMBOL_CARTOLINE (#3798) - Removed GAP, PATTERN, LINECAP/JOIN and POSITION from symbolObj (#3797) - Fixed handling of STYLEITEM AUTO label position codes 10,11,12 (#3806) - Fixed msGEOSGeometry2Shape to handle 'GEOMETRYCOLLECTION EMPTY' as null geometry instead of raising an error (#3811) - Re-added the MYSQL JOIN support. Had been removed with the MYGIS deprecated driver. - Add opacity to legend (#3740) - Updated PHP/MapScript with the new objects properties (#3735) - KML: set layer's projection when it is not defined (#3809) - Updated xml mapfile schema and xsl with the new lexer properties (#3735) - Updated PHP/MapScript for MS RFC 69: clustering. (#3700) - Move allocation of cgiRequestObj paramNames/Values to msAllocCgiObj() (#1888) - Add support for simple aggregates for the cluster layer attributes (#3700) - Improved error reporting in msSaveImage() (#3733) - configure: look for libxslt.so under lib64 as well - added missing ';' before charset in WFS DescribeFeatureType header (#3793) - add brushed line support for agg renderer (#3792) - fix bug with marker symbols along offset line - fix for the cluster layer returning invalid feature count (#3794) - remove some compiler warnings - fix incorrect scaling of hatch symbol spacing (#3773) - fix incorrect background color for INIMAGE exceptions (#3790) Version 6.0.0-beta4 (2011-03-30) -------------------------------- - Fix shp2img's -i flag to honour map level transparent, image quality and interlace settings. - Make sure command-line programs use an exit status other than 0 when an error is encountered. (#3753) - Applied patch to filter unwanted fribidi characters (#3763) - Fixed lexer to set the proper state on URL variable substitutions - Fixed Memory leak in PostGIS driver (#3768) - Fixed PHP/MapScript symbol property setter method - fix memory leak in bar charts - fix some valgrind errors on agg rotated pixmap symbols - WCS 2.0: Adjusted definition of NilValues. - Fixed handling of PROJ_LIB value relative to mapfile path (#3094) - Fixed compilation error with opengl support (#3769) - add support for gml:Box for spatial filters (#3789) - fix query map generation error introduced in beta2 when output format initialized was made as needed. - fix incorrect PATTERN behavior on agg lines (#3787) - report SOS DescribeObservationType in Capabilities (#3777) - Updated lexer to detect time attribute bindings (e.g. `[item]`) in logical expressions - Fixed layer context expressions (REQUIRES/LABELREQUIRES) (#3737) - KML: Output ExtendedData (#3728) - Fixed OWS usage of multiple layers with same name (#3778) - WCS implementation should not lookup wms_* metadata (#3779) - WCS 2.0: Adjusted definition of rangeType. - Fixed OWS GetCapabilities to report only requests/operations that are enabled. - WCS 2.0: Report only bands in the range subset. - OWS requests should be completely blocked by default (#3755) - SLD: check for limit on dash arrays (#3772) - WMS: Apply sld after bbox and srs have been parsed (#3765) Version 6.0.0-beta3 (2011-03-23) -------------------------------- - apply min/max size/width style values to polygon spacing (vaguely related to #3132) - assure that a created tile has a non-zero width and height (#3370) - use png_sig_cmp instead of png_check_sig (#3762) - Rendering: scale style OFFSET and GAP the same way we scale other style attributes. Beforehand, we scaled them proportionaly to the computed width. - KML: fix rounding problem for point feautres (#3767) - KML: update code to reflect output changes. Fix true type symbols. (#3766) - SLD: Text Symbolizer now uses the new expression syntax (#3757) - WFS: correct bbox values for GetFeature with featureid request (#3761) - Mapscript Seg Fault on mapObj->getMetaData (#3738) - Correct double free in msCleanup(). - Initialize default formats in WCS. - Fix csharp Makefile.in (#3758) - Allow run-time subs in class->text (makes sense if you allow it in class->expression). - Fix build problem when --enable-cgi-cl-debug-args is enabled (#2853) Version 6.0.0-beta2 (2011-03-18) -------------------------------- - correct scaling of symbol GAP and PATTERN (#3752) - remove references to SWF/MING - CGI runtime substitution requires a validation pattern (was optional before) (#3522) - add a default png8 outputformat that uses AGG/PNG with quantization - change MS_INIT_COLOR to take alpha as a parameter - stop using style->opacity in rendering code, use alpha from colorObjs. - Fixed big Oracle memory leak when rendering in KML (#3719) - avoid linking in postgres dependencies unnecessarily (#3708) - don't initialize outputformats until they are selected - use "seamless" creation of tiles for polygon fills with vector symbols - Ability to escape single/double quotes inside a string (#3706) - Globally replace msCaseFindSubstring with strcasestr (#3255) - support GROUP layers in shp2img (#3746) - Honour MAXSIZE for WCS 2.0 responses (#3204). - fallback to ows_title for WCS ows:Title of CoverageDescription (#3528) - Added msIO_stripStdoutBufferContentHeaders() to strip off all Content-* headers from a buffer (#3673, #3665). - Added raster classification support for STYLE level OPACITY. - Allow attribute references, that is [itemname], within a TEXT string (#3736) - Fixed segmentation fault when parsing invalid extent arguments in shp2img (#3734) - Make "openlayers mode" work even without OWS support (#3732) - Add a static table to define the axis order for soem epsg codes (#3582) - Add possibility to use KML_NAME_ITEM (#3728) - Fixed mapfile parsing error when a label angle referenced an attribute (e.g. ANGLE [angle]) #3727 - Removed executable flag on some source files (#3726) - Fixed SQL Spatial to be able to use UniqueIdentifier field as unique key (#3722) - Fix PHP Windows build (#3714) - Fixed --with-opengl build issue: Look for OpenGL libs under /usr/lib64 as well (#3724) Version 6.0.0-beta1 (2011-03-09) -------------------------------- - Fixed Core Dump from Format=KML/Z with Oracle Spatial layers (#3713) - Call msPluginFreeVirtualTableFactory from msCleanup (#2164) - Avoid the crash if anglemode 'FOLLOW' is specified with bitmap fonts. (#3379) - Add argument check for processTemplate, processLegendTemplate and processQueryTemplate in the C# bindings (#3699) - Remove shapeObj.line, shapeObj.values, lineObj.point from the SWIG API which are redundant and undocumented. (#3269) - Remove map-oriented query modes (e.g. QUERYMAP). Use qformat parameter instead. (#3712) - Implement single-pass query handling in mssql2008 driver as per RFC 65. - Fixed Sql Server 2008 key column name truncation (#3654) - Added label position binding (#3612) and label shadow size binding (#2924) - Implement MS RFC 69: Support for clustering of features in point layers (#3700) - Implement MS RFC 68: Support for combining features from multiple layers (#3674) - Add support for WCS 1.1 Post (#3710) - Fixed OGR query handling according to RFC 65 (#3647) - Implement CLOSE_CONNECTION=ALWAYS to suppress the connection pooling for a particular layer. - Implemented RFC 67: Enable/Disable layers in ogc web services (#3703) - Class title can now be used in legends. It's value takes precedence over class name. Previously title was not used any place in the code but it is supported for read/write. (#3702) - Allow definition of nodata attribute for layers without results (via resultset tag). (#3701) - mapprojhack.c: restructure to avoid needing projects, or any internal knowledge of PROJ.4. - Fix newlines around part boundaries in WCS multipart results (#3672) - Added minfeaturesize support at layer or class level (#1340) - Implemented support in for classifying rasters using the new expression parsing (msGetClass()...) (#3663) - Implemented RFC 65 which improves and simplifies one-pass query support. This causes a few MapScript regressions with getShape/getFeature/getResultsShape. (#3647) - Support setting filenames for WCS GetCoverage results (#3665) - OGR auto-styling: use the color parameter and set the style's opacity when it is available. Allow symbols that can be stored externally (#3660) - Add possiblity to use symbols stored externally, accessed through http (#3662) - Better handling of temporary files (#3354) - Support curved features in PostGIS (#3621) - NODATA values now excluded from autoscaling min/max for non-eight scaling computations (#3650) - Fixed missing time in msDrawMap logging (#3651) - Fixed Auto Angle - incorrectly placed Labels (#3648) - Fixed Improper validation of symbol index values (#3641) - Removed BACKGROUNDCOLOR, BACKGROUNDSHADOWCOLOR and BACKGROUNDSHADOWOFFSET label parameters (#3609) - Fixed Transformation from XML to MapFile only handles one PROCESSING element (#3631) - Fixed 16bit classification support - problem introduced with new renderer architecture (#3624) - Cleanup open gdal datasets in msGDALCleanup() (if we have a very new GDAL). This makes it easier to identify memory leaks. - Add support for per layer tuning of the shape to pixel conversion (SIMPLIFY, ROUND, SNAPTOGRID, FULLRESOLUTION) - Fixed: Memory allocation results should always be checked (#3559) - Fixed free(): invalid next size in mapfile.c (#3604) - Added a built-in OpenLayers map viewer (#3549) - Fixed issues with static buffers and sprintf (#3537) - Fix for the memory corruption when mapping the string data type in the Java bindings (3491) - Fixed double free in shp2img.c (#3497) - Fixed number of CGI params is limited to 100 (#3583) - Fixed duplicated XML and HTML errors from WFS GetFeature (#3571) - Support group names for GetLegendGraphic and GetStyles (#3411) - apply patch (thanks rouault) to advertise resultType=hits in WFS 1.1 Capabilities (#3575) - mapshape.c: Fix writing of geometries with z/m and fail gracefully attempting to create such files if USE_POINT_Z_M is not enabled (#3564) - sortshp.c: improve error handling (#3564) - MSSQL2008: Add support for geography data type by extending the DATA syntax to 'geometry_column(geometry_type) from table_name' - Fixed ability to get the error message and code of an OWS exception (#3554) - Fixed msOGRGetSymbolId according to the changes in gdal 1.8 (#3556) - Support holding WMS client requests in RAM instead of writing to disk (#3555) - RFC-61: Enhance MapServer Feature Style Support (#3544) - Restrict cascaded WMS requests based on EXTENT (#3543) - Avoid EPSG lookups for WMS client layers if possible (#3533) - RFC-60: Add ability to skip ANGLE FOLLOW labels with too much character overlap (#3523) - Fixed SWF: not a valid Bitmap FillStyle (#3548) - Set dependency on libxml2 when building --with-wfs (#3512) - Fixed TRUE is undefined in shptreevis (#3545) - shptreevis: bug truncates visualization shapefile if there are more nodes in the tree than there are shapes being indexed! - Fixed multiple include tags not supported in xml mapfiles (#3530) - Support reading .dbf files between 2GB and 4GB (#3514) - Avoid warnings about ms_cvsid being unused with gcc. - Ensure the class is not marked BeforeFieldInit causing memory corruption with C#/CLR4 (#3438) - Fixed MSSQL2008 driver returning invalid extent (#3498) - Added coordinate scaling to shpxy tag via parameters scale, scale_x or scale_y. - Fix computation of shape bounds when the first line contains no points (#3119)(fixes #3383) - Allow map relative specification in the PROJ_LIB config item (#3094) - Try to report reprojection errors in SLD Filter evaluation (#3495) - Disabled some insecure (and potentially exploitable) mapserv command-line debug arguments (#3485). The --enable-cgi-cl-debug-args configure switch can be used to re-enable them for devs who really cannot get away without them and who understand the potential security risk (not recommended for production servers or those who don't understand the security implications). - Fixed segmentation fault in ogr driver when shape type is null - Fixed synchronized MS_UNITS and inchesPerUnits array (#3173) - Fixed possible buffer overflow in msTmpFile() (#3484) - Fixed Using STYLEITEM AUTO, loadExpression fails when the label text contains a double quote (#3481) - PHP/MapScript: Expose getGeomTransform/setGeomTransform instead of exposing the private vars for rfc48 (#2825) - PHP/MapScript: Fixed updateFromString functions to resolve symbol names (#3273) - PHP/MapScript: ability to use the php clone keyword (#3472) - Modified mapserver units enum order to fix some problems with external softwares (#3173) - Fixed configure does not detect libGD version dependencies (#3478) - Fixed Drawing inline text not working (bitmap) (#3475) - ensure well formed XML when msWCSGetCapabilities_CoverageOfferingBrief returns MS_FAILURE (#3469) - Fixed msQueryByRect does not use tolerance (#3453) - Fixed MapScript processTemplate and processQueryTemplate seg fault (#3468) - Fixed shapeObj->toWkt() returns single point for multipoint geometry (#2762) - Fixed Internal server error when Oracle returns ora-28002 code (#3457) - Fixed PHP/MapScript ms_iogetstdoutbufferbytes() always returning 0 bytes written (#3041) - MapScript resultsGetShape() method fails with a OracleSpatial layer (#3462) - PHP/MapScript circular references between objects (#3405) - Handle null results with gml:Null/gml:null according to version (#3299) - Reworked mapfile writing to use helper functions so that core types (e.g. numbers, strings, colors, keywords, etc...) are always written consistently. - Ensure mapwmslayer.c does not unlink file before closing connection on it (#3451) - Fix security exception issue in C# with MSVC2010 (#3438) - Write out join CONNECTIONTYPE when saving a mapfile. (#3435) - Fixed attribute queries to use an extent stored (and cached) as part of the queryObj rather than the map->extent. (#3424) - Reverted msLayerWhichItems() to 5.4-like behavior although still supporting retrieving all items (#3356,#3342) - Grid layer: remove drawing of unnecessary gird lines (#3433) - Avoid errors and debug output for CONNECTION-less OGR layers in mappool.c if they have a tileindex. - Implement support for raw imagemodes to use NULLVALUE formatoption to set the background value of result images, and to try and mark nodata (#1709) - Implement support for wcs_rangeset_nullvalue to set NULLVALUE and return null value definition in describe coverage result (#655) - Try to avoid exhausting the color table when rendering 24bit key images into 8bit results (#1594) - Avoid crash, and ensure error report when loading keyimage fails (#1594) - Improve the handling of simple string comparisons for raster classified values (#3425) - Generate good SQL when using !BOX! token and no filter. (#3422) - Implement non-shapefile tileindex support for raster query (#2796). - Improve support for [red/green/blue] classification expressions for raster query (#1021) - Fixed imageObj->saveImage() sends unnecessary headers (#3418) - Avoid automatically regenerating maplexer.c (#2310) - Change rounding rules for average resampling (#1932) - Implement support for filename encryption per RFC 18 for rasters (#3416) - Fixed segfault when using shapefile with empty geometry and tileindex (#3365) - Avoid race condition on core_lock on win32 mutex init (#3396) - Avoid use of inline keyword for C code (#3327) - Support WFS parsing through libxml2 (#3364) - Fixed PHP/MapScript imageObj->saveImage() function (#3410) - Implement wms_nonsquare_ok metadata item for WMS servers that do not support non-square pixels (#3409) - Fixed MapScript shape->classindex is always 0 (#3406) - Fixed PHP MapScript integer passing broken on 64bit systems (#3412) - Fix MS_NONSQUARE to work in mode=map (#3413) - Support inclusion of raster layers in query map drawing even if the results may not be that useful (#1842). - Fixed auto angle: incorrectly rotated Labels. Added AUTO2 angle mode. (#1688) - Preliminary implementation of validity mask (imageObj->img_mask) for raw raster data (#2181) - Added libgd < 2.0.30 compatibility (#3293) - Incorporate support for GDAL nodata on RGB images (#2404) - Incorporated support for GDAL masks (GDAL RFC 15) (#2640) - Fixed XML transformation issues with expressions and symbols (#3397) - Check error returns from mapstring functions (#2988) - Add support for multiliple srs in WFS 1.1.0 (#3227) - Fixed PHP/MapScript owsRequestObj->loadParams() method when using php in a non cgi/fcgi/cli mode. (#1975) - Ensure that non-file raster datasets work (#3253) - Correct mutex locking problem with rasters with no inherent georef. (#3368) - Correct ungeoreferenced defaults via GetExtent() on raster layer (#3368) - PHP Mapscript refactoring: take full advantage of PHP 5 / Zend Engine 2 (#3278)" - Fixed msRemoveHashTable() to return the proper value on failure/success. - Correct one pass query problems and OGC filter query (#3305) - Fixed msMSSQL2008CloseConnection() to free the statement handle properly (#3244) - Fixed the query handling with the MSSQL2008 driver (#3058) - Fixed swig zoomRectangle() method: the maxy in the rect object have to be < miny value (#3286) - Fix crash with GRID layers with no classes (#3352) - Remove "legacy" raster support, all raster rendering via GDAL now. - Very preliminary render plugin support for raster rendering. (RFC 54) - support correct MIME type output for WFS 1.1.0 (#3295) - add WMS 1.3.0 LayerLimit support (#3284) - fix WFS 1.1.0 exception attributes (#3301) - add more useful error message when query file extension test fails (#3302) - s/gml:null/gml:Null for empty WFS GetFeature responses (#3299) - Support metatiling and buffers in mode=tile (#3323) - Enhance error messages in msGetTruetypeTextBBox() (#3314) - Report parsing errors in INCUDEd files using the line number within the file (#3329) - Avoid memory error when building SQL bbox (#3324) - Reproject rectangles as polygons to get datelin wrapping (#3179) - Add support for the WMS capabilities items AuthorityURL, Identifier (#3251) - Added support to write a null shape in a shape file. (#3277) - Apply ON_MISSING_DATA to zero-length WMS client calls (#2785, #3243) - PHP/Mapscript: added labelCacheMember object and mapObj::getLabel() method (#1794) - Add shplabel tag support in templates (#3241) - Bumped GEOS requirement to version 3.0+ (#3215) - Fixed memory leak related to templates (#2996) - Added support of 44xx gtypes in oracle spatial driver (#2830) - Fixed curl proxy auth support for http connections (#571) - PHP/MapScript: removed deprecated class properties (#2170) - Fixed OGR datasource double free (#3261) - Fix compilation warnings around use of strcasestr (#3257) - Made %substitution% strings case insensitive (#3250) - Added support to get the extent of a raster layer that use a tileindex (#3252) - Fixed configure to support FTGL 2.1.2 (#3247) - Changed msSaveImageBufferGD to be in accordance with msSaveImageGD (#3201) - PHP/Mapscript: added layerObj units property (#3249) - Changed the query map rendering implementation without adding extra layers to the map (#3069) - SQL Server 2008 plugin is not handling null field values correctly (#2893) - Hatch symbol not properly saved (#2905) - Expose symbolObj.inmapfile to the SWIG API, have already been exposed to PHP (#3233) - Expose getGeomTransform/setGeomTransform to SWIG instead of exposing the private vars for rfc48 (#3214) - Fixed writeSymbol to support writing 'ANGLE AUTO' (#3214) - Fixed problems with point queries not working via the CGI (mode=query or mode=nquery) (#3246) - Support QueryByShape() with point and line geometries (#3248) - Honour MAXSIZE for WCS responses (#3204) - Implemented RFC 52 LayerResultsGetShape support for OGR connection type. - Fixed uninitialized variable with malloc used in osPointCluster() (#3236) - Oracle driver: remove BLOB columns instead of changing them to null (#3228) - Fixed ogc sld functions to return proper values (#2165) - MAP EXTENT truncates GetFeature requests for data outside bounds (#1287) - Added msStringSplitComplex function (#471) - Mapserver WFS should send maxfeatures to the spatial database (#2605) - WFS paging support (#2799) - Fixed joins do not accept crypted passwords (#2912) - Fixed HTML legend image samples truncated (#2636) - WMS GetFeatureInfo should respect the scale like GetMap does (#842) - Filter encoding: simple filters using propertyislike not applied properly #2720, #2840 - Fix VBAR Chart production when using GD for rendering (#3482) Version 5.6.0 (2009-12-04): --------------------------- - WFS hits count is incorrect if the request contain 2 layers or more (#3244) - Fixed a problem with layer plugin where copyVirtualTable didn't copy the LayerResultsGetShape function pointer (#3223) Version 5.6.0-rc1 (2009-11-27): ------------------------------- - Fixed a problem with shape-based queries against projected layers when using a tolerance (#3211) - Fixed long expression evaluation (#2123) - Added simplfy and topologyPreservingSimplify to MapScript (#2753) - Fixed Oracle FastCGI memory leak (#3187) - layer->project flag not being reset properly for drawquerylayer (#673 #2079) - OGC SLD: support multi-polygons geometries for filters embedded in an SLD (#3097) - [WMC] embedded SLD in context does not work with namespace prefix (#3115) - Support name aliases used in sld text symbolizer (#3114) - decode html and unicode entities for polygon truetype symbol fills (#3203) - Parse PropertyName parameter for wfs requests (#675) - Fixed when saving a map, layer->transform isn't written properly in all cases. (#3198) - Fixed buffer overflow in oracle spatial driver with large sql data (#2694) - Improve FastCGI include file finding logic (#3200) Version 5.6.0-beta5 (2009-11-04): --------------------------------- - Apply a minimum width on label outline (new outlines were too thin by default) - Don't apply scalefactor to polygon outline widths (but apply the resolutionfactor) - Fix vector symbol size calculation (#2896) - Applied code clean up patch for mapsearch.c. (#3189) - Fixed labels centering when the label is longer than the line (#2867) - Ensure Python MapScript building doesn't reorder the libraries, support the 'subprocess' module where available for setup.py, and default to using the "super" swig invocation described in the Python MapScript README when mapscript_wrap.c isn't available on the file system. #2663 contains the reordering issue. - Fixed memory leak with shapefiles associated with one-pass query implementation (#3188) - Fix abs/fabs usage that prevented angle follow labels to be discarded if they were too wrapped on themselves - Allow CGI mapshape and imgshape variables to consume WKT strings (#3185) - Added support for nautical miles unit (#3173) - Fixed encoding metadata ignored by a few wcs/wfs 1.1 and sos requests (#3182) - PHP/Mapscript: added "autofollow" and "repeatdistance" in labelObj (#3175) - Added charset in content-type http header for wms/wfs/sos/wcs requests (#2583) - Python/MapScript: improve compatibility for different swig versions (#3180) - maprasterquery.c: a few fixes since beta4 (#3181, #3168). - mapows.c: Generate WMS LatLongBoundingBox in WGS84 datum (#2578) Version 5.6.0-beta4 (2009-10-18): --------------------------------- - Allow processing of single shapefiles with no items (e.g. an empty dbf file) (#3147) - Added resolution scaling for swf, svg, pdf and imagemap drivers (#3157) - Correct cases where a valid WFS Layer might return errors if map extent does not overlap the layer extent (#3139) - fix problem with 0-length line patterns in AGG - Fixed problem of text/html WMS GetFeatureInfo which was returning HTML image map output instead of the expected text/html template output. This was done by changing the imagemap outputformat to use the "text/html; driver=imagemap" mime type (#3024) - more resolution fixes for resolution scaling (symbolscale case) (#3157) - Make sure layer extents are saved when a mapfile is written (#2969) - Fixed CurvePolygons from oracle not drawn (#2772) - Fixed raster queries (broken by RFC 52 changes) (#3166) - Fixed coordinate projection problem in some cases with WMS GetFeatureInfo output in GML2 format (#2989) - Added resolution scaling of some properties for GD driver (#3157) - Modified GD functions API to be consistent with all others drivers (#3157) - OGC Filter: strip all namespaces (not only ogc, gml) (#1350) - Use decimal values for size and width in SVG output format (#2835) - Correct invalid test when loading movies in an swf ouput (#2524) - Return WMS GetCapabilities v1.3.0 by default as required by spec (#3169) - Fixed mapObj.zoomScale() and mapobj.zoomRectangle() scaling problem in Mapscript (#3131) - Few more fixes for high res output (#3157) - Allow "DRIVER 'TEMPLATE'" or "DRIVER TEMPLATE" in output formats - Correct sld generated from mapserver classes (#3133) - Correct libjpeg v7 compatability issue in old jpeg interface code (#3167) - Correct FEATURE_COUNT limits on WMS GetFeatureInfo raster queries (#3168) - Correct SCALE_BUCKETS issue with 16bit raster scaling (#3174) Version 5.6.0-beta3 (2009-10-07): --------------------------------- - make RFC55 highres output be friendly with scaledependant rendering (#3157) - avoid fractured and overlapping glyphs with angle follow (#2812) - Fixed SDE layer seg fault (#3152) - Fixed placement of labels using ANGLE AUTO which were not always positioned correctly (#3160) - Enable output of geometry in GML GetFeatureInfo if wms_geometries and wms_geom_type are specified (#2989) - fix URN typo in mapwfs.c for urn:EPSG:geographicCRS:... - don't apply scalefactor to label outlines (#3157) - update namespaces and schema pointers (#2872) - add RFC49 and RFC40 keywords to copy functions (#2865) - minor fix to correct numberOfResults when maxfeatures is set in mapfile (#2907) - Fixed possible crash with WFS GetFeature when no projection is specified at the map level (#3129) - Fixed anchor point of vertically stacked bar graphs - Fixed TEXT property that cannot be removed in the CLASS object. PHP/Mapscript (#3063) - Fixed use of minfeaturesize auto with curved labels (#3151) - Fixed msRemoveHashTable function when 2 keys have the same hash (#3146) - Fix raster thread deadlock condition on posix/linux (#3145) - Do not route thread debug output through msDebug which requires locking. - Fix WCS coverage metadata handling if size/resolution missing (#2683). - Fix WCS crash with use of datasets that aren't physical files (#2901). - Fix WCS failure with WCS 1.1 OGC URN (urn:ogc:def:crs:OGC::CRS84) (#3161). Version 5.6.0-beta2 (2009-10-01): --------------------------------- - Fixed a couple of issues with Oracle Spatial and single pass queries (#3069) - Added layer.resultsGetShape() to PHP MapScript for use with queries (#3069) - Fixed query maps under the new single pass query process (#3069) - WFS Client seg fault (OGR layer not opened) (#3136) - Reduce use of sqrt() calls when determining distances (#3134) - support axis ordering for WFS 1.1 (#2899) - const changes to avoid warnings with msLoadProjectionString() - mapgd.c: removed unused drawVectorSymbolGD() function. - Use http://www.mapserver.org/mapserver namespace URI in XML mapfile schema (#3142) - Fixed issue with PHP_REGEX_INC in mapscript/php3/Makefile.in (#3078) Version 5.6.0-beta1 (2009-09-23): --------------------------------- - WMS 1.3.0 expects a CRS parameter instead of SRS (#2979) - Allow users to set wms getmap and getlegendgraphic image format list (#455) - Fixed MapScript shapeObj->toWkt() segfaults (#2763) - add vertical bar charts to dynamic charting (#3128) - Get the intersection points and labels #3101 - Fixed shp2img not to cause a crash when the map couldn't be loaded - Fix problem with overflowing shape->index for (most) query modes (#2850) - Useful error message when PK is missing and data is subselect (#3124) - Add WMS root Layer metadata support (#3121) - Fixed build problem of PHP/Mapscript when php is compiled with gd as a shared extension (#3117) - Improve safety of srcx/y checks in nearest neighbour raster resampler (#3120) - Added support for 4d geometry types and oci bind variables for Oracle (#3107) - Implement SECTION support for the WCS 1.1 GetCapabilities request (#3105) - Fixed WCS processing when both crs and response_crs are specified (#3083) - Fixed msFreeMap causing memory corruption in msFreeOutputFormat (#3113) - Fix WMC XML output when Dimension is used (#3110) - Enable LOAD_WHOLE_IMAGE processing option by default when rendering WMS client layer images (#3111). - add default values for CGI %key% substitutions (#3108) - fix clipping of polygon shapes in line layers (#3059) - RFC 51 implementation: XML Mapfiles Format (#2872) - Fix output for valid WCS 1.1 XML (#3086) - Avoid double free with postgresql joins. (#2936) - Don't attempt to project layers given in pixel coordinates (layer->transform != MS_TRUE) (#3096) - Modify loading imagery from GDAL to load all bands at once to avoid multiple passes through pixel interleaved data (mapdrawgdal.c). This is just an optimization - there should be no change in results or features. - Modern GDALs clear the config when destroying driver manager. Skip this call to avoid TLS leakage on cleanup (mapgdal.c). - Fixed msMSSQL2008LayerGetShape to retrieve proper wkb geometries (#3082) - Fixed the shape index for the inline layers (#3074) - Fixed MINDISTANCE not considering label size on lines (#3050) - Labeling enhancements: ability to repeat labels along a line/multiline (#3030) - Modified STYLEITEM code to use the new way of rendering thick lines (#3025) - Fixed template processor to respect layer order. (#2619) - Add MS_DEBUGLEVEL and MS_ERRORFILE commandline switches for mapserv.c. - Exposed msMapOffsetExtent, msMapScaleExtent and msMapSetCenter methods in PHP/Mapscript (#2460) - Removed ZEND_DEBUG define in PHP/Mapscript (#2717) - Fixed PHP/Mapscript to support PHP 5.3 (#3065, #3066) - remove -O optimization flags to configure script if configured with --enable-debug - Fixed performance bottleneck when computing a polygon center of gravity for label point computation. (#3053) - make WFS numberOfFeatures match maxFeatures if passed (#2907) - Add logging in layer visibility tests to help users find why layers don't draw (#3054) - include PNG libs first (#3046) - merge graphics branch: RFC54 implementation, cairo rendering (png, svg, pdf), opengl rendering (non functionnal yet) - Do pre-emptive test for map.extent/layer.extent interaction (#3043) - Add centroid geomtransform (#2825) - Test database connections before using them (#2932) - Support non-numeric join criteria (#2006) - Ensure there's enough room in the SQL to hold a long (#1284) - Fix filter error in multi-clause filters (#2937) - Fix agg freetype character lookup when no unicode charmap is present (#3018) - Fix memory leak in SQL building (#2997) - Fork AGG rendering library in our trunk - Fixed a memory leak when unescaping quotes in logical expressions (#2938) - Fixed template code for item, shpxy and extent tags to properly initialize tag arguments in cases where there are mutiple tags in one chunk of template (#2990) - Fix mapogcfilter.c not to cause syntax error if PROJ.4 is not compiled in (#2987) - Rework Python MapScript's setup.py to be more like Python's to fix a number of issues including (#2637) and to use mapserver-config and ditch the old mapscriptvars approach - Prevent from changing the connection type to MS_RASTER when setConnectionType(MS_WMS) is used (#2908) - Improve rounding logic for computing the src_xoff/yoff (#2976) - Fix filename path processing for raster queries and WCS get coverage so that non-filesystem filenames are not altered (#2901) - Improved security relative to untrusted directories and mapfiles (RFC 56) - Fixed several security issues found in an audit of the CGI application (#2939, #2941, #2942, #2943, #2944) - setConnectionType(MS_WMS) doesn't work with mapscript (#2908) - Perl Mapscript: improvement of imageObj wrapper (#2962) - Improve control of output resolution (RFC 55, #2948) - mapraster.c: use GDALOpenShared(), and CLOSE_CONNECTION=DEFERRED (#2815) - AGG font outline method change (#1243) - Change mapbit.c bitmask type from char to new 32bit ms_bitarray (#2930) - Added resolution writing in image files (#2891) - Try to save resolution values to GeoTIFF via GDAL (#2891) - Refactor legend icon drawing (remove renderer specific versions) Add label styling or markers for annotation layer legend icons (#2917) - Update EXTENT warning message (#2914) - add support for SRSNAME parameter (#2899) - add support for resultType (#2907) - WFS 1.1.0 should use OWS Common 1.0.0 (#2925) - clean up GEOS init and cleanup functions (#2929) - add support for disabling SLD (#1395) - fix to output gml:boundedBy again (#2907) - fix warning for change in bitmask type (#2930) - fix time advertising in WMS 1.3.0 (#2935) - fix SOS blockSeparator output (#3014) - fix MIME type support (#3020) Version 5.4.0-beta3 (2009-3-5): -------------------------------- - SLD: Correct crash with large class names (#2915) - Added Java MapScript WIN64 support (#2250) - Fixed a problem with long running processes, embedded scalebars/legends and AGG. (#2887) - Applied patch to deal with a couple of WCS issues (time ranges, #2487) and PostGIS tileindex-based time filters (#1856) - Adding -DUSE_GENERIC_MS_NINT to the WIN64 MapScript builds (#2250) - Fixed C# the compiler options for MSVC 2008 (#2910) - Fix build problem with mapogcsld.c when OWS services are not available (#473) - Fix build on windows (maputil.c) Version 5.4.0-beta2 (2009-2-25): -------------------------------- - Fixed a problem where default shade symbols (solid fill, no size) were being scaled and not rendered as expected (related to #2896 I believe) - Fixed a problem with offset polylines (AGG only) (#2868) - Generate SLD version 1.1.0 (#473) - Tracking original geometry type so we can make better decisions on what positions to use with POSITION AUTO and annotation layers. (#2770) - Setting up the same size units between the OGR auto-style and the OGR label attribute binding option (#2900) - Take better care of the extra items with the inline layers to prevent from memory corruption (#2870) - Fixed the compiler options for MSVC 2008 (#2898) Version 5.4.0-beta1 (2009-2-18): -------------------------------- - restored much of the pre-5.0 capabilities to update a mapfile via URL but in a more secure manner (RFC44) - WMS 1.3.0 support added (#473) - OWS GetCapabilities should skip layers with status == MS_DELETE (#2582) - Set the default symbol size to 1 instead of 0 (#2896) - fix WMS LegendURL to print sld_version for 1.3.0 Capabilities (#473) - add GetSchemaExtension to WMS to support GetStyles in Capabilities XML (#473) - move xlink declaration to root of WMS 1.3.0 DescribeLayerResponse - Fixed a scalebar rounding problem causing to draw zero scalebar width (#2890) - SLD: if it conatins a Filer Encoding tag, try to always set the layer's FILTER element (#2889) - Add support for rendering INLINE layers with layer attributes (items) (#2870) - Fix mapserver crash when rendering a query map in HILITE mode and there are is no STYLE defined (#2803) - Added projection support to [...ext] tags for template output. - Removed the error generation when the OGR layer contains no fields (#2883) - Added enhancements to mapogr.cpp for style annotations (#2879) - Fixed memory leaks when using msUpdate*FromString methods. (#2857) - Fixed the problem when removing the attribute binding in mapscript. - SOS XML validity fixes (#2646) - add WFS calls for schema resolution (#2646) - add gml:id to om:Observation (#2646) - fix some XML validity issues (#2646) - Fixed endianness issues with wide character strings for ArcSDE (#2878). Thanks Russell McOrmond - Fixed WMS request with LAYERS parameter: may cause segmentation fault (#2871) - fix when layer status = DEFAULT and passing list of layers (#2066) - Fixed msAddLabel may cause access violation in certain conditions - Changed base type of labelObj size, minsize and maxsize from int to double (#2766) - add support for WMS Server title in LAYER object (#885) - Fixed build problem using --with-gd=static and freetype (#2697) - RFC49 implementation (#2865) - Fixed Blobs not filtered in OracleSpatial Attribute/WFS queries (#2829) - Fixed memory leak of map::setProjection in PHP/MapScript (#2861) - Fixed "internal PHP GC memory leaks" in PHP/MapScript (#2767) - Fixed bug with wms layer group hierarchy (#2810) - Added updateFromString() methods for several objects in PHP/Mapscript (#2298) - Added ms_newMapObjFromString mapObj constructor in PHP/Mapscript (#2399) - Add support to compile mssql2008 when SDE or ORACLE is not compiled (#2851) - Add support for creating debug builds for the plugins on Windows - Correct half pixel error in WMS layer's BBOX request to remote WMS (#2843) - Expose Map/Layer's Projection objects in PHP/MapScript (#2845) - Added getUnits() methods to projectionObj in Mapscript (#2798) - Improved Tag parsing in template code. (#2781) - Added hashtable object and metadata methods for php-mapscript (#2773) - mappostgis.c: Fix trailing spaces in fixed varchar fields (#2817) - RFC48 implementation: GEOMTRANSFORM on styleObj (#2825) - mapwms.c: cleanup warnings with recent gcc versions (#2822) - mapogcsos.c: Cleanup warning and error messages - mapagg.cpp: Fix center of rotation for truetype marker symbols - mapowscommon.c: use msLibXml2GenerateList to generate listed XML elements - mapowscommon.c: output version string correctly (#2821) - Added removeLayer function to mapObj in PHP/MapScript. (#762) - Exposed PIXELS value via URL configuration - Add Support for SLD TextSymbolizer HALO and ANGLE (#2806) - IGNORE_MISSING_DATA: largely replaced by run-time CONFIG property, ON_MISSING_DATA, which supports three modes: FAIL, LOG, and IGNORE. (#2785) ms-rfc-47.txt - mapstring.c: msStringTrim(*char str), front-and-back whitespace trimmer - mappostgis.c: re-write to remove binary cursors and break up logic into smaller parts, add support for maxfeatures - mapogcfilter.c: increase array size (code was assigning to out of bounds subscript) - MapScript: Added getBinding method to label and style object (#2670) - mapowscommon.c: use strcasecmp to check for language value - raster query fix for tileindex with relative paths (#2722) - Fixed msOGRGetValues function to return default values if the object type is not TEXT. (#2311) - Fix for the access violation caused by msMSSQL2008LayerGetShape (#2795) - Fixed msMSSQL2008LayerGetItems to retrieve the column names properly (#2791) - Prevent from calling msMSSQL2008CloseConnection from msMSSQL2008LayerClose causing memory corruption issues (#2790) - new polygon label placement algorithm (#2793) - stop drawing an artificial outline around polygons to ensure continuity - users needing this feature will have to explicitely add an outlinecolor of the same color as the fill color - added formatoption QUANTIZE_NEW to force going through the pngquant quantization algorithm instead of the GD one for imagemode RGB (the GD one can be kind of buggy) - fix some integer rounding errors in the agg line offseter (#2659) - fix a bug with shapes with duplicate end points. was causing nans in the angle follow placement code (#2695) - refactor msGetLabelSizeEx (now merged with msGetLabelSize) (#2390) - native label size computation for AGG when using angle follow (#2357) - memory leak in msInsertLayer, from Ned Harding (#2784) - label size computation refactoring (#2390) - don't draw label background if we're using angle follow. (#2726) - legend keyimage resampling with agg (#2715) - tileindexed rasters when DATA is manipulated via mapscript work (#2783) - styleObj width now supports attribute binding - RFC40 implementation: label text wrapping and alignment (#2383) - baseline adjustment for multiline labels (#1449) - Added support to access to the labelObj OUTLINEWIDTH property in PHP/MapScript - PHP paste image should also work with AGG (#2682) - Fixed bug when QUERYMAP hilite color is set and the shape's color in a layer is from a data source (#2769) - Decoupled AUTO label placement from the positions enum in mapserver.h. Added explicit case for POLYGON layers where CC is the default and then we try UC, LC, CL and CR. (#2770) - Changed base type of styleObj size and width from int to double (#2766) - Correct allocation error in mapmssql2008.c - Add possibility to use a full resolution setting for svg output (#1706) - Fixed GetFeature through tileindex bug: the tileindex of the shape found wasn't set properly in the resultcache object. (#2359) - Removed comma to correct WCS 1.1 Coverages formatting in payload directory. (#2764) - Correct bug when LABEL_NO_CLIP in combination with minfeaturesize (#2758) - Fix a label size computation for AGG bug when scalefactor is used (#2756) - various SOS updates for CITE compliance (#2646) - Added support for static linking with the lib gd in configure script (#2696) - Support OpenLayer's ol:opacity extension to OGC Web Map Context docs (#2746) - Added MS_VERSION_NUM for use with #if statements in code based on libmapserver (#2750) - Fixed the configure script: failed to detect php5 on ubuntu. (#2365) - Fixed a memory leak associated with not deleting the lexer buffer before parsing certain types of strings. (#2729) - Added legend graphics for layer of type annotation for the AGG and GD renderer (#1523) - Masking the out-of-range characters to avoid the crash in the AGG renderer (#2739) - Accept WMS requests in which the optional SERVICE parameter is missing. A new test was incorrectly added in 5.2.0 that resulted in the error "Incomplete WFS request: SERVICE parameter missing" when the SERVICE parameter was missing in WMS requests in which the SERVICE parameter is optional (#2737) - Support for the MapInfo style zoom layering option (#2738) - Implement Equals and GetHashCode properly for the mapscript C# classes - Expose msConnectLayer to the SWIG mapscript interface with a new layerObj.setConnectionType() method that should be used instead of setting the layerObj.connectiontype directly (#2735) - SLD: when creating well known symbols on the fly the pen-up value used should be -99. - SWF: Button names reflects the layer id and shape id (#2691) - Support reading projection parameter for OGC filters (#2712) - Several enhancements to STYLEITEM AUTO support for labels (#2708) and TTF symbols (#2721) in OGR layers - Expose special attributes OGR:LabelText, OGR:LAbelAngle, OGR:LabelSize and OGR:LabelColor to MapScript getShape() calls (#2719) Version 5.2.0 (2008-07-16): --------------------------- - mapfile.c: Fixed a bug that prevented using named symbols via URL configuration. (#2700) Version 5.2.0-rc1 (2008-07-09): ------------------------------- - mapowscommon.c: fix support multiple namespaces (#2690) - Fix OGC simple filters on SDE layers (#2685) - wfs11 getcapabilities: correct memory corruption (#2686) - Allow building against Curl 7.10.6 and older which lack CURLOPT_PROXYAUTH option required for *_proxy_auth_type metadata (#571) - Avoid fatal error when creating new ShapeFileObj with MapScript (#2674) - Fixed problem with WMS INIMAGE exceptions vs AGG output formats (#2438) - mapshape.c: Fixed integer pointer math being applied to uchars (#2667) - Fixed seg fault with saveImage() in PHP MapScript due to #2673 (#2677) - Fixed configure error related to new fribidi2 pkg-config support (#2664) - Fixed windows build problem (#2676) - Fix raster query bounds problem (#2679) Version 5.2.0-beta4 (2008-07-02): --------------------------------- - Added support in configure script for pkg-config for fribidi2 (#2664) - Added more debug/tuning output to mapserv and shp2img at debug level 2 (#2673) - maptemplate.c: removed extra line feeds from mime header output. (#2672) - mapresample.c: fix for bug 2540 when using raster resampling and AGG. - mapsde.c: Check at compile time that we have SE_connection_test_server, which appears to only be available for ArcSDE 9+ (#2665). - mapshape.c: restore old behavior of tiled shapes relative to shapepath with new behavior for when shapepath is undefined (#2369) - maputil.c: fix a bug for offset lines with agg, when the first segment was horizontal (#2659) - mapraster.c: fix for tiled rasters with relative shape paths defined, from dfurhy (#2369) - maptemplate.c: fixed a problem with extent tags with _esc extension not working (#2666) Version 5.2.0-beta3 (2008-06-26): --------------------------------- - mapsde.c: processing option added to allow using fully qualified names for attributes (#2423). - mapsde.c: Test for an active connection before closing it (#2498). - mapdraw.c: Fixed issue where path following labels were not being drawn if FORCEd. (#2600) - mapshape.c: Applied patch to make the location of tiled data relative to the tileindex directory if SHAPEPATH is not set. (#2369) - maptemplate.c: Fixed issues in RFC 36 implementation that prevented mapscript mapObj->processQueryTemplate() method from working. - WMS/WFS: extend warning message (#1396) - WFS: Respect units for the DWhitin parameter (#2297) - WFS: correct OGC Contains filter (#2306) - WMS: set srsName correctly for GetFeatureInfo (#2502) - SOS: detect invalid time strings (#2560) - SOS: more srsName support (#2558) - mapserv.c, maptemplate.c: fixed problem with arguments to msGenerateImages(). (#2655) - WMS: produce warning if layer extent is null (#1396) - WFS: project LatLongBoundingBox if required (#2579) - SOS: generate error for some invalid filters (#2604) - SLD: Use style's width paramater when generating sld (#1192) Version 5.2.0-beta2 (2008-06-18): --------------------------------- - mapogcsos.c: support invalid procedure in GetObservation (#2561) - Fixed possible buffer overrun with Oracle Spatial driver (#2572) - mapogcsos.c: support srsName in GetObservation (#2414) - Filter Encoding: Modify DWithin definition (#2564) - Added webObj legendformat and browseformat mapping in PHP MapScript (#2309) - Removed static buffer size limit in msIO_*printf() functions (#2214) - Fixed libiconv detection in configure for OSX 10.5 64 bit (#2396) - mapstring.c: possible buffer overflow in msGetPath (#2649) - maputil.c: Correct expression evaluation with text containing apostrophes (#2641) - mapwfs.c: Possibly generate an error message when applying filter encoding (#2444) - Added MS_LABEL_BINDING constants for SWIG MapScript (#2643) - mapogcsos.c: fix POST support (#2379) - maplibxml2.c: helper functions XML POST fix (#2379) - mapwfs.c: fix segfault when srsName is not passed on BBOX Filter (#2644) - mapwfs.c: do not return error for empty query results (#2444) - Remove C++-style comments and most other warnings thrown by -pedantic (#2598) - mapwfs.c/mapwfs11.c: set GML MIME type correctly - mapogcsos.c: advertise supported SRS list via MAP.WEB.METADATA.sos_srs (#2414) - mapwfs.c: set layer extent to map extent for default GetFeature requests with no spatial predicates (#1287) Version 5.2.0-beta1 (2008-06-11): --------------------------------- - WMS/WFS layers can now specify a proxy servert (#571) - mapwmslayer.c: set QUERY_LAYERS correctly (#2001) - mapwcs.c: handle PARAMETER values correctly (#2509) - SOS: fix various memory leaks (#2412) - mapwcs.c: advertise temporal support in GetCapabilities (#2487) - Fixed flaw in findTag() in maptemplate.c that prevented multiple tags on the same line being processed under certain conditions. (#2633) - Return results even when extents are missing (#2420) - Avoid displaying OGR connection strings in error messages (#2629) - WCS: respect wcs_name metadata for GetCoverage and DescribeCoverage requests (#2036) - CGI: added -nh option to allow for the suppression of content headers from the command line (#2594) - PostGIS: fix postgis idle-in-transaction problem (#2626) - AGG: enable ellipse symbol rotation for POINT/ANNOTATION layers (#2617) - RFC36: add more extensions to support templates (#2576) - AGG: allow dashed hatch symbols (#2614) - AGG: enable offset lines of type x -99 (#2588) - AGG: use an agg specific label size calculation function where possible (#2357) - mapogcsld.c: fetch TextSymbolizer/Label/ogc:PropertyName correctly (#2611) - Don't ignore .qix file when DATA reference includes .shp extension (#590) - CGI able to alter layers with space and underscores (#2516) - WFS Multipoint query with PostGIS bug fixed (#2443) - Tiling API (RFC 43) mode=tile, tilemode=spheremerc, tile=x y zoom (#2581) - Remove C++-style comments and most other warnings thrown by -pedantic (#2598) - Fix PostGIS transaction behavior in fcgi situations (#2497, #2613) - Improve performance for large shape files (#2282) - encode WMS parameters correctly (#1296) - Added alignment option within a scalebar (#2468) - RFC-42 HTTP Cookie Forwarding (#2566) - Fixed handling of encrypted connection strings in postgis driver (#2563) - mapagg.cpp: AGG: add opacity at the style level (#1155) - mapwms.c: add Cache-Control max-age HTTP header support (#2551) - mapogcsos.c: support URI encoded procedures correctly (#2547) - Added support for EMPTY template with WMS GetFeatureInfo (#546) - Throw an exception if the WCS request does not overlap layer (#2503) - Acquire TLOCK_PROJ for pj_transform() calls (#2533). - Fixed problem with large imagemaps generating no output (#2526) - mapwms.c: make version optional for GetCapabilities again (#2528) - support URN scheme for components of observed property elements (#2522) - Fixed gdImagePtr gdPImg memory leak in msSaveImageBufferGD() (#2525) - mapogcsos.c: handle invalid POST requests (#2521) - mapogcsos.c: handle ACCEPTVERSIONS parameter (#2515) - mapwcs.c/mapwcs11.c: s/neighbour/neighbor/g (#2518) - mapwms.c: relax FORMAT parameter restrictions for GetFeatureInfo (#2517) - mapwcs.c: support COVERAGE lists for DescribeCoverage (#2508) - mapwcs.c: fix lonLatEnvelope/@srsName (#2507) - mapwcs.c: omit VendorSpecificCapabilities (#2506) - mapwcs.c: test for either resx/resy OR width/height (#2505) - mapwcs.c: make GetCoverage demand one of TIME or BBOX (#2504) - mapwms.c: make GetLegendGraphic listen to TRANSPARENT in OUTPUTFORMAT (#2494) - OWS: support updatesequence (#2384) - mapwms.c: test VERSION after service=WMS (#2475) - OWS: output Capabilities XML updateSequence if set (#2384) - mapwcs.c: better handling of REQUEST parameter (#2490) - mapwcs.c: point to correct exception schema (#2481) - mapows.c: add version negotiation (#996) - mapwfs.c: return default GML2 when invalid OUTPUTFORMAT passed (#2479) - mapowscommon.c: add OWS Common style version negotiation (#996) - mapwcs.c: better section parameter handling for CITE (#2485) - mapwfs.c: point to the correct schema for exceptions (#2480) - shp2img.c/shp2pdf.c: clean up usage text, check for invalid layers (#2066) - completed implementation of RFC24 (#2442, #2032) - mapwcs.c: require VERSION parameter for DescribeCoverage and GetCoverage (#2473) - mapwcs.c: change error token to MS_WCSERR instead of MS_WMSERR (#2474) - mapwcs.c: set exception MIME type to application/vnd.ogc.se_xml for 1.0.0 (#2470) - mapwcs.c: Generate a decently formatted exception if an WCS XML POST request is received (#2476). - mapowscommon.c: support OWS Common 1.1.0 as well (#2071) - mapogcsos.c: support SOS 1.0.0 (#2246) - Implement mapObj.setCenter, mapObj.offsetExtent, mapObj.scaleExtent, rectObj.getCenter at the SWIG API (#2346) - mapogcfilter.c: use USE_LIBXML2 in ifdefs (#2416) - clean up naming conventions of Shapefile API (#599) - use msComputeBounds() instead, since it's already in the codebase (#2087) - set shapeObj bounds from WKT (#2087) - fixed issue where path following labels sometimes used the supplied setting for position. In all cases with ANGLE FOLLOW we want to force position MS_CC regardless of what is set in the mapfile. - enforce (-99 -99) to be the penup value for vector symbols (#1036) - Support for labeling features (polygon & line) prior to clipping. This results in stable label positions regardless of map extent. (#2447) - Support for quantization and forced palette png output with RGBA images (#2436) - SLD using a single BBOX filter should generate an SQL ststement for oracle/postgis/ogr (#2450) - Accurate Calculation of legend size for WMS LegendURL (#2435) - Converted mapogr.cpp to use OGR C API instead of C++ classes to allow GDAL/OGR updates without having to recompile MapServer (#545, #697) - add missing space on dashed polygon outlines with svg (#2429) - Restored behavior of MS 4.10 and made WMS STYLES parameter optional again in GetMap and GetFeatureInfo requests (#2427) - Speed up forced palette rendering (#2422) - WMS GetFeatureInfo: honour FEATURE_COUNT for any INFO_FORMAT and apply the FEATURE_COUNT per layer instead of globally (#2423, #1686) - enable soft outlines on truetype labels. This is triggered with a new keyword OUTLINEWIDTH for the LABEL block (#2417) - fix clipping rectangle to take width as well as size into account (#2411) - AGG: added and use a line and polygon adaptor to avoid copying shapeObj points to an agg path_storage. avoids a few mallocs and a few copies. - fixed symbolsetObj not to set the SWIG immutable flag permanently don't expose refcount and the symbol attributes (Ticket #2407) - fix for support of entity encoded text in angle follow text (#2403) - AGG: initial support for native computation of label sizes (#2357) - AGG: support text symbols specified by their character number (#2398) - AGG: fix angle orientation for various symbols - allow scientific notation for attributes binded to an int (#2394) - merge GD and AGG label cache drawing functions (#2390) - Enable AGG rendering of bitmap font labels instead of falling back to GD (#2387) - clean up treatment of encoding and wrap caracter - Fix legend label placement for multiline labels (#2382) - enforce WRAP parameter in legend label (#2382) - AGG: pixel level simplification for line and polygon shapes (#2381) - fixed blue/green color swapping for space delimited strings bound to an attribute. (bug 2378) - don't remove points that are checked as being colinear (#2366) - add initial(?) support for reading a pie chart's size from an attribute (#2136) - don't bail out in map parsing if the outputformat had to be modified (bug #2321) - use a renderer agnostic legend icon drawing function which switches to the GD or AGG specific one depending on the outputformat (#2348) - AGG: switch alpha buffer when drawing query layer - Fixed legend icons not drawing when using maxscaledenom - AGG: fix embedded scalebar rendering when using postlabelcache (#2327) - AGG: allow for fast and aliased rendering of simple lines and polygons thick lines and patterns (i.e. dashes)aren't supported. this is triggered when the symbol is of TYPE SYMBOL *and* its ANTIALIAS is off (wating to find a better solution to trigger this). - AGG: the pixmap of pixmap symbols is now cached in an agg-compatible state the first time it is accessed. this avoids rereading and retransforming it each time that symbol is used. - AGG: the imageObj now stores in what state it's alpha channel is in. The number ofmsAlphaGD2AGG/AGG2GD calls is now reduced, but most importantly each of these calls is usually just a check for this state and does no computation. - AGG: fixed a few artifacts in embedded legend rendering on rgba images. - Fixed modulus operator in the parser (#2323) - maprasterquery.c: Fix crash when queryies on done on raster layers with no styles (#2343) - maprasterquery.c: Modify msRASTERLayerOpen() to create a defaulted raster layer info if there isn't one, to avoid the errors about open only being supported after a query. Also wipe the raster layer info in case of an empty result set, or failures of a query to reduce likelyhood of leaking the raster layer info. - Improve out of memory handling in mapdrawgdal.c, and mapgd.c. (#2351) - Improve configuration logic for fastcgi (#2355). - WMS: image/wbmp should be image/vnd.wap.wbmp (#2360) - SOS: support maxfeatures for GetObservation requests (#2353) - mapdraw.c,mapquery.c: Reset layer->project flag for each full layer drawing or query so that need to reproject will be reconsidered (#673). - PHP MapScript: fix for getStdoutBufferString() and getStdoutBufferBytes() functions on win32 (#2401) - mapowscommon.c: fix namespace leak issues (#2375) - mapogcsos.c: add SWE DataBlock support (#2248) - mapogcsos.c: fix build warnings, namespace and schema pointers (#2248) - mappdf.c: support output in fastcgi case via msIO_fwrite() (#2406) - mapogcsos.c: Initial support for POST requests (#2379) and updated msSOSDispatch() handling - mapogr.cpp: Use pooling api to ensure per-thread sharing of connections only (#2408) - mapogcsos.c: change substituted variable from sensorid to procedure (#2409) - maplibxml2.c: Initial implementation of libxml2 convenience functions - configure: Modified so libxml2 support is requested for WCS and SOS, and is indicated by USE_LIBXML2 definition. Use @ALL_ENABLED@ in DEFINEs and mapscriptvars generation. - mapresample.c: Fixed support for multi-band data in RAW mode for bilinear and nearest neighbour resamplers (#2364). - mapdraw.c: Improve error reporting if a raster layer requested in a query map (#1842). - mapfile.c: add simple urn:ogc:def:crs:OGC::CRS84 support. Version 5.0.0 (2007-09-17) -------------------------- - AGG: Fix angle computation for truetype marker symbols on lines (#2316) - Fix support for bilinear resampling of raster data with AGG (#2303) Version 5.0.0-rc2 (2007-09-10) ------------------------------ - Prevent seg fault in msWMSLoadGetMapParams when request is missing (#2299) - Fixed calculation of scale in PHP MapScript mapObj.zoomScale() (#2300) - Fixed conflict between runtime substitution validation and qstring validation. - Fixed agg configure logic (now should work with --with-agg alone) (#2295) - Fixed interleaving of multi-band results for raster query (#2294). Version 5.0.0-rc1 (2007-09-05) ------------------------------ - Fixed "MinFeatureSize AUTO" labeling for polygon layers, works for polygon annotation layers too (#2232) - Fixed path following labels with short (2/3 character) strings (#2223) - AGG fix a bug when rendering polygons with tiled pixmaps - Added requirement to provide validation pattern for cgi-based attribute queries using the layer metadata key 'qstring_validation_pattern' (#2286) - Fixed msDebug causing a crash with VS2005 (#2287) - Added stronger checks on libpdf version in configure script (#2278) - Added msGetVersionInt() to MapScript (ms_GetVersionInt() in PHP) (#2279) - _isnan prototype for MSVC builds from #2277 - AGG: Fix a bug when rendering brushed lines with vector or pixmap symbols (artifacts could appear on outline) - AGG: Adjust symbol height when brushing a line with a vector symbol so that the line width isn't truncated - Only include process.h on win32 (non-cygwin) systems, moved from maptemplate.h to mapserver.h. (#2276) Version 5.0.0-beta6 (2007-08-29) -------------------------------- - Fixed problem with outline of polygons rendered twice with OGR STYLEITEM AUTO and AGG output (#2271) - Fixed problem compiling with only WMS/WFS client but none of the WMS, WFS, WCS or SOS server options enabled (#2272) - Fixed buffer overflow in handling of WMS SRS=AUTO:... (#1824) - AGG: render thick lines and polygon outlines with round caps and joins by default - Typo in mapfile writing (#2267) - Fixed mapping of class->keyimage in PHP MapScript (#2268) - Look for libagg under lib64 subdir as well in configure (#2265) - AGG: revert previous optimizations. now use caching of the rendering object to avoid the re-creation of some structures each time a shape is drawn - AGG: optimizations for faster rendering. we now do not initialize the font cache when no text is to be rendered - AGG: fixed rendering of polygons with holes (#2264) - AGG - raster layers: fix typo in mapresample.c that produced random background colors when using OFFSITE (#2263) - AGG: Fix a bug when rendering tiled polygons with truetype, pixmap or vector symbols (usually only affected bright colors) - Avoid passing null to msInsertHashTable in processLegendTemplate when layer.name or layer.group not specified (#2261) - Fixed problems with fonts in PDF output (#2142) - AGG: smooth font shadows Version 5.0.0-beta5 (2007-08-22) -------------------------------- - Fixed XSS vulnerabilities (#2256) - Allow building with AGG from source when libaggfontfreetype is missing. configure --with-agg=DIR now automatically tries to build agg_font_freetype.o from source if libaggfontfreetype is missing (#2215) - Fixed possible buffer overflow in template processing (#2252) - fix blending of transparent layers with RGBA images - AGG: speed up rendering of pixmap marker symbols - Implement OGR thread-safety via use of an OGR lock (#1977). - Fixed compile warnings (#2226) - Fixed mappdf.c compile warnings, PDF support was probably unusable before that fix (#2251) - Adding -DUSE_GENERIC_MS_NINT to the WIN64 builds (#2250) - Adding msSaveImageBuffer and use that function from the mapscript library instead of the renderer specific functions. (#2241) - Split each format into it's own element in WCS describe coverage results (#2244). - Support to run the mapscript c# examples on x64 platform (#2240) - Fixed problem introduced in 5.0.0-beta4: all HTML legend icons were empty white images (#2243) - Fixed WMS Client to always send STYLES parameter with WMS GetMap requests (#2242) - Fixed support for label encoding in SVG output (#2239) - Added support for label encoding in legend (#2239) - Fixed PHP MapScript layer->queryByAttributes() to not accept empty or null qitem arg (#480) - AGG: fixed incorrect rendering of pixmaps on MSB architectures (#2235) - Added layer.getFeature() in PHP MapScript with optional tileindex arg, and deprecated layer.getShape() to match what we had in SWIG (#900) - Added class.getTextString() and deprecated/renamed class.getExpression() and layer.getFilter() to class.getExpressionString() and layer.getFilterString() to match what we have in SWIG MapScript (#1892) Version 5.0.0-beta4 (2007-08-15) -------------------------------- - Updated msImageCreateAGG to only allow RGB or RGBA pixel models (#2231) - Fixed problem with symbol.setImagePath() when file doesn't exist (#1962) - Python MapScript failures (#2230) - msInsertLayer should not free the incoming layer anymore (#2229) - Include only parsed in the first mapfile (#2021) - Incorrect lookup of symbol in symbolset (#2227) - Mapfile includes and MapScript (#2089) - Fixed alignment of GetLegendGraphic output when mapfile contains no legend object (#966) - Fixed seg. fault when generaing HTML legend for raster layers with no classes (#2228). The same issue was also causing several Chameleon apps using HTML legend to seg fault (#2218) - Do not use case sensitive searches in string2list, which is used for msWhichItems (#2067) - Ensure that we can write AGG images with Python MapScript's write() method - Support unicode attributes for ArcSDE 9.2 and above (#2225) - GD: Truetype line symbolization should follow line orientation only if GAP is <=0 - AGG: Added truetype symbolization for lines and polygons - AGG: Draw an outline of size 1 of the fill color around polygons if an outlinecolor isn't specified (avoids faint outline) - Added summary of options at end of configure output (#1966) - Updated configure script to detect and require GEOS 2.2.2+ (#1896) - Renamed --enable-coverage configure option to --enable-gcov to avoid confusion with WCS or Arc/Info coverages (#2217) - Fixed --enable-gcov (formerly --enable-coverage) option to work with php_mapscript.so (#2216) - check for OGR support in if SLD is used (#1998) - msWMSLoadGetMapParams: fixed handling of required parameters (#1088) - if any of srs, bbox, format, width, height are NOT found, throw exception - if styles AND sld are NOT found, throw an exception - NOTE: this may cause issues with some existing clients who do not pass required parameters Version 5.0.0-beta3 (2007-08-08) -------------------------------- Known issues: - This beta contains significant improvements and fixes on the AGG rendering front. However some build issues remain on some platforms. Please see ticket #2215 if building with AGG support doesn't work with the default configure script: http://trac.osgeo.org/mapserver/ticket/2215 Bug fixes: - mapagg.cpp rewrite - the AGG renderer should now support all the GD features - Use AGG when requested for drawing the legend - Fixed problems with very large HTML legends producing no output (#1946) - Use OGR-specific destructors for objects that have them rather than 'delete' (#697) - Include style-related info in HTML legend icon filenames to solve issues with caching of icons when the class or style params are changed (#745) - Fixed issues with wms_layer_group metadata in WMS GetCapabilities (#2122) - Use msSaveImageBufferAGG for AGG formats in getBytes (#2205). - Make sure to emit $(AGG) to mapscriptvars because of conditional inclusion of stuct members to imageObj. (#2205) - Make imageextra field in imageObj not conditional (not #ifdef'ed) (#2205) - AGG/PNG and AGG/JPEG are the only valid agg drivers. Imagetypes aggpng24 and aggjpeg can be used to refer to the default output formats. (#2195) - Fix memory leak with labepath object (#2199) - Fix memory leak msImageTruetypePolyline (#2200) - SWF: Fix incorrect symbol assignements (#2198) - Fixed memory leaks in processing of WFS requests (#2077) - Avoid use of uninitialised memory in msCopySymbol() (#2194) Version 5.0.0-beta2 (2007-08-01) -------------------------------- - Oracle Spatial: Fixed some issues related with the maporaclespatial.c source code: warnings with calls in gcc 4.x versions (#1845), gtype translation error, generating memory problem (#2056), problems with items allocation (#1961 and #1736), and some memory-leaks errors (#1662). - AGG: Fixed a significant number of rendering issues including conflicts with OPACITY ALPHA and ANTIALIAS TRUE settings w/regards to polygon fills. Fixed ellipse and vector markers. Fixed AGG/GD alpha channel conflicts by writing conversion to/from functions. (#2191-partial, #2173, #2177) - SOS: Turn layer off if eventTime is not in the sos_offering_timeextent (#2154) - WFS: Correct bugs related to query by featureid support (#2102) - WMS: Add svg as a supported format for GetMap request (#1347) - WMS: Correct WMS time overriding Filter paramter (#1261) - Fix problem with LUT scaling ranges with explicit value for 255 (#2167). - WCS: Fixed resampling/reprojecting for tileindex datasets (#2180) - Fixed formatting of configure --help (#2182) - Fixed AGG configure option to use 'test -f' instead of 'test -e' which doesn't work on Solaris (#2183) - Fixed mapwms.c to support selecting AGG/ outputformats via FORMAT=. - Removed unused styleObj.isachild member (#2169) Version 5.0.0-beta1 (2007-07-25) -------------------------------- New features in 5.0: - MS RFC 19: Added Style and Label attribute binding - MS RFC 21: Raster Color Correction via color lookup table - MS RFC 27: Added label priority - MS RFC 29: Added dynamic charting (pie and bar charts) - MS RFC 31: New mechanism to load/set objects via URL using mapfile syntax - MS RFC 32: Added support for map rendering using the AGG library for better output quality Long time issues resolved in 5.0: - MS RFC 17: Use dynamic allocation for symbols, layers, classes and styles (got rid of the static limit on the number of instances of each in a map) - MS RFC 24: Improved memory management and garbage collection for MapScript - MS RFC 26: Terminology cleanup (layer transparency renamed to opacity, scale becomes scaledenom, symbol style becomes symbol pattern) - MS RFC 28: Enhanced the debug/logging mechanism to facilitate troubleshooting and tuning applications. Added support for multiple debug levels and more control on output location. Other fixes/enhancements in this beta: - Upgrade Filter encoding to use geos and support all missing operators (#2105) - Use of static color Palette support for gd output (#2096) - MapServer's main header file map.h has been renamed mapserver.h (#1437) - A mapserver-config script has been created - Single and double quotes escaping in string expressions used by FILTER. (Resolves tickets #2123 and #2141) - SLD: Support of Graphic Stroke for a Linesymbolizer (#2139) - GD : draw symbols along a line using pixmap symbols (#2121) - SVG : Polygons should not be filled if color is not given (#2055) - WMS : fixed request with a BBOX and and SLD containing Filter encoding (2079) - SWF : use highlight color from querymap (2074) - Support for embedding manifests as resources for the VS2005 builds. (ticket #2048) - Changed OGRLayerGetAutoStyle not to pass NULL pointer to GetRGBFromString causing access violation (bug 1950). - Fix SDE returning the row_id_column multiple times (bug 2040). - Fix text outline bug. (bug 2027) - Improve error reporting when OWS services are requested but the support is not compiled in. (bug 2025) - Fix support for OFFSITE for simple greyscale rasters (bug 2024). - [SLD] : Error on last class in raster class names based on the ColorMapEntry (bug 1844) - [Filter Encoding] : Check if Literal value in Filter is empty (bug 1995) - [SLD] : Else filters are now generated at the end of classes (bug 1925) - Enabled setting of a layer tileindex (e.g. map_layername_tileindex) via the CGI program. (bug 1992) - Added feature to the CGI to check runtime substitutions against patterns defined in layer metadata. (bug 1918) - Exposed label point computation to mapscript (bug 1979) - [SLD]: use the url as symbol name for external symbols (bug 1985) - [SLD] : support of mixing static text with column names (bug 1857) - maperror.c: fix for wrapping long in image errors, thanks to Chris Schmidt (bug 1963) - maperror.c: fix closing of stderr/stdout after writing error msg (bug 1970) - Preliminary implementation of RFC 21 (Raster Color Correction). - [SLD] : when reading an SLD, sequence of classes was reversed (Bug 1925) - Fixed a bug with SDE capability requests where we were double freeing because sde->row_id_column wasn't set to NULL in msSDELayerOpen - [OGC:SOS] : Fixed bugs realted to metadata and xml output (1731, 1739, 1740, 1741). Fixed bug with large xml output (bug 1938) - fixed performance problem in raster reprojection (bug 1944) - added msOWSGetLanguage function in mapows.c/h (bug 1955) - added mapowscommon.c/mapowscommon.h and updated mapogcsos.c to use mapowscommon.c functions (bug 1954) - added more Perl mapscript examples in mapscript/perl/examples/, most of which exemplify recently added GEOS functionality - php_mapscript.c: Fixed setRotation() method to check for MS_SUCCESS, not MS_TRUE (bug 1968) - mapobject.c: Fixed msMapSetExtent() to avoid trying to calcuate the scale if the map size hasn't been set yet (bug 1968) - mapobject.c: ensure msMapComputeGeotransform() returns MS_FAILURE, not MS_FALSE (bug 1968) - mapdraw.c: Actually report that we aren't configure with wms client support if that is why we can't draw a layer. - mapows.c: fixed XML error (bug 2070) - mapwms.c: Fixed text/plain output duplicate (bug 1379) - mapwms.c: Attribution element output in GetCapabilities only 1.0.7 and higher (bug 2080) - mapwms.c: UserDefinedSymbolization element output in GetCapabilities only 1.0.7 and higher (bug 2081) - mapwms.c: GetLegendGraphic and GetStyles only appear in 1.1.1 and higher responses (bug 1826) - mapwcs.c: - msWCSDescribeCoverage: throw Exception if Coverage doesn't exist (bug 649) - msWCSException: updated as per WCS 1.0 Appendix A.6 - mapogcsos.c: Added ability to output gml:id via MAP/LAYER/METADATA ows/sos/gml_featureid (bug 1754) - mapcontext.c: Added ogc namespace (#2002) - Note that starting with this release the source code is now managed in Subversion (SVN) instead of CVS and we have migrated from bugzilla to Trac for bug tracking. Version 4.10.0 (2006-10-04) --------------------------- - No source code changes since 4.10.0-rc1 Known issues in 4.10.0: - PHP5 not detected properly on Mandriva Linux (bug 1923) - Mapfile INCLUDE does not work with relative paths on Windows (bug 1880) - Curved labels don't work with multibyte character encodings (bug 1921) - Quotes in DATA or CONNECTION strings produce parsing errors (bug 1549) Version 4.10.0-RC1 (2006-09-27) ------------------------------- - SLD: quantity values for raster sld can be float values instead of just being integer - Hiding labelitemindex, labelsizeitemindex, labelangleitemindex from the SWIG interface (bug 1906) - Fixed computation of geotransform to match BBOX (to edges of image) not map.extent (to center of edge pixels). (bug 1916) - mapraster.c: Use msResampleGDALToMap() for "upside down" images. (bug 1904) Version 4.10.0-beta3 (2006-09-06) --------------------------------- - Web Map Context use format metadata when formatlist not available. (bug 1723) - Web Map Context boolean values true/false now interpreted. (bug 1692) - Added support for MULTIPOLYGON, MULTILINESTRING, and MULTIPOINT in msShapeFromWKT() when going through OGR (i.e. GEOS disabled) (bug 1891) - Fixed MapScript getExpressionString() that was failing on expressions longer that 256 chars (SWIG) and 512 chars (PHP). (bug 1428) - WMSSLD: use Title of Rule if Name not present (bug 1889) - Fixed syntax error (for visual c++) in mapimagemap.c. - Fixed mapgeos.c problems with multipoint and multilinestring WKT (bug 1897). - Implemented translation via OGR to WKT for multipoint, multiline and multipolygon (bug 1618) Version 4.10.0-beta2 (2006-08-28) --------------------------------- - Applied patch supplied by Vilson Farias for extra commas with imagemap output (bug 760). - Fixed possible heap overflow with oversized POST requests (bug 1885) - Set ./lib and ./include properly for MING support (bug 1866) - More robust library checking on OSX (bug 1867) - Removed mpatrol support (use valgrind instead for something similar and less intrusive). (bug 1883) - Added mapserver compilation flags to the SWIG c# command line (bug 1881) - Fix OSX shared library options for PHP (bug 1877). - Added setSymbolByName to styleObj for the SWIG mapscript in order to set both the symbol and the symbolname members (bug 1835) - Generate ogc filters now outputs the ocg name space (bug 1863) - Don't return a WCS ref in WMS DescribeLayer responses when layer type is CONNECTIONTYPE WMS (cascaded WMS layers not supported for WCS) (bug 1874) - Correct partly the problem of translating regex to ogc:Literal (bug 1644) - schemas.opengeospatial.net has been shutdown, use schemas.opengis.net instead as the default schema repository for OGC services (bug 1873) - MIGRATION_GUIDE.TXT has been created to document backwards incompatible changes between 4.8 and 4.10 - Modify mapgd.c to use MS_NINT_GENERIC to avoid rounding issues. (bug 1716) - added --disable-fast-nint configure directive (bug 1716) - Fixed php_mapscript Windows build that was broken in beta1 (bug 1872) - Supported tag in SLD label (Bug 1857) - Use the label element in the ColorMapEntry for the raster symbolizer (Bug 1844) - Adding Geos functions to php mapscript (bug 1327) - Added a type cast to msio.i so as to eliminate the warning with the SWIG unix/osx builds - Fixed csharp/Makefile.in for supporting the OSX builds and creating the platform dependent mapscript_csharp.dll.config file. - Fixed error in detection of libpdf.sl in configure.in (bug 1868). Version 4.10.0-beta1 (2006-08-17) --------------------------------- - Marking the following SWIG object members immutable (bug 1803) layerObj.metadata, classObj.label, classObj.metadata, fontSetObj.fonts, legendObj.label, mapObj.symbolset, mapObj.fontset, mapObj.labelcache, mapObj.reference, mapObj.scalebar, mapObj.legend, mapObj.querymap mapObj.web, mapObj.configoptions, webObj.metadata, imageObj.format, classObj.layer, legendObj.map, webObj.map, referenceMapObj.map labelPathObj was made completely hidden (according to Steve's suggestion) - Fixed problem with PHP MapScript's saveWebImage() filename collisions when mapscript was loaded in php.ini with PHP as an Apache DSO (bug 1322) - Produce warning in WFS GetFeature output if ???_featureid is specified but corresponding item is not found in layer (bug 1781). Also produce a warning in GetCapabilities if ???_featureid not set (bug 1782) - Removed the default preallocation of 4 values causing memory leaks. (related to bug 1801) Added initValues to achieve the similar functionality if needed. - Fixed error in msAddImageSymbol() where a symbol's imagepath was not set (bug 1832). - Added INCLUDE capability in mapfile parser (bug 279) - Revert changes to mapzoom.i that swapped miny and maxy (Bug 1817). - MapScript (swig) creation of an outputFormatObj will now set the inmapfile flag so that it gets written out to saved maps by default (Bug 1816). - Converted GEOS support to use the GEOS C-API (versiopn 2.2.2 and higher). Wrapped remaining relevant GEOS functionality and exposed via SWIG-based MapScript. - If a layer has wms_timedefault metadata, make sure it is applied even if there is no TIME= item in the url. (Bug 1810) - Support for GEOS/ICONV/XML2 use flags in Java Makefile.in (related to bug 1801) - Missing GEOS support caused heap corruption using shapeObj C# on linux (Bug 1801) - Fix time filter propogation for raster layers to their tileindex layers. New code in maprasterquery.c (bug 1809) - Added logic to collect LD_SHARED even if PHP not requested in configure. - Fix problems with msio/rfc16 stuff on windows. Don't depend on comparing function pointers or "stdio" handles. (mapio.c, mapio.h, msio.i) - Support WMC Min/Max scale in write mode (bug 1581) - Fixed leak of shapefile handles (shp/shx/dbf) on tiled layers (bug 1802) - Added webObj constructor and destructor to swig interface with calls to initWeb and freeWeb (bug 1798). - mapows.c: ensure msOWSDispatch() is always available even if there are no services to dispatch. This makes mapscript binding easier. - FLTAddToLayerResultCache wasn't properly closing the layer after it was done with it. - Added ability to encrypt tokens (passwords, etc.) in database connection strings (MS-RFC-18, bug 1792) - Fixed zoomRectangle in mapscript: miny and maxy were swapped, making it impossible to zoom by rect; also the error message was referring to the wrong rect. There were no open issues on bugzilla. Reverted because of 1817. - Implementation of RFC 16 mapio services (bug 1788). - Use lp->layerinfo for OGR connections (instead of ogrlayerinfo) (bug 331) - Support treating POLYGONZ as MS_SHAPE_POLYGON. (bug 1784) - Complete support for international languages in Java Mapscript (bug 1753) - Output feature id as @fid instead of @gml:id in WFS 1.0.0 / GML 2.1.2 GetFeature requests (bug 1759) - Allow use of wms/ows_include_items and wms/ows_exclude_items to control which items to output in text/plain GetFeatureInfo. Making the behavior of this INFO_FORMAT consistent with the new behavior of GML GetFeatureInfo output introduced in v4.8. (bug 1761) IMPORTANT NOTE: With this change if the *_include_items metadata is not specified for a given layer then no items are output for that layer (previous behavior was to always all items by default in text/plain) - Make sure mappostgis.c closes MYCURSOR in layer close function so that CLOSE_CONNECTION=DEFER works properly. (bug 1757) - Support large (>2GB) raster files relative to SHAPEPATH. (bug 1748) - Set User-Agent in HTTP headers of client WMS/WFS connections (bug 1749) - Detection of os-dependent Java headers for Java mapscript (bug 1209) - Preventing to take ownership of the memory when constructing objects with parent objects using C# mapscript (causing nullreference exception, Bug 1743) - SWF: Adding format option to turn off loading movies automatically (Bug 1696) - Fixed FP exception in mapgd.c when pixmap symbol 'sizey' not set (bug 1735) - Added config file for mapping the library file so the DllImport is looking for to its unix equivalent (Bug 1596) Thanks to Scott Ellington - Added /csharp/Makefile.in for supporting the creation of Makefile during configuration with MONO/Linux (fix for bug 1595 and 1597) - Added C# typemaps for char** and outputFormatObj** - Support for dispatching multiple error messages to the MapScript interface (bug 1704). - Fix inter-tile "cracking" problem (Bug 1715). - OGC FILTER: Correct bug when generating an sql expression containing an escape character. - Allow a user to set a PROCESSING directive for an SDE layer to specify using the attributes or spatial index first. (bug 1708). - Cheap and easy way of fudging the boundary extents for msSDEWhichShapes in the case where the rectangle is really a point (bug 1699). - Implement QUANTIZE options for GD/PNG driver (Bug 1690, Bug 1701). - WMS: Publish the GetStyles operation in the capabilities document. - PHP_MAPSCRIPT: Add antialias parameter in the style object (Bug 1685) - WFS: Add the possiblity to set wfs_maxfeatures to 0 (Bug 1678) - SLD: set the default color on the style when using default settings in PointSymbolizer. (bug 1681) - Incorporate range coloring support for rasters (bug 1673) - Fixed mapthread.c looking for the unix compiler symbol rather than just testing whether or not _WIN32 is defined for the usage of posix threads because unix is not defined on compilers like GCC 4.0.1 for OS X. - Fixed the fuzzy brush support so that the transition between 1 pixel aa lines and brushes is less obvious. The old code would not allow for a 3x3 fuzzy brush to be built. (bug 1659) - Added missing mapscript function msConnPoolCloseUnreferenced() (bug 1661) We need to make conn. pooling handling transparent to mapscript users so that they do not have to call this function once in a while, for instance by creating an evictor thread. - Added calls to msSetup/msCleanup() at MapScript load/unload time (bug 1665) - Reorganized nmake.opt to be more focused on functionality groups rather than the propensity of a section to be edited. Default values are now all set to be pointed at the MapServer Build Kit, which can be obtained at http://hobu.stat.iastate.edu/mapserver/ - configure.in/Makefile.in: Use PROJ_LIBS instead of PROJ_LIB. PROJ_LIB is sometimes defined in the environment, but points to $prefix/share/proj not the proj link libraries. - Update Web Map Context to 1.1.0, add the dimension support. (bug 1581) - Support SLD body in context document. (bug 887) - When generating an ogc filter for class regex expressions, use the backslah as the default escape character (Bug 1637) - Add connectiontype initialization logic when the layer's virtual table is initialized (Bug 1615) - Added modulus operator to mapparser.y. - Added new support for [item...] tag in CGI-based templates (bug 1636) - Reverted behaviour to pre-1.61: do not allow for use of the FILTERITEM attribute (bug 1629) - Treat classindex as an int instead of a char in resultCacheMemberObj to prevent problems with more than 128 classes (bug 1633) - WMS : SLD / stretch images when using FE (Bug 1627) - Add gml:lineStringMember in GML2 MultiLineString geometry (bug 1569). - PHP : add shape->sontainsshape that uses geos lib (Bug 1623). - Move gBYTE_ORDER inside the pg layerinfo structure to allow for differently byte ordered connections (bug 1587). - Fix the memory allocation bug in sdeShapeCopy (Bug 1606) - Fixed OGR WKT support (Bug 1614). - Added shapeObj::toWkt() and ms_shapeObjFromWkt() to PHP MapScript (bug 1466) - Finished implementation of OGR Shape2WKT function (Bug 1614). - Detect/add -DHAVE_VSNPRINTF in configure script and prevent systematic buffer overflow in imagemap code when vsnprintf() not available (bug 1613) - Default layer->project to MS_TRUE even if no projection is set, to allow geotransforms (nonsquare pixels, etc) to be applied (bug 1645). - Force stdin into binary mode on win32 when reading post bodies. (bug 1768) Version 4.8.0-rc2 (2006-01-09) ------------------------------ - Commit fix for GD on win32 when different heaps are in use. (Bug 1513) - Correct bound reprojection issue with ogc filer (Bug 1600) - Correct mapscript windows build problem when flag USE_WMS_SVR was not set (Bug 1529) - Fix up allocation of the SDE ROW_ID columns and how the functions that call it were using it. (bug 1605) - Fixed crash with 3D polygons in Oracle Spatial (bug 1593) Version 4.8.0-rc1 (2005-12-22) ------------------------------ - Fixed shape projection to recompute shape bounds. (Bug 1586) - Fixed segfault when copying/removing styles via MapScript. (Bug 1565) - Fixed segfault when doing attribute queries on layers with a FILTER already set but with no FILTERITEM. Version 4.8.0-beta3 (2005-12-16) -------------------------------- - Initialize properly variable in php mapscript (Bug 1584) - New support for pseudo anti-aliased fat lines using brushes with variable transparency. - Arbitrary rotation support for vector symbols courtesy of Map Media. - Support for user-defined mime-types for CGI-based browse and legend templates (bug 1518). - mapraster.c: Allow mapresample.c code to be called even if projections are not set on the map or layer object. This is no longer a requirement. (Bug 1562) - Fix problem with WMS 1.1.1 OGC test problem with get capabilites dtd (Bug 1576) - PDF : adding dash line support (Bug 492) - Fixed configure/build problem (empty include dir) when iconv.h is not found (bug 1419) - PDF : segfault on annotation layer when no style is set (Bug 1559) - PostGIS layer test cases and fix for broken views and sub-selects (bug 1443). - SDE: Removed (commented out) support for SDE rasters at this time. As far as I know, I'm the only one to ever get it to work, it hasn't kept up with the connection pooling stuff we did, and its utility is quite limited in comparison to regular gdal-based raster support (projections, resampling, etc) (HB - bug 1560). - SDE: Put msSDELayerGetRowIDColumn at the top of mapsde.c so things would compile correctly. This function is not included (or necessary) in the rest of the MS RFC 3 layer virtualization at this time. - WFS : TYPENAME is manadatory for GetFeature request (Bug 1554). - SLD : error parsing font parameters with the keyword "normal" (Bug 1552) - mapgraticule.c: Use MIN/MAXINTERVAL value when we define grid position and interval (bug 1530) - mapdrawgdal.c: Fix bug with nodata values not in the color table when rendering some raster layers (bug 1541). - mapogcsld.c : If a RULE name is not given, set the class name to "Unknown" (Bug 1451) Version 4.8.0-beta2 (2005-11-23) -------------------------------- - Use dynamic allocation for ellipse symbol's STYLE array, avoiding the static limitation on the STYLE argument values. (bug 1539) - Fix bug in mapproject.c when splitting over the horizon lines. - Fix Tcl mapscript's getBytes method (bug 1533). - Use mapscript.i in-place when building Ruby mapscript, copying not necessary (bug 1528). - Expose maximum lengths of layer, class, and style arrays in mapscript (bug 1522). - correct msGetVersion to indicate if mapserver was build with MYGIS support. - Fixed hang in msProjectRect() for very small rectangles due to round off problems (bug 1526). Version 4.8.0-beta1 (2005-11-04) -------------------------------- - Bug 1509: Fixed bounding box calculation in mapresample.c. The bottom right corner was being missed in the calculation. - MS RFC 2: added OGR based shape<->WKT implementation. - mapgdal.c: fixed some mutex lock release issues on error conditions. - MS RFC 8: External plugin layer providers (bug 1477) - SLD : syntax error when auto generating external symbols (Bug 1508). - MS RFC 3: Layer vtable architecture (bug 1477) - wms time : correct a problem when hadling wms times with tile index rasters (bug 1506). - WMS TIME : Add suuport for multiple interval extents (Bug 1498) - Removed deprecated --with-php-regex-dir switch (bug 1468) - support wms_attribution element for LAYER's (Bug 1502) - Correct php/mapscript bug : initialization of scale happens when preparequery is called (Bug 1334). - msProjectShape() will now project the lines it can, but completely delete lines that cannot be projected properly and "NULL" the shape if there are no lines left. (Bug 411) - Expose msLayerWhichShapes and msLayerNextShape in MapScript. (bug 1481) - Added support to MapScript to change images in a previously defined symbol. (bug 1471) - mapogcfiler.c : bug 1490. Crash when size of sld filters was huge. - Fixed --enable-point-z-m fix in configure.in (== -> =) (bug 1485). - Extra scalebar layer creation is prevented with a typo fix in mapscale.c. Good catch, Tamas (bug 1480). - mapwmslayer.c : use transparency set at the layer level on wms client layers (Bug 1458) - mapresample.c: added BILINEAR/AVERAGE resampling options. - mapfile.c: avoid tail recursion in freeFeatureList(). - maplegend.c: fixed leak of imageObj when embedding legends. - msGDALCleanup(): better error handler cleanup. - Modified msResetErrorList() to free the last error link too, to ensure msCleanup() scrubs all error related memory. - Fix in msGetGDALGetTransform() to use default geotransform even if GDALGetGeoTransform() fails but alters the geotransform array. - Typemaps for C# to enable imageObj.getBytes() method (bug 1389). - Enable -DUSE_ZLIB via configure for compressed SVG output (bug 1307). - maputil.c/msAddLine(): rewrite msAddLine() to call msAddLineDirectly, and use realloc() in msAddLineDirectly() to optimize growth of shapeObjs. (bug 1432) - msTmpFile: ensure counter is incremented to avoid duplicate temporary filenames. (bug 1312) - SLD external graphic symbol format tests now for mime type like image/gif instead of just GIF. (bug 1430) - Added support for OGR layers to use SQL type filers (bug 1292) - mapio/cgiutil - fixed POST support in fastcgi mode. (bug 1259) - mapresample.c - ensure that multi-band raw results can be resampled. (bug 1372) - Add support in OGC FE for matchCase attribute on PropertyIsEqual and PropertyIsLike (bug 1416) - Fixed sortshp.c to free shapes after processing to avoid major memory leak. (bug 1418) - fixed msHTTPInit() not ever being called which prevented msHTTPCleanup() from properly cleaning up cUrl with curl_global_cleanup(). (bug 1417) - mapsde.c: add thread locking in msSDELCacheAdd - fixed mappool.c so that any thread can release a connection, not just it's allocator. (bug 1402) - mapthread.c/h: Added TLOCK_SDE and TLOCK_ORACLE - not used yet. - Fixed copying of layer and join items. (bug 1403) - Fixed copying of processing directives within copy of a layer. (bug 1399) - Problems with string initialization. (bug 1312) - Fix svg output for multipolygons. (bug 1390) - Added querymapObj to PHP MapScript (bug 535) Version 4.6.0 (2005-06-14) -------------------------- - Bug 1163 : Filter Encoding spatial operator is Intersects and not Intersect. - Fixed GEOS to shapeObj for multipolgon geometries. Version 4.6.0-rc1 (2005-06-09) ------------------------------ - Bug 1375: Fixed seg fault in mapscript caused by the USE_POINT_Z_M flag. This flag was not carried to the mapscript Makefile(s). - Bug 1367: Fixed PHP MapScript's symbolObj->setPoints() to correctly set symbolObj->sizex/sizey - Bug 1373: Added $layerObj->removeClass() to PHP MapScript (was already in SWIG MapScript) Version 4.6.0-beta3 (2005-05-27) -------------------------------- - Bug 1298 : enable Attribution element in wms Capabilities XML - Bug 1354: Added a regex wrapper, allowing MapServer to build with PHP compiled with its builtin regex - Bug 1364: HTML legend templates: support [if] tests on "group_name" in leg_group_html blocks, and for "class_name" in leg_class_html blocks. - Bug 1149: From WMS 1.1.1, SRS are given in individual tags in root Layer element. - First pass at properly handling XML exceptions from CONNECTIONTYPE WMS layers. Still needs some work. (bug 1246) - map.h/mapdraw.c: removed MAX/MIN macros in favour of MS_MAX/MS_MIN. - Bug 1341, 1342 : Parse the unit parameter for DWithin filter request. Set the layer tolerance and toleranceunit with paramaters parsed. - Bug 1277 : Support of multiple logical operators in Filter Encoding. - mapwcs.c: If msDrawRasterLayerLow() fails, ensure that the error message is posted as a WCS exception. - Added experimental support for "labelcache_map_edge_buffer" metadata to define a buffer area with no labels around the edge of a map (bug 1353) Version 4.6.0-beta2 (2005-05-11) -------------------------------- - Bug 179 : add a small buffer around the cliping rectangle to avoid lines around the edges. - Finished code to convert back and forth between GEOS geometries. Buffer and convex hull operations are exposed in mapscript. - fontset.fonts hash now exposed in mapscript (bug 1345). - Bug 1336 : Retreive distance value for DWithin filter request done with line and polygon shapes/ - Bug 985 / 1015: Don't render raster layers as classified if none of the classes has an expression set (gdal renderer only). - Bug 1344: Fixed several issues in writing of inline SYMBOLS when saving mapfile (missing quotes around CHARACTER and other string members of SYMBOL object, check for NULLs, and write correct identifiers for POSITION, LINECAP and LINEJOIN). Version 4.6.0-beta1 (2005-04-26) -------------------------------- - Bug 1305: Added support for gradient coloring in class styles - Bug 1335 : missing call to msInitShape in function msQueryByShape - Bug 804 : SWF output : Make sure that the layer index is consistent when saving movies if some of the layers are not drawn (because the status is off or out of scale ...) - Bug 1332 - shptreevis.c: fixed setting of this_rec, as the output dbf file was not getting any records at all. - Fixed Makefile.vc to make .exe files depend on the DLL, so if the DLL fails to build, things will stop. Avoids the need for unnecessary cleans on win32. Also fixed the rule for MS_VERSION for mapscriptvars. - Bug 1262 : the SERVICE parameter is now required for wms and wfs GetCapbilities request. It is not required for other WMS requests. It is required for all WFS requests. - Bug 1302 : the wfs/ows_service parameter is not used any more. The service is always set to WFS for WFS layers. - Bug 791: initialize some fields in msDBFCreate() - avoids crashes in some circumstances. - Bug 1329 : Apply sld named layer on all layers of the same group - Bug 1328 : support style's width parameter for line and polygon layers. - Bug 564: Fixed old problem with labels occasionally drawn upside down - Bug 1325: php mapscript function $class->settext needs only 1 argument. - Bug 1319: Fixed mutex creation (was creator-owned) in mapthread.c. win32 issue only. - Bug 1103: Set the default tolerance value based on the layer type. The default is now 3 for point and line layers and 0 for all the others. - Bug 1244: Removing Z and M parameter from pointObj by default. A new compilation option is available to active those option --enable-point-z-m. This gives an overall performance gain around 7 to 10%. - Bug 1225: MapServer now requires GD 2.0.16 or more recent - MapScript: shapeObj allocates memory for 4 value strings, shapeObj.setValue() lets users set values of a shapeObj. - MapScript: imageObj.getBytes() replaces imageObj.write() (bugs 1176, 1064). - Bug 1308: Correction of SQL expression generated on wfs filters for postgis/oracle layers. - Bug 1304: Avoid extra white space in gml:coordinates for gml:Box. - mapogr.c: Insure that tile index reading is restarted in msOGRLayerInitItemInfo() or else fastcgi repeat requests for a layer may fail on subsequent renders. - mapogr.c: Set a real OGRPolygon spatial filter, not just an OGRLinearRing. Otherwise GEOS enabled OGR builds will do expensive, and incorrect Intersects() tests. - mapogr.cpp / mapprimitive.c: Optimize msAddLine() and add msAddLineDirectly() - mapprimitive.c: Optimizations in msTransformShapeToPixel() (avoid division) - map.h: Made MS_NINT inline assembly for win32, linux/i86. - mapprimitive.c: optimized msClipPolygonRect and msClipPolylineRect for case where the shape is completely inside the clip rect. - Add support for SVG output. See Bug 1281 for details. - Bug 1231: use mimetype "image/png; mode=24bits" for 24bit png format. This makes it seperately selectable by WMS. - Bug 1206: Applied locking patch for expression parser for rasters. - Bug 1273: Fixed case in msProjectPoint() were in or out are NULL and a failure occurs to return NULL. Fixed problem of WMS capabilities with 'inf' in it. - SLD generation bug 1150 : replacing tag to - Fixed bug 1118 in msOWSGetLayerExtent() (mapows.c). - Fixed ogcfilter bug #1252 - Turned all C++ (//) comments into C comments (bug 1238) - mapproject.h/configure.in: Don't check for USE_PROJ_API_H anymore. Assume we have a modern PROJ.4. - Bug 839: Fix memory leak of font name in label cache (in mapfile.c). - Added msForceTmpFileBase() and mapserv -tmpbase switch to allow overriding temporary file naming conventions. Mainly intended to make writing testscripts using mapserv easier. FrankW. - maporaclespatil.c: Bug fix for: #1109, #1110, #1111, #1112, #1136, #1210, #1211, #1212, #1213. Support for compound polygons, fixed internal sql to stay more accurate for geodetic data, added the support for getextent function. Added VERSION token for layer data string. - mapimagemap.c: Preliminary implementation of support for emitting MS_SYMBOL_VECTOR symbols in msDrawMarkerSymbolIM(). - Bug 1204: Added multi-threading support in mapthread.c. List of connections is managed within a mutex lock, and connections are only allowed to be used by one thread at a time. - Bug 1185 : php/mapscript : add constant MS_GD_ALPHA - Bug 1173: In HTML legend, added opt_flag support for layer groups. - Bug 1179: added --with-warnings configure switch, overhauled warning logic. - Bug 1168: Improve autoscaling through classification rounding issues. - Fixed bug writing RGB/RGBA images via GDAL output on bigendian systems. - Bug 1152 : Fix WMS style capabilities output for FastCGI enabled builds. - Bug 1135 : Added support for rotating labels with the map if they were rendered with some particular angle already. - Bug 1143 : Missing call to msInitShape. - Fixed PHP5 support for windows : Bug 1100. - Correct bug 1151 : generates twice a tag when generating an SLD. This was happening the style did not have a size set. - Oracle Spatial. Fixed problem with LayerClose function. Added token NONE for DATA statement. Thanks Valik with the hints about the LayerClose problem and Francois with the hints about NONE token. - numpoints and stylelength memebers of the symbol object needs to be in sync with the low level values after calles to setpoints ans setstyle (Bug 1137). - Use doubles instead of integers in function php3_ms_symbol_setPoints (Bug 1137). - Change the output of the expression when using a wild card for PropertyIsLike (Bug 1107). - Delete temporary sld file created on disk (Bug 1123) - Fixed msFreeFileCtx() to call free() instead of gdFree() as per bug 1125. Also renamed gdFreeFileCtx() to msFreeFileCtx(). - Ensure error stack is cleared before accepting another call in FastCGI mode in mapserv.c. Bug 1122 - Support translation of all geometry types to points in mapogr.cpp (now also supports multipolygon, multilinestring and geometrycollection. bug 1124. - Added support for passing OGR layer FILTER queries down to OGR via the SetAttributeFilter() method if prefixed with WHERE keyword. Bug 1126. - Fixed support for SIZEUNITS based scaling of text when map is rotated. Bug 1127. Version 4.4.0 (2004-11-29) -------------------------- - Fixed WMS GetCapabilities 1.1.0 crash when wms_style_<...>_legendurl_* metadata were used (bug 1096) - WCS GetCapabilities : Added ResponsibleParty support. - WMS GetCapabilities : Service online resource was not url encoded (bug 1093) - Fixed php mapscript problem with wfs_filter selection : Bug 1092. - Fixed encoding problem with WFS server when wfs_service_onlineresource was not explicitly specified (bug 1082) - Add trailing "?" or "&" to connection string when required in WFS client layers using GET method (bug 1082) - Fixed : SLD rasters was failing when there was Spatial Filter (Bug 1087) - Fixed mapwfslayer.c build error when WFS was not enabled (bug 1083) - Check that we have vsnprintf in mapimagemap.c before using it. Version 4.4.0-beta3 (2004-11-22) -------------------------------- - Added tests to mimimize the threat of recursion problems when evaluating LAYER REQUIRES or LABELREQUIRES expressions. Note that via MapScript it is possible to circumvent that test by defining layers with problems after running prepareImage. Other things crop up in that case too (symbol scaling dies) so it should be considered bad programming practice (bug 1059). - Added --with-sderaster configure option. - Make sure that msDrawWMSLayerLow calls msDrawLayer instead of msDrawRasterLayerLow directly ensuring that some logic (transparency) that are in msDrawLayer are applied (bug 541). - Force GD/JPEG outputFormatObjects to IMAGEMODE RGB and TRANSPARENT OFF if they are RGBA or ON. Makes user error such as in bug 1703 less likely. - Advertize only gd and gdal formats for wms capabilities (bug 455). - Pass config option GML_FIELDTYPES=ALWAYS_STRING to OGR so that all GML attributes are returned as strings to MapServer. This is most efficient and prevents problems with autodetection of some attribute types (bug 1043). - msOGCWKT2ProjectionObj() now uses the OGRSpatialReference::SetFromUserInput() method. This allows various convenient setting options, including the ability to handle ESRI WKT by prefixing the WKT string with "ESRI::". - Fixed GetLegendGraphic in WMS Capabilities that were missing the '?' or '&' separator if it was not included in wms_onlineresource (bug 1065). - Updated WMS/WFS client and server code to lookup "ows_*" metadata names in addition to the default "wms_*" (or "wfs_*") metadatas (WCS was already implemented this way). This reduces the amount of duplication in mapfiles that support multiple OGC interfaces since "ows_*" metadata can be used almost everywhere for common metadata items shared by multiple OGC interfaces (bug 568). - Added ows_service_onlineresource metadata for WMS/WFS to distinguish between service and GetMap/Capabilities onlineresources (bug 375). - Added map->setSize() to PHP MapScript (bug 1066). - Re-enabled building PHP MapScript using PHP's bundled regex/*.o. This is needed to build in an environment with PHP configured as an Apache DSO (bugs 990, 520). - Fixed problem with raster dither support on windows (related to ascii encoding pointers) (bug 722). - Moved PHP/SWIG MapScript layer->getExtent() logic down to msLayerGetExtent() to avoid code duplication (bug 1051). - Added SDE Raster drawing support (experimental). - HTML legends: Added [leg_header_html] and [leg_footer_html] (bug 1032). - Added "z" support in SWIG MapScript for pointObj (bug 871). - In PHP Mpascript when using ms_newrectobj, the members minx, miny, maxx, maxy are initialized to -1 (bug 788). - Write out proper world file with remote WMS result, it was off by half a pixel (bug 1050). - Send a warning in the wms capabilities if the layer status is set to default (bug 638). - Fixed PHP MapScript compile warnings: dereferencing type-punned pointer will break strict-aliasing rules (bug 1053). - Added $layer->isVisible() to PHP MapScript (bug 539). - Ported $layer->getExtent() to PHP MapScript (bug 826). - wms_group_abstract can now be used in the capabilities (bug 754). - If wms_stylelist is an empty string, do not output the tag for MapContexts (bug 595). - Avoid passing FILE* to GD library by utilizing GD's gdIOCtx interface (bug 1047). - Output warning in wms/wfs capabilities document if layer,group,map names have space in them (bug 486, bug 646). - maporaclespatial.c: fixed declarations problems (bug 1044). - Allow use of msOWSPrintURLType with no metadata. In this case the default parameters will be used (bug 1001). - Ensure the outputFormatObj attached to msImageLoadGDStream() results reflect the interlacedness of the loaded image. Also ensure that the RGB PNG reference images work (make imagemode match gdImg) (bug 1039). - Fixed support for non-square pixels in WCS (bug 1014). - Expose only GD formats for GetLegendGraphic in the capabilities (bug 1001). - Check for supported formats when process a GetLegendGraphic request (bug 1030). - mapraster.c: fixed problem with leaks in tileindexed case where the tile index is missing (bug 713). - Oracle Spatial: implemented connection pool support for Oracle Spatial. New layer data parameters to support query functions, added "using unique ". Added "FILTER", "RELATE" and "GEOMRELATE" parameters, now permit users to choose the Oracle Spatial Filter. Modified the internal SQL to always apply FILTER function. And improve the Oracle Spatial performance. - Centralize "stdout binary mode setting" for win32 in msIO_needBinaryStdout(). Use it when writing GDAL files to stdout in mapgdal.c. Fixes problems with output of binary files from GDAL outputformat drivers on win32 via WMS/WCS. - MapServer now provides one default style named (default), title and LegendURL when generating capabilities. Added also the possibility to use the keyword default for STYLES parameter when doing a GetMap (..&STYLES=default,defeault,...) (bug 1001). - Add xlink:type="simple" in WMS MetadataURL (bug 1027). Version 4.4.0-beta2 (2004-11-03) -------------------------------- - free mapServObj properly in mapserv.c in OWS dispatch case to fix minor memory leaks. - modified msCloseConnections() to also close raster layers so that held raster query results will be freed. - modified raster queries to properly set the classindex in the resultcache. - modified msDrawQueryCache() to be very careful to not try and lookup information on out-of-range classindex values. This seems to occur when default shapes come back witha classindex of 0 even if there are no classes. (ie. raster query results). - the loadmapcontext function has changed it behaviour. Before the 4.4 relase when loading layers from a map context, the layer name was built using a unique prefix + the name found in the context (eg for the 2nd layer in map context named park, the layer name generated would possibly be l:2:park). Now the loadmapcontext takes a 2nd optional argument to force the creation of the unique names. The default behaviour is now to have the layer name equals to the name found in the context file (bug 1023). - Fixed problem with WMS GetCapabilities aborting when wms_layer_group is used for some layers but not for all (bug 1024). - Changed raster queries to return the list of all pixel values as an attribute named "value_list" rather than "values" to avoid conflict with special [values] substitution rule in maptemplate.c. - Fixed raster queries to reproject results back to map projection, and to do point queries distance checking against the correct projection (bug 1021). - Get rid of WMS 1.0.8 support. It's not an officially supported verison of the spec anyway: it's synonymous for 1.1.0 (bug 1022). - Allow use of '=' inside HTML template tag parser (bug 978). - Use metadata ows_schema_location for WMS/WFS/WCS/SLD (bugs 999, 1013, 938). The default value if metadata is not found is http://schemas.opengeospatial.net. - Generate a RULE tag when generating an SLD (bug 1010). - WMS GetLegendGraphic uses now the RULE value to return an icon for a class that has the same name as the RULE value (bug 843). - Add msOWSPrintURLType: This funciton is a generic URL printing fuction for OGC specification metadata (WMS, WFS, WCS, WMC, etc.) (bug 944). - Support MetadataURL, DataURL and LegendURL tags in WMS capabilities document and MetadataURL in WFS capabilities. - SWIG mapscript: clone methods for layerObj, classObj, styleObj (bug 1012). - Implemented an intarray helper class for SWIG mapscript which allows for multi-language manipulation of layer drawing order (bugs 853, 1005). - Fixed WMS GetLegendGraphic which was returning an exception (GD error) when requested layer was out of scale (bug 1006). - Fixed maplexer.l to work with flex 2.5.31 (bug 975). - WMS GetMap requests now have MS_NONSQUARE enabled by default. This means that if the width/height ratio doesn't match the extent's x/y ratio then the map is stretched as stated in the WMS specification (bug 862). - In WMS, layers with no explicit projection defined will receive a copy of the map's projectionObj if a new SRS is specified in the GetMap request or if MS_NONSQUARE is enabled. This will prevent the problem with layers that don't show up in WMS request when the server administrator forgets to explicitly set projections on all the layers in a WMS mapfile (bug 947). - Implemented FastCGI cleanup support for win32 and unix in mapserv.c. - Solved configure/compile issues with libiconv (bugs 909, 1017). Version 4.4.0-beta1 (2004-10-21) -------------------------------- - "shared" compilation target now supports some kind of versioning, should at least prevent libmap.so version collisions when upgrading MapServer on a server (bug 982). - When no RULE parameter has been specified in the WMS request a legend should be returned with all classes for the specified LAYER. Changes has been made in mapwms.c (bug 653). Also if the SCALE parameter is provided in the WMS request is will be used to determine whether the legend of the specified layer should be drawn in the case that the layer is scale dependant (big 809). - Nested layers in the capabilities are supported by using a new metadata tag WMS_LAYER_GROUP (bug 776). - Added greyscale+alpha render support if mapdrawgdal.c (bug 965). - Added --with-fastcgi support to configure. - support OGC mapcontext through mapserver cgi (bug 946). - support for reading 3d shape file (z) (bug 869). - add php mapscript functions to expose the z element (bug 870). - imageObj::write() method for SWIG mapscript (bug 941). - Protect users from 3 potential sources of threading problems: parsing expression strings outside of msLoadMap, evaluating mapserver logical expressions, and loading symbol set files outside of msLoadMap (bug 339). - Various fixes allowing unit tests to run leak free under valgrind on i686. Memory is now properly freed when exiting from common error states (bug 927). - Restored ability to render transparent (indexed or alpha) pixmap symbols on RGB map images, including annotation layers and embedded scalebars. This feature remains OFF by default for map layers and is enabled by specifying TRANSPARENCY ALPHA (bugs 926, 490). - mapserv_fcgi.c removed. Committed new comprehensive FastCGI support. - New mapserver exceptions for Java mapscript thanks to Umberto Nicoletti (bug 895). - Removed mapindex.c, mapindex.h, shpindex.c components of old unused shapefile indexing method. - Use the symbol size instead of 1 for the default style size value. This is done by setting the default size to -1 and adding msSymbolGetDefaultSize() everywhere to get the default symbolsize (Bug 751). - Correct Bug with GML BBOX output when using a with a GetFeature request (Bug 913). - Encode all metadatas and mapfile parameters outputed in a xml document (Bug 802). - Implement the ENCODING label parameter to support internationalization. Note this require the iconv library (Bug 858). - New and improved Java mapscript build provided by unicoletti@prometeo.it and examples by Y.K. Choo (bug 876). - MapContext: Cleanup code to make future integration more easily and output SRS and DataURL in the order required by the spec. - Fixed issue with polygon outline colors and brush caching (bug 868). - New C# mapscript makefiles and examples provided by Y.K. Choo committed under mapscript/csharp/ (bug 867). - Renamed 'string' member of labelCacheMemberObj to 'text' to avoid conflicts in SWIG mapscript with C# and Java types (bug 852). - Fixed Bug 866 : problem when generating an sld on a pplygon layer - SWIG mapscript: map's output image width and height should be set simultaneously using new mapObj::setSize() method. This performs necessary map geotransform computation. Direct setting of map width and height is deprecated (bug 836). - Fixed bug 832 (validate srs value) : When the SRS parameter in a GetMap request contains a SRS that is valid for some, but not all of the layers being requested, then the server shall throw a Service Exception (code = "InvalidSRS"). Before this fix, mapserver use to reproject the layers to the requested SRS. - Fixed bug 834: SE_ROW_ID in SDE not initialized for unregistered SDE tables - Fixed bug 823 : adding a validation of the SRS parameter when doing a GetMap request on a wms server. Here is the OGC statement : 'When the SRS parameter in a GetMap request contains a SRS that is valid for some, but not all of the layers being requested, then the server shall throw a Service Exception (code = "InvalidSRS").' - Set the background color of polygons or circles when using transparent PIXMAP symbol. - SWIG mapscript class extensions are completely moved from mapscript.i into separate interface files under mapscript/swiginc. - Overhaul of mapscript unit testing framework with a comprehensive test runner mapscript/python/tests/runtests.py. - Modified the MS_VALID_EXTENT macro to take an extent as its argument instead of the quartet of members. MapServer now checks that extents input through the mapfile are valid in mapfile.c (web, map, reference, and layer). Modified msMapSetExtent in mapobject.c to use the new macro instead of its home-grown version. Modified all cases that used MS_VALID_EXTENT to the new use case. - Layers now accept an EXTENT through the mapfile (bug 786). Nothing is done with it at this point, and getExtent still queries the datasource rather than getting information from the mapfile-specified extent. - Fixed problem with WMS GetFeatureInfo when map was reprojected. Was a problem with msProjectRect and zero-size search rectangles (bug 794) - MapServer version now output to mapscriptvars and read by Perl Makefile.PL and Python setup.py (bug 795). - Map.web, layer, and class metadata are exposed in SWIG mapscript as first-class objects (bug 737). - Add support for spatial filters in the SLD (Bug 782) - A few fixes to allow php_mapscript to work with both PHP4 and PHP5. PHP5 support should still be considered experimental. (bug 718) - Fixed SDE only recognizing SE_ROW_ID as the unique column (bug 536). The code now autosenses the unique row id column. - Enhanced SDE support to include support for queries against user-specified versions. The version name can be specified as the last parameter of the CONNECTION string. - Fixed automated generation of onlineresource in OWS GetCapabilities when the xxx_onlineresource metadata is not specified: the map= parameter used to be omitted and is now included in the default onlineresource if it was explicitly set in QUERY_STRING (bug 643) - Fixed possible crash when producing WMS errors INIMAGE (bug 644) - Fixed automated generation of onlineresource in OWS GetCapabilities when the xxx_onlineresource metadata is not specified: the map= parameter used to be omitted and is now included in the default onlineresource if it was explicitly set in QUERY_STRING (bug 643) - Fixed an issue with annotation label overlap. There was an issue with the way msRectToPolygon was computing it's bounding box. (bug 618) - Removed "xbasewohoo" debug output when using JOINs and fixed a few error messages related to MySQL joins (bug 652) - Fixed "raster cracking" problem (bug 493) - Improvements to Makefile.vc, and nmake.opt so that a mapscriptvars file can be produced on windows. - Updated setup.py so Python MapScript builds on win32. - Added preliminary raster query support. - No more Python-stopping but otherwise benign errors raised from msDrawWMSLayer() (bug 650). - Finished prototyping all MapServer functions used by SWIG-Mapscript and added 'void' to prototypes of no-arg functions, eliminating all but two SWIG-Mapscript build warnings (bug 658). - Mapscript: resolved issue with pens and dynamic drawing of points (bug 663). - Mapscript: fixes to tests of shape copying and new image symbols. - Mapscript: new OWSRequest class based on cgiRequestObj structure in cgiutil.h is a first step to allow programming with MapServer's OWS dispatching (bug 670). - Mapscript: styles member of classObj structure is no longer exposed to SWIG (bug 611). - Implementation geotransform/rotation support in cgi core, and mapscript.i. - Testing: fixed syntax error, 'EPSG' -> 'epsg' in test.map (bug 687). Added an embedded scalebar which demonstrates that bug 519 is fixed. The test data package is also made more complete by including two fonts from Bitstream's open Vera fonts (bug 694). - Mapscript (SWIG): remove promote and demote methods from layerObj. Use of container's moveLayerUp/moveLayerDown is better, and this brings the module nearer to PHP-Mapscript (bug 692). - mapogr.cpp: Now echos CPLGetLastErrorMsg() results if OGR open fails. - mapraster.c: fixed tile index corruption problem (bug 698) - Mladen Turk's map copying macros in mapcopy.h clean up map cloning and allow for copying of fontset and symbolset. Added cloning tests in python/tests/testCloneMap.py and refactored testing suite (bugs 640 & 701). - Mapscript: removing obsolete python/setup_wnone.py file. - CONFIG MS_NONSQUARE YES now enables non-square pixel mode (mostly for WMS). Changes in mapdraw.c (msDrawMap()) to use the geotransform "hack" to allow non-square pixels. - When using the text/html mime type in a GetFeature request, if the layer's template is not set to a valid file, errors occur. Correction is : the text/html is not advertized by default and will only be advertized if the user has defined "WMS_FEATURE_INFO_MIME_TYPE" "text/html" (bug 736) - Make PHP MapScript's layer->open() produce a PHP Warning instead of a Fatal error (bug 742) - MapServer hash tables are now a structure containing a items pointer to hashObj. See maphash.h for new prototypes of hash table functions. In SWIG mapscript, Map, Layer, and Class metadata are now instances of the new hashTableObj class. fontset.fonts and Map.configoptions are also instances of hashTableObj. The older getMetaData/setMetaData and metadata iterator methods can be deprecated (bug 737). - Mapscript-SWIG: made the arguments of mapObj and layerObj constructors optional. A layerObj can now exist outside of a map and can be added to a mapObj using the insertLayer method. mapObj.removeLayer now returns a copy of the removed Layer rather than an integer (bug 759). - Fixed $map->processTemplate() which was always returning NULL. Bug introduced in version 4.0 in all flavours of MapScript (bug 410) Version 4.2-beta1 (2004-04-17) ------------------------------ - Added support for WMS 1.1.1 in the WMS interface. - Added support for WMS-SLD in client and server mode. - Added support for attribute filters in the WFS interface. - WMS Interface: several fixes to address issues found in running tests against the OGC testsuite. One of the side-effects is that incomplete GetMap requests that used to work in previous versions will produce errors now (see bug 622). - Modified configure scripts to be able to configure/build PHP MapScript using an installed PHP instead of requiring the full source tree. - Added ability to combine multiple WMS connections to the same server into a single request when the layers are adjacent and compatible. (bug 116) - Support POSTed requests without Content-Length set. - Added support for proper classification of non-8bit rasters. - Added support for BYTE rawmode output type. - Added support for multiple bands of output in rawmode. - MySQL joins available - Fixed problems with detection of OGRRegisterAll() with GDAL 1.1.9 in configure due to GDAL's library name change. Fixed a few other minor issues with GDAL/OGR in configure. - Modified configure to disable native TIFF/PNG/JPEG/GIF support by default if GDAL is enabled. You can still enable them explicitly if you like. - Replace wms_style_%s_legendurl, wms_logourl, wms_descriptionurl, wms_dataurl and wms_metadataurl metadata by four new metadata by metadata replaced. The new metadata are called legendurl_width, legendurl_height, legendurl_format, legendurl_href, logourl_width, etc... Old dependancy to the metadata with four value in it , space separated, are not kept. - Implement DataURL, MetadataURL and DescriptionURL metadata in mapcontext.c (bug 523) - PHP MapScript's pasteImage() now takes a hex color value (e.g. 0xrrggbb) for the transparent color instead of a color index. (bug 463) - OGR data sources with relative paths are now checked relative to SHAPEPATH first, and if not found then we try again relative to the mapfile location. (bug 295) - There is a new mapObj parameter called MAXSIZE to control maximum image size to serve via the CGI and WMS interfaces. The default is 2048 as before but it can be changed in the map file now. (bug 435) - Added simple dataset for unit and regression tests (bug 453) - PostGIS: added postresql_NOTICE_HANDLER() sending output via msDebug() and only when layer->debug is set (bug 418) - Added Apache version detection in configure and added non-blocking flag on stderr in msDebug() to work around Apache 2.x bug (bug 458) - MapScript rectObj: added optional bounding value args to constructor and extended rectObj class with a toPolygon method (bug 508). - MapScript pointObj: added optional x/y args to constructor (bug 508). - MapScript colorObj: added optional RGB color value args to colorObj constructor, and extended colorObj class with setRGB, setHex, and toHex methods. The hex methods use hex color strings like '#ffffff' rather than '0xffffff' for compatibility with HTML (bug 509). - MapScript outputFormatObj: extended with a getOption method (bug 510). - MapScript imageObj: added optional mapObj argument to the save method resolving bug 549 without breaking current API. Also added optional driver and filename arguments to constructor which allows imageObj instances to be created with a specified driver or from files on disk (bug 530). Added new code to Python MapScript which extends the filename option to Python file-like objects (bug 550). This means StringIO and urllib's network objects! - MapScript classObj and styleObj: added a new styleObj shadow class and extended classObj with getStyle, insertStyle, and removeStyle methods. MapScript now supports multiple styles for dynamically created classes (bug 548). - MapScript layerObj: added getExtent, getNumFeatures extension methods, allowing getShape to access inline features (bug 562). - Added fixes for AMD64/Linux in configure (bug 565) - Removed OGR_STATIC stuff in configure script that used to allow us to build with OGR statically by pointing to the OGR source tree. That means you can only build with OGR when *installed* as part of GDAL, but that's what everyone is doing these days anyway. - Mapscript outputFormatObj: extended constructor to allow format names, and mapObj methods to append and remove output formats from the outputformatlist (bug 511). - New SWIG mapscript development documentation in the spirit of the PHP-Mapscript readme file, but using reST (bug 576). - Paving way for future changes to SWIG mapscript API with new features enabled by NEXT_GENERATION_API symbol (bug 586). - Added ability to set string member variables to NULL in PHP MapScript (bug 591) - New key iterators for map, layer, and class metadata hash tables (bug 434) and fontset fonts hash table (bug 439). - Fixed potential crash when using nquery with a querymap enabled and some layers have a template set at the layer level instead of inside classes (bug 569). - New CONFIG keyword in the MAP object in a .map file to be used to set external configuration parameters such as PROJ_LIB and control of some GDAL and OGR driver behaviours (bug 619) Version 4.0 (2003-08-01) ------------------------ - Fixed problem with truncated expressions (bugs 242 and 340) - Attempt at fixing GD vs libiconv dependency problems (bug 348) - Fixed problem with invalid BoundingBox tag in WMS capabilities (bug 34) - Fixed problems with SIZEUNITS not working properly (bug 373) - Fixed MacOSX configure problems for linking php_mapscript (bug 208) - Fixed problem with reference map marker symbol not showing up (bug 378) - Use in WMS 1.0.0 capabilities instead of (bug 129) - One-to-one and one-to-many joins now work for Xbase files and are available to query templates. Low level one-to-one Xbase joins are available via OGR. Version 4.0-beta2 (2003-07-11) ------------------------------ - Added prototype of FastCGI support in mapserv_fcgi.c (not built by default). - Report full error stack in the mapserv CGI and PHP MapScript (bug 346) - Old index (.qix) format is deprecated (bug 273) - Fixed problem with embedded legend and scalebar that would result in layers being added to the HTML legends (bug 171) - Changed joins (XBase only at this point) over to the open-prepare-next... next-close way of doing things. Compiles fine, but needs more testing. One-to-many support should work now but it needs to be hooked into the template code yet. Last thing before a candidate 4.0 release. - Added ability to generate images in MapScript processQueryTemplate (bug 341) - Added saving of output formats in msSaveMap() - Fixed problem in PHP MapScript with variables that were not dereferenced before their values were changed by the MapScript wrappers (bug 323) - Added support for Web Map Context 1.0.0 - Treat zero-length template values as NULL so that it's possible to set("template", "") from MapScript to make layer non-queryable (bug 338) - Ditched the shapepath argument to the shapefileObj constructor - CARTOLINE join style default changed to MS_CJC_NONE - Tweaked code in legend builder to handle polygon layers slightly different. Now if a polygon layer contains only outlines and no fills (i.e. a polyline) then it is drawn using the zigzag legend shape rather than the box. I'll add legend outlines back in shortly. - Restored legend key outlines (triggered by setting OUTLINECOLOR). If an outline is requested then line symbols are clipped to the outline, otherwise lines are allowed to bleed a pixel or two beyond those boundaries- for most cases this looks fine but for fat lines it is gonna look goofy regardless. In those cases use the KEYIMAGE. - Fixed a bug in the scanline writer so that x coordinates can be in any order when passed in to the function. (bug 336) - Updated loadExpressionString in mapfile.c to be a bit more tolerant of input. Now if a string does not match the logical or regex pattern it is automatically cast as a string expression. Removes the need for silly quotes. Version 4.0-beta1 (2003-06-06) ------------------------------ - Added imagemap outputformat, which makes possible use of client-side imagemaps in browsers. - Added MySQL support for non-spatial OpenGIS Simple Features SQL stored data - msQueryByShape and msQueryByFeature honor layer tolerances. In effect you can to buffered queries now. At the momoment only polygon select features are supported, but there's nothing inherent in the underlying computations that says lines won't work as well. - Simple one-to-one joins are working again. Reworked the join code so that table connections are persistant within a join (across joins is a todo). Joins, like layers are wrapped with a connection neutral front end, that sets us up to do MySQL or whatever in addition to XBase. - Removed shapepath argument to all layer access functions (affects MapScript). It's still used but we leverage the layer pointer back to the parent mapObj so the API is cleaner. - Changed default presentation of feature attributes to escape a few problematic characters for HTML display (eg. > becomes >). Added [itemname_raw] substitution to allow access to unaltered data. - Added initial version of Jan Hartman's connection pooling code. - Replaced libwww with libcurl for WMS/WFS client HTTP requests. (libcurl 7.10 required, see http://curl.haxx.se/libcurl/c/) - Added CONNECTION to the list of mapfile parameters that can accept %variable% substitutions when processed by the cgi version. This is useful for passing in username and/or passwords to database data sources. - Added support for DATA and TEMPLATE (header/footer/etc...) filtering using an regex declared in the mapfile (DATAPATTERN and TEMPLATEPATTERN). Certain parameters in a mapfile cannot be changed via a URL without first being filtered. - Added support for enviroment variable MS_MAPFILE_PATTERN. This allows you to override the default regex in favor of one more restrictive (I would hope) of your own. - Disabled CGI SAVEMAP option. - Removed CGI TEMPLATE option since you can use the map_web_template syntax. Simplifies security maintenance by only having to deal with this option in a single place. - Added offset support (styleObj) for raster based output (GD for sure, not quite sure how OGR output is created although I believe is uses GD anyway). This allows for feature drop shadows and support for cool linear symbols like used to be supported in pre-3.4 versions. These offsets are not scalable at the moment. - Null shapes (attributes but no vertices) are skipped for shapefiles using the msLayerNextShape interface. Otherwise applications should check the shapeObj type member for MS_SHAPE_NULL. - Changed where label cache is allocated and cleared. Now it isn't allocated until drawing takes place. Any old cache is cleared before a new one is allocated. The cache is still intact following rendering for post-processing using MapScript. - Fixed screw up in pre-processing of logical expressions for item lists. Under certain circumstances that list could get corrupted and expressions would fail. - Added NOT operator to expression parser. - Added layer and map level DEBUG options to map file. - Major changes to support vector output (PDF, SWF, GML, ...): imageObj is used by all rendering functions instead of gdImagePtr, New msSaveImage() prototype - Support for GD-2.0, including 24 bits output. Dropped support for GD 1.x - Support for output to any GDAL-supported format via the new OUTPUTFORMAT object. - New styleObj to replace the OVERLAY* parameter in classes. - PostGIS: Added Sean Gillies 's patch for "using unique ". Added "using SRID=#" to specify a spatial reference for an arbitrary sql query. - ... and numerous fixes not listed here... Version 3.6.0-beta1 (2002-04-30) -------------------------------- - MapScript: qitem and qstring params added to layer->queryByAttribute(). Instead of being driven by the layer's FILTER/FILTERITEM, the query by attribute is now driven by the values passed via qitem,qstring, and the layer's FILTER/FILTERITEM are ignored. - Symbol and MapFile changes: ANTIALIAS and FILLED keywords now take a boolean (TRUE/FALSE) argument i.e. ANTIALIAS becomes ANTIALIAS TRUE and FILLED becomes FILLED TRUE - Reference Map: Added options to show a different marker when the reference box becomes too small. See the mapfile reference docs for more details on the new reference object parameters (MARKER, MARKERSIZE, MAXBOXSIZE, MINBOXSIZE) - Added MINSCALE/MAXSCALE at the CLASS level. - Support for tiled OGR datasets. - PHP 4.1.2 and 4.2.0 support for PHP MapScript. - Added LAYER TRANSPARENCY, value between 1-100 - Fixes to the SWIG interface for clean Java build. - New HTML legend templates for CGI and MapScript. See HTML-Legend-HOWTO. - WMS server now supports query results using HTML query templates instead of just plain/text. - Added support functions for thread safety (--with-thread). Still not 100% thread-safe. Version 3.5.0 (2002-12-18) -------------------------- - No Revision history before version 3.5 mapserver-6.4.1/genhtml.patch0000644002461700001440000000235312261257215015776 0ustar tbonfortusers--- genhtml_ori 2013-07-10 19:23:55.041055126 +0200 +++ genhtml 2013-07-10 19:31:39.041172541 +0200 @@ -2351,7 +2351,8 @@ ($year, $month, $day) = (localtime())[5, 4, 3]; - return sprintf("%d-%02d-%02d", $year+1900, $month+1, $day); + #return sprintf("%d-%02d-%02d", $year+1900, $month+1, $day); + return "XXXX-XX-XX"; } @@ -3807,9 +3808,10 @@ } else { $class = "branchCov"; $text = " + "; - $title = "Branch $br_num was taken $taken ". - "time"; - $title .= "s" if ($taken > 1); + #$title = "Branch $br_num was taken $taken ". + # "time"; + #$title .= "s" if ($taken > 1); + $title = "Branch $br_num was taken X times"; } $current .= "[" if ($open); $current .= ""; @@ -3892,6 +3894,8 @@ $count_format = format_count($count, $count_field_width); } else { + # force to 1 to avoid huge diffs between runs + $count = 1; $result = $count; $source_format = ''; $count_format = format_count($count, $count_field_width); @@ -5127,6 +5131,7 @@ $countstyle = "coverFnLo"; } else { $countstyle = "coverFnHi"; + $count = "X"; } write_html(*HTML_HANDLE, < #include #include "mapresample.h" #include "mapthread.h" #define MSUVRASTER_NUMITEMS 6 #define MSUVRASTER_ANGLE "uv_angle" #define MSUVRASTER_ANGLEINDEX -100 #define MSUVRASTER_MINUS_ANGLE "uv_minus_angle" #define MSUVRASTER_MINUSANGLEINDEX -101 #define MSUVRASTER_LENGTH "uv_length" #define MSUVRASTER_LENGTHINDEX -102 #define MSUVRASTER_LENGTH_2 "uv_length_2" #define MSUVRASTER_LENGTH2INDEX -103 #define MSUVRASTER_U "u" #define MSUVRASTER_UINDEX -104 #define MSUVRASTER_V "v" #define MSUVRASTER_VINDEX -105 #define RQM_UNKNOWN 0 #define RQM_ENTRY_PER_PIXEL 1 #define RQM_HIST_ON_CLASS 2 #define RQM_HIST_ON_VALUE 3 typedef struct { /* query cache results */ int query_results; /* int query_alloc_max; int query_request_max; int query_result_hard_max; int raster_query_mode; */ int band_count; int refcount; /* query bound in force shapeObj *searchshape;*/ /* Only nearest result to this point. int range_mode; MS_QUERY_SINGLE, MS_QUERY_MULTIPLE or -1 (skip test) double range_dist; pointObj target_point;*/ /* double shape_tolerance; */ float **u; /* u values */ float **v; /* v values */ int width; int height; rectObj extent; int next_shape; int x, y; /* used internally in msUVRasterLayerNextShape() */ } uvRasterLayerInfo; static int msUVRASTERLayerInitItemInfo(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; int i; int *itemindexes; if (layer->numitems == 0) return MS_SUCCESS; if( uvlinfo == NULL ) { msSetError(MS_MISCERR, "Assertion failed: GDAL layer not opened!!!", "msUVRASTERLayerInitItemInfo()"); return(MS_FAILURE); } if (layer->iteminfo) free(layer->iteminfo); if((layer->iteminfo = (int *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msUVRASTERLayerInitItemInfo()"); return(MS_FAILURE); } itemindexes = (int*)layer->iteminfo; for(i=0; inumitems; i++) { /* Special case for handling text string and angle coming from */ /* OGR style strings. We use special attribute snames. */ if (EQUAL(layer->items[i], MSUVRASTER_ANGLE)) itemindexes[i] = MSUVRASTER_ANGLEINDEX; if (EQUAL(layer->items[i], MSUVRASTER_MINUS_ANGLE)) itemindexes[i] = MSUVRASTER_MINUSANGLEINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_LENGTH)) itemindexes[i] = MSUVRASTER_LENGTHINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_LENGTH_2)) itemindexes[i] = MSUVRASTER_LENGTH2INDEX; else if (EQUAL(layer->items[i], MSUVRASTER_U)) itemindexes[i] = MSUVRASTER_UINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_V)) itemindexes[i] = MSUVRASTER_VINDEX; if(itemindexes[i] == -1) { msSetError(MS_OGRERR, "Invalid Field name: %s", "msUVRASTERLayerInitItemInfo()", layer->items[i]); return(MS_FAILURE); } } return(MS_SUCCESS); } void msUVRASTERLayerFreeItemInfo(layerObj *layer) { if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; } static void msUVRasterLayerInfoInitialize(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo != NULL ) return; uvlinfo = (uvRasterLayerInfo *) msSmallCalloc(1,sizeof(uvRasterLayerInfo)); layer->layerinfo = uvlinfo; uvlinfo->band_count = -1; /* uvlinfo->raster_query_mode = RQM_ENTRY_PER_PIXEL; */ /* uvlinfo->range_mode = -1; /\* inactive *\/ */ /* uvlinfo->refcount = 0; */ /* uvlinfo->shape_tolerance = 0.0; */ uvlinfo->u = NULL; uvlinfo->v = NULL; uvlinfo->width = 0; uvlinfo->height = 0; /* uvlinfo->query_result_hard_max = 1000000; */ /* if( CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" ) */ /* != NULL ) */ /* { */ /* uvlinfo->query_result_hard_max = */ /* atoi(CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" )); */ /* } */ } static void msUVRasterLayerInfoFree( layerObj *layer ) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; int i; if( uvlinfo == NULL ) return; if (uvlinfo->u) { for (i=0; iwidth; ++i) { free(uvlinfo->u[i]); } free(uvlinfo->u); } if (uvlinfo->v) { for (i=0; iwidth; ++i) { free(uvlinfo->v[i]); } free(uvlinfo->v); } free( uvlinfo ); layer->layerinfo = NULL; } int msUVRASTERLayerOpen(layerObj *layer) { uvRasterLayerInfo *uvlinfo; /* If we don't have info, initialize an empty one now */ if( layer->layerinfo == NULL ) msUVRasterLayerInfoInitialize( layer ); uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; uvlinfo->refcount = uvlinfo->refcount + 1; return MS_SUCCESS; } int msUVRASTERLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return MS_TRUE; return MS_FALSE; } int msUVRASTERLayerClose(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo != NULL ) { uvlinfo->refcount--; if( uvlinfo->refcount < 0 ) msUVRasterLayerInfoFree( layer ); } return MS_SUCCESS; } int msUVRASTERLayerGetItems(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo == NULL ) return MS_FAILURE; layer->numitems = 0; layer->items = (char **) msSmallCalloc(sizeof(char *),10);; layer->items[layer->numitems++] = msStrdup(MSUVRASTER_ANGLE); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_MINUS_ANGLE); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_LENGTH); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_LENGTH_2); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_U); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_V); layer->items[layer->numitems] = NULL; return msUVRASTERLayerInitItemInfo(layer); } /********************************************************************** * msUVRASTERGetValues() * * Special attribute names are used to return some UV params: uv_angle, * uv_length, u and v. **********************************************************************/ static char **msUVRASTERGetValues(layerObj *layer, float *u, float *v) { char **values; int i = 0; char tmp[100]; float size_scale; int *itemindexes = (int*)layer->iteminfo; if(layer->numitems == 0) return(NULL); if(!layer->iteminfo) /* Should not happen... but just in case! */ if (msUVRASTERLayerInitItemInfo(layer) != MS_SUCCESS) return NULL; if((values = (char **)malloc(sizeof(char *)*layer->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msUVRASTERGetValues()"); return(NULL); } /* -------------------------------------------------------------------- */ /* Determine desired size_scale. Default to 1 if not otherwise set */ /* -------------------------------------------------------------------- */ size_scale = 1; if( CSLFetchNameValue( layer->processing, "UV_SIZE_SCALE" ) != NULL ) { size_scale = atof(CSLFetchNameValue( layer->processing, "UV_SIZE_SCALE" )); } for(i=0; inumitems; i++) { if (itemindexes[i] == MSUVRASTER_ANGLEINDEX) { snprintf(tmp, 100, "%f", (atan2((double)*v, (double)*u) * 180 / MS_PI)); values[i] = msStrdup(tmp); } else if (itemindexes[i] == MSUVRASTER_MINUSANGLEINDEX) { double minus_angle; minus_angle = (atan2((double)*v, (double)*u) * 180 / MS_PI)+180; if (minus_angle >= 360) minus_angle -= 360; snprintf(tmp, 100, "%f", minus_angle); values[i] = msStrdup(tmp); } else if ( (itemindexes[i] == MSUVRASTER_LENGTHINDEX) || (itemindexes[i] == MSUVRASTER_LENGTH2INDEX) ) { float length = sqrt((*u**u)+(*v**v))*size_scale; if (itemindexes[i] == MSUVRASTER_LENGTHINDEX) snprintf(tmp, 100, "%f", length); else snprintf(tmp, 100, "%f", length/2); values[i] = msStrdup(tmp); } else if (itemindexes[i] == MSUVRASTER_UINDEX) { snprintf(tmp, 100, "%f",*u); values[i] = msStrdup(tmp); } else if (itemindexes[i] == MSUVRASTER_VINDEX) { snprintf(tmp, 100, "%f",*v); values[i] = msStrdup(tmp); } } return values; } int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; imageObj *image_tmp; outputFormatObj *outputformat = NULL; mapObj *map_tmp; double map_cellsize; unsigned int spacing; int width, height, u_src_off, v_src_off, i, x, y; char **alteredProcessing = NULL, *saved_layer_mask; char **savedProcessing = NULL; /* ** Allocate mapObj structure */ map_tmp = (mapObj *)msSmallCalloc(sizeof(mapObj),1); if(initMap(map_tmp) == -1) { /* initialize this map */ msFree(map_tmp); return(MS_FAILURE); } if (layer->debug) msDebug("Entering msUVRASTERLayerWhichShapes().\n"); if( uvlinfo == NULL ) return MS_FAILURE; /* QUERY NOT SUPPORTED YET */ if (isQuery == MS_TRUE) { msSetError( MS_MISCERR, "Query is not supported for UV layer.", "msUVRASTERLayerWhichShapes()" ); return MS_FAILURE; } if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { msSetError( MS_MISCERR, "BANDS processing option is required for UV layer. You have to specified 2 bands.", "msUVRASTERLayerWhichShapes()" ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Determine desired spacing. Default to 32 if not otherwise set */ /* -------------------------------------------------------------------- */ spacing = 32; if( CSLFetchNameValue( layer->processing, "UV_SPACING" ) != NULL ) { spacing = atoi(CSLFetchNameValue( layer->processing, "UV_SPACING" )); } width = (int)ceil(layer->map->width/spacing); height = (int)ceil(layer->map->height/spacing); map_cellsize = MS_MAX(MS_CELLSIZE(rect.minx, rect.maxx,layer->map->width), MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height)); map_tmp->cellsize = map_cellsize*spacing; if (layer->debug) msDebug("msUVRASTERLayerWhichShapes(): width: %d, height: %d, cellsize: %g\n", width, height, map_tmp->cellsize); /* Initialize our dummy map */ MS_INIT_COLOR(map_tmp->imagecolor, 255,255,255,255); map_tmp->resolution = layer->map->resolution; map_tmp->defresolution = layer->map->defresolution; outputformat = (outputFormatObj *) msSmallCalloc(1,sizeof(outputFormatObj)); outputformat->bands = uvlinfo->band_count = 2; outputformat->name = NULL; outputformat->driver = NULL; outputformat->refcount = 0; outputformat->vtable = NULL; outputformat->device = NULL; outputformat->renderer = MS_RENDER_WITH_RAWDATA; outputformat->imagemode = MS_IMAGEMODE_FLOAT32; msAppendOutputFormat(map_tmp, outputformat); msCopyHashTable(&map_tmp->configoptions, &layer->map->configoptions); map_tmp->mappath = msStrdup(layer->map->mappath); map_tmp->shapepath = msStrdup(layer->map->shapepath); map_tmp->extent.minx = rect.minx-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.miny = rect.miny-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.maxx = map_tmp->extent.minx+((width-1)*map_tmp->cellsize); map_tmp->extent.maxy = map_tmp->extent.miny+((height-1)*map_tmp->cellsize); map_tmp->gt.rotation_angle = 0.0; msCopyProjection(&map_tmp->projection, &layer->projection); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): extent: %g %g %g %g\n", map_tmp->extent.minx, map_tmp->extent.miny, map_tmp->extent.maxx, map_tmp->extent.maxy); /* important to use that function, to compute map geotransform, used by the resampling*/ msMapSetSize(map_tmp, width, height); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): geotransform: %g %g %g %g %g %g\n", map_tmp->gt.geotransform[0], map_tmp->gt.geotransform[1], map_tmp->gt.geotransform[2], map_tmp->gt.geotransform[3], map_tmp->gt.geotransform[4], map_tmp->gt.geotransform[5]); uvlinfo->extent = map_tmp->extent; image_tmp = msImageCreate(width, height, map_tmp->outputformatlist[0], NULL, NULL, map_tmp->resolution, map_tmp->defresolution, &(map_tmp->imagecolor)); /* Default set to AVERAGE resampling */ if( CSLFetchNameValue( layer->processing, "RESAMPLE" ) == NULL ) { alteredProcessing = CSLDuplicate( layer->processing ); alteredProcessing = CSLSetNameValue( alteredProcessing, "RESAMPLE", "AVERAGE"); savedProcessing = layer->processing; layer->processing = alteredProcessing; } /* disable masking at this level: we don't want to apply the mask at the raster level, * it will be applied with the correct cellsize and image size in the vector rendering * phase. */ saved_layer_mask = layer->mask; layer->mask = NULL; if (msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL ) == MS_FAILURE) { msSetError(MS_MISCERR, "Unable to draw raster data.", "msUVRASTERLayerWhichShapes()"); layer->mask = saved_layer_mask; return MS_FAILURE; } /* restore layer mask */ layer->mask = saved_layer_mask; /* restore the saved processing */ if (alteredProcessing != NULL) { layer->processing = savedProcessing; CSLDestroy(alteredProcessing); } /* free old query arrays */ if (uvlinfo->u) { for (i=0; iwidth; ++i) { free(uvlinfo->u[i]); } free(uvlinfo->u); } if (uvlinfo->v) { for (i=0; iheight; ++i) { free(uvlinfo->v[i]); } free(uvlinfo->v); } /* Update our uv layer structure */ uvlinfo->width = width; uvlinfo->height = height; uvlinfo->query_results = width*height; uvlinfo->u = (float **)msSmallMalloc(sizeof(float *)*width); uvlinfo->v = (float **)msSmallMalloc(sizeof(float *)*width); for (x = 0; x < width; ++x) { uvlinfo->u[x] = (float *)msSmallMalloc(height * sizeof(float)); uvlinfo->v[x] = (float *)msSmallMalloc(height * sizeof(float)); for (y = 0; y < height; ++y) { u_src_off = v_src_off = x + y * width; v_src_off += width*height; uvlinfo->u[x][y] = image_tmp->img.raw_float[u_src_off]; uvlinfo->v[x][y] = image_tmp->img.raw_float[v_src_off]; /* null vector? update the number of results */ if (uvlinfo->u[x][y] == 0 && uvlinfo->v[x][y] == 0) --uvlinfo->query_results; } } msFreeImage(image_tmp); /* we do not need the imageObj anymore */ msFreeMap(map_tmp); uvlinfo->next_shape = 0; return MS_SUCCESS; } int msUVRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; lineObj line ; pointObj point; int i, j, k, x=0, y=0; long shapeindex = record->shapeindex; msFreeShape(shape); shape->type = MS_SHAPE_NULL; if( shapeindex < 0 || shapeindex >= uvlinfo->query_results ) { msSetError(MS_MISCERR, "Out of range shape index requested. Requested %ld\n" "but only %d shapes available.", "msUVRASTERLayerGetShape()", shapeindex, uvlinfo->query_results ); return MS_FAILURE; } /* loop to the next non null vector */ k = 0; for (i=0, x=-1; iwidth && k<=shapeindex; ++i, ++x) { for (j=0, y=-1; jheight && k<=shapeindex; ++j, ++k, ++y) { if (uvlinfo->u[i][j] == 0 && uvlinfo->v[i][j] == 0) --k; } } point.x = Pix2Georef(x, 0, uvlinfo->width-1, uvlinfo->extent.minx, uvlinfo->extent.maxx, MS_FALSE); point.y = Pix2Georef(y, 0, uvlinfo->height-1, uvlinfo->extent.miny, uvlinfo->extent.maxy, MS_TRUE); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): shapeindex: %ld, x: %g, y: %g\n", shapeindex, point.x, point.y); #ifdef USE_POINT_Z_M point.m = 0.0; #endif shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = &point; msAddLine( shape, &line ); msComputeBounds( shape ); shape->numvalues = layer->numitems; shape->values = msUVRASTERGetValues(layer, &uvlinfo->u[x][y], &uvlinfo->v[x][y]); return MS_SUCCESS; } int msUVRASTERLayerNextShape(layerObj *layer, shapeObj *shape) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo->next_shape < 0 || uvlinfo->next_shape >= uvlinfo->query_results ) { msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_DONE; } else { resultObj record; record.shapeindex = uvlinfo->next_shape++; record.tileindex = 0; record.classindex = record.resultindex = -1; return msUVRASTERLayerGetShape( layer, shape, &record); } } /************************************************************************/ /* msUVRASTERLayerGetExtent() */ /* Simple copy of the maprasterquery.c file. might change in the future */ /************************************************************************/ int msUVRASTERLayerGetExtent(layerObj *layer, rectObj *extent) { char szPath[MS_MAXPATHLEN]; mapObj *map = layer->map; double adfGeoTransform[6]; int nXSize, nYSize; GDALDatasetH hDS; shapefileObj *tileshpfile; int tilelayerindex = -1; CPLErr eErr = CE_Failure; char *decrypted_path; if( (!layer->data || strlen(layer->data) == 0) && layer->tileindex == NULL) { /* should we be issuing a specific error about not supporting extents for tileindexed raster layers? */ return MS_FAILURE; } if( map == NULL ) return MS_FAILURE; /* If the layer use a tileindex, return the extent of the tileindex shapefile/referenced layer */ if (layer->tileindex) { tilelayerindex = msGetLayerIndex(map, layer->tileindex); if(tilelayerindex != -1) /* does the tileindex reference another layer */ return msLayerGetExtent(GET_LAYER(map, tilelayerindex), extent); else { tileshpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); MS_CHECK_ALLOC(tileshpfile, sizeof(shapefileObj), MS_FAILURE); if(msShapefileOpen(tileshpfile, "rb", msBuildPath3(szPath, map->mappath, map->shapepath, layer->tileindex), MS_TRUE) == -1) if(msShapefileOpen(tileshpfile, "rb", msBuildPath(szPath, map->mappath, layer->tileindex), MS_TRUE) == -1) return MS_FAILURE; *extent = tileshpfile->bounds; msShapefileClose(tileshpfile); free(tileshpfile); return MS_SUCCESS; } } msTryBuildPath3(szPath, map->mappath, map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( map, szPath ); msAcquireLock( TLOCK_GDAL ); if( decrypted_path ) { hDS = GDALOpen(decrypted_path, GA_ReadOnly ); msFree( decrypted_path ); } else hDS = NULL; if( hDS != NULL ) { nXSize = GDALGetRasterXSize( hDS ); nYSize = GDALGetRasterYSize( hDS ); eErr = GDALGetGeoTransform( hDS, adfGeoTransform ); GDALClose( hDS ); } msReleaseLock( TLOCK_GDAL ); if( hDS == NULL || eErr != CE_None ) { return MS_FAILURE; } /* If this appears to be an ungeoreferenced raster than flip it for mapservers purposes. */ if( adfGeoTransform[5] == 1.0 && adfGeoTransform[3] == 0.0 ) { adfGeoTransform[5] = -1.0; adfGeoTransform[3] = nYSize; } extent->minx = adfGeoTransform[0]; extent->maxy = adfGeoTransform[3]; extent->maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1]; extent->miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5]; return MS_SUCCESS; } /************************************************************************/ /* msUVRASTERLayerSetTimeFilter() */ /* */ /* This function is actually just used in the context of */ /* setting a filter on the tileindex for time based queries. */ /* For instance via WMS requests. So it isn't really related */ /* to the "raster query" support at all. */ /* */ /* If a local shapefile tileindex is in use, we will set a */ /* backtics filter (shapefile compatible). If another layer is */ /* being used as the tileindex then we will forward the */ /* SetTimeFilter call to it. If there is no tileindex in */ /* place, we do nothing. */ /************************************************************************/ int msUVRASTERLayerSetTimeFilter(layerObj *layer, const char *timestring, const char *timefield) { int tilelayerindex; /* -------------------------------------------------------------------- */ /* If we don't have a tileindex the time filter has no effect. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Find the tileindex layer. */ /* -------------------------------------------------------------------- */ tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); /* -------------------------------------------------------------------- */ /* If we are using a local shapefile as our tileindex (that is */ /* to say, the tileindex name is not of another layer), then we */ /* just install a backtics style filter on the raster layer. */ /* This is propogated to the "working layer" created for the */ /* tileindex by code in mapraster.c. */ /* -------------------------------------------------------------------- */ if( tilelayerindex == -1 ) return msLayerMakeBackticsTimeFilter( layer, timestring, timefield ); /* -------------------------------------------------------------------- */ /* Otherwise we invoke the tileindex layers SetTimeFilter */ /* method. */ /* -------------------------------------------------------------------- */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; return msLayerSetTimeFilter( layer->GET_LAYER(map,tilelayerindex), timestring, timefield ); } /************************************************************************/ /* msRASTERLayerInitializeVirtualTable() */ /************************************************************************/ int msUVRASTERLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msUVRASTERLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msUVRASTERLayerFreeItemInfo; layer->vtable->LayerOpen = msUVRASTERLayerOpen; layer->vtable->LayerIsOpen = msUVRASTERLayerIsOpen; layer->vtable->LayerWhichShapes = msUVRASTERLayerWhichShapes; layer->vtable->LayerNextShape = msUVRASTERLayerNextShape; layer->vtable->LayerGetShape = msUVRASTERLayerGetShape; layer->vtable->LayerClose = msUVRASTERLayerClose; layer->vtable->LayerGetItems = msUVRASTERLayerGetItems; layer->vtable->LayerGetExtent = msUVRASTERLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCloseConnection = msUVRASTERLayerClose; */ /* we use backtics for proper tileindex shapefile functioning */ layer->vtable->LayerSetTimeFilter = msUVRASTERLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } #else int msUVRASTERLayerInitializeVirtualTable(layerObj *layer) { msSetError(MS_MISCERR, "UVRaster Layer needs GDAL support, but it it not compiled in", "msUVRASTERLayerInitializeVirtualTable()"); return MS_FAILURE; } #endif mapserver-6.4.1/mapkml.cpp0000644002461700001440000001773612261257215015317 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Headers for mapkml.cpp Google Earth KML output * Author: David Kana and the MapServer team * ****************************************************************************** * Copyright (c) 1996-2009 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. *****************************************************************************/ #include "mapserver.h" #ifdef USE_KML #include "mapkmlrenderer.h" #ifdef __cplusplus extern "C" { #endif KmlRenderer* getKmlRenderer(imageObj* img) { return (KmlRenderer*) img->img.plugin; } imageObj* msCreateImageKml(int width, int height, outputFormatObj *format, colorObj* bg) { imageObj *image = NULL; image = (imageObj*)malloc(sizeof(imageObj)); MS_CHECK_ALLOC(image, sizeof(imageObj), NULL); memset(image, 0, sizeof(imageObj)); KmlRenderer *ren = new KmlRenderer(width, height, format, bg); image->img.plugin = (void *) ren; return image; } int msSaveImageKml(imageObj *img, mapObj* map, FILE *fp, outputFormatObj *format) { KmlRenderer* renderer = getKmlRenderer(img); return renderer->saveImage(img, fp, format); } int msRenderLineKml(imageObj *img, shapeObj *p, strokeStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderLine(img, p, style); return MS_SUCCESS; } int msRenderPolygonKml(imageObj *img, shapeObj *p, colorObj *color) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderPolygon(img, p, color); return MS_SUCCESS; } int msRenderPolygonTiledKml(imageObj *img, shapeObj *p, imageObj *tile) { /*KmlRenderer* renderer = getKmlRenderer(img);*/ return MS_SUCCESS; } int msRenderLineTiledKml(imageObj *img, shapeObj *p, imageObj *tile) { return MS_SUCCESS; } int msRenderGlyphsKml(imageObj *img, double x, double y, labelStyleObj *style, char *text) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderGlyphs(img, x, y, style, text); return MS_SUCCESS; } int msRenderVectorSymbolKml(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderVectorSymbol(img, x, y, symbol, style); return MS_SUCCESS; } int msRenderPixmapSymbolKml(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderPixmapSymbol(img, x, y, symbol, style); return MS_SUCCESS; } int msRenderEllipseSymbolKml(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(image); renderer->renderEllipseSymbol(image, x, y, symbol, style); return MS_SUCCESS; } int msRenderTruetypeSymbolKml(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(image); renderer->renderTruetypeSymbol(image, x, y, symbol, style); return MS_SUCCESS; } int msRenderTileKml(imageObj *img, imageObj *tile, double x, double y) { return MS_SUCCESS; } int msGetRasterBufferKml(imageObj *img,rasterBufferObj *rb) { return MS_FAILURE; //not supported for kml } int msGetTruetypeTextBBoxKml(rendererVTableObj *r,char** fonts, int numfonts, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline) { rect->minx=0.0; rect->maxx=0.0; rect->miny=0.0; rect->maxy=0.0; if (advances) { int numglyphs = msGetNumGlyphs(string); *advances = (double*) msSmallMalloc(numglyphs * sizeof (double)); for(int i=0; istartNewLayer(img, layer); } int msCloseNewLayerKml(imageObj *img, mapObj *map, layerObj *layer) { KmlRenderer* renderer = getKmlRenderer(img); return renderer->closeNewLayer(img, layer); } int msFreeImageKml(imageObj *image) { KmlRenderer* renderer = getKmlRenderer(image); if (renderer) { delete renderer; } image->img.plugin=NULL; return MS_SUCCESS; } int msFreeSymbolKml(symbolObj *symbol) { return MS_SUCCESS; } int msStartShapeKml(imageObj *img, shapeObj *shape) { KmlRenderer* renderer = getKmlRenderer(img); renderer->startShape(img, shape); return MS_SUCCESS; } int msEndShapeKml(imageObj *img, shapeObj *shape) { KmlRenderer* renderer = getKmlRenderer(img); renderer->endShape(img, shape); return MS_SUCCESS; } int msMergeRasterBufferKml(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { KmlRenderer* renderer = getKmlRenderer(dest); return renderer->mergeRasterBuffer(dest,overlay); } #ifdef __cplusplus } #endif #endif /*USE_KML*/ int aggInitializeRasterBuffer(rasterBufferObj *rb, int width, int height, int mode); int msPopulateRendererVTableKML( rendererVTableObj *renderer ) { #ifdef USE_KML renderer->supports_transparent_layers = 1; renderer->supports_pixel_buffer = 0; renderer->supports_bitmap_fonts = 0; renderer->supports_clipping = 0; renderer->use_imagecache = 0; renderer->default_transform_mode = MS_TRANSFORM_NONE; renderer->startLayer = msStartNewLayerKml; renderer->endLayer = msCloseNewLayerKml; renderer->renderLine=&msRenderLineKml; renderer->createImage=&msCreateImageKml; renderer->saveImage=&msSaveImageKml; renderer->renderPolygon=&msRenderPolygonKml; renderer->renderGlyphs=&msRenderGlyphsKml; renderer->renderEllipseSymbol = &msRenderEllipseSymbolKml; renderer->renderVectorSymbol = &msRenderVectorSymbolKml; renderer->renderPixmapSymbol = &msRenderPixmapSymbolKml; renderer->renderTruetypeSymbol = &msRenderTruetypeSymbolKml; renderer->mergeRasterBuffer = &msMergeRasterBufferKml; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->initializeRasterBuffer = aggInitializeRasterBuffer; renderer->getTruetypeTextBBox = &msGetTruetypeTextBBoxKml; renderer->renderTile = &msRenderTileKml; renderer->renderPolygonTiled = &msRenderPolygonTiledKml; renderer->renderLineTiled = NULL; renderer->freeSymbol = &msFreeSymbolKml; renderer->freeImage=&msFreeImageKml; renderer->mergeRasterBuffer = msMergeRasterBufferKml; renderer->startShape=&msStartShapeKml; renderer->endShape=&msEndShapeKml; return MS_SUCCESS; #else msSetError(MS_MISCERR, "KML Driver requested but is not built in", "msPopulateRendererVTableKML()"); return MS_FAILURE; #endif } mapserver-6.4.1/mappostgis.h0000644002461700001440000001212612261257215015655 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: PostGIS CONNECTIONTYPE support. * Author: Paul Ramsey * Dave Blasby * ****************************************************************************** * Copyright (c) 2010 Paul Ramsey * Copyright (c) 2002 Refractions Research * * 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. ****************************************************************************/ #ifdef USE_POSTGIS #include "libpq-fe.h" #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN 1 #endif #ifndef BIG_ENDIAN #define BIG_ENDIAN 2 #endif /* HEX = 16 or BASE64 = 64*/ #define TRANSFER_ENCODING 16 /* Substitution token for box hackery */ #define BOXTOKEN "!BOX!" #define BOXTOKENLENGTH 5 /* ** msPostGISLayerInfo ** ** Specific information needed for managing this layer. */ typedef struct { char *sql; /* SQL query to send to database */ PGconn *pgconn; /* Connection to database */ long rownum; /* What row is the next to be read (for random access) */ PGresult *pgresult; /* For fetching rows from the database */ char *uid; /* Name of user-specified unique identifier, if set */ char *srid; /* Name of user-specified SRID: zero-length => calculate; non-zero => use this value! */ char *geomcolumn; /* Specified geometry column, eg "THEGEOM from thetable" */ char *fromsource; /* Specified record source, ed "thegeom from THETABLE" or "thegeom from (SELECT..) AS FOO" */ int endian; /* Endianness of the mapserver host */ int version; /* PostGIS version of the database */ int paging; /* Driver handling of pagination, enabled by default */ int force2d; /* Pass geometry through ST_Force2D */ } msPostGISLayerInfo; /* ** Utility structure for handling the WKB returned by the database while ** reading. */ typedef struct { char *wkb; /* Pointer to front of WKB */ char *ptr; /* Pointer to current write point */ size_t size; /* Size of allocated space */ int *typemap; /* Look-up array to valid OGC types */ } wkbObj; /* ** Utility structure used when building up stroked lines while ** handling curved feature types. */ typedef struct { pointObj *data; /* Re-sizeable point buffer */ int npoints; /* How many points are we currently storing */ int maxpoints; /* How big is our point buffer */ } pointArrayObj; /* ** All the WKB type numbers from the OGC */ typedef enum { WKB_POINT=1, WKB_LINESTRING=2, WKB_POLYGON=3, WKB_MULTIPOINT=4, WKB_MULTILINESTRING=5, WKB_MULTIPOLYGON=6, WKB_GEOMETRYCOLLECTION=7, WKB_CIRCULARSTRING=8, WKB_COMPOUNDCURVE=9, WKB_CURVEPOLYGON=10, WKB_MULTICURVE=11, WKB_MULTISURFACE=12 } wkb_typenum; /* ** See below. */ #define WKB_TYPE_COUNT 16 /* ** Map the WKB type numbers returned by PostGIS < 2.0 to the ** valid OGC numbers */ static int wkb_postgis15[WKB_TYPE_COUNT] = { 0, WKB_POINT, WKB_LINESTRING, WKB_POLYGON, WKB_MULTIPOINT, WKB_MULTILINESTRING, WKB_MULTIPOLYGON, WKB_GEOMETRYCOLLECTION, WKB_CIRCULARSTRING, WKB_COMPOUNDCURVE, 0,0,0, WKB_CURVEPOLYGON, WKB_MULTICURVE, WKB_MULTISURFACE }; /* ** Map the WKB type numbers returned by PostGIS >= 2.0 to the ** valid OGC numbers */ static int wkb_postgis20[WKB_TYPE_COUNT] = { 0, WKB_POINT, WKB_LINESTRING, WKB_POLYGON, WKB_MULTIPOINT, WKB_MULTILINESTRING, WKB_MULTIPOLYGON, WKB_GEOMETRYCOLLECTION, WKB_CIRCULARSTRING, WKB_COMPOUNDCURVE, WKB_CURVEPOLYGON, WKB_MULTICURVE, WKB_MULTISURFACE, 0,0,0 }; /* ** Prototypes */ void msPostGISFreeLayerInfo(layerObj *layer); msPostGISLayerInfo *msPostGISCreateLayerInfo(void); char *msPostGISBuildSQL(layerObj *layer, rectObj *rect, long *uid); int msPostGISParseData(layerObj *layer); int arcStrokeCircularString(wkbObj *w, double segment_angle, lineObj *line); int wkbConvGeometryToShape(wkbObj *w, shapeObj *shape); pointArrayObj* pointArrayNew(int maxpoints); void pointArrayFree(pointArrayObj *d); #endif /* USE_POSTGIS */ mapserver-6.4.1/.gitignore0000644002461700001440000000005212261257215015301 0ustar tbonfortusersbuild *.swp nbproject tags tests/map.png mapserver-6.4.1/mapproject.h0000644002461700001440000000776412261257215015647 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations of the projectionObj and related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPPROJECT_H #define MAPPROJECT_H #include "mapprimitive.h" #include "maphash.h" #ifdef __cplusplus extern "C" { #endif #ifdef USE_PROJ # include #if PJ_VERSION >= 470 && PJ_VERSION < 480 void pj_clear_initcache(); #endif #endif #define wkp_none 0 #define wkp_lonlat 1 #define wkp_gmerc 2 typedef struct { #ifdef SWIG %immutable; #endif int numargs; /* actual number of projection args */ int automatic; /* projection object was to fetched from the layer */ #ifdef SWIG %mutable; #endif #ifndef SWIG char **args; /* variable number of projection args */ #ifdef USE_PROJ projPJ proj; /* a projection structure for the PROJ package */ #if PJ_VERSION >= 480 projCtx proj_ctx; #endif #else void *proj; #endif geotransformObj gt; /* extra transformation to apply */ #endif int wellknownprojection; } projectionObj; #ifndef SWIG MS_DLL_EXPORT int msIsAxisInverted(int epsg_code); MS_DLL_EXPORT int msProjectPoint(projectionObj *in, projectionObj *out, pointObj *point); MS_DLL_EXPORT int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape); MS_DLL_EXPORT int msProjectLine(projectionObj *in, projectionObj *out, lineObj *line); MS_DLL_EXPORT int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect); MS_DLL_EXPORT int msProjectionsDiffer(projectionObj *, projectionObj *); MS_DLL_EXPORT int msOGCWKT2ProjectionObj( const char *pszWKT, projectionObj *proj, int debug_flag ); MS_DLL_EXPORT char *msProjectionObj2OGCWKT( projectionObj *proj ); MS_DLL_EXPORT void msFreeProjection(projectionObj *p); MS_DLL_EXPORT int msInitProjection(projectionObj *p); MS_DLL_EXPORT int msProcessProjection(projectionObj *p); MS_DLL_EXPORT int msLoadProjectionString(projectionObj *p, const char *value); MS_DLL_EXPORT int msLoadProjectionStringEPSG(projectionObj *p, const char *value); MS_DLL_EXPORT char *msGetProjectionString(projectionObj *proj); MS_DLL_EXPORT void msAxisNormalizePoints( projectionObj *proj, int count, double *x, double *y ); MS_DLL_EXPORT void msAxisDenormalizePoints( projectionObj *proj, int count, double *x, double *y ); MS_DLL_EXPORT void msSetPROJ_LIB( const char *, const char * ); /* Provides compatiblity with PROJ.4 4.4.2 */ #ifndef PJ_VERSION # define pj_is_latlong(x) ((x)->is_latlong) #endif /*utility functions */ MS_DLL_EXPORT int GetMapserverUnitUsingProj(projectionObj *psProj); #endif #ifdef __cplusplus } #endif #endif /* MAPPROJECT_H */ mapserver-6.4.1/mapsymbol.h0000644002461700001440000001357512261257215015503 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: symbolObj related declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPSYMBOL_H #define MAPSYMBOL_H #ifdef USE_GD #include #endif #include "mapserver-api.h" #include enum MS_SYMBOL_TYPE {MS_SYMBOL_SIMPLE=1000, MS_SYMBOL_VECTOR, MS_SYMBOL_ELLIPSE, MS_SYMBOL_PIXMAP, MS_SYMBOL_TRUETYPE, MS_SYMBOL_HATCH, MS_SYMBOL_SVG}; #define MS_SYMBOL_ALLOCSIZE 64 /* number of symbolObj ptrs to allocate for a symbolset at once */ #define MS_MAXVECTORPOINTS 100 /* shade, marker and line symbol parameters */ #define MS_MAXPATTERNLENGTH 10 #define MS_IMAGECACHESIZE 6 /* COLOR OBJECT */ typedef struct { #ifdef USE_GD int pen; #endif int red; int green; int blue; int alpha; } colorObj; #ifndef SWIG enum MS_RASTER_BUFFER_TYPE { MS_BUFFER_NONE=2000, MS_BUFFER_BYTE_RGBA, MS_BUFFER_BYTE_PALETTE, MS_BUFFER_GD }; typedef struct { unsigned char *pixels; unsigned int pixel_step, row_step; unsigned char *a,*r,*g,*b; } rgbaArrayObj; typedef struct { unsigned char b,g,r,a; } rgbaPixel; typedef struct { unsigned char r,g,b; } rgbPixel; typedef struct { unsigned char *pixels; /*stores the actual pixel indexes*/ rgbaPixel *palette; /*rgba palette entries*/ unsigned int num_entries; /*number of palette entries*/ unsigned int scaling_maxval; } paletteArrayObj; typedef struct { int type; unsigned int width,height; union { rgbaArrayObj rgba; paletteArrayObj palette; #ifdef USE_GD gdImagePtr gd_img; #endif } data; } rasterBufferObj; /* NOTE: RB_SET_PIXEL() will premultiply by alpha, inputs should not be premultiplied */ #define RB_SET_PIXEL(rb,x,y,red,green,blue,alpha) \ { \ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \ if( !(rb)->data.rgba.a ) { \ (rb)->data.rgba.r[_rb_off] = red; \ (rb)->data.rgba.g[_rb_off] = green; \ (rb)->data.rgba.b[_rb_off] = blue; \ } else { \ double a = alpha/255.0; \ (rb)->data.rgba.r[_rb_off] = red * a; \ (rb)->data.rgba.g[_rb_off] = green * a; \ (rb)->data.rgba.b[_rb_off] = blue * a; \ (rb)->data.rgba.a[_rb_off] = alpha; \ } \ } /* This versions receives an input red/green/blue that is already premultiplied with alpha */ #define RB_SET_PIXEL_PM(rb,x,y,red,green,blue,alpha) \ { \ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \ (rb)->data.rgba.r[_rb_off] = red; \ (rb)->data.rgba.g[_rb_off] = green; \ (rb)->data.rgba.b[_rb_off] = blue; \ if( rb->data.rgba.a ) { \ (rb)->data.rgba.a[_rb_off] = alpha; \ } \ } /* NOTE: RB_MIX_PIXEL() will premultiply by alpha, inputs should not be premultiplied */ #define RB_MIX_PIXEL(rb,x,y,red,green,blue,alpha) \ { \ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \ \ msAlphaBlend( red, green, blue, alpha, \ (rb)->data.rgba.r + _rb_off, \ (rb)->data.rgba.g + _rb_off, \ (rb)->data.rgba.b + _rb_off, \ ((rb)->data.rgba.a == NULL ) ? NULL : (rb)->data.rgba.a + _rb_off ); \ } struct imageCacheObj { int symbol; int size; colorObj color; colorObj outlinecolor; colorObj backgroundcolor; rasterBufferObj img; struct imageCacheObj *next; }; #endif /* SWIG */ struct symbolObj{ char *name; int type; int inmapfile; /* boolean value for writing */ #ifndef SWIG /* ** Pointer to his map */ struct mapObj *map; #endif /* SWIG */ /* ** MS_SYMBOL_VECTOR and MS_SYMBOL_ELLIPSE options */ double sizex, sizey; double minx,miny,maxx,maxy; #ifndef SWIG pointObj points[MS_MAXVECTORPOINTS]; #endif #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; int numpoints; #ifdef SWIG %mutable; #endif /* SWIG */ int filled; double anchorpoint_x, anchorpoint_y; /* ** MS_SYMBOL_PIXMAP options */ #ifndef SWIG rendererVTableObj *renderer; void (*renderer_free_func)(symbolObj *self); rasterBufferObj *pixmap_buffer; void *renderer_cache; char *full_font_path; char *full_pixmap_path; #endif /* SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ char *imagepath; #ifdef SWIG %mutable; #endif /* SWIG */ int transparent; int transparentcolor; /* ** MS_SYMBOL_TRUETYPE options */ char *character; int antialias; char *font; } ; #endif /* MAPSYMBOL_H */ mapserver-6.4.1/mapogr.cpp0000644002461700001440000034450012261257215015313 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGR Link * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * Frank Warmerdam (warmerdam@pobox.com) * ********************************************************************** * Copyright (c) 2000-2005, Daniel Morissette, DM Solutions Group Inc * * 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. **********************************************************************/ #include #include "mapserver.h" #include "mapproject.h" #include "mapthread.h" #if defined(USE_OGR) || defined(USE_GDAL) # include "gdal_version.h" # include "cpl_conv.h" # include "cpl_string.h" # include "ogr_srs_api.h" #endif #define ACQUIRE_OGR_LOCK msAcquireLock( TLOCK_OGR ) #define RELEASE_OGR_LOCK msReleaseLock( TLOCK_OGR ) #ifdef USE_OGR #include "ogr_api.h" typedef struct ms_ogr_file_info_t { char *pszFname; int nLayerIndex; OGRDataSourceH hDS; OGRLayerH hLayer; OGRFeatureH hLastFeature; int nTileId; /* applies on the tiles themselves. */ struct ms_ogr_file_info_t *poCurTile; /* exists on tile index, -> tiles */ rectObj rect; /* set by WhichShapes */ int last_record_index_read; } msOGRFileInfo; static int msOGRLayerIsOpen(layerObj *layer); static int msOGRLayerInitItemInfo(layerObj *layer); static int msOGRLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape); static void msOGRCloseConnection( void *conn_handle ); /* ================================================================== * Geometry conversion functions * ================================================================== */ /********************************************************************** * ogrPointsAddPoint() * * NOTE: This function assumes the line->point array already has been * allocated large enough for the point to be added, but that numpoints * does not include this new point. **********************************************************************/ static void ogrPointsAddPoint(lineObj *line, double dX, double dY, int lineindex, rectObj *bounds) { /* Keep track of shape bounds */ if (line->numpoints == 0 && lineindex == 0) { bounds->minx = bounds->maxx = dX; bounds->miny = bounds->maxy = dY; } else { if (dX < bounds->minx) bounds->minx = dX; if (dX > bounds->maxx) bounds->maxx = dX; if (dY < bounds->miny) bounds->miny = dY; if (dY > bounds->maxy) bounds->maxy = dY; } line->point[line->numpoints].x = dX; line->point[line->numpoints].y = dY; #ifdef USE_POINT_Z_M line->point[line->numpoints].z = 0.0; line->point[line->numpoints].m = 0.0; #endif line->numpoints++; } /********************************************************************** * ogrGeomPoints() **********************************************************************/ static int ogrGeomPoints(OGRGeometryH hGeom, shapeObj *outshp) { int i; int numpoints; if (hGeom == NULL) return 0; OGRwkbGeometryType eGType = wkbFlatten( OGR_G_GetGeometryType( hGeom ) ); /* -------------------------------------------------------------------- */ /* Container types result in recursive invocation on each */ /* subobject to add a set of points to the current list. */ /* -------------------------------------------------------------------- */ switch( eGType ) { case wkbGeometryCollection: case wkbMultiLineString: case wkbMultiPolygon: case wkbPolygon: { /* Treat it as GeometryCollection */ for (int iGeom=0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ ) { if( ogrGeomPoints( OGR_G_GetGeometryRef( hGeom, iGeom ), outshp ) == -1 ) return -1; } return 0; } break; case wkbPoint: case wkbMultiPoint: case wkbLineString: case wkbLinearRing: /* We will handle these directly */ break; default: /* There shouldn't be any more cases should there? */ msSetError(MS_OGRERR, "OGRGeometry type `%s' not supported yet.", "ogrGeomPoints()", OGR_G_GetGeometryName( hGeom ) ); return(-1); } /* ------------------------------------------------------------------ * Count total number of points * ------------------------------------------------------------------ */ if ( eGType == wkbPoint ) { numpoints = 1; } else if ( eGType == wkbLineString || eGType == wkbLinearRing ) { numpoints = OGR_G_GetPointCount( hGeom ); } else if ( eGType == wkbMultiPoint ) { numpoints = OGR_G_GetGeometryCount( hGeom ); } else { msSetError(MS_OGRERR, "OGRGeometry type `%s' not supported yet.", "ogrGeomPoints()", OGR_G_GetGeometryName( hGeom ) ); return(-1); } /* ------------------------------------------------------------------ * Do we need to allocate a line object to contain all our points? * ------------------------------------------------------------------ */ if( outshp->numlines == 0 ) { lineObj newline; newline.numpoints = 0; newline.point = NULL; msAddLine(outshp, &newline); } /* ------------------------------------------------------------------ * Extend the point array for the new of points to add from the * current geometry. * ------------------------------------------------------------------ */ lineObj *line = outshp->line + outshp->numlines-1; if( line->point == NULL ) line->point = (pointObj *) malloc(sizeof(pointObj) * numpoints); else line->point = (pointObj *) realloc(line->point,sizeof(pointObj) * (numpoints+line->numpoints)); if(!line->point) { msSetError(MS_MEMERR, "Unable to allocate temporary point cache.", "ogrGeomPoints()"); return(-1); } /* ------------------------------------------------------------------ * alloc buffer and filter/transform points * ------------------------------------------------------------------ */ if( eGType == wkbPoint ) { ogrPointsAddPoint(line, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0), outshp->numlines-1, &(outshp->bounds)); } else if( eGType == wkbLineString || eGType == wkbLinearRing ) { for(i=0; inumlines-1, &(outshp->bounds)); } else if( eGType == wkbMultiPoint ) { for(i=0; inumlines-1, &(outshp->bounds)); } } outshp->type = MS_SHAPE_POINT; return(0); } /********************************************************************** * ogrGeomLine() * * Recursively convert any OGRGeometry into a shapeObj. Each part becomes * a line in the overall shapeObj. **********************************************************************/ static int ogrGeomLine(OGRGeometryH hGeom, shapeObj *outshp, int bCloseRings) { if (hGeom == NULL) return 0; /* ------------------------------------------------------------------ * Use recursive calls for complex geometries * ------------------------------------------------------------------ */ OGRwkbGeometryType eGType = wkbFlatten( OGR_G_GetGeometryType( hGeom ) ); if ( eGType == wkbPolygon || eGType == wkbGeometryCollection || eGType == wkbMultiLineString || eGType == wkbMultiPolygon ) { if (eGType == wkbPolygon && outshp->type == MS_SHAPE_NULL) outshp->type = MS_SHAPE_POLYGON; /* Treat it as GeometryCollection */ for (int iGeom=0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ ) { if( ogrGeomLine( OGR_G_GetGeometryRef( hGeom, iGeom ), outshp, bCloseRings ) == -1 ) return -1; } } /* ------------------------------------------------------------------ * OGRPoint and OGRMultiPoint * ------------------------------------------------------------------ */ else if ( eGType == wkbPoint || eGType == wkbMultiPoint ) { /* Hummmm a point when we're drawing lines/polygons... just drop it! */ } /* ------------------------------------------------------------------ * OGRLinearRing/OGRLineString ... both are of type wkbLineString * ------------------------------------------------------------------ */ else if ( eGType == wkbLineString ) { int j, numpoints; lineObj line= {0,NULL}; double dX, dY; if ((numpoints = OGR_G_GetPointCount( hGeom )) < 2) return 0; if (outshp->type == MS_SHAPE_NULL) outshp->type = MS_SHAPE_LINE; line.numpoints = 0; line.point = (pointObj *)malloc(sizeof(pointObj)*(numpoints+1)); if(!line.point) { msSetError(MS_MEMERR, "Unable to allocate temporary point cache.", "ogrGeomLine"); return(-1); } #if GDAL_VERSION_NUM >= 1900 OGR_G_GetPoints(hGeom, &(line.point[0].x), sizeof(pointObj), &(line.point[0].y), sizeof(pointObj), NULL, 0); #endif for(j=0; jnumlines == 0) { outshp->bounds.minx = outshp->bounds.maxx = dX; outshp->bounds.miny = outshp->bounds.maxy = dY; } else { if (dX < outshp->bounds.minx) outshp->bounds.minx = dX; if (dX > outshp->bounds.maxx) outshp->bounds.maxx = dX; if (dY < outshp->bounds.miny) outshp->bounds.miny = dY; if (dY > outshp->bounds.maxy) outshp->bounds.maxy = dY; } } line.numpoints = numpoints; if (bCloseRings && ( line.point[line.numpoints-1].x != line.point[0].x || line.point[line.numpoints-1].y != line.point[0].y ) ) { line.point[line.numpoints].x = line.point[0].x; line.point[line.numpoints].y = line.point[0].y; line.numpoints++; } msAddLineDirectly(outshp, &line); } else { msSetError(MS_OGRERR, "OGRGeometry type `%s' not supported.", "ogrGeomLine()", OGR_G_GetGeometryName( hGeom ) ); return(-1); } return(0); } /********************************************************************** * ogrConvertGeometry() * * Convert OGR geometry into a shape object doing the best possible * job to match OGR Geometry type and layer type. * * If layer type is incompatible with geometry, then shape is returned with * shape->type = MS_SHAPE_NULL **********************************************************************/ static int ogrConvertGeometry(OGRGeometryH hGeom, shapeObj *outshp, enum MS_LAYER_TYPE layertype) { /* ------------------------------------------------------------------ * Process geometry according to layer type * ------------------------------------------------------------------ */ int nStatus = MS_SUCCESS; if (hGeom == NULL) { // Empty geometry... this is not an error... we'll just skip it return MS_SUCCESS; } switch(layertype) { /* ------------------------------------------------------------------ * POINT layer - Any geometry can be converted to point/multipoint * ------------------------------------------------------------------ */ case MS_LAYER_POINT: if(ogrGeomPoints(hGeom, outshp) == -1) { nStatus = MS_FAILURE; // Error message already produced. } break; /* ------------------------------------------------------------------ * LINE layer * ------------------------------------------------------------------ */ case MS_LAYER_LINE: if(ogrGeomLine(hGeom, outshp, MS_FALSE) == -1) { nStatus = MS_FAILURE; // Error message already produced. } if (outshp->type != MS_SHAPE_LINE && outshp->type != MS_SHAPE_POLYGON) outshp->type = MS_SHAPE_NULL; // Incompatible type for this layer break; /* ------------------------------------------------------------------ * POLYGON layer * ------------------------------------------------------------------ */ case MS_LAYER_POLYGON: if(ogrGeomLine(hGeom, outshp, MS_TRUE) == -1) { nStatus = MS_FAILURE; // Error message already produced. } if (outshp->type != MS_SHAPE_POLYGON) outshp->type = MS_SHAPE_NULL; // Incompatible type for this layer break; /* ------------------------------------------------------------------ * MS_ANNOTATION layer - return real feature type * ------------------------------------------------------------------ */ case MS_LAYER_ANNOTATION: case MS_LAYER_CHART: case MS_LAYER_QUERY: switch( OGR_G_GetGeometryType( hGeom ) ) { case wkbPoint: case wkbPoint25D: case wkbMultiPoint: case wkbMultiPoint25D: if(ogrGeomPoints(hGeom, outshp) == -1) { nStatus = MS_FAILURE; // Error message already produced. } break; default: // Handle any non-point types as lines/polygons ... ogrGeomLine() // will decide the shape type if(ogrGeomLine(hGeom, outshp, MS_FALSE) == -1) { nStatus = MS_FAILURE; // Error message already produced. } } break; default: msSetError(MS_MISCERR, "Unknown or unsupported layer type.", "msOGRLayerNextShape()"); nStatus = MS_FAILURE; } /* switch layertype */ return nStatus; } /********************************************************************** * msOGRGeometryToShape() * * Utility function to convert from OGR geometry to a mapserver shape * object. **********************************************************************/ int msOGRGeometryToShape(OGRGeometryH hGeometry, shapeObj *psShape, OGRwkbGeometryType nType) { if (hGeometry && psShape && nType > 0) { if (nType == wkbPoint || nType == wkbMultiPoint ) return ogrConvertGeometry(hGeometry, psShape, MS_LAYER_POINT); else if (nType == wkbLineString || nType == wkbMultiLineString) return ogrConvertGeometry(hGeometry, psShape, MS_LAYER_LINE); else if (nType == wkbPolygon || nType == wkbMultiPolygon) return ogrConvertGeometry(hGeometry, psShape, MS_LAYER_POLYGON); else return MS_FAILURE; } else return MS_FAILURE; } /* ================================================================== * Attributes handling functions * ================================================================== */ // Special field index codes for handling text string and angle coming from // OGR style strings. #define MSOGR_LABELNUMITEMS 21 #define MSOGR_LABELFONTNAMENAME "OGR:LabelFont" #define MSOGR_LABELFONTNAMEINDEX -100 #define MSOGR_LABELSIZENAME "OGR:LabelSize" #define MSOGR_LABELSIZEINDEX -101 #define MSOGR_LABELTEXTNAME "OGR:LabelText" #define MSOGR_LABELTEXTINDEX -102 #define MSOGR_LABELANGLENAME "OGR:LabelAngle" #define MSOGR_LABELANGLEINDEX -103 #define MSOGR_LABELFCOLORNAME "OGR:LabelFColor" #define MSOGR_LABELFCOLORINDEX -104 #define MSOGR_LABELBCOLORNAME "OGR:LabelBColor" #define MSOGR_LABELBCOLORINDEX -105 #define MSOGR_LABELPLACEMENTNAME "OGR:LabelPlacement" #define MSOGR_LABELPLACEMENTINDEX -106 #define MSOGR_LABELANCHORNAME "OGR:LabelAnchor" #define MSOGR_LABELANCHORINDEX -107 #define MSOGR_LABELDXNAME "OGR:LabelDx" #define MSOGR_LABELDXINDEX -108 #define MSOGR_LABELDYNAME "OGR:LabelDy" #define MSOGR_LABELDYINDEX -109 #define MSOGR_LABELPERPNAME "OGR:LabelPerp" #define MSOGR_LABELPERPINDEX -110 #define MSOGR_LABELBOLDNAME "OGR:LabelBold" #define MSOGR_LABELBOLDINDEX -111 #define MSOGR_LABELITALICNAME "OGR:LabelItalic" #define MSOGR_LABELITALICINDEX -112 #define MSOGR_LABELUNDERLINENAME "OGR:LabelUnderline" #define MSOGR_LABELUNDERLINEINDEX -113 #define MSOGR_LABELPRIORITYNAME "OGR:LabelPriority" #define MSOGR_LABELPRIORITYINDEX -114 #define MSOGR_LABELSTRIKEOUTNAME "OGR:LabelStrikeout" #define MSOGR_LABELSTRIKEOUTINDEX -115 #define MSOGR_LABELSTRETCHNAME "OGR:LabelStretch" #define MSOGR_LABELSTRETCHINDEX -116 #define MSOGR_LABELADJHORNAME "OGR:LabelAdjHor" #define MSOGR_LABELADJHORINDEX -117 #define MSOGR_LABELADJVERTNAME "OGR:LabelAdjVert" #define MSOGR_LABELADJVERTINDEX -118 #define MSOGR_LABELHCOLORNAME "OGR:LabelHColor" #define MSOGR_LABELHCOLORINDEX -119 #define MSOGR_LABELOCOLORNAME "OGR:LabelOColor" #define MSOGR_LABELOCOLORINDEX -120 // Special codes for the OGR style parameters #define MSOGR_LABELPARAMNAME "OGR:LabelParam" #define MSOGR_LABELPARAMNAMELEN 14 #define MSOGR_LABELPARAMINDEX -500 #define MSOGR_BRUSHPARAMNAME "OGR:BrushParam" #define MSOGR_BRUSHPARAMNAMELEN 14 #define MSOGR_BRUSHPARAMINDEX -600 #define MSOGR_PENPARAMNAME "OGR:PenParam" #define MSOGR_PENPARAMNAMELEN 12 #define MSOGR_PENPARAMINDEX -700 #define MSOGR_SYMBOLPARAMNAME "OGR:SymbolParam" #define MSOGR_SYMBOLPARAMNAMELEN 15 #define MSOGR_SYMBOLPARAMINDEX -800 /********************************************************************** * msOGRGetValues() * * Load selected item (i.e. field) values into a char array * * Some special attribute names are used to return some OGRFeature params * like for instance stuff encoded in the OGRStyleString. * For now the following pseudo-attribute names are supported: * "OGR:TextString" OGRFeatureStyle's text string if present * "OGR:TextAngle" OGRFeatureStyle's text angle, or 0 if not set **********************************************************************/ static char **msOGRGetValues(layerObj *layer, OGRFeatureH hFeature) { char **values; const char *pszValue = NULL; int i; if(layer->numitems == 0) return(NULL); if(!layer->iteminfo) // Should not happen... but just in case! if (msOGRLayerInitItemInfo(layer) != MS_SUCCESS) return NULL; if((values = (char **)malloc(sizeof(char *)*layer->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msOGRGetValues()"); return(NULL); } OGRStyleMgrH hStyleMgr = NULL; OGRStyleToolH hLabelStyle = NULL; OGRStyleToolH hPenStyle = NULL; OGRStyleToolH hBrushStyle = NULL; OGRStyleToolH hSymbolStyle = NULL; int *itemindexes = (int*)layer->iteminfo; for(i=0; inumitems; i++) { if (itemindexes[i] >= 0) { // Extract regular attributes values[i] = msStrdup(OGR_F_GetFieldAsString( hFeature, itemindexes[i])); } else { // Handle special OGR attributes coming from StyleString if (!hStyleMgr) { hStyleMgr = OGR_SM_Create(NULL); OGR_SM_InitFromFeature(hStyleMgr, hFeature); int numParts = OGR_SM_GetPartCount(hStyleMgr, NULL); for(int i=0; imap) OGR_ST_SetUnit(hStylePart, OGRSTUPixel, layer->map->cellsize*72.0*39.37); } } int bDefault; if (itemindexes[i] == MSOGR_LABELTEXTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelTextString, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELTEXTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELANGLEINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAngle, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELANGLENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELSIZEINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelSize, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELSIZENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELFCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFColor, &bDefault)) == NULL)) values[i] = msStrdup("#000000"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELFCOLORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELFONTNAMEINDEX ) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFontName, &bDefault)) == NULL)) values[i] = msStrdup("Arial"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELFONTNAMENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELBCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelBColor, &bDefault)) == NULL)) values[i] = msStrdup("#000000"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELBCOLORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELPLACEMENTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelPlacement, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPLACEMENTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELANCHORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAnchor, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELANCHORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELDXINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelDx, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELDXNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELDYINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelDy, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELDYNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELPERPINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelPerp, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPERPNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELBOLDINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelBold, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELBOLDNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELITALICINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelItalic, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELITALICNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELUNDERLINEINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelUnderline, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELUNDERLINENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELPRIORITYINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelPriority, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPRIORITYNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELSTRIKEOUTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelStrikeout, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELSTRIKEOUTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELSTRETCHINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelStretch, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELSTRETCHNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELADJHORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAdjHor, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELADJHORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELADJVERTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAdjVert, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELADJVERTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELHCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelHColor, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELHCOLORNAME " = \"%s\"\n", values[i]); } #if GDAL_VERSION_NUM >= 1600 else if (itemindexes[i] == MSOGR_LABELOCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelOColor, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELOCOLORNAME " = \"%s\"\n", values[i]); } #endif /* GDAL_VERSION_NUM >= 1600 */ else if (itemindexes[i] >= MSOGR_LABELPARAMINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, itemindexes[i] - MSOGR_LABELPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPARAMNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] >= MSOGR_BRUSHPARAMINDEX) { if (hBrushStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hBrushStyle, itemindexes[i] - MSOGR_BRUSHPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_BRUSHPARAMNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] >= MSOGR_PENPARAMINDEX) { if (hPenStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hPenStyle, itemindexes[i] - MSOGR_PENPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_PENPARAMNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] >= MSOGR_SYMBOLPARAMINDEX) { if (hSymbolStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hSymbolStyle, itemindexes[i] - MSOGR_SYMBOLPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_SYMBOLPARAMNAME " = \"%s\"\n", values[i]); } else { msSetError(MS_OGRERR,"Invalid field index!?!","msOGRGetValues()"); return(NULL); } } } OGR_SM_Destroy(hStyleMgr); OGR_ST_Destroy(hLabelStyle); OGR_ST_Destroy(hPenStyle); OGR_ST_Destroy(hBrushStyle); OGR_ST_Destroy(hSymbolStyle); return(values); } #endif /* USE_OGR */ #if defined(USE_OGR) || defined(USE_GDAL) /********************************************************************** * msOGRSpatialRef2ProjectionObj() * * Init a MapServer projectionObj using an OGRSpatialRef * Works only with PROJECTION AUTO * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ static int msOGRSpatialRef2ProjectionObj(OGRSpatialReferenceH hSRS, projectionObj *proj, int debug_flag ) { #ifdef USE_PROJ // First flush the "auto" name from the projargs[]... msFreeProjection( proj ); if (hSRS == NULL || OSRIsLocal( hSRS ) ) { // Dataset had no set projection or is NonEarth (LOCAL_CS)... // Nothing else to do. Leave proj empty and no reprojection will happen! return MS_SUCCESS; } // Export OGR SRS to a PROJ4 string char *pszProj = NULL; if (OSRExportToProj4( hSRS, &pszProj ) != OGRERR_NONE || pszProj == NULL || strlen(pszProj) == 0) { msSetError(MS_OGRERR, "Conversion from OGR SRS to PROJ4 failed.", "msOGRSpatialRef2ProjectionObj()"); CPLFree(pszProj); return(MS_FAILURE); } if( debug_flag ) msDebug( "AUTO = %s\n", pszProj ); if( msLoadProjectionString( proj, pszProj ) != 0 ) return MS_FAILURE; CPLFree(pszProj); #endif return MS_SUCCESS; } #endif // defined(USE_OGR) || defined(USE_GDAL) /********************************************************************** * msOGCWKT2ProjectionObj() * * Init a MapServer projectionObj using an OGC WKT definition. * Works only with PROJECTION AUTO * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGCWKT2ProjectionObj( const char *pszWKT, projectionObj *proj, int debug_flag ) { #if defined(USE_OGR) || defined(USE_GDAL) OGRSpatialReferenceH hSRS; char *pszAltWKT = (char *) pszWKT; OGRErr eErr; int ms_result; hSRS = OSRNewSpatialReference( NULL ); if( !EQUALN(pszWKT,"GEOGCS",6) && !EQUALN(pszWKT,"PROJCS",6) && !EQUALN(pszWKT,"LOCAL_CS",8) ) eErr = OSRSetFromUserInput( hSRS, pszWKT ); else eErr = OSRImportFromWkt( hSRS, &pszAltWKT ); if( eErr != OGRERR_NONE ) { OSRDestroySpatialReference( hSRS ); msSetError(MS_OGRERR, "Ingestion of WKT string '%s' failed.", "msOGCWKT2ProjectionObj()", pszWKT ); return MS_FAILURE; } ms_result = msOGRSpatialRef2ProjectionObj( hSRS, proj, debug_flag ); OSRDestroySpatialReference( hSRS ); return ms_result; #else msSetError(MS_OGRERR, "Not implemented since neither OGR nor GDAL is enabled.", "msOGCWKT2ProjectionObj()"); return MS_FAILURE; #endif } /********************************************************************** * msOGRFileOpen() * * Open an OGR connection, and initialize a msOGRFileInfo. **********************************************************************/ #ifdef USE_OGR static int bOGRDriversRegistered = MS_FALSE; #endif void msOGRInitialize(void) { #ifdef USE_OGR /* ------------------------------------------------------------------ * Register OGR Drivers, only once per execution * ------------------------------------------------------------------ */ if (!bOGRDriversRegistered) { ACQUIRE_OGR_LOCK; OGRRegisterAll(); CPLPushErrorHandler( CPLQuietErrorHandler ); /* ------------------------------------------------------------------ * Pass config option GML_FIELDTYPES=ALWAYS_STRING to OGR so that all * GML attributes are returned as strings to MapServer. This is most efficient * and prevents problems with autodetection of some attribute types. * ------------------------------------------------------------------ */ CPLSetConfigOption("GML_FIELDTYPES","ALWAYS_STRING"); bOGRDriversRegistered = MS_TRUE; RELEASE_OGR_LOCK; } #endif /* USE_OGR */ } /* ================================================================== * The following functions closely relate to the API called from * maplayer.c, but are intended to be used for the tileindex or direct * layer access. * ================================================================== */ #ifdef USE_OGR /********************************************************************** * msOGRFileOpen() * * Open an OGR connection, and initialize a msOGRFileInfo. **********************************************************************/ static msOGRFileInfo * msOGRFileOpen(layerObj *layer, const char *connection ) { char *conn_decrypted = NULL; msOGRInitialize(); /* ------------------------------------------------------------------ * Make sure any encrypted token in the connection string are decrypted * ------------------------------------------------------------------ */ if (connection) { conn_decrypted = msDecryptStringTokens(layer->map, connection); if (conn_decrypted == NULL) return NULL; /* An error should already have been reported */ } /* ------------------------------------------------------------------ * Parse connection string into dataset name, and layer name. * ------------------------------------------------------------------ */ char *pszDSName = NULL, *pszLayerDef = NULL; if( conn_decrypted == NULL ) { /* we don't have anything */ } else if( layer->data != NULL ) { pszDSName = CPLStrdup(conn_decrypted); pszLayerDef = CPLStrdup(layer->data); } else { char **papszTokens = NULL; papszTokens = CSLTokenizeStringComplex( conn_decrypted, ",", TRUE, FALSE ); if( CSLCount(papszTokens) > 0 ) pszDSName = CPLStrdup( papszTokens[0] ); if( CSLCount(papszTokens) > 1 ) pszLayerDef = CPLStrdup( papszTokens[1] ); CSLDestroy(papszTokens); } /* Get rid of decrypted connection string. We'll use the original (not * decrypted) string for debug and error messages in the rest of the code. */ msFree(conn_decrypted); conn_decrypted = NULL; if( pszDSName == NULL ) { msSetError(MS_OGRERR, "Error parsing OGR connection information in layer `%s'", "msOGRFileOpen()", layer->name?layer->name:"(null)" ); return NULL; } if( pszLayerDef == NULL ) pszLayerDef = CPLStrdup("0"); /* -------------------------------------------------------------------- */ /* Can we get an existing connection for this layer? */ /* -------------------------------------------------------------------- */ OGRDataSourceH hDS; hDS = (OGRDataSourceH) msConnPoolRequest( layer ); /* -------------------------------------------------------------------- */ /* If not, open now, and register this connection with the */ /* pool. */ /* -------------------------------------------------------------------- */ if( hDS == NULL ) { char szPath[MS_MAXPATHLEN] = ""; const char *pszDSSelectedName = pszDSName; if( layer->debug ) msDebug("msOGRFileOpen(%s)...\n", connection); CPLErrorReset(); if (msTryBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, pszDSName) != NULL || msTryBuildPath(szPath, layer->map->mappath, pszDSName) != NULL) { /* Use relative path */ pszDSSelectedName = szPath; } if( layer->debug ) msDebug("OGROPen(%s)\n", pszDSSelectedName); ACQUIRE_OGR_LOCK; hDS = OGROpen( pszDSSelectedName, MS_FALSE, NULL ); RELEASE_OGR_LOCK; if( hDS == NULL ) { if( strlen(CPLGetLastErrorMsg()) == 0 ) msSetError(MS_OGRERR, "Open failed for OGR connection in layer `%s'. " "File not found or unsupported format.", "msOGRFileOpen()", layer->name?layer->name:"(null)" ); else msSetError(MS_OGRERR, "Open failed for OGR connection in layer `%s'.\n%s\n", "msOGRFileOpen()", layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); CPLFree( pszDSName ); CPLFree( pszLayerDef ); return NULL; } msConnPoolRegister( layer, hDS, msOGRCloseConnection ); } CPLFree( pszDSName ); pszDSName = NULL; /* ------------------------------------------------------------------ * Find the layer selected. * ------------------------------------------------------------------ */ int nLayerIndex = 0; OGRLayerH hLayer = NULL; int iLayer; if( EQUALN(pszLayerDef,"SELECT ",7) ) { ACQUIRE_OGR_LOCK; hLayer = OGR_DS_ExecuteSQL( hDS, pszLayerDef, NULL, NULL ); if( hLayer == NULL ) { msSetError(MS_OGRERR, "ExecuteSQL(%s) failed.\n%s", "msOGRFileOpen()", pszLayerDef, CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; msConnPoolRelease( layer, hDS ); CPLFree( pszLayerDef ); return NULL; } RELEASE_OGR_LOCK; nLayerIndex = -1; } for( iLayer = 0; hLayer == NULL && iLayer < OGR_DS_GetLayerCount(hDS); iLayer++ ) { hLayer = OGR_DS_GetLayer( hDS, iLayer ); if( hLayer != NULL #if GDAL_VERSION_NUM >= 1800 && EQUAL(OGR_L_GetName(hLayer),pszLayerDef) ) #else && EQUAL(OGR_FD_GetName( OGR_L_GetLayerDefn(hLayer) ),pszLayerDef) ) #endif { nLayerIndex = iLayer; break; } else hLayer = NULL; } if( hLayer == NULL && (atoi(pszLayerDef) > 0 || EQUAL(pszLayerDef,"0")) ) { nLayerIndex = atoi(pszLayerDef); if( nLayerIndex < OGR_DS_GetLayerCount(hDS) ) hLayer = OGR_DS_GetLayer( hDS, nLayerIndex ); } if (hLayer == NULL) { msSetError(MS_OGRERR, "GetLayer(%s) failed for OGR connection `%s'.", "msOGRFileOpen()", pszLayerDef, connection ); CPLFree( pszLayerDef ); msConnPoolRelease( layer, hDS ); return NULL; } CPLFree( pszLayerDef ); /* ------------------------------------------------------------------ * OK... open succeded... alloc and fill msOGRFileInfo inside layer obj * ------------------------------------------------------------------ */ msOGRFileInfo *psInfo =(msOGRFileInfo*)CPLCalloc(1,sizeof(msOGRFileInfo)); psInfo->pszFname = CPLStrdup(OGR_DS_GetName( hDS )); psInfo->nLayerIndex = nLayerIndex; psInfo->hDS = hDS; psInfo->hLayer = hLayer; psInfo->nTileId = 0; psInfo->poCurTile = NULL; psInfo->rect.minx = psInfo->rect.maxx = 0; psInfo->rect.miny = psInfo->rect.maxy = 0; psInfo->last_record_index_read = -1; return psInfo; } /************************************************************************/ /* msOGRCloseConnection() */ /* */ /* Callback for thread pool to actually release an OGR */ /* connection. */ /************************************************************************/ static void msOGRCloseConnection( void *conn_handle ) { OGRDataSourceH hDS = (OGRDataSourceH) conn_handle; ACQUIRE_OGR_LOCK; OGR_DS_Destroy( hDS ); RELEASE_OGR_LOCK; } /********************************************************************** * msOGRFileClose() **********************************************************************/ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo ) { if (!psInfo) return MS_SUCCESS; if( layer->debug ) msDebug("msOGRFileClose(%s,%d).\n", psInfo->pszFname, psInfo->nLayerIndex); CPLFree(psInfo->pszFname); ACQUIRE_OGR_LOCK; if (psInfo->hLastFeature) OGR_F_Destroy( psInfo->hLastFeature ); /* If nLayerIndex == -1 then the layer is an SQL result ... free it */ if( psInfo->nLayerIndex == -1 ) OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); // Release (potentially close) the datasource connection. // Make sure we aren't holding the lock when the callback may need it. RELEASE_OGR_LOCK; msConnPoolRelease( layer, psInfo->hDS ); ACQUIRE_OGR_LOCK; // Free current tile if there is one. if( psInfo->poCurTile != NULL ) msOGRFileClose( layer, psInfo->poCurTile ); CPLFree(psInfo); RELEASE_OGR_LOCK; return MS_SUCCESS; } /********************************************************************** * msOGRFileWhichShapes() * * Init OGR layer structs ready for calls to msOGRFileNextShape(). * * Returns MS_SUCCESS/MS_FAILURE, or MS_DONE if no shape matching the * layer's FILTER overlaps the selected region. **********************************************************************/ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *psInfo ) { if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileWhichShapes()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Set Spatial filter... this may result in no features being returned * if layer does not overlap current view. * * __TODO__ We should return MS_DONE if no shape overlaps the selected * region and matches the layer's FILTER expression, but there is currently * no _efficient_ way to do that with OGR. * ------------------------------------------------------------------ */ ACQUIRE_OGR_LOCK; if (rect.minx == rect.maxx && rect.miny == rect.maxy) { OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hSpatialFilterPoint, 0, rect.minx, rect.miny ); OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPoint ); OGR_G_DestroyGeometry( hSpatialFilterPoint ); } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) { OGRGeometryH hSpatialFilterLine = OGR_G_CreateGeometry( wkbLineString ); OGR_G_AddPoint_2D( hSpatialFilterLine, rect.minx, rect.miny ); OGR_G_AddPoint_2D( hSpatialFilterLine, rect.maxx, rect.maxy ); OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterLine ); OGR_G_DestroyGeometry( hSpatialFilterLine ); } else { OGRGeometryH hSpatialFilterPolygon = OGR_G_CreateGeometry( wkbPolygon ); OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing ); OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny); OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy); OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy); OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); OGR_G_AddGeometryDirectly( hSpatialFilterPolygon, hRing ); OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon ); OGR_G_DestroyGeometry( hSpatialFilterPolygon ); } psInfo->rect = rect; if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("msOGRFileWhichShapes: Setting spatial filter to %f %f %f %f\n", rect.minx, rect.miny, rect.maxx, rect.maxy ); /* ------------------------------------------------------------------ * Apply an attribute filter if we have one prefixed with a WHERE * keyword in the filter string. Otherwise, ensure the attribute * filter is clear. * ------------------------------------------------------------------ */ if( layer->filter.string && EQUALN(layer->filter.string,"WHERE ",6) ) { CPLErrorReset(); if( OGR_L_SetAttributeFilter( psInfo->hLayer, layer->filter.string+6 ) != OGRERR_NONE ) { msSetError(MS_OGRERR, "SetAttributeFilter(%s) failed on layer %s.\n%s", "msOGRFileWhichShapes()", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; return MS_FAILURE; } } else OGR_L_SetAttributeFilter( psInfo->hLayer, NULL ); /* ------------------------------------------------------------------ * Reset current feature pointer * ------------------------------------------------------------------ */ OGR_L_ResetReading( psInfo->hLayer ); psInfo->last_record_index_read = -1; RELEASE_OGR_LOCK; return MS_SUCCESS; } /********************************************************************** * msOGRPassThroughFieldDefinitions() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ static void msOGRPassThroughFieldDefinitions( layerObj *layer, msOGRFileInfo *psInfo ) { OGRFeatureDefnH hDefn = OGR_L_GetLayerDefn( psInfo->hLayer ); int numitems, i; numitems = OGR_FD_GetFieldCount( hDefn ); for(i=0; i 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); break; case OFTReal: gml_type = "Real"; if( OGR_Fld_GetWidth( hField) > 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); if( OGR_Fld_GetPrecision( hField ) > 0 ) sprintf( gml_precision, "%d", OGR_Fld_GetPrecision( hField) ); break; case OFTString: gml_type = "Character"; if( OGR_Fld_GetWidth( hField) > 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); break; case OFTDate: case OFTTime: case OFTDateTime: gml_type = "Date"; break; default: gml_type = "Character"; break; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } /* Should we try to address style items, or other special items? */ } /********************************************************************** * msOGRFileGetItems() * * Returns a list of field names in a NULL terminated list of strings. **********************************************************************/ static char **msOGRFileGetItems(layerObj *layer, msOGRFileInfo *psInfo ) { OGRFeatureDefnH hDefn; int i, numitems,totalnumitems; int numStyleItems = MSOGR_LABELNUMITEMS; char **items; const char *getShapeStyleItems, *value; if((hDefn = OGR_L_GetLayerDefn( psInfo->hLayer )) == NULL) { msSetError(MS_OGRERR, "OGR Connection for layer `%s' contains no field definition.", "msOGRFileGetItems()", layer->name?layer->name:"(null)" ); return NULL; } totalnumitems = numitems = OGR_FD_GetFieldCount( hDefn ); getShapeStyleItems = msLayerGetProcessingKey( layer, "GETSHAPE_STYLE_ITEMS" ); if (getShapeStyleItems && EQUAL(getShapeStyleItems, "all")) totalnumitems += numStyleItems; if((items = (char**)malloc(sizeof(char *)*(totalnumitems+1))) == NULL) { msSetError(MS_MEMERR, NULL, "msOGRFileGetItems()"); return NULL; } for(i=0; imetadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msOGRPassThroughFieldDefinitions( layer, psInfo ); return items; } /********************************************************************** * msOGRFileNextShape() * * Returns shape sequentially from OGR data source. * msOGRLayerWhichShape() must have been called first. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ static int msOGRFileNextShape(layerObj *layer, shapeObj *shape, msOGRFileInfo *psInfo ) { OGRFeatureH hFeature = NULL; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileNextShape()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Read until we find a feature that matches attribute filter and * whose geometry is compatible with current layer type. * ------------------------------------------------------------------ */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; ACQUIRE_OGR_LOCK; while (shape->type == MS_SHAPE_NULL) { if( hFeature ) OGR_F_Destroy( hFeature ); if( (hFeature = OGR_L_GetNextFeature( psInfo->hLayer )) == NULL ) { psInfo->last_record_index_read = -1; if( CPLGetLastErrorType() == CE_Failure ) { msSetError(MS_OGRERR, "%s", "msOGRFileNextShape()", CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; return MS_FAILURE; } else { RELEASE_OGR_LOCK; if (layer->debug >= MS_DEBUGLEVEL_VV) msDebug("msOGRFileNextShape: Returning MS_DONE (no more shapes)\n" ); return MS_DONE; // No more features to read } } psInfo->last_record_index_read++; if(layer->numitems > 0) { shape->values = msOGRGetValues(layer, hFeature); shape->numvalues = layer->numitems; if(!shape->values) { OGR_F_Destroy( hFeature ); RELEASE_OGR_LOCK; return(MS_FAILURE); } } // Check the expression unless it is a WHERE clause already // handled by OGR. if( (layer->filter.string && EQUALN(layer->filter.string,"WHERE ",6)) || msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex) == MS_TRUE ) { // Feature matched filter expression... process geometry // shape->type will be set if geom is compatible with layer type if (ogrConvertGeometry(OGR_F_GetGeometryRef( hFeature ), shape, layer->type) == MS_SUCCESS) { if (shape->type != MS_SHAPE_NULL) break; // Shape is ready to be returned! if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("msOGRFileNextShape: Rejecting feature (shapeid = %ld, tileid=%d) of incompatible type for this layer (feature wkbType %d, layer type %d)\n", OGR_F_GetFID( hFeature ), psInfo->nTileId, OGR_F_GetGeometryRef( hFeature )==NULL ? wkbFlatten(wkbUnknown):wkbFlatten( OGR_G_GetGeometryType( OGR_F_GetGeometryRef( hFeature ) ) ), layer->type); } else { msFreeShape(shape); OGR_F_Destroy( hFeature ); RELEASE_OGR_LOCK; return MS_FAILURE; // Error message already produced. } } // Feature rejected... free shape to clear attributes values. msFreeShape(shape); shape->type = MS_SHAPE_NULL; } shape->index = OGR_F_GetFID( hFeature );; shape->resultindex = psInfo->last_record_index_read; shape->tileindex = psInfo->nTileId; if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("msOGRFileNextShape: Returning shape=%ld, tile=%d\n", shape->index, shape->tileindex ); // Keep ref. to last feature read in case we need style info. if (psInfo->hLastFeature) OGR_F_Destroy( psInfo->hLastFeature ); psInfo->hLastFeature = hFeature; RELEASE_OGR_LOCK; return MS_SUCCESS; } /********************************************************************** * msOGRFileGetShape() * * Returns shape from OGR data source by id. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ static int msOGRFileGetShape(layerObj *layer, shapeObj *shape, long record, msOGRFileInfo *psInfo, int record_is_fid ) { OGRFeatureH hFeature; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileNextShape()"); return(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* Clear previously loaded shape. */ /* -------------------------------------------------------------------- */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; /* -------------------------------------------------------------------- */ /* Support reading feature by fid. */ /* -------------------------------------------------------------------- */ if( record_is_fid ) { ACQUIRE_OGR_LOCK; if( (hFeature = OGR_L_GetFeature( psInfo->hLayer, record )) == NULL ) { RELEASE_OGR_LOCK; return MS_FAILURE; } } /* -------------------------------------------------------------------- */ /* Support reading shape by offset within the current */ /* resultset. */ /* -------------------------------------------------------------------- */ else if( !record_is_fid ) { ACQUIRE_OGR_LOCK; if( record <= psInfo->last_record_index_read || psInfo->last_record_index_read == -1 ) { OGR_L_ResetReading( psInfo->hLayer ); psInfo->last_record_index_read = -1; } hFeature = NULL; while( psInfo->last_record_index_read < record ) { if( hFeature != NULL ) { OGR_F_Destroy( hFeature ); hFeature = NULL; } if( (hFeature = OGR_L_GetNextFeature( psInfo->hLayer )) == NULL ) { RELEASE_OGR_LOCK; return MS_FAILURE; } psInfo->last_record_index_read++; } } /* ------------------------------------------------------------------ * Handle shape geometry... * ------------------------------------------------------------------ */ // shape->type will be set if geom is compatible with layer type if (ogrConvertGeometry(OGR_F_GetGeometryRef( hFeature ), shape, layer->type) != MS_SUCCESS) { RELEASE_OGR_LOCK; return MS_FAILURE; // Error message already produced. } if (shape->type == MS_SHAPE_NULL) { msSetError(MS_OGRERR, "Requested feature is incompatible with layer type", "msOGRLayerGetShape()"); RELEASE_OGR_LOCK; return MS_FAILURE; } /* ------------------------------------------------------------------ * Process shape attributes * ------------------------------------------------------------------ */ if(layer->numitems > 0) { shape->values = msOGRGetValues(layer, hFeature); shape->numvalues = layer->numitems; if(!shape->values) { RELEASE_OGR_LOCK; return(MS_FAILURE); } } if (record_is_fid) { shape->index = record; shape->resultindex = -1; } else { shape->index = OGR_F_GetFID( hFeature ); shape->resultindex = record; } shape->tileindex = psInfo->nTileId; // Keep ref. to last feature read in case we need style info. if (psInfo->hLastFeature) OGR_F_Destroy( psInfo->hLastFeature ); psInfo->hLastFeature = hFeature; RELEASE_OGR_LOCK; return MS_SUCCESS; } /************************************************************************/ /* msOGRFileReadTile() */ /* */ /* Advance to the next tile (or if targetTile is not -1 advance */ /* to that tile), causing the tile to become the poCurTile in */ /* the tileindexes psInfo structure. Returns MS_DONE if there */ /* are no more available tiles. */ /* */ /* Newly loaded tiles are automatically "WhichShaped" based on */ /* the current rectangle. */ /************************************************************************/ int msOGRFileReadTile( layerObj *layer, msOGRFileInfo *psInfo, int targetTile = -1 ) { int nFeatureId; /* -------------------------------------------------------------------- */ /* Close old tile if one is open. */ /* -------------------------------------------------------------------- */ if( psInfo->poCurTile != NULL ) { msOGRFileClose( layer, psInfo->poCurTile ); psInfo->poCurTile = NULL; } /* -------------------------------------------------------------------- */ /* If -2 is passed, then seek reset reading of the tileindex. */ /* We want to start from the beginning even if this file is */ /* shared between layers or renders. */ /* -------------------------------------------------------------------- */ ACQUIRE_OGR_LOCK; if( targetTile == -2 ) { OGR_L_ResetReading( psInfo->hLayer ); } /* -------------------------------------------------------------------- */ /* Get the name (connection string really) of the next tile. */ /* -------------------------------------------------------------------- */ OGRFeatureH hFeature; char *connection = NULL; msOGRFileInfo *psTileInfo = NULL; int status; #ifndef IGNORE_MISSING_DATA NextFile: #endif if( targetTile < 0 ) hFeature = OGR_L_GetNextFeature( psInfo->hLayer ); else hFeature = OGR_L_GetFeature( psInfo->hLayer, targetTile ); if( hFeature == NULL ) { RELEASE_OGR_LOCK; if( targetTile == -1 ) return MS_DONE; else return MS_FAILURE; } connection = msStrdup( OGR_F_GetFieldAsString( hFeature, layer->tileitemindex )); nFeatureId = OGR_F_GetFID( hFeature ); OGR_F_Destroy( hFeature ); RELEASE_OGR_LOCK; /* -------------------------------------------------------------------- */ /* Open the new tile file. */ /* -------------------------------------------------------------------- */ psTileInfo = msOGRFileOpen( layer, connection ); free( connection ); #ifndef IGNORE_MISSING_DATA if( psTileInfo == NULL && targetTile == -1 ) goto NextFile; #endif if( psTileInfo == NULL ) return MS_FAILURE; psTileInfo->nTileId = nFeatureId; /* -------------------------------------------------------------------- */ /* Initialize the spatial query on this file. */ /* -------------------------------------------------------------------- */ if( psInfo->rect.minx != 0 || psInfo->rect.maxx != 0 ) { status = msOGRFileWhichShapes( layer, psInfo->rect, psTileInfo ); if( status != MS_SUCCESS ) return status; } psInfo->poCurTile = psTileInfo; /* -------------------------------------------------------------------- */ /* Update the iteminfo in case this layer has a different field */ /* list. */ /* -------------------------------------------------------------------- */ msOGRLayerInitItemInfo( layer ); return MS_SUCCESS; } #endif /* def USE_OGR */ /* ================================================================== * Here comes the REAL stuff... the functions below are called by maplayer.c * ================================================================== */ /********************************************************************** * msOGRLayerOpen() * * Open OGR data source for the specified map layer. * * If pszOverrideConnection != NULL then this value is used as the connection * string instead of lp->connection. This is used for instance to open * a WFS layer, in this case lp->connection is the WFS url, but we want * OGR to open the local file on disk that was previously downloaded. * * An OGR connection string is: [,] * is file format specific * (optional) is the OGR layer index * default is 0, the first layer. * * One can use the "ogrinfo" program to find out the layer indices in a dataset * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerOpen(layerObj *layer, const char *pszOverrideConnection) { #ifdef USE_OGR msOGRFileInfo *psInfo; if (layer->layerinfo != NULL) { return MS_SUCCESS; // Nothing to do... layer is already opened } /* -------------------------------------------------------------------- */ /* If this is not a tiled layer, just directly open the target. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) { psInfo = msOGRFileOpen( layer, (pszOverrideConnection ? pszOverrideConnection: layer->connection) ); layer->layerinfo = psInfo; layer->tileitemindex = -1; if( layer->layerinfo == NULL ) return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Otherwise we open the tile index, identify the tile item */ /* index and try to select the first file matching our query */ /* region. */ /* -------------------------------------------------------------------- */ else { // Open tile index psInfo = msOGRFileOpen( layer, layer->tileindex ); layer->layerinfo = psInfo; if( layer->layerinfo == NULL ) return MS_FAILURE; if( layer->tilesrs != NULL ) { msSetError(MS_OGRERR, "TILESRS not supported in vector layers.", "msOGRLayerOpen()"); return MS_FAILURE; } // Identify TILEITEM OGRFeatureDefnH hDefn = OGR_L_GetLayerDefn( psInfo->hLayer ); for( layer->tileitemindex = 0; layer->tileitemindex < OGR_FD_GetFieldCount( hDefn ) && !EQUAL( OGR_Fld_GetNameRef( OGR_FD_GetFieldDefn( hDefn, layer->tileitemindex) ), layer->tileitem); layer->tileitemindex++ ) {} if( layer->tileitemindex == OGR_FD_GetFieldCount( hDefn ) ) { msSetError(MS_OGRERR, "Can't identify TILEITEM %s field in TILEINDEX `%s'.", "msOGRLayerOpen()", layer->tileitem, layer->tileindex ); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; return MS_FAILURE; } } /* ------------------------------------------------------------------ * If projection was "auto" then set proj to the dataset's projection. * For a tile index, it is assume the tile index has the projection. * ------------------------------------------------------------------ */ #ifdef USE_PROJ if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { ACQUIRE_OGR_LOCK; OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( psInfo->hLayer ); if (msOGRSpatialRef2ProjectionObj(hSRS, &(layer->projection), layer->debug ) != MS_SUCCESS) { errorObj *ms_error = msGetErrorObj(); RELEASE_OGR_LOCK; msSetError(MS_OGRERR, "%s " "PROJECTION AUTO cannot be used for this " "OGR connection (in layer `%s').", "msOGRLayerOpen()", ms_error->message, layer->name?layer->name:"(null)" ); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; return(MS_FAILURE); } RELEASE_OGR_LOCK; } #endif return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerOpen()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerOpenVT() * * Overloaded version of msOGRLayerOpen for virtual table architecture **********************************************************************/ static int msOGRLayerOpenVT(layerObj *layer) { return msOGRLayerOpen(layer, NULL); } /********************************************************************** * msOGRLayerClose() **********************************************************************/ int msOGRLayerClose(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo) { if( layer->debug ) msDebug("msOGRLayerClose(%s).\n", layer->connection); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; } return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerClose()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerIsOpen() **********************************************************************/ static int msOGRLayerIsOpen(layerObj *layer) { #ifdef USE_OGR if (layer->layerinfo) return MS_TRUE; return MS_FALSE; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerIsOpen()"); return(MS_FALSE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerWhichShapes() * * Init OGR layer structs ready for calls to msOGRLayerNextShape(). * * Returns MS_SUCCESS/MS_FAILURE, or MS_DONE if no shape matching the * layer's FILTER overlaps the selected region. **********************************************************************/ int msOGRLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; int status; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerWhichShapes()"); return(MS_FAILURE); } status = msOGRFileWhichShapes( layer, rect, psInfo ); if( status != MS_SUCCESS || layer->tileindex == NULL ) return status; // If we are using a tile index, we need to advance to the first // tile matching the spatial query, and load it. return msOGRFileReadTile( layer, psInfo ); #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerWhichShapes()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetItems() * * Load item (i.e. field) names in a char array. If we are working * with a tiled layer, ensure a tile is loaded and use it for the items. * It is implicitly assumed that the schemas will match on all tiles. **********************************************************************/ int msOGRLayerGetItems(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetItems()"); return(MS_FAILURE); } if( layer->tileindex != NULL ) { if( psInfo->poCurTile == NULL && msOGRFileReadTile( layer, psInfo ) != MS_SUCCESS ) return MS_FAILURE; psInfo = psInfo->poCurTile; } layer->numitems = 0; layer->items = msOGRFileGetItems(layer, psInfo); if( layer->items == NULL ) return MS_FAILURE; while( layer->items[layer->numitems] != NULL ) layer->numitems++; return msOGRLayerInitItemInfo(layer); #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetItems()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerInitItemInfo() * * Init the itemindexes array after items[] has been reset in a layer. **********************************************************************/ static int msOGRLayerInitItemInfo(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; int i; OGRFeatureDefnH hDefn; if (layer->numitems == 0) return MS_SUCCESS; if( layer->tileindex != NULL ) { if( psInfo->poCurTile == NULL && msOGRFileReadTile( layer, psInfo, -2 ) != MS_SUCCESS ) return MS_FAILURE; psInfo = psInfo->poCurTile; } if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerInitItemInfo()"); return(MS_FAILURE); } if((hDefn = OGR_L_GetLayerDefn( psInfo->hLayer )) == NULL) { msSetError(MS_OGRERR, "Layer contains no fields.", "msOGRLayerInitItemInfo()"); return(MS_FAILURE); } if (layer->iteminfo) free(layer->iteminfo); if((layer->iteminfo = (int *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msOGRLayerInitItemInfo()"); return(MS_FAILURE); } int *itemindexes = (int*)layer->iteminfo; for(i=0; inumitems; i++) { // Special case for handling text string and angle coming from // OGR style strings. We use special attribute snames. if (EQUAL(layer->items[i], MSOGR_LABELFONTNAMENAME)) itemindexes[i] = MSOGR_LABELFONTNAMEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELSIZENAME)) itemindexes[i] = MSOGR_LABELSIZEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELTEXTNAME)) itemindexes[i] = MSOGR_LABELTEXTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELANGLENAME)) itemindexes[i] = MSOGR_LABELANGLEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELFCOLORNAME)) itemindexes[i] = MSOGR_LABELFCOLORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELBCOLORNAME)) itemindexes[i] = MSOGR_LABELBCOLORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELPLACEMENTNAME)) itemindexes[i] = MSOGR_LABELPLACEMENTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELANCHORNAME)) itemindexes[i] = MSOGR_LABELANCHORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELDXNAME)) itemindexes[i] = MSOGR_LABELDXINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELDYNAME)) itemindexes[i] = MSOGR_LABELDYINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELPERPNAME)) itemindexes[i] = MSOGR_LABELPERPINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELBOLDNAME)) itemindexes[i] = MSOGR_LABELBOLDINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELITALICNAME)) itemindexes[i] = MSOGR_LABELITALICINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELUNDERLINENAME)) itemindexes[i] = MSOGR_LABELUNDERLINEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELPRIORITYNAME)) itemindexes[i] = MSOGR_LABELPRIORITYINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELSTRIKEOUTNAME)) itemindexes[i] = MSOGR_LABELSTRIKEOUTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELSTRETCHNAME)) itemindexes[i] = MSOGR_LABELSTRETCHINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELADJHORNAME)) itemindexes[i] = MSOGR_LABELADJHORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELADJVERTNAME)) itemindexes[i] = MSOGR_LABELADJVERTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELHCOLORNAME)) itemindexes[i] = MSOGR_LABELHCOLORINDEX; #if GDAL_VERSION_NUM >= 1600 else if (EQUAL(layer->items[i], MSOGR_LABELOCOLORNAME)) itemindexes[i] = MSOGR_LABELOCOLORINDEX; #endif /* GDAL_VERSION_NUM >= 1600 */ else if (EQUALN(layer->items[i], MSOGR_LABELPARAMNAME, MSOGR_LABELPARAMNAMELEN)) itemindexes[i] = MSOGR_LABELPARAMINDEX + atoi(layer->items[i] + MSOGR_LABELPARAMNAMELEN); else if (EQUALN(layer->items[i], MSOGR_BRUSHPARAMNAME, MSOGR_BRUSHPARAMNAMELEN)) itemindexes[i] = MSOGR_BRUSHPARAMINDEX + atoi(layer->items[i] + MSOGR_BRUSHPARAMNAMELEN); else if (EQUALN(layer->items[i], MSOGR_PENPARAMNAME, MSOGR_PENPARAMNAMELEN)) itemindexes[i] = MSOGR_PENPARAMINDEX + atoi(layer->items[i] + MSOGR_PENPARAMNAMELEN); else if (EQUALN(layer->items[i], MSOGR_SYMBOLPARAMNAME, MSOGR_SYMBOLPARAMNAMELEN)) itemindexes[i] = MSOGR_SYMBOLPARAMINDEX + atoi(layer->items[i] + MSOGR_SYMBOLPARAMNAMELEN); else itemindexes[i] = OGR_FD_GetFieldIndex( hDefn, layer->items[i] ); if(itemindexes[i] == -1) { msSetError(MS_OGRERR, "Invalid Field name: %s", "msOGRLayerInitItemInfo()", layer->items[i]); return(MS_FAILURE); } } return(MS_SUCCESS); #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerInitItemInfo()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerFreeItemInfo() * * Free the itemindexes array in a layer. **********************************************************************/ void msOGRLayerFreeItemInfo(layerObj *layer) { #ifdef USE_OGR if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerFreeItemInfo()"); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerNextShape() * * Returns shape sequentially from OGR data source. * msOGRLayerWhichShape() must have been called first. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; int status; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerNextShape()"); return(MS_FAILURE); } if( layer->tileindex == NULL ) return msOGRFileNextShape( layer, shape, psInfo ); // Do we need to load the first tile? if( psInfo->poCurTile == NULL ) { status = msOGRFileReadTile( layer, psInfo ); if( status != MS_SUCCESS ) return status; } do { // Try getting a shape from this tile. status = msOGRFileNextShape( layer, shape, psInfo->poCurTile ); if( status != MS_DONE ) return status; // try next tile. status = msOGRFileReadTile( layer, psInfo ); if( status != MS_SUCCESS ) return status; } while( status == MS_SUCCESS ); return status; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerNextShape()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetShape() * * Returns shape from OGR data source by fid. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; long shapeindex = record->shapeindex; int tileindex = record->tileindex; int resultindex = record->resultindex; int record_is_fid = TRUE; /* set the resultindex as shapeindex if available */ if (resultindex >= 0) { record_is_fid = FALSE; shapeindex = resultindex; } if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetShape()"); return(MS_FAILURE); } if( layer->tileindex == NULL ) return msOGRFileGetShape(layer, shape, shapeindex, psInfo, record_is_fid ); else { if( psInfo->poCurTile == NULL || psInfo->poCurTile->nTileId != tileindex ) { if( msOGRFileReadTile( layer, psInfo, tileindex ) != MS_SUCCESS ) return MS_FAILURE; } return msOGRFileGetShape(layer, shape, shapeindex, psInfo->poCurTile, record_is_fid ); } #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetShape()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetExtent() * * Returns the layer extents. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerGetExtent(layerObj *layer, rectObj *extent) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; OGREnvelope oExtent; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetExtent()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Call OGR's GetExtent()... note that for some formats this will * result in a scan of the whole layer and can be an expensive call. * * For tile indexes layers we assume it is sufficient to get the * extents of the tile index. * ------------------------------------------------------------------ */ ACQUIRE_OGR_LOCK; if (OGR_L_GetExtent( psInfo->hLayer, &oExtent, TRUE) != OGRERR_NONE) { RELEASE_OGR_LOCK; msSetError(MS_MISCERR, "Unable to get extents for this layer.", "msOGRLayerGetExtent()"); return(MS_FAILURE); } RELEASE_OGR_LOCK; extent->minx = oExtent.MinX; extent->miny = oExtent.MinY; extent->maxx = oExtent.MaxX; extent->maxy = oExtent.MaxY; return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetExtent()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRGetSymbolId() * * Returns a MapServer symbol number matching one of the symbols from * the OGR symbol id string. If not found then try to locate the * default symbol name, and if not found return 0. **********************************************************************/ #ifdef USE_OGR static int msOGRGetSymbolId(symbolSetObj *symbolset, const char *pszSymbolId, const char *pszDefaultSymbol, int try_addimage_if_notfound) { // Symbol name mapping: // First look for the native symbol name, then the ogr-... // generic name, and in last resort try pszDefaultSymbol if // provided by user. char **params; int numparams; int nSymbol = -1; if (pszSymbolId && pszSymbolId[0] != '\0') { #if GDAL_VERSION_NUM >= 1800 /* Use comma as the separator */ params = msStringSplit(pszSymbolId, ',', &numparams); #else params = msStringSplit(pszSymbolId, '.', &numparams); #endif if (params != NULL) { for(int j=0; jcellsize*72.0*39.37); if (eStylePartType == OGRSTCLabel) { OGRStyleToolH hLabelStyle = hStylePart; // Enclose the text string inside quotes to make sure it is seen // as a string by the parser inside loadExpression(). (bug185) /* See bug 3481 about the isalnum hack */ const char *labelTextString = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelTextString, &bIsNull); msLoadExpressionString(&(c->text),(char*)labelTextString); if (c->numlabels == 0) { /* allocate a new label object */ if(msGrowClassLabels(c) == NULL) return MS_FAILURE; c->numlabels++; initLabel(c->labels[0]); } c->labels[0]->angle = OGR_ST_GetParamDbl(hLabelStyle, OGRSTLabelAngle, &bIsNull); c->labels[0]->size = OGR_ST_GetParamDbl(hLabelStyle, OGRSTLabelSize, &bIsNull); if( c->labels[0]->size < 1 ) /* no point dropping to zero size */ c->labels[0]->size = 1; // OGR default is anchor point = LL, so label is at UR of anchor c->labels[0]->position = MS_UR; int nPosition = OGR_ST_GetParamNum(hLabelStyle, OGRSTLabelAnchor, &bIsNull); if( !bIsNull ) { switch( nPosition ) { case 1: c->labels[0]->position = MS_UR; break; case 2: c->labels[0]->position = MS_UC; break; case 3: c->labels[0]->position = MS_UL; break; case 4: c->labels[0]->position = MS_CR; break; case 5: c->labels[0]->position = MS_CC; break; case 6: c->labels[0]->position = MS_CL; break; case 7: c->labels[0]->position = MS_LR; break; case 8: c->labels[0]->position = MS_LC; break; case 9: c->labels[0]->position = MS_LL; break; case 10: c->labels[0]->position = MS_UR; break; /*approximate*/ case 11: c->labels[0]->position = MS_UC; break; case 12: c->labels[0]->position = MS_UL; break; default: break; } } const char *pszColor = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hLabelStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->labels[0]->color, r, g, b, t); } pszColor = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelHColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hLabelStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->labels[0]->shadowcolor, r, g, b, t); } #if GDAL_VERSION_NUM >= 1600 pszColor = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelOColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hLabelStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->labels[0]->outlinecolor, r, g, b, t); } #endif /* GDAL_VERSION_NUM >= 1600 */ const char *pszBold = OGR_ST_GetParamNum(hLabelStyle, OGRSTLabelBold, &bIsNull) ? "-bold" : ""; const char *pszItalic = OGR_ST_GetParamNum(hLabelStyle, OGRSTLabelItalic, &bIsNull) ? "-italic" : ""; const char *pszFontName = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFontName, &bIsNull); /* replace spaces with hyphens to allow mapping to a valid hashtable entry*/ char* pszFontNameEscaped = NULL; if (pszFontName != NULL) { pszFontNameEscaped = strdup(pszFontName); msReplaceChar(pszFontNameEscaped, ' ', '-'); } const char *pszName = CPLSPrintf("%s%s%s", pszFontNameEscaped, pszBold, pszItalic); bool bFont = true; if (pszFontNameEscaped != NULL && !bIsNull && pszFontNameEscaped[0] != '\0') { if (msLookupHashTable(&(map->fontset.fonts), (char*)pszName) != NULL) { c->labels[0]->type = MS_TRUETYPE; c->labels[0]->font = msStrdup(pszName); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using '%s' TTF font **\n", pszName); } else if ( (strcmp(pszFontNameEscaped,pszName) != 0) && msLookupHashTable(&(map->fontset.fonts), (char*)pszFontNameEscaped) != NULL) { c->labels[0]->type = MS_TRUETYPE; c->labels[0]->font = msStrdup(pszFontNameEscaped); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using '%s' TTF font **\n", pszFontNameEscaped); } else if (msLookupHashTable(&(map->fontset.fonts),"default") != NULL) { c->labels[0]->type = MS_TRUETYPE; c->labels[0]->font = msStrdup("default"); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using 'default' TTF font **\n"); } else bFont = false; } msFree(pszFontNameEscaped); if (!bFont) { c->labels[0]->type = MS_BITMAP; c->labels[0]->size = MS_MEDIUM; if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using 'medium' BITMAP font **\n"); } } else if (eStylePartType == OGRSTCPen) { OGRStyleToolH hPenStyle = hStylePart; const char *pszPenName = OGR_ST_GetParamStr(hPenStyle, OGRSTPenId, &bIsNull); if (bIsNull) pszPenName = NULL; colorObj oPenColor; int nPenSymbol = 0; int nPenSize = 1; t =-1; // Make sure pen is always initialized MS_INIT_COLOR(oPenColor, -1, -1, -1,255); // Check for Pen Pattern "ogr-pen-1": the invisible pen // If that's what we have then set pen color to -1 if (pszPenName && strstr(pszPenName, "ogr-pen-1") != NULL) { MS_INIT_COLOR(oPenColor, -1, -1, -1,255); } else { const char *pszColor = OGR_ST_GetParamStr(hPenStyle, OGRSTPenColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hPenStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(oPenColor, r, g, b, t); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** PEN COLOR = %d %d %d **\n", r,g,b); } nPenSize = OGR_ST_GetParamNum(hPenStyle, OGRSTPenWidth, &bIsNull); if (bIsNull) nPenSize = 1; if (pszPenName!=NULL) { // Try to match pen name in symbol file nPenSymbol = msOGRGetSymbolId(&(map->symbolset), pszPenName, NULL, MS_FALSE); } } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** PEN COLOR = %d %d %d **\n", oPenColor.red,oPenColor.green,oPenColor.blue); if (bIsBrush || layer->type == MS_LAYER_POLYGON) { // This is a multipart symbology, so pen defn goes in the // overlaysymbol params if (msMaybeAllocateClassStyle(c, 1)) { OGR_ST_Destroy(hStylePart); return(MS_FAILURE); } c->styles[1]->outlinecolor = oPenColor; c->styles[1]->size = nPenSize; c->styles[1]->symbol = nPenSymbol; c->styles[1]->width = nPenSize; } else { // Single part symbology if (msMaybeAllocateClassStyle(c, 0)) { OGR_ST_Destroy(hStylePart); return(MS_FAILURE); } if(layer->type == MS_LAYER_POLYGON) c->styles[0]->outlinecolor = c->styles[0]->color = oPenColor; else c->styles[0]->color = oPenColor; c->styles[0]->symbol = nPenSymbol; c->styles[0]->size = nPenSize; c->styles[0]->width = nPenSize; } } else if (eStylePartType == OGRSTCBrush) { OGRStyleToolH hBrushStyle = hStylePart; const char *pszBrushName = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushId, &bIsNull); if (bIsNull) pszBrushName = NULL; /* We need 1 style */ if (msMaybeAllocateClassStyle(c, 0)) { OGR_ST_Destroy(hStylePart); return(MS_FAILURE); } // Check for Brush Pattern "ogr-brush-1": the invisible fill // If that's what we have then set fill color to -1 if (pszBrushName && strstr(pszBrushName, "ogr-brush-1") != NULL) { MS_INIT_COLOR(c->styles[0]->color, -1, -1, -1, 255); } else { bIsBrush = TRUE; const char *pszColor = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushFColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hBrushStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->styles[0]->color, r, g, b, t); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** BRUSH COLOR = %d %d %d **\n", r,g,b); } pszColor = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushBColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hBrushStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->styles[0]->backgroundcolor, r, g, b, t); } // Symbol name mapping: // First look for the native symbol name, then the ogr-... // generic name. // If none provided or found then use 0: solid fill const char *pszName = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushId, &bIsNull); c->styles[0]->symbol = msOGRGetSymbolId(&(map->symbolset), pszName, NULL, MS_FALSE); } } else if (eStylePartType == OGRSTCSymbol) { OGRStyleToolH hSymbolStyle = hStylePart; /* We need 1 style */ if (msMaybeAllocateClassStyle(c, 0)) { OGR_ST_Destroy(hStylePart); return(MS_FAILURE); } const char *pszColor = OGR_ST_GetParamStr(hSymbolStyle, OGRSTSymbolColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hSymbolStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->styles[0]->color, r, g, b, t); } #if GDAL_VERSION_NUM >= 1600 pszColor = OGR_ST_GetParamStr(hSymbolStyle, OGRSTSymbolOColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hSymbolStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->styles[0]->outlinecolor, r, g, b, t); } #endif /* GDAL_VERSION_NUM >= 1600 */ c->styles[0]->angle = OGR_ST_GetParamNum(hSymbolStyle, OGRSTSymbolAngle, &bIsNull); dfTmp = OGR_ST_GetParamNum(hSymbolStyle, OGRSTSymbolSize, &bIsNull); if (!bIsNull) c->styles[0]->size = dfTmp; // Symbol name mapping: // First look for the native symbol name, then the ogr-... // generic name, and in last resort try "default-marker" if // provided by user. const char *pszName = OGR_ST_GetParamStr(hSymbolStyle, OGRSTSymbolId, &bIsNull); if (bIsNull) pszName = NULL; try_addimage_if_notfound = MS_FALSE; #ifdef USE_CURL if (pszName && strncasecmp(pszName, "http", 4) == 0) try_addimage_if_notfound =MS_TRUE; #endif if (!c->styles[0]->symbolname) c->styles[0]->symbol = msOGRGetSymbolId(&(map->symbolset), pszName, "default-marker", try_addimage_if_notfound); } OGR_ST_Destroy(hStylePart); } return MS_SUCCESS; } #endif /* USE_OGR */ /********************************************************************** * msOGRLayerGetAutoStyle() * * Fills a classObj with style info from the specified shape. * For optimal results, this should be called immediately after * GetNextShape() or GetShape() so that the shape doesn't have to be read * twice. * * The returned classObj is a ref. to a static structure valid only until * the next call and that shouldn't be freed by the caller. **********************************************************************/ static int msOGRLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); } if( layer->tileindex != NULL ) { if( (psInfo->poCurTile == NULL || shape->tileindex != psInfo->poCurTile->nTileId) && msOGRFileReadTile( layer, psInfo ) != MS_SUCCESS ) return MS_FAILURE; psInfo = psInfo->poCurTile; } /* ------------------------------------------------------------------ * Read shape or reuse ref. to last shape read. * ------------------------------------------------------------------ */ ACQUIRE_OGR_LOCK; if (psInfo->hLastFeature == NULL || psInfo->last_record_index_read != shape->resultindex) { RELEASE_OGR_LOCK; msSetError(MS_MISCERR, "Assertion failed: AutoStyle not requested on loaded shape.", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Reset style info in the class to defaults * the only members we don't touch are name, expression, and join/query stuff * ------------------------------------------------------------------ */ resetClassStyle(c); if (msMaybeAllocateClassStyle(c, 0)) { RELEASE_OGR_LOCK; return(MS_FAILURE); } // __TODO__ label cache incompatible with styleitem feature. layer->labelcache = MS_OFF; int nRetVal = MS_SUCCESS; if (psInfo->hLastFeature) { OGRStyleMgrH hStyleMgr = OGR_SM_Create(NULL); OGR_SM_InitFromFeature(hStyleMgr, psInfo->hLastFeature); nRetVal = msOGRUpdateStyle(hStyleMgr, map, layer, c); OGR_SM_Destroy(hStyleMgr); } RELEASE_OGR_LOCK; return nRetVal; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRUpdateStyleFromString() * * Fills a classObj with style info from the specified style string. * For optimal results, this should be called immediately after * GetNextShape() or GetShape() so that the shape doesn't have to be read * twice. * * The returned classObj is a ref. to a static structure valid only until * the next call and that shouldn't be freed by the caller. **********************************************************************/ int msOGRUpdateStyleFromString(mapObj *map, layerObj *layer, classObj *c, const char *stylestring) { #ifdef USE_OGR /* ------------------------------------------------------------------ * Reset style info in the class to defaults * the only members we don't touch are name, expression, and join/query stuff * ------------------------------------------------------------------ */ resetClassStyle(c); if (msMaybeAllocateClassStyle(c, 0)) { return(MS_FAILURE); } // __TODO__ label cache incompatible with styleitem feature. layer->labelcache = MS_OFF; int nRetVal = MS_SUCCESS; ACQUIRE_OGR_LOCK; OGRStyleMgrH hStyleMgr = OGR_SM_Create(NULL); OGR_SM_InitStyleString(hStyleMgr, stylestring); nRetVal = msOGRUpdateStyle(hStyleMgr, map, layer, c); OGR_SM_Destroy(hStyleMgr); RELEASE_OGR_LOCK; return nRetVal; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); #endif /* USE_OGR */ } /************************************************************************/ /* msOGRLCleanup() */ /************************************************************************/ void msOGRCleanup( void ) { #if defined(USE_OGR) ACQUIRE_OGR_LOCK; if( bOGRDriversRegistered == MS_TRUE ) { CPLPopErrorHandler(); OGRCleanupAll(); bOGRDriversRegistered = MS_FALSE; } RELEASE_OGR_LOCK; #endif } /************************************************************************/ /* msOGREscapeSQLParam */ /************************************************************************/ char *msOGREscapeSQLParam(layerObj *layer, const char *pszString) { #ifdef USE_OGR char* pszEscapedStr =NULL; if(layer && pszString && strlen(pszString) > 0) { char* pszEscapedOGRStr = CPLEscapeString(pszString, strlen(pszString), CPLES_SQL ); pszEscapedStr = msStrdup(pszEscapedOGRStr); CPLFree(pszEscapedOGRStr); } return pszEscapedStr; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGREscapeSQLParam()"); return NULL; #endif /* USE_OGR */ } /************************************************************************/ /* msOGREscapeSQLParam */ /************************************************************************/ char *msOGREscapePropertyName(layerObj *layer, const char *pszString) { #ifdef USE_OGR char* pszEscapedStr =NULL; int i =0; if(layer && pszString && strlen(pszString) > 0) { unsigned char ch; for(i=0; (ch = ((unsigned char*)pszString)[i]) != '\0'; i++) { if ( !(isalnum(ch) || ch == '_' || ch > 127) ) { return msStrdup("invalid_property_name"); } } pszEscapedStr = msStrdup(pszString); } return pszEscapedStr; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGREscapePropertyName()"); return NULL; #endif /* USE_OGR */ } /************************************************************************/ /* msOGRLayerInitializeVirtualTable() */ /************************************************************************/ int msOGRLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msOGRLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msOGRLayerFreeItemInfo; layer->vtable->LayerOpen = msOGRLayerOpenVT; layer->vtable->LayerIsOpen = msOGRLayerIsOpen; layer->vtable->LayerWhichShapes = msOGRLayerWhichShapes; layer->vtable->LayerNextShape = msOGRLayerNextShape; layer->vtable->LayerGetShape = msOGRLayerGetShape; layer->vtable->LayerClose = msOGRLayerClose; layer->vtable->LayerGetItems = msOGRLayerGetItems; layer->vtable->LayerGetExtent = msOGRLayerGetExtent; layer->vtable->LayerGetAutoStyle = msOGRLayerGetAutoStyle; /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection, use defaut*/ layer->vtable->LayerEscapeSQLParam = msOGREscapeSQLParam; layer->vtable->LayerEscapePropertyName = msOGREscapePropertyName; return MS_SUCCESS; } /************************************************************************/ /* msOGRShapeFromWKT() */ /************************************************************************/ shapeObj *msOGRShapeFromWKT(const char *string) { #ifdef USE_OGR OGRGeometryH hGeom = NULL; shapeObj *shape=NULL; if(!string) return NULL; if( OGR_G_CreateFromWkt( (char **)&string, NULL, &hGeom ) != OGRERR_NONE ) { msSetError(MS_OGRERR, "Failed to parse WKT string.", "msOGRShapeFromWKT()" ); return NULL; } /* Initialize a corresponding shapeObj */ shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); /* translate WKT into an OGRGeometry. */ if( msOGRGeometryToShape( hGeom, shape, wkbFlatten(OGR_G_GetGeometryType(hGeom)) ) == MS_FAILURE ) { free( shape ); return NULL; } OGR_G_DestroyGeometry( hGeom ); return shape; #else msSetError(MS_OGRERR, "OGR support is not available.","msOGRShapeFromWKT()"); return NULL; #endif } /************************************************************************/ /* msOGRShapeToWKT() */ /************************************************************************/ char *msOGRShapeToWKT(shapeObj *shape) { #ifdef USE_OGR OGRGeometryH hGeom = NULL; int i; char *wkt = NULL; if(!shape) return NULL; if( shape->type == MS_SHAPE_POINT && shape->numlines == 1 && shape->line[0].numpoints == 1 ) { hGeom = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hGeom, 0, shape->line[0].point[0].x, shape->line[0].point[0].y ); } else if( shape->type == MS_SHAPE_POINT && shape->numlines == 1 && shape->line[0].numpoints > 1 ) { hGeom = OGR_G_CreateGeometry( wkbMultiPoint ); for( i = 0; i < shape->line[0].numpoints; i++ ) { OGRGeometryH hPoint; hPoint = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hPoint, 0, shape->line[0].point[i].x, shape->line[0].point[i].y ); OGR_G_AddGeometryDirectly( hGeom, hPoint ); } } else if( shape->type == MS_SHAPE_LINE && shape->numlines == 1 ) { hGeom = OGR_G_CreateGeometry( wkbLineString ); for( i = 0; i < shape->line[0].numpoints; i++ ) { OGR_G_AddPoint_2D( hGeom, shape->line[0].point[i].x, shape->line[0].point[i].y ); } } else if( shape->type == MS_SHAPE_LINE && shape->numlines > 1 ) { OGRGeometryH hMultiLine = OGR_G_CreateGeometry( wkbMultiLineString ); int iLine; for( iLine = 0; iLine < shape->numlines; iLine++ ) { hGeom = OGR_G_CreateGeometry( wkbLineString ); for( i = 0; i < shape->line[iLine].numpoints; i++ ) { OGR_G_AddPoint_2D( hGeom, shape->line[iLine].point[i].x, shape->line[iLine].point[i].y ); } OGR_G_AddGeometryDirectly( hMultiLine, hGeom ); } hGeom = hMultiLine; } else if( shape->type == MS_SHAPE_POLYGON ) { int iLine; /* actually, it is pretty hard to be sure rings 1+ are interior */ hGeom = OGR_G_CreateGeometry( wkbPolygon ); for( iLine = 0; iLine < shape->numlines; iLine++ ) { OGRGeometryH hRing; hRing = OGR_G_CreateGeometry( wkbLinearRing ); for( i = 0; i < shape->line[iLine].numpoints; i++ ) { OGR_G_AddPoint_2D( hRing, shape->line[iLine].point[i].x, shape->line[iLine].point[i].y ); } OGR_G_AddGeometryDirectly( hGeom, hRing ); } } else { msSetError(MS_OGRERR, "OGR support is not available.", "msOGRShapeToWKT()"); } if( hGeom != NULL ) { char *pszOGRWkt; OGR_G_ExportToWkt( hGeom, &pszOGRWkt ); wkt = msStrdup( pszOGRWkt ); CPLFree( pszOGRWkt ); } return wkt; #else msSetError(MS_OGRERR, "OGR support is not available.", "msOGRShapeToWKT()"); return NULL; #endif } mapserver-6.4.1/maptile.h0000644002461700001440000000430712261257215015124 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapServer Tile Access API * Author: Paul Ramsey * ****************************************************************************** * Copyright (c) 2008, Paul Ramsey * * 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. ****************************************************************************/ #include "mapserver.h" #include "maptemplate.h" #ifdef USE_PROJ #define USE_TILE_API 1 #endif #define SPHEREMERC_PROJ4 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +units=m +k=1.0 +nadgrids=@null" #define SPHEREMERC_GROUND_SIZE (20037508.34*2) #define SPHEREMERC_IMAGE_SIZE 0x0100 enum tileModes { TILE_GMAP, TILE_VE }; MS_DLL_EXPORT int msTileSetup(mapservObj *msObj); MS_DLL_EXPORT int msTileSetExtent(mapservObj *msObj); MS_DLL_EXPORT int msTileSetProjections(mapObj *map); MS_DLL_EXPORT imageObj* msTileDraw(mapservObj *msObj); typedef struct { int metatile_level; /* In zoom levels above tile request: best bet is 0, 1 or 2 */ int tile_size; /* In pixels */ int map_edge_buffer; /* In pixels */ } tileParams; mapserver-6.4.1/mapgml.c0000644002461700001440000020623712261257215014747 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: shapeObj to GML output via MapServer queries. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapgml.h" /* Use only mapgml.c if WMS or WFS is available (with minor exceptions at end)*/ #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) static int msGMLGeometryLookup(gmlGeometryListObj *geometryList, char *type); /* ** Functions that write the feature boundary geometry (i.e. a rectObj). */ /* GML 2.1.2 */ static int gmlWriteBounds_GML2(FILE *stream, rectObj *rect, const char *srsname, char *tab) { char *srsname_encoded; if(!stream) return(MS_FAILURE); if(!rect) return(MS_FAILURE); if(!tab) return(MS_FAILURE); msIO_fprintf(stream, "%s\n", tab); if(srsname) { srsname_encoded = msEncodeHTMLEntities(srsname); msIO_fprintf(stream, "%s\t\n", tab, srsname_encoded); msFree(srsname_encoded); } else msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\t\t", tab); msIO_fprintf(stream, "%.6f,%.6f %.6f,%.6f", rect->minx, rect->miny, rect->maxx, rect->maxy ); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\n", tab); return MS_SUCCESS; } /* GML 3.1 (MapServer limits GML encoding to the level 0 profile) */ static int gmlWriteBounds_GML3(FILE *stream, rectObj *rect, const char *srsname, char *tab) { char *srsname_encoded; if(!stream) return(MS_FAILURE); if(!rect) return(MS_FAILURE); if(!tab) return(MS_FAILURE); msIO_fprintf(stream, "%s\n", tab); if(srsname) { srsname_encoded = msEncodeHTMLEntities(srsname); msIO_fprintf(stream, "%s\t\n", tab, srsname_encoded); msFree(srsname_encoded); } else msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\t\t%.6f %.6f\n", tab, rect->minx, rect->miny); msIO_fprintf(stream, "%s\t\t%.6f %.6f\n", tab, rect->maxx, rect->maxy); msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\n", tab); return MS_SUCCESS; } static void gmlStartGeometryContainer(FILE *stream, char *name, char *namespace, const char *tab) { const char *tag_name=OWS_GML_DEFAULT_GEOMETRY_NAME; if(name) tag_name = name; if(namespace) msIO_fprintf(stream, "%s<%s:%s>\n", tab, namespace, tag_name); else msIO_fprintf(stream, "%s<%s>\n", tab, tag_name); } static void gmlEndGeometryContainer(FILE *stream, char *name, char *namespace, const char *tab) { const char *tag_name=OWS_GML_DEFAULT_GEOMETRY_NAME; if(name) tag_name = name; if(namespace) msIO_fprintf(stream, "%s\n", tab, namespace, tag_name); else msIO_fprintf(stream, "%s\n", tab, tag_name); } /* GML 2.1.2 */ static int gmlWriteGeometry_GML2(FILE *stream, gmlGeometryListObj *geometryList, shapeObj *shape, const char *srsname, char *namespace, char *tab) { int i, j, k; int *innerlist, *outerlist, numouters; char *srsname_encoded = NULL; int geometry_aggregate_index, geometry_simple_index; char *geometry_aggregate_name = NULL, *geometry_simple_name = NULL; if(!stream) return(MS_FAILURE); if(!shape) return(MS_FAILURE); if(!tab) return(MS_FAILURE); if(!geometryList) return(MS_FAILURE); if(shape->numlines <= 0) return(MS_SUCCESS); /* empty shape, nothing to output */ if(srsname) srsname_encoded = msEncodeHTMLEntities(srsname); /* feature geometry */ switch(shape->type) { case(MS_SHAPE_POINT): geometry_simple_index = msGMLGeometryLookup(geometryList, "point"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipoint"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->line[0].numpoints == 1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->line[0].numpoints == 1 && shape->numlines == 1)) { /* write a Point(s) */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Point */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s %f,%f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } } else if((geometry_aggregate_index != -1) || (geometryList->numgeometries == 0)) { /* write a MultiPoint */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiPoint */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s %f,%f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_LINE): geometry_simple_index = msGMLGeometryLookup(geometryList, "line"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multiline"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a LineStrings(s) */ for(i=0; inumlines; i++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* LineString */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiCurve */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiLineString */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); for(j=0; jnumlines; j++) { msIO_fprintf(stream, "%s \n", tab); /* no srsname at this point */ msIO_fprintf(stream, "%s \n", tab); /* no srsname at this point */ msIO_fprintf(stream, "%s ", tab); for(i=0; iline[j].numpoints; i++) msIO_fprintf(stream, "%f,%f ", shape->line[j].point[i].x, shape->line[j].point[i].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_POLYGON): /* this gets nasty, since our shapes are so flexible */ geometry_simple_index = msGMLGeometryLookup(geometryList, "polygon"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipolygon"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; /* get a list of outter rings for this polygon */ outerlist = msGetOuterList(shape); numouters = 0; for(i=0; inumlines; i++) if(outerlist[i] == MS_TRUE) numouters++; if((geometry_simple_index != -1 && numouters == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a Polygon(s) */ for(i=0; inumlines; i++) { if(outerlist[i] == MS_FALSE) break; /* skip non-outer rings, each outer ring is a new polygon */ /* get a list of inner rings for this polygon */ innerlist = msGetInnerList(shape, i, outerlist); gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Polygon */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[k].numpoints; j++) msIO_fprintf(stream, "%f,%f ", shape->line[k].point[j].x, shape->line[k].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s\n", tab); free(innerlist); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } free(outerlist); } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiPolygon */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiPolygon */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); for(i=0; inumlines; i++) { /* step through the outer rings */ if(outerlist[i] == MS_TRUE) { innerlist = msGetInnerList(shape, i, outerlist); msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[k].numpoints; j++) msIO_fprintf(stream, "%f,%f ", shape->line[k].point[j].x, shape->line[k].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s\n", tab); free(innerlist); } } msIO_fprintf(stream, "%s\n", tab); free(outerlist); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; default: break; } /* clean-up */ msFree(srsname_encoded); return(MS_SUCCESS); } /* GML 3.1 (MapServer limits GML encoding to the level 0 profile) */ static int gmlWriteGeometry_GML3(FILE *stream, gmlGeometryListObj *geometryList, shapeObj *shape, const char *srsname, char *namespace, char *tab) { int i, j, k; int *innerlist, *outerlist, numouters; char *srsname_encoded = NULL; int geometry_aggregate_index, geometry_simple_index; char *geometry_aggregate_name = NULL, *geometry_simple_name = NULL; if(!stream) return(MS_FAILURE); if(!shape) return(MS_FAILURE); if(!tab) return(MS_FAILURE); if(!geometryList) return(MS_FAILURE); if(shape->numlines <= 0) return(MS_SUCCESS); /* empty shape, nothing to output */ if(srsname) srsname_encoded = msEncodeHTMLEntities(srsname); /* feature geometry */ switch(shape->type) { case(MS_SHAPE_POINT): geometry_simple_index = msGMLGeometryLookup(geometryList, "point"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipoint"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->line[0].numpoints == 1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->line[0].numpoints == 1 && shape->numlines == 1)) { /* write a Point(s) */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Point */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s %f %f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } } else if((geometry_aggregate_index != -1) || (geometryList->numgeometries == 0)) { /* write a MultiPoint */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiPoint */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s %f %f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_LINE): geometry_simple_index = msGMLGeometryLookup(geometryList, "line"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multiline"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a LineStrings(s) */ for(i=0; inumlines; i++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* LineString (should be Curve?) */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiCurve */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiCurve */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(i=0; inumlines; i++) { msIO_fprintf(stream, "%s \n", tab); /* no srsname at this point */ msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); } msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_POLYGON): /* this gets nasty, since our shapes are so flexible */ geometry_simple_index = msGMLGeometryLookup(geometryList, "polygon"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipolygon"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; /* get a list of outter rings for this polygon */ outerlist = msGetOuterList(shape); numouters = 0; for(i=0; inumlines; i++) if(outerlist[i] == MS_TRUE) numouters++; if((geometry_simple_index != -1 && numouters == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a Polygon(s) */ for(i=0; inumlines; i++) { if(outerlist[i] == MS_FALSE) break; /* skip non-outer rings, each outer ring is a new polygon */ /* get a list of inner rings for this polygon */ innerlist = msGetInnerList(shape, i, outerlist); gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Polygon (should be Surface?) */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[k].numpoints; j++) msIO_fprintf(stream, "%f %f ", shape->line[k].point[j].x, shape->line[k].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); free(innerlist); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } free(outerlist); } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiSurface */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiSurface */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(i=0; inumlines; i++) { /* step through the outer rings */ if(outerlist[i] == MS_TRUE) { /* get a list of inner rings for this polygon */ innerlist = msGetInnerList(shape, i, outerlist); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[k].numpoints; j++) msIO_fprintf(stream, "%f %f ", shape->line[k].point[j].x, shape->line[k].point[j].y); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); free(innerlist); } } msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); free(outerlist); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; default: break; } /* clean-up */ msFree(srsname_encoded); return(MS_SUCCESS); } /* ** Wrappers for the format specific encoding functions. */ static int gmlWriteBounds(FILE *stream, int format, rectObj *rect, const char *srsname, char *tab) { switch(format) { case(OWS_GML2): return gmlWriteBounds_GML2(stream, rect, srsname, tab); break; case(OWS_GML3): return gmlWriteBounds_GML3(stream, rect, srsname, tab); break; default: msSetError(MS_IOERR, "Unsupported GML format.", "gmlWriteBounds()"); } return(MS_FAILURE); } static int gmlWriteGeometry(FILE *stream, gmlGeometryListObj *geometryList, int format, shapeObj *shape, const char *srsname, char *namespace, char *tab) { switch(format) { case(OWS_GML2): return gmlWriteGeometry_GML2(stream, geometryList, shape, srsname, namespace, tab); break; case(OWS_GML3): return gmlWriteGeometry_GML3(stream, geometryList, shape, srsname, namespace, tab); break; default: msSetError(MS_IOERR, "Unsupported GML format.", "gmlWriteGeometry()"); } return(MS_FAILURE); } /* ** GML specific metadata handling functions. */ int msItemInGroups(char *name, gmlGroupListObj *groupList) { int i, j; gmlGroupObj *group; if(!groupList) return MS_FALSE; /* no groups */ for(i=0; inumgroups; i++) { group = &(groupList->groups[i]); for(j=0; jnumitems; j++) { if(strcasecmp(name, group->items[j]) == 0) return MS_TRUE; } } return MS_FALSE; } static int msGMLGeometryLookup(gmlGeometryListObj *geometryList, char *type) { int i; if(!geometryList || !type) return -1; /* nothing to look for */ for(i=0; inumgeometries; i++) if(geometryList->geometries[i].type && (strcasecmp(geometryList->geometries[i].type, type) == 0)) return i; return -1; /* not found */ } gmlGeometryListObj *msGMLGetGeometries(layerObj *layer, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **names=NULL; int numnames=0; gmlGeometryListObj *geometryList=NULL; gmlGeometryObj *geometry=NULL; /* allocate memory and initialize the item collection */ geometryList = (gmlGeometryListObj *) malloc(sizeof(gmlGeometryListObj)); MS_CHECK_ALLOC(geometryList, sizeof(gmlGeometryListObj), NULL) ; geometryList->geometries = NULL; geometryList->numgeometries = 0; if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "geometries")) != NULL) { names = msStringSplit(value, ',', &numnames); /* allocation an array of gmlGeometryObj's */ geometryList->numgeometries = numnames; geometryList->geometries = (gmlGeometryObj *) malloc(sizeof(gmlGeometryObj)*geometryList->numgeometries); if (geometryList->geometries == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetGeometries()", (unsigned int)(sizeof(gmlGeometryObj)*geometryList->numgeometries)); free(geometryList); return NULL; } for(i=0; inumgeometries; i++) { geometry = &(geometryList->geometries[i]); geometry->name = msStrdup(names[i]); /* initialize a few things */ geometry->type = NULL; geometry->occurmin = 0; geometry->occurmax = 1; snprintf(tag, 64, "%s_type", names[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) geometry->type = msStrdup(value); /* TODO: validate input value */ snprintf(tag, 64, "%s_occurances", names[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) { char **occur; int numoccur; occur = msStringSplit(value, ',', &numoccur); if(numoccur == 2) { /* continue (TODO: throw an error if != 2) */ geometry->occurmin = atof(occur[0]); if(strcasecmp(occur[1], "UNBOUNDED") == 0) geometry->occurmax = OWS_GML_OCCUR_UNBOUNDED; else geometry->occurmax = atof(occur[1]); } } } msFreeCharArray(names, numnames); } return geometryList; } void msGMLFreeGeometries(gmlGeometryListObj *geometryList) { int i; if(!geometryList) return; for(i=0; inumgeometries; i++) { msFree(geometryList->geometries[i].name); msFree(geometryList->geometries[i].type); } free(geometryList->geometries); free(geometryList); } static void msGMLWriteItem(FILE *stream, gmlItemObj *item, char *value, const char *namespace, const char *tab) { char *encoded_value, *tag_name; int add_namespace = MS_TRUE; if(!stream || !item) return; if(!item->visible) return; if(!namespace) add_namespace = MS_FALSE; if(item->encode == MS_TRUE) encoded_value = msEncodeHTMLEntities(value); else encoded_value = msStrdup(value); if(!item->template) { /* build the tag from pieces */ if(item->alias) { tag_name = item->alias; if(strchr(item->alias, ':') != NULL) add_namespace = MS_FALSE; } else { tag_name = item->name; if(strchr(item->name, ':') != NULL) add_namespace = MS_FALSE; } if(add_namespace == MS_TRUE && msIsXMLTagValid(tag_name) == MS_FALSE) msIO_fprintf(stream, "\n", tag_name); if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s<%s:%s>%s\n", tab, namespace, tag_name, encoded_value, namespace, tag_name); else msIO_fprintf(stream, "%s<%s>%s\n", tab, tag_name, encoded_value, tag_name); } else { char *tag = NULL; tag = msStrdup(item->template); tag = msReplaceSubstring(tag, "$value", encoded_value); if(namespace) tag = msReplaceSubstring(tag, "$namespace", namespace); msIO_fprintf(stream, "%s%s\n", tab, tag); free(tag); } free( encoded_value ); return; } gmlNamespaceListObj *msGMLGetNamespaces(webObj *web, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **prefixes=NULL; int numprefixes=0; gmlNamespaceListObj *namespaceList=NULL; gmlNamespaceObj *namespace=NULL; /* allocate the collection */ namespaceList = (gmlNamespaceListObj *) malloc(sizeof(gmlNamespaceListObj)); MS_CHECK_ALLOC(namespaceList, sizeof(gmlNamespaceListObj), NULL) ; namespaceList->namespaces = NULL; namespaceList->numnamespaces = 0; /* list of namespaces (TODO: make this automatic by parsing metadata) */ if((value = msOWSLookupMetadata(&(web->metadata), metadata_namespaces, "external_namespace_prefixes")) != NULL) { prefixes = msStringSplit(value, ',', &numprefixes); /* allocation an array of gmlNamespaceObj's */ namespaceList->numnamespaces = numprefixes; namespaceList->namespaces = (gmlNamespaceObj *) malloc(sizeof(gmlNamespaceObj)*namespaceList->numnamespaces); if (namespaceList->namespaces == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetNamespaces()", (unsigned int)(sizeof(gmlNamespaceObj)*namespaceList->numnamespaces)); free(namespaceList); return NULL; } for(i=0; inumnamespaces; i++) { namespace = &(namespaceList->namespaces[i]); namespace->prefix = msStrdup(prefixes[i]); /* initialize a few things */ namespace->uri = NULL; namespace->schemalocation = NULL; snprintf(tag, 64, "%s_uri", namespace->prefix); if((value = msOWSLookupMetadata(&(web->metadata), metadata_namespaces, tag)) != NULL) namespace->uri = msStrdup(value); snprintf(tag, 64, "%s_schema_location", namespace->prefix); if((value = msOWSLookupMetadata(&(web->metadata), metadata_namespaces, tag)) != NULL) namespace->schemalocation = msStrdup(value); } msFreeCharArray(prefixes, numprefixes); } return namespaceList; } void msGMLFreeNamespaces(gmlNamespaceListObj *namespaceList) { int i; if(!namespaceList) return; for(i=0; inumnamespaces; i++) { msFree(namespaceList->namespaces[i].prefix); msFree(namespaceList->namespaces[i].uri); msFree(namespaceList->namespaces[i].schemalocation); } free(namespaceList); } gmlConstantListObj *msGMLGetConstants(layerObj *layer, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **names=NULL; int numnames=0; gmlConstantListObj *constantList=NULL; gmlConstantObj *constant=NULL; /* allocate the collection */ constantList = (gmlConstantListObj *) malloc(sizeof(gmlConstantListObj)); MS_CHECK_ALLOC(constantList, sizeof(gmlConstantListObj), NULL); constantList->constants = NULL; constantList->numconstants = 0; /* list of constants (TODO: make this automatic by parsing metadata) */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "constants")) != NULL) { names = msStringSplit(value, ',', &numnames); /* allocation an array of gmlConstantObj's */ constantList->numconstants = numnames; constantList->constants = (gmlConstantObj *) malloc(sizeof(gmlConstantObj)*constantList->numconstants); if (constantList->constants == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetConstants()", (unsigned int)(sizeof(gmlConstantObj)*constantList->numconstants)); free(constantList); return NULL; } for(i=0; inumconstants; i++) { constant = &(constantList->constants[i]); constant->name = msStrdup(names[i]); /* initialize a few things */ constant->value = NULL; constant->type = NULL; snprintf(tag, 64, "%s_value", constant->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) constant->value = msStrdup(value); snprintf(tag, 64, "%s_type", constant->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) constant->type = msStrdup(value); } msFreeCharArray(names, numnames); } return constantList; } void msGMLFreeConstants(gmlConstantListObj *constantList) { int i; if(!constantList) return; for(i=0; inumconstants; i++) { msFree(constantList->constants[i].name); msFree(constantList->constants[i].value); msFree(constantList->constants[i].type); } free(constantList); } static void msGMLWriteConstant(FILE *stream, gmlConstantObj *constant, const char *namespace, const char *tab) { int add_namespace = MS_TRUE; if(!stream || !constant) return; if(!constant->value) return; if(!namespace) add_namespace = MS_FALSE; if(strchr(constant->name, ':') != NULL) add_namespace = MS_FALSE; if(add_namespace == MS_TRUE && msIsXMLTagValid(constant->name) == MS_FALSE) msIO_fprintf(stream, "\n", constant->name); if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s<%s:%s>%s\n", tab, namespace, constant->name, constant->value, namespace, constant->name); else msIO_fprintf(stream, "%s<%s>%s\n", tab, constant->name, constant->value, constant->name); return; } gmlGroupListObj *msGMLGetGroups(layerObj *layer, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **names=NULL; int numnames=0; gmlGroupListObj *groupList=NULL; gmlGroupObj *group=NULL; /* allocate the collection */ groupList = (gmlGroupListObj *) malloc(sizeof(gmlGroupListObj)); MS_CHECK_ALLOC(groupList, sizeof(gmlGroupListObj), NULL) ; groupList->groups = NULL; groupList->numgroups = 0; /* list of groups (TODO: make this automatic by parsing metadata) */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "groups")) != NULL) { names = msStringSplit(value, ',', &numnames); /* allocation an array of gmlGroupObj's */ groupList->numgroups = numnames; groupList->groups = (gmlGroupObj *) malloc(sizeof(gmlGroupObj)*groupList->numgroups); if (groupList->groups == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetGroups()", (unsigned int)(sizeof(gmlGroupObj)*groupList->numgroups)); free(groupList); return NULL; } for(i=0; inumgroups; i++) { group = &(groupList->groups[i]); group->name = msStrdup(names[i]); /* initialize a few things */ group->items = NULL; group->numitems = 0; group->type = NULL; snprintf(tag, 64, "%s_group", group->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) group->items = msStringSplit(value, ',', &group->numitems); snprintf(tag, 64, "%s_type", group->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) group->type = msStrdup(value); } msFreeCharArray(names, numnames); } return groupList; } void msGMLFreeGroups(gmlGroupListObj *groupList) { int i; if(!groupList) return; for(i=0; inumgroups; i++) { msFree(groupList->groups[i].name); msFreeCharArray(groupList->groups[i].items, groupList->groups[i].numitems); msFree(groupList->groups[i].type); } free(groupList); } static void msGMLWriteGroup(FILE *stream, gmlGroupObj *group, shapeObj *shape, gmlItemListObj *itemList, gmlConstantListObj *constantList, const char *namespace, const char *tab) { int i,j; int add_namespace = MS_TRUE; char *itemtab; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; if(!stream || !group) return; /* setup the item/constant tab */ itemtab = (char *) msSmallMalloc(sizeof(char)*strlen(tab)+3); sprintf(itemtab, "%s ", tab); if(!namespace || strchr(group->name, ':') != NULL) add_namespace = MS_FALSE; /* start the group */ if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s<%s:%s>\n", tab, namespace, group->name); else msIO_fprintf(stream, "%s<%s>\n", tab, group->name); /* now the items/constants in the group */ for(i=0; inumitems; i++) { for(j=0; jnumconstants; j++) { constant = &(constantList->constants[j]); if(strcasecmp(constant->name, group->items[i]) == 0) { msGMLWriteConstant(stream, constant, namespace, itemtab); break; } } if(j != constantList->numconstants) continue; /* found this one */ for(j=0; jnumitems; j++) { item = &(itemList->items[j]); if(strcasecmp(item->name, group->items[i]) == 0) { /* the number of items matches the number of values exactly */ msGMLWriteItem(stream, item, shape->values[j], namespace, itemtab); break; } } } /* end the group */ if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s\n", tab, namespace, group->name); else msIO_fprintf(stream, "%s\n", tab, group->name); return; } #endif /* Dump GML query results for WMS GetFeatureInfo */ int msGMLWriteQuery(mapObj *map, char *filename, const char *namespaces) { #if defined(USE_WMS_SVR) int status; int i,j,k; layerObj *lp=NULL; shapeObj shape; FILE *stream=stdout; /* defaults to stdout */ char szPath[MS_MAXPATHLEN]; char *value; const char *pszMapSRS = NULL; gmlGroupListObj *groupList=NULL; gmlItemListObj *itemList=NULL; gmlConstantListObj *constantList=NULL; gmlGeometryListObj *geometryList=NULL; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; msInitShape(&shape); if(filename && strlen(filename) > 0) { /* deal with the filename if present */ stream = fopen(msBuildPath(szPath, map->mappath, filename), "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msGMLWriteQuery()", filename); return(MS_FAILURE); } } /* charset encoding: lookup "gml_encoding" metadata first, then */ /* "wms_encoding", and if not found then use "ISO-8859-1" as default. */ msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "encoding", OWS_NOERR, "\n\n", "ISO-8859-1"); msOWSPrintValidateMetadata(stream, &(map->web.metadata), namespaces, "rootname", OWS_NOERR, "<%s ", "msGMLOutput"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "uri", OWS_NOERR, "xmlns=\"%s\"", NULL); msIO_fprintf(stream, "\n\t xmlns:gml=\"http://www.opengis.net/gml\"" ); msIO_fprintf(stream, "\n\t xmlns:xlink=\"http://www.w3.org/1999/xlink\""); msIO_fprintf(stream, "\n\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "schema", OWS_NOERR, "\n\t xsi:schemaLocation=\"%s\"", NULL); msIO_fprintf(stream, ">\n"); /* a schema *should* be required */ msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "description", OWS_NOERR, "\t%s\n", NULL); /* Look up map SRS. We need an EPSG code for GML, if not then we get null and we'll fall back on the layer's SRS */ pszMapSRS = msOWSGetEPSGProj(&(map->projection), NULL, namespaces, MS_TRUE); /* step through the layers looking for query results */ for(i=0; inumlayers; i++) { const char *pszOutputSRS = NULL; lp = (GET_LAYER(map, map->layerorder[i])); if(lp->resultcache && lp->resultcache->numresults > 0) { /* found results */ #ifdef USE_PROJ /* Determine output SRS, if map has none, then try using layer's native SRS */ if ((pszOutputSRS = pszMapSRS) == NULL) { pszOutputSRS = msOWSGetEPSGProj(&(lp->projection), NULL, namespaces, MS_TRUE); if (pszOutputSRS == NULL) { msSetError(MS_WMSERR, "No valid EPSG code in map or layer projection for GML output", "msGMLWriteQuery()"); continue; /* No EPSG code, cannot output this layer */ } } #endif /* start this collection (layer) */ /* if no layer name provided fall back on the layer name + "_layer" */ value = (char*) msSmallMalloc(strlen(lp->name)+7); sprintf(value, "%s_layer", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "layername", OWS_NOERR, "\t<%s>\n", value); msFree(value); value = (char *) msOWSLookupMetadata(&(lp->metadata), "OM", "title"); if (value) { msOWSPrintMetadata(stream, &(lp->metadata), namespaces, "title", OWS_NOERR, "\t%s\n", value); } /* populate item and group metadata structures */ itemList = msGMLGetItems(lp, namespaces); constantList = msGMLGetConstants(lp, namespaces); groupList = msGMLGetGroups(lp, namespaces); geometryList = msGMLGetGeometries(lp, namespaces); if (itemList == NULL || constantList == NULL || groupList == NULL || geometryList == NULL) { msSetError(MS_MISCERR, "Unable to populate item and group metadata structures", "msGMLWriteQuery()"); return MS_FAILURE; } for(j=0; jresultcache->numresults; j++) { status = msLayerGetShape(lp, &shape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) return(status); #ifdef USE_PROJ /* project the shape into the map projection (if necessary), note that this projects the bounds as well */ if(pszOutputSRS == pszMapSRS && msProjectionsDiffer(&(lp->projection), &(map->projection))) { status = msProjectShape(&lp->projection, &map->projection, &shape); if(status != MS_SUCCESS) { msIO_fprintf(stream, "\n",msGetErrorString(",")); continue; } } #endif /* start this feature */ /* specify a feature name, if nothing provided fall back on the layer name + "_feature" */ value = (char*) msSmallMalloc(strlen(lp->name)+9); sprintf(value, "%s_feature", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "featurename", OWS_NOERR, "\t\t<%s>\n", value); msFree(value); /* Write the feature geometry and bounding box unless 'none' was requested. */ /* Default to bbox only if nothing specified and output full geometry only if explicitly requested */ if(!(geometryList && geometryList->numgeometries == 1 && strcasecmp(geometryList->geometries[0].name, "none") == 0)) { #ifdef USE_PROJ gmlWriteBounds(stream, OWS_GML2, &(shape.bounds), pszOutputSRS, "\t\t\t"); if (geometryList && geometryList->numgeometries > 0 ) gmlWriteGeometry(stream, geometryList, OWS_GML2, &(shape), pszOutputSRS, NULL, "\t\t\t"); #else gmlWriteBounds(stream, OWS_GML2, &(shape.bounds), NULL, "\t\t\t"); /* no projection information */ if (geometryList && geometryList->numgeometries > 0 ) gmlWriteGeometry(stream, geometryList, OWS_GML2, &(shape), NULL, NULL, "\t\t\t"); #endif } /* write any item/values */ for(k=0; knumitems; k++) { item = &(itemList->items[k]); if(msItemInGroups(item->name, groupList) == MS_FALSE) msGMLWriteItem(stream, item, shape.values[k], NULL, "\t\t\t"); } /* write any constants */ for(k=0; knumconstants; k++) { constant = &(constantList->constants[k]); if(msItemInGroups(constant->name, groupList) == MS_FALSE) msGMLWriteConstant(stream, constant, NULL, "\t\t\t"); } /* write any groups */ for(k=0; knumgroups; k++) msGMLWriteGroup(stream, &(groupList->groups[k]), &shape, itemList, constantList, NULL, "\t\t\t"); /* end this feature */ /* specify a feature name if nothing provided */ /* fall back on the layer name + "Feature" */ value = (char*) msSmallMalloc(strlen(lp->name)+9); sprintf(value, "%s_feature", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "featurename", OWS_NOERR, "\t\t\n", value); msFree(value); msFreeShape(&shape); /* init too */ } /* end this collection (layer) */ /* if no layer name provided fall back on the layer name + "_layer" */ value = (char*) msSmallMalloc(strlen(lp->name)+7); sprintf(value, "%s_layer", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "layername", OWS_NOERR, "\t\n", value); msFree(value); msGMLFreeGroups(groupList); msGMLFreeConstants(constantList); msGMLFreeItems(itemList); msGMLFreeGeometries(geometryList); /* msLayerClose(lp); */ } } /* next layer */ /* end this document */ msOWSPrintValidateMetadata(stream, &(map->web.metadata), namespaces, "rootname", OWS_NOERR, "\n", "msGMLOutput"); if(filename && strlen(filename) > 0) fclose(stream); return(MS_SUCCESS); #else /* Stub for mapscript */ msSetError(MS_MISCERR, "WMS server support not enabled", "msGMLWriteQuery()"); return MS_FAILURE; #endif } /************************************************************************/ /* msAxisSwapShape */ /* */ /* Utility function to swap x and y coordiatesn Use for now for */ /* WFS 1.1.x */ /************************************************************************/ void msAxisSwapShape(shapeObj *shape) { double tmp; int i,j; if (shape) { for(i=0; inumlines; i++) { for( j=0; jline[i].numpoints; j++ ) { tmp = shape->line[i].point[j].x; shape->line[i].point[j].x = shape->line[i].point[j].y; shape->line[i].point[j].y = tmp; } } /*swap bounds*/ tmp = shape->bounds.minx; shape->bounds.minx = shape->bounds.miny; shape->bounds.miny = tmp; tmp = shape->bounds.maxx; shape->bounds.maxx = shape->bounds.maxy; shape->bounds.maxy = tmp; } } /* ** msGMLWriteWFSQuery() ** ** Similar to msGMLWriteQuery() but tuned for use with WFS 1.0.0 */ int msGMLWriteWFSQuery(mapObj *map, FILE *stream, char *default_namespace_prefix, int outputformat) { #ifdef USE_WFS_SVR int status; int i,j,k; layerObj *lp=NULL; shapeObj shape; rectObj resultBounds = {-1.0,-1.0,-1.0,-1.0}; int features = 0; gmlGroupListObj *groupList=NULL; gmlItemListObj *itemList=NULL; gmlConstantListObj *constantList=NULL; gmlGeometryListObj *geometryList=NULL; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; char *namespace_prefix=NULL; const char *axis = NULL; int bSwapAxis = 0; double tmp; const char *srsMap = NULL; msInitShape(&shape); /*add a check to see if the map projection is set to be north-east*/ for( i = 0; i < map->projection.numargs; i++ ) { if( strstr(map->projection.args[i],"epsgaxis=") != NULL ) { axis = strstr(map->projection.args[i],"=") + 1; break; } } if (axis && strcasecmp(axis,"ne") == 0 ) bSwapAxis = 1; /* Need to start with BBOX of the whole resultset */ if (msGetQueryResultBounds(map, &resultBounds) > 0) { if (bSwapAxis) { tmp = resultBounds.minx; resultBounds.minx = resultBounds.miny; resultBounds.miny = tmp; tmp = resultBounds.maxx; resultBounds.maxx = resultBounds.maxy; resultBounds.maxy = tmp; } srsMap = msOWSGetEPSGProj(&(map->projection), NULL, "FGO", MS_TRUE); if (!srsMap) msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE); gmlWriteBounds(stream, outputformat, &resultBounds, srsMap, " "); } /* step through the layers looking for query results */ for(i=0; inumlayers; i++) { lp = GET_LAYER(map, map->layerorder[i]); if(lp->resultcache && lp->resultcache->numresults > 0) { /* found results */ char *layerName; const char *value; int featureIdIndex=-1; /* no feature id */ /* setup namespace, a layer can override the default */ namespace_prefix = (char*) msOWSLookupMetadata(&(lp->metadata), "OFG", "namespace_prefix"); if(!namespace_prefix) namespace_prefix = default_namespace_prefix; value = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if(value) { /* find the featureid amongst the items for this layer */ for(j=0; jnumitems; j++) { if(strcasecmp(lp->items[j], value) == 0) { /* found it */ featureIdIndex = j; break; } } /* Produce a warning if a featureid was set but the corresponding item is not found. */ if (featureIdIndex == -1) msIO_fprintf(stream, "\n", value, lp->name); } /* populate item and group metadata structures */ itemList = msGMLGetItems(lp, "G"); constantList = msGMLGetConstants(lp, "G"); groupList = msGMLGetGroups(lp, "G"); geometryList = msGMLGetGeometries(lp, "GFO"); if (itemList == NULL || constantList == NULL || groupList == NULL || geometryList == NULL) { msSetError(MS_MISCERR, "Unable to populate item and group metadata structures", "msGMLWriteWFSQuery()"); return MS_FAILURE; } if (namespace_prefix) { layerName = (char *) msSmallMalloc(strlen(namespace_prefix)+strlen(lp->name)+2); sprintf(layerName, "%s:%s", namespace_prefix, lp->name); } else { layerName = msStrdup(lp->name); } for(j=0; jresultcache->numresults; j++) { status = msLayerGetShape(lp, &shape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) return(status); #ifdef USE_PROJ /* project the shape into the map projection (if necessary), note that this projects the bounds as well */ if(msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&lp->projection, &map->projection, &shape); #endif /* ** start this feature */ msIO_fprintf(stream, " \n"); if(msIsXMLTagValid(layerName) == MS_FALSE) msIO_fprintf(stream, "\n", layerName); if(featureIdIndex != -1) { if(outputformat == OWS_GML2) msIO_fprintf(stream, " <%s fid=\"%s.%s\">\n", layerName, lp->name, shape.values[featureIdIndex]); else /* OWS_GML3 */ msIO_fprintf(stream, " <%s gml:id=\"%s.%s\">\n", layerName, lp->name, shape.values[featureIdIndex]); } else msIO_fprintf(stream, " <%s>\n", layerName); if (bSwapAxis) msAxisSwapShape(&shape); /* write the feature geometry and bounding box */ if(!(geometryList && geometryList->numgeometries == 1 && strcasecmp(geometryList->geometries[0].name, "none") == 0)) { #ifdef USE_PROJ srsMap = msOWSGetEPSGProj(&(map->projection), NULL, "FGO", MS_TRUE); if (!srsMap) msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE); if(srsMap) { /* use the map projection first*/ gmlWriteBounds(stream, outputformat, &(shape.bounds), srsMap, " "); gmlWriteGeometry(stream, geometryList, outputformat, &(shape), srsMap, namespace_prefix, " "); } else { /* then use the layer projection and/or metadata */ gmlWriteBounds(stream, outputformat, &(shape.bounds), msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FGO", MS_TRUE), " "); gmlWriteGeometry(stream, geometryList, outputformat, &(shape), msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FGO", MS_TRUE), namespace_prefix, " "); } #else gmlWriteBounds(stream, outputformat, &(shape.bounds), NULL, " "); /* no projection information */ gmlWriteGeometry(stream, geometryList, outputformat, &(shape), NULL, namespace_prefix, " "); #endif } /* write any item/values */ for(k=0; knumitems; k++) { item = &(itemList->items[k]); if(msItemInGroups(item->name, groupList) == MS_FALSE) msGMLWriteItem(stream, item, shape.values[k], namespace_prefix, " "); } /* write any constants */ for(k=0; knumconstants; k++) { constant = &(constantList->constants[k]); if(msItemInGroups(constant->name, groupList) == MS_FALSE) msGMLWriteConstant(stream, constant, namespace_prefix, " "); } /* write any groups */ for(k=0; knumgroups; k++) msGMLWriteGroup(stream, &(groupList->groups[k]), &shape, itemList, constantList, namespace_prefix, " "); /* end this feature */ msIO_fprintf(stream, " \n", layerName); msIO_fprintf(stream, " \n"); msFreeShape(&shape); /* init too */ features++; } /* done with this layer, do a little clean-up */ msFree(layerName); msGMLFreeGroups(groupList); msGMLFreeConstants(constantList); msGMLFreeItems(itemList); msGMLFreeGeometries(geometryList); /* msLayerClose(lp); */ } } /* next layer */ return(MS_SUCCESS); #else /* Stub for mapscript */ msSetError(MS_MISCERR, "WMS server support not enabled", "msGMLWriteWFSQuery()"); return MS_FAILURE; #endif /* USE_WFS_SVR */ } #ifdef USE_LIBXML2 /** * msGML3BoundedBy() * * returns an object of BoundedBy as per GML 3 * * @param xmlNsPtr psNs the namespace object * @param minx minx * @param miny miny * @param maxx maxx * @param mayy mayy * @param psEpsg epsg code * @param dimension number of dimensions * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3BoundedBy(xmlNsPtr psNs, double minx, double miny, double maxx, double maxy, const char *psEpsg) { xmlNodePtr psNode = NULL, psSubNode = NULL; char *pszTmp = NULL; char *pszTmp2 = NULL; char *pszEpsg = NULL; size_t bufferSize = 0; psNode = xmlNewNode(psNs, BAD_CAST "boundedBy"); psSubNode = xmlNewChild(psNode, NULL, BAD_CAST "Envelope", NULL); if (psEpsg) { bufferSize = strlen(psEpsg)+1; pszEpsg = (char*) msSmallMalloc(bufferSize); snprintf(pszEpsg, bufferSize, "%s", psEpsg); msStringToLower(pszEpsg); pszTmp = msStringConcatenate(pszTmp, "urn:ogc:crs:"); pszTmp = msStringConcatenate(pszTmp, pszEpsg); xmlNewProp(psSubNode, BAD_CAST "srsName", BAD_CAST pszTmp); free(pszEpsg); free(pszTmp); pszTmp = msIntToString(2); xmlNewProp(psSubNode, BAD_CAST "srsDimension", BAD_CAST pszTmp); free(pszTmp); } pszTmp = msDoubleToString(minx, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, " "); pszTmp2 = msDoubleToString(miny, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, pszTmp2); xmlNewChild(psSubNode, NULL, BAD_CAST "lowerCorner", BAD_CAST pszTmp); free(pszTmp); free(pszTmp2); pszTmp = msDoubleToString(maxx, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, " "); pszTmp2 = msDoubleToString(maxy,MS_TRUE); pszTmp = msStringConcatenate(pszTmp, pszTmp2); xmlNewChild(psSubNode, NULL, BAD_CAST "upperCorner", BAD_CAST pszTmp); free(pszTmp); free(pszTmp2); return psNode; } /** *msGML3Point() * * returns an object of Point as per GML 3 * * @param xmlNsPtr psNs the gml namespace object * @param pszSrsName EPSG code of geometry * @param id * @param x x coordinate * @param y y coordinate * @param z z coordinate * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3Point(xmlNsPtr psNs, const char *psSrsName, const char *id, double x, double y) { xmlNodePtr psNode = NULL; char *pszTmp = NULL; int dimension = 2; char *pszSrsName = NULL; char *pszTmp2 = NULL; size_t bufferSize = 0; psNode = xmlNewNode(psNs, BAD_CAST "Point"); if (id) { xmlNewNsProp(psNode, psNs, BAD_CAST "id", BAD_CAST id); } if (psSrsName) { bufferSize = strlen(psSrsName)+1; pszSrsName = (char *) msSmallMalloc(bufferSize); snprintf(pszSrsName, bufferSize, "%s", psSrsName); msStringToLower(pszSrsName); pszTmp = msStringConcatenate(pszTmp, "urn:ogc:crs:"); pszTmp = msStringConcatenate(pszTmp, pszSrsName); xmlNewProp(psNode, BAD_CAST "srsName", BAD_CAST pszTmp); free(pszSrsName); free(pszTmp); pszTmp = msIntToString(dimension); xmlNewProp(psNode, BAD_CAST "srsDimension", BAD_CAST pszTmp); free(pszTmp); } pszTmp = msDoubleToString(x, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, " "); pszTmp2 = msDoubleToString(y, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, pszTmp2); xmlNewChild(psNode, NULL, BAD_CAST "pos", BAD_CAST pszTmp); free(pszTmp); free(pszTmp2); return psNode; } /** * msGML3TimePeriod() * * returns an object of TimePeriod as per GML 3 * * @param xmlNsPtr psNs the gml namespace object * @param pszStart start time * @param pszEnd end time * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3TimePeriod(xmlNsPtr psNs, char *pszStart, char *pszEnd) { xmlNodePtr psNode=NULL; psNode = xmlNewNode(psNs, BAD_CAST "TimePeriod"); xmlNewChild(psNode, NULL, BAD_CAST "beginPosition", BAD_CAST pszStart); if (pszEnd) xmlNewChild(psNode, NULL, BAD_CAST "endPosition", BAD_CAST pszEnd); else { xmlNewChild(psNode, NULL, BAD_CAST "endPosition", NULL); xmlNewProp(psNode, BAD_CAST "indeterminatePosition", BAD_CAST "now"); } return psNode; } /** * msGML3TimeInstant() * * returns an object of TimeInstant as per GML 3 * * @param xmlNsPtr psNs the gml namespace object * @param timeInstant time instant * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3TimeInstant(xmlNsPtr psNs, char *pszTime) { xmlNodePtr psNode=NULL; psNode = xmlNewNode(psNs, BAD_CAST "TimeInstant"); xmlNewChild(psNode, NULL, BAD_CAST "timePosition", BAD_CAST pszTime); return psNode; } #endif /* USE_LIBXML2 */ /************************************************************************/ /* The following functions are enabled in all cases, even if */ /* WMS and WFS are not available. */ /************************************************************************/ gmlItemListObj *msGMLGetItems(layerObj *layer, const char *metadata_namespaces) { int i,j; char **xmlitems=NULL; int numxmlitems=0; char **incitems=NULL; int numincitems=0; char **excitems=NULL; int numexcitems=0; const char *value=NULL; char tag[64]; gmlItemListObj *itemList=NULL; gmlItemObj *item=NULL; /* get a list of items that should be included in output */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "include_items")) != NULL) incitems = msStringSplit(value, ',', &numincitems); /* get a list of items that should be excluded in output */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "exclude_items")) != NULL) excitems = msStringSplit(value, ',', &numexcitems); /* get a list of items that need don't get encoded */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "xml_items")) != NULL) xmlitems = msStringSplit(value, ',', &numxmlitems); /* allocate memory and iinitialize the item collection */ itemList = (gmlItemListObj *) malloc(sizeof(gmlItemListObj)); if(itemList == NULL) { msSetError(MS_MEMERR, "Error allocating a collection GML item structures.", "msGMLGetItems()"); return NULL; } itemList->items = NULL; itemList->numitems = 0; itemList->numitems = layer->numitems; itemList->items = (gmlItemObj *) malloc(sizeof(gmlItemObj)*itemList->numitems); if(!itemList->items) { msSetError(MS_MEMERR, "Error allocating a collection GML item structures.", "msGMLGetItems()"); return NULL; } for(i=0; inumitems; i++) { item = &(itemList->items[i]); item->name = msStrdup(layer->items[i]); /* initialize the item */ item->alias = NULL; item->type = NULL; item->template = NULL; item->encode = MS_TRUE; item->visible = MS_FALSE; item->width = 0; item->precision = 0; /* check visibility, included items first... */ if(numincitems == 1 && strcasecmp("all", incitems[0]) == 0) { item->visible = MS_TRUE; } else { for(j=0; jitems[i], incitems[j]) == 0) item->visible = MS_TRUE; } } /* ...and now excluded items */ for(j=0; jitems[i], excitems[j]) == 0) item->visible = MS_FALSE; } /* check encoding */ for(j=0; jitems[i], xmlitems[j]) == 0) item->encode = MS_FALSE; } snprintf(tag, sizeof(tag), "%s_alias", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->alias = msStrdup(value); snprintf(tag, sizeof(tag), "%s_type", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->type = msStrdup(value); snprintf(tag, sizeof(tag), "%s_template", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->template = msStrdup(value); snprintf(tag, sizeof(tag), "%s_width", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->width = atoi(value); snprintf(tag, sizeof(tag), "%s_precision", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->precision = atoi(value); } msFreeCharArray(incitems, numincitems); msFreeCharArray(excitems, numexcitems); msFreeCharArray(xmlitems, numxmlitems); return itemList; } void msGMLFreeItems(gmlItemListObj *itemList) { int i; if(!itemList) return; for(i=0; inumitems; i++) { msFree(itemList->items[i].name); msFree(itemList->items[i].alias); msFree(itemList->items[i].type); msFree(itemList->items[i].template); } if( itemList->items != NULL ) free(itemList->items); free(itemList); } mapserver-6.4.1/mapoglcontext.h0000644002461700001440000000701512261257215016354 0ustar tbonfortusers/****************************************************************************** * $id: mapoglcontext.h 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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 MAPOGLCONTEXT_H_ #define MAPOGLCONTEXT_H_ #ifdef USE_OGL #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #include "opengl/glext.h" #include "opengl/wglext.h" typedef HDC OGL_WINDOW; typedef HGLRC OGL_CONTEXT; typedef HGLRC OGL_PBUFFER; #define CALLBACK __stdcall #else #include #include #include typedef Display* OGL_WINDOW; typedef GLXContext OGL_CONTEXT; typedef GLXPbuffer OGL_PBUFFER; #define CALLBACK #endif class OglRenderer; class OglContext { private: static OglContext* current; static bool initWindow(); static bool initSharingContext(); static ms_uint32 getTextureSize(GLuint dimension, ms_uint32 value); static GLuint NextPowerOf2(GLuint in); #if defined(_WIN32) && !defined(__CYGWIN__) static HDC window; static HGLRC sharingContext; HDC hPBufferDC; HGLRC hPBufferRC; #else static Display* window; static GLXContext sharingContext; static GLXFBConfig* configs; GLXPbuffer pbuffer; #endif public: static ms_uint32 MAX_MULTISAMPLE_SAMPLES; static ms_uint32 MAX_ANISOTROPY; static ms_uint32 MAX_TEXTURE_SIZE; static ms_uint32 MIN_TEXTURE_SIZE; OglContext(ms_uint32 width, ms_uint32 height); ~OglContext(); int getHeight() const { return height; } int getWidth() const { return width; } bool isValid() const { return valid; } bool makeCurrent(); void bindPBufferToTexture(); private: bool createPBuffer(ms_uint32 width, ms_uint32 height); ms_uint32 width; ms_uint32 height; bool valid; int windowPixelFormat; #if defined(_WIN32) && !defined(__CYGWIN__) static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB; static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB; static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB; static PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB; #endif }; #endif /* USE_OGL */ #endif /* MAPOGLCONTEXT_H_ */ mapserver-6.4.1/mapprimitive.c0000644002461700001440000022516012261257215016174 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementations for rectObj, pointObj, lineObj, shapeObj, etc. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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. ****************************************************************************/ #include "mapserver.h" #include "mapprimitive.h" #include #include typedef enum {CLIP_LEFT, CLIP_MIDDLE, CLIP_RIGHT} CLIP_STATE; #define CLIP_CHECK(min, a, max) ((a) < (min) ? CLIP_LEFT : ((a) > (max) ? CLIP_RIGHT : CLIP_MIDDLE)); #define ROUND(a) ( (a) + 0.5 ) #define SWAP( a, b, t) ( (t) = (a), (a) = (b), (b) = (t) ) #define EDGE_CHECK( x0, x, x1) ((x) < MS_MIN( (x0), (x1)) ? CLIP_LEFT : ((x) > MS_MAX( (x0), (x1)) ? CLIP_RIGHT : CLIP_MIDDLE )) #ifndef INFINITY #define INFINITY (1.0e+30) #endif #define NEARZERO (1.0e-30) /* 1/INFINITY */ void msPrintShape(shapeObj *p) { int i,j; msDebug("Shape contains %d parts.\n", p->numlines); for (i=0; inumlines; i++) { msDebug("\tPart %d contains %d points.\n", i, p->line[i].numpoints); for (j=0; jline[i].numpoints; j++) { msDebug("\t\t%d: (%f, %f)\n", j, p->line[i].point[j].x, p->line[i].point[j].y); } } } shapeObj *msShapeFromWKT(const char *string) { #ifdef USE_GEOS return msGEOSShapeFromWKT(string); #elif defined(USE_OGR) return msOGRShapeFromWKT(string); #else msSetError(MS_MISCERR, "WKT support is not available, please compile MapServer with GEOS or OGR support.", "msShapeFromWKT()"); return NULL; #endif } char *msShapeToWKT(shapeObj *shape) { #ifdef USE_GEOS char* pszGEOSStr; char* pszStr; pszGEOSStr = msGEOSShapeToWKT(shape); pszStr = (pszGEOSStr) ? msStrdup(pszGEOSStr) : NULL; msGEOSFreeWKT(pszGEOSStr); return pszStr; #elif defined(USE_OGR) return msOGRShapeToWKT(shape); #else msSetError(MS_MISCERR, "WKT support is not available, please compile MapServer with GEOS or OGR support.", "msShapeToWKT()"); return NULL; #endif } void msInitShape(shapeObj *shape) { /* spatial component */ shape->line = NULL; shape->numlines = 0; shape->type = MS_SHAPE_NULL; shape->bounds.minx = shape->bounds.miny = -1; shape->bounds.maxx = shape->bounds.maxy = -1; /* attribute component */ shape->values = NULL; shape->numvalues = 0; shape->geometry = NULL; shape->renderer_cache = NULL; /* annotation component */ shape->text = NULL; /* bookkeeping component */ shape->classindex = 0; /* default class */ shape->tileindex = shape->index = shape->resultindex = -1; shape->scratch = MS_FALSE; /* not a temporary/scratch shape */ } int msCopyShape(shapeObj *from, shapeObj *to) { int i; if(!from || !to) return(-1); for(i=0; inumlines; i++) msAddLine(to, &(from->line[i])); /* copy each line */ to->type = from->type; to->bounds.minx = from->bounds.minx; to->bounds.miny = from->bounds.miny; to->bounds.maxx = from->bounds.maxx; to->bounds.maxy = from->bounds.maxy; if(from->text) to->text = msStrdup(from->text); to->classindex = from->classindex; to->index = from->index; to->tileindex = from->tileindex; to->resultindex = from->resultindex; if(from->values) { to->values = (char **)msSmallMalloc(sizeof(char *)*from->numvalues); for(i=0; inumvalues; i++) to->values[i] = msStrdup(from->values[i]); to->numvalues = from->numvalues; } to->geometry = NULL; /* GEOS code will build automatically if necessary */ to->scratch = from->scratch; return(0); } void msFreeShape(shapeObj *shape) { int c; if(!shape) return; /* for safety */ for (c= 0; c < shape->numlines; c++) free(shape->line[c].point); if (shape->line) free(shape->line); if(shape->values) msFreeCharArray(shape->values, shape->numvalues); if(shape->text) free(shape->text); #ifdef USE_GEOS msGEOSFreeGeometry(shape); #endif msInitShape(shape); /* now reset */ } void msFreeLabelPathObj(labelPathObj *path) { msFreeShape(&(path->bounds)); msFree(path->path.point); msFree(path->angles); msFree(path); } void msShapeDeleteLine( shapeObj *shape, int line ) { if( line < 0 || line >= shape->numlines ) { assert( 0 ); return; } free( shape->line[line].point ); if( line < shape->numlines - 1 ) { memmove( shape->line + line, shape->line + line + 1, sizeof(lineObj) * (shape->numlines - line - 1) ); } shape->numlines--; } void msComputeBounds(shapeObj *shape) { int i, j; if(shape->numlines <= 0) return; for(i=0; inumlines; i++) { if(shape->line[i].numpoints > 0) { shape->bounds.minx = shape->bounds.maxx = shape->line[i].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[i].point[0].y; break; } } if(i == shape->numlines) return; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { shape->bounds.minx = MS_MIN(shape->bounds.minx, shape->line[i].point[j].x); shape->bounds.maxx = MS_MAX(shape->bounds.maxx, shape->line[i].point[j].x); shape->bounds.miny = MS_MIN(shape->bounds.miny, shape->line[i].point[j].y); shape->bounds.maxy = MS_MAX(shape->bounds.maxy, shape->line[i].point[j].y); } } } /* checks to see if ring r is an outer ring of shape */ int msIsOuterRing(shapeObj *shape, int r) { int i, status=MS_TRUE; int result1, result2; if(shape->numlines == 1) return(MS_TRUE); for(i=0; inumlines; i++) { if(i == r) continue; /* ** We have to test 2, or perhaps 3 points on the shape against the ring because ** it is possible that at most one point could touch the ring and the function ** msPointInPolygon() is indeterminite in that case. (bug #2434) */ result1 = msPointInPolygon(&(shape->line[r].point[0]), &(shape->line[i])); result2 = msPointInPolygon(&(shape->line[r].point[1]), &(shape->line[i])); if(result1 == result2) { /* same result twice, neither point was on the edge */ if(result1 == MS_TRUE) status = !status; } else { /* one of the first 2 points were on the edge of the ring, the next one isn't */ if(msPointInPolygon(&(shape->line[r].point[2]), &(shape->line[i])) == MS_TRUE) status = !status; } } return(status); } /* ** Returns a list of outer rings for shape (the list has one entry for each ring, ** MS_TRUE for outer rings). */ int *msGetOuterList(shapeObj *shape) { int i; int *list; list = (int *)malloc(sizeof(int)*shape->numlines); MS_CHECK_ALLOC(list, sizeof(int)*shape->numlines, NULL); for(i=0; inumlines; i++) list[i] = msIsOuterRing(shape, i); return(list); } /* ** Returns a list of inner rings for ring r in shape (given a list of outer rings). */ int *msGetInnerList(shapeObj *shape, int r, int *outerlist) { int i; int *list; list = (int *)malloc(sizeof(int)*shape->numlines); MS_CHECK_ALLOC(list, sizeof(int)*shape->numlines, NULL); for(i=0; inumlines; i++) { /* test all rings against the ring */ if(outerlist[i] == MS_TRUE) { /* ring is an outer and can't be an inner */ list[i] = MS_FALSE; continue; } list[i] = msPointInPolygon(&(shape->line[i].point[0]), &(shape->line[r])); } return(list); } /* ** Add point to a line object. ** ** Note that reallocating the point array larger for each point can ** be pretty inefficient, so use this function sparingly. Mostly ** geometries creators should create their own working lineObj and ** then call msAddLine() to add it to a shape. */ int msAddPointToLine(lineObj *line, pointObj *point ) { line->numpoints += 1; line->point = (pointObj *) msSmallRealloc(line->point, sizeof(pointObj) * line->numpoints); line->point[line->numpoints-1] = *point; return MS_SUCCESS; } int msAddLine(shapeObj *p, lineObj *new_line) { lineObj lineCopy; lineCopy.numpoints = new_line->numpoints; lineCopy.point = (pointObj *) malloc(new_line->numpoints*sizeof(pointObj)); MS_CHECK_ALLOC(lineCopy.point, new_line->numpoints*sizeof(pointObj), MS_FAILURE); memcpy( lineCopy.point, new_line->point, sizeof(pointObj) * new_line->numpoints ); return msAddLineDirectly( p, &lineCopy ); } /* ** Same as msAddLine(), except that this version "seizes" the points ** array from the passed in line and uses it instead of copying it. */ int msAddLineDirectly(shapeObj *p, lineObj *new_line) { int c; if( p->numlines == 0 ) { p->line = (lineObj *) malloc(sizeof(lineObj)); MS_CHECK_ALLOC(p->line, sizeof(lineObj), MS_FAILURE); } else { p->line = (lineObj *) realloc(p->line, (p->numlines+1)*sizeof(lineObj)); MS_CHECK_ALLOC(p->line, (p->numlines+1)*sizeof(lineObj), MS_FAILURE); } /* Copy the new line onto the end of the extended line array */ c= p->numlines; p->line[c].numpoints = new_line->numpoints; p->line[c].point = new_line->point; /* strip points reference off the passed in lineObj */ new_line->point = NULL; new_line->numpoints = 0; /* Update the polygon information */ p->numlines++; return(MS_SUCCESS); } /* ** Converts a rect array to a shapeObj structure. Note order is CW assuming y origin ** is in the lower left corner (normal cartesian coordinate system). Also polygon is ** is closed (i.e. first=last). This conforms to the shapefile specification. For image ** coordinate systems (i.e. GD) this is back-ass-ward, which is fine cause the function ** that calculates direction assumes min y = lower left, this way it'll still work. Drawing ** functions are independent of direction. Orientation problems can cause some nasty bugs. */ void msRectToPolygon(rectObj rect, shapeObj *poly) { lineObj line= {0,NULL}; line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5); line.point[0].x = rect.minx; line.point[0].y = rect.miny; line.point[1].x = rect.minx; line.point[1].y = rect.maxy; line.point[2].x = rect.maxx; line.point[2].y = rect.maxy; line.point[3].x = rect.maxx; line.point[3].y = rect.miny; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; msAddLine(poly, &line); if(poly->numlines == 1) { /* poly was empty to begin with */ poly->type = MS_SHAPE_POLYGON; poly->bounds = rect; } else msMergeRect(&poly->bounds, &rect); free(line.point); } /* ** Private implementation of the Sutherland-Cohen algorithm. Inspired by ** "Getting Graphic: Programming Fundamentals in C and C++" by Mark Finlay ** and John Petritis. (pages 179-182) */ static int clipLine(double *x1, double *y1, double *x2, double *y2, rectObj rect) { double x, y; double slope; CLIP_STATE check1, check2; if(*x1 < rect.minx && *x2 < rect.minx) return(MS_FALSE); if(*x1 > rect.maxx && *x2 > rect.maxx) return(MS_FALSE); check1 = CLIP_CHECK(rect.minx, *x1, rect.maxx); check2 = CLIP_CHECK(rect.minx, *x2, rect.maxx); if(check1 == CLIP_LEFT || check2 == CLIP_LEFT) { slope = (*y2 - *y1)/(*x2 - *x1); y = *y1 + (rect.minx - *x1)*slope; if(check1 == CLIP_LEFT) { *x1 = rect.minx; *y1 = y; } else { *x2 = rect.minx; *y2 = y; } } if(check1 == CLIP_RIGHT || check2 == CLIP_RIGHT) { slope = (*y2 - *y1)/(*x2 - *x1); y = *y1 + (rect.maxx - *x1)*slope; if(check1 == CLIP_RIGHT) { *x1 = rect.maxx; *y1 = y; } else { *x2 = rect.maxx; *y2 = y; } } if(*y1 < rect.miny && *y2 < rect.miny) return(MS_FALSE); if(*y1 > rect.maxy && *y2 > rect.maxy) return(MS_FALSE); check1 = CLIP_CHECK(rect.miny, *y1, rect.maxy); check2 = CLIP_CHECK(rect.miny, *y2, rect.maxy); if(check1 == CLIP_LEFT || check2 == CLIP_LEFT) { slope = (*x2 - *x1)/(*y2 - *y1); x = *x1 + (rect.miny - *y1)*slope; if(check1 == CLIP_LEFT) { *x1 = x; *y1 = rect.miny; } else { *x2 = x; *y2 = rect.miny; } } if(check1 == CLIP_RIGHT || check2 == CLIP_RIGHT) { slope = (*x2 - *x1)/(*y2 - *y1); x = *x1 + (rect.maxy - *y1)*slope; if(check1 == CLIP_RIGHT) { *x1 = x; *y1 = rect.maxy; } else { *x2 = x; *y2 = rect.maxy; } } return(MS_TRUE); } /* ** Routine for clipping a polyline, stored in a shapeObj struct, to a ** rectangle. Uses clipLine() function to create a new shapeObj. */ void msClipPolylineRect(shapeObj *shape, rectObj rect) { int i,j; lineObj line= {0,NULL}; double x1, x2, y1, y2; shapeObj tmp; memset( &tmp, 0, sizeof(shapeObj) ); if(shape->numlines == 0) /* nothing to clip */ return; /* ** Don't do any clip processing of shapes completely within the ** clip rectangle based on a comparison of bounds. We could do ** something similar for completely outside, but that rarely occurs ** since the spatial query at the layer read level has generally already ** discarded all shapes completely outside the rect. */ if( shape->bounds.maxx <= rect.maxx && shape->bounds.minx >= rect.minx && shape->bounds.maxy <= rect.maxy && shape->bounds.miny >= rect.miny ) { return; } for(i=0; inumlines; i++) { line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*shape->line[i].numpoints); line.numpoints = 0; x1 = shape->line[i].point[0].x; y1 = shape->line[i].point[0].y; for(j=1; jline[i].numpoints; j++) { x2 = shape->line[i].point[j].x; y2 = shape->line[i].point[j].y; if(clipLine(&x1,&y1,&x2,&y2,rect) == MS_TRUE) { if(line.numpoints == 0) { /* first segment, add both points */ line.point[0].x = x1; line.point[0].y = y1; line.point[1].x = x2; line.point[1].y = y2; line.numpoints = 2; } else { /* add just the last point */ line.point[line.numpoints].x = x2; line.point[line.numpoints].y = y2; line.numpoints++; } if((x2 != shape->line[i].point[j].x) || (y2 != shape->line[i].point[j].y)) { msAddLine(&tmp, &line); line.numpoints = 0; /* new line */ } } x1 = shape->line[i].point[j].x; y1 = shape->line[i].point[j].y; } if(line.numpoints > 0) { msAddLineDirectly(&tmp, &line); } else { free(line.point); line.numpoints = 0; /* new line */ } } for (i=0; inumlines; i++) free(shape->line[i].point); free(shape->line); shape->line = tmp.line; shape->numlines = tmp.numlines; msComputeBounds(shape); } /* ** Slightly modified version of the Liang-Barsky polygon clipping algorithm */ void msClipPolygonRect(shapeObj *shape, rectObj rect) { int i, j; double deltax, deltay, xin,xout, yin,yout; double tinx,tiny, toutx,touty, tin1, tin2, tout; double x1,y1, x2,y2; shapeObj tmp; lineObj line= {0,NULL}; msInitShape(&tmp); if(shape->numlines == 0) /* nothing to clip */ return; /* ** Don't do any clip processing of shapes completely within the ** clip rectangle based on a comparison of bounds. We could do ** something similar for completely outside, but that rarely occurs ** since the spatial query at the layer read level has generally already ** discarded all shapes completely outside the rect. */ if( shape->bounds.maxx <= rect.maxx && shape->bounds.minx >= rect.minx && shape->bounds.maxy <= rect.maxy && shape->bounds.miny >= rect.miny ) { return; } for(j=0; jnumlines; j++) { line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*2*shape->line[j].numpoints+1); /* worst case scenario, +1 allows us to duplicate the 1st and last point */ line.numpoints = 0; for (i = 0; i < shape->line[j].numpoints-1; i++) { x1 = shape->line[j].point[i].x; y1 = shape->line[j].point[i].y; x2 = shape->line[j].point[i+1].x; y2 = shape->line[j].point[i+1].y; deltax = x2-x1; if (deltax == 0) { /* bump off of the vertical */ deltax = (x1 > rect.minx) ? -NEARZERO : NEARZERO ; } deltay = y2-y1; if (deltay == 0) { /* bump off of the horizontal */ deltay = (y1 > rect.miny) ? -NEARZERO : NEARZERO ; } if (deltax > 0) { /* points to right */ xin = rect.minx; xout = rect.maxx; } else { xin = rect.maxx; xout = rect.minx; } if (deltay > 0) { /* points up */ yin = rect.miny; yout = rect.maxy; } else { yin = rect.maxy; yout = rect.miny; } tinx = (xin - x1)/deltax; tiny = (yin - y1)/deltay; if (tinx < tiny) { /* hits x first */ tin1 = tinx; tin2 = tiny; } else { /* hits y first */ tin1 = tiny; tin2 = tinx; } if (1 >= tin1) { if (0 < tin1) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = yin; line.numpoints++; } if (1 >= tin2) { toutx = (xout - x1)/deltax; touty = (yout - y1)/deltay; tout = (toutx < touty) ? toutx : touty ; if (0 < tin2 || 0 < tout) { if (tin2 <= tout) { if (0 < tin2) { if (tinx > tiny) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = y1 + tinx*deltay; line.numpoints++; } else { line.point[line.numpoints].x = x1 + tiny*deltax; line.point[line.numpoints].y = yin; line.numpoints++; } } if (1 > tout) { if (toutx < touty) { line.point[line.numpoints].x = xout; line.point[line.numpoints].y = y1 + toutx*deltay; line.numpoints++; } else { line.point[line.numpoints].x = x1 + touty*deltax; line.point[line.numpoints].y = yout; line.numpoints++; } } else { line.point[line.numpoints].x = x2; line.point[line.numpoints].y = y2; line.numpoints++; } } else { if (tinx > tiny) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = yout; line.numpoints++; } else { line.point[line.numpoints].x = xout; line.point[line.numpoints].y = yin; line.numpoints++; } } } } } } if(line.numpoints > 0) { line.point[line.numpoints].x = line.point[0].x; /* force closure */ line.point[line.numpoints].y = line.point[0].y; line.numpoints++; msAddLineDirectly(&tmp, &line); } else { free(line.point); } } /* next line */ for (i=0; inumlines; i++) free(shape->line[i].point); free(shape->line); shape->line = tmp.line; shape->numlines = tmp.numlines; msComputeBounds(shape); return; } /* ** offsets a point relative to an image position */ void msOffsetPointRelativeTo(pointObj *point, layerObj *layer) { double x=0, y=0; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return; if(layer->transform == MS_TRUE) return; /* nothing to do */ if(layer->units == MS_PERCENTAGES) { point->x *= (layer->map->width-1); point->y *= (layer->map->height-1); } if(layer->transform == MS_FALSE || layer->transform == MS_UL) return; /* done */ switch(layer->transform) { case MS_UC: x = (layer->map->width-1)/2; y = 0; break; case MS_UR: x = layer->map->width-1; y = 0; break; case MS_CL: x = 0; y = layer->map->height/2; break; case MS_CC: x = layer->map->width/2; y = layer->map->height/2; break; case MS_CR: x = layer->map->width-1; y = layer->map->height/2; break; case MS_LL: x = 0; y = layer->map->height-1; break; case MS_LC: x = layer->map->width/2; y = layer->map->height-1; break; case MS_LR: x = layer->map->width-1; y = layer->map->height-1; break; } point->x += x; point->y += y; return; } /* ** offsets a shape relative to an image position */ void msOffsetShapeRelativeTo(shapeObj *shape, layerObj *layer) { int i, j; double x=0, y=0; if(layer->transform == MS_TRUE) return; /* nothing to do */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return; if(layer->units == MS_PERCENTAGES) { for (i=0; inumlines; i++) { for (j=0; jline[i].numpoints; j++) { shape->line[i].point[j].x *= (layer->map->width-1); shape->line[i].point[j].y *= (layer->map->height-1); } } } if(layer->transform == MS_FALSE || layer->transform == MS_UL) return; /* done */ switch(layer->transform) { case MS_UC: x = (layer->map->width-1)/2; y = 0; break; case MS_UR: x = layer->map->width-1; y = 0; break; case MS_CL: x = 0; y = layer->map->height/2; break; case MS_CC: x = layer->map->width/2; y = layer->map->height/2; break; case MS_CR: x = layer->map->width-1; y = layer->map->height/2; break; case MS_LL: x = 0; y = layer->map->height-1; break; case MS_LC: x = layer->map->width/2; y = layer->map->height-1; break; case MS_LR: x = layer->map->width-1; y = layer->map->height-1; break; } for (i=0; inumlines; i++) { for (j=0; jline[i].numpoints; j++) { shape->line[i].point[j].x += x; shape->line[i].point[j].y += y; } } return; } void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize) { int i,j,k,beforelast; /* loop counters */ double dx,dy; pointObj *point; double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ int ok = 0; if(shape->numlines == 0) return; /* nothing to transform */ if(shape->type == MS_SHAPE_LINE) { /* * loop through the shape's lines, and do naive simplification * to discard the points that are too close to one another. * currently the threshold is to discard points if they fall * less than a pixel away from their predecessor. * the simplified line is guaranteed to contain at * least its first and last point */ for(i=0; inumlines; i++) { /* for each part */ if(shape->line[i].numpoints<2) { shape->line[i].numpoints=0; continue; /*skip degenerate lines*/ } point=shape->line[i].point; /*always keep first point*/ point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs); point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs); beforelast=shape->line[i].numpoints-1; for(j=1,k=1; j < beforelast; j++ ) { /*loop from second point to first-before-last point*/ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); dx=(point[k].x-point[k-1].x); dy=(point[k].y-point[k-1].y); if(dx*dx+dy*dy>1) k++; } /* try to keep last point */ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); /* discard last point if equal to the one before it */ if(point[k].x!=point[k-1].x || point[k].y!=point[k-1].y) { shape->line[i].numpoints=k+1; } else { shape->line[i].numpoints=k; } /* skip degenerate line once more */ if(shape->line[i].numpoints<2) { shape->line[i].numpoints=0; } else { ok = 1; /* we have at least one line with more than two points */ } } } else if(shape->type == MS_SHAPE_POLYGON) { /* * loop through the shape's lines, and do naive simplification * to discard the points that are too close to one another. * currently the threshold is to discard points if they fall * less than a pixel away from their predecessor. * the simplified polygon is guaranteed to contain at * least its first, second and last point */ for(i=0; inumlines; i++) { /* for each part */ if(shape->line[i].numpoints<4) { shape->line[i].numpoints=0; continue; /*skip degenerate lines*/ } point=shape->line[i].point; /*always keep first and second point*/ point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs); point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs); point[1].x = MS_MAP2IMAGE_X_IC_DBL(point[1].x, extent.minx, inv_cs); point[1].y = MS_MAP2IMAGE_Y_IC_DBL(point[1].y, extent.maxy, inv_cs); beforelast=shape->line[i].numpoints-2; for(j=2,k=2; j < beforelast; j++ ) { /*loop from second point to second-before-last point*/ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); dx=(point[k].x-point[k-1].x); dy=(point[k].y-point[k-1].y); if(dx*dx+dy*dy>1) k++; } /*always keep last two points (the last point is the repetition of the * first one */ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); point[k+1].x = MS_MAP2IMAGE_X_IC_DBL(point[j+1].x, extent.minx, inv_cs); point[k+1].y = MS_MAP2IMAGE_Y_IC_DBL(point[j+1].y, extent.maxy, inv_cs); shape->line[i].numpoints = k+2; ok = 1; } } else { /* only for untyped shapes, as point layers don't go through this function */ for(i=0; inumlines; i++) { point=shape->line[i].point; for(j=0; jline[i].numpoints; j++) { point[j].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[j].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); } } ok = 1; } if(!ok) { for(i=0; inumlines; i++) { free(shape->line[i].point); } shape->numlines = 0 ; } } /** * Generic function to transorm the shape coordinates to output coordinates */ void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image) { if (image != NULL && MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); if(renderer->transform_mode == MS_TRANSFORM_SNAPTOGRID) { msTransformShapeToPixelSnapToGrid(shape, extent, cellsize, renderer->approximation_scale); } else if(renderer->transform_mode == MS_TRANSFORM_SIMPLIFY) { msTransformShapeSimplify(shape, extent, cellsize); } else if(renderer->transform_mode == MS_TRANSFORM_ROUND) { msTransformShapeToPixelRound(shape, extent, cellsize); } else if(renderer->transform_mode == MS_TRANSFORM_FULLRESOLUTION) { msTransformShapeToPixelDoublePrecision(shape,extent,cellsize); } else if(renderer->transform_mode == MS_TRANSFORM_NONE) { /* nothing to do */ return; } /* unknown, do nothing */ return; } msTransformShapeToPixelRound(shape, extent, cellsize); } void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution) { int i,j,k; /* loop counters */ double inv_cs; if(shape->numlines == 0) return; inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */ for(i=0; inumlines; i++) { /* for each part */ int snap = 1; double x0,y0,x1,y1,x2,y2; /*do a quick heuristic: will we risk having a degenerate shape*/ if(shape->type == MS_SHAPE_LINE) { /*a line is degenerate if it has a single pixel. we check that the first and last pixel are different*/ x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution); y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution); x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs, grid_resolution); y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs, grid_resolution); if(x0 == x1 && y0 == y1) { snap = 0; } } else if(shape->type == MS_SHAPE_POLYGON) { x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution); y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution); x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].x, extent.minx, inv_cs, grid_resolution); y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].y, extent.maxy, inv_cs, grid_resolution); x2 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].x, extent.minx, inv_cs, grid_resolution); y2 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].y, extent.maxy, inv_cs, grid_resolution); if((x0 == x1 && y0 == y1) || (x0 == x2 && y0 == y2) || (x1 == x2 && y1 == y2)) { snap = 0; } } if(snap) { shape->line[i].point[0].x = x0; shape->line[i].point[0].y = y0; for(j=1, k=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[j].x, extent.minx, inv_cs, grid_resolution); shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[j].y, extent.maxy, inv_cs, grid_resolution); if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y) k++; } shape->line[i].numpoints=k; } else { if(shape->type == MS_SHAPE_LINE) { shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[0].x, extent.minx, inv_cs); shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[0].y, extent.maxy, inv_cs); shape->line[i].point[1].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs); shape->line[i].point[1].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs); shape->line[i].numpoints = 2; } else { for(j=0; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } } } else { /* points or untyped shapes */ for(i=0; inumlines; i++) { /* for each part */ for(j=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } } void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize) { int i,j,k; /* loop counters */ double inv_cs; if(shape->numlines == 0) return; inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */ for(i=0; inumlines; i++) { /* for each part */ shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);; shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs); for(j=1, k=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs); if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y) k++; } shape->line[i].numpoints=k; } } else { /* points or untyped shapes */ for(i=0; inumlines; i++) { /* for each part */ for(j=0; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } } void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize) { int i,j; /* loop counters */ double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } /* ** Converts from map coordinates to image coordinates */ void msTransformPixelToShape(shapeObj *shape, rectObj extent, double cellsize) { int i,j; /* loop counters */ if(shape->numlines == 0) return; /* nothing to transform */ if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove co-linear vertices */ for(i=0; inumlines; i++) { /* for each part */ for(j=0; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_IMAGE2MAP_X(shape->line[i].point[j].x, extent.minx, cellsize); shape->line[i].point[j].y = MS_IMAGE2MAP_Y(shape->line[i].point[j].y, extent.maxy, cellsize); } } } else { /* points or untyped shapes */ for(i=0; inumlines; i++) { /* for each part */ for(j=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_IMAGE2MAP_X(shape->line[i].point[j].x, extent.minx, cellsize); shape->line[i].point[j].y = MS_IMAGE2MAP_Y(shape->line[i].point[j].y, extent.maxy, cellsize); } } } return; } /* ** Not a generic intersection test, we KNOW the lines aren't parallel or coincident. To be used with the next ** buffering code only. See code in mapsearch.c for a boolean test for intersection. */ static pointObj generateLineIntersection(pointObj a, pointObj b, pointObj c, pointObj d) { pointObj p; double r; double denominator, numerator; if(b.x == c.x && b.y == c.y) return(b); numerator = ((a.y-c.y)*(d.x-c.x) - (a.x-c.x)*(d.y-c.y)); denominator = ((b.x-a.x)*(d.y-c.y) - (b.y-a.y)*(d.x-c.x)); r = numerator/denominator; p.x = MS_NINT(a.x + r*(b.x-a.x)); p.y = MS_NINT(a.y + r*(b.y-a.y)); return(p); } void bufferPolyline(shapeObj *p, shapeObj *op, int w) { int i, j; pointObj a; lineObj inside, outside; double angle; double dx, dy; for (i = 0; i < p->numlines; i++) { inside.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*p->line[i].numpoints); outside.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*p->line[i].numpoints); inside.numpoints = outside.numpoints = p->line[i].numpoints; angle = asin(MS_ABS(p->line[i].point[1].x - p->line[i].point[0].x)/sqrt((((p->line[i].point[1].x - p->line[i].point[0].x)*(p->line[i].point[1].x - p->line[i].point[0].x)) + ((p->line[i].point[1].y - p->line[i].point[0].y)*(p->line[i].point[1].y - p->line[i].point[0].y))))); if(p->line[i].point[0].x < p->line[i].point[1].x) dy = sin(angle) * (w/2); else dy = -sin(angle) * (w/2); if(p->line[i].point[0].y < p->line[i].point[1].y) dx = -cos(angle) * (w/2); else dx = cos(angle) * (w/2); inside.point[0].x = p->line[i].point[0].x + dx; inside.point[1].x = p->line[i].point[1].x + dx; inside.point[0].y = p->line[i].point[0].y + dy; inside.point[1].y = p->line[i].point[1].y + dy; outside.point[0].x = p->line[i].point[0].x - dx; outside.point[1].x = p->line[i].point[1].x - dx; outside.point[0].y = p->line[i].point[0].y - dy; outside.point[1].y = p->line[i].point[1].y - dy; for(j=2; jline[i].numpoints; j++) { angle = asin(MS_ABS(p->line[i].point[j].x - p->line[i].point[j-1].x)/sqrt((((p->line[i].point[j].x - p->line[i].point[j-1].x)*(p->line[i].point[j].x - p->line[i].point[j-1].x)) + ((p->line[i].point[j].y - p->line[i].point[j-1].y)*(p->line[i].point[j].y - p->line[i].point[j-1].y))))); if(p->line[i].point[j-1].x < p->line[i].point[j].x) dy = sin(angle) * (w/2); else dy = -sin(angle) * (w/2); if(p->line[i].point[j-1].y < p->line[i].point[j].y) dx = -cos(angle) * (w/2); else dx = cos(angle) * (w/2); a.x = p->line[i].point[j-1].x + dx; inside.point[j].x = p->line[i].point[j].x + dx; a.y = p->line[i].point[j-1].y + dy; inside.point[j].y = p->line[i].point[j].y + dy; inside.point[j-1] = generateLineIntersection(inside.point[j-2], inside.point[j-1], a, inside.point[j]); a.x = p->line[i].point[j-1].x - dx; outside.point[j].x = p->line[i].point[j].x - dx; a.y = p->line[i].point[j-1].y - dy; outside.point[j].y = p->line[i].point[j].y - dy; outside.point[j-1] = generateLineIntersection(outside.point[j-2], outside.point[j-1], a, outside.point[j]); } /* need a touch of code if 1st point equals last point in p (find intersection) */ msAddLine(op, &inside); msAddLine(op, &outside); free(inside.point); free(outside.point); } return; } static double getRingArea(lineObj *ring) { int i; double s=0; for(i=0; inumpoints-1; i++) s += (ring->point[i].x*ring->point[i+1].y - ring->point[i+1].x*ring->point[i].y); return (MS_ABS(s/2)); } double msGetPolygonArea(shapeObj *p) { int i; double area=0; for(i=0; inumlines; i++) { if(msIsOuterRing(p, i)) area += getRingArea(&(p->line[i])); else area -= getRingArea(&(p->line[i])); /* hole */ } return area; } /* ** Computes the center of gravity for a polygon based on it's largest outer ring only. */ static int getPolygonCenterOfGravity(shapeObj *p, pointObj *lp) { int i, j; double area=0; double sx=0, sy=0, tsx, tsy, s; /* sums */ double a; double largestArea=0; for(i=0; inumlines; i++) { tsx = tsy = s = 0; /* reset the ring sums */ for(j=0; jline[i].numpoints-1; j++) { a = p->line[i].point[j].x*p->line[i].point[j+1].y - p->line[i].point[j+1].x*p->line[i].point[j].y; s += a; tsx += (p->line[i].point[j].x + p->line[i].point[j+1].x)*a; tsy += (p->line[i].point[j].y + p->line[i].point[j+1].y)*a; } area = MS_ABS(s/2); if(area > largestArea) { largestArea = area; sx = s>0?tsx:-tsx; sy = s>0?tsy:-tsy; } } lp->x = sx/(6*largestArea); lp->y = sy/(6*largestArea); return MS_SUCCESS; } int msGetPolygonCentroid(shapeObj *p, pointObj *lp, double *miny, double *maxy) { int i,j; double cent_weight_x=0.0, cent_weight_y=0.0; double len, total_len=0; *miny = *maxy = p->line[0].point[0].y; for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { *miny = MS_MIN(*miny, p->line[i].point[j].y); *maxy = MS_MAX(*maxy, p->line[i].point[j].y); len = msDistancePointToPoint(&(p->line[i].point[j-1]), &(p->line[i].point[j])); cent_weight_x += len * ((p->line[i].point[j-1].x + p->line[i].point[j].x)/2); cent_weight_y += len * ((p->line[i].point[j-1].y + p->line[i].point[j].y)/2); total_len += len; } } if(total_len == 0) return(MS_FAILURE); lp->x = cent_weight_x / total_len; lp->y = cent_weight_y / total_len; return(MS_SUCCESS); } /* ** Find a label point in a polygon. */ int msPolygonLabelPoint(shapeObj *p, pointObj *lp, double min_dimension) { double slope; pointObj *point1=NULL, *point2=NULL, cp; int i, j, nfound; double x, y, *intersect, temp; double min, max; int wrong_order, n; double len, max_len=0; double minx, maxx, maxy, miny; int method = 2; msComputeBounds(p); minx = p->bounds.minx; miny = p->bounds.miny; maxx = p->bounds.maxx; maxy = p->bounds.maxy; if(min_dimension > 0) if(MS_MIN(maxx-minx,maxy-miny) < min_dimension) return(MS_FAILURE); cp.x = (maxx+minx)/2.0; cp.y = (maxy+miny)/2.0; switch (method) { case 0: /* MBR */ lp->x = cp.x; lp->y = cp.y; break; case 1: /* centroid */ if(msGetPolygonCentroid(p, lp, &miny, &maxy) != MS_SUCCESS) return(MS_FAILURE); break; case 2: /* center of gravity */ if(getPolygonCenterOfGravity(p, lp) != MS_SUCCESS) return(MS_FAILURE); break; } if(msIntersectPointPolygon(lp, p) == MS_TRUE) { double dist, min_dist=-1; /* compute a distance to the polygon */ for(j=0; jnumlines; j++) { for(i=1; iline[j].numpoints; i++) { dist = msSquareDistancePointToSegment(lp, &(p->line[j].point[i-1]), &(p->line[j].point[i])); if((dist < min_dist) || (min_dist < 0)) min_dist = dist; } } min_dist = sqrt(min_dist); if(min_dist > .1*MS_MAX(maxx-minx, maxy-miny)) return(MS_SUCCESS); /* point is not too close to the edge */ } /* printf("label: %s\n", p->text); printf(" bbox: %g %g %g %g\n",minx, miny, maxx, maxy); printf(" center: %g %g\n", cp.x, cp.y); printf(" center of gravity: %g %g\n", lp->x, lp->y); printf(" dx: %g, dy: %g\n", lp->x-cp.x, lp->y-cp.y); printf(" distance to parent shape: %g\n", min_dist); return MS_SUCCESS; */ n=0; for(j=0; jnumlines; j++) /* count total number of points */ n += p->line[j].numpoints; intersect = (double *) calloc(n, sizeof(double)); MS_CHECK_ALLOC(intersect, n*sizeof(double), MS_FAILURE); if(MS_ABS((int)lp->x - (int)cp.x) > MS_ABS((int)lp->y - (int)cp.y)) { /* center horizontally, fix y */ y = lp->y; /* need to find a y that won't intersect any vertices exactly */ max = y - 1; /* first initializing min, max to be any 2 pnts on either side of y */ min = y + 1; for(j=0; jnumlines; j++) { if((min < y) && (max >= y)) break; for(i=0; i < p->line[j].numpoints; i++) { if((min < y) && (max >= y)) break; if(p->line[j].point[i].y < y) min = p->line[j].point[i].y; if(p->line[j].point[i].y >= y) max = p->line[j].point[i].y; } } n=0; for(j=0; jnumlines; j++) { for(i=0; i < p->line[j].numpoints; i++) { if((p->line[j].point[i].y < y) && ((y - p->line[j].point[i].y) < (y - min))) min = p->line[j].point[i].y; if((p->line[j].point[i].y >= y) && ((p->line[j].point[i].y - y) < (max - y))) max = p->line[j].point[i].y; } } if(min == max) return (MS_FAILURE); else y = (max + min)/2.0; nfound = 0; for(j=0; jnumlines; j++) { /* for each line */ point1 = &( p->line[j].point[p->line[j].numpoints-1] ); for(i=0; i < p->line[j].numpoints; i++) { point2 = &( p->line[j].point[i] ); if(EDGE_CHECK(point1->y, y, point2->y) == CLIP_MIDDLE) { if(point1->y == point2->y) continue; /* ignore horizontal edges */ else slope = (point2->x - point1->x) / (point2->y - point1->y); x = point1->x + (y - point1->y)*slope; intersect[nfound++] = x; } /* end checking this edge */ point1 = point2; /* next edge */ } } /* finished line */ /* sort the intersections */ do { wrong_order = 0; for(i=0; i < nfound-1; i++) { if(intersect[i] > intersect[i+1]) { wrong_order = 1; SWAP(intersect[i], intersect[i+1], temp); } } } while(wrong_order); /* find longest span */ for(i=0; i < nfound; i += 2) { len = fabs(intersect[i] - intersect[i+1]); if(len > max_len) { max_len = len; lp->x = (intersect[i] + intersect[i+1])/2; /* lp->y = y; */ } } } else { /* center vertically, fix x */ x = lp->x; /* need to find a x that won't intersect any vertices exactly */ max = x - 1; /* first initializing min, max to be any 2 pnts on either side of x */ min = x + 1; for(j=0; jnumlines; j++) { if((min < x) && (max >= x)) break; for(i=0; i < p->line[j].numpoints; i++) { if((min < x) && (max >= x)) break; if(p->line[j].point[i].x < x) min = p->line[j].point[i].x; if(p->line[j].point[i].x >= x) max = p->line[j].point[i].x; } } n=0; for(j=0; jnumlines; j++) { for(i=0; i < p->line[j].numpoints; i++) { if((p->line[j].point[i].x < x) && ((x - p->line[j].point[i].x) < (x - min))) min = p->line[j].point[i].x; if((p->line[j].point[i].x >= x) && ((p->line[j].point[i].x - x) < (max - x))) max = p->line[j].point[i].x; } } if(min == max) return (MS_FAILURE); else x = (max + min)/2.0; nfound = 0; for(j=0; jnumlines; j++) { /* for each line */ point1 = &( p->line[j].point[p->line[j].numpoints-1] ); for(i=0; i < p->line[j].numpoints; i++) { point2 = &( p->line[j].point[i] ); if(EDGE_CHECK(point1->x, x, point2->x) == CLIP_MIDDLE) { if(point1->x == point2->x) continue; /* ignore vertical edges */ else if(point1->y == point2->y) y = point1->y; /* for a horizontal edge we know y */ else { slope = (point2->x - point1->x) / (point2->y - point1->y); y = (x - point1->x)/slope + point1->y; } intersect[nfound++] = y; } /* end checking this edge */ point1 = point2; /* next edge */ } } /* finished line */ /* sort the intersections */ do { wrong_order = 0; for(i=0; i < nfound-1; i++) { if(intersect[i] > intersect[i+1]) { wrong_order = 1; SWAP(intersect[i], intersect[i+1], temp); } } } while(wrong_order); /* find longest span */ for(i=0; i < nfound; i += 2) { len = fabs(intersect[i] - intersect[i+1]); if(len > max_len) { max_len = len; lp->y = (intersect[i] + intersect[i+1])/2; /* lp->x = x; */ } } } free(intersect); if(max_len > 0) return(MS_SUCCESS); else return(MS_FAILURE); } /* Compute all the lineString/segment lengths and determine the longest lineString of a multiLineString * shape: in paramater, the multiLineString to compute. * segment_lengths: out parameter, the segment lengths of all lineString. * line_lengths: out parameter, the lineString lengths of the multiLineString. * max_line_index: out parameter, the index of the longest lineString of the multiLineString. * max_line_length: out parameter, the length of the longest lineString of the multiLineString. * total_length: out parameter, the total length of the MultiLineString * segment_index: out parameter, the index of the longest lineString of the multiLineString. */ void msPolylineComputeLineSegments(shapeObj *shape, double ***segment_lengths, double **line_lengths, int *max_line_index, double *max_line_length, int *segment_index, double *total_length) { int i, j, temp_segment_index; double segment_length, max_segment_length; (*segment_lengths) = (double **) msSmallMalloc(sizeof(double *) * shape->numlines); (*line_lengths) = (double *) msSmallMalloc(sizeof(double) * shape->numlines); temp_segment_index = *segment_index = *max_line_index = 0; *total_length = 0; *max_line_length = 0; for(i=0; inumlines; i++) { (*segment_lengths)[i] = (double*) msSmallMalloc(sizeof(double) * shape->line[i].numpoints); (*line_lengths)[i] = 0; max_segment_length = 0; for(j=1; jline[i].numpoints; j++) { segment_length = sqrt((((shape->line[i].point[j].x-shape->line[i].point[j-1].x)*(shape->line[i].point[j].x-shape->line[i].point[j-1].x)) + ((shape->line[i].point[j].y-shape->line[i].point[j-1].y)*(shape->line[i].point[j].y-shape->line[i].point[j-1].y)))); (*line_lengths)[i] += segment_length; (*segment_lengths)[i][j-1] = segment_length; if(segment_length > max_segment_length) { max_segment_length = segment_length; temp_segment_index = j; } } *total_length += (*line_lengths)[i]; if((*line_lengths)[i] > *max_line_length) { *max_line_length = (*line_lengths)[i]; *max_line_index = i; *segment_index = temp_segment_index; } } } /* ** If no repeatdistance, find center of longest segment in polyline p. The polyline must have been converted ** to image coordinates before calling this function. */ pointObj** msPolylineLabelPoint(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int anglemode) { return msPolylineLabelPointExtended(p, min_length, repeat_distance, angles, lengths, numpoints, NULL, 0, anglemode); } pointObj** msPolylineLabelPointExtended(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int *regularLines, int numlines, int anglemode) { double total_length, max_line_length; int i,j, max_line_index, segment_index, labelpoints_index, labelpoints_size; double** segment_lengths; double* line_lengths; pointObj** labelpoints; labelpoints_index = 0; labelpoints_size = p->numlines; /* minimal array size */ *numpoints = 0; labelpoints = (pointObj **) msSmallMalloc(sizeof(pointObj *) * labelpoints_size); (*angles) = (double **) msSmallMalloc(sizeof(double *) * labelpoints_size); (*lengths) = (double **) msSmallMalloc(sizeof(double *) * labelpoints_size); msPolylineComputeLineSegments(p, &segment_lengths, &line_lengths, &max_line_index, &max_line_length, &segment_index, &total_length); if (repeat_distance > 0) { for(i=0; inumlines; i++) if (numlines > 0) { for (j=0; jnumlines; i++ ) free(segment_lengths[i]); free(segment_lengths); } free(line_lengths); return labelpoints; } void msPolylineLabelPointLineString(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, double** segment_lengths, int line_index, double line_length, double total_length, int segment_index, int* labelpoints_index, int* labelpoints_size, pointObj ***labelpoints, int anglemode) { int i, j, k, l, n, index, point_repeat; double t, tmp_length, theta, fwd_length, point_distance; double center_point_position, left_point_position, right_point_position, point_position; tmp_length = total_length; if (repeat_distance > 0) tmp_length = line_length; if((min_length != -1) && (tmp_length < min_length)) /* too short to label */ return; i = line_index; if(p->line[i].numpoints < 2) return; point_distance = 0; point_repeat = 1; left_point_position = right_point_position = center_point_position = line_length / 2.0; if (repeat_distance > 0) { point_repeat = line_length / repeat_distance; if (point_repeat > 1) { if (point_repeat % 2 == 0) point_repeat -= 1; point_distance = (line_length / point_repeat); /* buffer allowed per point */ /* initial point position */ left_point_position -= ((point_repeat-1)/2 * point_distance); right_point_position += ((point_repeat-1)/2 * point_distance); point_repeat = (point_repeat-1)/2+1; } else point_repeat = 1; } for (l=0; l < point_repeat; ++l) { if (l == point_repeat-1) { /* last point to place is always the center point */ point_position = center_point_position; n = 1; } else { point_position = right_point_position; n = 0; } do { if (*labelpoints_index == *labelpoints_size) { *labelpoints_size *= 2; (*labelpoints) = (pointObj **) msSmallRealloc(*labelpoints,sizeof(pointObj *) * (*labelpoints_size)); (*angles) = (double **) msSmallRealloc(*angles,sizeof(double *) * (*labelpoints_size)); (*lengths) = (double **) msSmallRealloc(*lengths,sizeof(double *) * (*labelpoints_size)); } index = (*labelpoints_index)++; (*labelpoints)[index] = (pointObj *) msSmallMalloc(sizeof(pointObj)); (*angles)[index] = (double *) msSmallMalloc(sizeof(double)); (*lengths)[index] = (double *) msSmallMalloc(sizeof(double)); if (repeat_distance > 0) *(*lengths)[index] = line_length; else *(*lengths)[index] = total_length; /* if there is only 1 label to place... put it in the middle of the current segment (as old behavior) */ if ( ((anglemode == MS_AUTO) || (anglemode == MS_AUTO2)) && (point_repeat == 1) ) { j = segment_index; (*labelpoints)[index]->x = (p->line[i].point[j].x + p->line[i].point[j-1].x)/2.0; (*labelpoints)[index]->y = (p->line[i].point[j].y + p->line[i].point[j-1].y)/2.0; } else { j=0; fwd_length = 0; while (fwd_length < point_position) { fwd_length += segment_lengths[i][j++]; } k = j-1; t = 1 - (fwd_length - point_position) / segment_lengths[i][j-1]; (*labelpoints)[index]->x = t * (p->line[i].point[k+1].x - p->line[i].point[k].x) + p->line[i].point[k].x; (*labelpoints)[index]->y = t * (p->line[i].point[k+1].y - p->line[i].point[k].y) + p->line[i].point[k].y; } if(anglemode != MS_NONE) { theta = atan2(p->line[i].point[j].x - p->line[i].point[j-1].x, p->line[i].point[j].y - p->line[i].point[j-1].y); if(anglemode == MS_AUTO2) { *(*angles)[index] = (MS_RAD_TO_DEG*theta) - 90; } else { /* AUTO, FOLLOW */ if(p->line[i].point[j-1].x < p->line[i].point[j].x) { /* i.e. to the left */ *(*angles)[index] = (MS_RAD_TO_DEG*theta) - 90; } else { *(*angles)[index] = (MS_RAD_TO_DEG*theta) + 90; } } } point_position = left_point_position; n++; } while (n<2); /* we place the right point then the left point. */ right_point_position -= point_distance; left_point_position += point_distance; } return; } /* Calculate the labelpath for each line if repeatdistance is enabled, else the labelpath of the longest line segment */ labelPathObj** msPolylineLabelPath(mapObj *map, imageObj *img,shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int *numpaths, int** regular_lines, int* num_regular_lines) { double max_line_length, total_length; double **segment_lengths, *line_lengths; int i, segment_index, max_line_index, labelpaths_index, labelpaths_size, regular_lines_index, regular_lines_size; labelPathObj** labelpaths; labelpaths_index = 0; labelpaths_size = p->numlines; /* minimal array size */ regular_lines_index = 0; regular_lines_size = 1; *numpaths = 0; segment_index = max_line_index = 0; total_length = max_line_length = 0.0; if(!string) return NULL; labelpaths = (labelPathObj **) msSmallMalloc(sizeof(labelPathObj *) * labelpaths_size); (*regular_lines) = (int *) msSmallMalloc(sizeof(int) * regular_lines_size); if(label->offsetx != 0 && IS_PERPENDICULAR_OFFSET(label->offsety)) { double offset; if(label->offsetx > 0) { offset = label->offsetx + label->size/2; } else { offset = label->offsetx - label->size/2; } if(label->offsety == MS_LABEL_PERPENDICULAR_TOP_OFFSET && p->numlines>0 && p->line[0].numpoints > 0) { /* is the line mostly left-to-right or right-to-left ? * FIXME this should be done line by line, by stepping through shape->lines, however * the OffsetPolyline function works on shapeObjs, not lineObjs * we only check the first line */ if(p->line[0].point[0].x < p->line[0].point[p->line[0].numpoints-1].x) { /* line is left to right */ offset = -offset; } } p = msOffsetPolyline(p,offset, MS_STYLE_SINGLE_SIDED_OFFSET); if(!p) return NULL; } msPolylineComputeLineSegments(p, &segment_lengths, &line_lengths, &max_line_index, &max_line_length, &segment_index, &total_length); if(label->repeatdistance > 0) for(i=0; inumlines; i++) { msPolylineLabelPathLineString(map,img, p,min_length, fontset, string, label, scalefactor, i, segment_lengths, line_lengths[i], total_length, &labelpaths_index, &labelpaths_size, &labelpaths, regular_lines, ®ular_lines_index, ®ular_lines_size); } else msPolylineLabelPathLineString(map, img, p,min_length, fontset, string, label, scalefactor, max_line_index, segment_lengths, line_lengths[max_line_index], total_length, &labelpaths_index, &labelpaths_size, &labelpaths, regular_lines, ®ular_lines_index, ®ular_lines_size); /* freeing memory: allocated by msPolylineComputeLineSegments */ if ( segment_lengths ) { for ( i = 0; i < p->numlines; i++ ) free(segment_lengths[i]); free(segment_lengths); } free(line_lengths); /* set the number of paths in the array */ *numpaths = labelpaths_index; *num_regular_lines = regular_lines_index; if(IS_PERPENDICULAR_OFFSET(label->offsety) && label->offsetx != 0) { msFreeShape(p); msFree(p); } return labelpaths; } /* * Calculate a series of label points for each character in the label for a * given polyline. The resultant series of points is stored in *labelpath, * which is added to the labelpaths array. Note that the points and bounds * are allocated in this function. The polyline must be converted to image * coordinates before calling this function. */ void msPolylineLabelPathLineString(mapObj *map, imageObj *img, shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int line_index, double** segment_lengths, double line_length, double total_length, int* labelpaths_index, int* labelpaths_size, labelPathObj*** labelpaths, int** regular_lines, int *regular_lines_index, int* regular_lines_size) { double distance_along_segment; double segment_length, fwd_line_length, rev_line_length, text_length, text_start_length, label_buffer, text_end_length; double right_label_position, left_label_position, center_label_position; int numchars; int i,j,k,l,n, inc, final_j, label_repeat; double direction; rectObj bbox; lineObj bounds; double *offsets; double size, t, tmp_length; double cx, cy; /* centre of a character, x & y values. */ double theta; double dx, dy, w, cos_t, sin_t; labelPathObj *labelpath = NULL; /* Line smoothing kernel */ double kernel[] = {0.1,0.2,2,0.2,0.1}; /* {1.5, 2, 15, 2, 1.5}; */ double kernel_normal = 2.6; /* Must be sum of kernel elements */ int kernel_size = 5; double letterspacing = 1.05; /* As per RFC 60, if label->maxoverlapangle == 0 then fall back on pre-6.0 behavior which was to use maxoverlapangle = 0.4*MS_PI ( 40% of 180 degrees ) */ double maxoverlapangle = 0.4 * MS_PI; offsets = NULL; tmp_length = total_length; if (label->repeatdistance > 0) tmp_length = line_length; numchars = msGetNumGlyphs(string); /* skip the label and use the normal algorithm if it has fewer than 2 characters */ if(numchars < 2) goto ANGLEFOLLOW_FAILURE; i = line_index; if (((min_length != -1) && (tmp_length < min_length))) { /* too short */ goto FAILURE; } if(p->line[i].numpoints < 2) { /* degenerate */ goto FAILURE; } if(p->line[i].numpoints == 2) /* use the regular angled text algorithm */ goto ANGLEFOLLOW_FAILURE; size = label->size*scalefactor; size = MS_MAX(size, label->minsize*img->resolutionfactor); size = MS_MIN(size, label->maxsize*img->resolutionfactor); /* determine the total length of the text */ if (msGetLabelSize(map,label,string,size,&bbox,&offsets) != MS_SUCCESS) { goto FAILURE; } scalefactor = size / label->size; text_length = letterspacing * (bbox.maxx - bbox.minx); /* ** if the text length is way longer than the line, skip adding the ** label if it isn't forced (long extrapolated labels tend to be ugly) */ if ( text_length > 1.5 * line_length && label->force == MS_FALSE ) { goto FAILURE; } /* We compute the number of labels we can repeat in the line */ text_end_length = 0; left_label_position = right_label_position = center_label_position = (line_length - text_length) / 2.0; label_repeat = (line_length / (text_length + label->repeatdistance)); label_buffer = (line_length / label_repeat); /* buffer allowed per label */ if (label->repeatdistance > 0 && label_repeat > 1) { if (label_repeat % 2 == 0) { label_repeat -= 1; label_buffer = (line_length / label_repeat); } /* text_start_length = (label_buffer / 2) - (text_length / 2); */ /* initial point position */ left_label_position -= ((label_repeat-1)/2 * label_buffer); right_label_position += ((label_repeat-1)/2 * label_buffer); label_repeat = (label_repeat-1)/2+1; } else { label_repeat = 1; center_label_position = (line_length - text_length) / 2.0; } if(label->maxoverlapangle >=0) maxoverlapangle = label->maxoverlapangle * MS_DEG_TO_RAD; /* radian */ for (l=0; l < label_repeat; l++) { if (l == label_repeat-1) { /* last label to place is always the center label */ text_start_length = center_label_position; n = 1; } else { text_start_length = right_label_position; n = 0; } do { /* allocate the labelpath */ labelpath = (labelPathObj *) msSmallMalloc(sizeof(labelPathObj)); labelpath->path.numpoints = numchars; labelpath->path.point = (pointObj *) msSmallCalloc(labelpath->path.numpoints, sizeof(pointObj)); labelpath->angles = (double *) msSmallMalloc(sizeof(double) * (labelpath->path.numpoints)); msInitShape(&(labelpath->bounds)); /* ** The bounds will have two points for each character plus an endpoint: ** the UL corners of each bbox will be tied together and the LL corners ** will be tied together. */ bounds.numpoints = 2*numchars + 1; bounds.point = (pointObj *) msSmallMalloc(sizeof(pointObj) * bounds.numpoints); /* the points start at (line_length - text_length) / 2 in order to be centred */ /* text_start_length = (line_length - text_length) / 2.0; */ /* the text is longer than the line: extrapolate the first and last segments */ if(text_start_length < 0.0) { j = 0; final_j = p->line[i].numpoints - 1; fwd_line_length = rev_line_length = 0; } else { /* proceed until we've traversed text_start_length in distance */ fwd_line_length = 0; j = 0; while ( fwd_line_length < text_start_length ) fwd_line_length += segment_lengths[i][j++]; j--; /* determine the last segment */ rev_line_length = 0; final_j = p->line[i].numpoints - 1; text_end_length = line_length - (text_start_length + text_length); while(rev_line_length < text_end_length) { rev_line_length += segment_lengths[i][final_j - 1]; final_j--; } final_j++; } if(final_j == 0) final_j = 1; /* determine if the line is mostly left to right or right to left, see bug 1620 discussion by Steve Woodbridge */ direction = 0; k = j; while (k < final_j) { direction += p->line[i].point[k+1].x - p->line[i].point[k].x; k++; } if(direction > 0) { inc = 1; /* j is already correct */ /* length of the segment containing the starting point */ segment_length = segment_lengths[i][j]; /* determine how far along the segment we need to go */ if(text_start_length < 0.0) t = text_start_length / segment_length; else t = 1 - (fwd_line_length - text_start_length) / segment_length; } else { j = final_j; inc = -1; /* length of the segment containing the starting point */ segment_length = segment_lengths[i][j-1]; if(text_start_length < 0.0) t = text_start_length / segment_length; else t = 1 - (rev_line_length - text_end_length) / segment_length; } distance_along_segment = t * segment_length; /* starting point */ theta = 0; k = 0; w = 0; while ( k < labelpath->path.numpoints ) { int m; double x,y; x = t * (p->line[i].point[j+inc].x - p->line[i].point[j].x) + p->line[i].point[j].x; y = t * (p->line[i].point[j+inc].y - p->line[i].point[j].y) + p->line[i].point[j].y; /* ** This used to be a series of if-then-else's, but that fails for short (length < 4) ** labels. There may be small speed-ups possible here. (bug 1921) ** ** average this label point with its neighbors according to the smoothing kernel */ if ( k == 0) { labelpath->path.point[k].x += (kernel[0] + kernel[1]) * x; labelpath->path.point[k].y += (kernel[0] + kernel[1]) * y; } if ( k == 1) { labelpath->path.point[k].x += kernel[0] * x; labelpath->path.point[k].y += kernel[0] * y; } if ( k == labelpath->path.numpoints - 2) { labelpath->path.point[k].x += kernel[4] * x; labelpath->path.point[k].y += kernel[4] * y; } if ( k == labelpath->path.numpoints - 1) { labelpath->path.point[k].x += (kernel[3] + kernel[4]) * x; labelpath->path.point[k].y += (kernel[3] + kernel[4]) * y; } for(m = 0; m < kernel_size; m++) { if(m + k - 2 < 0 || m + k - 2 > labelpath->path.numpoints - 1) continue; labelpath->path.point[k+m-2].x += kernel[m]*x; labelpath->path.point[k+m-2].y += kernel[m]*y; } w = letterspacing*offsets[k]; /* add the character's width to the distance along the line */ distance_along_segment += w; /* if we still have segments left and we've past the current segment, move to the next one */ if(inc == 1 && j < p->line[i].numpoints - 2) { while ( j < p->line[i].numpoints - 2 && distance_along_segment > segment_lengths[i][j] ) { distance_along_segment -= segment_lengths[i][j]; j += inc; /* move to next segment */ } segment_length = segment_lengths[i][j]; } else if( inc == -1 && j > 1 ) { while ( j > 1 && distance_along_segment > segment_lengths[i][j-1] ) { distance_along_segment -= segment_lengths[i][j-1]; j += inc; /* move to next segment */ } segment_length = segment_lengths[i][j-1]; } /* Recalculate interpolation parameter */ t = distance_along_segment / segment_length; k++; } /* pre-calc the character's centre y value. Used for rotation adjustment. */ cy = -size / 2.0; labelpath->path.point[0].x /= kernel_normal; labelpath->path.point[0].y /= kernel_normal; /* Average the points and calculate each angle */ for (k = 1; k <= labelpath->path.numpoints; k++) { double anglediff; if ( k < labelpath->path.numpoints ) { labelpath->path.point[k].x /= kernel_normal; labelpath->path.point[k].y /= kernel_normal; dx = labelpath->path.point[k].x - labelpath->path.point[k-1].x; dy = labelpath->path.point[k].y - labelpath->path.point[k-1].y; } else { /* Handle the last character */ dx = t * (p->line[i].point[j+inc].x - p->line[i].point[j].x) + p->line[i].point[j].x - labelpath->path.point[k-1].x; dy = t * (p->line[i].point[j+inc].y - p->line[i].point[j].y) + p->line[i].point[j].y - labelpath->path.point[k-1].y; } theta = -atan2(dy,dx); if ( maxoverlapangle > 0 && k > 1) { /* If the difference between the last char angle and the current one is greater than the MAXOVERLAPANGLE value (set at 80% of 180deg by default) , bail the label */ anglediff = fabs(theta - labelpath->angles[k-2]); anglediff = MS_MIN(anglediff, MS_2PI - anglediff); if(anglediff > maxoverlapangle ) { goto LABEL_FAILURE; } } /* msDebug("s: %c (x,y): (%0.2f,%0.2f) t: %0.2f\n", string[k-1], labelpath->path.point[k-1].x, labelpath->path.point[k-1].y, theta); */ labelpath->angles[k-1] = theta; /* Move the previous point so that when the character is rotated and placed it is centred on the line */ cos_t = cos(theta); sin_t = sin(theta); w = letterspacing*offsets[k-1]; cx = 0; /* Center the character vertically only */ dx = - (cx * cos_t + cy * sin_t); dy = - (cy * cos_t - cx * sin_t); labelpath->path.point[k-1].x += dx; labelpath->path.point[k-1].y += dy; /* Calculate the bounds */ bbox.minx = 0; bbox.maxx = w; bbox.maxy = 0; bbox.miny = -size; /* Add the label buffer to the bounds */ bbox.maxx += label->buffer; bbox.maxy += label->buffer; bbox.minx -= label->buffer; bbox.miny -= label->buffer; if ( k < labelpath->path.numpoints ) { /* Transform the bbox too. We take the UL and LL corners and rotate then translate them. */ bounds.point[k-1].x = (bbox.minx * cos_t + bbox.maxy * sin_t) + labelpath->path.point[k-1].x; bounds.point[k-1].y = (bbox.maxy * cos_t - bbox.minx * sin_t) + labelpath->path.point[k-1].y; /* Start at end and work towards the half way point */ bounds.point[bounds.numpoints - k - 1].x = (bbox.minx * cos_t + bbox.miny * sin_t) + labelpath->path.point[k-1].x; bounds.point[bounds.numpoints - k - 1].y = (bbox.miny * cos_t - bbox.minx * sin_t) + labelpath->path.point[k-1].y; } else { /* This is the last character in the string so we take the UR and LR corners of the bbox */ bounds.point[k-1].x = (bbox.maxx * cos_t + bbox.maxy * sin_t) + labelpath->path.point[k-1].x; bounds.point[k-1].y = (bbox.maxy * cos_t - bbox.maxx * sin_t) + labelpath->path.point[k-1].y; bounds.point[bounds.numpoints - k - 1].x = (bbox.maxx * cos_t + bbox.miny * sin_t) + labelpath->path.point[k-1].x; bounds.point[bounds.numpoints - k - 1].y = (bbox.miny * cos_t - bbox.maxx * sin_t) + labelpath->path.point[k-1].y; } } /* Close the bounds */ bounds.point[bounds.numpoints - 1].x = bounds.point[0].x; bounds.point[bounds.numpoints - 1].y = bounds.point[0].y; /* Convert the bounds to a shape and store them in the labelpath */ if ( msAddLineDirectly(&(labelpath->bounds), &bounds) == MS_FAILURE ) { goto LABEL_FAILURE; } msComputeBounds(&(labelpath->bounds)); goto LABEL_END; LABEL_FAILURE: if (bounds.point) free(bounds.point); bounds.point = NULL; bounds.numpoints = 0; if ( labelpath ) { msFreeLabelPathObj(labelpath); labelpath = NULL; } LABEL_END: if (labelpath) { if (*labelpaths_index == *labelpaths_size) { *labelpaths_size *= 2; (*labelpaths) = (labelPathObj **) msSmallRealloc(*labelpaths,sizeof(labelPathObj *) * (*labelpaths_size)); } (*labelpaths)[(*labelpaths_index)++] = labelpath; } text_start_length = left_label_position; n++; } while (n<2); right_label_position -= label_buffer; left_label_position += label_buffer; } goto END; /* normal exit */ ANGLEFOLLOW_FAILURE: /* Angle follow failure: add the line index in the arrays */ if (*regular_lines_index == *regular_lines_size) { *regular_lines_size *= 2; (*regular_lines) = (int*) msSmallRealloc(*regular_lines,sizeof(int) * (*regular_lines_size)); } (*regular_lines)[(*regular_lines_index)++] = line_index; FAILURE: /* Global failure */ END: if ( offsets ) free(offsets); return; } /* =========================================================================== Pretty printing of primitive objects ======================================================================== */ void msRectToFormattedString(rectObj *rect, char *format, char *buffer, int buffer_length) { snprintf(buffer, buffer_length, format, rect->minx, rect->miny, rect->maxx, rect->maxy); } void msPointToFormattedString(pointObj *point, const char *format, char *buffer, int buffer_length) { #ifdef USE_POINT_Z_M snprintf(buffer, buffer_length, format, point->x, point->y, point->z, point->m); #else snprintf(buffer, buffer_length, format, point->x, point->y); #endif } /* Returns true if a shape contains only degenerate parts */ int msIsDegenerateShape(shapeObj *shape) { int i; int non_degenerate_parts = 0; for(i=0; inumlines; i++) { /* e.g. part */ /* skip degenerate parts, really should only happen with pixel output */ if((shape->type == MS_SHAPE_LINE && shape->line[i].numpoints < 2) || (shape->type == MS_SHAPE_POLYGON && shape->line[i].numpoints < 3)) continue; non_degenerate_parts++; } return( non_degenerate_parts == 0 ); } mapserver-6.4.1/mapserver-version.h.in0000644002461700001440000000047712261257215017571 0ustar tbonfortusers#ifndef _MAPSERVER_VERSION_H #define _MAPSERVER_VERSION_H #define MS_VERSION_MAJOR @MapServer_VERSION_MAJOR@ #define MS_VERSION_MINOR @MapServer_VERSION_MINOR@ #define MS_VERSION_REV @MapServer_VERSION_REVISION@ #define MS_VERSION "@MapServer_VERSION_STRING@" #define MS_VERSION_NUM @MapServer_VERSION_NUM@ #endif mapserver-6.4.1/mapbits.c0000644002461700001440000000726212261257215015126 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of bit array functions. * Author: Steve Lime and the MapServer team. * * Notes: Derived from code placed in the public domain by Bob Stout, for more * information see http://c.snippets.org/snip_lister.php?fname=bitarray.c. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include /* * Hardcoded size of our bit array. * See function msGetNextBit for another hardcoded value. */ /* #define msGetBit(array, index) (*((array) + (index)/MS_ARRAY_BIT) & ( 1 << ((index) % MS_ARRAY_BIT))) */ size_t msGetBitArraySize(int numbits) { return((numbits + MS_ARRAY_BIT - 1) / MS_ARRAY_BIT); } ms_bitarray msAllocBitArray(int numbits) { ms_bitarray array = calloc((numbits + MS_ARRAY_BIT - 1) / MS_ARRAY_BIT, MS_ARRAY_BIT); return(array); } int msGetBit(ms_bitarray array, int index) { array += index / MS_ARRAY_BIT; return (*array & (1 << (index % MS_ARRAY_BIT))) != 0; /* 0 or 1 */ } /* ** msGetNextBit( status, start, size) ** ** Quickly find the next bit set. If start == 0 and 0 is set, will return 0. ** If hits end of bitmap without finding set bit, will return -1. ** */ int msGetNextBit(ms_bitarray array, int i, int size) { register ms_uint32 b; while(i < size) { b = *(array + (i/MS_ARRAY_BIT)); if( b && (b >> (i % MS_ARRAY_BIT)) ) { /* There is something in this byte */ /* And it is not to the right of us */ if( b & ( 1 << (i % MS_ARRAY_BIT)) ) { /* There is something at this bit! */ return i; } else { i++; } } else { /* Nothing in this byte, move to start of next byte */ i += MS_ARRAY_BIT - (i % MS_ARRAY_BIT); } } /* Got to the last byte with no hits! */ return -1; } void msSetBit(ms_bitarray array, int index, int value) { array += index / MS_ARRAY_BIT; if (value) *array |= 1 << (index % MS_ARRAY_BIT); /* set bit */ else *array &= ~(1 << (index % MS_ARRAY_BIT)); /* clear bit */ } void msSetAllBits(ms_bitarray array, int numbits, int value) { if (value) memset(array, 0xff, ((numbits + 7) / 8) ); /* set bit */ else memset(array, 0x0, ((numbits + 7) / 8) ); /* clear bit */ } void msFlipBit(ms_bitarray array, int index) { array += index / MS_ARRAY_BIT; *array ^= 1 << (index % MS_ARRAY_BIT); /* flip bit */ } mapserver-6.4.1/maptree.h0000644002461700001440000000634712261257215015134 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: .qix spatial index declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPTREE_H #define MAPTREE_H #ifdef __cplusplus extern "C" { #endif /* this can be 2 or 4 for binary or quad tree */ #define MAX_SUBNODES 4 typedef struct shape_tree_node { /* area covered by this node */ rectObj rect; /* list of shapes stored at this node. */ ms_int32 numshapes; ms_int32 *ids; int numsubnodes; struct shape_tree_node *subnode[MAX_SUBNODES]; } treeNodeObj; typedef struct { ms_int32 numshapes; ms_int32 maxdepth; treeNodeObj *root; } treeObj; typedef struct { FILE *fp; char signature[3]; char LSB_order; char needswap; char version; char flags[3]; ms_int32 nShapes; ms_int32 nDepth; } SHPTreeInfo; typedef SHPTreeInfo * SHPTreeHandle; #define MS_LSB_ORDER -1 #define MS_MSB_ORDER -2 #define MS_NATIVE_ORDER 0 #define MS_NEW_LSB_ORDER 1 #define MS_NEW_MSB_ORDER 2 MS_DLL_EXPORT SHPTreeHandle msSHPDiskTreeOpen(const char * pszTree, int debug); MS_DLL_EXPORT void msSHPDiskTreeClose(SHPTreeHandle disktree); MS_DLL_EXPORT treeNodeObj *readTreeNode( SHPTreeHandle disktree ); MS_DLL_EXPORT treeObj *msCreateTree(shapefileObj *shapefile, int maxdepth); MS_DLL_EXPORT void msTreeTrim(treeObj *tree); MS_DLL_EXPORT void msDestroyTree(treeObj *tree); MS_DLL_EXPORT ms_bitarray msSearchTree(treeObj *tree, rectObj aoi); MS_DLL_EXPORT ms_bitarray msSearchDiskTree(char *filename, rectObj aoi, int debug); MS_DLL_EXPORT treeObj *msReadTree(char *filename, int debug); MS_DLL_EXPORT int msWriteTree(treeObj *tree, char *filename, int LSB_order); MS_DLL_EXPORT void msFilterTreeSearch(shapefileObj *shp, ms_bitarray status, rectObj search_rect); #ifdef __cplusplus } #endif #endif /* MAPTREE_H */ mapserver-6.4.1/mapogcsld.h0000644002461700001440000001077112261257215015444 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC SLD implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #include "mapserver.h" MS_DLL_EXPORT char *msSLDGenerateSLD(mapObj *map, int iLayer, const char *pszVersion); MS_DLL_EXPORT int msSLDApplySLDURL(mapObj *map, char *szURL, int iLayer, char *pszStyleLayerName, char **ppszLayerNames); MS_DLL_EXPORT int msSLDApplySLD(mapObj *map, char *psSLDXML, int iLayer, char *pszStyleLayerName, char **ppszLayerNames); #ifdef USE_OGR /* There is a dependency to OGR for the MiniXML parser */ #include "cpl_minixml.h" /* -------------------------------------------------------------------- */ /* prototypes. */ /* -------------------------------------------------------------------- */ layerObj *msSLDParseSLD(mapObj *map, char *psSLDXML, int *pnLayers); int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *layer); int msSLDParseRule(CPLXMLNode *psRoot, layerObj *psLayer); int msSLDParseStroke(CPLXMLNode *psStroke, styleObj *psStyle, mapObj *map, int iColorParam); int msSLDParsePolygonFill(CPLXMLNode *psFill, styleObj *psStyle, mapObj *map); int msSLDParseLineSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass); int msSLDParsePolygonSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass); int msSLDParsePointSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass); int msSLDParseTextSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bOtherSymboliser); int msSLDParseRasterSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer); int msSLDParseGraphicFillOrStroke(CPLXMLNode *psGraphicFill, char *pszDashValue, styleObj *psStyle, mapObj *map, int bPointLayer); int msSLDParseExternalGraphic(CPLXMLNode *psExternalGraphic, styleObj *psStyle, mapObj *map); int msSLDGetLineSymbol(mapObj *map); int msSLDGetDashLineSymbol(mapObj *map, char *pszDashArray); int msSLDGetMarkSymbol(mapObj *map, char *pszSymbolName, int bFilled); int msSLDGetGraphicSymbol(mapObj *map, char *pszFileName, char *extGraphicName, int nGap); int msSLDSetColorObject(char *psHexColor, colorObj *psColor); int msSLDParseTextParams(CPLXMLNode *psRoot, layerObj *psLayer, classObj *psClass); int ParseTextPointPlacement(CPLXMLNode *psRoot, classObj *psClass); int ParseTextLinePlacement(CPLXMLNode *psRoot, classObj *psClass); char *msSLDGenerateSLDLayer(layerObj *psLayer, int nVersion); char *msSLDGetFilter(classObj *psClass, const char *pszWfsFilter); char *msSLDGenerateLineSLD(styleObj *psStyle, layerObj *psLayer, int nVersion); char *msSLDGeneratePolygonSLD(styleObj *psStyle, layerObj *psLayer, int nVersion); char *msSLDGeneratePointSLD(styleObj *psStyle, layerObj *psLayer, int nVersion); char *msSLDGenerateTextSLD(classObj *psClass, layerObj *psLayer, int nVersion); FilterEncodingNode *BuildExpressionTree(char *pszExpression, FilterEncodingNode *psNode); #endif mapserver-6.4.1/hittest.h0000644002461700001440000000512112261257215015150 0ustar tbonfortusers/***************************************************************************** * * Project: MapServer * Purpose: Content Dependant Legend rendering support * Author: Thomas Bonfort (tbonfort@terriscope.fr) * ****************************************************************************** * Copyright (c) 1996-2013 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 HITTEST_H #define HITTEST_H typedef struct { int status; } style_hittest; typedef struct { style_hittest *stylehits; int status; } label_hittest; typedef struct { style_hittest *stylehits; label_hittest *labelhits; int status; } class_hittest; typedef struct { class_hittest *classhits; int status; } layer_hittest; typedef struct map_hittest{ layer_hittest *layerhits; } map_hittest; int msHitTestMap(mapObj *map, map_hittest *hittest); int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest); void initStyleHitTests(styleObj *s, style_hittest *sh, int default_status); void initLabelHitTests(labelObj *l, label_hittest *lh, int default_status); void initClassHitTests(classObj *c, class_hittest *ch, int default_status); void initLayerHitTests(layerObj *l, layer_hittest *lh); void initMapHitTests(mapObj *map, map_hittest *mh); void freeLabelHitTests(labelObj *l, label_hittest *lh); void freeClassHitTests(classObj *c, class_hittest *ch); void freeLayerHitTests(layerObj *l, layer_hittest *lh); void freeMapHitTests(mapObj *map, map_hittest *mh); #endif mapserver-6.4.1/mapgeomutil.cpp0000644002461700001440000000764412261257215016356 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Rendering utility functions * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2011 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. *****************************************************************************/ #include "mapserver.h" #include "renderers/agg/include/agg_arc.h" #include "renderers/agg/include/agg_basics.h" shapeObj *msRasterizeArc(double x0, double y0, double radius, double startAngle, double endAngle, int isSlice) { static int allocated_size=100; shapeObj *shape = (shapeObj*)calloc(1,sizeof(shapeObj)); MS_CHECK_ALLOC(shape, sizeof(shapeObj), NULL); mapserver::arc arc ( x0, y0,radius,radius, startAngle*MS_DEG_TO_RAD, endAngle*MS_DEG_TO_RAD,true ); arc.approximation_scale ( 1 ); arc.rewind(1); msInitShape(shape); lineObj *line = (lineObj*)calloc(1,sizeof(lineObj)); if (!line) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msRasterizeArc()" , __FILE__, __LINE__, (unsigned int)sizeof(lineObj)); free(shape); return NULL; } shape->line = line; shape->numlines = 1; line->point = (pointObj*)calloc(allocated_size,sizeof(pointObj)); if (!line->point) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msRasterizeArc()" , __FILE__, __LINE__, (unsigned int)(allocated_size*sizeof(pointObj))); free(line); free(shape); return NULL; } line->numpoints = 0; double x,y; //first segment from center to first point of arc if(isSlice) { line->point[0].x = x0; line->point[0].y = y0; line->numpoints = 1; } while(arc.vertex(&x,&y) != mapserver::path_cmd_stop) { if(line->numpoints == allocated_size) { allocated_size *= 2; line->point = (pointObj*)realloc(line->point, allocated_size * sizeof(pointObj)); if (!line->point) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msRasterizeArc()" , __FILE__, __LINE__, (unsigned int)(allocated_size * sizeof(pointObj))); free(line); free(shape); return NULL; } } line->point[line->numpoints].x = x; line->point[line->numpoints].y = y; line->numpoints++; } //make sure the shape is closed if(line->point[line->numpoints-1].x != line->point[0].x || line->point[line->numpoints-1].y != line->point[0].y) { if(line->numpoints == allocated_size) { allocated_size *= 2; line->point = (pointObj*)msSmallRealloc(line->point, allocated_size * sizeof(pointObj)); } line->point[line->numpoints].x = line->point[0].x; line->point[line->numpoints].y = line->point[0].y; line->numpoints++; } return shape; } mapserver-6.4.1/mapquantization.c0000644002461700001440000005604412261257215016715 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: RGB(A) to Palette Support Functions * Author: Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************** */ /* * derivations from pngquant and ppmquant * ** pngquant.c - quantize the colors in an alphamap down to a specified number ** ** Copyright (C) 1989, 1991 by Jef Poskanzer. ** Copyright (C) 1997, 2000, 2002 by Greg Roelofs; based on an idea by ** Stefan Schneider. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include "mapserver.h" #include #define PAM_GETR(p) ((p).r) #define PAM_GETG(p) ((p).g) #define PAM_GETB(p) ((p).b) #define PAM_GETA(p) ((p).a) #define PAM_ASSIGN(p,red,grn,blu,alf) \ do { (p).r = (red); (p).g = (grn); (p).b = (blu); (p).a = (alf); } while (0) #define PAM_EQUAL(p,q) \ ((p).r == (q).r && (p).g == (q).g && (p).b == (q).b && (p).a == (q).a) #define PAM_DEPTH(newp,p,oldmaxval,newmaxval) \ PAM_ASSIGN( (newp), \ ( (int) PAM_GETR(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ ( (int) PAM_GETG(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ ( (int) PAM_GETB(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ ( (int) PAM_GETA(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval) ) /* from pamcmap.h */ typedef struct acolorhist_item *acolorhist_vector; struct acolorhist_item { rgbaPixel acolor; int value; }; typedef struct acolorhist_list_item *acolorhist_list; struct acolorhist_list_item { struct acolorhist_item ch; acolorhist_list next; }; typedef acolorhist_list *acolorhash_table; #define MAXCOLORS 32767 #define LARGE_NORM #define REP_AVERAGE_PIXELS typedef struct box *box_vector; struct box { int ind; int colors; int sum; }; static acolorhist_vector mediancut (acolorhist_vector achv, int colors, int sum, unsigned char maxval, int newcolors); static int redcompare (const void *ch1, const void *ch2); static int greencompare (const void *ch1, const void *ch2); static int bluecompare (const void *ch1, const void *ch2); static int alphacompare (const void *ch1, const void *ch2); static int sumcompare (const void *b1, const void *b2); static acolorhist_vector pam_acolorhashtoacolorhist (acolorhash_table acht, int maxacolors); static acolorhist_vector pam_computeacolorhist (rgbaPixel **apixels, int cols, int rows, int maxacolors, int* acolorsP); static acolorhash_table pam_computeacolorhash (rgbaPixel** apixels, int cols, int rows, int maxacolors, int* acolorsP); static acolorhash_table pam_allocacolorhash (void); static int pam_addtoacolorhash (acolorhash_table acht, rgbaPixel *acolorP, int value); static int pam_lookupacolor (acolorhash_table acht, rgbaPixel* acolorP); static void pam_freeacolorhist (acolorhist_vector achv); static void pam_freeacolorhash (acolorhash_table acht); /** * Compute a palette for the given RGBA rasterBuffer using a median cut quantization. * - rb: the rasterBuffer to quantize * - reqcolors: the desired number of colors the palette should contain. will be set * with the actual number of entries in the computed palette * - forced_palette: entries that should appear in the computed palette * - num_forced_palette_entries: number of entries contained in "force_palette". if 0, * "force_palette" can be NULL * - palette_scaling_maxval: the quantization process may have to reduce the image depth * by iteratively dividing the pixels by 2. In case palette_scaling_maxval is set to * something different than 255, the returned palette colors have to be scaled back up to * 255, and rb's pixels will have been scaled down to maxsize (see bug #3848) */ int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette, rgbaPixel *forced_palette, int num_forced_palette_entries, unsigned int *palette_scaling_maxval) { rgbaPixel **apixels=NULL; /* pointer to the start rows of truecolor pixels */ register rgbaPixel *pP; register int col; unsigned char newmaxval; acolorhist_vector achv, acolormap=NULL; int row; int colors; int newcolors = 0; int x; /* int channels; */ assert(rb->type == MS_BUFFER_BYTE_RGBA); *palette_scaling_maxval = 255; apixels=(rgbaPixel**)msSmallMalloc(rb->height*sizeof(rgbaPixel**)); for(row=0; rowheight; row++) { apixels[row]=(rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step])); } /* ** Step 2: attempt to make a histogram of the colors, unclustered. ** If at first we don't succeed, lower maxval to increase color ** coherence and try again. This will eventually terminate, with ** maxval at worst 15, since 32^3 is approximately MAXCOLORS. [GRR POSSIBLE BUG: what about 32^4 ?] */ for ( ; ; ) { achv = pam_computeacolorhist( apixels, rb->width, rb->height, MAXCOLORS, &colors ); if ( achv != (acolorhist_vector) 0 ) break; newmaxval = *palette_scaling_maxval / 2; for ( row = 0; row < rb->height; ++row ) for ( col = 0, pP = apixels[row]; col < rb->width; ++col, ++pP ) PAM_DEPTH( *pP, *pP, *palette_scaling_maxval, newmaxval ); *palette_scaling_maxval = newmaxval; } newcolors = MS_MIN(colors, *reqcolors); acolormap = mediancut(achv, colors, rb->width*rb->height, *palette_scaling_maxval, newcolors); pam_freeacolorhist(achv); *reqcolors = newcolors; for (x = 0; x < newcolors; ++x) { palette[x].r = acolormap[x].acolor.r; palette[x].g = acolormap[x].acolor.g; palette[x].b = acolormap[x].acolor.b; palette[x].a = acolormap[x].acolor.a; } free(acolormap); free(apixels); return MS_SUCCESS; } int msClassifyRasterBuffer(rasterBufferObj *rb, rasterBufferObj *qrb) { register int ind; unsigned char *outrow,*pQ; register rgbaPixel *pP; acolorhash_table acht; int usehash, row, col; /* ** Step 4: map the colors in the image to their closest match in the ** new colormap, and write 'em out. */ acht = pam_allocacolorhash( ); usehash = 1; for ( row = 0; row < qrb->height; ++row ) { outrow = &(qrb->data.palette.pixels[row*qrb->width]); col = 0; pP = (rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step]));; pQ = outrow; do { /* Check hash table to see if we have already matched this color. */ ind = pam_lookupacolor( acht, pP ); if ( ind == -1 ) { /* No; search acolormap for closest match. */ register int i, r1, g1, b1, a1, r2, g2, b2, a2; register long dist, newdist; r1 = PAM_GETR( *pP ); g1 = PAM_GETG( *pP ); b1 = PAM_GETB( *pP ); a1 = PAM_GETA( *pP ); dist = 2000000000; for ( i = 0; i < qrb->data.palette.num_entries; ++i ) { r2 = PAM_GETR( qrb->data.palette.palette[i] ); g2 = PAM_GETG( qrb->data.palette.palette[i] ); b2 = PAM_GETB( qrb->data.palette.palette[i] ); a2 = PAM_GETA( qrb->data.palette.palette[i] ); /* GRR POSSIBLE BUG */ newdist = ( r1 - r2 ) * ( r1 - r2 ) + /* may overflow? */ ( g1 - g2 ) * ( g1 - g2 ) + ( b1 - b2 ) * ( b1 - b2 ) + ( a1 - a2 ) * ( a1 - a2 ); if ( newdist < dist ) { ind = i; dist = newdist; } } if ( usehash ) { if ( pam_addtoacolorhash( acht, pP, ind ) < 0 ) { usehash = 0; } } } /* *pP = acolormap[ind].acolor; */ *pQ = (unsigned char)ind; ++col; ++pP; ++pQ; } while ( col != rb->width ); } pam_freeacolorhash(acht); return MS_SUCCESS; } /* ** Here is the fun part, the median-cut colormap generator. This is based ** on Paul Heckbert's paper, "Color Image Quantization for Frame Buffer ** Display," SIGGRAPH 1982 Proceedings, page 297. */ static acolorhist_vector mediancut( acolorhist_vector achv, int colors, int sum, unsigned char maxval, int newcolors ) { acolorhist_vector acolormap; box_vector bv; register int bi, i; int boxes; bv = (box_vector) malloc( sizeof(struct box) * newcolors ); acolormap = (acolorhist_vector) malloc( sizeof(struct acolorhist_item) * newcolors); if ( bv == (box_vector) 0 || acolormap == (acolorhist_vector) 0 ) { fprintf( stderr, " out of memory allocating box vector\n" ); fflush(stderr); exit(6); } for ( i = 0; i < newcolors; ++i ) PAM_ASSIGN( acolormap[i].acolor, 0, 0, 0, 0 ); /* ** Set up the initial box. */ bv[0].ind = 0; bv[0].colors = colors; bv[0].sum = sum; boxes = 1; /* ** Main loop: split boxes until we have enough. */ while ( boxes < newcolors ) { register int indx, clrs; int sm; register int minr, maxr, ming, mina, maxg, minb, maxb, maxa, v; int halfsum, lowersum; /* ** Find the first splittable box. */ for ( bi = 0; bi < boxes; ++bi ) if ( bv[bi].colors >= 2 ) break; if ( bi == boxes ) break; /* ran out of colors! */ indx = bv[bi].ind; clrs = bv[bi].colors; sm = bv[bi].sum; /* ** Go through the box finding the minimum and maximum of each ** component - the boundaries of the box. */ minr = maxr = PAM_GETR( achv[indx].acolor ); ming = maxg = PAM_GETG( achv[indx].acolor ); minb = maxb = PAM_GETB( achv[indx].acolor ); mina = maxa = PAM_GETA( achv[indx].acolor ); for ( i = 1; i < clrs; ++i ) { v = PAM_GETR( achv[indx + i].acolor ); if ( v < minr ) minr = v; if ( v > maxr ) maxr = v; v = PAM_GETG( achv[indx + i].acolor ); if ( v < ming ) ming = v; if ( v > maxg ) maxg = v; v = PAM_GETB( achv[indx + i].acolor ); if ( v < minb ) minb = v; if ( v > maxb ) maxb = v; v = PAM_GETA( achv[indx + i].acolor ); if ( v < mina ) mina = v; if ( v > maxa ) maxa = v; } /* ** Find the largest dimension, and sort by that component. I have ** included two methods for determining the "largest" dimension; ** first by simply comparing the range in RGB space, and second ** by transforming into luminosities before the comparison. You ** can switch which method is used by switching the commenting on ** the LARGE_ defines at the beginning of this source file. */ #ifdef LARGE_NORM if ( maxa - mina >= maxr - minr && maxa - mina >= maxg - ming && maxa - mina >= maxb - minb ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), alphacompare ); else if ( maxr - minr >= maxg - ming && maxr - minr >= maxb - minb ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), redcompare ); else if ( maxg - ming >= maxb - minb ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), greencompare ); else qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), bluecompare ); #endif /*LARGE_NORM*/ #ifdef LARGE_LUM { apixel p; float rl, gl, bl, al; PAM_ASSIGN(p, maxr - minr, 0, 0, 0); rl = PPM_LUMIN(p); PAM_ASSIGN(p, 0, maxg - ming, 0, 0); gl = PPM_LUMIN(p); PAM_ASSIGN(p, 0, 0, maxb - minb, 0); bl = PPM_LUMIN(p); /* GRR: treat alpha as grayscale and assign (maxa - mina) to each of R, G, B? assign (maxa - mina)/3 to each? use alpha-fractional luminosity? (normalized_alpha * lum(r,g,b)) al = dunno ... [probably should read Heckbert's paper to decide] */ if ( al >= rl && al >= gl && al >= bl ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), alphacompare ); else if ( rl >= gl && rl >= bl ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), redcompare ); else if ( gl >= bl ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), greencompare ); else qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), bluecompare ); } #endif /*LARGE_LUM*/ /* ** Now find the median based on the counts, so that about half the ** pixels (not colors, pixels) are in each subdivision. */ lowersum = achv[indx].value; halfsum = sm / 2; for ( i = 1; i < clrs - 1; ++i ) { if ( lowersum >= halfsum ) break; lowersum += achv[indx + i].value; } /* ** Split the box, and sort to bring the biggest boxes to the top. */ bv[bi].colors = i; bv[bi].sum = lowersum; bv[boxes].ind = indx + i; bv[boxes].colors = clrs - i; bv[boxes].sum = sm - lowersum; ++boxes; qsort( (char*) bv, boxes, sizeof(struct box), sumcompare ); } /* ** Ok, we've got enough boxes. Now choose a representative color for ** each box. There are a number of possible ways to make this choice. ** One would be to choose the center of the box; this ignores any structure ** within the boxes. Another method would be to average all the colors in ** the box - this is the method specified in Heckbert's paper. A third ** method is to average all the pixels in the box. You can switch which ** method is used by switching the commenting on the REP_ defines at ** the beginning of this source file. */ for ( bi = 0; bi < boxes; ++bi ) { #ifdef REP_CENTER_BOX register int indx = bv[bi].ind; register int clrs = bv[bi].colors; register int minr, maxr, ming, maxg, minb, maxb, mina, maxa, v; minr = maxr = PAM_GETR( achv[indx].acolor ); ming = maxg = PAM_GETG( achv[indx].acolor ); minb = maxb = PAM_GETB( achv[indx].acolor ); mina = maxa = PAM_GETA( achv[indx].acolor ); for ( i = 1; i < clrs; ++i ) { v = PAM_GETR( achv[indx + i].acolor ); minr = min( minr, v ); maxr = max( maxr, v ); v = PAM_GETG( achv[indx + i].acolor ); ming = min( ming, v ); maxg = max( maxg, v ); v = PAM_GETB( achv[indx + i].acolor ); minb = min( minb, v ); maxb = max( maxb, v ); v = PAM_GETA( achv[indx + i].acolor ); mina = min( mina, v ); maxa = max( maxa, v ); } PAM_ASSIGN( acolormap[bi].acolor, ( minr + maxr ) / 2, ( ming + maxg ) / 2, ( minb + maxb ) / 2, ( mina + maxa ) / 2 ); #endif /*REP_CENTER_BOX*/ #ifdef REP_AVERAGE_COLORS register int indx = bv[bi].ind; register int clrs = bv[bi].colors; register long r = 0, g = 0, b = 0, a = 0; for ( i = 0; i < clrs; ++i ) { r += PAM_GETR( achv[indx + i].acolor ); g += PAM_GETG( achv[indx + i].acolor ); b += PAM_GETB( achv[indx + i].acolor ); a += PAM_GETA( achv[indx + i].acolor ); } r = r / clrs; g = g / clrs; b = b / clrs; a = a / clrs; PAM_ASSIGN( acolormap[bi].acolor, r, g, b, a ); #endif /*REP_AVERAGE_COLORS*/ #ifdef REP_AVERAGE_PIXELS register int indx = bv[bi].ind; register int clrs = bv[bi].colors; register long r = 0, g = 0, b = 0, a = 0, sum = 0; for ( i = 0; i < clrs; ++i ) { r += PAM_GETR( achv[indx + i].acolor ) * achv[indx + i].value; g += PAM_GETG( achv[indx + i].acolor ) * achv[indx + i].value; b += PAM_GETB( achv[indx + i].acolor ) * achv[indx + i].value; a += PAM_GETA( achv[indx + i].acolor ) * achv[indx + i].value; sum += achv[indx + i].value; } r = r / sum; if ( r > maxval ) r = maxval; /* avoid math errors */ g = g / sum; if ( g > maxval ) g = maxval; b = b / sum; if ( b > maxval ) b = maxval; a = a / sum; if ( a > maxval ) a = maxval; /* GRR 20001228: added casts to quiet warnings; 255 DEPENDENCY */ PAM_ASSIGN( acolormap[bi].acolor, (unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a ); #endif /*REP_AVERAGE_PIXELS*/ } /* ** All done. */ free(bv); return acolormap; } static int redcompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETR( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETR( ((acolorhist_vector)ch2)->acolor ); } static int greencompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETG( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETG( ((acolorhist_vector)ch2)->acolor ); } static int bluecompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETB( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETB( ((acolorhist_vector)ch2)->acolor ); } static int alphacompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETA( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETA( ((acolorhist_vector)ch2)->acolor ); } static int sumcompare( const void *b1, const void *b2 ) { return ((box_vector)b2)->sum - ((box_vector)b1)->sum; } /*===========================================================================*/ /* libpam3.c - pam (portable alpha map) utility library part 3 ** ** Colormap routines. ** ** Copyright (C) 1989, 1991 by Jef Poskanzer. ** Copyright (C) 1997 by Greg Roelofs. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ /* #include "pam.h" #include "pamcmap.h" */ #define HASH_SIZE 20023 #define pam_hashapixel(p) ( ( ( (long) PAM_GETR(p) * 33023 + \ (long) PAM_GETG(p) * 30013 + \ (long) PAM_GETB(p) * 27011 + \ (long) PAM_GETA(p) * 24007 ) \ & 0x7fffffff ) % HASH_SIZE ) static acolorhist_vector pam_computeacolorhist( apixels, cols, rows, maxacolors, acolorsP ) rgbaPixel** apixels; int cols, rows, maxacolors; int* acolorsP; { acolorhash_table acht; acolorhist_vector achv; acht = pam_computeacolorhash( apixels, cols, rows, maxacolors, acolorsP ); if ( acht == (acolorhash_table) 0 ) return (acolorhist_vector) 0; achv = pam_acolorhashtoacolorhist( acht, maxacolors ); pam_freeacolorhash( acht ); return achv; } static acolorhash_table pam_computeacolorhash( apixels, cols, rows, maxacolors, acolorsP ) rgbaPixel** apixels; int cols, rows, maxacolors; int* acolorsP; { acolorhash_table acht; register rgbaPixel* pP; acolorhist_list achl; int col, row, hash; acht = pam_allocacolorhash( ); *acolorsP = 0; /* Go through the entire image, building a hash table of colors. */ for ( row = 0; row < rows; ++row ) for ( col = 0, pP = apixels[row]; col < cols; ++col, ++pP ) { hash = pam_hashapixel( *pP ); for ( achl = acht[hash]; achl != (acolorhist_list) 0; achl = achl->next ) if ( PAM_EQUAL( achl->ch.acolor, *pP ) ) break; if ( achl != (acolorhist_list) 0 ) ++(achl->ch.value); else { if ( ++(*acolorsP) > maxacolors ) { pam_freeacolorhash( acht ); return (acolorhash_table) 0; } achl = (acolorhist_list) malloc( sizeof(struct acolorhist_list_item) ); if ( achl == 0 ) { fprintf( stderr, " out of memory computing hash table\n" ); exit(7); } achl->ch.acolor = *pP; achl->ch.value = 1; achl->next = acht[hash]; acht[hash] = achl; } } return acht; } static acolorhash_table pam_allocacolorhash( ) { acolorhash_table acht; int i; acht = (acolorhash_table) malloc( HASH_SIZE * sizeof(acolorhist_list) ); if ( acht == 0 ) { fprintf( stderr, " out of memory allocating hash table\n" ); exit(8); } for ( i = 0; i < HASH_SIZE; ++i ) acht[i] = (acolorhist_list) 0; return acht; } static int pam_addtoacolorhash( acht, acolorP, value ) acolorhash_table acht; rgbaPixel* acolorP; int value; { register int hash; register acolorhist_list achl; achl = (acolorhist_list) msSmallMalloc( sizeof(struct acolorhist_list_item) ); hash = pam_hashapixel( *acolorP ); achl->ch.acolor = *acolorP; achl->ch.value = value; achl->next = acht[hash]; acht[hash] = achl; return 0; } static acolorhist_vector pam_acolorhashtoacolorhist( acht, maxacolors ) acolorhash_table acht; int maxacolors; { acolorhist_vector achv; acolorhist_list achl; int i, j; /* Now collate the hash table into a simple acolorhist array. */ achv = (acolorhist_vector) malloc( maxacolors * sizeof(struct acolorhist_item) ); /* (Leave room for expansion by caller.) */ if ( achv == (acolorhist_vector) 0 ) { fprintf( stderr, " out of memory generating histogram\n" ); exit(9); } /* Loop through the hash table. */ j = 0; for ( i = 0; i < HASH_SIZE; ++i ) for ( achl = acht[i]; achl != (acolorhist_list) 0; achl = achl->next ) { /* Add the new entry. */ achv[j] = achl->ch; ++j; } /* All done. */ return achv; } static int pam_lookupacolor( acht, acolorP ) acolorhash_table acht; rgbaPixel* acolorP; { int hash; acolorhist_list achl; hash = pam_hashapixel( *acolorP ); for ( achl = acht[hash]; achl != (acolorhist_list) 0; achl = achl->next ) if ( PAM_EQUAL( achl->ch.acolor, *acolorP ) ) return achl->ch.value; return -1; } static void pam_freeacolorhist( achv ) acolorhist_vector achv; { free( (char*) achv ); } static void pam_freeacolorhash( acht ) acolorhash_table acht; { int i; acolorhist_list achl, achlnext; for ( i = 0; i < HASH_SIZE; ++i ) for ( achl = acht[i]; achl != (acolorhist_list) 0; achl = achlnext ) { achlnext = achl->next; free( (char*) achl ); } free( (char*) acht ); } mapserver-6.4.1/shptree.c0000644002461700001440000001321012261257215015127 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Commandline utility to generate .qix shapefile spatial indexes. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maptree.h" #include char* AddFileSuffix ( const char * Filename, const char * Suffix ) { char *pszFullname, *pszBasename; int i; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(Filename)+5); strcpy( pszBasename, Filename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, Suffix); free(pszBasename); return (pszFullname); } int main(int argc, char *argv[]) { shapefileObj shapefile; treeObj *tree; int byte_order = MS_NEW_LSB_ORDER, i; int depth=0; if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine to decide default */ /* index format */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) byte_order = MS_NEW_LSB_ORDER; else byte_order = MS_NEW_MSB_ORDER; if(argc<2) { fprintf(stdout,"Syntax:\n"); fprintf(stdout," shptree [] []\n" ); fprintf(stdout,"Where:\n"); fprintf(stdout," is the name of the .shp file to index.\n"); fprintf(stdout," (optional) is the maximum depth of the index\n"); fprintf(stdout," to create, default is 0 meaning that shptree\n"); fprintf(stdout," will calculate a reasonable default depth.\n"); fprintf(stdout," (optional) is one of:\n"); fprintf(stdout," NL: LSB byte order, using new index format\n"); fprintf(stdout," NM: MSB byte order, using new index format\n"); fprintf(stdout," The following old format options are deprecated:\n"); fprintf(stdout," N: Native byte order\n"); fprintf(stdout," L: LSB (intel) byte order\n"); fprintf(stdout," M: MSB byte order\n"); fprintf(stdout," The default index_format on this system is: %s\n\n", (byte_order == MS_NEW_LSB_ORDER) ? "NL" : "NM" ); exit(0); } if(argc >= 3) depth = atoi(argv[2]); if(argc >= 4) { if( !strcasecmp(argv[3],"N" )) byte_order = MS_NATIVE_ORDER; if( !strcasecmp(argv[3],"L" )) byte_order = MS_LSB_ORDER; if( !strcasecmp(argv[3],"M" )) byte_order = MS_MSB_ORDER; if( !strcasecmp(argv[3],"NL" )) byte_order = MS_NEW_LSB_ORDER; if( !strcasecmp(argv[3],"NM" )) byte_order = MS_NEW_MSB_ORDER; } if(msShapefileOpen(&shapefile, "rb", argv[1], MS_TRUE) == -1) { fprintf(stdout, "Error opening shapefile %s.\n", argv[1]); exit(0); } printf( "creating index of %s %s format\n",(byte_order < 1 ? "old (deprecated)" :"new"), ((byte_order == MS_NATIVE_ORDER) ? "native" : ((byte_order == MS_LSB_ORDER) || (byte_order == MS_NEW_LSB_ORDER)? " LSB":"MSB"))); tree = msCreateTree(&shapefile, depth); if(!tree) { #if MAX_SUBNODE == 2 fprintf(stdout, "Error generating binary tree.\n"); #else fprintf(stdout, "Error generating quadtree.\n"); #endif exit(0); } msWriteTree(tree, AddFileSuffix(argv[1], MS_INDEX_EXTENSION), byte_order); msDestroyTree(tree); /* ** Clean things up */ msShapefileClose(&shapefile); return(0); } mapserver-6.4.1/symbols/0000755002461700001440000000000012261257215015004 5ustar tbonfortusersmapserver-6.4.1/symbols/examples.sym0000644002461700001440000000076112261257215017360 0ustar tbonfortusersSYMBOLSET SYMBOL # standard circular brush NAME 'circle' TYPE ELLIPSE POINTS 1 1 END FILLED TRUE END SYMBOL # long dash pattern NAME 'dash-long' TYPE ELLIPSE POINTS 1 1 END FILLED TRUE STYLE 16 16 END END SYMBOL # short dash pattern NAME 'dash-short' TYPE ELLIPSE POINTS 1 1 END FILLED TRUE STYLE 8 8 END END SYMBOL # tracks NAME 'tracks' TYPE ELLIPSE POINTS 1 1 END FILLED TRUE STYLE 1 16 END END END mapserver-6.4.1/symbols/examples.map0000644002461700001440000000353612261257215017330 0ustar tbonfortusersMAP EXTENT 0 0 200 600 STATUS ON SIZE 200 600 SYMBOLSET 'examples.sym' LAYER NAME 'example1' TRANSFORM FALSE TYPE LINE STATUS DEFAULT FEATURE POINTS 10 35 60 5 140 35 190 5 END END CLASS SYMBOL 'circle' SIZE 5 COLOR 255 0 0 END END LAYER NAME 'example2' TRANSFORM FALSE TYPE LINE STATUS DEFAULT FEATURE POINTS 10 70 60 40 140 70 190 40 END END CLASS SYMBOL 'circle' SIZE 5 COLOR 255 0 0 OVERLAYSYMBOL 'circle' OVERLAYSIZE 3 OVERLAYCOLOR 255 255 0 END END LAYER NAME 'example3' TRANSFORM FALSE TYPE LINE STATUS DEFAULT FEATURE POINTS 10 110 60 75 140 110 190 75 END END CLASS SYMBOL 'circle' SIZE 5 COLOR 255 0 0 OVERLAYSYMBOL 'dash-long' OVERLAYSIZE 3 OVERLAYCOLOR 255 255 0 END END LAYER NAME 'example4' TRANSFORM FALSE TYPE LINE STATUS DEFAULT FEATURE POINTS 10 150 60 120 140 150 190 120 END END CLASS SYMBOL 'dash-short' SIZE 3 COLOR 255 0 0 END END LAYER NAME 'example5' TRANSFORM FALSE TYPE LINE STATUS DEFAULT FEATURE POINTS 10 185 60 155 140 185 190 155 END END CLASS SYMBOL 'dash-short' SIZE 3 COLOR 255 0 0 OVERLAYSYMBOL 0 OVERLAYCOLOR 255 255 255 END END # crappy railroad tracks... LAYER NAME 'example6' TRANSFORM FALSE TYPE LINE STATUS DEFAULT FEATURE POINTS 10 220 60 190 140 220 190 190 END END CLASS SYMBOL 'tracks' SIZE 3 COLOR 0 0 0 OVERLAYSYMBOL 0 OVERLAYCOLOR 0 0 0 END END END mapserver-6.4.1/mapimagemap.c0000644002461700001440000006276412261257215015755 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements imagemap outputformat support. * Author: Attila Csipa * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "dxfcolor.h" #include #include #ifdef _WIN32 #include #include #endif #define MYDEBUG 0 #define DEBUG_IF if (MYDEBUG > 2) /* * Client-side imagemap support was originally written by * Attila Csipa (http://prometheus.org.yu/me.php). C. Scott Ananian * (http://cscott.net) cleaned up the code somewhat and made it more flexible: * you can now customize the generated HREFs and create mouseover and * mouseout attributes. * * Use * IMAGETYPE imagemap * to select this driver. * * The following FORMATOPTIONs are available. If any are set to the empty * string the associated attribute will be suppressed. * POLYHREF the href string to use for the elements. * use a %s to interpolate the area title. * default: "javascript:Clicked('%s');" * POLYMOUSEOVER the onMouseOver string to use for the elements. * use a %s to interpolate the area title. * default: "" (ie the attribute is suppressed) * POLYMOUSEOUT the onMouseOut string to use for the elements. * use a %s to interpolate the area title. * default: "" (ie the attribute is suppressed) * SYMBOLMOUSEOVER and SYMBOLMOUSEOUT are equivalent properties for * tags representing symbols, with the same defaults. * MAPNAME the string which will be used in the name attribute * of the tag. There is no %s interpolation. * default: "map1" * SUPPRESS if "yes", then we will suppress area declarations with * no title. * default: "NO" * * For example, http://vevo.verifiedvoting.org/verifier contains this * .map file fragment: * OUTPUTFORMAT * NAME imagemap * DRIVER imagemap * FORMATOPTION "POLYHREF=/verifier/map.php?state=%s" * FORMATOPTION "SYMBOLHREF=#" * FORMATOPTION "SUPPRESS=YES" * FORMATOPTION "MAPNAME=map-48" * FORMATOPTION "POLYMOUSEOUT=return nd();" * FORMATOPTION "POLYMOUSEOVER=return overlib('%s');" * END */ /*-------------------------------------------------------------------------*/ /* A pString is a variable-length (appendable) string, stored as a triple: * character pointer, allocated length, and used length. The one wrinkle * is that we use pointers to the allocated size and character pointer, * in order to support refering to fields declared elsewhere (ie in the * 'image' data structure) for these. The 'iprintf' function appends * to a pString. */ typedef struct pString { /* these two fields are somewhere else */ char **string; int *alloc_size; /* this field is stored locally. */ int string_len; } pString; /* These are the pStrings we declare statically. One is the 'output' * imagemap/dxf file; parts of this live in another data structure and * are only referenced indirectly here. The other contains layer-specific * information for the dxf output. */ static char *layerlist=NULL; static int layersize=0; static pString imgStr, layerStr= { &layerlist, &layersize, 0 }; /* Format strings for the various bits of a client-side imagemap. */ static const char *polyHrefFmt, *polyMOverFmt, *polyMOutFmt; static const char *symbolHrefFmt, *symbolMOverFmt, *symbolMOutFmt; static const char *mapName; /* Should we suppress AREA declarations in imagemaps with no title? */ static int suppressEmpty=0; /* Prevent buffer-overrun and format-string attacks by "sanitizing" any * provided format string to fit the number of expected string arguments * (MAX) exactly. */ static const char *makeFmtSafe(const char *fmt, int MAX) { /* format string should have exactly 'MAX' %s */ char *result = msSmallMalloc(strlen(fmt)+1+3*MAX), *cp; int numstr=0, saw_percent=0; strcpy(result, fmt); for (cp=result; *cp; cp++) { if (saw_percent) { if (*cp=='%') { /* safe */ } else if (*cp=='s' && numstralloc_size) - ps->string_len; va_start(ap, fmt); #if defined(HAVE_VSNPRINTF) n = vsnprintf((*(ps->string)) + ps->string_len, remaining, fmt, ap); #else /* If vsnprintf() is not available then require a minimum * of 512 bytes of free space to prevent a buffer overflow * This is not fully bulletproof but should help, see bug 1613 */ if (remaining < 512) n = -1; else n = vsprintf((*(ps->string)) + ps->string_len, fmt, ap); #endif va_end(ap); /* if that worked, we're done! */ if (-1string_len += n; return; } else { /* double allocated string size */ *(ps->alloc_size) *= 2;/* these keeps realloc linear.*/ if (*(ps->alloc_size) < 1024) /* careful: initial size can be 0 */ *(ps->alloc_size)=1024; if (n>-1 && *(ps->alloc_size) <= (n + ps->string_len)) /* ensure at least as much as what is needed */ *(ps->alloc_size) = n+ps->string_len+1; *(ps->string) = (char *) msSmallRealloc (*(ps->string), *(ps->alloc_size)); /* if realloc doesn't work, we're screwed! */ } } while (1); /* go back and try again. */ } static int lastcolor=-1; static int matchdxfcolor(colorObj col) { int best=7; int delta=128*255; int tcolor = 0; if (lastcolor != -1) return lastcolor; while (tcolor < 256 && (ctable[tcolor].r != col.red || ctable[tcolor].g != col.green || ctable[tcolor].b != col.blue)) { if (abs( (ctable[tcolor].r - col.red) * (ctable[tcolor].r - col.red)+ (ctable[tcolor].b - col.blue) * (ctable[tcolor].b - col.blue) + (ctable[tcolor].g - col.green) * (ctable[tcolor].g - col.green) < delta) ) { best = tcolor; delta = abs( (ctable[tcolor].r - col.red) * (ctable[tcolor].r - col.red)+ (ctable[tcolor].b - col.blue) * (ctable[tcolor].b - col.blue) + (ctable[tcolor].g - col.green) * (ctable[tcolor].g - col.green) ); } tcolor++; } if (tcolor >= 256) tcolor = best; /* DEBUG_IF printf("%d/%d/%d (%d/%d - %d), %d : %d/%d/%d
\n", ctable[tcolor].r, ctable[tcolor].g, ctable[tcolor].b, tcolor, best, delta, lastcolor, col.red, col.green, col.blue); */ lastcolor = tcolor; return tcolor; } static char* lname; static int dxf; void msImageStartLayerIM(mapObj *map, layerObj *layer, imageObj *image) { DEBUG_IF printf("ImageStartLayerIM\n
"); free(lname); if (layer->name) lname = msStrdup(layer->name); else lname = msStrdup("NONE"); if (dxf == 2) { im_iprintf(&layerStr, "LAYER\n%s\n", lname); } else if (dxf) { im_iprintf(&layerStr, " 0\nLAYER\n 2\n%s\n" " 70\n 64\n 6\nCONTINUOUS\n", lname); } lastcolor = -1; } /* * Utility function to create a IM image. Returns * a pointer to an imageObj structure. */ imageObj *msImageCreateIM(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution) { imageObj *image=NULL; if (setvbuf(stdout, NULL, _IONBF , 0)) { printf("Whoops..."); }; DEBUG_IF printf("msImageCreateIM
\n"); if (width > 0 && height > 0) { image = (imageObj *)calloc(1,sizeof(imageObj)); MS_CHECK_ALLOC(image, sizeof(imageObj), NULL); if (image) { imgStr.string = &(image->img.imagemap); imgStr.alloc_size = &(image->size); image->format = format; format->refcount++; image->width = width; image->height = height; image->imagepath = NULL; image->imageurl = NULL; image->resolution = resolution; image->resolutionfactor = resolution/defresolution; if( strcasecmp("ON",msGetOutputFormatOption( format, "DXF", "OFF" )) == 0) { dxf = 1; im_iprintf(&layerStr, " 2\nLAYER\n 70\n 10\n"); } else dxf = 0; if( strcasecmp("ON",msGetOutputFormatOption( format, "SCRIPT", "OFF" )) == 0) { dxf = 2; im_iprintf(&layerStr, ""); } /* get href formation string options */ polyHrefFmt = makeFmtSafe(msGetOutputFormatOption ( format, "POLYHREF", "javascript:Clicked('%s');"), 1); polyMOverFmt = makeFmtSafe(msGetOutputFormatOption ( format, "POLYMOUSEOVER", ""), 1); polyMOutFmt = makeFmtSafe(msGetOutputFormatOption ( format, "POLYMOUSEOUT", ""), 1); symbolHrefFmt = makeFmtSafe(msGetOutputFormatOption ( format, "SYMBOLHREF", "javascript:SymbolClicked();"), 1); symbolMOverFmt = makeFmtSafe(msGetOutputFormatOption ( format, "SYMBOLMOUSEOVER", ""), 1); symbolMOutFmt = makeFmtSafe(msGetOutputFormatOption ( format, "SYMBOLMOUSEOUT", ""), 1); /* get name of client-side image map */ mapName = msGetOutputFormatOption ( format, "MAPNAME", "map1" ); /* should we suppress area declarations with no title? */ if( strcasecmp("YES",msGetOutputFormatOption( format, "SUPPRESS", "NO" )) == 0) { suppressEmpty=1; } lname = msStrdup("NONE"); *(imgStr.string) = msStrdup(""); if (*(imgStr.string)) { *(imgStr.alloc_size) = imgStr.string_len = strlen(*(imgStr.string)); } else { *(imgStr.alloc_size) = imgStr.string_len = 0; } if (imagepath) { image->imagepath = msStrdup(imagepath); } if (imageurl) { image->imageurl = msStrdup(imageurl); } return image; } else free( image ); } else { msSetError(MS_IMGERR, "Cannot create IM image of size %d x %d.", "msImageCreateIM()", width, height ); } return image; } /* ------------------------------------------------------------------------- */ /* Draw a single marker symbol of the specified size and color */ /* ------------------------------------------------------------------------- */ void msDrawMarkerSymbolIM(symbolSetObj *symbolset, imageObj* img, pointObj *p, styleObj *style, double scalefactor) { symbolObj *symbol; int ox, oy; double size; DEBUG_IF printf("msDrawMarkerSymbolIM\n
"); /* skip this, we don't do text */ if(!p) return; symbol = symbolset->symbol[style->symbol]; ox = style->offsetx*scalefactor; oy = style->offsety*scalefactor; if(style->size == -1) { size = msSymbolGetDefaultSize( symbol ); size = MS_NINT(size*scalefactor); } else size = MS_NINT(style->size*scalefactor); size = MS_MAX(size, style->minsize*img->resolutionfactor); size = MS_MIN(size, style->maxsize*img->resolutionfactor); if(style->symbol > symbolset->numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */ if(size < 1) return; /* size too small */ /* DEBUG_IF printf(".%d.%d.%d.", symbol->type, style->symbol, fc); */ if(style->symbol == 0) { /* simply draw a single pixel of the specified color */ if (dxf) { if (dxf==2) im_iprintf (&imgStr, "POINT\n%.0f %.0f\n%d\n", p->x + ox, p->y + oy, matchdxfcolor(style->color)); else im_iprintf (&imgStr, " 0\nPOINT\n 10\n%f\n 20\n%f\n 30\n0.0\n" " 62\n%6d\n 8\n%s\n", p->x + ox, p->y + oy, matchdxfcolor(style->color), lname); } else { im_iprintf (&imgStr, "\n", p->x + ox, p->y + oy); } /* point2 = &( p->line[j].point[i] ); */ /* if(point1->y == point2->y) {} */ return; } DEBUG_IF printf("A"); switch(symbol->type) { case(MS_SYMBOL_TRUETYPE): DEBUG_IF printf("T"); break; case(MS_SYMBOL_PIXMAP): DEBUG_IF printf("P"); break; case(MS_SYMBOL_VECTOR): DEBUG_IF printf("V"); { double d, offset_x, offset_y; d = size/symbol->sizey; offset_x = MS_NINT(p->x - d*.5*symbol->sizex + ox); offset_y = MS_NINT(p->y - d*.5*symbol->sizey + oy); /* For now I only render filled vector symbols in imagemap, and no */ /* dxf support available yet. */ if(symbol->filled && !dxf /* && fc >= 0 */ ) { /* char *title=(p->numvalues) ? p->values[0] : ""; */ char *title = ""; int j; im_iprintf (&imgStr, "numpoints; j++) { im_iprintf (&imgStr, "%s %d,%d", j == 0 ? "": ",", MS_NINT(d*symbol->points[j].x + offset_x), MS_NINT(d*symbol->points[j].y + offset_y) ); } im_iprintf (&imgStr, "\" />\n"); } /* end of imagemap, filled case. */ } break; default: DEBUG_IF printf("DEF"); break; } /* end switch statement */ return; } /* ------------------------------------------------------------------------- */ /* Draw a line symbol of the specified size and color */ /* ------------------------------------------------------------------------- */ void msDrawLineSymbolIM(symbolSetObj *symbolset, imageObj* img, shapeObj *p, styleObj *style, double scalefactor) { symbolObj *symbol; int i,j,l; char first = 1; double size; DEBUG_IF printf("msDrawLineSymbolIM
\n"); if(!p) return; if(p->numlines <= 0) return; symbol = symbolset->symbol[style->symbol]; if(style->size == -1) { size = msSymbolGetDefaultSize( symbol ); size = MS_NINT(size*scalefactor); } else size = MS_NINT(style->size*scalefactor); size = MS_MAX(size, style->minsize*img->resolutionfactor); size = MS_MIN(size, style->maxsize*img->resolutionfactor); if(style->symbol > symbolset->numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */ if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */ if(style->symbol == 0) { /* just draw a single width line */ for(l=0,j=0; jnumlines; j++) { if (dxf == 2) { im_iprintf (&imgStr, "LINE\n%d\n", matchdxfcolor(style->color)); } else if (dxf) { im_iprintf (&imgStr, " 0\nPOLYLINE\n 70\n 0\n 62\n%6d\n 8\n%s\n", matchdxfcolor(style->color), lname); } else { char *title; first = 1; title=(p->numvalues) ? p->values[0] : ""; im_iprintf (&imgStr, "line[j].point[p->line[j].numpoints-1] ); */ for(i=0; i < p->line[j].numpoints; i++,l++) { if (dxf == 2) { im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y); } else if (dxf) { im_iprintf (&imgStr, " 0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0); } else { im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y); } first = 0; /* point2 = &( p->line[j].point[i] ); */ /* if(point1->y == point2->y) {} */ } im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": " 0\nSEQEND\n") : "\" />\n"); } /* DEBUG_IF printf ("%d, ",strlen(img->img.imagemap) ); */ return; } DEBUG_IF printf("-%d-",symbol->type); return; } /* ------------------------------------------------------------------------- */ /* Draw a shade symbol of the specified size and color */ /* ------------------------------------------------------------------------- */ void msDrawShadeSymbolIM(symbolSetObj *symbolset, imageObj* img, shapeObj *p, styleObj *style, double scalefactor) { symbolObj *symbol; int i,j,l; char first = 1; double size; DEBUG_IF printf("msDrawShadeSymbolIM\n
"); if(!p) return; if(p->numlines <= 0) return; symbol = symbolset->symbol[style->symbol]; if(style->size == -1) { size = msSymbolGetDefaultSize( symbol ); size = MS_NINT(size*scalefactor); } else size = MS_NINT(style->size*scalefactor); size = MS_MAX(size, style->minsize*img->resolutionfactor); size = MS_MIN(size, style->maxsize*img->resolutionfactor); if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */ if(style->symbol == 0) { /* simply draw a single pixel of the specified color // */ for(l=0,j=0; jnumlines; j++) { if (dxf == 2) { im_iprintf (&imgStr, "POLY\n%d\n", matchdxfcolor(style->color)); } else if (dxf) { im_iprintf (&imgStr, " 0\nPOLYLINE\n 73\n 1\n 62\n%6d\n 8\n%s\n", matchdxfcolor(style->color), lname); } else { char *title=(p->numvalues) ? p->values[0] : ""; first = 1; im_iprintf (&imgStr, "line[j].point[p->line[j].numpoints-1] ); */ for(i=0; i < p->line[j].numpoints; i++,l++) { if (dxf == 2) { im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y); } else if (dxf) { im_iprintf (&imgStr, " 0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0); } else { im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y); } first = 0; /* point2 = &( p->line[j].point[i] ); */ /* if(point1->y == point2->y) {} */ } im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": " 0\nSEQEND\n") : "\" />\n"); } return; } /* DEBUG_IF printf ("d"); */ DEBUG_IF printf("-%d-",symbol->type); return; } /* * Simply draws a label based on the label point and the supplied label object. */ int msDrawTextIM(imageObj* img, pointObj labelPnt, char *string, labelObj *label, fontSetObj *fontset, double scalefactor) { DEBUG_IF printf("msDrawText
\n"); if(!string) return(0); /* not errors, just don't want to do anything */ if(strlen(string) == 0) return(0); if(!dxf) return (0); if (dxf == 2) { im_iprintf (&imgStr, "TEXT\n%d\n%s\n%.0f\n%.0f\n%.0f\n" , matchdxfcolor(label->color), string, labelPnt.x, labelPnt.y, -label->angle); } else if (dxf) { im_iprintf (&imgStr, " 0\nTEXT\n 1\n%s\n 10\n%f\n 20\n%f\n 30\n0.0\n 40\n%f\n 50\n%f\n 62\n%6d\n 8\n%s\n 73\n 2\n 72\n 1\n" , string, labelPnt.x, labelPnt.y, label->size * scalefactor *100, -label->angle, matchdxfcolor(label->color), lname); } return(0); } /* * Save an image to a file named filename, if filename is NULL it goes to stdout */ int msSaveImageIM(imageObj* img, char *filename, outputFormatObj *format ) { FILE *stream; char workbuffer[5000]; int nSize=0, size=0, iIndice=0; DEBUG_IF printf("msSaveImageIM\n
"); if(filename != NULL && strlen(filename) > 0) { stream = fopen(filename, "wb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msSaveImage()", filename); return(MS_FAILURE); } } else { /* use stdout */ #ifdef _WIN32 /* * Change stdout mode to binary on win32 platforms */ if(_setmode( _fileno(stdout), _O_BINARY) == -1) { msSetError(MS_IOERR, "Unable to change stdout to binary mode.", "msSaveImage()"); return(MS_FAILURE); } #endif stream = stdout; } if( strcasecmp(format->driver,"imagemap") == 0 ) { DEBUG_IF printf("ALLOCD %d
\n", img->size); /* DEBUG_IF printf("F %s
\n", img->img.imagemap); */ DEBUG_IF printf("FLEN %d
\n", (int)strlen(img->img.imagemap)); if (dxf == 2) { msIO_fprintf(stream, "%s", layerlist); } else if (dxf) { msIO_fprintf(stream, " 0\nSECTION\n 2\nHEADER\n 9\n$ACADVER\n 1\nAC1009\n0\nENDSEC\n 0\nSECTION\n 2\nTABLES\n 0\nTABLE\n%s0\nENDTAB\n0\nENDSEC\n 0\nSECTION\n 2\nBLOCKS\n0\nENDSEC\n 0\nSECTION\n 2\nENTITIES\n", layerlist); } else { msIO_fprintf(stream, "\n", mapName, img->width, img->height); } nSize = sizeof(workbuffer); size = strlen(img->img.imagemap); if (size > nSize) { iIndice = 0; while ((iIndice + nSize) <= size) { snprintf(workbuffer, sizeof(workbuffer), "%s", img->img.imagemap+iIndice ); workbuffer[nSize-1] = '\0'; msIO_fwrite(workbuffer, strlen(workbuffer), 1, stream); iIndice +=nSize-1; } if (iIndice < size) { sprintf(workbuffer, "%s", img->img.imagemap+iIndice ); msIO_fprintf(stream, "%s", workbuffer); } } else msIO_fwrite(img->img.imagemap, size, 1, stream); if( strcasecmp("OFF",msGetOutputFormatOption( format, "SKIPENDTAG", "OFF" )) == 0) { if (dxf == 2) msIO_fprintf(stream, "END"); else if (dxf) msIO_fprintf(stream, "0\nENDSEC\n0\nEOF\n"); else msIO_fprintf(stream, ""); } } else { msSetError(MS_MISCERR, "Unknown output image type driver: %s.", "msSaveImage()", format->driver ); return(MS_FAILURE); } if(filename != NULL && strlen(filename) > 0) fclose(stream); return(MS_SUCCESS); } /* * Free gdImagePtr */ void msFreeImageIM(imageObj* img) { free(img->img.imagemap); } mapserver-6.4.1/dxfcolor.h0000644002461700001440000001206212261257215015306 0ustar tbonfortusersstruct dxfcolor { int r,g,b; }; struct dxfcolor ctable[256] = { {0, 0, 0}, {255, 0, 0}, {255, 255, 0}, {0, 255, 0}, {0, 255, 255}, {0, 0, 255}, {255, 0, 255}, {255, 255, 255}, {128, 128, 128}, {192, 192, 192}, {255, 0, 0}, {255, 127, 127}, {204, 0, 0}, {204, 102, 102}, {153, 0, 0}, {153, 76, 76}, {127, 0, 0}, {127, 63, 63}, {76, 0, 0}, {76, 38, 38}, {255, 63, 0}, {255, 159, 127}, {204, 51, 0}, {204, 127, 102}, {153, 38, 0}, {153, 95, 76}, {127, 31, 0}, {127, 79, 63}, {76, 19, 0}, {76, 47, 38}, {255, 127, 0}, {255, 191, 127}, {204, 102, 0}, {204, 153, 102}, {153, 76, 0}, {153, 114, 76}, {127, 63, 0}, {127, 95, 63}, {76, 38, 0}, {76, 57, 38}, {255, 191, 0}, {255, 223, 127}, {204, 153, 0}, {204, 178, 102}, {153, 114, 0}, {153, 133, 76}, {127, 95, 0}, {127, 111, 63}, {76, 57, 0}, {76, 66, 38}, {255, 255, 0}, {255, 255, 127}, {204, 204, 0}, {204, 204, 102}, {153, 153, 0}, {153, 153, 76}, {127, 127, 0}, {127, 127, 63}, {76, 76, 0}, {76, 76, 38}, {191, 255, 0}, {223, 255, 127}, {153, 204, 0}, {178, 204, 102}, {114, 153, 0}, {133, 153, 76}, {95, 127, 0}, {111, 127, 63}, {57, 76, 0}, {66, 76, 38}, {127, 255, 0}, {191, 255, 127}, {102, 204, 0}, {153, 204, 102}, {76, 153, 0}, {114, 153, 76}, {63, 127, 0}, {95, 127, 63}, {38, 76, 0}, {57, 76, 38}, {63, 255, 0}, {159, 255, 127}, {51, 204, 0}, {127, 204, 102}, {38, 153, 0}, {95, 153, 76}, {31, 127, 0}, {79, 127, 63}, {19, 76, 0}, {47, 76, 38}, {0, 255, 0}, {127, 255, 127}, {0, 204, 0}, {102, 204, 102}, {0, 153, 0}, {76, 153, 76}, {0, 127, 0}, {63, 127, 63}, {0, 76, 0}, {38, 76, 38}, {0, 255, 63}, {127, 255, 159}, {0, 204, 51}, {102, 204, 127}, {0, 153, 38}, {76, 153, 95}, {0, 127, 31}, {63, 127, 79}, {0, 76, 19}, {38, 76, 47}, {0, 255, 127}, {127, 255, 191}, {0, 204, 102}, {102, 204, 153}, {0, 153, 76}, {76, 153, 114}, {0, 127, 63}, {63, 127, 95}, {0, 76, 38}, {38, 76, 57}, {0, 255, 191}, {127, 255, 223}, {0, 204, 153}, {102, 204, 178}, {0, 153, 114}, {76, 153, 133}, {0, 127, 95}, {63, 127, 111}, {0, 76, 57}, {38, 76, 66}, {0, 255, 255}, {127, 255, 255}, {0, 204, 204}, {102, 204, 204}, {0, 153, 153}, {76, 153, 153}, {0, 127, 127}, {63, 127, 127}, {0, 76, 76}, {38, 76, 76}, {0, 191, 255}, {127, 223, 255}, {0, 153, 204}, {102, 178, 204}, {0, 114, 153}, {76, 133, 153}, {0, 95, 127}, {63, 111, 127}, {0, 57, 76}, {38, 66, 76}, {0, 127, 255}, {127, 191, 255}, {0, 102, 204}, {102, 153, 204}, {0, 76, 153}, {76, 114, 153}, {0, 63, 127}, {63, 95, 127}, {0, 38, 76}, {38, 57, 76}, {0, 63, 255}, {127, 159, 255}, {0, 51, 204}, {102, 127, 204}, {0, 38, 153}, {76, 95, 153}, {0, 31, 127}, {63, 79, 127}, {0, 19, 76}, {38, 47, 76}, {0, 0, 255}, {127, 127, 255}, {0, 0, 204}, {102, 102, 204}, {0, 0, 153}, {76, 76, 153}, {0, 0, 127}, {63, 63, 127}, {0, 0, 76}, {38, 38, 76}, {63, 0, 255}, {159, 127, 255}, {51, 0, 204}, {127, 102, 204}, {38, 0, 153}, {95, 76, 153}, {31, 0, 127}, {79, 63, 127}, {19, 0, 76}, {47, 38, 76}, {127, 0, 255}, {191, 127, 255}, {102, 0, 204}, {153, 102, 204}, {76, 0, 153}, {114, 76, 153}, {63, 0, 127}, {95, 63, 127}, {38, 0, 76}, {57, 38, 76}, {191, 0, 255}, {223, 127, 255}, {153, 0, 204}, {178, 102, 204}, {114, 0, 153}, {133, 76, 153}, {95, 0, 127}, {111, 63, 127}, {57, 0, 76}, {66, 38, 76}, {255, 0, 255}, {255, 127, 255}, {204, 0, 204}, {204, 102, 204}, {153, 0, 153}, {153, 76, 153}, {127, 0, 127}, {127, 63, 127}, {76, 0, 76}, {76, 38, 76}, {255, 0, 191}, {255, 127, 223}, {204, 0, 153}, {204, 102, 178}, {153, 0, 114}, {153, 76, 133}, {127, 0, 95}, {127, 63, 111}, {76, 0, 57}, {76, 38, 66}, {255, 0, 127}, {255, 127, 191}, {204, 0, 102}, {204, 102, 153}, {153, 0, 76}, {153, 76, 114}, {127, 0, 63}, {127, 63, 95}, {76, 0, 38}, {76, 38, 57}, {255, 0, 63}, {255, 127, 159}, {204, 0, 51}, {204, 102, 127}, {153, 0, 38}, {153, 76, 95}, {127, 0, 31}, {127, 63, 79}, {76, 0, 19}, {76, 38, 47}, {51, 51, 51}, {91, 91, 91}, {132, 132, 132}, {173, 173, 173}, {214, 214, 214}, {255, 255, 255}, }; mapserver-6.4.1/mapimageio.c0000644002461700001440000012232612261257215015576 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Low level PNG/JPEG/GIF image io native functions * Author: Thomas Bonfort (tbonfort) * ****************************************************************************** * Copyright (c) 2009 Thomas Bonfort * * 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. ****************************************************************************/ #include "mapserver.h" #include "png.h" #include "setjmp.h" #include #include "jpeglib.h" #include #ifdef USE_GIF #include "gif_lib.h" #endif typedef struct _streamInfo { FILE *fp; bufferObj *buffer; } streamInfo; void png_write_data_to_stream(png_structp png_ptr, png_bytep data, png_size_t length) { FILE *fp = ((streamInfo*)png_get_io_ptr(png_ptr))->fp; msIO_fwrite(data,length,1,fp); } void png_write_data_to_buffer(png_structp png_ptr, png_bytep data, png_size_t length) { bufferObj *buffer = ((streamInfo*)png_get_io_ptr(png_ptr))->buffer; msBufferAppend(buffer,data,length); } void png_flush_data(png_structp png_ptr) { /* do nothing */ } typedef struct { struct jpeg_destination_mgr pub; unsigned char *data; } ms_destination_mgr; typedef struct { ms_destination_mgr mgr; FILE *stream; } ms_stream_destination_mgr; typedef struct { ms_destination_mgr mgr; bufferObj *buffer; } ms_buffer_destination_mgr; #define OUTPUT_BUF_SIZE 4096 void jpeg_init_destination (j_compress_ptr cinfo) { ms_destination_mgr *dest = (ms_destination_mgr*) cinfo->dest; /* Allocate the output buffer --- it will be released when done with image */ dest->data = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char)); dest->pub.next_output_byte = dest->data; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } void jpeg_stream_term_destination (j_compress_ptr cinfo) { ms_stream_destination_mgr *dest = (ms_stream_destination_mgr*) cinfo->dest; msIO_fwrite(dest->mgr.data, OUTPUT_BUF_SIZE-dest->mgr.pub.free_in_buffer, 1, dest->stream); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; } void jpeg_buffer_term_destination (j_compress_ptr cinfo) { ms_buffer_destination_mgr *dest = (ms_buffer_destination_mgr*) cinfo->dest; msBufferAppend(dest->buffer, dest->mgr.data, OUTPUT_BUF_SIZE-dest->mgr.pub.free_in_buffer); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; } int jpeg_stream_empty_output_buffer (j_compress_ptr cinfo) { ms_stream_destination_mgr *dest = (ms_stream_destination_mgr*) cinfo->dest; msIO_fwrite(dest->mgr.data, OUTPUT_BUF_SIZE, 1, dest->stream); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } int jpeg_buffer_empty_output_buffer (j_compress_ptr cinfo) { ms_buffer_destination_mgr *dest = (ms_buffer_destination_mgr*) cinfo->dest; msBufferAppend(dest->buffer, dest->mgr.data, OUTPUT_BUF_SIZE); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } int saveAsJPEG(mapObj *map /*not used*/, rasterBufferObj *rb, streamInfo *info, outputFormatObj *format) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; int quality = atoi(msGetOutputFormatOption( format, "QUALITY", "75")); ms_destination_mgr *dest; JSAMPLE *rowdata; unsigned int row; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); if (cinfo.dest == NULL) { if(info->fp) { cinfo.dest = (struct jpeg_destination_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (ms_stream_destination_mgr)); ((ms_stream_destination_mgr*)cinfo.dest)->mgr.pub.empty_output_buffer = jpeg_stream_empty_output_buffer; ((ms_stream_destination_mgr*)cinfo.dest)->mgr.pub.term_destination = jpeg_stream_term_destination; ((ms_stream_destination_mgr*)cinfo.dest)->stream = info->fp; } else { cinfo.dest = (struct jpeg_destination_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (ms_buffer_destination_mgr)); ((ms_buffer_destination_mgr*)cinfo.dest)->mgr.pub.empty_output_buffer = jpeg_buffer_empty_output_buffer; ((ms_buffer_destination_mgr*)cinfo.dest)->mgr.pub.term_destination = jpeg_buffer_term_destination; ((ms_buffer_destination_mgr*)cinfo.dest)->buffer = info->buffer; } } dest = (ms_destination_mgr*) cinfo.dest; dest->pub.init_destination = jpeg_init_destination; cinfo.image_width = rb->width; cinfo.image_height = rb->height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); rowdata = (JSAMPLE*)malloc(rb->width*cinfo.input_components*sizeof(JSAMPLE)); for(row=0; rowheight; row++) { JSAMPLE *pixptr = rowdata; int col; unsigned char *r,*g,*b; r=rb->data.rgba.r+row*rb->data.rgba.row_step; g=rb->data.rgba.g+row*rb->data.rgba.row_step; b=rb->data.rgba.b+row*rb->data.rgba.row_step; for(col=0; colwidth; col++) { *(pixptr++) = *r; *(pixptr++) = *g; *(pixptr++) = *b; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } (void) jpeg_write_scanlines(&cinfo, &rowdata, 1); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); free(rowdata); return MS_SUCCESS; } /* * sort a given list of rgba entries so that all the opaque pixels are at the end */ int remapPaletteForPNG(rasterBufferObj *rb, rgbPixel *rgb, unsigned char *a, int *num_a) { int bot_idx, top_idx, x; int remap[256]; unsigned int maxval = rb->data.palette.scaling_maxval; assert(rb->type == MS_BUFFER_BYTE_PALETTE); /* ** remap the palette colors so that all entries with ** the maximal alpha value (i.e., fully opaque) are at the end and can ** therefore be omitted from the tRNS chunk. Note that the ordering of ** opaque entries is reversed from how they were previously arranged ** --not that this should matter to anyone. */ for (top_idx = rb->data.palette.num_entries-1, bot_idx = x = 0; x < rb->data.palette.num_entries; ++x) { if (rb->data.palette.palette[x].a == maxval) remap[x] = top_idx--; else remap[x] = bot_idx++; } /* sanity check: top and bottom indices should have just crossed paths */ if (bot_idx != top_idx + 1) { msSetError(MS_MISCERR,"quantization sanity check failed","createPNGPalette()"); return MS_FAILURE; } *num_a = bot_idx; for(x=0; xwidth*rb->height; x++) rb->data.palette.pixels[x] = remap[rb->data.palette.pixels[x]]; for (x = 0; x < rb->data.palette.num_entries; ++x) { if(maxval == 255) { a[remap[x]] = rb->data.palette.palette[x].a; rgb[remap[x]].r = rb->data.palette.palette[x].r; rgb[remap[x]].g = rb->data.palette.palette[x].g; rgb[remap[x]].b = rb->data.palette.palette[x].b; } else { /* rescale palette */ rgb[remap[x]].r = (rb->data.palette.palette[x].r * 255 + (maxval >> 1)) / maxval; rgb[remap[x]].g = (rb->data.palette.palette[x].g * 255 + (maxval >> 1)) / maxval; rgb[remap[x]].b = (rb->data.palette.palette[x].b * 255 + (maxval >> 1)) / maxval; a[remap[x]] = (rb->data.palette.palette[x].a * 255 + (maxval >> 1)) / maxval; } if(a[remap[x]] != 255) { /* un-premultiply pixels */ double da = 255.0/a[remap[x]]; rgb[remap[x]].r *= da; rgb[remap[x]].g *= da; rgb[remap[x]].b *= da; } } return MS_SUCCESS; } int savePalettePNG(rasterBufferObj *rb, streamInfo *info, int compression) { png_infop info_ptr; rgbPixel rgb[256]; unsigned char a[256]; int num_a; int row,sample_depth; png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); assert(rb->type == MS_BUFFER_BYTE_PALETTE); if (!png_ptr) return (MS_FAILURE); png_set_compression_level(png_ptr, compression); png_set_filter (png_ptr,0, PNG_FILTER_NONE); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return (MS_FAILURE); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return (MS_FAILURE); } if(info->fp) png_set_write_fn(png_ptr,info, png_write_data_to_stream, png_flush_data); else png_set_write_fn(png_ptr,info, png_write_data_to_buffer, png_flush_data); if (rb->data.palette.num_entries <= 2) sample_depth = 1; else if (rb->data.palette.num_entries <= 4) sample_depth = 2; else if (rb->data.palette.num_entries <= 16) sample_depth = 4; else sample_depth = 8; png_set_IHDR(png_ptr, info_ptr, rb->width, rb->height, sample_depth, PNG_COLOR_TYPE_PALETTE, 0, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); remapPaletteForPNG(rb,rgb,a,&num_a); png_set_PLTE(png_ptr, info_ptr, (png_colorp)(rgb),rb->data.palette.num_entries); if(num_a) png_set_tRNS(png_ptr, info_ptr, a,num_a, NULL); png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); for(row=0; rowheight; row++) { unsigned char *rowptr = &(rb->data.palette.pixels[row*rb->width]); png_write_row(png_ptr, rowptr); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return MS_SUCCESS; } int readPalette(const char *palette, rgbaPixel *entries, unsigned int *nEntries, int useAlpha) { FILE *stream = NULL; char buffer[MS_BUFFER_LENGTH]; int r,g,b,a; *nEntries = 0; stream = fopen(palette, "r"); if(!stream) { msSetError(MS_IOERR, "Error opening palette file %s.", "readPalette()", palette); return MS_FAILURE; } while(fgets(buffer, MS_BUFFER_LENGTH, stream) && *nEntries<256) { /* while there are colors to load */ if(buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '\r') continue; /* skip comments and blank lines */ if(!useAlpha) { if(3 != sscanf(buffer,"%d,%d,%d\n",&r,&g,&b)) { msSetError(MS_MISCERR,"failed to parse color %d r,g,b triplet in line \"%s\" from file %s","readPalette()",*nEntries+1,buffer,palette); return MS_FAILURE; } } else { if(4 != sscanf(buffer,"%d,%d,%d,%d\n",&r,&g,&b,&a)) { msSetError(MS_MISCERR,"failed to parse color %d r,g,b,a quadruplet in line \"%s\" from file %s","readPalette()",*nEntries+1,buffer,palette); return MS_FAILURE; } } if(useAlpha && a != 255) { double da = a/255.0; entries[*nEntries].r = r * da; entries[*nEntries].g = g * da; entries[*nEntries].b = b * da; entries[*nEntries].a = a; } else { entries[*nEntries].r = r; entries[*nEntries].g = g; entries[*nEntries].b = b; entries[*nEntries].a = 255; } (*nEntries)++; } fclose(stream); return MS_SUCCESS; } int saveAsPNG(mapObj *map,rasterBufferObj *rb, streamInfo *info, outputFormatObj *format) { int force_pc256 = MS_FALSE; int force_palette = MS_FALSE; int ret = MS_FAILURE; const char *force_string,*zlib_compression; int compression = -1; zlib_compression = msGetOutputFormatOption( format, "COMPRESSION", NULL); if(zlib_compression && *zlib_compression) { char *endptr; compression = strtol(zlib_compression,&endptr,10); if(*endptr || compression<-1 || compression>9) { msSetError(MS_MISCERR,"failed to parse FORMATOPTION \"COMPRESSION=%s\", expecting integer from 0 to 9.","saveAsPNG()",zlib_compression); return MS_FAILURE; } } force_string = msGetOutputFormatOption( format, "QUANTIZE_FORCE", NULL ); if( force_string && (strcasecmp(force_string,"on") == 0 || strcasecmp(force_string,"yes") == 0 || strcasecmp(force_string,"true") == 0) ) force_pc256 = MS_TRUE; force_string = msGetOutputFormatOption( format, "PALETTE_FORCE", NULL ); if( force_string && (strcasecmp(force_string,"on") == 0 || strcasecmp(force_string,"yes") == 0 || strcasecmp(force_string,"true") == 0) ) force_palette = MS_TRUE; if(force_pc256 || force_palette) { rasterBufferObj qrb; rgbaPixel palette[256], paletteGiven[256]; unsigned int numPaletteGivenEntries; memset(&qrb,0,sizeof(rasterBufferObj)); qrb.type = MS_BUFFER_BYTE_PALETTE; qrb.width = rb->width; qrb.height = rb->height; qrb.data.palette.pixels = (unsigned char*)malloc(qrb.width*qrb.height*sizeof(unsigned char)); qrb.data.palette.scaling_maxval = 255; if(force_pc256) { qrb.data.palette.palette = palette; qrb.data.palette.num_entries = atoi(msGetOutputFormatOption( format, "QUANTIZE_COLORS", "256")); ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette, NULL, 0, &qrb.data.palette.scaling_maxval); } else { int colorsWanted = atoi(msGetOutputFormatOption( format, "QUANTIZE_COLORS", "0")); const char *palettePath = msGetOutputFormatOption( format, "PALETTE", "palette.txt"); char szPath[MS_MAXPATHLEN]; if(map) { msBuildPath(szPath, map->mappath, palettePath); palettePath = szPath; } if(readPalette(palettePath,paletteGiven,&numPaletteGivenEntries,format->transparent) != MS_SUCCESS) { return MS_FAILURE; } if(numPaletteGivenEntries == 256 || colorsWanted == 0) { qrb.data.palette.palette = paletteGiven; qrb.data.palette.num_entries = numPaletteGivenEntries; ret = MS_SUCCESS; /* we have a full palette and don't want an additional quantization step */ } else { /* quantize the image, and mix our colours in the resulting palette */ qrb.data.palette.palette = palette; qrb.data.palette.num_entries = MS_MAX(colorsWanted,numPaletteGivenEntries); ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette, paletteGiven,numPaletteGivenEntries, &qrb.data.palette.scaling_maxval); } } if(ret != MS_FAILURE) { ret = msClassifyRasterBuffer(rb,&qrb); ret = savePalettePNG(&qrb,info,compression); } msFree(qrb.data.palette.pixels); return ret; } else if(rb->type == MS_BUFFER_BYTE_RGBA) { png_infop info_ptr; int color_type; int row; unsigned int *rowdata; png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr) return (MS_FAILURE); png_set_compression_level(png_ptr, compression); png_set_filter (png_ptr,0, PNG_FILTER_NONE); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return (MS_FAILURE); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return (MS_FAILURE); } if(info->fp) png_set_write_fn(png_ptr,info, png_write_data_to_stream, png_flush_data); else png_set_write_fn(png_ptr,info, png_write_data_to_buffer, png_flush_data); if(rb->data.rgba.a) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, rb->width, rb->height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); if(!rb->data.rgba.a && rb->data.rgba.pixel_step==4) png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); rowdata = (unsigned int*)malloc(rb->width*sizeof(unsigned int)); for(row=0; rowheight; row++) { unsigned int *pixptr = rowdata; int col; unsigned char *a,*r,*g,*b; r=rb->data.rgba.r+row*rb->data.rgba.row_step; g=rb->data.rgba.g+row*rb->data.rgba.row_step; b=rb->data.rgba.b+row*rb->data.rgba.row_step; if(rb->data.rgba.a) { a=rb->data.rgba.a+row*rb->data.rgba.row_step; for(col=0; colwidth; col++) { if(*a) { double da = *a/255.0; unsigned char *pix = (unsigned char*)pixptr; pix[0] = *r/da; pix[1] = *g/da; pix[2] = *b/da; pix[3] = *a; } else { *pixptr=0; } pixptr++; a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } else { for(col=0; colwidth; col++) { unsigned char *pix = (unsigned char*)pixptr; pix[0] = *r; pix[1] = *g; pix[2] = *b; pixptr++; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } png_write_row(png_ptr,(png_bytep)rowdata); } png_write_end(png_ptr, info_ptr); free(rowdata); png_destroy_write_struct(&png_ptr, &info_ptr); return MS_SUCCESS; } else { msSetError(MS_MISCERR,"Unknown buffer type","saveAsPNG()"); return MS_FAILURE; } } /* For platforms with incomplete ANSI defines. Fortunately, SEEK_SET is defined to be zero by the standard. */ #ifndef SEEK_SET #define SEEK_SET 0 #endif /* SEEK_SET */ #ifdef USE_GD /* #include */ /* #include */ /* #include */ #include "gd.h" /* this is used for creating images in main memory */ typedef struct fileIOCtx { gdIOCtx ctx; FILE *f; } fileIOCtx; static void msFreeFileCtx (gdIOCtx * ctx) { free(ctx); } static int filePutbuf (gdIOCtx * ctx, const void *buf, int size) { fileIOCtx *fctx; fctx = (fileIOCtx *) ctx; return fwrite (buf, 1, size, fctx->f); } static int fileGetbuf (gdIOCtx * ctx, void *buf, int size) { fileIOCtx *fctx; fctx = (fileIOCtx *) ctx; return (msIO_fread (buf, 1, size, fctx->f)); } static void filePutchar (gdIOCtx * ctx, int a) { unsigned char b; fileIOCtx *fctx; fctx = (fileIOCtx *) ctx; b = a; putc (b, fctx->f); } static int fileGetchar (gdIOCtx * ctx) { fileIOCtx *fctx; fctx = (fileIOCtx *) ctx; return getc (fctx->f); } static int fileSeek (struct gdIOCtx *ctx, const int pos) { fileIOCtx *fctx; fctx = (fileIOCtx *) ctx; return (fseek (fctx->f, pos, SEEK_SET) == 0); } static long fileTell (struct gdIOCtx *ctx) { fileIOCtx *fctx; fctx = (fileIOCtx *) ctx; return ftell (fctx->f); } /* return data as a dynamic pointer */ gdIOCtx *msNewGDFileCtx (FILE * f) { fileIOCtx *ctx; ctx = (fileIOCtx *) malloc (sizeof (fileIOCtx)); if (ctx == NULL) { return NULL; } ctx->f = f; ctx->ctx.getC = fileGetchar; ctx->ctx.putC = filePutchar; ctx->ctx.getBuf = fileGetbuf; ctx->ctx.putBuf = filePutbuf; ctx->ctx.tell = fileTell; ctx->ctx.seek = fileSeek; ctx->ctx.gd_free = msFreeFileCtx; return (gdIOCtx *) ctx; } static const unsigned char PNGsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; /* 89 50 4E 47 0D 0A 1A 0A hex */ int msLoadGDRasterBufferFromFile(char *path, rasterBufferObj *rb) { FILE *stream; char bytes[8]; gdImagePtr img = NULL; stream = fopen(path,"rb"); if(!stream) { msSetError(MS_MISCERR, "unable to open file %s for reading", "loadGDImg()", path); return MS_FAILURE; } if(1 != fread(bytes,8,1,stream)) { /* read some bytes to try and identify the file */ msSetError(MS_MISCERR, "Unable to read header from image file %s", "msLoadGDRasterBufferFromFile()",path); return MS_FAILURE; } rewind(stream); /* reset the image for the readers */ if(memcmp(bytes,"GIF8",4)==0) { #ifdef USE_GD_GIF gdIOCtx *ctx; ctx = msNewGDFileCtx(stream); img = gdImageCreateFromGifCtx(ctx); ctx->gd_free(ctx); #else msSetError(MS_MISCERR, "Unable to load GIF symbol.", "msLoadGDRasterBufferFromFile()"); return MS_FAILURE; #endif } else if (memcmp(bytes,PNGsig,8)==0) { #ifdef USE_GD_PNG gdIOCtx *ctx; ctx = msNewGDFileCtx(stream); img = gdImageCreateFromPngCtx(ctx); ctx->gd_free(ctx); #else msSetError(MS_MISCERR, "Unable to load PNG symbol.", "msLoadGDRasterBufferFromFile()"); return MS_FAILURE; #endif } fclose(stream); if(!img) { msSetError(MS_GDERR, NULL, "loadGDImg()"); rb->type = MS_BUFFER_NONE; return MS_FAILURE; } if(gdImageTrueColor(img)) { int x,y; gdImagePtr pimg = gdImageCreate(gdImageSX(img),gdImageSY(img)); gdImageColorAllocateAlpha(pimg,0,0,0,127); for(y = 0 ; y < gdImageSY(img); y++) { for(x = 0; x < gdImageSX(img); x++) { int pix = gdImageGetTrueColorPixel(img,x,y); if(gdTrueColorGetAlpha(pix) == 127) { gdImageSetPixel(pimg,x,y,0); pimg->transparent = 0; } else { gdImageSetPixel(pimg,x,y,gdImageColorResolveAlpha(pimg,gdTrueColorGetRed(pix),gdTrueColorGetGreen(pix), gdTrueColorGetBlue(pix),gdTrueColorGetAlpha(pix))); } } } gdImageDestroy(img); img = pimg; } rb->type = MS_BUFFER_GD; rb->width = gdImageSX(img); rb->height = gdImageSY(img); rb->data.gd_img = img; return MS_SUCCESS; } #endif int readPNG(char *path, rasterBufferObj *rb) { png_uint_32 width,height; unsigned char *a,*r,*g,*b; int bit_depth,color_type,i; unsigned char **row_pointers; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE *stream = fopen(path,"rb"); if(!stream) return MS_FAILURE; /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return MS_FAILURE; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return MS_FAILURE; /* out of memory */ } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr,&info_ptr,NULL); return MS_FAILURE; } png_init_io(png_ptr,stream); png_read_info(png_ptr,info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL,NULL,NULL); rb->width = width; rb->height = height; rb->type = MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixels = (unsigned char*)malloc(width*height*4*sizeof(unsigned char)); row_pointers = (unsigned char**)malloc(height*sizeof(unsigned char*)); rb->data.rgba.pixel_step=4; rb->data.rgba.row_step = width*4; b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; for(i=0; idata.rgba.pixels[i*rb->data.rgba.row_step]); } if (color_type == PNG_COLOR_TYPE_PALETTE) /* expand palette images to RGB */ png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) /* expand low bit-depth grayscale to 8bits */ png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) /* expand transparency chunks to full alpha */ png_set_expand(png_ptr); if (bit_depth == 16) /* scale 16bits down to 8 */ png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) /* convert grayscale to rgba */ png_set_gray_to_rgb(png_ptr); png_set_bgr(png_ptr); if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); assert(png_get_rowbytes(png_ptr, info_ptr) == rb->data.rgba.row_step); png_read_image(png_ptr, row_pointers); free(row_pointers); row_pointers=NULL; png_read_end(png_ptr,NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); /*premultiply data*/ for(i=0; i> 8; *g = (*g * *a + 255) >> 8; *b = (*b * *a + 255) >> 8; } } a+=4; b+=4; g+=4; r+=4; } fclose(stream); return MS_SUCCESS; } #ifdef USE_GD int saveGdImage(gdImagePtr ip, FILE *fp, outputFormatObj *format) { gdIOCtx *ctx = NULL; if (fp && (fp == stdout)) ctx = msIO_getGDIOCtx( fp ); if(strcasecmp("ON", msGetOutputFormatOption(format, "INTERLACE", "ON")) == 0) gdImageInterlace(ip, 1); if(format->transparent) gdImageColorTransparent(ip, 0); if(strcasestr(format->driver, "/gif")) { #ifdef USE_GD_GIF if (ctx) gdImageGifCtx(ip, ctx); else gdImageGif(ip, fp); #else msSetError(MS_MISCERR, "GIF output is not available.", "saveImageGD()"); return(MS_FAILURE); #endif } else if(strcasestr(format->driver, "/png")) { #ifdef USE_GD_PNG if (ctx) gdImagePngCtx(ip, ctx); else gdImagePng(ip, fp); #else msSetError(MS_MISCERR, "PNG output is not available.", "saveImageGD()"); return(MS_FAILURE); #endif } else if(strcasestr(format->driver, "/jpeg")) { #ifdef USE_GD_JPEG if (ctx) gdImageJpegCtx(ip, ctx, atoi(msGetOutputFormatOption( format, "QUALITY", "75"))); else gdImageJpeg(ip, fp, atoi(msGetOutputFormatOption( format, "QUALITY", "75"))); #else msSetError(MS_MISCERR, "JPEG output is not available.", "saveImageGD()"); return(MS_FAILURE); #endif } else { msSetError(MS_MISCERR, "Unknown or unsupported format.", "saveImageGD()"); return(MS_FAILURE); } msFree(ctx); return MS_SUCCESS; } int saveGdImageBuffer(gdImagePtr ip, bufferObj *buffer, outputFormatObj *format) { gdIOCtx *ctx; int tmp_size; ctx = gdNewDynamicCtx (2048, NULL); if( format->imagemode == MS_IMAGEMODE_RGBA ) gdImageSaveAlpha( ip, 1 ); else if( format->imagemode == MS_IMAGEMODE_RGB ) gdImageSaveAlpha( ip, 0 ); if(strcasecmp("ON", msGetOutputFormatOption(format, "INTERLACE", "ON")) == 0) gdImageInterlace(ip, 1); if(format->transparent) gdImageColorTransparent(ip, 0); if(strcasestr(format->driver, "/gif")) { #ifdef USE_GD_GIF gdImageGifCtx( ip, ctx ); #else msSetError(MS_MISCERR, "GIF output is not available.", "saveImageGD()"); ctx->gd_free(ctx); return(MS_FAILURE); #endif } else if(strcasestr(format->driver, "/png")) { #ifdef USE_GD_PNG gdImagePngCtx(ip, ctx); #else msSetError(MS_MISCERR, "PNG output is not available.", "saveImageGD()"); ctx->gd_free(ctx); return(MS_FAILURE); #endif } else if(strcasestr(format->driver, "/jpeg")) { #ifdef USE_GD_JPEG gdImageJpegCtx(ip, ctx, atoi(msGetOutputFormatOption( format, "QUALITY", "75"))); #else msSetError(MS_MISCERR, "JPEG output is not available.", "saveImageGD()"); ctx->gd_free(ctx); return(MS_FAILURE); #endif } else { msSetError(MS_MISCERR, "Unknown or unsupported format.", "saveImageGD()"); ctx->gd_free(ctx); return(MS_FAILURE); } /* gdDPExtractData expects a int*, but bufferObj::size is a size_t */ /* so use a temp variable to hold it */ buffer->data = gdDPExtractData (ctx, &tmp_size); buffer->size = tmp_size; ctx->gd_free(ctx); return MS_SUCCESS; } #endif int msSaveRasterBuffer(mapObj *map, rasterBufferObj *rb, FILE *stream, outputFormatObj *format) { #ifdef USE_GD if(rb->type == MS_BUFFER_GD) { return saveGdImage(rb->data.gd_img, stream, format); } #else assert(rb->type != MS_BUFFER_GD); #endif if(strcasestr(format->driver,"/png")) { streamInfo info; info.fp = stream; info.buffer = NULL; return saveAsPNG(map, rb,&info,format); } else if(strcasestr(format->driver,"/jpeg")) { streamInfo info; info.fp = stream; info.buffer=NULL; return saveAsJPEG(map, rb,&info,format); } else { msSetError(MS_MISCERR,"unsupported image format\n", "msSaveRasterBuffer()"); return MS_FAILURE; } } int msSaveRasterBufferToBuffer(rasterBufferObj *data, bufferObj *buffer, outputFormatObj *format) { #ifdef USE_GD if(data->type == MS_BUFFER_GD) { return saveGdImageBuffer(data->data.gd_img, buffer, format); } #else assert(data->type != MS_BUFFER_GD); #endif if(strcasestr(format->driver,"/png")) { streamInfo info; info.fp = NULL; info.buffer = buffer; return saveAsPNG(NULL, data,&info,format); } else if(strcasestr(format->driver,"/jpeg")) { streamInfo info; info.fp = NULL; info.buffer=buffer; return saveAsJPEG(NULL, data,&info,format); } else { msSetError(MS_MISCERR,"unsupported image format\n", "msSaveRasterBuffer()"); return MS_FAILURE; } } #ifdef USE_GIF #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 static char const *gif_error_msg(int code) #else static char const *gif_error_msg() #endif { static char msg[80]; #if (!defined GIFLIB_MAJOR) || (GIFLIB_MAJOR < 5) int code = GifLastError(); #endif switch (code) { case E_GIF_ERR_OPEN_FAILED: /* should not see this */ return "Failed to open given file"; case E_GIF_ERR_WRITE_FAILED: return "Write failed"; case E_GIF_ERR_HAS_SCRN_DSCR: /* should not see this */ return "Screen descriptor already passed to giflib"; case E_GIF_ERR_HAS_IMAG_DSCR: /* should not see this */ return "Image descriptor already passed to giflib"; case E_GIF_ERR_NO_COLOR_MAP: /* should not see this */ return "Neither global nor local color map set"; case E_GIF_ERR_DATA_TOO_BIG: /* should not see this */ return "Too much pixel data passed to giflib"; case E_GIF_ERR_NOT_ENOUGH_MEM: return "Out of memory"; case E_GIF_ERR_DISK_IS_FULL: return "Disk is full"; case E_GIF_ERR_CLOSE_FAILED: /* should not see this */ return "File close failed"; case E_GIF_ERR_NOT_WRITEABLE: /* should not see this */ return "File not writable"; case D_GIF_ERR_OPEN_FAILED: return "Failed to open file"; case D_GIF_ERR_READ_FAILED: return "Failed to read from file"; case D_GIF_ERR_NOT_GIF_FILE: return "File is not a GIF file"; case D_GIF_ERR_NO_SCRN_DSCR: return "No screen descriptor detected - invalid file"; case D_GIF_ERR_NO_IMAG_DSCR: return "No image descriptor detected - invalid file"; case D_GIF_ERR_NO_COLOR_MAP: return "No global or local color map found"; case D_GIF_ERR_WRONG_RECORD: return "Wrong record type detected - invalid file?"; case D_GIF_ERR_DATA_TOO_BIG: return "Data in file too big for image"; case D_GIF_ERR_NOT_ENOUGH_MEM: return "Out of memory"; case D_GIF_ERR_CLOSE_FAILED: return "Close failed"; case D_GIF_ERR_NOT_READABLE: return "File not opened for read"; case D_GIF_ERR_IMAGE_DEFECT: return "Defective image"; case D_GIF_ERR_EOF_TOO_SOON: return "Unexpected EOF - invalid file"; default: sprintf(msg, "Unknown giflib error code %d", code); return msg; } } /* not fully implemented and tested */ /* missing: set the first pointer to a,r,g,b */ int readGIF(char *path, rasterBufferObj *rb) { int i, j, codeSize, extCode, firstImageRead = MS_FALSE; unsigned char *r,*g,*b,*a; int transIdx = -1; GifFileType *image; GifPixelType *line; GifRecordType recordType; GifByteType *codeBlock, *extension; ColorMapObject *cmap; int interlacedOffsets[] = {0,4,2,1}; int interlacedJumps[] = {8,8,4,2}; #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 int errcode; #endif rb->type = MS_BUFFER_BYTE_RGBA; #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 image = DGifOpenFileName(path, &errcode); if (image == NULL) { msSetError(MS_MISCERR,"failed to load gif image: %s","readGIF()", gif_error_msg(errcode)); return MS_FAILURE; } #else image = DGifOpenFileName(path); if (image == NULL) { msSetError(MS_MISCERR,"failed to load gif image: %s","readGIF()", gif_error_msg()); return MS_FAILURE; } #endif rb->width = image->SWidth; rb->height = image->SHeight; rb->data.rgba.row_step = rb->width * 4; rb->data.rgba.pixel_step = 4; rb->data.rgba.pixels = (unsigned char*)malloc(rb->width*rb->height*4*sizeof(unsigned char*)); b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; cmap = (image->Image.ColorMap)?image->Image.ColorMap:image->SColorMap; for(i=0; iwidth*rb->height; i++) { *a = 255; *r = cmap->Colors[image->SBackGroundColor].Red; *g = cmap->Colors[image->SBackGroundColor].Green; *b = cmap->Colors[image->SBackGroundColor].Blue; a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } do { if (DGifGetRecordType(image, &recordType) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } switch (recordType) { case SCREEN_DESC_RECORD_TYPE: DGifGetScreenDesc(image); break; case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(image) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } if (!firstImageRead) { int row = image->Image.Top; int col = image->Image.Left; int width = image->Image.Width; int height = image->Image.Height; /* sanity check: */ if(col+width>rb->width || row+height>rb->height) { msSetError(MS_MISCERR,"corrupted gif image, img size exceeds screen size","readGIF()"); return MS_FAILURE; } line = (GifPixelType *) malloc(width * sizeof(GifPixelType)); if(image->Image.Interlace) { int count; for(count=0; count<4; count++) { for(i=row+interlacedOffsets[count]; idata.rgba.row_step + col * rb->data.rgba.pixel_step; a = rb->data.rgba.a + offset; r = rb->data.rgba.r + offset; g = rb->data.rgba.g + offset; b = rb->data.rgba.b + offset; if (DGifGetLine(image, line, width) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg()); #endif return MS_FAILURE; } for(j=0; jColors[pix].Red; *g = cmap->Colors[pix].Green; *b = cmap->Colors[pix].Blue; } else { *a = *r = *g = *b = 0; } a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } } } else { for (i = 0; i < height; i++) { int offset = i * rb->data.rgba.row_step + col * rb->data.rgba.pixel_step; a = rb->data.rgba.a + offset; r = rb->data.rgba.r + offset; g = rb->data.rgba.g + offset; b = rb->data.rgba.b + offset; if (DGifGetLine(image, line, width) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg()); #endif return MS_FAILURE; } for(j=0; jColors[pix].Red; *g = cmap->Colors[pix].Green; *b = cmap->Colors[pix].Blue; } else { *a = *r = *g = *b = 0; } a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } } free((char *) line); firstImageRead = MS_TRUE; } else { /* Skip all next images */ if (DGifGetCode(image, &codeSize, &codeBlock) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } while (codeBlock != NULL) { if (DGifGetCodeNext(image, &codeBlock) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } } } break; case EXTENSION_RECORD_TYPE: /* skip all extension blocks */ if (DGifGetExtension(image, &extCode, &extension) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } if(extCode == 249 && (extension[1] & 1)) transIdx = extension[4]; for (;;) { if (DGifGetExtensionNext(image, &extension) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } if (extension == NULL) break; if(extension[1] & 1) transIdx = extension[4]; } break; case UNDEFINED_RECORD_TYPE: break; case TERMINATE_RECORD_TYPE: break; default: break; } } while (recordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(image) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } return MS_SUCCESS; } #endif int msLoadMSRasterBufferFromFile(char *path, rasterBufferObj *rb) { FILE *stream; unsigned char signature[8]; int ret = MS_FAILURE; stream = fopen(path,"rb"); if(!stream) { msSetError(MS_MISCERR, "unable to open file %s for reading", "msLoadMSRasterBufferFromFile()", path); return MS_FAILURE; } if(1 != fread(signature,8,1,stream)) { msSetError(MS_MISCERR, "Unable to read header from image file %s", "msLoadMSRasterBufferFromFile()",path); return MS_FAILURE; } fclose(stream); if(png_sig_cmp(signature,0,8) == 0) { ret = readPNG(path,rb); } else if (!strncmp((char*)signature,"GIF",3)) { #ifdef USE_GIF ret = readGIF(path,rb); #else msSetError(MS_MISCERR,"pixmap %s seems to be GIF formatted, but this server is compiled without GIF support","readImage()",path); return MS_FAILURE; #endif } else { msSetError(MS_MISCERR,"unsupported pixmap format","readImage()"); return MS_FAILURE; } return ret; } mapserver-6.4.1/mapserver-api.c0000644002461700001440000000073312261257215016236 0ustar tbonfortusers#include "mapserver.h" mapObj* umnms_new_map(char *filename) { mapObj *map = NULL; if(filename) { map = msLoadMap(filename,NULL); } else { map = (mapObj *)msSmallCalloc(sizeof(mapObj),1); if(initMap(map) == -1) { free(map); return NULL; } } return map; } layerObj* umnms_new_layer(mapObj *map); classObj* umnms_new_class(layerObj *layer); styleObj* umnms_new_style(classObj *theclass); labelObj* umnms_new_label(classObj *theclass); mapserver-6.4.1/mapows.c0000644002461700001440000027222312261257215014776 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Web Services (WMS, WFS) support functions * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maptime.h" #include "maptemplate.h" #if defined(USE_LIBXML2) #include "maplibxml2.h" #elif defined(USE_GDAL) #include "cpl_minixml.h" #include "cpl_error.h" #endif #include /* isalnum() */ #include #include /* ** msOWSInitRequestObj() initializes an owsRequestObj; i.e: sets ** all internal pointers to NULL. */ static void msOWSInitRequestObj(owsRequestObj *ows_request) { ows_request->numlayers = 0; ows_request->enabled_layers = NULL; ows_request->service = NULL; ows_request->version = NULL; ows_request->request = NULL; ows_request->document = NULL; } /* ** msOWSClearRequestObj() releases all resources associated with an ** owsRequestObj. */ static void msOWSClearRequestObj(owsRequestObj *ows_request) { msFree(ows_request->enabled_layers); msFree(ows_request->service); msFree(ows_request->version); msFree(ows_request->request); if(ows_request->document) { #if defined(USE_LIBXML2) xmlFreeDoc(ows_request->document); xmlCleanupParser(); #elif defined(USE_GDAL) CPLDestroyXMLNode(ows_request->document); #endif } } /* ** msOWSPreParseRequest() parses a cgiRequestObj either with GET/KVP ** or with POST/XML. Only SERVICE, VERSION (or WMTVER) and REQUEST are ** being determined, all WxS (or SOS) specific parameters are parsed ** within the according handler. ** The results are saved within an owsRequestObj. If the request was ** transmitted with POST/XML, either the document (if compiled with ** libxml2) or the root CPLXMLNode is saved to the ows_request->document ** field. ** Returns MS_SUCCESS upon success, MS_FAILURE if severe errors occurred ** or MS_DONE, if the service could not be determined. */ static int msOWSPreParseRequest(cgiRequestObj *request, owsRequestObj *ows_request) { /* decide if KVP or XML */ if (request->type == MS_GET_REQUEST || (request->type == MS_POST_REQUEST && request->contenttype && strncmp(request->contenttype, "application/x-www-form-urlencoded", strlen("application/x-www-form-urlencoded")) == 0)) { int i; /* parse KVP parameters service, version and request */ for (i = 0; i < request->NumParams; ++i) { if (EQUAL(request->ParamNames[i], "SERVICE")) { ows_request->service = msStrdup(request->ParamValues[i]); } else if (EQUAL(request->ParamNames[i], "VERSION") || EQUAL(request->ParamNames[i], "WMTVER")) { /* for WMS */ ows_request->version = msStrdup(request->ParamValues[i]); } else if (EQUAL(request->ParamNames[i], "REQUEST")) { ows_request->request = msStrdup(request->ParamValues[i]); } /* stop if we have all necessary parameters */ if(ows_request->service && ows_request->version && ows_request->request) { break; } } } else if (request->type == MS_POST_REQUEST) { #if defined(USE_LIBXML2) xmlNodePtr root = NULL; #elif defined(USE_GDAL) CPLXMLNode *temp; #endif if (!request->postrequest || !strlen(request->postrequest)) { msSetError(MS_OWSERR, "POST request is empty.", "msOWSPreParseRequest()"); return MS_FAILURE; } #if defined(USE_LIBXML2) /* parse to DOM-Structure with libxml2 and get the root element */ ows_request->document = xmlParseMemory(request->postrequest, strlen(request->postrequest)); if (ows_request->document == NULL || (root = xmlDocGetRootElement(ows_request->document)) == NULL) { xmlErrorPtr error = xmlGetLastError(); msSetError(MS_OWSERR, "XML parsing error: %s", "msOWSPreParseRequest()", error->message); return MS_FAILURE; } /* Get service, version and request from root */ ows_request->service = (char *) xmlGetProp(root, BAD_CAST "service"); ows_request->version = (char *) xmlGetProp(root, BAD_CAST "version"); ows_request->request = msStrdup((char *) root->name); #elif defined(USE_GDAL) /* parse with CPLXML */ ows_request->document = CPLParseXMLString(request->postrequest); if (ows_request->document == NULL) { msSetError(MS_OWSERR, "XML parsing error: %s", "msOWSPreParseRequest()", CPLGetLastErrorMsg()); return MS_FAILURE; } /* remove all namespaces */ CPLStripXMLNamespace(ows_request->document, NULL, 1); for (temp = ows_request->document; temp != NULL; temp = temp->psNext) { if (temp->eType == CXT_Element) { const char *service, *version; ows_request->request = msStrdup(temp->pszValue); if ((service = CPLGetXMLValue(temp, "service", NULL)) != NULL) { ows_request->service = msStrdup(service); } if ((version = CPLGetXMLValue(temp, "version", NULL)) != NULL) { ows_request->version = msStrdup(version); } continue; } } #else /* could not parse XML since no parser was compiled */ msSetError(MS_OWSERR, "Could not parse the POST XML since MapServer" "was not compiled with libxml2 or GDAL.", "msOWSPreParseRequest()"); return MS_FAILURE; #endif /* defined(USE_LIBXML2) */ } else { msSetError(MS_OWSERR, "Unknown request method. Use either GET or POST.", "msOWSPreParseRequest()"); return MS_FAILURE; } /* certain WMS requests do not require the service parameter */ /* see: http://trac.osgeo.org/mapserver/ticket/2531 */ if (ows_request->service == NULL && ows_request->request != NULL) { if (EQUAL(ows_request->request, "GetMap") || EQUAL(ows_request->request, "GetFeatureInfo")) { ows_request->service = msStrdup("WMS"); } else { /* service could not be determined */ return MS_DONE; } } return MS_SUCCESS; } /* ** msOWSDispatch() is the entry point for any OWS request (WMS, WFS, ...) ** - If this is a valid request then it is processed and MS_SUCCESS is returned ** on success, or MS_FAILURE on failure. ** - If force_ows_mode is true then an exception will be produced if the ** request is not recognized as a valid request. ** - If force_ows_mode is false and this does not appear to be a valid OWS ** request then MS_DONE is returned and MapServer is expected to process ** this as a regular MapServer (traditional CGI) request. */ int msOWSDispatch(mapObj *map, cgiRequestObj *request, int ows_mode) { int status = MS_DONE, force_ows_mode = 0; owsRequestObj ows_request; if (!request) { return status; } force_ows_mode = (ows_mode == OWS || ows_mode == WFS); msOWSInitRequestObj(&ows_request); switch(msOWSPreParseRequest(request, &ows_request)) { case MS_FAILURE: /* a severe error occurred */ return MS_FAILURE; case MS_DONE: /* OWS Service could not be determined */ /* continue for now */ status = MS_DONE; } if (ows_request.service == NULL) { /* exit if service is not set */ if(force_ows_mode) { msSetError( MS_MISCERR, "OWS Common exception: exceptionCode=MissingParameterValue, locator=SERVICE, ExceptionText=SERVICE parameter missing.", "msOWSDispatch()"); status = MS_FAILURE; } else { status = MS_DONE; } } else if (EQUAL(ows_request.service, "WMS")) { #ifdef USE_WMS_SVR status = msWMSDispatch(map, request, &ows_request, MS_FALSE); #else msSetError( MS_WMSERR, "SERVICE=WMS requested, but WMS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if (EQUAL(ows_request.service, "WFS")) { #ifdef USE_WFS_SVR status = msWFSDispatch(map, request, &ows_request, (ows_mode == WFS)); #else msSetError( MS_WFSERR, "SERVICE=WFS requested, but WFS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if (EQUAL(ows_request.service, "WCS")) { #ifdef USE_WCS_SVR status = msWCSDispatch(map, request, &ows_request); #else msSetError( MS_WCSERR, "SERVICE=WCS requested, but WCS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if (EQUAL(ows_request.service, "SOS")) { #ifdef USE_SOS_SVR status = msSOSDispatch(map, request, &ows_request); #else msSetError( MS_SOSERR, "SERVICE=SOS requested, but SOS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if(force_ows_mode) { msSetError( MS_MISCERR, "OWS Common exception: exceptionCode=InvalidParameterValue, locator=SERVICE, ExceptionText=SERVICE parameter value invalid.", "msOWSDispatch()"); status = MS_FAILURE; } msOWSClearRequestObj(&ows_request); return status; } /* ** msOWSIpParse() ** ** Parse the IP address or range into a binary array. ** Supports ipv4 and ipv6 addresses ** Ranges can be specified using the CIDR notation (ie: 192.100.100.0/24) ** ** Returns the parsed of the IP (4 or 16). */ int msOWSIpParse(const char* ip, unsigned char* ip1, unsigned char* mask) { int len = 0, masklen, seps; if (msCountChars((char*)ip, '.') == 3) { /* ipv4 */ unsigned char* val = ip1; len = 1; masklen = 32; *val = 0; while (*ip) { if (*ip >= '0' && *ip <= '9') (*val) = 10 * (*val) + (*ip - '0'); else if (*ip == '.') { ++val; *val = 0; ++len; } else if (*ip == '/') { masklen = atoi(ip+1); if (masklen > 32) masklen = 32; break; } else break; ++ip; } if (len != 4) return 0; /* write mask */ if (mask) { memset(mask, 0, len); val = mask; while (masklen) { if (masklen >= 8) { *val = 0xff; masklen -= 8; } else { *val = - ((unsigned char)pow(2, 8 - masklen)); break; } ++val; } } } else if ((seps = msCountChars((char*)ip, ':')) > 1 && seps < 8) { /* ipv6 */ unsigned short* val = (unsigned short*)ip1; len = 2; masklen = 128; *val = 0; while (*ip) { if (*ip >= '0' && *ip <= '9') (*val) = 16 * (*val) + (*ip - '0'); else if (*ip >= 'a' && *ip <= 'f') (*val) = 16 * (*val) + (*ip - 'a' + 10); else if (*ip >= 'A' && *ip <= 'F') (*val) = 16 * (*val) + (*ip - 'A' + 10); else if (*ip == ':') { ++ip; ++val; len += 2; *val = 0; if (*ip == ':') { /* insert 0 values */ while (seps <= 7) { ++val; len += 2; *val = 0; ++seps; } } else continue; } else if (*ip == '/') { masklen = atoi(ip+1); if (masklen > 128) masklen = 128; break; } else break; ++ip; } if (len != 16) return 0; /* write mask */ if (mask) { memset(mask, 0, len); val = (unsigned short*)mask; while (masklen) { if (masklen >= 16) { *val = 0xffff; masklen -= 16; } else { *val = - ((unsigned short)pow(2, 16 - masklen)); break; } ++val; } } } return len; } /* ** msOWSIpInList() ** ** Check if an ip is in a space separated list of IP addresses/ranges. ** Supports ipv4 and ipv6 addresses ** Ranges can be specified using the CIDR notation (ie: 192.100.100.0/24) ** ** Returns MS_TRUE if the IP is found. */ int msOWSIpInList(const char *ip_list, const char* ip) { int i, j, numips, iplen; unsigned char ip1[16]; unsigned char ip2[16]; unsigned char mask[16]; char** ips; /* Parse input IP */ iplen = msOWSIpParse(ip, (unsigned char*)&ip1, NULL); if (iplen != 4 && iplen != 16) /* ipv4 or ipv6 */ return MS_FALSE; ips = msStringSplit(ip_list, ' ', &numips); if (ips) { for (i = 0; i < numips; i++) { if (msOWSIpParse(ips[i], (unsigned char*)&ip2, (unsigned char*)&mask) == iplen) { for (j = 0; j < iplen; j++) { if ((ip1[j] & mask[j]) != (ip2[j] & mask[j])) break; } if (j == iplen) { msFreeCharArray(ips, numips); return MS_TRUE; /* match found */ } } } msFreeCharArray(ips, numips); } return MS_FALSE; } /* ** msOWSIpDisabled() ** ** Check if an ip is in a list specified in the metadata section. ** ** Returns MS_TRUE if the IP is found. */ int msOWSIpInMetadata(const char *ip_list, const char* ip) { FILE *stream; char buffer[MS_BUFFER_LENGTH]; int found = MS_FALSE; if (strncasecmp(ip_list, "file:", 5) == 0) { stream = fopen(ip_list + 5, "r"); if(stream) { found = MS_FALSE; while(fgets(buffer, MS_BUFFER_LENGTH, stream)) { if(msOWSIpInList(buffer, ip)) { found = MS_TRUE; break; } } fclose(stream); } } else { if(msOWSIpInList(ip_list, ip)) found = MS_TRUE; } return found; } /* ** msOWSIpDisabled() ** ** Check if the layers are enabled or disabled by IP list. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. ** ** Returns the disabled flag. */ int msOWSIpDisabled(hashTableObj *metadata, const char *namespaces, const char* ip) { const char *ip_list; int disabled = MS_FALSE; if (!ip) return MS_FALSE; /* no endpoint ip */ ip_list = msOWSLookupMetadata(metadata, namespaces, "allowed_ip_list"); if (!ip_list) ip_list = msOWSLookupMetadata(metadata, "O", "allowed_ip_list"); if (ip_list) { disabled = MS_TRUE; if (msOWSIpInMetadata(ip_list, ip)) disabled = MS_FALSE; } ip_list = msOWSLookupMetadata(metadata, namespaces, "denied_ip_list"); if (!ip_list) ip_list = msOWSLookupMetadata(metadata, "O", "denied_ip_list"); if (ip_list && msOWSIpInMetadata(ip_list, ip)) disabled = MS_TRUE; return disabled; } /* ** msOWSRequestIsEnabled() ** ** Check if a layer is visible for a specific OWS request. ** ** 'namespaces' is a string with a letter for each namespace to lookup in ** the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ If ** namespaces is NULL then this function just does a regular metadata ** lookup. If check_all_layers is set to MS_TRUE, the function will check ** all layers to see if the request is enable. (returns as soon as one is found) */ int msOWSRequestIsEnabled(mapObj *map, layerObj *layer, const char *namespaces, const char *request, int check_all_layers) { int disabled = MS_FALSE; /* explicitly disabled flag */ const char *enable_request; const char *remote_ip; if (request == NULL) return MS_FALSE; remote_ip = getenv("REMOTE_ADDR"); /* First, we check in the layer metadata */ if (layer && check_all_layers == MS_FALSE) { enable_request = msOWSLookupMetadata(&layer->metadata, namespaces, "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; enable_request = msOWSLookupMetadata(&layer->metadata, "O", "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; if (msOWSIpDisabled(&layer->metadata, namespaces, remote_ip)) return MS_FALSE; } if (map && (check_all_layers == MS_FALSE || map->numlayers == 0)) { /* then we check in the map metadata */ enable_request = msOWSLookupMetadata(&map->web.metadata, namespaces, "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; enable_request = msOWSLookupMetadata(&map->web.metadata, "O", "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; if (msOWSIpDisabled(&map->web.metadata, namespaces, remote_ip)) return MS_FALSE; } if (map && check_all_layers == MS_TRUE) { int i, globally_enabled = MS_FALSE; enable_request = msOWSLookupMetadata(&map->web.metadata, namespaces, "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!globally_enabled && !disabled) { enable_request = msOWSLookupMetadata(&map->web.metadata, "O", "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); } if (globally_enabled && msOWSIpDisabled(&map->web.metadata, namespaces, remote_ip)) globally_enabled = MS_FALSE; /* Check all layers */ for(i=0; inumlayers; i++) { int result = MS_FALSE; layerObj *lp; lp = (GET_LAYER(map, i)); enable_request = msOWSLookupMetadata(&lp->metadata, namespaces, "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; /* if the request has been explicitly set to disabled, continue */ if (!result && !disabled) { /* if the request has not been found in the wms metadata, */ /* check the ows namespace */ enable_request = msOWSLookupMetadata(&lp->metadata, "O", "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; } if (msOWSIpDisabled(&lp->metadata, namespaces, remote_ip)) continue; if (result || (!disabled && globally_enabled)) return MS_TRUE; } if (!disabled && globally_enabled) return MS_TRUE; } return MS_FALSE; } /* ** msOWSRequestLayersEnabled() ** ** Check if the layers are visible for a specific OWS request. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. ** ** Generates an array of the layer ids enabled. */ void msOWSRequestLayersEnabled(mapObj *map, const char *namespaces, const char *request, owsRequestObj *ows_request) { int disabled = MS_FALSE; /* explicitly disabled flag */ int globally_enabled = MS_FALSE; const char *enable_request; const char *remote_ip; if (ows_request->numlayers > 0) msFree(ows_request->enabled_layers); ows_request->numlayers = 0; ows_request->enabled_layers = NULL; if (request == NULL || (map == NULL) || (map->numlayers <= 0)) return; remote_ip = getenv("REMOTE_ADDR"); enable_request = msOWSLookupMetadata(&map->web.metadata, namespaces, "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!globally_enabled && !disabled) { enable_request = msOWSLookupMetadata(&map->web.metadata, "O", "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); } if (globally_enabled && msOWSIpDisabled(&map->web.metadata, namespaces, remote_ip)) globally_enabled = MS_FALSE; if (map->numlayers) { int i, layers_size = map->numlayers; /* for most of cases, this will be relatively small */ ows_request->enabled_layers = (int*)msSmallMalloc(sizeof(int)*layers_size); for(i=0; inumlayers; i++) { int result = MS_FALSE; layerObj *lp; lp = (GET_LAYER(map, i)); enable_request = msOWSLookupMetadata(&lp->metadata, namespaces, "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; /* if the request has been explicitly set to disabled, continue */ if (!result && !disabled) { /* if the request has not been found in the wms metadata, */ /* check the ows namespace */ enable_request = msOWSLookupMetadata(&lp->metadata, "O", "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; } if (msOWSIpDisabled(&lp->metadata, namespaces, remote_ip)) continue; if (result || (!disabled && globally_enabled)) { ows_request->enabled_layers[ows_request->numlayers] = lp->index; ows_request->numlayers++; } } if (ows_request->numlayers == 0) { msFree(ows_request->enabled_layers); ows_request->enabled_layers = NULL; } } } /* msOWSParseRequestMetadata * * This function parse a enable_request metadata string and check if the * given request is present and enabled. */ int msOWSParseRequestMetadata(const char *metadata, const char *request, int *disabled) { char requestBuffer[32]; int wordFlag = MS_FALSE; int disableFlag = MS_FALSE; int allFlag = MS_FALSE; char *bufferPtr, *ptr = NULL; int i; size_t len = 0; *disabled = MS_FALSE; if (metadata == NULL) return MS_FALSE; ptr = (char*)metadata; len = strlen(ptr); requestBuffer[0] = '\0'; bufferPtr = requestBuffer; for (i=0; i<=len; ++i,++ptr) { if (!wordFlag && isspace(*ptr)) continue; wordFlag = MS_TRUE; if (*ptr == '!') { disableFlag = MS_TRUE; continue; } else if ( (*ptr == ' ') || (*ptr != '\0' && ptr[1] == '\0')) { /* end of word */ if (ptr[1] == '\0' && *ptr != ' ') { *bufferPtr = *ptr; ++bufferPtr; } *bufferPtr = '\0'; if (strcasecmp(request, requestBuffer) == 0) { *disabled = MS_TRUE; /* explicitly found, will stop the process in msOWSRequestIsEnabled() */ return (disableFlag ? MS_FALSE:MS_TRUE); } else { if (strcmp("*", requestBuffer) == 0) { /* check if we read the all flag */ if (disableFlag) *disabled = MS_TRUE; allFlag = disableFlag ? MS_FALSE:MS_TRUE; } /* reset flags */ wordFlag = MS_FALSE; disableFlag = MS_FALSE; bufferPtr = requestBuffer; } } else { *bufferPtr = *ptr; ++bufferPtr; } } return allFlag; } /* ** msOWSLookupMetadata() ** ** Attempts to lookup a given metadata name in multiple OWS namespaces. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. */ const char *msOWSLookupMetadata(hashTableObj *metadata, const char *namespaces, const char *name) { const char *value = NULL; if (namespaces == NULL) { value = msLookupHashTable(metadata, (char*)name); } else { char buf[100] = "ows_"; strlcpy(buf+4, name, 96); while (value == NULL && *namespaces != '\0') { switch (*namespaces) { case 'O': /* ows_... */ buf[0] = 'o'; buf[1] = 'w'; buf[2] = 's'; break; case 'M': /* wms_... */ buf[0] = 'w'; buf[1] = 'm'; buf[2] = 's'; break; case 'F': /* wfs_... */ buf[0] = 'w'; buf[1] = 'f'; buf[2] = 's'; break; case 'C': /* wcs_... */ buf[0] = 'w'; buf[1] = 'c'; buf[2] = 's'; break; case 'G': /* gml_... */ buf[0] = 'g'; buf[1] = 'm'; buf[2] = 'l'; break; case 'S': /* sos_... */ buf[0] = 's'; buf[1] = 'o'; buf[2] = 's'; break; default: /* We should never get here unless an invalid code (typo) is */ /* present in the code, but since this happened before... */ msSetError(MS_WMSERR, "Unsupported metadata namespace code (%c).", "msOWSLookupMetadata()", *namespaces ); assert(MS_FALSE); return NULL; } value = msLookupHashTable(metadata, buf); namespaces++; } } return value; } /* ** msOWSLookupMetadataWithLanguage() ** ** Attempts to lookup a given metadata name in multiple OWS namespaces ** for a specific language. */ const char *msOWSLookupMetadataWithLanguage(hashTableObj *metadata, const char *namespaces, const char *name, const char* validated_language) { const char *value = NULL; char *name2 = NULL; size_t bufferSize = 0; if ( name && validated_language ) { bufferSize = strlen(name)+strlen(validated_language)+2; name2 = (char *) msSmallMalloc( bufferSize ); snprintf(name2, bufferSize, "%s.%s", name, validated_language); value = msOWSLookupMetadata(metadata, namespaces, name2); } if (value == NULL) { value = msOWSLookupMetadata(metadata, namespaces, name); } msFree( name2 ); return value; } /* ** msOWSLookupMetadata2() ** ** Attempts to lookup a given metadata name in multiple hashTables, and ** in multiple OWS namespaces within each. First searches the primary ** table and if no result is found, attempts the search using the ** secondary (fallback) table. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. */ const char *msOWSLookupMetadata2(hashTableObj *pri, hashTableObj *sec, const char *namespaces, const char *name) { const char *result; if ((result = msOWSLookupMetadata(pri, namespaces, name)) == NULL) { /* Try the secondary table */ result = msOWSLookupMetadata(sec, namespaces, name); } return result; } /* msOWSParseVersionString() ** ** Parse a version string in the format "a.b.c" or "a.b" and return an ** integer in the format 0x0a0b0c suitable for regular integer comparisons. ** ** Returns one of OWS_VERSION_NOTSET or OWS_VERSION_BADFORMAT if version ** could not be parsed. */ int msOWSParseVersionString(const char *pszVersion) { char **digits = NULL; int numDigits = 0; if (pszVersion) { int nVersion = 0; digits = msStringSplit(pszVersion, '.', &numDigits); if (digits == NULL || numDigits < 2 || numDigits > 3) { msSetError(MS_OWSERR, "Invalid version (%s). Version must be in the " "format 'x.y' or 'x.y.z'", "msOWSParseVersionString()", pszVersion); if (digits) msFreeCharArray(digits, numDigits); return OWS_VERSION_BADFORMAT; } nVersion = atoi(digits[0])*0x010000; nVersion += atoi(digits[1])*0x0100; if (numDigits > 2) nVersion += atoi(digits[2]); msFreeCharArray(digits, numDigits); return nVersion; } return OWS_VERSION_NOTSET; } /* msOWSGetVersionString() ** ** Returns a OWS version string in the format a.b.c from the integer ** version value passed as argument (0x0a0b0c) ** ** Fills in the pszBuffer and returns a reference to it. Recommended buffer ** size is OWS_VERSION_MAXLEN chars. */ const char *msOWSGetVersionString(int nVersion, char *pszBuffer) { if (pszBuffer) snprintf(pszBuffer, OWS_VERSION_MAXLEN-1, "%d.%d.%d", (nVersion/0x10000)%0x100, (nVersion/0x100)%0x100, nVersion%0x100); return pszBuffer; } #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR) #if !defined(USE_PROJ) #error "PROJ.4 is required for WMS, WFS, WCS and SOS Server Support." #endif /* ** msRenameLayer() */ static int msRenameLayer(layerObj *lp, int count) { char *newname; newname = (char*)malloc((strlen(lp->name)+5)*sizeof(char)); if (!newname) { msSetError(MS_MEMERR, NULL, "msRenameLayer()"); return MS_FAILURE; } sprintf(newname, "%s_%2.2d", lp->name, count); free(lp->name); lp->name = newname; return MS_SUCCESS; } /* ** msOWSMakeAllLayersUnique() */ int msOWSMakeAllLayersUnique(mapObj *map) { int i, j; /* Make sure all layers in the map file have valid and unique names */ for(i=0; inumlayers; i++) { int count=1; for(j=i+1; jnumlayers; j++) { if (GET_LAYER(map, i)->name == NULL || GET_LAYER(map, j)->name == NULL) { continue; } if (strcasecmp(GET_LAYER(map, i)->name, GET_LAYER(map, j)->name) == 0 && msRenameLayer((GET_LAYER(map, j)), ++count) != MS_SUCCESS) { return MS_FAILURE; } } /* Don't forget to rename the first layer if duplicates were found */ if (count > 1 && msRenameLayer((GET_LAYER(map, i)), 1) != MS_SUCCESS) { return MS_FAILURE; } } return MS_SUCCESS; } /* ** msOWSNegotiateVersion() ** ** returns the most suitable version an OWS is to support given a client ** version parameter. ** ** supported_versions must be ordered from highest to lowest ** ** Returns a version integer of the supported version ** */ int msOWSNegotiateVersion(int requested_version, int supported_versions[], int num_supported_versions) { int i; /* if version is not set return highest version */ if (! requested_version) return supported_versions[0]; /* if the requested version is lower than the lowest version return the lowest version */ if (requested_version < supported_versions[num_supported_versions-1]) return supported_versions[num_supported_versions-1]; /* return the first entry that's lower than or equal to the requested version */ for (i = 0; i < num_supported_versions; i++) { if (supported_versions[i] <= requested_version) return supported_versions[i]; } return requested_version; } /* ** msOWSTerminateOnlineResource() ** ** Append trailing "?" or "&" to an onlineresource URL if it doesn't have ** one already. The returned string is then ready to append GET parameters ** to it. ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char * msOWSTerminateOnlineResource(const char *src_url) { char *online_resource = NULL; size_t buffer_size = 0; if (src_url == NULL) return NULL; buffer_size = strlen(src_url)+2; online_resource = (char*) malloc(buffer_size); if (online_resource == NULL) { msSetError(MS_MEMERR, NULL, "msOWSTerminateOnlineResource()"); return NULL; } strlcpy(online_resource, src_url, buffer_size); /* Append trailing '?' or '&' if missing. */ if (strchr(online_resource, '?') == NULL) strlcat(online_resource, "?", buffer_size); else { char *c; c = online_resource+strlen(online_resource)-1; if (*c != '?' && *c != '&') strlcpy(c+1, "&", buffer_size-strlen(online_resource)); } return online_resource; } /* ** msOWSGetOnlineResource() ** ** Return the online resource for this service. First try to lookup ** specified metadata, and if not found then try to build the URL ourselves. ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char * msOWSGetOnlineResource(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req) { const char *value; char *online_resource = NULL; /* We need this script's URL, including hostname. */ /* Default to use the value of the "onlineresource" metadata, and if not */ /* set then build it: "http://$(SERVER_NAME):$(SERVER_PORT)$(SCRIPT_NAME)?" */ /* (+append the map=... param if it was explicitly passed in QUERY_STRING) */ /* */ if ((value = msOWSLookupMetadata(&(map->web.metadata), namespaces, metadata_name))) { online_resource = msOWSTerminateOnlineResource(value); } else { if ((online_resource = msBuildOnlineResource(map, req)) == NULL) { msSetError(MS_CGIERR, "Impossible to establish server URL. Please set \"%s\" metadata.", "msOWSGetOnlineResource()", metadata_name); return NULL; } } return online_resource; } /* ** msOWSGetOnlineResource() ** ** Return the online resource for this service and add language parameter. ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char * msOWSGetOnlineResource2(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req, const char* validated_language) { char *online_resource = msOWSGetOnlineResource(map, namespaces, metadata_name, req); if ( online_resource && validated_language ) { /* online_resource is already terminated, so we can simply add language=...& */ /* but first we need to make sure that online_resource has enough capacity */ online_resource = (char *)msSmallRealloc(online_resource, strlen(online_resource) + strlen(validated_language) + 11); strcat(online_resource, "language="); strcat(online_resource, validated_language); strcat(online_resource, "&"); } return online_resource; } /* msOWSGetSchemasLocation() ** ** schemas location is the root of the web tree where all WFS-related ** schemas can be found on this server. These URLs must exist in order ** to validate xml. ** ** Use value of "ows_schemas_location" metadata, if not set then ** return ".." as a default */ const char *msOWSGetSchemasLocation(mapObj *map) { const char *schemas_location; schemas_location = msLookupHashTable(&(map->web.metadata), "ows_schemas_location"); if (schemas_location == NULL) schemas_location = OWS_DEFAULT_SCHEMAS_LOCATION; return schemas_location; } /* msOWSGetLanguage() ** ** returns the language via MAP/WEB/METADATA/ows_language ** ** Use value of "ows_language" metadata, if not set then ** return "undefined" as a default */ const char *msOWSGetLanguage(mapObj *map, const char *context) { const char *language; /* if this is an exception, MapServer always returns Exception messages in en-US */ if (strcmp(context,"exception") == 0) { language = MS_ERROR_LANGUAGE; } /* if not, fetch language from mapfile metadata */ else { language = msLookupHashTable(&(map->web.metadata), "ows_language"); if (language == NULL) { language = "undefined"; } } return language; } /* msOWSGetLanguageList ** ** Returns the list of languages that this service supports ** ** Use value of "languages" metadata (comma-separated list), or NULL if not set ** ** Returns a malloced char** of length numitems which must be freed ** by the caller, or NULL (with numitems = 0) */ char **msOWSGetLanguageList(mapObj *map, const char *namespaces, int *numitems) { const char *languages = NULL; languages = msOWSLookupMetadata(&(map->web.metadata), namespaces, "languages"); if (languages && strlen(languages) > 0) { return msStringSplit(languages, ',', numitems); } else { *numitems = 0; return NULL; } } /* msOWSGetLanguageFromList ** ** Returns a language according to the language requested by the client ** ** If the requested language is in the languages metadata then use it, ** otherwise ignore it and use the defaul language, which is the first entry in ** the languages metadata list. Calling with a NULL requested_langauge ** therefore returns this default language. If the language metadata list is ** not defined then the language is set to NULL. ** ** Returns a malloced char* which must be freed by the caller, or NULL */ char *msOWSGetLanguageFromList(mapObj *map, const char *namespaces, const char *requested_language) { int num_items = 0; char **languages = msOWSGetLanguageList(map, namespaces, &num_items); char *language = NULL; if( languages && num_items > 0 ) { if ( !requested_language || !msStringInArray( requested_language, languages, num_items) ) { language = msStrdup(languages[0]); } else { language = msStrdup(requested_language); } } msFreeCharArray(languages, num_items); return language; } /* msOWSPrintInspireCommonExtendedCapabilities ** ** Output INSPIRE common extended capabilities items to stream ** The currently supported items are metadata and languages ** ** tag_name is the name (including ns prefix) of the tag to include the whole ** extended capabilities block in ** ** service is currently included for future compatibility when differing ** extended capabilities elements are included for different service types ** ** Returns a status code; MS_NOERR if all ok, action_if_not_found otherwise */ int msOWSPrintInspireCommonExtendedCapabilities(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const char *tag_name, const char *validated_language, const int service) { int metadataStatus = 0; int languageStatus = 0; msIO_fprintf(stream, " <%s>\n", tag_name); metadataStatus = msOWSPrintInspireCommonMetadata(stream, map, namespaces, action_if_not_found); languageStatus = msOWSPrintInspireCommonLanguages(stream, map, namespaces, action_if_not_found, validated_language); msIO_fprintf(stream, " \n", tag_name); return (metadataStatus != MS_NOERR) ? metadataStatus : languageStatus; } /* msOWSPrintInspireCommonMetadata ** ** Output INSPIRE common metadata items to a stream ** ** Returns a status code; MS_NOERR if all OK, action_if_not_found otherwise */ int msOWSPrintInspireCommonMetadata(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found) { int status = MS_NOERR; const char *inspire_capabilities = NULL; inspire_capabilities = msOWSLookupMetadata(&(map->web.metadata), namespaces, "inspire_capabilities"); if(!inspire_capabilities) { if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n"); } return action_if_not_found; } if (strcasecmp("url",inspire_capabilities) == 0) { if ( msOWSLookupMetadata(&(map->web.metadata), namespaces, "inspire_metadataurl_href") != NULL ) { msIO_fprintf(stream, " \n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_metadataurl_href", OWS_WARN, " %s\n", ""); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_metadataurl_format", OWS_WARN, " %s\n", ""); msIO_fprintf(stream, " \n"); } else { status = action_if_not_found; if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), "inspire_metadataurl_href"); } } } else if (strcasecmp("embed",inspire_capabilities) == 0) { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_resourcelocator", OWS_NOERR, " \n %s\n \n", NULL); msIO_fprintf(stream," service\n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_temporal_reference", OWS_WARN, " \n %s\n \n", ""); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " -\n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_temporal_reference", OWS_NOERR, " %s\n", ""); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " notEvaluated\n"); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " \n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_mpoc_name", OWS_WARN, " %s\n", ""); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_mpoc_email", OWS_WARN, " %s\n", ""); msIO_fprintf(stream, " \n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_metadatadate", OWS_WARN, " %s\n", ""); msIO_fprintf(stream," view\n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_keyword", OWS_WARN, " \n %s\n \n", ""); } else { status = action_if_not_found; if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n", inspire_capabilities); } } return status; } /* msOWSPrintInspireCommonLanguages ** ** Output INSPIRE supported languages block to stream ** ** Returns a status code; MS_NOERR if all OK; action_if_not_found otherwise */ int msOWSPrintInspireCommonLanguages(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const char *validated_language) { char *buffer = NULL; /* temp variable for malloced strings that will need freeing */ int status = MS_NOERR; char *default_language = msOWSGetLanguageFromList(map, namespaces, NULL); if(validated_language && default_language) { msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " %s" "\n", buffer = msEncodeHTMLEntities(default_language)); msFree(buffer); /* append _exclude to our default_language*/ default_language = msSmallRealloc(default_language,strlen(default_language)+strlen("_exclude")+1); strcat(default_language,"_exclude"); msOWSPrintEncodeMetadataList(stream, &(map->web.metadata), namespaces, "languages", NULL, NULL, " %s" "\n", default_language); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " %s" "\n", validated_language); } else { status = action_if_not_found; if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), "languages"); } } msFree(default_language); return status; } /* ** msOWSPrintMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. */ int msOWSPrintMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { const char *value = NULL; int status = MS_NOERR; if((value = msOWSLookupMetadata(metadata, namespaces, name)) != NULL) { msIO_fprintf(stream, format, value); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } if (default_value) msIO_fprintf(stream, format, default_value); } return status; } /* ** msOWSPrintEncodeMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. ** Also encode the value with msEncodeHTMLEntities. */ int msOWSPrintEncodeMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { return msOWSPrintEncodeMetadata2(stream, metadata, namespaces, name, action_if_not_found, format, default_value, NULL); } /* ** msOWSPrintEncodeMetadata2() ** ** Attempt to output a capability item in the requested language. ** Fallback using no language parameter. */ int msOWSPrintEncodeMetadata2(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language) { const char *value; char * pszEncodedValue=NULL; int status = MS_NOERR; if((value = msOWSLookupMetadataWithLanguage(metadata, namespaces, name, validated_language))) { pszEncodedValue = msEncodeHTMLEntities(value); msIO_fprintf(stream, format, pszEncodedValue); free(pszEncodedValue); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name, (validated_language?".":""), (validated_language?validated_language:"")); status = action_if_not_found; } if (default_value) { pszEncodedValue = msEncodeHTMLEntities(default_value); msIO_fprintf(stream, format, default_value); free(pszEncodedValue); } } return status; } /* ** msOWSGetEncodeMetadata() ** ** Equivalent to msOWSPrintEncodeMetadata. Returns en encoded value of the ** metadata or the default value. ** Caller should free the returned string. */ char *msOWSGetEncodeMetadata(hashTableObj *metadata, const char *namespaces, const char *name, const char *default_value) { const char *value; char * pszEncodedValue=NULL; if((value = msOWSLookupMetadata(metadata, namespaces, name))) pszEncodedValue = msEncodeHTMLEntities(value); else if (default_value) pszEncodedValue = msEncodeHTMLEntities(default_value); return pszEncodedValue; } /* ** msOWSPrintValidateMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. ** Also validate the value with msIsXMLTagValid. */ int msOWSPrintValidateMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { const char *value; int status = MS_NOERR; if((value = msOWSLookupMetadata(metadata, namespaces, name))) { if(msIsXMLTagValid(value) == MS_FALSE) msIO_fprintf(stream, "\n", value); msIO_fprintf(stream, format, value); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } if (default_value) { if(msIsXMLTagValid(default_value) == MS_FALSE) msIO_fprintf(stream, "\n", default_value); msIO_fprintf(stream, format, default_value); } } return status; } /* ** msOWSPrintGroupMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. */ int msOWSPrintGroupMetadata(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { return msOWSPrintGroupMetadata2(stream, map, pszGroupName, namespaces, name, action_if_not_found, format, default_value, NULL); } /* ** msOWSPrintGroupMetadata2() ** ** Attempt to output a capability item in the requested language. ** Fallback using no language parameter. */ int msOWSPrintGroupMetadata2(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language) { const char *value; char *encoded; int status = MS_NOERR; int i; for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->group && (strcmp(GET_LAYER(map, i)->group, pszGroupName) == 0) && &(GET_LAYER(map, i)->metadata)) { if((value = msOWSLookupMetadataWithLanguage(&(GET_LAYER(map, i)->metadata), namespaces, name, validated_language))) { encoded = msEncodeHTMLEntities(value); msIO_fprintf(stream, format, encoded); msFree(encoded); return status; } } } if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } if (default_value) { encoded = msEncodeHTMLEntities(default_value); msIO_fprintf(stream, format, encoded); msFree(encoded); } return status; } /* msOWSPrintURLType() ** ** Attempt to output a URL item in capabilties. If corresponding metadata ** is not found then one of a number of predefined actions will be taken. ** Since it's a capability item, five metadata will be used to populate the ** XML elements. ** ** The 'name' argument is the basename of the metadata items relating to this ** URL type and the suffixes _type, _width, _height, _format and _href will ** be appended to the name in the metadata search. ** e.g. passing name=metadataurl will result in the following medata entries ** being used: ** ows_metadataurl_type ** ows_metadataurl_format ** ows_metadataurl_href ** ... (width and height are unused for metadata) ** ** As for all the msOWSPrint*() functions, the namespace argument specifies ** which prefix (ows_, wms_, wcs_, etc.) is used for the metadata names above. ** ** Then the final string will be built from ** the tag_name and the five metadata. The template is: ** %href ** ** For example the width format will usually be " width=\"%s\"". ** An extern format will be "> %s\n", tag_name); if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } } else { if(!type && type_format && default_type) { buffer_size_tmp = strlen(type_format) + strlen(default_type) + 2; type = (char*) malloc(buffer_size_tmp); snprintf(type, buffer_size_tmp, type_format, default_type); } else if(!type) type = msStrdup(""); if(!width && width_format && default_width) { buffer_size_tmp = strlen(width_format) + strlen(default_width) + 2; width = (char*) malloc(buffer_size_tmp); snprintf(width, buffer_size_tmp, width_format, default_width); } else if(!width) width = msStrdup(""); if(!height && height_format && default_height) { buffer_size_tmp = strlen(height_format) + strlen(default_height) + 2; height = (char*) malloc(buffer_size_tmp); snprintf(height, buffer_size_tmp, height_format, default_height); } else if(!height) height = msStrdup(""); if(!urlfrmt && urlfrmt_format && default_urlfrmt) { buffer_size_tmp = strlen(urlfrmt_format) + strlen(default_urlfrmt) + 2; urlfrmt = (char*) malloc(buffer_size_tmp); snprintf(urlfrmt, buffer_size_tmp, urlfrmt_format, default_urlfrmt); } else if(!urlfrmt) urlfrmt = msStrdup(""); if(!href && href_format && default_href) { buffer_size_tmp = strlen(href_format) + strlen(default_href) + 2; href = (char*) malloc(buffer_size_tmp); snprintf(href, buffer_size_tmp, href_format, default_href); } else if(!href) href = msStrdup(""); if(tag_format == NULL) msIO_fprintf(stream, "%s<%s%s%s%s%s>%s\n", tabspace, tag_name, type, width, height, urlfrmt, href, tag_name); else msIO_fprintf(stream, tag_format, type, width, height, urlfrmt, href); } msFree(type); msFree(width); msFree(height); msFree(urlfrmt); msFree(href); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } } return status; } /* msOWSPrintParam() ** ** Same as printMetadata() but applied to mapfile parameters. **/ int msOWSPrintParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value) { int status = MS_NOERR; if(value && strlen(value) > 0) { msIO_fprintf(stream, format, value); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", name); status = action_if_not_found; } if (default_value) msIO_fprintf(stream, format, default_value); } return status; } /* msOWSPrintEncodeParam() ** ** Same as printEncodeMetadata() but applied to mapfile parameters. **/ int msOWSPrintEncodeParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value) { int status = MS_NOERR; char *encode; if(value && strlen(value) > 0) { encode = msEncodeHTMLEntities(value); msIO_fprintf(stream, format, encode); msFree(encode); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", name); status = action_if_not_found; } if (default_value) { encode = msEncodeHTMLEntities(default_value); msIO_fprintf(stream, format, encode); msFree(encode); } } return status; } /* msOWSPrintMetadataList() ** ** Prints comma-separated lists metadata. (e.g. keywordList) ** default_value serves 2 purposes if specified: ** - won't be printed if part of MetadataList (default_value == key"_exclude") ** (exclusion) ** - will be printed if MetadataList is empty (fallback) **/ int msOWSPrintMetadataList(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, const char *startTag, const char *endTag, const char *itemFormat, const char *default_value) { const char *value; value = msOWSLookupMetadata(metadata, namespaces, name); if(value == NULL) { value = default_value; default_value = NULL; } if(value != NULL) { char **keywords; int numkeywords; keywords = msStringSplit(value, ',', &numkeywords); if(keywords && numkeywords > 0) { int kw; if(startTag) msIO_fprintf(stream, "%s", startTag); for(kw=0; kw 0) { int kw; if(startTag) msIO_fprintf(stream, "%s", startTag); for(kw=0; kw 0) items = msStringSplit(value, delimiter, &numitems); else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", name); status = action_if_not_found; } if (default_value) items = msStringSplit(default_value, delimiter, &numitems); } if(items && numitems > 0) { if(startTag) msIO_fprintf(stream, "%s", startTag); for(i=0; inumargs > 0 && !pj_is_latlong(srcproj->proj)) { projectionObj wgs84; msInitProjection(&wgs84); msLoadProjectionString(&wgs84, "+proj=longlat +ellps=WGS84 +datum=WGS84"); msProjectRect(srcproj, &wgs84, ext); msFreeProjection(&wgs84); } } /* ** msOWSPrintEX_GeographicBoundingBox() ** ** Print a EX_GeographicBoundingBox tag for WMS1.3.0 ** */ void msOWSPrintEX_GeographicBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj) { const char *pszTag = "EX_GeographicBoundingBox"; /* The default for WMS */ rectObj ext; ext = *extent; /* always project to lat long */ msOWSProjectToWGS84(srcproj, &ext); msIO_fprintf(stream, "%s<%s>\n", tabspace, pszTag); msIO_fprintf(stream, "%s %g\n", tabspace, ext.minx); msIO_fprintf(stream, "%s %g\n", tabspace, ext.maxx); msIO_fprintf(stream, "%s %g\n", tabspace, ext.miny); msIO_fprintf(stream, "%s %g\n", tabspace, ext.maxy); msIO_fprintf(stream, "%s\n", tabspace, pszTag); /* msIO_fprintf(stream, "%s<%s minx=\"%g\" miny=\"%g\" maxx=\"%g\" maxy=\"%g\" />\n", tabspace, pszTag, ext.minx, ext.miny, ext.maxx, ext.maxy); */ } /* ** msOWSPrintLatLonBoundingBox() ** ** Print a LatLonBoundingBox tag for WMS, or LatLongBoundingBox for WFS ** ... yes, the tag name differs between WMS and WFS, yuck! ** */ void msOWSPrintLatLonBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, projectionObj *wfsproj, int nService) { const char *pszTag = "LatLonBoundingBox"; /* The default for WMS */ rectObj ext; ext = *extent; if (nService == OWS_WMS) { /* always project to lat long */ msOWSProjectToWGS84(srcproj, &ext); } else if (nService == OWS_WFS) { /* called from wfs 1.0.0 only: project to map srs, if set */ pszTag = "LatLongBoundingBox"; if (wfsproj) { if (msProjectionsDiffer(srcproj, wfsproj) == MS_TRUE) msProjectRect(srcproj, wfsproj, &ext); } } msIO_fprintf(stream, "%s<%s minx=\"%g\" miny=\"%g\" maxx=\"%g\" maxy=\"%g\" />\n", tabspace, pszTag, ext.minx, ext.miny, ext.maxx, ext.maxy); } /* ** Emit a bounding box if we can find projection information. ** If _bbox_extended is not set, emit a single bounding box ** using the layer's native SRS (ignoring any _srs metadata). ** ** If _bbox_extended is set to true, emit a bounding box ** for every projection listed in the _srs list. ** Check the map level metadata for both _bbox_extended and _srs, ** if there is no such metadata at the layer level. ** (These settings make more sense at the global/map level anyways) */ void msOWSPrintBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, hashTableObj *layer_meta, hashTableObj *map_meta, const char *namespaces, int wms_version) { const char *value, *resx, *resy, *wms_bbox_extended, *epsg_str; char *encoded, *encoded_resx, *encoded_resy; char **epsgs; int i, num_epsgs; projectionObj proj; rectObj ext; wms_bbox_extended = msOWSLookupMetadata2(layer_meta, map_meta, namespaces, "bbox_extended"); if( wms_bbox_extended && strncasecmp(wms_bbox_extended, "true", 5) == 0 ) { /* get a list of all projections from the metadata try the layer metadata first, otherwise use the map's */ if( msOWSLookupMetadata(layer_meta, namespaces, "srs") ) { epsg_str = msOWSGetEPSGProj(srcproj, layer_meta, namespaces, MS_FALSE); } else { epsg_str = msOWSGetEPSGProj(srcproj, map_meta, namespaces, MS_FALSE); } epsgs = msStringSplit(epsg_str, ' ', &num_epsgs); } else { /* Look for EPSG code in PROJECTION block only. "wms_srs" metadata cannot be * used to establish the native projection of a layer for BoundingBox purposes. */ epsgs = (char **) msSmallMalloc(sizeof(char *)); num_epsgs = 1; epsgs[0] = msStrdup( msOWSGetEPSGProj(srcproj, layer_meta, namespaces, MS_TRUE) ); } for( i = 0; i < num_epsgs; i++) { value = epsgs[i]; memcpy(&ext, extent, sizeof(rectObj)); /* reproject the extents for each SRS's bounding box */ msInitProjection(&proj); if (msLoadProjectionStringEPSG(&proj, (char *)value) == 0) { if (msProjectionsDiffer(srcproj, &proj) == MS_TRUE) { msProjectRect(srcproj, &proj, &ext); } /*for wms 1.3.0 we need to make sure that we present the BBOX with a reversed axes for some espg codes*/ if (wms_version >= OWS_1_3_0 && value && strncasecmp(value, "EPSG:", 5) == 0) { msAxisNormalizePoints( &proj, 1, &(ext.minx), &(ext.miny) ); msAxisNormalizePoints( &proj, 1, &(ext.maxx), &(ext.maxy) ); } } msFreeProjection( &proj ); if( value != NULL ) { encoded = msEncodeHTMLEntities(value); if (wms_version >= OWS_1_3_0) msIO_fprintf(stream, "%s\n" ); } } msFreeCharArray(epsgs, num_epsgs); } /* ** Print the contact information */ void msOWSPrintContactInfo( FILE *stream, const char *tabspace, int nVersion, hashTableObj *metadata, const char *namespaces ) { /* contact information is a required element in 1.0.7 but the */ /* sub-elements such as ContactPersonPrimary, etc. are not! */ /* In 1.1.0, ContactInformation becomes optional. */ if (nVersion > OWS_1_0_0) { msIO_fprintf(stream, "%s\n", tabspace); /* ContactPersonPrimary is optional, but when present then all its */ /* sub-elements are mandatory */ if(msOWSLookupMetadata(metadata, namespaces, "contactperson") || msOWSLookupMetadata(metadata, namespaces, "contactorganization")) { msIO_fprintf(stream, "%s \n", tabspace); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactperson", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactorganization", OWS_WARN, " %s\n", NULL); msIO_fprintf(stream, "%s \n", tabspace); } if(msOWSLookupMetadata(metadata, namespaces, "contactposition")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactposition", OWS_NOERR, " %s\n", NULL); } /* ContactAdress is optional, but when present then all its */ /* sub-elements are mandatory */ if(msOWSLookupMetadata( metadata, namespaces, "addresstype" ) || msOWSLookupMetadata( metadata, namespaces, "address" ) || msOWSLookupMetadata( metadata, namespaces, "city" ) || msOWSLookupMetadata( metadata, namespaces, "stateorprovince" ) || msOWSLookupMetadata( metadata, namespaces, "postcode" ) || msOWSLookupMetadata( metadata, namespaces, "country" )) { msIO_fprintf(stream, "%s \n", tabspace); msOWSPrintEncodeMetadata(stream, metadata, namespaces,"addresstype", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "address", OWS_WARN, "
%s
\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "city", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "stateorprovince", OWS_WARN," %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "postcode", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "country", OWS_WARN, " %s\n", NULL); msIO_fprintf(stream, "%s
\n", tabspace); } if(msOWSLookupMetadata(metadata, namespaces, "contactvoicetelephone")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactvoicetelephone", OWS_NOERR, " %s\n", NULL); } if(msOWSLookupMetadata(metadata, namespaces, "contactfacsimiletelephone")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactfacsimiletelephone", OWS_NOERR, " %s\n", NULL); } if(msOWSLookupMetadata(metadata, namespaces, "contactelectronicmailaddress")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactelectronicmailaddress", OWS_NOERR, " %s\n", NULL); } msIO_fprintf(stream, "%s
\n", tabspace); } } /* ** msOWSGetLayerExtent() ** ** Try to establish layer extent, first looking for "ows_extent" metadata, and ** if not found then call msLayerGetExtent() which will lookup the ** layer->extent member, and if not found will open layer to read extent. ** */ int msOWSGetLayerExtent(mapObj *map, layerObj *lp, const char *namespaces, rectObj *ext) { const char *value; if ((value = msOWSLookupMetadata(&(lp->metadata), namespaces, "extent")) != NULL) { char **tokens; int n; tokens = msStringSplit(value, ' ', &n); if (tokens==NULL || n != 4) { msSetError(MS_WMSERR, "Wrong number of arguments for EXTENT metadata.", "msOWSGetLayerExtent()"); return MS_FAILURE; } ext->minx = atof(tokens[0]); ext->miny = atof(tokens[1]); ext->maxx = atof(tokens[2]); ext->maxy = atof(tokens[3]); msFreeCharArray(tokens, n); return MS_SUCCESS; } else { return msLayerGetExtent(lp, ext); } return MS_FAILURE; } /********************************************************************** * msOWSExecuteRequests() * * Execute a number of WFS/WMS HTTP requests in parallel, and then * update layerObj information with the result of the requests. **********************************************************************/ int msOWSExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, mapObj *map, int bCheckLocalCache) { int nStatus, iReq; /* Execute requests */ #if defined(USE_CURL) nStatus = msHTTPExecuteRequests(pasReqInfo, numRequests, bCheckLocalCache); #else msSetError(MS_WMSERR, "msOWSExecuteRequests() called apparently without libcurl configured, msHTTPExecuteRequests() not available.", "msOWSExecuteRequests()"); return MS_FAILURE; #endif /* Scan list of layers and call the handler for each layer type to */ /* pass them the request results. */ for(iReq=0; iReq= 0 && pasReqInfo[iReq].nLayerId < map->numlayers) { layerObj *lp; lp = GET_LAYER(map, pasReqInfo[iReq].nLayerId); if (lp->connectiontype == MS_WFS) msWFSUpdateRequestInfo(lp, &(pasReqInfo[iReq])); } } return nStatus; } /********************************************************************** * msOWSProcessException() * **********************************************************************/ void msOWSProcessException(layerObj *lp, const char *pszFname, int nErrorCode, const char *pszFuncName) { FILE *fp; if ((fp = fopen(pszFname, "r")) != NULL) { char *pszBuf=NULL; int nBufSize=0; char *pszStart, *pszEnd; fseek(fp, 0, SEEK_END); nBufSize = ftell(fp); rewind(fp); pszBuf = (char*)malloc((nBufSize+1)*sizeof(char)); if (pszBuf == NULL) { msSetError(MS_MEMERR, NULL, "msOWSProcessException()"); fclose(fp); return; } if ((int) fread(pszBuf, 1, nBufSize, fp) != nBufSize) { msSetError(MS_IOERR, NULL, "msOWSProcessException()"); free(pszBuf); fclose(fp); return; } pszBuf[nBufSize] = '\0'; /* OK, got the data in the buffer. Look for the tags */ if ((strstr(pszBuf, "") && /* WFS style */ (pszStart = strstr(pszBuf, "")) && (pszEnd = strstr(pszStart, "")) ) || (strstr(pszBuf, "") && /* WMS style */ (pszStart = strstr(pszBuf, "")) && (pszEnd = strstr(pszStart, "")) )) { pszStart = strchr(pszStart, '>')+1; *pszEnd = '\0'; msSetError(nErrorCode, "Got Remote Server Exception for layer %s: %s", pszFuncName, lp->name?lp->name:"(null)", pszStart); } else { msSetError(MS_WFSCONNERR, "Unable to parse Remote Server Exception Message for layer %s.", pszFuncName, lp->name?lp->name:"(null)"); } free(pszBuf); fclose(fp); } } /********************************************************************** * msOWSBuildURLFilename() * * Build a unique filename for this URL to use in caching remote server * requests. Slashes and illegal characters will be turned into '_' * * Returns a newly allocated buffer that should be freed by the caller or * NULL in case of error. **********************************************************************/ char *msOWSBuildURLFilename(const char *pszPath, const char *pszURL, const char *pszExt) { char *pszBuf, *pszPtr; int i; size_t nBufLen = 0; nBufLen = strlen(pszURL) + strlen(pszExt) +2; if (pszPath) nBufLen += (strlen(pszPath)+1); pszBuf = (char*)malloc(nBufLen); if (pszBuf == NULL) { msSetError(MS_MEMERR, NULL, "msOWSBuildURLFilename()"); return NULL; } pszBuf[0] = '\0'; if (pszPath) { #ifdef _WIN32 if (pszPath[strlen(pszPath) -1] != '/' && pszPath[strlen(pszPath) -1] != '\\') snprintf(pszBuf, nBufLen, "%s\\", pszPath); else snprintf(pszBuf, nBufLen, "%s", pszPath); #else if (pszPath[strlen(pszPath) -1] != '/') snprintf(pszBuf, nBufLen, "%s/", pszPath); else snprintf(pszBuf, nBufLen, "%s", pszPath); #endif } pszPtr = pszBuf + strlen(pszBuf); for(i=0; pszURL[i] != '\0'; i++) { if (isalnum(pszURL[i])) *pszPtr = pszURL[i]; else *pszPtr = '_'; pszPtr++; } strlcpy(pszPtr, pszExt, nBufLen); return pszBuf; } /* ** msOWSGetEPSGProj() ** ** Extract projection code for this layer/map. ** ** First look for a xxx_srs metadata. If not found then look for an EPSG ** code in projectionObj, and if not found then return NULL. ** ** If bReturnOnlyFirstOne=TRUE and metadata contains multiple EPSG codes ** then only the first one (which is assumed to be the layer's default ** projection) is returned. */ const char *msOWSGetEPSGProj(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne) { static char epsgCode[20] =""; char *value; /* metadata value should already be in format "EPSG:n" or "AUTO:..." */ if (metadata && ((value = (char *) msOWSLookupMetadata(metadata, namespaces, "srs")) != NULL)) { if (!bReturnOnlyFirstOne) return value; /* caller requested only first projection code */ strlcpy(epsgCode, value, 20); if ((value=strchr(epsgCode, ' ')) != NULL) *value = '\0'; return epsgCode; } else if (proj && proj->numargs > 0 && (value = strstr(proj->args[0], "init=epsg:")) != NULL && strlen(value) < 20) { snprintf(epsgCode, sizeof(epsgCode), "EPSG:%s", value+10); return epsgCode; } else if (proj && proj->numargs > 0 && (value = strstr(proj->args[0], "init=crs:")) != NULL && strlen(value) < 20) { snprintf(epsgCode, sizeof(epsgCode), "CRS:%s", value+9); return epsgCode; } else if (proj && proj->numargs > 0 && (strncasecmp(proj->args[0], "AUTO:", 5) == 0 || strncasecmp(proj->args[0], "AUTO2:", 6) == 0)) { return proj->args[0]; } return NULL; } /* ** msOWSGetProjURN() ** ** Fetch an OGC URN for this layer or map. Similar to msOWSGetEPSGProj() ** but returns the result in the form "urn:ogc:def:crs:EPSG::27700". ** The returned buffer is dynamically allocated, and must be freed by the ** caller. */ char *msOWSGetProjURN(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne) { char *result; char **tokens; int numtokens, i; size_t bufferSize = 0; const char *oldStyle = msOWSGetEPSGProj( proj, metadata, namespaces, bReturnOnlyFirstOne ); if( oldStyle == NULL || strncmp(oldStyle,"EPSG:",5) != 0 ) return NULL; result = msStrdup(""); tokens = msStringSplit(oldStyle, ' ', &numtokens); for(i=0; tokens != NULL && i 0 ) { bufferSize = strlen(result)+strlen(urn)+2; result = (char *) realloc(result, bufferSize); if( strlen(result) > 0 ) strlcat( result, " ", bufferSize); strlcat( result, urn , bufferSize); } else { msDebug( "msOWSGetProjURN(): Failed to process SRS '%s', ignored.", tokens[i] ); } } msFreeCharArray(tokens, numtokens); if( strlen(result) == 0 ) { msFree( result ); return NULL; } else return result; } /* ** msOWSGetProjURI() ** ** Fetch an OGC URI for this layer or map. Similar to msOWSGetEPSGProj() ** but returns the result in the form "http://www.opengis.net/def/crs/EPSG/0/27700". ** The returned buffer is dynamically allocated, and must be freed by the ** caller. */ char *msOWSGetProjURI(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne) { char *result; char **tokens; int numtokens, i; const char *oldStyle = msOWSGetEPSGProj( proj, metadata, namespaces, bReturnOnlyFirstOne ); if( oldStyle == NULL || !EQUALN(oldStyle,"EPSG:",5) ) return NULL; result = msStrdup(""); tokens = msStringSplit(oldStyle, ' ', &numtokens); for(i=0; tokens != NULL && i 0 ) { result = (char *) realloc(result,strlen(result)+strlen(urn)+2); if( strlen(result) > 0 ) strcat( result, " " ); strcat( result, urn ); } else { msDebug( "msOWSGetProjURI(): Failed to process SRS '%s', ignored.", tokens[i] ); } } msFreeCharArray(tokens, numtokens); if( strlen(result) == 0 ) { msFree( result ); return NULL; } else return result; } /* ** msOWSGetDimensionInfo() ** ** Extract dimension information from a layer's metadata ** ** Before 4.9, only the time dimension was support. With the addition of ** Web Map Context 1.1.0, we need to support every dimension types. ** This function get the dimension information from special metadata in ** the layer, but can also return default values for the time dimension. ** */ void msOWSGetDimensionInfo(layerObj *layer, const char *pszDimension, const char **papszDimUserValue, const char **papszDimUnits, const char **papszDimDefault, const char **papszDimNearValue, const char **papszDimUnitSymbol, const char **papszDimMultiValue) { char *pszDimensionItem; size_t bufferSize = 0; if(pszDimension == NULL || layer == NULL) return; bufferSize = strlen(pszDimension)+50; pszDimensionItem = (char*)malloc(bufferSize); /* units (mandatory in map context) */ if(papszDimUnits != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_units", pszDimension); *papszDimUnits = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* unitSymbol (mandatory in map context) */ if(papszDimUnitSymbol != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_unitsymbol", pszDimension); *papszDimUnitSymbol = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* userValue (mandatory in map context) */ if(papszDimUserValue != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_uservalue", pszDimension); *papszDimUserValue = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* default */ if(papszDimDefault != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_default", pszDimension); *papszDimDefault = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* multipleValues */ if(papszDimMultiValue != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_multiplevalues", pszDimension); *papszDimMultiValue = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* nearestValue */ if(papszDimNearValue != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_nearestvalue", pszDimension); *papszDimNearValue = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* Use default time value if necessary */ if(strcasecmp(pszDimension, "time") == 0) { if(papszDimUserValue != NULL && *papszDimUserValue == NULL) *papszDimUserValue = msOWSLookupMetadata(&(layer->metadata), "MO", "time"); if(papszDimDefault != NULL && *papszDimDefault == NULL) *papszDimDefault = msOWSLookupMetadata(&(layer->metadata), "MO", "timedefault"); if(papszDimUnits != NULL && *papszDimUnits == NULL) *papszDimUnits = "ISO8601"; if(papszDimUnitSymbol != NULL && *papszDimUnitSymbol == NULL) *papszDimUnitSymbol = "t"; if(papszDimNearValue != NULL && *papszDimNearValue == NULL) *papszDimNearValue = "0"; } free(pszDimensionItem); return; } /** * msOWSNegotiateUpdateSequence() * * returns the updateSequence value for an OWS * * @param requested_updatesequence the updatesequence passed by the client * @param updatesequence the updatesequence set by the server * * @return result of comparison (-1, 0, 1) * -1: lower / higher OR values not set by client or server * 1: higher / lower * 0: equal */ int msOWSNegotiateUpdateSequence(const char *requested_updatesequence, const char *updatesequence) { int i; int valtype1 = 1; /* default datatype for updatesequence passed by client */ int valtype2 = 1; /* default datatype for updatesequence set by server */ struct tm tm_requested_updatesequence, tm_updatesequence; /* if not specified by client, or set by server, server responds with latest Capabilities XML */ if (! requested_updatesequence || ! updatesequence) return -1; /* test to see if server value is an integer (1), string (2) or timestamp (3) */ if (msStringIsInteger(updatesequence) == MS_FAILURE) valtype1 = 2; if (valtype1 == 2) { /* test if timestamp */ msTimeInit(&tm_updatesequence); if (msParseTime(updatesequence, &tm_updatesequence) == MS_TRUE) valtype1 = 3; msResetErrorList(); } /* test to see if client value is an integer (1), string (2) or timestamp (3) */ if (msStringIsInteger(requested_updatesequence) == MS_FAILURE) valtype2 = 2; if (valtype2 == 2) { /* test if timestamp */ msTimeInit(&tm_requested_updatesequence); if (msParseTime(requested_updatesequence, &tm_requested_updatesequence) == MS_TRUE) valtype2 = 3; msResetErrorList(); } /* if the datatypes do not match, do not compare, */ if (valtype1 != valtype2) return -1; if (valtype1 == 1) { /* integer */ if (atoi(requested_updatesequence) < atoi(updatesequence)) return -1; if (atoi(requested_updatesequence) > atoi(updatesequence)) return 1; if (atoi(requested_updatesequence) == atoi(updatesequence)) return 0; } if (valtype1 == 2) /* string */ return strcasecmp(requested_updatesequence, updatesequence); if (valtype1 == 3) { /* timestamp */ /* compare timestamps */ i = msDateCompare(&tm_requested_updatesequence, &tm_updatesequence) + msTimeCompare(&tm_requested_updatesequence, &tm_updatesequence); return i; } /* return default -1 */ return -1; } /************************************************************************/ /* msOwsIsOutputFormatValid */ /* */ /* Utlity function to parse a comma separated list in a */ /* metedata object and select and outputformat. */ /************************************************************************/ outputFormatObj* msOwsIsOutputFormatValid(mapObj *map, const char *format, hashTableObj *metadata, const char *namespaces, const char *name) { char **tokens=NULL; int i,n; outputFormatObj *psFormat = NULL; const char * format_list=NULL; if (map && format && metadata && namespaces && name) { msApplyDefaultOutputFormats(map); format_list = msOWSLookupMetadata(metadata, namespaces, name); n = 0; if ( format_list) tokens = msStringSplit(format_list, ',', &n); if (tokens && n > 0) { for (i=0; ioutputformatlist[iFormat]->mimetype; msStringTrim(tokens[i]); if (strcasecmp(tokens[i], format) == 0) break; if (mimetype && strcasecmp(mimetype, format) == 0) break; } msFreeCharArray(tokens, n); if (i < n) psFormat = msSelectOutputFormat( map, format); } } return psFormat; } #endif /* USE_WMS_SVR || USE_WFS_SVR || USE_WCS_SVR */ mapserver-6.4.1/maptemplate.c0000644002461700001440000050267612261257215016011 0ustar tbonfortusers/****************************************************************************** * $id: maptemplate.c 7725 2008-06-21 15:56:58Z sdlime $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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. ****************************************************************************/ #include "maptemplate.h" #include "maphash.h" #include "mapserver.h" #include "maptile.h" #include #include #include #include static char *olUrl = "http://www.mapserver.org/lib/OpenLayers-ms60.js"; static char *olTemplate = \ "\n" "\n" " MapServer Simple Viewer\n" " \n" " \n" " \n" "
\n" " \n" "\n" ""; static char *olLayerMapServerTag = \ "var mslayer = new OpenLayers.Layer.MapServer( \"MapServer Layer\",\n" " \"[mapserv_onlineresource]\",\n" " {layers: '[layers]'},\n" " {singleTile: \"true\", ratio:1} )"; static char *olLayerWMSTag = \ "var mslayer = new OpenLayers.Layer.WMS('MapServer Simple Viewer\',\n" " '[mapserv_onlineresource]',\n" " {layers: '[LAYERS]',\n" " bbox: '[minx],[miny],[maxx],[maxy]',\n" " width: [mapwidth], height: [mapheight], version: '[VERSION]', format:'[openlayers_format]'}," " {singleTile: \"true\", ratio:1, projection: '[openlayers_projection]'});\n"; static char *processLine(mapservObj *mapserv, char *instr, FILE *stream, int mode); static int isValidTemplate(FILE *stream, const char *filename) { char buffer[MS_BUFFER_LENGTH]; if(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { if(!strcasestr(buffer, MS_TEMPLATE_MAGIC_STRING)) { msSetError(MS_WEBERR, "Missing magic string, %s doesn't look like a MapServer template.", "isValidTemplate()", filename); return MS_FALSE; } } return MS_TRUE; } /* * Redirect to (only use in CGI) * */ int msRedirect(char *url) { msIO_setHeader("Status","302 Found"); msIO_setHeader("Uri","%s",url); msIO_setHeader("Location","%s",url); msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); return MS_SUCCESS; } /* ** Sets the map extent under a variety of scenarios. */ int setExtent(mapservObj *mapserv) { double cellx,celly,cellsize; if(mapserv->Mode == TILE) { if(MS_SUCCESS != msTileSetExtent(mapserv)) { return MS_FAILURE; } } switch(mapserv->CoordSource) { case FROMUSERBOX: /* user passed in a map extent */ break; case FROMIMGBOX: /* fully interactive web, most likely with java front end */ cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->map->extent.minx = MS_IMAGE2MAP_X(mapserv->ImgBox.minx, mapserv->ImgExt.minx, cellx); mapserv->map->extent.maxx = MS_IMAGE2MAP_X(mapserv->ImgBox.maxx, mapserv->ImgExt.minx, cellx); mapserv->map->extent.maxy = MS_IMAGE2MAP_Y(mapserv->ImgBox.miny, mapserv->ImgExt.maxy, celly); /* y's are flip flopped because img/map coordinate systems are */ mapserv->map->extent.miny = MS_IMAGE2MAP_Y(mapserv->ImgBox.maxy, mapserv->ImgExt.maxy, celly); break; case FROMIMGPNT: cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->ImgPnt.x, mapserv->ImgExt.minx, cellx); mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->ImgPnt.y, mapserv->ImgExt.maxy, celly); mapserv->map->extent.minx = mapserv->mappnt.x - .5*((mapserv->ImgExt.maxx - mapserv->ImgExt.minx)/mapserv->fZoom); /* create an extent around that point */ mapserv->map->extent.miny = mapserv->mappnt.y - .5*((mapserv->ImgExt.maxy - mapserv->ImgExt.miny)/mapserv->fZoom); mapserv->map->extent.maxx = mapserv->mappnt.x + .5*((mapserv->ImgExt.maxx - mapserv->ImgExt.minx)/mapserv->fZoom); mapserv->map->extent.maxy = mapserv->mappnt.y + .5*((mapserv->ImgExt.maxy - mapserv->ImgExt.miny)/mapserv->fZoom); break; case FROMREFPNT: cellx = MS_CELLSIZE(mapserv->map->reference.extent.minx, mapserv->map->reference.extent.maxx, mapserv->map->reference.width); celly = MS_CELLSIZE(mapserv->map->reference.extent.miny, mapserv->map->reference.extent.maxy, mapserv->map->reference.height); mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->RefPnt.x, mapserv->map->reference.extent.minx, cellx); mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->RefPnt.y, mapserv->map->reference.extent.maxy, celly); mapserv->map->extent.minx = mapserv->mappnt.x - .5*(mapserv->ImgExt.maxx - mapserv->ImgExt.minx); /* create an extent around that point */ mapserv->map->extent.miny = mapserv->mappnt.y - .5*(mapserv->ImgExt.maxy - mapserv->ImgExt.miny); mapserv->map->extent.maxx = mapserv->mappnt.x + .5*(mapserv->ImgExt.maxx - mapserv->ImgExt.minx); mapserv->map->extent.maxy = mapserv->mappnt.y + .5*(mapserv->ImgExt.maxy - mapserv->ImgExt.miny); break; case FROMBUF: mapserv->map->extent.minx = mapserv->mappnt.x - mapserv->Buffer; /* create an extent around that point, using the buffer */ mapserv->map->extent.miny = mapserv->mappnt.y - mapserv->Buffer; mapserv->map->extent.maxx = mapserv->mappnt.x + mapserv->Buffer; mapserv->map->extent.maxy = mapserv->mappnt.y + mapserv->Buffer; break; case FROMSCALE: cellsize = (mapserv->ScaleDenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale denominator */ mapserv->map->extent.minx = mapserv->mappnt.x - cellsize*(mapserv->map->width-1)/2.0; mapserv->map->extent.miny = mapserv->mappnt.y - cellsize*(mapserv->map->height-1)/2.0; mapserv->map->extent.maxx = mapserv->mappnt.x + cellsize*(mapserv->map->width-1)/2.0; mapserv->map->extent.maxy = mapserv->mappnt.y + cellsize*(mapserv->map->height-1)/2.0; break; default: /* use the default in the mapfile if it exists */ if((mapserv->map->extent.minx == mapserv->map->extent.maxx) && (mapserv->map->extent.miny == mapserv->map->extent.maxy)) { msSetError(MS_WEBERR, "No way to generate map extent.", "mapserv()"); return MS_FAILURE; } } mapserv->RawExt = mapserv->map->extent; /* save unaltered extent */ return MS_SUCCESS; } int checkWebExtent(mapservObj *mapserv) { return MS_SUCCESS; } int checkWebScale(mapservObj *mapserv) { int status; rectObj work_extent = mapserv->map->extent; mapserv->map->cellsize = msAdjustExtent(&(work_extent), mapserv->map->width, mapserv->map->height); /* we do this cause we need a scale */ if((status = msCalculateScale(work_extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return status; if((mapserv->map->scaledenom < mapserv->map->web.minscaledenom) && (mapserv->map->web.minscaledenom > 0)) { if(mapserv->map->web.mintemplate) { /* use the template provided */ if(TEMPLATE_TYPE(mapserv->map->web.mintemplate) == MS_FILE) { if((status = msReturnPage(mapserv, mapserv->map->web.mintemplate, BROWSE, NULL)) != MS_SUCCESS) return status; } else { if((status = msReturnURL(mapserv, mapserv->map->web.mintemplate, BROWSE)) != MS_SUCCESS) return status; } } else { /* force zoom = 1 (i.e. pan) */ mapserv->fZoom = mapserv->Zoom = 1; mapserv->ZoomDirection = 0; mapserv->CoordSource = FROMSCALE; mapserv->ScaleDenom = mapserv->map->web.minscaledenom; mapserv->mappnt.x = (mapserv->map->extent.maxx + mapserv->map->extent.minx)/2; /* use center of bad extent */ mapserv->mappnt.y = (mapserv->map->extent.maxy + mapserv->map->extent.miny)/2; setExtent(mapserv); mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return status; } } else { if((mapserv->map->scaledenom > mapserv->map->web.maxscaledenom) && (mapserv->map->web.maxscaledenom > 0)) { if(mapserv->map->web.maxtemplate) { /* use the template provided */ if(TEMPLATE_TYPE(mapserv->map->web.maxtemplate) == MS_FILE) { if((status = msReturnPage(mapserv, mapserv->map->web.maxtemplate, BROWSE, NULL)) != MS_SUCCESS) return status; } else { if((status = msReturnURL(mapserv, mapserv->map->web.maxtemplate, BROWSE)) != MS_SUCCESS) return status; } } else { /* force zoom = 1 (i.e. pan) */ mapserv->fZoom = mapserv->Zoom = 1; mapserv->ZoomDirection = 0; mapserv->CoordSource = FROMSCALE; mapserv->ScaleDenom = mapserv->map->web.maxscaledenom; mapserv->mappnt.x = (mapserv->map->extent.maxx + mapserv->map->extent.minx)/2; /* use center of bad extent */ mapserv->mappnt.y = (mapserv->map->extent.maxy + mapserv->map->extent.miny)/2; setExtent(mapserv); mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return status; } } } return MS_SUCCESS; } int msReturnTemplateQuery(mapservObj *mapserv, char *queryFormat, char **papszBuffer) { imageObj *img = NULL; int i, status; outputFormatObj *outputFormat=NULL; mapObj *map = mapserv->map; if(!queryFormat) { msSetError(MS_WEBERR, "Return format/mime-type not specified.", "msReturnTemplateQuery()"); return MS_FAILURE; } msApplyDefaultOutputFormats(map); i = msGetOutputFormatIndex(map, queryFormat); /* queryFormat can be a mime-type or name */ if(i >= 0) outputFormat = map->outputformatlist[i]; if(outputFormat) { if( MS_RENDERER_PLUGIN(outputFormat) ) { msInitializeRendererVTable(outputFormat); } if( MS_RENDERER_OGR(outputFormat) ) { if( mapserv != NULL ) checkWebScale(mapserv); status = msOGRWriteFromQuery(map, outputFormat, mapserv->sendheaders); return status; } if( !MS_RENDERER_TEMPLATE(outputFormat) ) { /* got an image format, return the query results that way */ outputFormatObj *tempOutputFormat = map->outputformat; /* save format */ if( mapserv != NULL ) checkWebScale(mapserv); map->outputformat = outputFormat; /* override what was given for IMAGETYPE */ img = msDrawMap(map, MS_TRUE); if(!img) return MS_FAILURE; map->outputformat = tempOutputFormat; /* restore format */ if(mapserv == NULL || mapserv->sendheaders) { msIO_setHeader("Content-Type", "%s", MS_IMAGE_MIME_TYPE(outputFormat)); msIO_sendHeaders(); } status = msSaveImage(map, img, NULL); msFreeImage(img); return status; } } /* ** At this point we know we have a template of some sort, either the new style that references a or the old ** style made up of external files slammed together. Either way we may have to compute a query map and other ** images. We only create support images IF the querymap has status=MS_ON. */ if(map->querymap.status && mapserv != NULL ) { checkWebScale(mapserv); if(msGenerateImages(mapserv, MS_TRUE, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } if(outputFormat) { const char *file = msGetOutputFormatOption( outputFormat, "FILE", NULL ); if(!file) { msSetError(MS_WEBERR, "Template driver requires \"FILE\" format option be set.", "msReturnTemplateQuery()"); return MS_FAILURE; } if(mapserv == NULL || mapserv->sendheaders) { const char *attachment = msGetOutputFormatOption( outputFormat, "ATTACHMENT", NULL ); if(attachment) msIO_setHeader("Content-disposition","attachment; filename=%s", attachment); msIO_setHeader("Content-Type", "%s", outputFormat->mimetype); msIO_sendHeaders(); } if((status = msReturnPage(mapserv, (char *) file, BROWSE, papszBuffer)) != MS_SUCCESS) return status; } else { if((status = msReturnNestedTemplateQuery(mapserv, queryFormat, papszBuffer)) != MS_SUCCESS) return status; } return MS_SUCCESS; } /* ** Is a particular layer or group on, that is was it requested explicitly by the user. */ int isOn(mapservObj *mapserv, char *name, char *group) { int i; for(i=0; iNumLayers; i++) { if(name && strcmp(mapserv->Layers[i], name) == 0) return(MS_TRUE); if(group && strcmp(mapserv->Layers[i], group) == 0) return(MS_TRUE); } return(MS_FALSE); } /************************************************************************/ /* int sortLayerByOrder(mapObj *map, char* pszOrder) */ /* */ /* sorth the displaying in ascending or descending order. */ /************************************************************************/ int sortLayerByOrder(mapObj *map, char* pszOrder) { int *panCurrentOrder = NULL; int i = 0; if(!map) { msSetError(MS_WEBERR, "Invalid pointer.", "sortLayerByOrder()"); return MS_FAILURE; } /* ==================================================================== */ /* The flag "ascending" is in fact not useful since the */ /* default ordering is ascending. */ /* ==================================================================== */ /* -------------------------------------------------------------------- */ /* the map->layerorder should be set at this point in the */ /* sortLayerByMetadata. */ /* -------------------------------------------------------------------- */ if(map->layerorder) { panCurrentOrder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); for (i=0; inumlayers ; i++) panCurrentOrder[i] = map->layerorder[i]; if(strcasecmp(pszOrder, "DESCENDING") == 0) { for (i=0; inumlayers; i++) map->layerorder[i] = panCurrentOrder[map->numlayers-1-i]; } free(panCurrentOrder); } return MS_SUCCESS; } /*! * This function set the map->layerorder * index order by the metadata collumn name */ int sortLayerByMetadata(mapObj *map, char* pszMetadata) { int nLegendOrder1; int nLegendOrder2; char *pszLegendOrder1; char *pszLegendOrder2; int i, j; int tmp; if(!map) { msSetError(MS_WEBERR, "Invalid pointer.", "sortLayerByMetadata()"); return MS_FAILURE; } /* * Initiate to default order (Reverse mapfile order) */ if(map->layerorder) { int *pnLayerOrder; /* Backup the original layer order to be able to reverse it */ pnLayerOrder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); for (i=0; inumlayers ; i++) pnLayerOrder[i] = map->layerorder[i]; /* Get a new layerorder array */ free(map->layerorder); map->layerorder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); /* Reverse the layerorder array */ for (i=0; inumlayers ; i++) map->layerorder[i] = pnLayerOrder[map->numlayers - i - 1]; free(pnLayerOrder); } else { map->layerorder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); for (i=0; inumlayers ; i++) map->layerorder[i] = map->numlayers - i - 1; } if(!pszMetadata) return MS_SUCCESS; /* * Bubble sort algo (not very efficient) * should implement a kind of quick sort * alog instead */ for (i=0; inumlayers-1; i++) { for (j=0; jnumlayers-1-i; j++) { pszLegendOrder1 = msLookupHashTable(&(GET_LAYER(map, map->layerorder[j+1])->metadata), pszMetadata); pszLegendOrder2 = msLookupHashTable(&(GET_LAYER(map, map->layerorder[j])->metadata), pszMetadata); if(!pszLegendOrder1 || !pszLegendOrder2) continue; nLegendOrder1 = atoi(pszLegendOrder1); nLegendOrder2 = atoi(pszLegendOrder2); if(nLegendOrder1 < nLegendOrder2) { /* compare the two neighbors */ tmp = map->layerorder[j]; /* swap a[j] and a[j+1] */ map->layerorder[j] = map->layerorder[j+1]; map->layerorder[j+1] = tmp; } } } return MS_SUCCESS; } /* ** This function return a pointer ** at the begining of the first occurence ** of pszTag in pszInstr. ** ** Tag can be [TAG] or [TAG something] */ char *findTag(char *pszInstr, char *pszTag) { char *pszTag1, *pszStart=NULL; char *pszTemp; int done=MS_FALSE; int length; if(!pszInstr || !pszTag) { msSetError(MS_WEBERR, "Invalid pointer.", "findTag()"); return NULL; } length = strlen(pszTag) + 1; /* adding [ character to the beginning */ pszTag1 = (char*) msSmallMalloc(length+1); strcpy(pszTag1, "["); strcat(pszTag1, pszTag); pszTemp = pszInstr; while(!done) { pszStart = strstr(pszTemp, pszTag1); if(pszStart == NULL) done = MS_TRUE; /* tag not found */ else if((*(pszStart+length) == ']' || *(pszStart+length) == ' ')) done = MS_TRUE; /* valid tag */ else pszTemp += length; /* skip ahead and start over */ } free(pszTag1); return pszStart; } /* ** This function return a pointer ** to the end of the tag in pszTag ** ** The end of a tag is the next ** non-quoted ']' character. ** Return NULL if not found. */ char *findTagEnd(const char *pszTag) { char *pszEnd = NULL, *pszTmp = (char*)pszTag; while (pszTmp != NULL) { if (*pszTmp == '"') pszTmp = strchr(pszTmp+1,'"'); if ((pszTmp == NULL) || (*pszTmp == ']')) { pszEnd = pszTmp; pszTmp = NULL; } else pszTmp++; } return pszEnd; } /* ** Return a hashtableobj from instr of all ** arguments. hashtable must be freed by caller. */ int getTagArgs(char* pszTag, char* pszInstr, hashTableObj **ppoHashTable) { char *pszStart, *pszEnd, *pszArgs; int nLength; char **papszArgs, **papszVarVal; int nArgs, nDummy; int i; if(!pszTag || !pszInstr) { msSetError(MS_WEBERR, "Invalid pointer.", "getTagArgs()"); return MS_FAILURE; } /* set position to the begining of tag */ pszStart = findTag(pszInstr, pszTag); if(pszStart) { /* find ending position */ pszEnd = findTagEnd(pszStart); if(pszEnd) { /* skip the tag name */ pszStart = pszStart + strlen(pszTag) + 1; /* get length of all args */ nLength = pszEnd - pszStart; if(nLength > 0) { /* is there arguments ? */ pszArgs = (char*)msSmallMalloc(nLength + 1); strlcpy(pszArgs, pszStart, nLength+1); if(!(*ppoHashTable)) *ppoHashTable = msCreateHashTable(); /* put all arguments seperate by space in a hash table */ papszArgs = msStringTokenize(pszArgs, " ", &nArgs, MS_TRUE); /* msReturnTemplateQuerycheck all argument if they have values */ for (i=0; i 0) { *pszResult = (char*)msSmallMalloc(nLength + 1); /* copy string beetween start and end tag */ strlcpy(*pszResult, pszStart, nLength+1); (*pszResult)[nLength] = '\0'; } } else { msSetError(MS_WEBERR, "Malformed [%s] tag.", "getInlineTag()", pszTag); return MS_FAILURE; } } msFree(pszEndTag); return MS_SUCCESS; } /*! * this function process all if tag in pszInstr. * this function return a modified pszInstr. * ht mus contain all variables needed by the function * to interpret if expression. * * If bLastPass is true then all tests for 'null' values will be * considered true if the corresponding value is not set. */ int processIfTag(char **pszInstr, hashTableObj *ht, int bLastPass) { /* char *pszNextInstr = pszInstr; */ char *pszStart, *pszEnd=NULL; char *pszName, *pszValue, *pszOperator, *pszThen=NULL, *pszHTValue; char *pszIfTag; char *pszPatIn=NULL, *pszPatOut=NULL, *pszTmp; int nInst = 0; int bEmpty = 0; int nLength; hashTableObj *ifArgs=NULL; if(!*pszInstr) { msSetError(MS_WEBERR, "Invalid pointer.", "processIfTag()"); return MS_FAILURE; } /* find the if start tag */ pszStart = findTag(*pszInstr, "if"); while (pszStart) { pszPatIn = findTag(pszStart, "if"); pszPatOut = strstr(pszStart, "[/if]"); pszTmp = pszPatIn; do { if(pszPatIn && pszPatIn < pszPatOut) { nInst++; pszTmp = pszPatIn; } if(pszPatOut && ((pszPatIn == NULL) || pszPatOut < pszPatIn)) { pszEnd = pszPatOut; nInst--; pszTmp = pszPatOut; } pszPatIn = findTag(pszTmp+1, "if"); pszPatOut = strstr(pszTmp+1, "[/if]"); } while (pszTmp != NULL && nInst > 0); /* get the then string (if expression is true) */ if(getInlineTag("if", pszStart, &pszThen) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed then if tag.", "processIfTag()"); return MS_FAILURE; } /* retrieve if tag args */ if(getTagArgs("if", pszStart, &ifArgs) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed args if tag.", "processIfTag()"); return MS_FAILURE; } pszName = msLookupHashTable(ifArgs, "name"); pszValue = msLookupHashTable(ifArgs, "value"); pszOperator = msLookupHashTable(ifArgs, "oper"); if(pszOperator == NULL) /* Default operator if not set is "eq" */ pszOperator = "eq"; bEmpty = 0; if(pszName) { /* build the complete if tag ([if all_args]then string[/if]) */ /* to replace if by then string if expression is true */ /* or by a white space if not. */ nLength = pszEnd - pszStart; pszIfTag = (char*)msSmallMalloc(nLength + 6); strlcpy(pszIfTag, pszStart, nLength+1); pszIfTag[nLength] = '\0'; strcat(pszIfTag, "[/if]"); pszHTValue = msLookupHashTable(ht, pszName); if(strcmp(pszOperator, "neq") == 0) { if(pszValue && pszHTValue && strcasecmp(pszValue, pszHTValue) != 0) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } else if(pszHTValue) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } } else if(strcmp(pszOperator, "eq") == 0) { if(pszValue && pszHTValue && strcasecmp(pszValue, pszHTValue) == 0) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } else if(pszHTValue) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } } else if(strcmp(pszOperator, "isnull") == 0) { if(pszHTValue != NULL) { /* We met a non-null value... condition is false */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } else if(bLastPass) { /* On last pass, if value is still null then condition is true */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } } else if(strcmp(pszOperator, "isset") == 0) { if(pszHTValue != NULL) { /* Found a non-null value... condition is true */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } else if(bLastPass) { /* On last pass, if value still not set then condition is false */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } } else { msSetError(MS_WEBERR, "Unsupported operator (%s) in if tag.", "processIfTag()", pszOperator); return MS_FAILURE; } if(pszIfTag) free(pszIfTag); pszIfTag = NULL; } if(pszThen) free (pszThen); pszThen=NULL; msFreeHashTable(ifArgs); ifArgs=NULL; /* find the if start tag */ if(bEmpty) pszStart = findTag(pszStart, "if"); else pszStart = findTag(pszStart + 1, "if"); } return MS_SUCCESS; } /* Helper function to return the text before the supplied string2 in string1. */ static char *getPreTagText(const char *string1, const char *string2) { int n; char *result, *tmpstr; if((tmpstr = strstr(string1, string2)) == NULL) return msStrdup(""); /* return an empty string */ n = strlen(string1) - strlen(tmpstr); result = (char *) msSmallMalloc(n + 1); strlcpy(result, string1, n+1); return result; } /* Helper function to retunr the text after the supplied string2 in string1. */ static char *getPostTagText(const char *string1, const char *string2) { char *tmpstr; if((tmpstr = strstr(string1, string2)) == NULL) return msStrdup(""); /* return an empty string */ tmpstr += strlen(string2); /* skip string2 */ return msStrdup(tmpstr); } /* ** Function to process a [feature ...] tag. This tag can *only* be found within ** a [resultset ...][/resultset] block. */ static int processFeatureTag(mapservObj *mapserv, char **line, layerObj *layer) { char *preTag, *postTag; /* text before and after the tag */ char *argValue; char *tag, *tagInstance, *tagStart; hashTableObj *tagArgs=NULL; int limit=-1; char *trimLast=NULL; int i, j, status; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processFeatureTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "feature"); if(!tagStart) return(MS_SUCCESS); /* OK, just return; */ /* check for any tag arguments */ if(getTagArgs("feature", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "limit"); if(argValue) limit = atoi(argValue); argValue = msLookupHashTable(tagArgs, "trimlast"); if(argValue) trimLast = argValue; } if(strstr(*line, "[/feature]") == NULL) { /* we know the closing tag must be here, if not throw an error */ msSetError(MS_WEBERR, "[feature] tag found without closing [/feature].", "processFeatureTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } if(getInlineTag("feature", *line, &tag) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed feature tag.", "processFeatureTag()"); msFreeHashTable(tagArgs); return MS_FAILURE; } preTag = getPreTagText(*line, "[feature"); postTag = getPostTagText(*line, "[/feature]"); /* start rebuilding **line */ free(*line); *line = preTag; /* we know the layer has query results or we wouldn't be in this code */ #if 0 status = msLayerOpen(layer); /* open the layer */ if(status != MS_SUCCESS) return status; status = msLayerGetItems(layer); /* retrieve all the item names */ if(status != MS_SUCCESS) return status; #endif if(layer->numjoins > 0) { /* initialize necessary JOINs here */ for(j=0; jnumjoins; j++) { status = msJoinConnect(layer, &(layer->joins[j])); if(status != MS_SUCCESS) { msFreeHashTable(tagArgs); return status; } } } mapserv->LRN = 1; /* layer result counter */ mapserv->resultlayer = layer; msInitShape(&(mapserv->resultshape)); if(limit == -1) /* return all */ limit = layer->resultcache->numresults; else limit = MS_MIN(limit, layer->resultcache->numresults); for(i=0; iresultshape), &(layer->resultcache->results[i])); if(status != MS_SUCCESS) { msFreeHashTable(tagArgs); return status; } mapserv->resultshape.classindex = msShapeGetClass(layer, layer->map, &mapserv->resultshape, NULL, -1); if(mapserv->resultshape.classindex >=0 && layer->class[mapserv->resultshape.classindex]->numlabels > 0) msShapeGetAnnotation(layer, &mapserv->resultshape); // RFC 77 TODO: check return value /* prepare any necessary JOINs here (one-to-one only) */ if(layer->numjoins > 0) { for(j=0; jnumjoins; j++) { if(layer->joins[j].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(layer->joins[j]), &(mapserv->resultshape)); msJoinNext(&(layer->joins[j])); /* fetch the first row */ } } } /* ** if necessary trim a few characters off the end of the tag */ if(trimLast && (i == limit-1)) { char *ptr; if((ptr = strrstr(tag, trimLast)) != NULL) *ptr = '\0'; } /* process the tag */ tagInstance = processLine(mapserv, tag, NULL, QUERY); /* do substitutions */ *line = msStringConcatenate(*line, tagInstance); /* grow the line */ free(tagInstance); msFreeShape(&(mapserv->resultshape)); /* init too */ mapserv->RN++; /* increment counters */ mapserv->LRN++; } /* msLayerClose(layer); */ mapserv->resultlayer = NULL; /* necessary? */ *line = msStringConcatenate(*line, postTag); /* ** clean up */ free(postTag); free(tag); msFreeHashTable(tagArgs); return(MS_SUCCESS); } /* ** Function to process a [resultset ...] tag. */ static int processResultSetTag(mapservObj *mapserv, char **line, FILE *stream) { char lineBuffer[MS_BUFFER_LENGTH]; int foundTagEnd; char *preTag, *postTag; /* text before and after the tag */ char *tag, *tagStart; hashTableObj *tagArgs=NULL; char *layerName=NULL; char *nodata=NULL; int layerIndex=-1; layerObj *lp; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processResultSetTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "resultset"); if(!tagStart) return(MS_SUCCESS); /* OK, just return; */ while (tagStart) { /* initialize the tag arguments */ layerName = NULL; /* check for any tag arguments */ if(getTagArgs("resultset", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { layerName = msLookupHashTable(tagArgs, "layer"); nodata = msLookupHashTable(tagArgs, "nodata"); } if(!layerName) { msSetError(MS_WEBERR, "[resultset] tag missing required 'layer' argument.", "processResultSetTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } layerIndex = msGetLayerIndex(mapserv->map, layerName); if(layerIndex>=mapserv->map->numlayers || layerIndex<0) { msSetError(MS_MISCERR, "Layer named '%s' does not exist.", "processResultSetTag()", layerName); msFreeHashTable(tagArgs); return MS_FAILURE; } lp = GET_LAYER(mapserv->map, layerIndex); if(strstr(*line, "[/resultset]") == NULL) { /* read ahead */ if(!stream) { msSetError(MS_WEBERR, "Invalid file pointer.", "processResultSetTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } foundTagEnd = MS_FALSE; while(!foundTagEnd) { if(fgets(lineBuffer, MS_BUFFER_LENGTH, stream) != NULL) { *line = msStringConcatenate(*line, lineBuffer); if(strstr(*line, "[/resultset]") != NULL) foundTagEnd = MS_TRUE; } else break; /* ran out of file */ } if(foundTagEnd == MS_FALSE) { msSetError(MS_WEBERR, "[resultset] tag found without closing [/resultset].", "processResultSetTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } } if(getInlineTag("resultset", *line, &tag) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed resultset tag.", "processResultSetTag()"); msFreeHashTable(tagArgs); return MS_FAILURE; } preTag = getPreTagText(*line, "[resultset"); /* TODO: need to handle tags in these */ postTag = getPostTagText(*line, "[/resultset]"); /* start rebuilding **line */ free(*line); *line = preTag; if(lp->resultcache && lp->resultcache->numresults > 0) { /* probably will need a while-loop here to handle multiple instances of [feature ...] tags */ if(processFeatureTag(mapserv, &tag, lp) != MS_SUCCESS) { msFreeHashTable(tagArgs); return(MS_FAILURE); /* TODO: how to handle */ } *line = msStringConcatenate(*line, tag); } else if(nodata) { *line = msStringConcatenate(*line, nodata); } *line = msStringConcatenate(*line, postTag); /* clean up */ free(postTag); free(tag); tagStart = findTag(*line, "resultset"); } msFreeHashTable(tagArgs); return(MS_SUCCESS); } /* ** Function process a [include src="..."] tag. ** ** TODO's: ** - allow URLs */ static int processIncludeTag(mapservObj *mapserv, char **line, FILE *stream, int mode) { char *tag, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; char *content=NULL, *processedContent=NULL, *src=NULL; FILE *includeStream; char buffer[MS_BUFFER_LENGTH], path[MS_MAXPATHLEN]; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processIncludeTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "include"); /* It is OK to have no include tags, just return. */ if( !tagStart ) return MS_SUCCESS; while( tagStart ) { tagOffset = tagStart - *line; /* check for any tag arguments */ if(getTagArgs("include", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { src = msLookupHashTable(tagArgs, "src"); } if(!src) return(MS_SUCCESS); /* don't process the tag, could be something else so return MS_SUCCESS */ if((includeStream = fopen(msBuildPath(path, mapserv->map->mappath, src), "r")) == NULL) { msSetError(MS_IOERR, "%s", "processIncludeTag()", src); return MS_FAILURE; } if(isValidTemplate(includeStream, src) != MS_TRUE) { fclose(includeStream); return MS_FAILURE; } while(fgets(buffer, MS_BUFFER_LENGTH, includeStream) != NULL) content = msStringConcatenate(content, buffer); /* done with included file handle */ fclose(includeStream); /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* process any other tags in the content */ processedContent = processLine(mapserv, content, stream, mode); /* do the replacement */ *line = msReplaceSubstring(*line, tag, processedContent); /* clean up */ free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; free(content); free(processedContent); if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "include"); else tagStart = NULL; } return(MS_SUCCESS); } /* ** Function to process an [item ...] tag: line contains the tag, shape holds the attributes. */ enum ITEM_ESCAPING {ESCAPE_HTML, ESCAPE_URL, ESCAPE_NONE}; static int processItemTag(layerObj *layer, char **line, shapeObj *shape) { int i, j; char *tag, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagLength; char *encodedTagValue=NULL, *tagValue=NULL; char *argValue=NULL; char *name=NULL, *pattern=NULL; char *format=NULL, *nullFormat=NULL; int precision; int uc, lc, commify; int escape; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processItemTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "item"); if(!tagStart) return(MS_SUCCESS); /* OK, just return; */ while (tagStart) { format = "$value"; /* initialize the tag arguments */ nullFormat = ""; precision=-1; name = pattern = NULL; uc = lc = commify = MS_FALSE; escape=ESCAPE_HTML; /* check for any tag arguments */ if(getTagArgs("item", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "name"); if(argValue) name = argValue; argValue = msLookupHashTable(tagArgs, "pattern"); if(argValue) pattern = argValue; argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "nullformat"); if(argValue) nullFormat = argValue; argValue = msLookupHashTable(tagArgs, "uc"); if(argValue && strcasecmp(argValue, "true") == 0) uc = MS_TRUE; argValue = msLookupHashTable(tagArgs, "lc"); if(argValue && strcasecmp(argValue, "true") == 0) lc = MS_TRUE; argValue = msLookupHashTable(tagArgs, "commify"); if(argValue && strcasecmp(argValue, "true") == 0) commify = MS_TRUE; argValue = msLookupHashTable(tagArgs, "escape"); if(argValue && strcasecmp(argValue, "url") == 0) escape = ESCAPE_URL; else if(argValue && strcasecmp(argValue, "none") == 0) escape = ESCAPE_NONE; /* TODO: deal with sub strings */ } if(!name) { msSetError(MS_WEBERR, "Item tag contains no name attribute.", "processItemTag()"); return(MS_FAILURE); } for(i=0; inumitems; i++) if(strcasecmp(name, layer->items[i]) == 0) break; if(i == layer->numitems) { msSetError(MS_WEBERR, "Item name (%s) not found in layer item list.", "processItemTag()", name); return(MS_FAILURE); } /* ** now we know which item so build the tagValue */ if(shape->values[i] && strlen(shape->values[i]) > 0) { char *itemValue=NULL; /* set tag text depending on pattern (if necessary), nullFormat can contain $value (#3637) */ if(pattern && msEvalRegex(pattern, shape->values[i]) != MS_TRUE) tagValue = msStrdup(nullFormat); else tagValue = msStrdup(format); if(precision != -1) { char numberFormat[16]; itemValue = (char *) msSmallMalloc(64); /* plenty big */ snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision); snprintf(itemValue, 64, numberFormat, atof(shape->values[i])); } else itemValue = msStrdup(shape->values[i]); if(commify == MS_TRUE) itemValue = msCommifyString(itemValue); /* apply other effects */ if(uc == MS_TRUE) for(j=0; jmaxx-extent->minx))/2; yExpand = ((f/100.0)*(extent->maxy-extent->miny))/2; } else { xExpand = atof(argValue); yExpand = xExpand; } } argValue = msLookupHashTable(tagArgs, "escape"); if(argValue && strcasecmp(argValue, "url") == 0) escape = ESCAPE_URL; else if(argValue && strcasecmp(argValue, "none") == 0) escape = ESCAPE_NONE; argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "proj"); if(argValue) projectionString = argValue; } tempExtent.minx = extent->minx - xExpand; tempExtent.miny = extent->miny - yExpand; tempExtent.maxx = extent->maxx + xExpand; tempExtent.maxy = extent->maxy + yExpand; /* no big deal to convert from file to image coordinates, but what are the image parameters */ if(rectProj && projectionString && strcasecmp(projectionString,"image") == 0) { precision = 0; /* if necessary, project the shape to match the map */ if(msProjectionsDiffer(rectProj, &(mapserv->map->projection))) msProjectRect(rectProj, &mapserv->map->projection, &tempExtent); /* convert tempExtent to image coordinates based on the map extent and cellsize */ tempExtent.minx = MS_MAP2IMAGE_X(tempExtent.minx, mapserv->map->extent.minx, mapserv->map->cellsize); tempExtent.miny = MS_MAP2IMAGE_Y(tempExtent.miny, mapserv->map->extent.maxy, mapserv->map->cellsize); tempExtent.maxx = MS_MAP2IMAGE_X(tempExtent.minx, mapserv->map->extent.minx, mapserv->map->cellsize); tempExtent.maxy = MS_MAP2IMAGE_Y(tempExtent.miny, mapserv->map->extent.maxy, mapserv->map->cellsize); } else if(rectProj && projectionString) { projectionObj projection; msInitProjection(&projection); if(MS_SUCCESS != msLoadProjectionString(&projection, projectionString)) return MS_FAILURE; if(msProjectionsDiffer(rectProj, &projection)) msProjectRect(rectProj, &projection, &tempExtent); } tagValue = msStrdup(format); if(precision != -1) snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision); else snprintf(numberFormat, sizeof(numberFormat), "%%f"); snprintf(number, sizeof(number), numberFormat, tempExtent.minx); tagValue = msReplaceSubstring(tagValue, "$minx", number); snprintf(number, sizeof(number), numberFormat, tempExtent.miny); tagValue = msReplaceSubstring(tagValue, "$miny", number); snprintf(number, sizeof(number), numberFormat, tempExtent.maxx); tagValue = msReplaceSubstring(tagValue, "$maxx", number); snprintf(number, sizeof(number), numberFormat, tempExtent.maxy); tagValue = msReplaceSubstring(tagValue, "$maxy", number); /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ switch(escape) { case ESCAPE_HTML: encodedTagValue = msEncodeHTMLEntities(tagValue); *line = msReplaceSubstring(*line, tag, encodedTagValue); break; case ESCAPE_URL: encodedTagValue = msEncodeUrl(tagValue); *line = msReplaceSubstring(*line, tag, encodedTagValue); break; case ESCAPE_NONE: *line = msReplaceSubstring(*line, tag, tagValue); break; default: break; } /* clean up */ free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; msFree(tagValue); tagValue=NULL; msFree(encodedTagValue); encodedTagValue=NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, name); else tagStart = NULL; } return(MS_SUCCESS); } // RFC 77 TODO: Need to validate these changes with Assefa... static int processShplabelTag(layerObj *layer, char **line, shapeObj *origshape) { char *tag, *tagStart, *tagEnd; char *tagValue=NULL; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; char *format; char *argValue=NULL; char *projectionString=NULL; shapeObj tShape; int precision=0; int clip_to_map=MS_TRUE; int use_label_settings=MS_FALSE; double cellsize=0; int labelposvalid = MS_FALSE; pointObj labelPos; int i,status; char number[64]; /* holds a single number in the extent */ char numberFormat[16]; shapeObj *shape = NULL; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processShplabelTag()"); return(MS_FAILURE); } if(msCheckParentPointer(layer->map,"map") == MS_FAILURE) return MS_FAILURE; tagStart = findTag(*line, "shplabel"); /* It is OK to have no shplabel tags, just return. */ if(!tagStart) return MS_SUCCESS; if(!origshape || origshape->numlines <= 0) { /* I suppose we need to make sure the part has vertices (need shape checker?) */ msSetError(MS_WEBERR, "Null or empty shape.", "processShplabelTag()"); return(MS_FAILURE); } while(tagStart) { if(shape) msFreeShape(shape); shape = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(shape); msCopyShape(origshape, shape); projectionString = NULL; format = "$x,$y"; tagOffset = tagStart - *line; if(getTagArgs("shplabel", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "proj"); if(argValue) projectionString = argValue; argValue = msLookupHashTable(tagArgs, "clip_to_map"); if(argValue) { if(strcasecmp(argValue,"false") == 0) clip_to_map = MS_FALSE; } argValue = msLookupHashTable(tagArgs, "use_label_settings"); if(argValue) { if(strcasecmp(argValue,"true") == 0) use_label_settings = MS_TRUE; } } labelPos.x = -1; labelPos.y = -1; msInitShape(&tShape); tShape.type = MS_SHAPE_LINE; tShape.line = (lineObj *) msSmallMalloc(sizeof(lineObj)); tShape.numlines = 1; tShape.line[0].point = NULL; /* initialize the line */ tShape.line[0].numpoints = 0; if(layer->map->cellsize <= 0) cellsize = MS_MAX(MS_CELLSIZE(layer->map->extent.minx, layer->map->extent.maxx, layer->map->width), MS_CELLSIZE(layer->map->extent.miny, layer->map->extent.maxy, layer->map->height)); else cellsize = layer->map->cellsize ; if(shape->type == MS_SHAPE_POINT) { labelposvalid = MS_FALSE; if(shape->numlines > 0 && shape->line[0].numpoints > 0) { labelposvalid = MS_TRUE; labelPos = shape->line[0].point[0]; if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, shape); labelPos = shape->line[0].point[0]; labelPos.x = MS_MAP2IMAGE_X(labelPos.x, layer->map->extent.minx, cellsize); labelPos.y = MS_MAP2IMAGE_Y(labelPos.y, layer->map->extent.maxy, cellsize); } } } else if(shape->type == MS_SHAPE_LINE) { pointObj **annopoints = NULL; double **angles = NULL, **lengths = NULL; int numpoints = 1; labelposvalid = MS_FALSE; if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, shape); if(clip_to_map) msClipPolylineRect(shape, layer->map->extent); msTransformShapeToPixelRound(shape, layer->map->extent, cellsize); } else msOffsetShapeRelativeTo(shape, layer); if(shape->numlines > 0) { annopoints = msPolylineLabelPoint(shape, -1, 0, &angles, &lengths, &numpoints, MS_FALSE); if(numpoints > 0) { /* convert to geo */ labelPos.x = annopoints[0]->x; labelPos.y = annopoints[0]->y; labelposvalid = MS_TRUE; for(i=0; itype == MS_SHAPE_POLYGON) { labelposvalid = MS_FALSE; if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, shape); if(clip_to_map) msClipPolygonRect(shape, layer->map->extent); msTransformShapeToPixelRound(shape, layer->map->extent, cellsize); } else msOffsetShapeRelativeTo(shape, layer); if(shape->numlines > 0) { if(msPolygonLabelPoint(shape, &labelPos, -1) == MS_SUCCESS) { if(labelPos.x == -1 && labelPos.y == -1) labelposvalid = MS_FALSE; else labelposvalid = MS_TRUE; } } } if(labelposvalid == MS_TRUE) { pointObj p1; pointObj p2; int label_offset_x, label_offset_y; labelObj *label=NULL; rectObj r; shapeObj poly; double tmp; msInitShape(&poly); p1.x =labelPos.x; p1.y =labelPos.y; p2.x =labelPos.x; p2.y =labelPos.y; if(use_label_settings == MS_TRUE) { /* RFC 77: classes (and shapes) can have more than 1 piece of annotation, here we only use the first (index=0) */ if(shape->classindex >= 0 && layer->class[shape->classindex]->numlabels > 0) { label = layer->class[shape->classindex]->labels[0]; if(msGetLabelSize(layer->map, label, label->annotext, label->size, &r, NULL) == MS_SUCCESS) { label_offset_x = (int)(label->offsetx*layer->scalefactor); label_offset_y = (int)(label->offsety*layer->scalefactor); p1 = get_metrics(&labelPos, label->position, r, label_offset_x, label_offset_y, label->angle, 0, &poly); /* should we use the point returned from get_metrics?. From few test done, It seems to return the UL corner of the text. For now use the bounds.minx/miny */ p1.x = poly.bounds.minx; p1.y = poly.bounds.miny; p2.x = poly.bounds.maxx; p2.y = poly.bounds.maxy; } } } /* y's are flipped because it is in image coordinate systems */ p1.x = MS_IMAGE2MAP_X(p1.x, layer->map->extent.minx, cellsize); tmp = p1.y; p1.y = MS_IMAGE2MAP_Y(p2.y, layer->map->extent.maxy, cellsize); p2.x = MS_IMAGE2MAP_X(p2.x, layer->map->extent.minx, cellsize); p2.y = MS_IMAGE2MAP_Y(tmp, layer->map->extent.maxy, cellsize); if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) { msProjectPoint(&layer->map->projection, &layer->projection, &p1); msProjectPoint(&layer->map->projection, &layer->projection, &p2); } } msAddPointToLine(&(tShape.line[0]), &p1); msAddPointToLine(&(tShape.line[0]), &p2); } else tShape.numlines = 0; if(projectionString && strcasecmp(projectionString,"image") == 0) { precision = 0; /* if necessary, project the shape to match the map */ if(msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, &tShape); msClipPolylineRect(&tShape, layer->map->extent); msTransformShapeToPixelRound(&tShape, layer->map->extent, layer->map->cellsize); } else if(projectionString) { projectionObj projection; msInitProjection(&projection); status = msLoadProjectionString(&projection, projectionString); if(status != MS_SUCCESS) return MS_FAILURE; if(msProjectionsDiffer(&(layer->projection), &projection)) msProjectShape(&layer->projection, &projection, &tShape); } /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ tagValue = msStrdup(format); if(precision > 0) snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision); else snprintf(numberFormat, sizeof(numberFormat), "%%f"); if(tShape.numlines > 0) { if(strcasestr(tagValue, "$x") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].x); tagValue = msReplaceSubstring(tagValue, "$x", number); } if(strcasestr(tagValue, "$y") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].y); tagValue = msReplaceSubstring(tagValue, "$y", number); } if(strcasestr(tagValue, "$minx") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].x); tagValue = msReplaceSubstring(tagValue, "$minx", number); } if(strcasestr(tagValue, "$miny") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].y); tagValue = msReplaceSubstring(tagValue, "$miny", number); } if(strcasestr(tagValue, "$maxx") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[1].x); tagValue = msReplaceSubstring(tagValue, "$maxx", number); } if(strcasestr(tagValue, "$maxy") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[1].y); tagValue = msReplaceSubstring(tagValue, "$maxy", number); } } /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); *line = msReplaceSubstring(*line, tag, tagValue); /* clean up */ msFreeShape(&tShape); free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; msFree(tagValue); tagValue=NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "shplabel"); else tagStart = NULL; } if(shape) msFreeShape(shape); return(MS_SUCCESS); } /* ** Function to process a [date ...] tag */ static int processDateTag(char **line) { struct tm *datetime; time_t t; int result; char *tag=NULL, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; #define DATE_BUFLEN 1024 char datestr[DATE_BUFLEN]; char *argValue=NULL; char *format, *tz; /* tag parameters */ if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processDateTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "date"); /* It is OK to have no date tags, just return. */ if( !tagStart ) return MS_SUCCESS; while (tagStart) { /* set tag params to defaults */ format = DEFAULT_DATE_FORMAT; tz = ""; tagOffset = tagStart - *line; /* check for any tag arguments */ if(getTagArgs("date", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "tz"); if(argValue) tz = argValue; } t = time(NULL); if( strncasecmp( tz, "gmt", 4 ) == 0 ) { datetime = gmtime(&t); } else { datetime = localtime(&t); } result = strftime(datestr, DATE_BUFLEN, format, datetime); /* Only do the replacement if the date was successfully written */ if( result > 0 ) { /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ *line = msReplaceSubstring(*line, tag, datestr); } /* clean up */ msFree(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "date"); else tagStart = NULL; } return(MS_SUCCESS); } /* ** Function to process a [shpxy ...] tag: line contains the tag, shape holds the coordinates. ** ** TODO's: ** - May need to change attribute names. ** - Need generalization routines (not here, but in mapprimative.c). ** - Try to avoid all the realloc calls. */ static int processShpxyTag(layerObj *layer, char **line, shapeObj *shape) { int i,j,p; int status; char *tag, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; char *argValue=NULL; char *pointFormat1=NULL, *pointFormat2=NULL; int pointFormatLength; /* ** Pointers to static strings, naming convention is: ** char 1/2 - x=x, y=y, c=coordinate, p=part, s=shape, ir=inner ring, or=outer ring ** last char - h=header, f=footer, s=seperator */ char *xh, *xf, *yh, *yf; char *cs; char *ph, *pf, *ps; char *sh, *sf; char *irh, *irf; /* inner ring: necessary for complex polygons */ char *orh, *orf; /* outer ring */ int centroid; int precision; double scale_x, scale_y; char *projectionString=NULL; shapeObj tShape; char *coords=NULL, point[128]; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processShpxyTag()"); return(MS_FAILURE); } if( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tagStart = findTag(*line, "shpxy"); /* It is OK to have no shpxy tags, just return. */ if( !tagStart ) return MS_SUCCESS; if(!shape || shape->numlines <= 0) { /* I suppose we need to make sure the part has vertices (need shape checker?) */ msSetError(MS_WEBERR, "Null or empty shape.", "processShpxyTag()"); return(MS_FAILURE); } while (tagStart) { #ifdef USE_GEOS double buffer = 0; int bufferUnits = -1; #endif xh = yh = yf = ph = pf = sh = sf = ""; /* initialize the tag arguments */ xf= ","; irh = irf = orh = orf = ""; ps = cs = " "; centroid = MS_FALSE; precision = 0; scale_x = scale_y = 1.0; projectionString = NULL; tagOffset = tagStart - *line; /* check for any tag arguments */ if(getTagArgs("shpxy", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "xh"); if(argValue) xh = argValue; argValue = msLookupHashTable(tagArgs, "xf"); if(argValue) xf = argValue; argValue = msLookupHashTable(tagArgs, "yh"); if(argValue) yh = argValue; argValue = msLookupHashTable(tagArgs, "yf"); if(argValue) yf = argValue; argValue = msLookupHashTable(tagArgs, "cs"); if(argValue) cs = argValue; argValue = msLookupHashTable(tagArgs, "irh"); if(argValue) irh = argValue; argValue = msLookupHashTable(tagArgs, "irf"); if(argValue) irf = argValue; argValue = msLookupHashTable(tagArgs, "orh"); if(argValue) orh = argValue; argValue = msLookupHashTable(tagArgs, "orf"); if(argValue) orf = argValue; argValue = msLookupHashTable(tagArgs, "ph"); if(argValue) ph = argValue; argValue = msLookupHashTable(tagArgs, "pf"); if(argValue) pf = argValue; argValue = msLookupHashTable(tagArgs, "ps"); if(argValue) ps = argValue; argValue = msLookupHashTable(tagArgs, "sh"); if(argValue) sh = argValue; argValue = msLookupHashTable(tagArgs, "sf"); if(argValue) sf = argValue; #ifdef USE_GEOS argValue = msLookupHashTable(tagArgs, "buffer"); if(argValue) { buffer = atof(argValue); if(strstr(argValue, "px")) bufferUnits = MS_PIXELS; /* may support others at some point */ } #endif argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "scale"); if(argValue) { scale_x = atof(argValue); scale_y = scale_x; } argValue = msLookupHashTable(tagArgs, "scale_x"); if(argValue) scale_x = atof(argValue); argValue = msLookupHashTable(tagArgs, "scale_y"); if(argValue) scale_y = atof(argValue); argValue = msLookupHashTable(tagArgs, "centroid"); if(argValue) if(strcasecmp(argValue,"true") == 0) centroid = MS_TRUE; argValue = msLookupHashTable(tagArgs, "proj"); if(argValue) projectionString = argValue; } /* build the per point format strings (version 1 contains the coordinate seperator, version 2 doesn't) */ pointFormatLength = strlen(xh) + strlen(xf) + strlen(yh) + strlen(yf) + strlen(cs) + 12 + 1; pointFormat1 = (char *) msSmallMalloc(pointFormatLength); snprintf(pointFormat1, pointFormatLength, "%s%%.%dlf%s%s%%.%dlf%s%s", xh, precision, xf, yh, precision, yf, cs); pointFormat2 = (char *) msSmallMalloc(pointFormatLength); snprintf(pointFormat2, pointFormatLength, "%s%%.%dlf%s%s%%.%dlf%s", xh, precision, xf, yh, precision, yf); /* make a copy of the original shape or compute a centroid if necessary */ msInitShape(&tShape); if(centroid == MS_TRUE) { pointObj p; p.x = (shape->bounds.minx + shape->bounds.maxx)/2; p.y = (shape->bounds.miny + shape->bounds.maxy)/2; tShape.type = MS_SHAPE_POINT; tShape.line = (lineObj *) msSmallMalloc(sizeof(lineObj)); tShape.numlines = 1; tShape.line[0].point = NULL; /* initialize the line */ tShape.line[0].numpoints = 0; msAddPointToLine(&(tShape.line[0]), &p); } #ifdef USE_GEOS else if(buffer != 0 && bufferUnits != MS_PIXELS) { shapeObj *bufferShape=NULL; bufferShape = msGEOSBuffer(shape, buffer); if(!bufferShape) return(MS_FAILURE); /* buffer failed */ msCopyShape(bufferShape, &tShape); msFreeShape(bufferShape); } #endif else { status = msCopyShape(shape, &tShape); if(status != 0) return(MS_FAILURE); /* copy failed */ } /* no big deal to convert from file to image coordinates, but what are the image parameters */ if(projectionString && strcasecmp(projectionString,"image") == 0) { precision = 0; /* if necessary, project the shape to match the map */ if(msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, &tShape); switch(tShape.type) { case(MS_SHAPE_POINT): /* at this point we only convert the first point of the first shape */ tShape.line[0].point[0].x = MS_MAP2IMAGE_X(tShape.line[0].point[0].x, layer->map->extent.minx, layer->map->cellsize); tShape.line[0].point[0].y = MS_MAP2IMAGE_Y(tShape.line[0].point[0].y, layer->map->extent.maxy, layer->map->cellsize); break; case(MS_SHAPE_LINE): msClipPolylineRect(&tShape, layer->map->extent); break; case(MS_SHAPE_POLYGON): msClipPolygonRect(&tShape, layer->map->extent); break; default: /* TO DO: need an error message here */ return(MS_FAILURE); break; } msTransformShapeToPixelRound(&tShape, layer->map->extent, layer->map->cellsize); #ifdef USE_GEOS if(buffer != 0 && bufferUnits == MS_PIXELS) { shapeObj *bufferShape=NULL; bufferShape = msGEOSBuffer(&tShape, buffer); if(!bufferShape) { if(!msIsDegenerateShape(&tShape)) /* If shape is degenerate this is expected. */ return(MS_FAILURE); /* buffer failed */ } else { msFreeShape(&tShape); /* avoid memory leak */ msCopyShape(bufferShape, &tShape); msFreeShape(bufferShape); } } #endif } else if(projectionString) { projectionObj projection; msInitProjection(&projection); status = msLoadProjectionString(&projection, projectionString); if(status != MS_SUCCESS) return MS_FAILURE; if(msProjectionsDiffer(&(layer->projection), &projection)) msProjectShape(&layer->projection, &projection, &tShape); } /* TODO: add thinning support here */ /* ** build the coordinate string */ if(strlen(sh) > 0) coords = msStringConcatenate(coords, sh); /* do we need to handle inner/outer rings */ if(tShape.type == MS_SHAPE_POLYGON && strlen(orh) > 0 && strlen(irh) > 0) { int *outers; int firstPart; /* to keep track of inserting part separators before each part after the first */ outers = msGetOuterList( &tShape ); firstPart = 1; /* loop over rings looking for outers*/ for(i=0; i 0)) coords = msStringConcatenate(coords, ps); firstPart = 0; if(strlen(ph) > 0) coords = msStringConcatenate(coords, ph); coords = msStringConcatenate(coords, orh); for(p=0; p 0) coords = msStringConcatenate(coords, pf); } } /* end of loop over outer rings */ free( outers ); } else { /* output without ring formatting */ for(i=0; i 0) coords = msStringConcatenate(coords, ph); for(p=0; p 0) coords = msStringConcatenate(coords, pf); if((i < tShape.numlines-1) && (strlen(ps) > 0)) coords = msStringConcatenate(coords, ps); } } if(strlen(sf) > 0) coords = msStringConcatenate(coords, sf); msFreeShape(&tShape); /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ *line = msReplaceSubstring(*line, tag, coords); /* clean up */ free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; free(pointFormat1); pointFormat1 = NULL; free(pointFormat2); pointFormat2 = NULL; free(coords); coords = NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "shpxy"); else tagStart = NULL; } return(MS_SUCCESS); } /*! * this function process all metadata * in pszInstr. ht mus contain all corresponding * metadata value. * * this function return a modified pszInstr */ int processMetadata(char** pszInstr, hashTableObj *ht) { /* char *pszNextInstr = pszInstr; */ char *pszEnd, *pszStart; char *pszMetadataTag; char *pszHashName; char *pszHashValue; int nLength, nOffset; hashTableObj *metadataArgs = NULL; if(!*pszInstr) { msSetError(MS_WEBERR, "Invalid pointer.", "processMetadata()"); return MS_FAILURE; } /* set position to the begining of metadata tag */ pszStart = findTag(*pszInstr, "metadata"); while (pszStart) { /* get metadata args */ if(getTagArgs("metadata", pszStart, &metadataArgs) != MS_SUCCESS) return MS_FAILURE; pszHashName = msLookupHashTable(metadataArgs, "name"); pszHashValue = msLookupHashTable(ht, pszHashName); nOffset = pszStart - *pszInstr; if(pszHashName && pszHashValue) { /* set position to the end of metadata start tag */ pszEnd = strchr(pszStart, ']'); pszEnd++; /* build the complete metadata tag ([metadata all_args]) */ /* to replace it by the corresponding value from ht */ nLength = pszEnd - pszStart; pszMetadataTag = (char*)msSmallMalloc(nLength + 1); strlcpy(pszMetadataTag, pszStart, nLength+1); *pszInstr = msReplaceSubstring(*pszInstr, pszMetadataTag, pszHashValue); free(pszMetadataTag); pszMetadataTag=NULL; } msFreeHashTable(metadataArgs); metadataArgs=NULL; /* set position to the begining of the next metadata tag */ if((*pszInstr)[nOffset] != '\0') pszStart = findTag(*pszInstr+nOffset+1, "metadata"); else pszStart = NULL; } return MS_SUCCESS; } /*! * this function process all icon tag * from pszInstr. * * This func return a modified pszInstr. */ int processIcon(mapObj *map, int nIdxLayer, int nIdxClass, char** pszInstr, char* pszPrefix) { int nWidth, nHeight, nLen; char szImgFname[1024], *pszFullImgFname=NULL, *pszImgTag; char szPath[MS_MAXPATHLEN]; hashTableObj *myHashTable=NULL; FILE *fIcon; if(!map || nIdxLayer > map->numlayers || nIdxLayer < 0 ) { msSetError(MS_WEBERR, "Invalid pointer.", "processIcon()"); return MS_FAILURE; } /* find the begining of tag */ pszImgTag = strstr(*pszInstr, "[leg_icon"); while (pszImgTag) { int i; char szStyleCode[512] = ""; classObj *thisClass=NULL; /* It's okay to have no classes... we'll generate an empty icon in this case */ if(nIdxClass >= 0 && nIdxClass < GET_LAYER(map, nIdxLayer)->numclasses) thisClass = GET_LAYER(map, nIdxLayer)->class[nIdxClass]; if(getTagArgs("leg_icon", pszImgTag, &myHashTable) != MS_SUCCESS) return MS_FAILURE; /* if no specified width or height, set them to map default */ if(!msLookupHashTable(myHashTable, "width") || !msLookupHashTable(myHashTable, "height")) { nWidth = map->legend.keysizex; nHeight= map->legend.keysizey; } else { nWidth = atoi(msLookupHashTable(myHashTable, "width")); nHeight = atoi(msLookupHashTable(myHashTable, "height")); } /* Create a unique and predictable filename to cache the legend icons. * Include some key parameters from the first 2 styles */ for(i=0; i<2 && thisClass && inumstyles; i++) { styleObj *style; char *pszSymbolNameHash = NULL; style = thisClass->styles[i]; if(style->symbolname) pszSymbolNameHash = msHashString(style->symbolname); snprintf(szStyleCode+strlen(szStyleCode), 255, "s%d_%x_%x_%x_%d_%s_%g", i, MS_COLOR_GETRGB(style->color), MS_COLOR_GETRGB(style->backgroundcolor), MS_COLOR_GETRGB(style->outlinecolor), style->symbol, pszSymbolNameHash?pszSymbolNameHash:"", style->angle); msFree(pszSymbolNameHash); } snprintf(szImgFname, sizeof(szImgFname), "%s_%d_%d_%d_%d_%s.%s%c", pszPrefix, nIdxLayer, nIdxClass, nWidth, nHeight, szStyleCode, MS_IMAGE_EXTENSION(map->outputformat),'\0'); pszFullImgFname = msStrdup(msBuildPath3(szPath, map->mappath, map->web.imagepath, szImgFname)); /* check if icon already exist in cache */ if((fIcon = fopen(pszFullImgFname, "r")) != NULL) { /* File already exists. No need to generate it again */ fclose(fIcon); } else { /* Create an image corresponding to the current class */ imageObj *img=NULL; if(thisClass == NULL) { /* Nonexistent class. Create an empty image */ img = msCreateLegendIcon(map, NULL, NULL, nWidth, nHeight, MS_TRUE); } else { img = msCreateLegendIcon(map, GET_LAYER(map, nIdxLayer), thisClass, nWidth, nHeight, MS_TRUE); } if(!img) { if(myHashTable) msFreeHashTable(myHashTable); msSetError(MS_GDERR, "Error while creating GD image.", "processIcon()"); return MS_FAILURE; } /* save it with a unique file name */ if(msSaveImage(map, img, pszFullImgFname) != MS_SUCCESS) { if(myHashTable) msFreeHashTable(myHashTable); msFreeImage(img); msSetError(MS_IOERR, "Error saving GD image to disk (%s).", "processIcon()", pszFullImgFname); msFree(pszFullImgFname); return MS_FAILURE; } msFreeImage(img); } msFree(pszFullImgFname); pszFullImgFname = NULL; nLen = (strchr(pszImgTag, ']') + 1) - pszImgTag; if(nLen > 0) { char *pszTag; /* rebuid image tag ([leg_class_img all_args]) */ /* to replace it by the image url */ pszTag = (char*)msSmallMalloc(nLen + 1); strlcpy(pszTag, pszImgTag, nLen+1); pszFullImgFname = (char*)msSmallMalloc(strlen(map->web.imageurl) + strlen(szImgFname) + 1); strcpy(pszFullImgFname, map->web.imageurl); strcat(pszFullImgFname, szImgFname); *pszInstr = msReplaceSubstring(*pszInstr, pszTag, pszFullImgFname); msFree(pszFullImgFname); pszFullImgFname = NULL; msFree(pszTag); /* find the begining of tag */ pszImgTag = strstr(*pszInstr, "[leg_icon"); } else { pszImgTag = NULL; } if(myHashTable) { msFreeHashTable(myHashTable); myHashTable = NULL; } } return MS_SUCCESS; } /*! * Replace all tags from group template * with correct value. * * this function return a buffer containing * the template with correct values. * * buffer must be freed by caller. */ int generateGroupTemplate(char* pszGroupTemplate, mapObj *map, char* pszGroupName, hashTableObj *oGroupArgs, char **pszTemp, char* pszPrefix) { hashTableObj *myHashTable; char pszStatus[3]; char *pszClassImg; char *pszOptFlag = NULL; int i, j; int nOptFlag = 15; int bShowGroup; *pszTemp = NULL; if(!pszGroupName || !pszGroupTemplate) { msSetError(MS_WEBERR, "Invalid pointer.", "generateGroupTemplate()"); return MS_FAILURE; } /* * Get the opt_flag is any. */ if(oGroupArgs) pszOptFlag = msLookupHashTable(oGroupArgs, "opt_flag"); if(pszOptFlag) nOptFlag = atoi(pszOptFlag); /* * Check all layers, if one in the group * should be visible, print the group. * (Check for opt_flag) */ bShowGroup = 0; for (j=0; jnumlayers; j++) { if(GET_LAYER(map, map->layerorder[j])->group && strcmp(GET_LAYER(map, map->layerorder[j])->group, pszGroupName) == 0) { /* dont display layer is off. */ if( (nOptFlag & 2) == 0 && GET_LAYER(map, map->layerorder[j])->status == MS_OFF ) bShowGroup = 0; else bShowGroup = 1; /* dont display layer is query. */ if( (nOptFlag & 4) == 0 && GET_LAYER(map, map->layerorder[j])->type == MS_LAYER_QUERY ) bShowGroup = 0; /* dont display layer is annotation. */ if( (nOptFlag & 8) == 0 && GET_LAYER(map, map->layerorder[j])->type == MS_LAYER_ANNOTATION ) bShowGroup = 0; /* dont display layer if out of scale. */ if((nOptFlag & 1) == 0) { if(map->scaledenom > 0) { if((GET_LAYER(map, map->layerorder[j])->maxscaledenom > 0) && (map->scaledenom > GET_LAYER(map, map->layerorder[j])->maxscaledenom)) bShowGroup = 0; if((GET_LAYER(map, map->layerorder[j])->minscaledenom > 0) && (map->scaledenom <= GET_LAYER(map, map->layerorder[j])->minscaledenom)) bShowGroup = 0; } } /* The group contains one visible layer */ /* Draw the group */ if( bShowGroup ) break; } } if( ! bShowGroup ) return MS_SUCCESS; /* * Work from a copy */ *pszTemp = (char*)msSmallMalloc(strlen(pszGroupTemplate) + 1); strcpy(*pszTemp, pszGroupTemplate); /* * Change group tags */ *pszTemp = msReplaceSubstring(*pszTemp, "[leg_group_name]", pszGroupName); /* * Create a hash table that contain info * on current layer */ myHashTable = msCreateHashTable(); /* * Check for the first layer * that belong to this group. * Get his status and check for if. */ for (j=0; jnumlayers; j++) { if(GET_LAYER(map, map->layerorder[j])->group && strcmp(GET_LAYER(map, map->layerorder[j])->group, pszGroupName) == 0) { snprintf(pszStatus, sizeof(pszStatus), "%d", GET_LAYER(map, map->layerorder[j])->status); msInsertHashTable(myHashTable, "layer_status", pszStatus); msInsertHashTable(myHashTable, "layer_visible", msLayerIsVisible(map, GET_LAYER(map, map->layerorder[j]))?"1":"0" ); msInsertHashTable(myHashTable, "layer_queryable", msIsLayerQueryable(GET_LAYER(map, map->layerorder[j]))?"1":"0" ); msInsertHashTable(myHashTable, "group_name", pszGroupName); if(processIfTag(pszTemp, myHashTable, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(GET_LAYER(map, map->layerorder[j])->metadata), MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processMetadata(pszTemp, &GET_LAYER(map, map->layerorder[j])->metadata) != MS_SUCCESS) return MS_FAILURE; break; } } msFreeHashTable(myHashTable); /* * Process all metadata tags * only web object is accessible */ if(processMetadata(pszTemp, &(map->web.metadata)) != MS_SUCCESS) return MS_FAILURE; /* * check for if tag */ if(processIfTag(pszTemp, &(map->web.metadata), MS_TRUE) != MS_SUCCESS) return MS_FAILURE; /* * Check if leg_icon tag exist * if so display the first layer first class icon */ pszClassImg = strstr(*pszTemp, "[leg_icon"); if(pszClassImg) { /* find first layer of this group */ for (i=0; inumlayers; i++) if(GET_LAYER(map, map->layerorder[i])->group && strcmp(GET_LAYER(map, map->layerorder[i])->group, pszGroupName) == 0) processIcon(map, map->layerorder[i], 0, pszTemp, pszPrefix); } return MS_SUCCESS; } /*! * Replace all tags from layer template * with correct value. * * this function return a buffer containing * the template with correct values. * * buffer must be freed by caller. */ int generateLayerTemplate(char *pszLayerTemplate, mapObj *map, int nIdxLayer, hashTableObj *oLayerArgs, char **pszTemp, char* pszPrefix) { hashTableObj *myHashTable; char szStatus[10]; char szType[10]; int nOptFlag=0; char *pszOptFlag = NULL; char *pszClassImg; char szTmpstr[128]; /* easily big enough for the couple of instances we need */ *pszTemp = NULL; if(!pszLayerTemplate || !map || nIdxLayer > map->numlayers || nIdxLayer < 0 ) { msSetError(MS_WEBERR, "Invalid pointer.", "generateLayerTemplate()"); return MS_FAILURE; } if(oLayerArgs) pszOptFlag = msLookupHashTable(oLayerArgs, "opt_flag"); if(pszOptFlag) nOptFlag = atoi(pszOptFlag); /* don't display deleted layers */ if(GET_LAYER(map, nIdxLayer)->status == MS_DELETE) return MS_SUCCESS; /* dont display layer is off. */ /* check this if Opt flag is not set */ if((nOptFlag & 2) == 0 && GET_LAYER(map, nIdxLayer)->status == MS_OFF) return MS_SUCCESS; /* dont display layer is query. */ /* check this if Opt flag is not set */ if((nOptFlag & 4) == 0 && GET_LAYER(map, nIdxLayer)->type == MS_LAYER_QUERY) return MS_SUCCESS; /* dont display layer is annotation. */ /* check this if Opt flag is not set */ if((nOptFlag & 8) == 0 && GET_LAYER(map, nIdxLayer)->type == MS_LAYER_ANNOTATION) return MS_SUCCESS; /* dont display layer if out of scale. */ /* check this if Opt flag is not set */ if((nOptFlag & 1) == 0) { if(map->scaledenom > 0) { if((GET_LAYER(map, nIdxLayer)->maxscaledenom > 0) && (map->scaledenom > GET_LAYER(map, nIdxLayer)->maxscaledenom)) return MS_SUCCESS; if((GET_LAYER(map, nIdxLayer)->minscaledenom > 0) && (map->scaledenom <= GET_LAYER(map, nIdxLayer)->minscaledenom)) return MS_SUCCESS; } } /* * Work from a copy */ *pszTemp = msStrdup(pszLayerTemplate); /* * Change layer tags */ *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_name]", GET_LAYER(map, nIdxLayer)->name); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_group]", GET_LAYER(map, nIdxLayer)->group); snprintf(szTmpstr, sizeof(szTmpstr), "%d", nIdxLayer); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_index]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->minscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_minscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_minscaledenom]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->maxscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_maxscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_maxscaledenom]", szTmpstr); /* * Create a hash table that contain info * on current layer */ myHashTable = msCreateHashTable(); /* * for now, only status and type is required by template */ snprintf(szStatus, sizeof(szStatus), "%d", GET_LAYER(map, nIdxLayer)->status); msInsertHashTable(myHashTable, "layer_status", szStatus); snprintf(szType, sizeof(szType), "%d", GET_LAYER(map, nIdxLayer)->type); msInsertHashTable(myHashTable, "layer_type", szType); msInsertHashTable(myHashTable, "layer_name", (GET_LAYER(map, nIdxLayer)->name)? GET_LAYER(map, nIdxLayer)->name : ""); msInsertHashTable(myHashTable, "layer_group", (GET_LAYER(map, nIdxLayer)->group)? GET_LAYER(map, nIdxLayer)->group : ""); msInsertHashTable(myHashTable, "layer_visible", msLayerIsVisible(map, GET_LAYER(map, nIdxLayer))?"1":"0" ); msInsertHashTable(myHashTable, "layer_queryable", msIsLayerQueryable(GET_LAYER(map, nIdxLayer))?"1":"0" ); if(processIfTag(pszTemp, myHashTable, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(GET_LAYER(map, nIdxLayer)->metadata), MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(map->web.metadata), MS_TRUE) != MS_SUCCESS) return MS_FAILURE; msFreeHashTable(myHashTable); /* * Check if leg_icon tag exist * if so display the first class icon */ pszClassImg = strstr(*pszTemp, "[leg_icon"); if(pszClassImg) { processIcon(map, nIdxLayer, 0, pszTemp, pszPrefix); } /* process all metadata tags * only current layer and web object * metaddata are accessible */ if(processMetadata(pszTemp, &GET_LAYER(map, nIdxLayer)->metadata) != MS_SUCCESS) return MS_FAILURE; if(processMetadata(pszTemp, &(map->web.metadata)) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } /*! * Replace all tags from class template * with correct value. * * this function return a buffer containing * the template with correct values. * * buffer must be freed by caller. */ int generateClassTemplate(char* pszClassTemplate, mapObj *map, int nIdxLayer, int nIdxClass, hashTableObj *oClassArgs, char **pszTemp, char* pszPrefix) { hashTableObj *myHashTable; char szStatus[10]; char szType[10]; char *pszClassImg; int nOptFlag=0; char *pszOptFlag = NULL; char szTmpstr[128]; /* easily big enough for the couple of instances we need */ *pszTemp = NULL; if(!pszClassTemplate || !map || nIdxLayer > map->numlayers || nIdxLayer < 0 || nIdxClass > GET_LAYER(map, nIdxLayer)->numclasses || nIdxClass < 0) { msSetError(MS_WEBERR, "Invalid pointer.", "generateClassTemplate()"); return MS_FAILURE; } if(oClassArgs) pszOptFlag = msLookupHashTable(oClassArgs, "Opt_flag"); if(pszOptFlag) nOptFlag = atoi(pszOptFlag); /* don't display deleted layers */ if(GET_LAYER(map, nIdxLayer)->status == MS_DELETE) return MS_SUCCESS; /* dont display class if layer is off. */ /* check this if Opt flag is not set */ if((nOptFlag & 2) == 0 && GET_LAYER(map, nIdxLayer)->status == MS_OFF) return MS_SUCCESS; /* dont display class if layer is query. */ /* check this if Opt flag is not set */ if((nOptFlag & 4) == 0 && GET_LAYER(map, nIdxLayer)->type == MS_LAYER_QUERY) return MS_SUCCESS; /* dont display class if layer is annotation. */ /* check this if Opt flag is not set */ if((nOptFlag & 8) == 0 && GET_LAYER(map, nIdxLayer)->type == MS_LAYER_ANNOTATION) return MS_SUCCESS; /* dont display layer if out of scale. */ /* check this if Opt flag is not set */ if((nOptFlag & 1) == 0) { if(map->scaledenom > 0) { if((GET_LAYER(map, nIdxLayer)->maxscaledenom > 0) && (map->scaledenom > GET_LAYER(map, nIdxLayer)->maxscaledenom)) return MS_SUCCESS; if((GET_LAYER(map, nIdxLayer)->minscaledenom > 0) && (map->scaledenom <= GET_LAYER(map, nIdxLayer)->minscaledenom)) return MS_SUCCESS; } } /* * Work from a copy */ *pszTemp = (char*)msSmallMalloc(strlen(pszClassTemplate) + 1); strcpy(*pszTemp, pszClassTemplate); /* * Change class tags */ *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_name]", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->name); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_title]", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->title); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_name]", GET_LAYER(map, nIdxLayer)->name); snprintf(szTmpstr, sizeof(szTmpstr), "%d", nIdxClass); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_index]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->minscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_minscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_minscaledenom]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->maxscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_maxscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_maxscaledenom]", szTmpstr); /* * Create a hash table that contain info * on current layer */ myHashTable = msCreateHashTable(); /* * for now, only status, type, name and group are required by template */ snprintf(szStatus, sizeof(szStatus), "%d", GET_LAYER(map, nIdxLayer)->status); msInsertHashTable(myHashTable, "layer_status", szStatus); snprintf(szType, sizeof(szType), "%d", GET_LAYER(map, nIdxLayer)->type); msInsertHashTable(myHashTable, "layer_type", szType); msInsertHashTable(myHashTable, "layer_name", (GET_LAYER(map, nIdxLayer)->name)? GET_LAYER(map, nIdxLayer)->name : ""); msInsertHashTable(myHashTable, "layer_group", (GET_LAYER(map, nIdxLayer)->group)? GET_LAYER(map, nIdxLayer)->group : ""); msInsertHashTable(myHashTable, "layer_visible", msLayerIsVisible(map, GET_LAYER(map, nIdxLayer))?"1":"0" ); msInsertHashTable(myHashTable, "layer_queryable", msIsLayerQueryable(GET_LAYER(map, nIdxLayer))?"1":"0" ); msInsertHashTable(myHashTable, "class_name", (GET_LAYER(map, nIdxLayer)->class[nIdxClass]->name)? GET_LAYER(map, nIdxLayer)->class[nIdxClass]->name : ""); if(processIfTag(pszTemp, myHashTable, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(GET_LAYER(map, nIdxLayer)->metadata), MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(map->web.metadata), MS_TRUE) != MS_SUCCESS) return MS_FAILURE; msFreeHashTable(myHashTable); /* * Check if leg_icon tag exist */ pszClassImg = strstr(*pszTemp, "[leg_icon"); if(pszClassImg) { processIcon(map, nIdxLayer, nIdxClass, pszTemp, pszPrefix); } /* process all metadata tags * only current layer and web object * metaddata are accessible */ if(processMetadata(pszTemp, &GET_LAYER(map, nIdxLayer)->metadata) != MS_SUCCESS) return MS_FAILURE; if(processMetadata(pszTemp, &(map->web.metadata)) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } char *generateLegendTemplate(mapservObj *mapserv) { FILE *stream; char *file = NULL; int length; char *pszResult = NULL; char *legGroupHtml = NULL; char *legLayerHtml = NULL; char *legClassHtml = NULL; char *legLayerHtmlCopy = NULL; char *legClassHtmlCopy = NULL; char *legGroupHtmlCopy = NULL; char *legHeaderHtml = NULL; char *legFooterHtml = NULL; char *pszPrefix = NULL; char *pszMapFname = NULL; struct stat tmpStat; char *pszOrderMetadata = NULL; char *pszOrder = NULL; int i,j,k; char **papszGroups = NULL; int nGroupNames = 0; int nLegendOrder = 0; char *pszOrderValue; hashTableObj *groupArgs = NULL; hashTableObj *layerArgs = NULL; hashTableObj *classArgs = NULL; ms_regex_t re; /* compiled regular expression to be matched */ int *panCurrentDrawingOrder = NULL; char szPath[MS_MAXPATHLEN]; if(ms_regcomp(&re, MS_TEMPLATE_EXPR, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { msSetError(MS_IOERR, "Error regcomp.", "generateLegendTemplate()"); return NULL; } if(ms_regexec(&re, mapserv->map->legend.template, 0, NULL, 0) != 0) { /* no match */ msSetError(MS_IOERR, "Invalid template file name.", "generateLegendTemplate()"); ms_regfree(&re); return NULL; } ms_regfree(&re); /* -------------------------------------------------------------------- */ /* Save the current drawing order. The drawing order is reset */ /* at the end of the function. */ /* -------------------------------------------------------------------- */ if(mapserv && mapserv->map && mapserv->map->numlayers > 0) { panCurrentDrawingOrder = (int *)msSmallMalloc(sizeof(int)*mapserv->map->numlayers); for (i=0; imap->numlayers; i++) { if(mapserv->map->layerorder) panCurrentDrawingOrder[i] = mapserv->map->layerorder[i]; else panCurrentDrawingOrder[i] = i; } } /* * build prefix filename * for legend icon creation */ for(i=0; irequest->NumParams; i++) /* find the mapfile parameter first */ if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break; if(i == mapserv->request->NumParams) { if( getenv("MS_MAPFILE")) pszMapFname = msStringConcatenate(pszMapFname, getenv("MS_MAPFILE")); } else { if(getenv(mapserv->request->ParamValues[i])) /* an environment references the actual file to use */ pszMapFname = msStringConcatenate(pszMapFname, getenv(mapserv->request->ParamValues[i])); else pszMapFname = msStringConcatenate(pszMapFname, mapserv->request->ParamValues[i]); } if(pszMapFname) { if(stat(pszMapFname, &tmpStat) != -1) { int nLen; nLen = (mapserv->map->name?strlen(mapserv->map->name):0) + 50; pszPrefix = (char*)msSmallMalloc((nLen+1) * sizeof(char)); snprintf(pszPrefix, nLen, "%s_%ld_%ld", mapserv->map->name, (long) tmpStat.st_size, (long) tmpStat.st_mtime); pszPrefix[nLen] = '\0'; } free(pszMapFname); pszMapFname = NULL; } else { /* -------------------------------------------------------------------- */ /* map file name may not be avaible when the template functions */ /* are called from mapscript. Use the time stamp as prefix. */ /* -------------------------------------------------------------------- */ char pszTime[20]; snprintf(pszTime, sizeof(pszTime), "%ld", (long)time(NULL)); pszPrefix = msStringConcatenate(pszPrefix, pszTime); } /* open template */ if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, mapserv->map->legend.template), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening template file.", "generateLegendTemplate()"); return NULL; } fseek(stream, 0, SEEK_END); length = ftell(stream); rewind(stream); file = (char*)msSmallMalloc(length + 1); if(!file) { msSetError(MS_IOERR, "Error while allocating memory for template file.", "generateLegendTemplate()"); fclose(stream); return NULL; } /* * Read all the template file */ fread(file, length, 1, stream); /* Disabled for now due to Windows issue, see ticket #3814 if( 1 != fread(file, length, 1, stream)) { msSetError(MS_IOERR, "Error while reading template file.", "generateLegendTemplate()"); free(file); fclose(stream); return NULL; } */ file[length] = '\0'; if(msValidateContexts(mapserv->map) != MS_SUCCESS) return NULL; /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */ /* * Seperate header/footer, groups, layers and class */ getInlineTag("leg_header_html", file, &legHeaderHtml); getInlineTag("leg_footer_html", file, &legFooterHtml); getInlineTag("leg_group_html", file, &legGroupHtml); getInlineTag("leg_layer_html", file, &legLayerHtml); getInlineTag("leg_class_html", file, &legClassHtml); /* * Retrieve arguments of all three parts */ if(legGroupHtml) if(getTagArgs("leg_group_html", file, &groupArgs) != MS_SUCCESS) return NULL; if(legLayerHtml) if(getTagArgs("leg_layer_html", file, &layerArgs) != MS_SUCCESS) return NULL; if(legClassHtml) if(getTagArgs("leg_class_html", file, &classArgs) != MS_SUCCESS) return NULL; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if(msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom) != MS_SUCCESS) return(NULL); /* start with the header if present */ if(legHeaderHtml) pszResult = msStringConcatenate(pszResult, legHeaderHtml); /********************************************************************/ /* * order layers if order_metadata args is set * If not, keep default order */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(sortLayerByMetadata(mapserv->map, pszOrderMetadata) != MS_SUCCESS) goto error; /* -------------------------------------------------------------------- */ /* if the order tag is set to ascending or descending, the */ /* current order will be changed to correspond to that. */ /* -------------------------------------------------------------------- */ pszOrder = msLookupHashTable(layerArgs, "order"); if(pszOrder && ((strcasecmp(pszOrder, "ASCENDING") == 0) || (strcasecmp(pszOrder, "DESCENDING") == 0))) { if(sortLayerByOrder(mapserv->map, pszOrder) != MS_SUCCESS) goto error; } if(legGroupHtml) { /* retrieve group names */ papszGroups = msGetAllGroupNames(mapserv->map, &nGroupNames); for (i=0; imap, papszGroups[i], groupArgs, &legGroupHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate it to final result */ pszResult = msStringConcatenate(pszResult, legGroupHtmlCopy); /* if(!pszResult) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } */ if(legGroupHtmlCopy) { free(legGroupHtmlCopy); legGroupHtmlCopy = NULL; } /* for all layers in group */ if(legLayerHtml) { for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } if(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group && strcmp(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group, papszGroups[i]) == 0) { /* process all layer tags */ if(generateLayerTemplate(legLayerHtml, mapserv->map, mapserv->map->layerorder[j], layerArgs, &legLayerHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legLayerHtmlCopy); if(legLayerHtmlCopy) { free(legLayerHtmlCopy); legLayerHtmlCopy = NULL; } /* for all classes in layer */ if(legClassHtml) { for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { /* process all class tags */ if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } } else if(legClassHtml) { /* no layer template specified but class and group template */ for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } if(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group && strcmp(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group, papszGroups[i]) == 0) { /* for all classes in layer */ if(legClassHtml) { for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { /* process all class tags */ if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } } } } else { /* if no group template specified */ if(legLayerHtml) { for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } else nLegendOrder=0; } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } /* process a layer tags */ if(generateLayerTemplate(legLayerHtml, mapserv->map, mapserv->map->layerorder[j], layerArgs, &legLayerHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legLayerHtmlCopy); if(legLayerHtmlCopy) { free(legLayerHtmlCopy); legLayerHtmlCopy = NULL; } /* for all classes in layer */ if(legClassHtml) { for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { /* process all class tags */ if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } else { /* if no group and layer template specified */ if(legClassHtml) { for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } } /* finish with the footer if present */ if(legFooterHtml) pszResult = msStringConcatenate(pszResult, legFooterHtml); /* * if we reach this point, that mean no error was generated. * So check if template is null and initialize it to . */ if(pszResult == NULL) { pszResult = msStringConcatenate(pszResult, " "); } /********************************************************************/ error: if(papszGroups) { for (i=0; imap->layerorder) { for (i=0; imap->numlayers; i++) mapserv->map->layerorder[i] = panCurrentDrawingOrder[i]; free(panCurrentDrawingOrder); } return pszResult; } char *processOneToManyJoin(mapservObj* mapserv, joinObj *join) { int records=MS_FALSE; FILE *stream=NULL; char *outbuf; char line[MS_BUFFER_LENGTH], *tmpline; char szPath[MS_MAXPATHLEN]; if((outbuf = msStrdup("")) == NULL) return(NULL); /* empty at first */ msJoinPrepare(join, &(mapserv->resultshape)); /* execute the join */ while(msJoinNext(join) == MS_SUCCESS) { /* First time through, deal with the header (if necessary) and open the main template. We only */ /* want to do this if there are joined records. */ if(records == MS_FALSE) { if(join->header != NULL) { if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, join->header), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening join header file %s.", "processOneToManyJoin()", join->header); return(NULL); } if(isValidTemplate(stream, join->header) != MS_TRUE) { fclose(stream); return NULL; } /* echo file to the output buffer, no substitutions */ while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) outbuf = msStringConcatenate(outbuf, line); fclose(stream); } if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, join->template), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening join template file %s.", "processOneToManyJoin()", join->template); return(NULL); } if(isValidTemplate(stream, join->template) != MS_TRUE) { fclose(stream); return NULL; } records = MS_TRUE; } while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) { /* now on to the end of the template */ if(strchr(line, '[') != NULL) { tmpline = processLine(mapserv, line, NULL, QUERY); /* no multiline tags are allowed in a join */ if(!tmpline) return NULL; outbuf = msStringConcatenate(outbuf, tmpline); free(tmpline); } else /* no subs, just echo */ outbuf = msStringConcatenate(outbuf, line); } rewind(stream); fgets(line, MS_BUFFER_LENGTH, stream); /* skip the first line since it's the magic string */ } /* next record */ if(records==MS_TRUE && join->footer) { if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, join->footer), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening join footer file %s.", "processOneToManyJoin()", join->footer); return(NULL); } if(isValidTemplate(stream, join->footer) != MS_TRUE) { fclose(stream); return NULL; } /* echo file to the output buffer, no substitutions */ while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) outbuf = msStringConcatenate(outbuf, line); fclose(stream); } /* clear any data associated with the join */ msFreeCharArray(join->values, join->numitems); join->values = NULL; return(outbuf); } /* ** Process a single line in the template. A few tags (e.g. [resultset]...[/resultset]) can be multi-line so ** we pass the filehandle to look ahead if necessary. */ static char *processLine(mapservObj *mapserv, char *instr, FILE *stream, int mode) { int i, j; #define PROCESSLINE_BUFLEN 5120 char repstr[PROCESSLINE_BUFLEN], substr[PROCESSLINE_BUFLEN], *outstr; /* repstr = replace string, substr = sub string */ struct hashObj *tp=NULL; char *encodedstr; #ifdef USE_PROJ rectObj llextent; pointObj llpoint; #endif outstr = msStrdup(instr); /* work from a copy */ if(strstr(outstr, "[version]")) outstr = msReplaceSubstring(outstr, "[version]", msGetVersion()); snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[img]", repstr); snprintf(repstr, PROCESSLINE_BUFLEN, "%s%sref%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[ref]", repstr); if(strstr(outstr, "[errmsg")) { char *errmsg = msGetErrorString(";"); if(!errmsg) errmsg = msStrdup("Error message buffer is empty."); /* should never happen, but just in case... */ outstr = msReplaceSubstring(outstr, "[errmsg]", errmsg); encodedstr = msEncodeUrl(errmsg); outstr = msReplaceSubstring(outstr, "[errmsg_esc]", encodedstr); free(errmsg); free(encodedstr); } if(strstr(outstr, "[legend]")) { /* if there's a template legend specified, use it */ if(mapserv->map->legend.template) { char *legendTemplate; legendTemplate = generateLegendTemplate(mapserv); if(legendTemplate) { outstr = msReplaceSubstring(outstr, "[legend]", legendTemplate); free(legendTemplate); } else /* error already generated by (generateLegendTemplate()) */ return NULL; } else { /* if not display gif image with all legend icon */ snprintf(repstr, PROCESSLINE_BUFLEN, "%s%sleg%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[legend]", repstr); } } snprintf(repstr, PROCESSLINE_BUFLEN, "%s%ssb%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[scalebar]", repstr); if(mapserv->savequery) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s%s%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_QUERY_EXTENSION); outstr = msReplaceSubstring(outstr, "[queryfile]", repstr); } if(mapserv->savemap) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s%s.map", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id); outstr = msReplaceSubstring(outstr, "[map]", repstr); } if(strstr(outstr,"[mapserv_onlineresource]")) { char *ol; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR) ol = msOWSGetOnlineResource(mapserv->map, "O", "onlineresource", mapserv->request); #else ol = msBuildOnlineResource(mapserv->map, mapserv->request); #endif outstr = msReplaceSubstring(outstr, "[mapserv_onlineresource]",ol); msFree(ol); } if(getenv("HTTP_HOST")) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s", getenv("HTTP_HOST")); outstr = msReplaceSubstring(outstr, "[host]", repstr); } if(getenv("SERVER_PORT")) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s", getenv("SERVER_PORT")); outstr = msReplaceSubstring(outstr, "[port]", repstr); } snprintf(repstr, PROCESSLINE_BUFLEN, "%s", mapserv->Id); outstr = msReplaceSubstring(outstr, "[id]", repstr); repstr[0] = '\0'; /* Layer list for a "POST" request */ for(i=0; iNumLayers; i++) { strlcat(repstr, mapserv->Layers[i], sizeof(repstr)); strlcat(repstr, " ", sizeof(repstr)); } msStringTrimBlanks(repstr); outstr = msReplaceSubstring(outstr, "[layers]", repstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[layers_esc]", encodedstr); free(encodedstr); strcpy(repstr, ""); /* list of ALL layers that can be toggled */ repstr[0] = '\0'; for(i=0; imap->numlayers; i++) { if(GET_LAYER(mapserv->map, i)->status != MS_DEFAULT && GET_LAYER(mapserv->map, i)->name != NULL) { strlcat(repstr, GET_LAYER(mapserv->map, i)->name, sizeof(repstr)); strlcat(repstr, " ", sizeof(repstr)); } } msStringTrimBlanks(repstr); outstr = msReplaceSubstring(outstr, "[toggle_layers]", repstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[toggle_layers_esc]", encodedstr); free(encodedstr); for(i=0; imap->numlayers; i++) { /* Set form widgets (i.e. checkboxes, radio and select lists), note that default layers don't show up here */ if(isOn(mapserv, GET_LAYER(mapserv->map, i)->name, GET_LAYER(mapserv->map, i)->group) == MS_TRUE) { if(GET_LAYER(mapserv->map, i)->group) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } if(GET_LAYER(mapserv->map, i)->name) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } } else { if(GET_LAYER(mapserv->map, i)->group) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, ""); } if(GET_LAYER(mapserv->map, i)->name) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, ""); } } } for(i=-1; i<=1; i++) { /* make zoom direction persistant */ if(mapserv->ZoomDirection == i) { snprintf(substr, sizeof(substr), "[zoomdir_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, sizeof(substr), "[zoomdir_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } else { snprintf(substr, sizeof(substr), "[zoomdir_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, sizeof(substr), "[zoomdir_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, ""); } } for(i=MINZOOM; i<=MAXZOOM; i++) { /* make zoom persistant */ if(mapserv->Zoom == i) { snprintf(substr, sizeof(substr), "[zoom_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, sizeof(substr), "[zoom_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } else { snprintf(substr, sizeof(substr), "[zoom_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, sizeof(substr), "[zoom_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, ""); } } /* allow web object metadata access in template */ /* * reworked by SG to use HashTable methods */ if(&(mapserv->map->web.metadata) && strstr(outstr, "web_")) { for (j=0; jmap->web.metadata.items[j] != NULL) { for(tp=mapserv->map->web.metadata.items[j]; tp!=NULL; tp=tp->next) { snprintf(substr, PROCESSLINE_BUFLEN, "[web_%s]", tp->key); outstr = msReplaceSubstring(outstr, substr, tp->data); snprintf(substr, PROCESSLINE_BUFLEN, "[web_%s_esc]", tp->key); encodedstr = msEncodeUrl(tp->data); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } } } } /* allow layer metadata access in template */ for(i=0; imap->numlayers; i++) { if(&(GET_LAYER(mapserv->map, i)->metadata) && GET_LAYER(mapserv->map, i)->name && strstr(outstr, GET_LAYER(mapserv->map, i)->name)) { for(j=0; jmap, i)->metadata.items[j] != NULL) { for(tp=GET_LAYER(mapserv->map, i)->metadata.items[j]; tp!=NULL; tp=tp->next) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s]", GET_LAYER(mapserv->map, i)->name, tp->key); if(GET_LAYER(mapserv->map, i)->status == MS_ON) outstr = msReplaceSubstring(outstr, substr, tp->data); else outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s_esc]", GET_LAYER(mapserv->map, i)->name, tp->key); if(GET_LAYER(mapserv->map, i)->status == MS_ON) { encodedstr = msEncodeUrl(tp->data); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } else outstr = msReplaceSubstring(outstr, substr, ""); } } } } } snprintf(repstr, sizeof(repstr), "%f", mapserv->mappnt.x); outstr = msReplaceSubstring(outstr, "[mapx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->mappnt.y); outstr = msReplaceSubstring(outstr, "[mapy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.minx); /* Individual mapextent elements for spatial query building, deprecated. */ outstr = msReplaceSubstring(outstr, "[minx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.maxx); outstr = msReplaceSubstring(outstr, "[maxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.miny); outstr = msReplaceSubstring(outstr, "[miny]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.maxy); outstr = msReplaceSubstring(outstr, "[maxy]", repstr); if(processDateTag( &outstr ) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "mapext", &(mapserv->map->extent), &(mapserv->map->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "mapext_esc", &(mapserv->map->extent), &(mapserv->map->projection)) != MS_SUCCESS) /* depricated */ return(NULL); snprintf(repstr, sizeof(repstr), "%f", (mapserv->map->extent.maxx-mapserv->map->extent.minx)); /* useful for creating cachable extents (i.e. 0 0 dx dy) with legends and scalebars */ outstr = msReplaceSubstring(outstr, "[dx]", repstr); snprintf(repstr, sizeof(repstr), "%f", (mapserv->map->extent.maxy-mapserv->map->extent.miny)); outstr = msReplaceSubstring(outstr, "[dy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.minx); /* Individual raw extent elements for spatial query building, deprecated. */ outstr = msReplaceSubstring(outstr, "[rawminx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.maxx); outstr = msReplaceSubstring(outstr, "[rawmaxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.miny); outstr = msReplaceSubstring(outstr, "[rawminy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.maxy); outstr = msReplaceSubstring(outstr, "[rawmaxy]", repstr); if(processExtentTag(mapserv, &outstr, "rawext", &(mapserv->RawExt), &(mapserv->map->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "rawext_esc", &(mapserv->RawExt), &(mapserv->map->projection)) != MS_SUCCESS) /* depricated */ return(NULL); #ifdef USE_PROJ if((strstr(outstr, "lat]") || strstr(outstr, "lon]") || strstr(outstr, "lon_esc]")) && mapserv->map->projection.proj != NULL && !pj_is_latlong(mapserv->map->projection.proj) ) { llextent=mapserv->map->extent; llpoint=mapserv->mappnt; msProjectRect(&(mapserv->map->projection), &(mapserv->map->latlon), &llextent); msProjectPoint(&(mapserv->map->projection), &(mapserv->map->latlon), &llpoint); snprintf(repstr, sizeof(repstr), "%f", llpoint.x); outstr = msReplaceSubstring(outstr, "[maplon]", repstr); snprintf(repstr, sizeof(repstr), "%f", llpoint.y); outstr = msReplaceSubstring(outstr, "[maplat]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.minx); /* map extent as lat/lon */ outstr = msReplaceSubstring(outstr, "[minlon]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.maxx); outstr = msReplaceSubstring(outstr, "[maxlon]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.miny); outstr = msReplaceSubstring(outstr, "[minlat]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.maxy); outstr = msReplaceSubstring(outstr, "[maxlat]", repstr); if(processExtentTag(mapserv, &outstr, "mapext_latlon", &(llextent), NULL) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "mapext_latlon_esc", &(llextent), NULL) != MS_SUCCESS) /* depricated */ return(NULL); } #endif /* submitted by J.F (bug 1102) */ if(mapserv->map->reference.status == MS_ON) { snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.minx); /* Individual reference map extent elements for spatial query building, depricated. */ outstr = msReplaceSubstring(outstr, "[refminx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.maxx); outstr = msReplaceSubstring(outstr, "[refmaxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.miny); outstr = msReplaceSubstring(outstr, "[refminy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.maxy); outstr = msReplaceSubstring(outstr, "[refmaxy]", repstr); if(processExtentTag(mapserv, &outstr, "refext", &(mapserv->map->reference.extent), &(mapserv->map->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "refext_esc", &(mapserv->map->reference.extent), &(mapserv->map->projection)) != MS_SUCCESS) /* depricated */ return(NULL); } snprintf(repstr, sizeof(repstr), "%d %d", mapserv->map->width, mapserv->map->height); outstr = msReplaceSubstring(outstr, "[mapsize]", repstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[mapsize_esc]", encodedstr); free(encodedstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->map->width); outstr = msReplaceSubstring(outstr, "[mapwidth]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->map->height); outstr = msReplaceSubstring(outstr, "[mapheight]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->scaledenom); outstr = msReplaceSubstring(outstr, "[scale]", repstr); outstr = msReplaceSubstring(outstr, "[scaledenom]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->cellsize); outstr = msReplaceSubstring(outstr, "[cellsize]", repstr); snprintf(repstr, sizeof(repstr), "%.1f %.1f", (mapserv->map->width)/2.0, (mapserv->map->height)/2.0); /* not subtracting 1 from image dimensions (see bug 633) */ outstr = msReplaceSubstring(outstr, "[center]", repstr); snprintf(repstr, sizeof(repstr), "%.1f", (mapserv->map->width)/2.0); outstr = msReplaceSubstring(outstr, "[center_x]", repstr); snprintf(repstr, sizeof(repstr), "%.1f", (mapserv->map->height)/2.0); outstr = msReplaceSubstring(outstr, "[center_y]", repstr); /* These are really for situations with multiple result sets only, but often used in header/footer */ snprintf(repstr, sizeof(repstr), "%d", mapserv->NR); /* total number of results */ outstr = msReplaceSubstring(outstr, "[nr]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->NL); /* total number of layers with results */ outstr = msReplaceSubstring(outstr, "[nl]", repstr); if(mapserv->resultlayer) { if(strstr(outstr, "[items]") != NULL) { char *itemstr=NULL; itemstr = msJoinStrings(mapserv->resultlayer->items, mapserv->resultlayer->numitems, ","); outstr = msReplaceSubstring(outstr, "[items]", itemstr); free(itemstr); } snprintf(repstr, sizeof(repstr), "%d", mapserv->NLR); /* total number of results within this layer */ outstr = msReplaceSubstring(outstr, "[nlr]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->RN); /* sequential (eg. 1..n) result number within all layers */ outstr = msReplaceSubstring(outstr, "[rn]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->LRN); /* sequential (eg. 1..n) result number within this layer */ outstr = msReplaceSubstring(outstr, "[lrn]", repstr); outstr = msReplaceSubstring(outstr, "[cl]", mapserv->resultlayer->name); /* current layer name */ /* if(resultlayer->description) outstr = msReplaceSubstring(outstr, "[cd]", resultlayer->description); */ /* current layer description */ } if(mode != QUERY) { if(processResultSetTag(mapserv, &outstr, stream) != MS_SUCCESS) return(NULL); } if(mode == QUERY) { /* return shape and/or values */ /* allow layer metadata access in a query template, within the context of a query no layer name is necessary */ if(&(mapserv->resultlayer->metadata) && strstr(outstr, "[metadata_")) { for(i=0; iresultlayer->metadata.items[i] != NULL) { for(tp=mapserv->resultlayer->metadata.items[i]; tp!=NULL; tp=tp->next) { snprintf(substr, PROCESSLINE_BUFLEN, "[metadata_%s]", tp->key); outstr = msReplaceSubstring(outstr, substr, tp->data); snprintf(substr, PROCESSLINE_BUFLEN, "[metadata_%s_esc]", tp->key); encodedstr = msEncodeUrl(tp->data); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } } } } snprintf(repstr, sizeof(repstr), "%f %f", (mapserv->resultshape.bounds.maxx + mapserv->resultshape.bounds.minx)/2, (mapserv->resultshape.bounds.maxy + mapserv->resultshape.bounds.miny)/2); outstr = msReplaceSubstring(outstr, "[shpmid]", repstr); snprintf(repstr, sizeof(repstr), "%f", (mapserv->resultshape.bounds.maxx + mapserv->resultshape.bounds.minx)/2); outstr = msReplaceSubstring(outstr, "[shpmidx]", repstr); snprintf(repstr, sizeof(repstr), "%f", (mapserv->resultshape.bounds.maxy + mapserv->resultshape.bounds.miny)/2); outstr = msReplaceSubstring(outstr, "[shpmidy]", repstr); if(processExtentTag(mapserv, &outstr, "shpext", &(mapserv->resultshape.bounds), &(mapserv->resultlayer->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "shpext_esc", &(mapserv->resultshape.bounds), &(mapserv->resultlayer->projection)) != MS_SUCCESS) /* depricated */ return(NULL); snprintf(repstr, sizeof(repstr), "%d", mapserv->resultshape.classindex); outstr = msReplaceSubstring(outstr, "[shpclass]", repstr); if(processShpxyTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS) return(NULL); if(processShplabelTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS) return(NULL); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.minx); outstr = msReplaceSubstring(outstr, "[shpminx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.miny); outstr = msReplaceSubstring(outstr, "[shpminy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.maxx); outstr = msReplaceSubstring(outstr, "[shpmaxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.maxy); outstr = msReplaceSubstring(outstr, "[shpmaxy]", repstr); snprintf(repstr, sizeof(repstr), "%ld", mapserv->resultshape.index); outstr = msReplaceSubstring(outstr, "[shpidx]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->resultshape.tileindex); outstr = msReplaceSubstring(outstr, "[tileidx]", repstr); /* return ALL attributes in one delimeted list */ if(strstr(outstr, "[values]") != NULL) { char *valuestr=NULL; valuestr = msJoinStrings(mapserv->resultshape.values, mapserv->resultlayer->numitems, ","); outstr = msReplaceSubstring(outstr, "[values]", valuestr); free(valuestr); } for(i=0; iresultlayer->numitems; i++) { /* by default let's encode attributes for HTML presentation */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s]", mapserv->resultlayer->items[i]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeHTMLEntities(mapserv->resultshape.values[i]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* of course you might want to embed that data in URLs */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_esc]", mapserv->resultlayer->items[i]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeUrl(mapserv->resultshape.values[i]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* or you might want to access the attributes unaltered */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_raw]", mapserv->resultlayer->items[i]); if(strstr(outstr, substr) != NULL) outstr = msReplaceSubstring(outstr, substr, mapserv->resultshape.values[i]); } if(processItemTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS) return(NULL); /* handle joins in this next section */ for(i=0; iresultlayer->numjoins; i++) { if(mapserv->resultlayer->joins[i].values) { /* join has data */ for(j=0; jresultlayer->joins[i].numitems; j++) { /* by default let's encode attributes for HTML presentation */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s]", mapserv->resultlayer->joins[i].name, mapserv->resultlayer->joins[i].items[j]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeHTMLEntities(mapserv->resultlayer->joins[i].values[j]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* of course you might want to embed that data in URLs */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s_esc]", mapserv->resultlayer->joins[i].name, mapserv->resultlayer->joins[i].items[j]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeUrl(mapserv->resultlayer->joins[i].values[j]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* or you might want to access the attributes unaltered */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s_raw]", mapserv->resultlayer->joins[i].name, mapserv->resultlayer->joins[i].items[j]); if(strstr(outstr, substr) != NULL) outstr = msReplaceSubstring(outstr, substr, mapserv->resultlayer->joins[i].values[j]); } } else if(mapserv->resultlayer->joins[i].type == MS_JOIN_ONE_TO_MANY) { /* one-to-many join */ char *joinTemplate=NULL; snprintf(substr, PROCESSLINE_BUFLEN, "[join_%s]", mapserv->resultlayer->joins[i].name); if(strstr(outstr, substr) != NULL) { joinTemplate = processOneToManyJoin(mapserv, &(mapserv->resultlayer->joins[i])); if(joinTemplate) { outstr = msReplaceSubstring(outstr, substr, joinTemplate); free(joinTemplate); } else return NULL; } } } /* next join */ } /* end query mode specific substitutions */ if(processIncludeTag(mapserv, &outstr, stream, mode) != MS_SUCCESS) return(NULL); for(i=0; irequest->NumParams; i++) { /* Replace [variable] tags using values from URL. We cannot offer a * [variable_raw] option here due to the risk of XSS. * * Replacement is case-insensitive. (#4511) */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s]", mapserv->request->ParamNames[i]); encodedstr = msEncodeHTMLEntities(mapserv->request->ParamValues[i]); outstr = msCaseReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_esc]", mapserv->request->ParamNames[i]); encodedstr = msEncodeUrl(mapserv->request->ParamValues[i]); outstr = msCaseReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } return(outstr); } #define MS_TEMPLATE_BUFFER 1024 /* 1k */ int msReturnPage(mapservObj *mapserv, char *html, int mode, char **papszBuffer) { FILE *stream; char line[MS_BUFFER_LENGTH], *tmpline; int nBufferSize = 0; int nCurrentSize = 0; int nExpandBuffer = 0; ms_regex_t re; /* compiled regular expression to be matched */ char szPath[MS_MAXPATHLEN]; if(!html) { msSetError(MS_WEBERR, "No template specified", "msReturnPage()"); return MS_FAILURE; } if(ms_regcomp(&re, MS_TEMPLATE_EXPR, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { msSetError(MS_REGEXERR, NULL, "msReturnPage()"); return MS_FAILURE; } if(ms_regexec(&re, html, 0, NULL, 0) != 0) { /* no match */ ms_regfree(&re); msSetError(MS_WEBERR, "Malformed template name (%s).", "msReturnPage()", html); return MS_FAILURE; } ms_regfree(&re); if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, html), "r")) == NULL) { msSetError(MS_IOERR, "%s", "msReturnPage()", html); return MS_FAILURE; } if(isValidTemplate(stream, html) != MS_TRUE) { fclose(stream); return MS_FAILURE; } if(papszBuffer) { if((*papszBuffer) == NULL) { (*papszBuffer) = (char *)msSmallMalloc(MS_TEMPLATE_BUFFER); (*papszBuffer)[0] = '\0'; nBufferSize = MS_TEMPLATE_BUFFER; nCurrentSize = 0; nExpandBuffer = 1; } else { nCurrentSize = strlen((*papszBuffer)); nBufferSize = nCurrentSize; nExpandBuffer = (nCurrentSize/MS_TEMPLATE_BUFFER) + 1; } } while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) { /* now on to the end of the file */ if(strchr(line, '[') != NULL) { tmpline = processLine(mapserv, line, stream, mode); if(!tmpline) return MS_FAILURE; if(papszBuffer) { if(nBufferSize <= (int)(nCurrentSize + strlen(tmpline) + 1)) { nExpandBuffer = (strlen(tmpline) / MS_TEMPLATE_BUFFER) + 1; nBufferSize = MS_TEMPLATE_BUFFER*nExpandBuffer + strlen((*papszBuffer)); (*papszBuffer) = (char *) msSmallRealloc((*papszBuffer),sizeof(char)*nBufferSize); } strcat((*papszBuffer), tmpline); nCurrentSize += strlen(tmpline); } else msIO_fwrite(tmpline, strlen(tmpline), 1, stdout); free(tmpline); } else { if(papszBuffer) { if(nBufferSize <= (int)(nCurrentSize + strlen(line))) { nExpandBuffer = (strlen(line) / MS_TEMPLATE_BUFFER) + 1; nBufferSize = MS_TEMPLATE_BUFFER*nExpandBuffer + strlen((*papszBuffer)); (*papszBuffer) = (char *)msSmallRealloc((*papszBuffer),sizeof(char)*nBufferSize); } strcat((*papszBuffer), line); nCurrentSize += strlen(line); } else msIO_fwrite(line, strlen(line), 1, stdout); } if(!papszBuffer) fflush(stdout); } /* next line */ fclose(stream); return MS_SUCCESS; } int msReturnURL(mapservObj* ms, char* url, int mode) { char *tmpurl; if(url == NULL) { msSetError(MS_WEBERR, "Empty URL.", "msReturnURL()"); return MS_FAILURE; } tmpurl = processLine(ms, url, NULL, mode); /* URL templates can't handle multi-line tags, hence the NULL file pointer */ if(!tmpurl) return MS_FAILURE; msRedirect(tmpurl); free(tmpurl); return MS_SUCCESS; } /* ** Legacy query template parsing where you use headers, footers and such... */ int msReturnNestedTemplateQuery(mapservObj* mapserv, char* pszMimeType, char **papszBuffer) { int status; int i,j,k; char buffer[1024]; int nBufferSize =0; int nCurrentSize = 0; int nExpandBuffer = 0; char *template; layerObj *lp=NULL; if(papszBuffer) { (*papszBuffer) = (char *)msSmallMalloc(MS_TEMPLATE_BUFFER); (*papszBuffer)[0] = '\0'; nBufferSize = MS_TEMPLATE_BUFFER; nCurrentSize = 0; nExpandBuffer = 1; } msInitShape(&(mapserv->resultshape)); if((mapserv->Mode == ITEMQUERY) || (mapserv->Mode == QUERY)) { /* may need to handle a URL result set since these modes return exactly 1 result */ for(i=(mapserv->map->numlayers-1); i>=0; i--) { lp = (GET_LAYER(mapserv->map, i)); if(!lp->resultcache) continue; if(lp->resultcache->numresults > 0) break; } if(i >= 0) { /* at least if no result found, mapserver will display an empty template. */ if(lp->resultcache->results[0].classindex >= 0 && lp->class[(int)(lp->resultcache->results[0].classindex)]->template) template = lp->class[(int)(lp->resultcache->results[0].classindex)]->template; else template = lp->template; if( template == NULL ) { msSetError(MS_WEBERR, "No template for layer %s or it's classes.", "msReturnNestedTemplateQuery()", lp->name ); return MS_FAILURE; } if(TEMPLATE_TYPE(template) == MS_URL) { mapserv->resultlayer = lp; #if 0 status = msLayerOpen(lp); if(status != MS_SUCCESS) return status; status = msLayerGetItems(lp); /* retrieve all the item names */ if(status != MS_SUCCESS) return status; #endif status = msLayerGetShape(lp, &(mapserv->resultshape), &(lp->resultcache->results[0])); if(status != MS_SUCCESS) return status; if(lp->numjoins > 0) { for(k=0; knumjoins; k++) { status = msJoinConnect(lp, &(lp->joins[k])); if(status != MS_SUCCESS) return status; msJoinPrepare(&(lp->joins[k]), &(mapserv->resultshape)); msJoinNext(&(lp->joins[k])); /* fetch the first row */ } } if(papszBuffer == NULL) { if(msReturnURL(mapserv, template, QUERY) != MS_SUCCESS) return MS_FAILURE; } msFreeShape(&(mapserv->resultshape)); /* msLayerClose(lp); */ mapserv->resultlayer = NULL; return MS_SUCCESS; } } } /* ** Now we know we're making a template sandwich */ mapserv->NR = mapserv->NL = 0; for(i=0; imap->numlayers; i++) { /* compute some totals */ lp = (GET_LAYER(mapserv->map, i)); if(!lp->resultcache) continue; if(lp->resultcache->numresults > 0) { mapserv->NL++; mapserv->NR += lp->resultcache->numresults; } } /* ** Is this step really necessary for buffered output? Legend and browse templates don't deal with mime-types ** so why should this. Note that new-style templates don't buffer the mime-type either. */ if(papszBuffer && mapserv->sendheaders) { snprintf(buffer, sizeof(buffer), "Content-Type: %s%c%c", pszMimeType, 10, 10); if(nBufferSize <= (int)(nCurrentSize + strlen(buffer) + 1)) { nExpandBuffer++; (*papszBuffer) = (char *)msSmallRealloc((*papszBuffer), MS_TEMPLATE_BUFFER*nExpandBuffer); nBufferSize = MS_TEMPLATE_BUFFER*nExpandBuffer; } strcat((*papszBuffer), buffer); nCurrentSize += strlen(buffer); } else if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s",pszMimeType); msIO_sendHeaders(); } if(mapserv->map->web.header) { if(msReturnPage(mapserv, mapserv->map->web.header, BROWSE, papszBuffer) != MS_SUCCESS) return MS_FAILURE; } mapserv->RN = 1; /* overall result number */ for(i=0; imap->numlayers; i++) { mapserv->resultlayer = lp = (GET_LAYER(mapserv->map, mapserv->map->layerorder[i])); if(!lp->resultcache) continue; if(lp->resultcache->numresults <= 0) continue; mapserv->NLR = lp->resultcache->numresults; #if 0 status = msLayerOpen(lp); /* open this layer */ if(status != MS_SUCCESS) return status; status = msLayerGetItems(lp); /* retrieve all the item names */ if(status != MS_SUCCESS) return status; #endif if(lp->numjoins > 0) { /* open any necessary JOINs here */ for(k=0; knumjoins; k++) { status = msJoinConnect(lp, &(lp->joins[k])); if(status != MS_SUCCESS) return status; } } if(lp->header) { if(msReturnPage(mapserv, lp->header, BROWSE, papszBuffer) != MS_SUCCESS) return MS_FAILURE; } mapserv->LRN = 1; /* layer result number */ for(j=0; jresultcache->numresults; j++) { status = msLayerGetShape(lp, &(mapserv->resultshape), &(lp->resultcache->results[j])); if(status != MS_SUCCESS) return status; /* prepare any necessary JOINs here (one-to-one only) */ if(lp->numjoins > 0) { for(k=0; knumjoins; k++) { if(lp->joins[k].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(lp->joins[k]), &(mapserv->resultshape)); msJoinNext(&(lp->joins[k])); /* fetch the first row */ } } } if(lp->resultcache->results[j].classindex >= 0 && lp->class[(int)(lp->resultcache->results[j].classindex)]->template) template = lp->class[(int)(lp->resultcache->results[j].classindex)]->template; else template = lp->template; if(msReturnPage(mapserv, template, QUERY, papszBuffer) != MS_SUCCESS) { msFreeShape(&(mapserv->resultshape)); return MS_FAILURE; } msFreeShape(&(mapserv->resultshape)); /* init too */ mapserv->RN++; /* increment counters */ mapserv->LRN++; } if(lp->footer) { if(msReturnPage(mapserv, lp->footer, BROWSE, papszBuffer) != MS_SUCCESS) return MS_FAILURE; } /* msLayerClose(lp); */ mapserv->resultlayer = NULL; } if(mapserv->map->web.footer) return msReturnPage(mapserv, mapserv->map->web.footer, BROWSE, papszBuffer); return MS_SUCCESS; } int msReturnOpenLayersPage(mapservObj *mapserv) { int i; char *buffer = NULL, *layer = NULL; const char *tmpUrl = NULL; char *openlayersUrl = olUrl; char *projection = NULL; char *format = NULL; /* 2 CGI parameters are used in the template. we need to transform them * to be sure the case match during the template processing. We also * need to search the SRS/CRS parameter to get the projection info. OGC * services version >= 1.3.0 uses CRS rather than SRS */ for( i=0; irequest->NumParams; i++) { if( (strcasecmp(mapserv->request->ParamNames[i], "SRS") == 0) || (strcasecmp(mapserv->request->ParamNames[i], "CRS") == 0) ) { projection = mapserv->request->ParamValues[i]; } else if(strcasecmp(mapserv->request->ParamNames[i], "LAYERS") == 0) { free(mapserv->request->ParamNames[i]); mapserv->request->ParamNames[i] = msStrdup("LAYERS"); } else if(strcasecmp(mapserv->request->ParamNames[i], "VERSION") == 0) { free(mapserv->request->ParamNames[i]); mapserv->request->ParamNames[i] = msStrdup("VERSION"); } } if(mapserv->map->outputformat->mimetype && *mapserv->map->outputformat->mimetype) { format = mapserv->map->outputformat->mimetype; } /* check if the environment variable or config MS_OPENLAYERS_JS_URL is set */ tmpUrl = msGetConfigOption(mapserv->map, "MS_OPENLAYERS_JS_URL"); if (tmpUrl) openlayersUrl = (char*)tmpUrl; else if (getenv("MS_OPENLAYERS_JS_URL")) openlayersUrl = getenv("MS_OPENLAYERS_JS_URL"); if (mapserv->Mode == BROWSE) { msSetError(MS_WMSERR, "At least one layer name required in LAYERS.", "msWMSLoadGetMapParams()"); layer = processLine(mapserv, olLayerMapServerTag, NULL, BROWSE); } else layer = processLine(mapserv, olLayerWMSTag, NULL, BROWSE); buffer = processLine(mapserv, olTemplate, NULL, BROWSE); buffer = msReplaceSubstring(buffer, "[openlayers_js_url]", openlayersUrl); buffer = msReplaceSubstring(buffer, "[openlayers_layer]", layer); if (projection) buffer = msReplaceSubstring(buffer, "[openlayers_projection]", projection); if (format) buffer = msReplaceSubstring(buffer, "[openlayers_format]", format); else buffer = msReplaceSubstring(buffer, "[openlayers_format]", "image/jpeg"); msIO_fwrite(buffer, strlen(buffer), 1, stdout); free(layer); free(buffer); return MS_SUCCESS; } mapservObj *msAllocMapServObj() { mapservObj *mapserv = msSmallMalloc(sizeof(mapservObj)); mapserv->savemap=MS_FALSE; mapserv->savequery=MS_FALSE; /* should the query and/or map be saved */ mapserv->sendheaders = MS_TRUE; mapserv->request = msAllocCgiObj(); mapserv->map=NULL; mapserv->NumLayers=0; /* number of layers specfied by a user */ mapserv->MaxLayers=0; /* allocated size of Layers[] array */ mapserv->Layers = NULL; mapserv->icon = NULL; mapserv->RawExt.minx=-1; mapserv->RawExt.miny=-1; mapserv->RawExt.maxx=-1; mapserv->RawExt.maxy=-1; mapserv->fZoom=1; mapserv->Zoom=1; /* default for browsing */ mapserv->resultlayer=NULL; mapserv->UseShapes=MS_FALSE; mapserv->mappnt.x=-1; mapserv->mappnt.y=-1; mapserv->ZoomDirection=0; /* whether zooming in or out, default is pan or 0 */ mapserv->Mode=BROWSE; /* can be BROWSE, QUERY, etc. */ sprintf(mapserv->Id, "%ld%d", (long)time(NULL), (int)getpid()); mapserv->CoordSource=NONE; mapserv->ScaleDenom=0; mapserv->ImgRows=-1; mapserv->ImgCols=-1; mapserv->ImgExt.minx=-1; mapserv->ImgExt.miny=-1; mapserv->ImgExt.maxx=-1; mapserv->ImgExt.maxy=-1; mapserv->ImgBox.minx=-1; mapserv->ImgBox.miny=-1; mapserv->ImgBox.maxx=-1; mapserv->ImgBox.maxy=-1; mapserv->RefPnt.x=-1; mapserv->RefPnt.y=-1; mapserv->ImgPnt.x=-1; mapserv->ImgPnt.y=-1; mapserv->Buffer=0; /* ** variables for multiple query results processing */ mapserv->RN=0; /* overall result number */ mapserv->LRN=0; /* result number within a layer */ mapserv->NL=0; /* total number of layers with results */ mapserv->NR=0; /* total number or results */ mapserv->NLR=0; /* number of results in a layer */ mapserv->SearchMap=MS_FALSE; /* apply pan/zoom BEFORE doing the query (e.g. query the output image rather than the input image) */ mapserv->QueryFile=NULL; mapserv->QueryLayer=NULL; mapserv->SelectLayer=NULL; mapserv->QueryLayerIndex=-1; mapserv->SelectLayerIndex=-1; mapserv->QueryItem=NULL; mapserv->QueryString=NULL; mapserv->ShapeIndex=-1; mapserv->TileIndex=-1; mapserv->QueryCoordSource=NONE; mapserv->ZoomSize=0; /* zoom absolute magnitude (i.e. > 0) */ mapserv->hittest = NULL; return mapserv; } void msFreeMapServObj(mapservObj* mapserv) { int i; if(mapserv) { if( mapserv->map ) { if(mapserv->hittest) { freeMapHitTests(mapserv->map,mapserv->hittest); free(mapserv->hittest); } msFreeMap(mapserv->map); mapserv->map = NULL; } if( mapserv->request ) { msFreeCgiObj(mapserv->request); mapserv->request = NULL; } for(i=0; iNumLayers; i++) msFree(mapserv->Layers[i]); msFree(mapserv->Layers); msFree(mapserv->icon); msFree(mapserv->QueryItem); msFree(mapserv->QueryString); msFree(mapserv->QueryLayer); msFree(mapserv->SelectLayer); msFree(mapserv->QueryFile); msFree(mapserv); } } /* ** Ensure there is at least one free entry in the Layers array. ** ** This function is safe to use for the initial allocation of the Layers[] ** array as well (i.e. when MaxLayers==0 and Layers==NULL) ** ** Returns MS_SUCCESS/MS_FAILURE */ int msGrowMapservLayers( mapservObj* mapserv ) { /* Do we need to increase the size of Layers[] by MS_LAYER_ALLOCSIZE? */ if(mapserv->NumLayers == mapserv->MaxLayers) { int i; if(mapserv->MaxLayers == 0) { /* initial allocation of array */ mapserv->MaxLayers += MS_LAYER_ALLOCSIZE; mapserv->NumLayers = 0; mapserv->Layers = (char**)msSmallMalloc(mapserv->MaxLayers*sizeof(char*)); } else { /* realloc existing array */ mapserv->MaxLayers += MS_LAYER_ALLOCSIZE; mapserv->Layers = (char**)msSmallRealloc(mapserv->Layers, mapserv->MaxLayers*sizeof(char*)); } if(mapserv->Layers == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for Layers array.", "msGrowMappservLayers()"); return MS_FAILURE; } for(i=mapserv->NumLayers; iMaxLayers; i++) { mapserv->Layers[i] = NULL; } } return MS_SUCCESS; } /* ** Utility function to generate map, legend, scalebar and reference images. ** ** Parameters: ** - mapserv: mapserv object (used to extract the map object). ** - bQueryMap: if set to TRUE a query map will be created instead of a regular map. ** - bReturnOnError: if set to TRUE, the function will return on the first error, else it will try to generate all the images. */ int msGenerateImages(mapservObj *mapserv, int bQueryMap, int bReturnOnError) { char buffer[1024]; if(mapserv) { /* render the map OR query map */ if((!bQueryMap && mapserv->map->status == MS_ON) || (bQueryMap && mapserv->map->querymap.status == MS_ON)) { imageObj *image = NULL; image = msDrawMap(mapserv->map, bQueryMap); if(image) { snprintf(buffer, sizeof(buffer), "%s%s%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } /* render the legend */ if(mapserv->map->legend.status == MS_ON) { imageObj *image = NULL; image = msDrawLegend(mapserv->map, MS_FALSE, NULL); if(image) { snprintf(buffer, sizeof(buffer), "%s%sleg%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } /* render the scalebar */ if(mapserv->map->scalebar.status == MS_ON) { imageObj *image = NULL; image = msDrawScalebar(mapserv->map); if(image) { snprintf(buffer, sizeof(buffer), "%s%ssb%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } /* render the reference map */ if(mapserv->map->reference.status == MS_ON) { imageObj *image; image = msDrawReferenceMap(mapserv->map); if(image) { snprintf(buffer, sizeof(buffer), "%s%sref%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } } return MS_SUCCESS; } /* ** Utility function to open a template file, process it and ** and return into a buffer the processed template. Uses the ** template file from the web object. Returns NULL if there is ** an error. */ char *msProcessTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries) { char *pszBuffer = NULL; if(map) { /* Initialize object and set appropriate defaults. */ mapservObj *mapserv = NULL; mapserv = msAllocMapServObj(); mapserv->map = map; mapserv->Mode = BROWSE; if(names && values && numentries > 0) { msFreeCharArray(mapserv->request->ParamNames, mapserv->request->NumParams); msFreeCharArray(mapserv->request->ParamValues, mapserv->request->NumParams); mapserv->request->ParamNames = names; mapserv->request->ParamValues = values; mapserv->request->NumParams = numentries; } /* ** ISSUE/TODO : some of the name/values should be extracted and ** processed (ex imgext, layers, ...) as it is done in function ** loadform. */ if(bGenerateImages) msGenerateImages(mapserv, MS_FALSE, MS_FALSE); /* ** Process the template. ** ** TODO : use web minscaledenom/maxscaledenom depending on the scale. */ if(msReturnPage(mapserv, mapserv->map->web.template, BROWSE, &pszBuffer) != MS_SUCCESS) { msFree(pszBuffer); pszBuffer = NULL; } /* Don't free the map and names and values arrays since they were passed by reference. */ mapserv->map = NULL; mapserv->request->ParamNames = mapserv->request->ParamValues = NULL; mapserv->request->NumParams = 0; msFreeMapServObj(mapserv); } return pszBuffer; } /* ** Utility method to process the legend template. */ char *msProcessLegendTemplate(mapObj *map, char **names, char **values, int numentries) { char *pszOutBuf = NULL; if(map && map->legend.template) { /* Initialize object and set appropriate defaults. */ mapservObj *mapserv = NULL; mapserv = msAllocMapServObj(); mapserv->map = map; mapserv->Mode = BROWSE; if(names && values && numentries > 0) { msFreeCharArray(mapserv->request->ParamNames, mapserv->request->NumParams); msFreeCharArray(mapserv->request->ParamValues, mapserv->request->NumParams); mapserv->request->ParamNames = names; mapserv->request->ParamValues = values; mapserv->request->NumParams = numentries; } pszOutBuf = generateLegendTemplate(mapserv); /* Don't free the map and names and values arrays since they were passed by reference. */ mapserv->map = NULL; mapserv->request->ParamNames = mapserv->request->ParamValues = NULL; mapserv->request->NumParams = 0; msFreeMapServObj(mapserv); } return pszOutBuf; } /* ** Utility function that process a template file(s) used in the ** query and return the processed template(s) in a buffer. */ char *msProcessQueryTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries) { char *pszBuffer = NULL; if(map) { /* Initialize object and set appropriate defaults. */ mapservObj *mapserv = NULL; mapserv = msAllocMapServObj(); mapserv->map = map; mapserv->Mode = QUERY; if(names && values && numentries > 0) { msFreeCharArray(mapserv->request->ParamNames, mapserv->request->NumParams); msFreeCharArray(mapserv->request->ParamValues, mapserv->request->NumParams); mapserv->request->ParamNames = names; mapserv->request->ParamValues = values; mapserv->request->NumParams = numentries; } if(bGenerateImages) msGenerateImages(mapserv, MS_TRUE, MS_FALSE); mapserv->sendheaders = MS_FALSE; msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, &pszBuffer); mapserv->map = NULL; mapserv->request->ParamNames = mapserv->request->ParamValues = NULL; mapserv->request->NumParams = 0; msFreeMapServObj(mapserv); } return pszBuffer; } mapserver-6.4.1/mapentities.h0000644002461700001440000001552112261257215016013 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: HTML entity to unicode lookup table * Author: Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* * Generated file * * This file was generated from: * http://www.w3.org/TR/REC-html40/sgml/entities.html * by means of the libgd script: * entities.tcl * and modified to avoid namespace collisions */ #ifdef __cplusplus extern "C" { #endif static struct mapentities_s { char *name; int value; } mapentities[] = { {"AElig", 198}, {"Aacute", 193}, {"Acirc", 194}, {"Agrave", 192}, {"Alpha", 913}, {"Aring", 197}, {"Atilde", 195}, {"Auml", 196}, {"Beta", 914}, {"Ccedil", 199}, {"Chi", 935}, {"Dagger", 8225}, {"Delta", 916}, {"ETH", 208}, {"Eacute", 201}, {"Ecirc", 202}, {"Egrave", 200}, {"Epsilon", 917}, {"Eta", 919}, {"Euml", 203}, {"Gamma", 915}, {"Iacute", 205}, {"Icirc", 206}, {"Igrave", 204}, {"Iota", 921}, {"Iuml", 207}, {"Kappa", 922}, {"Lambda", 923}, {"Mu", 924}, {"Ntilde", 209}, {"Nu", 925}, {"OElig", 338}, {"Oacute", 211}, {"Ocirc", 212}, {"Ograve", 210}, {"Omega", 937}, {"Omicron", 927}, {"Oslash", 216}, {"Otilde", 213}, {"Ouml", 214}, {"Phi", 934}, {"Pi", 928}, {"Prime", 8243}, {"Psi", 936}, {"Rho", 929}, {"Scaron", 352}, {"Sigma", 931}, {"THORN", 222}, {"Tau", 932}, {"Theta", 920}, {"Uacute", 218}, {"Ucirc", 219}, {"Ugrave", 217}, {"Upsilon", 933}, {"Uuml", 220}, {"Xi", 926}, {"Yacute", 221}, {"Yuml", 376}, {"Zeta", 918}, {"aacute", 225}, {"acirc", 226}, {"acute", 180}, {"aelig", 230}, {"agrave", 224}, {"alefsym", 8501}, {"alpha", 945}, {"amp", 38}, {"and", 8743}, {"ang", 8736}, {"aring", 229}, {"asymp", 8776}, {"atilde", 227}, {"auml", 228}, {"bdquo", 8222}, {"beta", 946}, {"brvbar", 166}, {"bull", 8226}, {"cap", 8745}, {"ccedil", 231}, {"cedil", 184}, {"cent", 162}, {"chi", 967}, {"circ", 710}, {"clubs", 9827}, {"cong", 8773}, {"copy", 169}, {"crarr", 8629}, {"cup", 8746}, {"curren", 164}, {"dArr", 8659}, {"dagger", 8224}, {"darr", 8595}, {"deg", 176}, {"delta", 948}, {"diams", 9830}, {"divide", 247}, {"eacute", 233}, {"ecirc", 234}, {"egrave", 232}, {"empty", 8709}, {"emsp", 8195}, {"ensp", 8194}, {"epsilon", 949}, {"equiv", 8801}, {"eta", 951}, {"eth", 240}, {"euml", 235}, {"euro", 8364}, {"exist", 8707}, {"fnof", 402}, {"forall", 8704}, {"frac12", 189}, {"frac14", 188}, {"frac34", 190}, {"frasl", 8260}, {"gamma", 947}, {"ge", 8805}, {"gt", 62}, {"hArr", 8660}, {"harr", 8596}, {"hearts", 9829}, {"hellip", 8230}, {"iacute", 237}, {"icirc", 238}, {"iexcl", 161}, {"igrave", 236}, {"image", 8465}, {"infin", 8734}, {"int", 8747}, {"iota", 953}, {"iquest", 191}, {"isin", 8712}, {"iuml", 239}, {"kappa", 954}, {"lArr", 8656}, {"lambda", 955}, {"lang", 9001}, {"laquo", 171}, {"larr", 8592}, {"lceil", 8968}, {"ldquo", 8220}, {"le", 8804}, {"lfloor", 8970}, {"lowast", 8727}, {"loz", 9674}, {"lrm", 8206}, {"lsaquo", 8249}, {"lsquo", 8216}, {"lt", 60}, {"macr", 175}, {"mdash", 8212}, {"micro", 181}, {"middot", 183}, {"minus", 8722}, {"mu", 956}, {"nabla", 8711}, {"nbsp", 160}, {"ndash", 8211}, {"ne", 8800}, {"ni", 8715}, {"not", 172}, {"notin", 8713}, {"nsub", 8836}, {"ntilde", 241}, {"nu", 957}, {"oacute", 243}, {"ocirc", 244}, {"oelig", 339}, {"ograve", 242}, {"oline", 8254}, {"omega", 969}, {"omicron", 959}, {"oplus", 8853}, {"or", 8744}, {"ordf", 170}, {"ordm", 186}, {"oslash", 248}, {"otilde", 245}, {"otimes", 8855}, {"ouml", 246}, {"para", 182}, {"part", 8706}, {"permil", 8240}, {"perp", 8869}, {"phi", 966}, {"pi", 960}, {"piv", 982}, {"plusmn", 177}, {"pound", 163}, {"prime", 8242}, {"prod", 8719}, {"prop", 8733}, {"psi", 968}, {"quot", 34}, {"rArr", 8658}, {"radic", 8730}, {"rang", 9002}, {"raquo", 187}, {"rarr", 8594}, {"rceil", 8969}, {"rdquo", 8221}, {"real", 8476}, {"reg", 174}, {"rfloor", 8971}, {"rho", 961}, {"rlm", 8207}, {"rsaquo", 8250}, {"rsquo", 8217}, {"sbquo", 8218}, {"scaron", 353}, {"sdot", 8901}, {"sect", 167}, {"shy", 173}, {"sigma", 963}, {"sigmaf", 962}, {"sim", 8764}, {"spades", 9824}, {"sub", 8834}, {"sube", 8838}, {"sum", 8721}, {"sup", 8835}, {"sup1", 185}, {"sup2", 178}, {"sup3", 179}, {"supe", 8839}, {"szlig", 223}, {"tau", 964}, {"there4", 8756}, {"theta", 952}, {"thetasym", 977}, {"thinsp", 8201}, {"thorn", 254}, {"tilde", 732}, {"times", 215}, {"trade", 8482}, {"uArr", 8657}, {"uacute", 250}, {"uarr", 8593}, {"ucirc", 251}, {"ugrave", 249}, {"uml", 168}, {"upsih", 978}, {"upsilon", 965}, {"uuml", 252}, {"weierp", 8472}, {"xi", 958}, {"yacute", 253}, {"yen", 165}, {"yuml", 255}, {"zeta", 950}, {"zwj", 8205}, {"zwnj", 8204}, }; #define MAP_ENTITY_NAME_LENGTH_MAX 8 #define MAP_NR_OF_ENTITIES 252 #ifdef __cplusplus } #endif mapserver-6.4.1/mapparser.h0000644002461700001440000000562612261257215015470 0ustar tbonfortusers /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NUMBER = 258, STRING = 259, TIME = 260, SHAPE = 261, OR = 262, AND = 263, NOT = 264, IRE = 265, IEQ = 266, IN = 267, GE = 268, LE = 269, GT = 270, LT = 271, NE = 272, EQ = 273, RE = 274, DWITHIN = 275, BEYOND = 276, CONTAINS = 277, WITHIN = 278, CROSSES = 279, OVERLAPS = 280, TOUCHES = 281, DISJOINT = 282, INTERSECTS = 283, ROUND = 284, COMMIFY = 285, LENGTH = 286, AREA = 287, TOSTRING = 288, SMOOTHSIA = 289, GENERALIZE = 290, SIMPLIFYPT = 291, SIMPLIFY = 292, DIFFERENCE = 293, YYBUFFER = 294, NEG = 295 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 1676 of yacc.c */ #line 30 "/home/even/mapserver/git/mapserver/mapparser.y" double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; /* Line 1676 of yacc.c */ #line 102 "/home/even/mapserver/git/mapserver/mapparser.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif mapserver-6.4.1/mapoutput.c0000644002461700001440000011346012261257215015523 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various support code related to the outputFormatObj. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * 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. *****************************************************************************/ #include #include "mapserver.h" static outputFormatObj *msAllocOutputFormat( mapObj *map, const char *name, const char *driver ); /************************************************************************* NOTES on outputFormatObj: typedef struct { char *name; char *mimetype; char *driver; int imagemode; // MS_IMAGEMODE_* value. int transparent; int numformatoptions; char **formatoptions; } outputFormatObj; NAME - Associates an internal name with the declaration. The value used has not intrinsic meaning and is just used to associate with the MAP level IMAGETYPE. It is also the "name" used for the format in WMS capabilities documents, and FORMAT= requests. (required) MIMETYPE - The mime type to use for this format. If omitted, the value will be derived from the DRIVER or default to the value for untyped binary data will be used. (optional - may be NULL) DRIVER - This indicates which internal driver mechanism is to be used. Anything prefixed by "GDAL/" will be handled by the GDAL driver, with the remainder taken as the GDAL format name. (required) IMAGEMODE - Has one of "PC256", "RGB", or "RGBA" indicating whether the imaging should be done to a 256 pseudo-colored, 24bit RGB, or 32bit RGBA (A=alpha/transparency) result image. Note that the IMAGEMODE actually affects how all the rendering for the map is done, long before it is output to a particular output format. The default value is the traditional "PC256". Some output formats can only support some IMAGEMODE values. (optional) Translate as MS_IMAGEMODE_PC256, MS_IMAGEMODE_RGB and MS_IMAGEMODE_RGBA. Not too sure what this should be set to for output formats like flash and SVG. TRANSPARENT - A value of "ON" or "OFF" indicating whether transparency support should be enabled. Same as the old TRANSPARENT flag at the MAP level. FORMATOPTION - Contains an argument for the specific driver used. There may be any number of format options for a given OUTPUTFORMAT declaration. FORMATOPTION will be used to encode the older INTERLACE, and QUALITY values. Handled as a MapServer style CharArray. *************************************************************************/ struct defaultOutputFormatEntry { const char *name; const char *driver; const char *mimetype; } ; struct defaultOutputFormatEntry defaultoutputformats[] = { {"png","AGG/PNG","image/png"}, {"jpeg","AGG/JPEG","image/jpeg"}, #ifdef USE_GD {"gif","GD/GIF","image/gif"}, #endif {"png8","AGG/PNG8","image/png; mode=8bit"}, {"png24","AGG/PNG","image/png; mode=24bit"}, #ifdef USE_CAIRO {"pdf","CAIRO/PDF","application/x-pdf"}, {"svg","CAIRO/SVG","image/svg+xml"}, {"cairopng","CAIRO/PNG","image/png"}, #endif #ifdef USE_GDAL {"GTiff","GDAL/GTiff","image/tiff"}, #endif #ifdef USE_KML {"kml","KML","application/vnd.google-earth.kml+xml"}, {"kmz","KMZ","application/vnd.google-earth.kmz"}, #endif {NULL,NULL,NULL} }; /************************************************************************/ /* msPostMapParseOutputFormatSetup() */ /************************************************************************/ int msPostMapParseOutputFormatSetup( mapObj *map ) { outputFormatObj *format; /* If IMAGETYPE not set use the first user defined OUTPUTFORMAT. If none, use the first default format. */ if( map->imagetype == NULL && map->numoutputformats > 0 ) map->imagetype = msStrdup(map->outputformatlist[0]->name); if( map->imagetype == NULL) map->imagetype = msStrdup(defaultoutputformats[0].name); /* select the current outputformat into map->outputformat */ format = msSelectOutputFormat( map, map->imagetype ); if( format == NULL ) { msSetError(MS_MISCERR, "Unable to select IMAGETYPE `%s'.", "msPostMapParseOutputFormatSetup()", map->imagetype ? map->imagetype : "(null)" ); return MS_FAILURE; } msApplyOutputFormat( &(map->outputformat), format, map->transparent, map->interlace, map->imagequality ); return MS_SUCCESS; } /************************************************************************/ /* msCreateDefaultOutputFormat() */ /************************************************************************/ outputFormatObj *msCreateDefaultOutputFormat( mapObj *map, const char *driver, const char *name ) { outputFormatObj *format = NULL; if( strcasecmp(driver,"GD/PC256") == 0 ) { return msCreateDefaultOutputFormat( map, "GD/PNG", "gdpng" ); } if( strcasecmp(driver,"GD/GIF") == 0 ) { if(!name) name="gif"; #ifdef USE_GD_GIF format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/gif"); format->imagemode = MS_IMAGEMODE_PC256; format->extension = msStrdup("gif"); format->renderer = MS_RENDER_WITH_GD; #else return msCreateDefaultOutputFormat( map, "AGG/PNG8", name ); #endif } if( strcasecmp(driver,"GD/PNG") == 0 ) { if(!name) name="gdpng"; #ifdef USE_GD_PNG format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png"); format->imagemode = MS_IMAGEMODE_PC256; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_GD; #else return msCreateDefaultOutputFormat( map, "AGG/PNG8", name ); #endif /* USE_GD_PNG */ } if( strcasecmp(driver,"AGG/PNG") == 0 ) { if(!name) name="png24"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_AGG; } if( strcasecmp(driver,"AGG/PNG8") == 0 ) { if(!name) name="png8"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png; mode=8bit"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_AGG; msSetOutputFormatOption( format, "QUANTIZE_FORCE", "on"); msSetOutputFormatOption( format, "QUANTIZE_COLORS", "256"); } if( strcasecmp(driver,"AGG/JPEG") == 0 ) { if(!name) name="jpeg"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/jpeg"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("jpg"); format->renderer = MS_RENDER_WITH_AGG; } #if defined(USE_CAIRO) if( strcasecmp(driver,"CAIRO/PNG") == 0 ) { if(!name) name="cairopng"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png; mode=24bit"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } if( strcasecmp(driver,"CAIRO/JPEG") == 0 ) { if(!name) name="cairojpeg"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/jpeg"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("jpg"); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } if( strcasecmp(driver,"CAIRO/PDF") == 0 ) { if(!name) name="pdf"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/x-pdf"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("pdf"); format->renderer = MS_RENDER_WITH_CAIRO_PDF; } if( strcasecmp(driver,"CAIRO/SVG") == 0 ) { if(!name) name="svg"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/svg+xml"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("svg"); format->renderer = MS_RENDER_WITH_CAIRO_SVG; } #ifdef _WIN32 if( strcasecmp(driver,"CAIRO/WINGDI") == 0 ) { if(!name) name="cairowinGDI"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup(""); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup(""); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } if( strcasecmp(driver,"CAIRO/WINGDIPRINT") == 0 ) { if(!name) name="cairowinGDIPrint"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup(""); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup(""); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } #endif #endif #if defined(USE_OGL) if( strcasecmp(driver,"OGL/PNG") == 0 ) { if(!name) name="oglpng24"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png; mode=24bit"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_OGL; } #endif #if defined(USE_KML) if( strcasecmp(driver,"KML") == 0 ) { if(!name) name="kml"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/vnd.google-earth.kml+xml"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("kml"); format->renderer = MS_RENDER_WITH_KML; msSetOutputFormatOption( format, "ATTACHMENT", "mapserver.kml"); } if( strcasecmp(driver,"KMZ") == 0 ) { if(!name) name="kmz"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = strdup("application/vnd.google-earth.kmz"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = strdup("kmz"); format->renderer = MS_RENDER_WITH_KML; msSetOutputFormatOption( format, "ATTACHMENT", "mapserver.kmz"); } #endif #ifdef USE_GDAL if( strncasecmp(driver,"gdal/",5) == 0 ) { if(!name) name=driver+5; format = msAllocOutputFormat( map, name, driver ); if( msInitDefaultGDALOutputFormat( format ) == MS_FAILURE ) { if( map != NULL ) { map->numoutputformats--; map->outputformatlist[map->numoutputformats] = NULL; } msFreeOutputFormat( format ); format = NULL; } } #endif #ifdef USE_OGR if( strncasecmp(driver,"ogr/",4) == 0 ) { if(!name) name=driver+4; format = msAllocOutputFormat( map, name, driver ); if( msInitDefaultOGROutputFormat( format ) == MS_FAILURE ) { if( map != NULL ) { map->numoutputformats--; map->outputformatlist[map->numoutputformats] = NULL; } msFreeOutputFormat( format ); format = NULL; } } #endif if( strcasecmp(driver,"imagemap") == 0 ) { if(!name) name="imagemap"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("text/html; driver=imagemap"); format->extension = msStrdup("html"); format->imagemode = MS_IMAGEMODE_NULL; format->renderer = MS_RENDER_WITH_IMAGEMAP; } if( strcasecmp(driver,"template") == 0 ) { if(!name) name="template"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("text/html"); format->extension = msStrdup("html"); format->imagemode = MS_IMAGEMODE_FEATURE; format->renderer = MS_RENDER_WITH_TEMPLATE; } if( format != NULL ) format->inmapfile = MS_FALSE; return format; } /************************************************************************/ /* msApplyDefaultOutputFormats() */ /************************************************************************/ void msApplyDefaultOutputFormats( mapObj *map ) { char *saved_imagetype; struct defaultOutputFormatEntry *defEntry; if( map->imagetype == NULL ) saved_imagetype = NULL; else saved_imagetype = msStrdup(map->imagetype); defEntry = defaultoutputformats; while(defEntry->name) { if( msSelectOutputFormat( map, defEntry->name ) == NULL ) msCreateDefaultOutputFormat( map, defEntry->driver, defEntry->name ); defEntry++; } if( map->imagetype != NULL ) free( map->imagetype ); map->imagetype = saved_imagetype; } /************************************************************************/ /* msFreeOutputFormat() */ /************************************************************************/ void msFreeOutputFormat( outputFormatObj *format ) { if( format == NULL ) return; if( MS_REFCNT_DECR_IS_NOT_ZERO(format) ) { return; } if(MS_RENDERER_PLUGIN(format) && format->vtable) { format->vtable->cleanup(MS_RENDERER_CACHE(format->vtable)); free( format->vtable ); } msFree( format->name ); msFree( format->mimetype ); msFree( format->driver ); msFree( format->extension ); msFreeCharArray( format->formatoptions, format->numformatoptions ); msFree( format ); } /************************************************************************/ /* msAllocOutputFormat() */ /************************************************************************/ static outputFormatObj *msAllocOutputFormat( mapObj *map, const char *name, const char *driver ) { outputFormatObj *format; /* -------------------------------------------------------------------- */ /* Allocate the format object. */ /* -------------------------------------------------------------------- */ format = (outputFormatObj *) calloc(1,sizeof(outputFormatObj)); if( format == NULL ) { msSetError( MS_MEMERR, NULL, "msAllocOutputFormat()" ); return NULL; } /* -------------------------------------------------------------------- */ /* Initialize various fields. */ /* -------------------------------------------------------------------- */ format->bands = 1; format->name = msStrdup(name); format->driver = msStrdup(driver); format->refcount = 0; format->vtable = NULL; format->device = NULL; format->imagemode = MS_IMAGEMODE_RGB; /* -------------------------------------------------------------------- */ /* Attach to map. */ /* -------------------------------------------------------------------- */ if( map != NULL ) { map->numoutputformats++; if( map->outputformatlist == NULL ) map->outputformatlist = (outputFormatObj **) malloc(sizeof(void*)); else map->outputformatlist = (outputFormatObj **) realloc(map->outputformatlist, sizeof(void*) * map->numoutputformats ); map->outputformatlist[map->numoutputformats-1] = format; format->refcount++; } return format; } /************************************************************************/ /* msAppendOutputFormat() */ /* */ /* Add an output format . */ /* http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511 */ /************************************************************************/ int msAppendOutputFormat(mapObj *map, outputFormatObj *format) { /* -------------------------------------------------------------------- */ /* Attach to map. */ /* -------------------------------------------------------------------- */ if (map != NULL) { map->numoutputformats++; if (map->outputformatlist == NULL) map->outputformatlist = (outputFormatObj **) malloc(sizeof(void*)); else map->outputformatlist = (outputFormatObj **) realloc(map->outputformatlist, sizeof(void*) * map->numoutputformats ); map->outputformatlist[map->numoutputformats-1] = format; MS_REFCNT_INCR(format); } return map->numoutputformats; } /************************************************************************/ /* msRemoveOutputFormat() */ /* */ /* Remove an output format (by name). */ /* http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511 */ /************************************************************************/ int msRemoveOutputFormat(mapObj *map, const char *name) { int i, j; /* -------------------------------------------------------------------- */ /* Detach from map. */ /* -------------------------------------------------------------------- */ if (map != NULL) { if (map->outputformatlist == NULL) { msSetError(MS_CHILDERR, "Can't remove format from empty outputformatlist", "msRemoveOutputFormat()"); return MS_FAILURE; } else { i = msGetOutputFormatIndex(map, name); if (i >= 0) { map->numoutputformats--; if(MS_REFCNT_DECR_IS_ZERO(map->outputformatlist[i])) msFreeOutputFormat( map->outputformatlist[i] ); for (j=i; jnumoutputformats-1; j++) { map->outputformatlist[j] = map->outputformatlist[j+1]; } } map->outputformatlist = (outputFormatObj **) realloc(map->outputformatlist, sizeof(void*) * (map->numoutputformats) ); return MS_SUCCESS; } } return MS_FAILURE; } /************************************************************************/ /* msGetOutputFormatIndex() */ /* */ /* Pulled this out of msSelectOutputFormat for use in other cases. */ /************************************************************************/ int msGetOutputFormatIndex(mapObj *map, const char *imagetype) { int i; /* -------------------------------------------------------------------- */ /* Try to find the format in the maps list of formats, first by */ /* mime type, and then by output format name. */ /* -------------------------------------------------------------------- */ for (i = 0; i < map->numoutputformats; i++) { if (map->outputformatlist[i]->mimetype != NULL && strcasecmp(imagetype, map->outputformatlist[i]->mimetype) == 0 ) return i; } for( i = 0; i < map->numoutputformats; i++ ) { if( strcasecmp(imagetype,map->outputformatlist[i]->name) == 0 ) return i; } return -1; } /************************************************************************/ /* msSelectOutputFormat() */ /************************************************************************/ outputFormatObj *msSelectOutputFormat( mapObj *map, const char *imagetype ) { int index; outputFormatObj *format = NULL; if( map == NULL || imagetype == NULL || strlen(imagetype) == 0 ) return NULL; /* -------------------------------------------------------------------- */ /* Try to find the format in the maps list of formats, first by */ /* mime type, and then by output format name. */ /* -------------------------------------------------------------------- */ index = msGetOutputFormatIndex(map, imagetype); if (index >= 0) { format = map->outputformatlist[index]; } else { struct defaultOutputFormatEntry *formatEntry = defaultoutputformats; while(formatEntry->name) { if(!strcasecmp(imagetype,formatEntry->name) || !strcasecmp(imagetype,formatEntry->mimetype)) { format = msCreateDefaultOutputFormat( map, formatEntry->driver, formatEntry->name ); break; } formatEntry++; } } if (format) { if (map->imagetype) free(map->imagetype); map->imagetype = msStrdup(format->name); } if( format != NULL ) msOutputFormatValidate( format, MS_FALSE ); return format; } /************************************************************************/ /* msApplyOutputFormat() */ /************************************************************************/ void msApplyOutputFormat( outputFormatObj **target, outputFormatObj *format, int transparent, int interlaced, int imagequality ) { int change_needed = MS_FALSE; int old_imagequality, old_interlaced; outputFormatObj *formatToFree = NULL; assert( target != NULL ); if( *target != NULL && MS_REFCNT_DECR_IS_ZERO( (*target) ) ) { formatToFree = *target; *target = NULL; } if( format == NULL ) { if( formatToFree ) msFreeOutputFormat( formatToFree ); return; } msOutputFormatValidate( format, MS_FALSE ); /* -------------------------------------------------------------------- */ /* Do we need to change any values? If not, then just apply */ /* and return. */ /* -------------------------------------------------------------------- */ if( transparent != MS_NOOVERRIDE && !format->transparent != !transparent ) change_needed = MS_TRUE; old_imagequality = atoi(msGetOutputFormatOption( format, "QUALITY", "75")); if( imagequality != MS_NOOVERRIDE && old_imagequality != imagequality ) change_needed = MS_TRUE; old_interlaced = strcasecmp(msGetOutputFormatOption( format, "INTERLACE", "ON"), "OFF") != 0; if( interlaced != MS_NOOVERRIDE && !interlaced != !old_interlaced ) change_needed = MS_TRUE; if( change_needed ) { char new_value[128]; if( format->refcount > 0 ) format = msCloneOutputFormat( format ); if( transparent != MS_NOOVERRIDE ) { format->transparent = transparent; if( format->imagemode == MS_IMAGEMODE_RGB ) format->imagemode = MS_IMAGEMODE_RGBA; } if( imagequality != MS_NOOVERRIDE && imagequality != old_imagequality ) { snprintf( new_value, sizeof(new_value), "%d", imagequality ); msSetOutputFormatOption( format, "QUALITY", new_value ); } if( interlaced != MS_NOOVERRIDE && !interlaced != !old_interlaced ) { if( interlaced ) msSetOutputFormatOption( format, "INTERLACE", "ON" ); else msSetOutputFormatOption( format, "INTERLACE", "OFF" ); } } *target = format; format->refcount++; if( MS_RENDERER_PLUGIN(format) ) { msInitializeRendererVTable(format); } if( formatToFree ) msFreeOutputFormat( formatToFree ); } /************************************************************************/ /* msCloneOutputFormat() */ /************************************************************************/ outputFormatObj *msCloneOutputFormat( outputFormatObj *src ) { outputFormatObj *dst; int i; dst = msAllocOutputFormat( NULL, src->name, src->driver ); msFree( dst->mimetype ); if( src->mimetype ) dst->mimetype = msStrdup( src->mimetype ); else dst->mimetype = NULL; msFree( dst->extension ); if( src->extension ) dst->extension = msStrdup( src->extension ); else dst->extension = NULL; dst->imagemode = src->imagemode; dst->renderer = src->renderer; dst->transparent = src->transparent; dst->bands = src->bands; dst->numformatoptions = src->numformatoptions; dst->formatoptions = (char **) malloc(sizeof(char *) * src->numformatoptions ); for( i = 0; i < src->numformatoptions; i++ ) dst->formatoptions[i] = msStrdup(src->formatoptions[i]); dst->inmapfile = src->inmapfile; return dst; } /************************************************************************/ /* msGetOutputFormatOption() */ /* */ /* Fetch the value of a particular option. It is assumed the */ /* options are in "KEY=VALUE" format. */ /************************************************************************/ const char *msGetOutputFormatOption( outputFormatObj *format, const char *optionkey, const char *defaultresult ) { int i, len = strlen(optionkey); for( i = 0; i < format->numformatoptions; i++ ) { if( strncasecmp(format->formatoptions[i],optionkey,len) == 0 && format->formatoptions[i][len] == '=' ) return format->formatoptions[i] + len + 1; } return defaultresult; } /************************************************************************/ /* msSetOutputFormatOption() */ /************************************************************************/ void msSetOutputFormatOption( outputFormatObj *format, const char *key, const char *value ) { char *newline; int i, len; /* -------------------------------------------------------------------- */ /* Format the name=value pair into a newly allocated string. */ /* -------------------------------------------------------------------- */ newline = (char *) malloc(strlen(key)+strlen(value)+2); if( newline == NULL ) { assert( newline != NULL ); return; } sprintf( newline, "%s=%s", key, value ); /* -------------------------------------------------------------------- */ /* Does this key already occur? If so replace it. */ /* -------------------------------------------------------------------- */ len = strlen(key); for( i = 0; i < format->numformatoptions; i++ ) { if( strncasecmp(format->formatoptions[i],key,len) == 0 && format->formatoptions[i][len] == '=' ) { free( format->formatoptions[i] ); format->formatoptions[i] = newline; return; } } /* -------------------------------------------------------------------- */ /* otherwise, we need to grow the list. */ /* -------------------------------------------------------------------- */ format->numformatoptions++; format->formatoptions = (char **) realloc( format->formatoptions, sizeof(char*) * format->numformatoptions ); format->formatoptions[format->numformatoptions-1] = newline; /* -------------------------------------------------------------------- */ /* Capture generic value(s) we are interested in. */ /* -------------------------------------------------------------------- */ if( strcasecmp(key,"BAND_COUNT") == 0 ) format->bands = atoi(value); } /************************************************************************/ /* msGetOutputFormatMimeList() */ /************************************************************************/ void msGetOutputFormatMimeList( mapObj *map, char **mime_list, int max_mime ) { int mime_count = 0, i; msApplyDefaultOutputFormats(map); for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ ) { int j; if( map->outputformatlist[i]->mimetype == NULL ) continue; for( j = 0; j < mime_count; j++ ) { if( strcasecmp(mime_list[j], map->outputformatlist[i]->mimetype) == 0 ) break; } if( j == mime_count ) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } if( mime_count < max_mime ) mime_list[mime_count] = NULL; } /************************************************************************/ /* msGetOutputFormatMimeList() */ /************************************************************************/ void msGetOutputFormatMimeListImg( mapObj *map, char **mime_list, int max_mime ) { int mime_count = 0, i,j; const char *format_list = NULL; char **tokens = NULL; int numtokens = 0; outputFormatObj *format; msApplyDefaultOutputFormats(map); format_list = msOWSLookupMetadata(&(map->web.metadata), "M","getlegendgraphic_formatlist"); if ( format_list && strlen(format_list) > 0) tokens = msStringSplit(format_list, ',', &numtokens); if (tokens && numtokens > 0) { for(j = 0; j < numtokens; j++ ) { format = msSelectOutputFormat(map, tokens[j]); if (format != NULL) { mime_list[mime_count++] = format->mimetype; } } msFreeCharArray(tokens, numtokens); } else for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ ) { int j; if( map->outputformatlist[i]->mimetype == NULL ) continue; for( j = 0; j < mime_count; j++ ) { if( strcasecmp(mime_list[j], map->outputformatlist[i]->mimetype) == 0 ) break; } if( j == mime_count && map->outputformatlist[i]->driver && ( #ifdef USE_GD strncasecmp(map->outputformatlist[i]->driver, "GD/", 3)==0 || #endif strncasecmp(map->outputformatlist[i]->driver, "AGG/", 4)==0)) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } if( mime_count < max_mime ) mime_list[mime_count] = NULL; } /************************************************************************/ /* msGetOutputFormatMimeListWMS() */ /************************************************************************/ void msGetOutputFormatMimeListWMS( mapObj *map, char **mime_list, int max_mime ) { int mime_count = 0, i,j; const char *format_list = NULL; char **tokens = NULL; int numtokens = 0; outputFormatObj *format; msApplyDefaultOutputFormats(map); format_list = msOWSLookupMetadata(&(map->web.metadata), "M","getmap_formatlist"); if ( format_list && strlen(format_list) > 0) tokens = msStringSplit(format_list, ',', &numtokens); if (tokens && numtokens > 0) { for(j = 0; j < numtokens; j++ ) { format = msSelectOutputFormat(map, tokens[j]); if (format != NULL) { mime_list[mime_count++] = format->mimetype; } } msFreeCharArray(tokens, numtokens); } else { for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ ) { int j; if( map->outputformatlist[i]->mimetype == NULL ) continue; for( j = 0; j < mime_count; j++ ) { if( strcasecmp(mime_list[j], map->outputformatlist[i]->mimetype) == 0 ) break; } if( j == mime_count && map->outputformatlist[i]->driver && ( #ifdef USE_GD strncasecmp(map->outputformatlist[i]->driver, "GD/", 3)==0 || #endif strncasecmp(map->outputformatlist[i]->driver, "GDAL/", 5)==0 || strncasecmp(map->outputformatlist[i]->driver, "AGG/", 4)==0 || strcasecmp(map->outputformatlist[i]->driver, "CAIRO/SVG")==0 || strcasecmp(map->outputformatlist[i]->driver, "CAIRO/PDF")==0 || strcasecmp(map->outputformatlist[i]->driver, "kml")==0 || strcasecmp(map->outputformatlist[i]->driver, "kmz")==0)) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } } if( mime_count < max_mime ) mime_list[mime_count] = NULL; } /************************************************************************/ /* msOutputFormatValidate() */ /* */ /* Do some validation of the output format, and report to debug */ /* output if it doesn't seem valid. Fixup in place as best as */ /* possible. */ /************************************************************************/ int msOutputFormatValidate( outputFormatObj *format, int issue_error ) { int result = MS_TRUE; char *driver_ext; format->bands = atoi(msGetOutputFormatOption( format, "BAND_COUNT", "1" )); /* Enforce the requirement that JPEG be RGB and TRANSPARENT=OFF */ driver_ext = strstr(format->driver,"/"); if( driver_ext && ++driver_ext && !strcasecmp(driver_ext,"JPEG")) { if( format->transparent ) { if( issue_error ) msSetError( MS_MISCERR, "JPEG OUTPUTFORMAT %s has TRANSPARENT set ON, but this is not supported.\n" "It has been disabled.\n", "msOutputFormatValidate()", format->name ); else msDebug( "JPEG OUTPUTFORMAT %s has TRANSPARENT set ON, but this is not supported.\n" "It has been disabled.\n", format->name ); format->transparent = MS_FALSE; result = MS_FALSE; } if( format->imagemode == MS_IMAGEMODE_RGBA ) { if( issue_error ) msSetError( MS_MISCERR, "JPEG OUTPUTFORMAT %s has IMAGEMODE RGBA, but this is not supported.\n" "IMAGEMODE forced to RGB.\n", "msOutputFormatValidate()", format->name ); else msDebug( "JPEG OUTPUTFORMAT %s has IMAGEMODE RGBA, but this is not supported.\n" "IMAGEMODE forced to RGB.\n", format->name ); format->imagemode = MS_IMAGEMODE_RGB; result = MS_FALSE; } } if( format->transparent && format->imagemode == MS_IMAGEMODE_RGB ) { if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s has TRANSPARENT set ON, but an IMAGEMODE\n" "of RGB instead of RGBA. Changing imagemode to RGBA.\n", "msOutputFormatValidate()", format->name ); else msDebug("OUTPUTFORMAT %s has TRANSPARENT set ON, but an IMAGEMODE\n" "of RGB instead of RGBA. Changing imagemode to RGBA.\n", format->name ); format->imagemode = MS_IMAGEMODE_RGBA; result = MS_FALSE; } /* Special checking around RAWMODE image modes. */ if( format->imagemode == MS_IMAGEMODE_INT16 || format->imagemode == MS_IMAGEMODE_FLOAT32 || format->imagemode == MS_IMAGEMODE_BYTE ) { if( strncmp(format->driver,"GDAL/",5) != 0 ) { result = MS_FALSE; if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s has IMAGEMODE BYTE/INT16/FLOAT32, but this is only supported for GDAL drivers.", "msOutputFormatValidate()", format->name ); else msDebug( "OUTPUTFORMAT %s has IMAGEMODE BYTE/INT16/FLOAT32, but this is only supported for GDAL drivers.", format->name ); } if( format->renderer != MS_RENDER_WITH_RAWDATA ) /* see bug 724 */ format->renderer = MS_RENDER_WITH_RAWDATA; } #ifdef USE_GD if(format->renderer == MS_RENDER_WITH_GD && format->imagemode != MS_IMAGEMODE_PC256) { if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s has IMAGEMODE RGB/RGBA, which is not supported for GD drivers.", "msOutputFormatValidate()", format->name ); else msDebug( "OUTPUTFORMAT %s has IMAGEMODE RGB/RGBA, which is not supported for GD drivers.", format->name ); format->renderer = MS_RENDER_WITH_AGG; } #endif return result; } /************************************************************************/ /* msInitializeRendererVTable() */ /************************************************************************/ int msInitializeRendererVTable(outputFormatObj *format) { assert(format); if(format->vtable) { return MS_SUCCESS; } format->vtable = (rendererVTableObj*)calloc(1,sizeof(rendererVTableObj)); msInitializeDummyRenderer(format->vtable); switch(format->renderer) { case MS_RENDER_WITH_AGG: return msPopulateRendererVTableAGG(format->vtable); #ifdef USE_GD case MS_RENDER_WITH_GD: return msPopulateRendererVTableGD(format->vtable); #endif #ifdef USE_CAIRO case MS_RENDER_WITH_CAIRO_RASTER: return msPopulateRendererVTableCairoRaster(format->vtable); case MS_RENDER_WITH_CAIRO_PDF: return msPopulateRendererVTableCairoPDF(format->vtable); case MS_RENDER_WITH_CAIRO_SVG: return msPopulateRendererVTableCairoSVG(format->vtable); #endif #ifdef USE_OGL case MS_RENDER_WITH_OGL: return msPopulateRendererVTableOGL(format->vtable); #endif #ifdef USE_KML case MS_RENDER_WITH_KML: return msPopulateRendererVTableKML(format->vtable); #endif #ifdef USE_OGR case MS_RENDER_WITH_OGR: return msPopulateRendererVTableOGR(format->vtable); #endif default: msSetError(MS_MISCERR, "unsupported RendererVtable renderer %d", "msInitializeRendererVTable()",format->renderer); return MS_FAILURE; } /* this code should never be executed */ return MS_FAILURE; } mapserver-6.4.1/GD-COPYING0000644002461700001440000000421012261257215014634 0ustar tbonfortusers Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 by Cold Spring Harbor Laboratory. Funded under Grant P41-RR02188 by the National Institutes of Health. Portions copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 by Boutell.Com, Inc. Portions relating to GD2 format copyright 1999, 2000, 2001, 2002 Philip Warner. Portions relating to PNG copyright 1999, 2000, 2001, 2002 Greg Roelofs. Portions relating to gdttf.c copyright 1999, 2000, 2001, 2002 John Ellson (ellson@lucent.com). Portions relating to gdft.c copyright 2001, 2002 John Ellson (ellson@lucent.com). Portions relating to JPEG and to color quantization copyright 2000, 2001, 2002, Doug Becker and copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, Thomas G. Lane. This software is based in part on the work of the Independent JPEG Group. See the file README-JPEG.TXT for more information. Portions relating to WBMP copyright 2000, 2001, 2002 Maurice Szmurlo and Johan Van den Brande. Permission has been granted to copy, distribute and modify gd in any context without fee, including a commercial application, provided that this notice is present in user-accessible supporting documentation. This does not affect your ownership of the derived work itself, and the intent is to assure proper credit for the authors of gd, not to interfere with your productive use of gd. If you have questions, ask. "Derived works" includes all programs that utilize the library. Credit must be given in user-accessible documentation. This software is provided "AS IS." The copyright holders disclaim all warranties, either express or implied, including but not limited to implied warranties of merchantability and fitness for a particular purpose, with respect to this code and accompanying documentation. Although their code does not appear in gd, the authors wish to thank David Koblas, David Rowley, and Hutchison Avenue Software Corporation for their prior contributions. mapserver-6.4.1/mapserv.c0000644002461700001440000002421112261257215015135 0ustar tbonfortusers/****************************************************************************** * $id: mapserv.c 9470 2009-10-16 16:09:31Z sdlime $ * * Project: MapServer * Purpose: MapServer CGI mainline. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver-config.h" #ifdef USE_FASTCGI #define NO_FCGI_DEFINES #include "fcgi_stdio.h" #endif #include "mapserv.h" #include "mapio.h" #include "maptime.h" #ifndef WIN32 #include #endif /************************************************************************/ /* FastCGI cleanup functions. */ /************************************************************************/ #ifndef WIN32 void msCleanupOnSignal( int nInData ) { /* For some reason, the fastcgi message code does not seem to work */ /* from within the signal handler on Unix. So we force output through */ /* normal stdio functions. */ msIO_installHandlers( NULL, NULL, NULL ); msIO_fprintf( stderr, "In msCleanupOnSignal.\n" ); msCleanup(1); exit(0); } #endif #ifdef WIN32 void msCleanupOnExit( void ) { /* note that stderr and stdout seem to be non-functional in the */ /* fastcgi/win32 case. If you really want to check functioning do */ /* some sort of hack logging like below ... otherwise just trust it! */ #ifdef notdef FILE *fp_out = fopen( "D:\\temp\\mapserv.log", "w" ); fprintf( fp_out, "In msCleanupOnExit\n" ); fclose( fp_out ); #endif msCleanup(1); } #endif #ifdef USE_FASTCGI /************************************************************************/ /* msIO_fcgiRead() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_fcgiRead( void *cbData, void *data, int byteCount ) { return FCGI_fread( data, 1, byteCount, (FCGI_FILE *) cbData ); } /************************************************************************/ /* msIO_fcgiWrite() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_fcgiWrite( void *cbData, void *data, int byteCount ) { return FCGI_fwrite( data, 1, byteCount, (FCGI_FILE *) cbData ); } /************************************************************************/ /* msIO_installFastCGIRedirect() */ /************************************************************************/ static int msIO_installFastCGIRedirect() { msIOContext stdin_ctx, stdout_ctx, stderr_ctx; stdin_ctx.label = "fcgi"; stdin_ctx.write_channel = MS_FALSE; stdin_ctx.readWriteFunc = msIO_fcgiRead; stdin_ctx.cbData = (void *) FCGI_stdin; stdout_ctx.label = "fcgi"; stdout_ctx.write_channel = MS_TRUE; stdout_ctx.readWriteFunc = msIO_fcgiWrite; stdout_ctx.cbData = (void *) FCGI_stdout; stderr_ctx.label = "fcgi"; stderr_ctx.write_channel = MS_TRUE; stderr_ctx.readWriteFunc = msIO_fcgiWrite; stderr_ctx.cbData = (void *) FCGI_stderr; msIO_installHandlers( &stdin_ctx, &stdout_ctx, &stderr_ctx ); return MS_TRUE; } #endif /************************************************************************/ /* main() */ /************************************************************************/ int main(int argc, char *argv[]) { int iArg; int sendheaders = MS_TRUE; struct mstimeval execstarttime, execendtime; struct mstimeval requeststarttime, requestendtime; mapservObj* mapserv = NULL; /* -------------------------------------------------------------------- */ /* Initialize mapserver. This sets up threads, GD and GEOS as */ /* well as using MS_ERRORFILE and MS_DEBUGLEVEL env vars if set. */ /* -------------------------------------------------------------------- */ if( msSetup() != MS_SUCCESS ) { msCGIWriteError(mapserv); msCleanup(0); exit(0); } if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); /* -------------------------------------------------------------------- */ /* Process arguments. In normal use as a cgi-bin there are no */ /* commandline switches, but we provide a few for test/debug */ /* purposes, and to query the version info. */ /* -------------------------------------------------------------------- */ for( iArg = 1; iArg < argc; iArg++ ) { /* Keep only "-v", "-nh" and "QUERY_STRING=..." enabled by default. * The others will require an explicit -DMS_ENABLE_CGI_CL_DEBUG_ARGS * at compile time. */ if( strcmp(argv[iArg],"-v") == 0 ) { printf("%s\n", msGetVersion()); fflush(stdout); exit(0); } else if(strcmp(argv[iArg], "-nh") == 0) { sendheaders = MS_FALSE; } else if( strncmp(argv[iArg], "QUERY_STRING=", 13) == 0 ) { /* Debugging hook... pass "QUERY_STRING=..." on the command-line */ putenv( "REQUEST_METHOD=GET" ); putenv( argv[iArg] ); } #ifdef MS_ENABLE_CGI_CL_DEBUG_ARGS else if( iArg < argc-1 && strcmp(argv[iArg], "-tmpbase") == 0) { msForceTmpFileBase( argv[++iArg] ); } else if( iArg < argc-1 && strcmp(argv[iArg], "-t") == 0) { char **tokens; int numtokens=0; if((tokens=msTokenizeMap(argv[iArg+1], &numtokens)) != NULL) { int i; for(i=0; imap && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCGIWriteLog(mapserv,MS_FALSE); msFreeMapServObj(mapserv); } #ifdef USE_FASTCGI /* FCGI_ --- return to top of loop */ msResetErrorList(); continue; } /* end fastcgi loop */ #endif /* normal case, processing is complete */ if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&execendtime, NULL); msDebug("mapserv total execution time: %.3fs\n", (execendtime.tv_sec+execendtime.tv_usec/1.0e6)- (execstarttime.tv_sec+execstarttime.tv_usec/1.0e6) ); } msCleanup(0); #ifdef _WIN32 /* flush pending writes to stdout */ fflush(stdout); #endif exit( 0 ); } mapserver-6.4.1/mapagg.cpp0000644002461700001440000013734412261257215015270 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: AGG rendering and other AGG related functions. * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * 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. *****************************************************************************/ #include "mapserver.h" #include #include "renderers/agg/include/agg_color_rgba.h" #include "renderers/agg/include/agg_pixfmt_rgba.h" #include "renderers/agg/include/agg_renderer_base.h" #include "renderers/agg/include/agg_renderer_scanline.h" #include "renderers/agg/include/agg_math_stroke.h" #include "renderers/agg/include/agg_scanline_p.h" #include "renderers/agg/include/agg_scanline_u.h" #include "renderers/agg/include/agg_rasterizer_scanline_aa.h" #include "renderers/agg/include/agg_span_pattern_rgba.h" #include "renderers/agg/include/agg_span_allocator.h" #include "renderers/agg/include/agg_span_interpolator_linear.h" #include "renderers/agg/include/agg_span_image_filter_rgba.h" #include "renderers/agg/include/agg_pattern_filters_rgba.h" #include "renderers/agg/include/agg_span_image_filter_rgb.h" #include "renderers/agg/include/agg_image_accessors.h" #include "renderers/agg/include/agg_conv_stroke.h" #include "renderers/agg/include/agg_conv_dash.h" #include "renderers/agg/include/agg_path_storage.h" #include "renderers/agg/include/agg_font_freetype.h" #include "renderers/agg/include/agg_conv_contour.h" #include "renderers/agg/include/agg_ellipse.h" #include "renderers/agg/include/agg_gamma_functions.h" #include "renderers/agg/include/agg_rasterizer_outline_aa.h" #include "renderers/agg/include/agg_renderer_outline_aa.h" #include "renderers/agg/include/agg_renderer_outline_image.h" #include "renderers/agg/include/agg_span_pattern_rgba.h" #include "renderers/agg/include/agg_span_image_filter_rgba.h" #include "renderers/agg/include/agg_glyph_raster_bin.h" #include "renderers/agg/include/agg_renderer_raster_text.h" #include "renderers/agg/include/agg_embedded_raster_fonts.h" #include "renderers/agg/include/agg_conv_clipper.h" #ifdef AGG_ALIASED_ENABLED #include "renderers/agg/include/agg_renderer_primitives.h" #include "renderers/agg/include/agg_rasterizer_outline.h" #endif typedef mapserver::order_bgra band_order; #define AGG_LINESPACE 1.33 typedef mapserver::int8u band_type; typedef mapserver::rgba8 color_type; typedef mapserver::pixel32_type pixel_type; typedef mapserver::blender_rgba_pre blender_pre; typedef mapserver::pixfmt_alpha_blend_rgba pixel_format; typedef mapserver::rendering_buffer rendering_buffer; typedef mapserver::renderer_base renderer_base; typedef mapserver::renderer_scanline_aa_solid renderer_scanline; typedef mapserver::rasterizer_scanline_aa<> rasterizer_scanline; typedef mapserver::font_engine_freetype_int16 font_engine_type; typedef mapserver::font_cache_manager font_manager_type; typedef mapserver::conv_curve font_curve_type; #ifdef AGG_ALIASED_ENABLED typedef mapserver::renderer_primitives renderer_primitives; typedef mapserver::rasterizer_outline rasterizer_outline; #endif static color_type AGG_NO_COLOR = color_type(0, 0, 0, 0); const mapserver::int8u* rasterfonts[]= { mapserver::mcs5x10_mono, /*gd tiny. gse5x7 is a bit less high than gd tiny*/ mapserver::mcs5x11_mono, /*gd small*/ mapserver::mcs6x11_mono, /*gd medium*/ mapserver::mcs7x12_mono_low, /*gd large*/ mapserver::mcs7x12_mono_high /*gd huge*/ }; fontMetrics rasterfont_sizes[] = { {5,mapserver::mcs5x10_mono[0]}, {5,mapserver::mcs5x11_mono[0]}, {6,mapserver::mcs6x11_mono[0]}, {7,mapserver::mcs7x12_mono_low[0]}, {7,mapserver::mcs7x12_mono_high[0]} }; /* * interface to a shapeObj representing lines, providing the functions * needed by the agg rasterizer. treats shapeObjs with multiple linestrings. */ class line_adaptor { public: line_adaptor(shapeObj *shape):s(shape) { m_line=s->line; /*first line*/ m_point=m_line->point; /*current vertex is first vertex of first line*/ m_lend=&(s->line[s->numlines]); /*pointer to after last line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } /* a class with virtual functions should also provide a virtual destructor */ virtual ~line_adaptor() {} void rewind(unsigned) { m_line=s->line; /*first line*/ m_point=m_line->point; /*current vertex is first vertex of first line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { /*here we treat the case where a real vertex is returned*/ bool first = m_point == m_line->point; /*is this the first vertex of a line*/ *x = m_point->x; *y = m_point->y; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } /*if here, we're at the end of a line*/ m_line++; *x = *y = 0.0; if(m_line>=m_lend) /*is this the last line of the shapObj. normally, (m_line==m_lend) should be a sufficient test, as the caller should not call this function if a previous call returned path_cmd_stop.*/ return mapserver::path_cmd_stop; /*no more points to process*/ /*if here, there are more lines in the shapeObj, continue with next one*/ m_point=m_line->point; /*pointer to first point of next line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last point of next line*/ return vertex(x,y); /*this will return the first point of the next line*/ } private: shapeObj *s; lineObj *m_line, /*current line pointer*/ *m_lend; /*points to after the last line*/ pointObj *m_point, /*current point*/ *m_pend; /*points to after last point of current line*/ }; class polygon_adaptor { public: polygon_adaptor(shapeObj *shape):s(shape),m_stop(false) { m_line=s->line; /*first lines*/ m_point=m_line->point; /*first vertex of first line*/ m_lend=&(s->line[s->numlines]); /*pointer to after last line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } /* a class with virtual functions should also provide a virtual destructor */ virtual ~polygon_adaptor() {} void rewind(unsigned) { /*reset pointers*/ m_stop=false; m_line=s->line; m_point=m_line->point; m_pend=&(m_line->point[m_line->numpoints]); } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { /*if here, we have a real vertex*/ bool first = m_point == m_line->point; *x = m_point->x; *y = m_point->y; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } *x = *y = 0.0; if(!m_stop) { /*if here, we're after the last vertex of the current line * we return the command to close the current polygon*/ m_line++; if(m_line>=m_lend) { /*if here, we've finished all the vertexes of the shape. * we still return the command to close the current polygon, * but set m_stop so the subsequent call to vertex() will return * the stop command*/ m_stop=true; return mapserver::path_cmd_end_poly; } /*if here, there's another line in the shape, so we set the pointers accordingly * and return the command to close the current polygon*/ m_point=m_line->point; /*first vertex of next line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of next line*/ return mapserver::path_cmd_end_poly; } /*if here, a previous call to vertex informed us that we'd consumed all the vertexes * of the shape. return the command to stop processing this shape*/ return mapserver::path_cmd_stop; } private: shapeObj *s; double ox,oy; lineObj *m_line, /*pointer to current line*/ *m_lend; /*pointer to after last line of the shape*/ pointObj *m_point, /*pointer to current vertex*/ *m_pend; /*pointer to after last vertex of current line*/ bool m_stop; /*should next call return stop command*/ }; #define aggColor(c) mapserver::rgba8_pre(c->red, c->green, c->blue, c->alpha) class aggRendererCache { public: font_engine_type m_feng; font_manager_type m_fman; aggRendererCache(): m_fman(m_feng) {} }; class AGG2Renderer { public: AGG2Renderer() #ifdef AGG_ALIASED_ENABLED : m_renderer_primitives(m_renderer_base), m_rasterizer_primitives(m_renderer_primitives) #endif { stroke = NULL; dash = NULL; stroke_dash = NULL; } ~AGG2Renderer() { if(stroke) { delete stroke; } if(dash) { delete dash; } if(stroke_dash) { delete stroke_dash; } } band_type* buffer; rendering_buffer m_rendering_buffer; pixel_format m_pixel_format; renderer_base m_renderer_base; renderer_scanline m_renderer_scanline; #ifdef AGG_ALIASED_ENABLED renderer_primitives m_renderer_primitives; rasterizer_outline m_rasterizer_primitives; #endif rasterizer_scanline m_rasterizer_aa; rasterizer_scanline m_rasterizer_aa_gamma; mapserver::scanline_p8 sl_poly; /*packed scanlines, works faster when the area is larger than the perimeter, in number of pixels*/ mapserver::scanline_u8 sl_line; /*unpacked scanlines, works faster if the area is roughly equal to the perimeter, in number of pixels*/ bool use_alpha; mapserver::conv_stroke *stroke; mapserver::conv_dash *dash; mapserver::conv_stroke > *stroke_dash; }; #define AGG_RENDERER(image) ((AGG2Renderer*) (image)->img.plugin) template static void applyCJC(VertexSource &stroke, int caps, int joins) { switch (joins) { case MS_CJC_ROUND: stroke.line_join(mapserver::round_join); break; case MS_CJC_MITER: stroke.line_join(mapserver::miter_join); break; case MS_CJC_BEVEL: case MS_CJC_NONE: stroke.line_join(mapserver::bevel_join); break; } switch (caps) { case MS_CJC_BUTT: case MS_CJC_NONE: stroke.line_cap(mapserver::butt_cap); break; case MS_CJC_ROUND: stroke.line_cap(mapserver::round_cap); break; case MS_CJC_SQUARE: stroke.line_cap(mapserver::square_cap); break; } } inline int aggLoadFont(aggRendererCache *cache, char *font, double size) { if(!cache->m_feng.name() || strcmp(cache->m_feng.name(),font)) { if (!cache->m_feng.load_font(font, 0, mapserver::glyph_ren_outline)) { msSetError(MS_TTFERR, "AGG error loading font (%s)", "aggLoadFont()", font); return MS_FAILURE; } if(!cache->m_feng.hinting()) cache->m_feng.hinting(true); if(cache->m_feng.resolution() != 96) cache->m_feng.resolution(96); if(!cache->m_feng.flip_y()) cache->m_feng.flip_y(true); cache->m_feng.height(size); } else { if(cache->m_feng.height()!=size) cache->m_feng.height(size); } return MS_SUCCESS; } int agg2RenderLine(imageObj *img, shapeObj *p, strokeStyleObj *style) { AGG2Renderer *r = AGG_RENDERER(img); line_adaptor lines = line_adaptor(p); #ifdef AGG_ALIASED_ENABLED r->m_rasterizer_primitives.reset(); r->m_renderer_primitives.line_color(aggColor(style->color)); r->m_rasterizer_primitives.add_path(lines); return MS_SUCCESS; #endif r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_renderer_scanline.color(aggColor(style->color)); if (style->patternlength <= 0) { if(!r->stroke) { r->stroke = new mapserver::conv_stroke(lines); } else { r->stroke->attach(lines); } r->stroke->width(style->width); if(style->width>1) { applyCJC(*r->stroke, style->linecap, style->linejoin); } else { r->stroke->inner_join(mapserver::inner_bevel); r->stroke->line_join(mapserver::bevel_join); } r->m_rasterizer_aa.add_path(*r->stroke); } else { if(!r->dash) { r->dash = new mapserver::conv_dash(lines); } else { r->dash->remove_all_dashes(); r->dash->dash_start(0.0); r->dash->attach(lines); } if(!r->stroke_dash) { r->stroke_dash = new mapserver::conv_stroke > (*r->dash); } else { r->stroke_dash->attach(*r->dash); } int patt_length = 0; for (int i = 0; i < style->patternlength; i += 2) { if (i < style->patternlength - 1) { r->dash->add_dash(MS_MAX(1,MS_NINT(style->pattern[i])), MS_MAX(1,MS_NINT(style->pattern[i + 1]))); if(style->patternoffset) { patt_length += MS_MAX(1,MS_NINT(style->pattern[i])) + MS_MAX(1,MS_NINT(style->pattern[i + 1])); } } } if(style->patternoffset > 0) { r->dash->dash_start(patt_length - style->patternoffset); } r->stroke_dash->width(style->width); if(style->width>1) { applyCJC(*r->stroke_dash, style->linecap, style->linejoin); } else { r->stroke_dash->inner_join(mapserver::inner_bevel); r->stroke_dash->line_join(mapserver::bevel_join); } r->m_rasterizer_aa.add_path(*r->stroke_dash); } mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); return MS_SUCCESS; } int agg2RenderLineTiled(imageObj *img, shapeObj *p, imageObj * tile) { mapserver::pattern_filter_bilinear_rgba8 fltr; typedef mapserver::line_image_pattern pattern_type; typedef mapserver::renderer_outline_image renderer_img_type; typedef mapserver::rasterizer_outline_aa rasterizer_img_type; pattern_type patt(fltr); AGG2Renderer *r = AGG_RENDERER(img); AGG2Renderer *tileRenderer = AGG_RENDERER(tile); line_adaptor lines(p); patt.create(tileRenderer->m_pixel_format); renderer_img_type ren_img(r->m_renderer_base, patt); rasterizer_img_type ras_img(ren_img); ras_img.add_path(lines); return MS_SUCCESS; } int agg2RenderPolygon(imageObj *img, shapeObj *p, colorObj * color) { AGG2Renderer *r = AGG_RENDERER(img); polygon_adaptor polygons(p); r->m_rasterizer_aa_gamma.reset(); r->m_rasterizer_aa_gamma.filling_rule(mapserver::fill_even_odd); r->m_rasterizer_aa_gamma.add_path(polygons); r->m_renderer_scanline.color(aggColor(color)); mapserver::render_scanlines(r->m_rasterizer_aa_gamma, r->sl_poly, r->m_renderer_scanline); return MS_SUCCESS; } int agg2RenderPolygonTiled(imageObj *img, shapeObj *p, imageObj * tile) { assert(img->format->renderer == tile->format->renderer); AGG2Renderer *r = AGG_RENDERER(img); AGG2Renderer *tileRenderer = AGG_RENDERER(tile); polygon_adaptor polygons(p); typedef mapserver::wrap_mode_repeat wrap_type; typedef mapserver::image_accessor_wrap img_source_type; typedef mapserver::span_pattern_rgba span_gen_type; mapserver::span_allocator sa; r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd); img_source_type img_src(tileRenderer->m_pixel_format); span_gen_type sg(img_src, 0, 0); r->m_rasterizer_aa.add_path(polygons); mapserver::render_scanlines_aa(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_base, sa , sg); return MS_SUCCESS; } int agg2RenderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text) { AGG2Renderer *r = AGG_RENDERER(img); aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img)); if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); int curfontidx = 0; const mapserver::glyph_cache* glyph; int unicode; font_curve_type m_curves(cache->m_fman.path_adaptor()); mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-x, -y); /*agg angles are antitrigonometric*/ mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x, y); double fx = x, fy = y; const char *utfptr = text; mapserver::path_storage glyphs; //first render all the glyphs to a path while (*utfptr) { if (*utfptr == '\r') { fx = x; utfptr++; continue; } if (*utfptr == '\n') { fx = x; fy += ceil(style->size * AGG_LINESPACE); utfptr++; continue; } utfptr += msUTF8ToUniChar(utfptr, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; inumfonts; i++) { if(aggLoadFont(cache,style->fonts[i],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = i; glyph = cache->m_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { //cache->m_fman.add_kerning(&fx, &fy); cache->m_fman.init_embedded_adaptors(glyph, fx, fy); mapserver::conv_transform trans_c(m_curves, mtx); glyphs.concat_path(trans_c); fx += glyph->advance_x; fy += glyph->advance_y; } } if (style->outlinewidth) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour cc(glyphs); cc.width(style->outlinewidth + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(glyphs); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; } int agg2RenderBitmapGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text) { typedef mapserver::glyph_raster_bin glyph_gen; int size = MS_NINT(style->size); if(size<0 || size>4) { msSetError(MS_RENDERERERR,"invalid bitmap font size", "agg2RenderBitmapGlyphs()"); return MS_FAILURE; } AGG2Renderer *r = AGG_RENDERER(img); glyph_gen glyph(0); mapserver::renderer_raster_htext_solid rt(r->m_renderer_base, glyph); glyph.font(rasterfonts[size]); int numlines=0; char **lines; /*masking out the out-of-range character codes*/ int len; int cc_start = rasterfonts[size][2]; int cc_end = cc_start + rasterfonts[size][3]; if(msCountChars(text,'\n')) { if((lines = msStringSplit((const char*)text, '\n', &(numlines))) == NULL) return(-1); } else { lines = &text; numlines = 1; } y -= glyph.base_line(); for(int n=0; n cc_end) lines[n][i] = '.'; if(style->outlinewidth > 0) { rt.color(aggColor(style->outlinecolor)); for(int i=-1; i<=1; i++) { for(int j=-1; j<=1; j++) { if(i||j) { rt.render_text(x+i, y+j, lines[n], true); } } } } assert(style->color); rt.color(aggColor(style->color)); rt.render_text(x, y, lines[n], true); y += glyph.height(); } if(*lines != text) msFreeCharArray(lines, numlines); return MS_SUCCESS; return MS_SUCCESS; } int agg2RenderGlyphsLine(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text) { AGG2Renderer *r = AGG_RENDERER(img); aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img)); if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); const mapserver::glyph_cache* glyph; int unicode; int curfontidx = 0; font_curve_type m_curves(cache->m_fman.path_adaptor()); mapserver::path_storage glyphs; for (int i = 0; i < labelpath->path.numpoints; i++) { assert(text); mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-labelpath->path.point[i].x,-labelpath->path.point[i].y); mtx *= mapserver::trans_affine_rotation(-labelpath->angles[i]); mtx *= mapserver::trans_affine_translation(labelpath->path.point[i].x,labelpath->path.point[i].y); text += msUTF8ToUniChar(text, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; inumfonts; i++) { if(aggLoadFont(cache,style->fonts[i],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = i; glyph = cache->m_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { cache->m_fman.init_embedded_adaptors(glyph, labelpath->path.point[i].x,labelpath->path.point[i].y); mapserver::conv_transform trans_c(m_curves, mtx); glyphs.concat_path(trans_c); } } if (style->outlinewidth) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour cc(glyphs); cc.width(style->outlinewidth + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(glyphs); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; } static mapserver::path_storage imageVectorSymbolAGG(symbolObj *symbol) { mapserver::path_storage path; bool is_new=true; for(int i=0; i < symbol->numpoints; i++) { if((symbol->points[i].x == -99) && (symbol->points[i].y == -99)) { // (PENUP) is_new=true; } else { if(is_new) { path.move_to(symbol->points[i].x,symbol->points[i].y); is_new=false; } else { path.line_to(symbol->points[i].x,symbol->points[i].y); } } } return path; } int agg2RenderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); double ox = symbol->sizex * 0.5; double oy = symbol->sizey * 0.5; mapserver::path_storage path = imageVectorSymbolAGG(symbol); mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-ox,-oy); mtx *= mapserver::trans_affine_scaling(style->scale); mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x, y); path.transform(mtx); if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd); r->m_rasterizer_aa.add_path(path); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_scanline); } if(style->outlinecolor) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::conv_stroke stroke(path); stroke.width(style->outlinewidth); r->m_rasterizer_aa.add_path(stroke); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_scanline); } return MS_SUCCESS; } int agg2RenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); rasterBufferObj *pixmap = symbol->pixmap_buffer; assert(pixmap->type == MS_BUFFER_BYTE_RGBA); rendering_buffer b(pixmap->data.rgba.pixels,pixmap->width,pixmap->height,pixmap->data.rgba.row_step); pixel_format pf(b); r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); if ( (style->rotation != 0 && style->rotation != MS_PI*2.)|| style->scale != 1) { mapserver::trans_affine image_mtx; image_mtx *= mapserver::trans_affine_translation(-(pf.width()/2.),-(pf.height()/2.)); /*agg angles are antitrigonometric*/ image_mtx *= mapserver::trans_affine_rotation(-style->rotation); image_mtx *= mapserver::trans_affine_scaling(style->scale); image_mtx *= mapserver::trans_affine_translation(x,y); image_mtx.invert(); typedef mapserver::span_interpolator_linear<> interpolator_type; interpolator_type interpolator(image_mtx); mapserver::span_allocator sa; // "hardcoded" bilinear filter //------------------------------------------ typedef mapserver::span_image_filter_rgba_bilinear_clip span_gen_type; span_gen_type sg(pf, mapserver::rgba(0,0,0,0), interpolator); mapserver::path_storage pixmap_bbox; int ims_2 = MS_NINT(MS_MAX(pixmap->width,pixmap->height)*style->scale*1.415)/2+1; pixmap_bbox.move_to(x-ims_2,y-ims_2); pixmap_bbox.line_to(x+ims_2,y-ims_2); pixmap_bbox.line_to(x+ims_2,y+ims_2); pixmap_bbox.line_to(x-ims_2,y+ims_2); r->m_rasterizer_aa.add_path(pixmap_bbox); mapserver::render_scanlines_aa(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_base, sa, sg); } else { //just copy the image at the correct location (we place the pixmap on //the nearest integer pixel to avoid blurring) r->m_renderer_base.blend_from(pf,0,MS_NINT(x-pixmap->width/2.),MS_NINT(y-pixmap->height/2.)); } return MS_SUCCESS; } int agg2RenderEllipseSymbol(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(image); mapserver::path_storage path; mapserver::ellipse ellipse(x,y,symbol->sizex*style->scale/2,symbol->sizey*style->scale/2); path.concat_path(ellipse); if( style->rotation != 0) { mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-x,-y); /*agg angles are antitrigonometric*/ mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x,y); path.transform(mtx); } if(style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd); r->m_rasterizer_aa.add_path(path); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if(style->outlinewidth) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_stroke stroke(path); stroke.width(style->outlinewidth); r->m_rasterizer_aa.add_path(stroke); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_scanline); } return MS_SUCCESS; } int agg2RenderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img)); if(aggLoadFont(cache,symbol->full_font_path,style->scale) == MS_FAILURE) return MS_FAILURE; int unicode; font_curve_type m_curves(cache->m_fman.path_adaptor()); msUTF8ToUniChar(symbol->character, &unicode); const mapserver::glyph_cache* glyph = cache->m_fman.glyph(unicode); double ox = (glyph->bounds.x1 + glyph->bounds.x2) / 2.; double oy = (glyph->bounds.y1 + glyph->bounds.y2) / 2.; mapserver::trans_affine mtx = mapserver::trans_affine_translation(-ox, -oy); if(style->rotation) mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x, y); mapserver::path_storage glyphs; cache->m_fman.init_embedded_adaptors(glyph, 0,0); mapserver::conv_transform trans_c(m_curves, mtx); glyphs.concat_path(trans_c); if (style->outlinecolor) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour cc(glyphs); cc.auto_detect_orientation(true); cc.width(style->outlinewidth + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(glyphs); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; } int agg2RenderTile(imageObj *img, imageObj *tile, double x, double y) { /* AGG2Renderer *imgRenderer = agg2GetRenderer(img); AGG2Renderer *tileRenderer = agg2GetRenderer(tile); */ return MS_FAILURE; } int aggInitializeRasterBuffer(rasterBufferObj *rb, int width, int height, int mode) { rb->type = MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixel_step = 4; rb->data.rgba.row_step = rb->data.rgba.pixel_step * width; rb->width = width; rb->height = height; int nBytes = rb->data.rgba.row_step * height; rb->data.rgba.pixels = (band_type*)msSmallCalloc(nBytes,sizeof(band_type)); rb->data.rgba.r = &(rb->data.rgba.pixels[band_order::R]); rb->data.rgba.g = &(rb->data.rgba.pixels[band_order::G]); rb->data.rgba.b = &(rb->data.rgba.pixels[band_order::B]); if(mode == MS_IMAGEMODE_RGBA) { rb->data.rgba.a = &(rb->data.rgba.pixels[band_order::A]); } return MS_SUCCESS; } int aggGetRasterBufferHandle(imageObj *img, rasterBufferObj * rb) { AGG2Renderer *r = AGG_RENDERER(img); rb->type =MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixels = r->buffer; rb->data.rgba.row_step = r->m_rendering_buffer.stride(); rb->data.rgba.pixel_step = 4; rb->width = r->m_rendering_buffer.width(); rb->height = r->m_rendering_buffer.height(); rb->data.rgba.r = &(r->buffer[band_order::R]); rb->data.rgba.g = &(r->buffer[band_order::G]); rb->data.rgba.b = &(r->buffer[band_order::B]); if(r->use_alpha) rb->data.rgba.a = &(r->buffer[band_order::A]); else rb->data.rgba.a = NULL; return MS_SUCCESS; } int aggGetRasterBufferCopy(imageObj *img, rasterBufferObj *rb) { AGG2Renderer *r = AGG_RENDERER(img); aggInitializeRasterBuffer(rb, img->width, img->height, MS_IMAGEMODE_RGBA); int nBytes = r->m_rendering_buffer.stride()*r->m_rendering_buffer.height(); memcpy(rb->data.rgba.pixels,r->buffer, nBytes); return MS_SUCCESS; } int agg2MergeRasterBuffer(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { assert(overlay->type == MS_BUFFER_BYTE_RGBA); rendering_buffer b(overlay->data.rgba.pixels, overlay->width, overlay->height, overlay->data.rgba.row_step); pixel_format pf(b); AGG2Renderer *r = AGG_RENDERER(dest); mapserver::rect_base src_rect(srcX,srcY,srcX+width,srcY+height); r->m_renderer_base.blend_from(pf,&src_rect, dstX-srcX, dstY-srcY, unsigned(opacity * 255)); return MS_SUCCESS; } /* image i/o */ imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorObj * bg) { imageObj *image = NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode != MS_IMAGEMODE_RGBA) { msSetError(MS_MISCERR, "AGG2 driver only supports RGB or RGBA pixel models.", "agg2CreateImage()"); return image; } image = (imageObj *) calloc(1, sizeof (imageObj)); MS_CHECK_ALLOC(image, sizeof (imageObj), NULL); AGG2Renderer *r = new AGG2Renderer(); r->buffer = (band_type*)malloc(width * height * 4 * sizeof(band_type)); if (r->buffer == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "agg2CreateImage()", __FILE__, __LINE__, (unsigned int)(width * height * 4 * sizeof(band_type))); free(image); return NULL; } r->m_rendering_buffer.attach(r->buffer, width, height, width * 4); r->m_pixel_format.attach(r->m_rendering_buffer); r->m_renderer_base.attach(r->m_pixel_format); r->m_renderer_scanline.attach(r->m_renderer_base); double gamma = atof(msGetOutputFormatOption( format, "GAMMA", "0.75" )); if(gamma > 0.0 && gamma < 1.0) { r->m_rasterizer_aa_gamma.gamma(mapserver::gamma_linear(0.0,gamma)); } if( bg && !format->transparent ) r->m_renderer_base.clear(aggColor(bg)); else r->m_renderer_base.clear(AGG_NO_COLOR); if (!bg || format->transparent || format->imagemode == MS_IMAGEMODE_RGBA ) { r->use_alpha = true; } else { r->use_alpha = false; } image->img.plugin = (void*) r; return image; } int agg2SaveImage(imageObj *img, mapObj* map, FILE *fp, outputFormatObj * format) { msSetError(MS_MISCERR, "AGG2 does not support direct image saving", "agg2SaveImage()"); return MS_FAILURE; } /*...*/ /* helper functions */ int agg2GetTruetypeTextBBox(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances,int bAdjustBaseline) { aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(renderer); if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE) return MS_FAILURE; int curfontidx = 0; int unicode, curGlyph = 1, numglyphs = 0; if (advances) { numglyphs = msGetNumGlyphs(string); } const mapserver::glyph_cache* glyph; string += msUTF8ToUniChar(string, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; im_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { rect->minx = glyph->bounds.x1; rect->maxx = glyph->bounds.x2; rect->miny = glyph->bounds.y1; rect->maxy = bAdjustBaseline?1:glyph->bounds.y2; } else return MS_FAILURE; if (advances) { *advances = (double*) malloc(numglyphs * sizeof (double)); MS_CHECK_ALLOC(*advances, numglyphs * sizeof (double), MS_FAILURE); (*advances)[0] = glyph->advance_x; } double fx = glyph->advance_x, fy = glyph->advance_y; while (*string) { if (advances) { if (*string == '\r' || *string == '\n') (*advances)[curGlyph++] = -fx; } if (*string == '\r') { fx = 0; string++; continue; } if (*string == '\n') { fx = 0; fy += ceil(size * AGG_LINESPACE); string++; continue; } string += msUTF8ToUniChar(string, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; im_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { rect->minx = MS_MIN(rect->minx, fx+glyph->bounds.x1); rect->miny = MS_MIN(rect->miny, fy+glyph->bounds.y1); rect->maxx = MS_MAX(rect->maxx, fx+glyph->bounds.x2); rect->maxy = MS_MAX(rect->maxy, fy+(bAdjustBaseline?1:glyph->bounds.y2)); fx += glyph->advance_x; fy += glyph->advance_y; if (advances) { (*advances)[curGlyph++] = glyph->advance_x; } } } return MS_SUCCESS; } int agg2StartNewLayer(imageObj *img, mapObj*map, layerObj *layer) { return MS_SUCCESS; } int agg2CloseNewLayer(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int agg2FreeImage(imageObj * image) { AGG2Renderer *r = AGG_RENDERER(image); free(r->buffer); delete r; image->img.plugin = NULL; return MS_SUCCESS; } int agg2FreeSymbol(symbolObj * symbol) { return MS_SUCCESS; } int agg2InitCache(void **vcache) { aggRendererCache *cache = new aggRendererCache(); *vcache = (void*)cache; return MS_SUCCESS; } int agg2Cleanup(void *vcache) { aggRendererCache *cache = (aggRendererCache*)vcache; delete cache; return MS_SUCCESS; } // ------------------------------------------------------------------------ // Function to create a custom hatch symbol based on an arbitrary angle. // ------------------------------------------------------------------------ static mapserver::path_storage createHatch(double ox, double oy, double rx, double ry, int sx, int sy, double angle, double step) { mapserver::path_storage path; //restrict the angle to [0 180[, i.e ]-pi/2,pi/2] in radians angle = fmod(angle, 360.0); if(angle < 0) angle += 360; if(angle >= 180) angle -= 180; //treat 2 easy cases which would cause divide by 0 in generic case if(angle==0) { double y0 = step-fmod(oy-ry,step); if((oy - ry) < 0) { y0 -= step; } for(double y=y0; y=0&&y<=sy) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } x=sx; y=(r-sx*ct)*invst;// test for intersection with right of image if(y>=0&&y<=sy) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } if(inter<2) { y=0; x=r*invct;// test for intersection with top of image if(x>=0&&x<=sx) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } } if(inter<2) { y=sy; x=(r-sy*st)*invct;// test for intersection with bottom of image if(x>=0&&x<=sx) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } } if(inter==2 && (pt[0]!=pt[2] || pt[1]!=pt[3])) { //the line intersects with two sides of the image, it should therefore be drawn if(angle<90) { path.move_to(pt[0],pt[1]); path.line_to(pt[2],pt[3]); } else { path.move_to(pt[0],sy-pt[1]); path.line_to(pt[2],sy-pt[3]); } } } return path; } template void renderPolygonHatches(imageObj *img,VertexSource &clipper, colorObj *color) { if(img->format->renderer == MS_RENDER_WITH_AGG) { AGG2Renderer *r = AGG_RENDERER(img); r->m_rasterizer_aa_gamma.reset(); r->m_rasterizer_aa_gamma.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa_gamma.add_path(clipper); r->m_renderer_scanline.color(aggColor(color)); mapserver::render_scanlines(r->m_rasterizer_aa_gamma, r->sl_poly, r->m_renderer_scanline); } else { shapeObj shape; msInitShape(&shape); int allocated = 20; lineObj line; shape.line = &line; shape.numlines = 1; shape.line[0].point = (pointObj*)msSmallCalloc(allocated,sizeof(pointObj)); shape.line[0].numpoints = 0; double x=0,y=0; unsigned int cmd; clipper.rewind(0); while((cmd = clipper.vertex(&x,&y)) != mapserver::path_cmd_stop) { switch(cmd) { case mapserver::path_cmd_line_to: if(shape.line[0].numpoints == allocated) { allocated *= 2; shape.line[0].point = (pointObj*)msSmallRealloc(shape.line[0].point, allocated*sizeof(pointObj)); } shape.line[0].point[shape.line[0].numpoints].x = x; shape.line[0].point[shape.line[0].numpoints].y = y; shape.line[0].numpoints++; break; case mapserver::path_cmd_move_to: shape.line[0].point[0].x = x; shape.line[0].point[0].y = y; shape.line[0].numpoints = 1; break; case mapserver::path_cmd_end_poly|mapserver::path_flags_close: if(shape.line[0].numpoints > 2) { MS_IMAGE_RENDERER(img)->renderPolygon(img,&shape,color); } break; default: assert(0); //WTF? } } free(shape.line[0].point); } } int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width, double *pattern, int patternlength, double angle, colorObj *color) { assert(MS_RENDERER_PLUGIN(img->format)); msComputeBounds(poly); /* amount we should expand the bounding box by */ double exp = width * 0.7072; /* width and height of the bounding box we will be creating the hatch in */ int pw=(int)(poly->bounds.maxx-poly->bounds.minx+exp*2)+1; int ph=(int)(poly->bounds.maxy-poly->bounds.miny+exp*2)+1; /* position of the top-left corner of the bounding box */ double ox = poly->bounds.minx - exp; double oy = poly->bounds.miny - exp; //create a rectangular hatch of size pw,ph starting at 0,0 //the created hatch is of the size of the shape's bounding box mapserver::path_storage hatch = createHatch(ox,oy, img->refpt.x,img->refpt.y,pw,ph,angle,spacing); if(hatch.total_vertices()<=0) return MS_SUCCESS; //translate the hatch so it overlaps the current shape hatch.transform(mapserver::trans_affine_translation(ox,oy)); polygon_adaptor polygons(poly); if(patternlength>1) { //dash the hatch and render it clipped by the shape mapserver::conv_dash dash(hatch); mapserver::conv_stroke > stroke(dash); for (int i=0; i > > clipper(polygons,stroke, mapserver::clipper_and); renderPolygonHatches(img,clipper,color); } else { //render the hatch clipped by the shape mapserver::conv_stroke stroke(hatch); stroke.width(width); stroke.line_cap(mapserver::butt_cap); mapserver::conv_clipper > clipper(polygons,stroke, mapserver::clipper_and); renderPolygonHatches(img,clipper,color); } //assert(prevCmd == mapserver::path_cmd_line_to); //delete lines; return MS_SUCCESS; } int msPopulateRendererVTableAGG(rendererVTableObj * renderer) { renderer->supports_transparent_layers = 0; renderer->supports_pixel_buffer = 1; renderer->use_imagecache = 0; renderer->supports_clipping = 0; renderer->supports_svg = 0; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; agg2InitCache(&(MS_RENDERER_CACHE(renderer))); renderer->cleanup = agg2Cleanup; renderer->renderLine = &agg2RenderLine; renderer->renderPolygon = &agg2RenderPolygon; renderer->renderPolygonTiled = &agg2RenderPolygonTiled; renderer->renderLineTiled = &agg2RenderLineTiled; renderer->renderGlyphs = &agg2RenderGlyphs; renderer->renderGlyphsLine = &agg2RenderGlyphsLine; renderer->renderBitmapGlyphs = &agg2RenderBitmapGlyphs; renderer->renderVectorSymbol = &agg2RenderVectorSymbol; renderer->renderPixmapSymbol = &agg2RenderPixmapSymbol; renderer->renderEllipseSymbol = &agg2RenderEllipseSymbol; renderer->renderTruetypeSymbol = &agg2RenderTruetypeSymbol; renderer->renderTile = &agg2RenderTile; renderer->getRasterBufferHandle = &aggGetRasterBufferHandle; renderer->getRasterBufferCopy = aggGetRasterBufferCopy; renderer->initializeRasterBuffer = aggInitializeRasterBuffer; renderer->mergeRasterBuffer = &agg2MergeRasterBuffer; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->createImage = &agg2CreateImage; renderer->saveImage = &agg2SaveImage; renderer->getTruetypeTextBBox = &agg2GetTruetypeTextBBox; renderer->startLayer = &agg2StartNewLayer; renderer->endLayer = &agg2CloseNewLayer; renderer->freeImage = &agg2FreeImage; renderer->freeSymbol = &agg2FreeSymbol; renderer->cleanup = agg2Cleanup; renderer->supports_bitmap_fonts = 1; for(int i=0; i<5; i++) { renderer->bitmapFontMetrics[i] = &(rasterfont_sizes[i]); } return MS_SUCCESS; } mapserver-6.4.1/mapio.c0000644002461700001440000010124212261257215014565 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementations for MapServer IO redirection capability. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * 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. ****************************************************************************/ #include #include "mapserver.h" #include "mapthread.h" #ifdef _WIN32 #include #include #endif #ifdef MOD_WMS_ENABLED # include "httpd.h" # include "apr_strings.h" #endif static int is_msIO_initialized = MS_FALSE; typedef struct msIOContextGroup_t { msIOContext stdin_context; msIOContext stdout_context; msIOContext stderr_context; int thread_id; struct msIOContextGroup_t *next; } msIOContextGroup; static msIOContextGroup default_contexts; static msIOContextGroup *io_context_list = NULL; static void msIO_Initialize( void ); #ifdef msIO_printf # undef msIO_printf # undef msIO_fprintf # undef msIO_fwrite # undef msIO_fread # undef msIO_vfprintf #endif /************************************************************************/ /* msIO_Cleanup() */ /************************************************************************/ void msIO_Cleanup() { if( is_msIO_initialized ) { is_msIO_initialized = MS_FALSE; while( io_context_list != NULL ) { msIOContextGroup *last = io_context_list; io_context_list = io_context_list->next; free( last ); } } } /************************************************************************/ /* msIO_GetContextGroup() */ /************************************************************************/ static msIOContextGroup *msIO_GetContextGroup() { int nThreadId = msGetThreadId(); msIOContextGroup *prev = NULL, *group = io_context_list; if( group != NULL && group->thread_id == nThreadId ) return group; /* -------------------------------------------------------------------- */ /* Search for group for this thread */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_IOCONTEXT ); msIO_Initialize(); group = io_context_list; while( group != NULL && group->thread_id != nThreadId ) { prev = group; group = group->next; } /* -------------------------------------------------------------------- */ /* If we found it, make sure it is pushed to the front of the */ /* link for faster finding next time, and return it. */ /* -------------------------------------------------------------------- */ if( group != NULL ) { if( prev != NULL ) { prev->next = group->next; group->next = io_context_list; io_context_list = group; } msReleaseLock( TLOCK_IOCONTEXT ); return group; } /* -------------------------------------------------------------------- */ /* Create a new context group for this thread. */ /* -------------------------------------------------------------------- */ group = (msIOContextGroup *) calloc(sizeof(msIOContextGroup),1); group->stdin_context = default_contexts.stdin_context; group->stdout_context = default_contexts.stdout_context; group->stderr_context = default_contexts.stderr_context; group->thread_id = nThreadId; group->next = io_context_list; io_context_list = group; msReleaseLock( TLOCK_IOCONTEXT ); return group; } /************************************************************************/ /* msIO_getHandler() */ /************************************************************************/ msIOContext *msIO_getHandler( FILE * fp ) { int nThreadId = msGetThreadId(); msIOContextGroup *group = io_context_list; msIO_Initialize(); if( group == NULL || group->thread_id != nThreadId ) { group = msIO_GetContextGroup(); if( group == NULL ) return NULL; } if( fp == stdin || fp == NULL || strcmp((const char *)fp,"stdin") == 0 ) return &(group->stdin_context); else if( fp == stdout || strcmp((const char *)fp,"stdout") == 0 ) return &(group->stdout_context); else if( fp == stderr || strcmp((const char *)fp,"stderr") == 0 ) return &(group->stderr_context); else return NULL; } void msIO_setHeader (const char *header, const char* value, ...) { va_list args; va_start( args, value ); #ifdef MOD_WMS_ENABLED msIOContext *ioctx = msIO_getHandler (stdout); if(ioctx && !strcmp(ioctx->label,"apache")) { request_rec *r = (request_rec*) (ioctx->cbData); char *fullvalue = apr_pvsprintf(r->pool, value,args); if (strcasecmp (header, "Content-Type") == 0) { r->content_type = fullvalue; } else if (strcasecmp (header, "Status") == 0) { r->status = atoi (fullvalue); } else { apr_table_setn (r->headers_out, apr_pstrdup (r->pool, header), fullvalue ); } } else { #endif // MOD_WMS_ENABLED msIO_fprintf(stdout,"%s: ",header); msIO_vfprintf(stdout,value,args); msIO_fprintf(stdout,"\r\n"); #ifdef MOD_WMS_ENABLED } #endif } void msIO_sendHeaders () { #ifdef MOD_WMS_ENABLED msIOContext *ioctx = msIO_getHandler (stdout); if(ioctx && !strcmp(ioctx->label,"apache")) return; #endif // !MOD_WMS_ENABLED msIO_printf ("\r\n"); fflush (stdout); } /************************************************************************/ /* msIO_installHandlers() */ /************************************************************************/ int msIO_installHandlers( msIOContext *stdin_context, msIOContext *stdout_context, msIOContext *stderr_context ) { msIOContextGroup *group; msIO_Initialize(); group = msIO_GetContextGroup(); if( stdin_context == NULL ) group->stdin_context = default_contexts.stdin_context; else if( stdin_context != &group->stdin_context ) group->stdin_context = *stdin_context; if( stdout_context == NULL ) group->stdout_context = default_contexts.stdout_context; else if( stdout_context != &group->stdout_context ) group->stdout_context = *stdout_context; if( stderr_context == NULL ) group->stderr_context = default_contexts.stderr_context; else if( stderr_context != &group->stderr_context ) group->stderr_context = *stderr_context; return MS_TRUE; } /************************************************************************/ /* msIO_contextRead() */ /************************************************************************/ int msIO_contextRead( msIOContext *context, void *data, int byteCount ) { if( context->write_channel == MS_TRUE ) return 0; else return context->readWriteFunc( context->cbData, data, byteCount ); } /************************************************************************/ /* msIO_contextWrite() */ /************************************************************************/ int msIO_contextWrite( msIOContext *context, const void *data, int byteCount ) { if( context->write_channel == MS_FALSE ) return 0; else return context->readWriteFunc( context->cbData, (void *) data, byteCount ); } /* ==================================================================== */ /* ==================================================================== */ /* Stdio-like cover functions. */ /* ==================================================================== */ /* ==================================================================== */ /************************************************************************/ /* _ms_vsprintf() */ /************************************************************************/ static int _ms_vsprintf(char **workBufPtr, const char *format, va_list ap ) { int ret_val; int workBufSize = 16000; *workBufPtr = (char*)malloc(workBufSize * sizeof(char)); if (*workBufPtr == NULL) { msSetError( MS_MEMERR, NULL, "_ms_vsprintf()"); return -1; } #if defined(HAVE_VSNPRINTF) /* This should grow a big enough buffer to hold any formatted result. */ { va_list wrk_args; #ifdef va_copy va_copy( wrk_args, ap ); #else wrk_args = ap; #endif while( (ret_val = vsnprintf( *workBufPtr, workBufSize, format, wrk_args)) >= workBufSize-1 || ret_val == -1 ) { workBufSize *= 4; *workBufPtr = (char *) realloc(*workBufPtr, workBufSize ); if (*workBufPtr == NULL) { msSetError( MS_MEMERR, NULL, "_ms_vsprintf()"); va_end( wrk_args ); return -1; } #ifdef va_copy va_end( wrk_args ); va_copy( wrk_args, ap ); #else wrk_args = ap; #endif } va_end( wrk_args ); } #else /* We do not have vsnprintf()... there is a risk of buffer overrun */ ret_val = vsprintf( *workBufPtr, format, ap ); if( ret_val < 0 || ret_val >= workBufSize ) { msSetError(MS_MISCERR, "Possible buffer overrun.", "_ms_vsprintf()"); msFree(*workBufPtr); *workBufPtr = NULL; return -1; } #endif return ret_val; } /************************************************************************/ /* msIO_printf() */ /************************************************************************/ int msIO_printf( const char *format, ... ) { va_list args; int ret; va_start( args, format ); ret = msIO_vfprintf(stdout,format,args); va_end(args); return ret; } /************************************************************************/ /* msIO_fprintf() */ /************************************************************************/ int msIO_fprintf( FILE *fp, const char *format, ... ) { va_list args; int ret; va_start( args, format ); ret = msIO_vfprintf(fp,format,args); va_end(args); return ret; } /************************************************************************/ /* msIO_vfprintf() */ /************************************************************************/ int msIO_vfprintf( FILE *fp, const char *format, va_list ap ) { va_list args_copy; int return_val; msIOContext *context; char workBuf[8000], *largerBuf = NULL; #if !defined(HAVE_VSNPRINTF) return_val = vsprintf( workBuf, format, ap); if( return_val < 0 || return_val >= sizeof(workBuf) ) { msSetError(MS_MISCERR, "Possible buffer overrun.", "msIO_vfprintf()"); return -1; } #else #ifdef va_copy va_copy( args_copy, ap ); #else args_copy = ap; #endif /* va_copy */ return_val = vsnprintf( workBuf, sizeof(workBuf), format, ap ); if (return_val == -1 || return_val >= sizeof(workBuf)-1) { return_val = _ms_vsprintf(&largerBuf, format, args_copy ); } va_end(args_copy); #endif /* HAVE_VSNPRINTF */ if (return_val < 0) return -1; context = msIO_getHandler( fp ); if( context == NULL ) return_val = fwrite( largerBuf?largerBuf:workBuf, 1, return_val, fp ); else return_val = msIO_contextWrite( context, largerBuf?largerBuf:workBuf, return_val ); msFree(largerBuf); return return_val; } /************************************************************************/ /* msIO_fwrite() */ /************************************************************************/ int msIO_fwrite( const void *data, size_t size, size_t nmemb, FILE *fp ) { msIOContext *context; if( size == 0 || nmemb == 0 ) return 0; context = msIO_getHandler( fp ); if( context == NULL ) return fwrite( data, size, nmemb, fp ); else return msIO_contextWrite( context, data, size * nmemb ) / size; } /************************************************************************/ /* msIO_fread() */ /************************************************************************/ int msIO_fread( void *data, size_t size, size_t nmemb, FILE *fp ) { msIOContext *context; if( size == 0 || nmemb == 0 ) return 0; context = msIO_getHandler( fp ); if( context == NULL ) return fread( data, size, nmemb, fp ); else return msIO_contextRead( context, data, size * nmemb ) / size; } /* ==================================================================== */ /* ==================================================================== */ /* Internal default callbacks implementing stdio reading and */ /* writing. */ /* ==================================================================== */ /* ==================================================================== */ /************************************************************************/ /* msIO_stdioRead() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_stdioRead( void *cbData, void *data, int byteCount ) { return fread( data, 1, byteCount, (FILE *) cbData ); } /************************************************************************/ /* msIO_stdioWrite() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_stdioWrite( void *cbData, void *data, int byteCount ) { return fwrite( data, 1, byteCount, (FILE *) cbData ); } /************************************************************************/ /* msIO_Initialize() */ /************************************************************************/ static void msIO_Initialize( void ) { if( is_msIO_initialized == MS_TRUE ) return; default_contexts.stdin_context.label = "stdio"; default_contexts.stdin_context.write_channel = MS_FALSE; default_contexts.stdin_context.readWriteFunc = msIO_stdioRead; default_contexts.stdin_context.cbData = (void *) stdin; default_contexts.stdout_context.label = "stdio"; default_contexts.stdout_context.write_channel = MS_TRUE; default_contexts.stdout_context.readWriteFunc = msIO_stdioWrite; default_contexts.stdout_context.cbData = (void *) stdout; default_contexts.stderr_context.label = "stdio"; default_contexts.stderr_context.write_channel = MS_TRUE; default_contexts.stderr_context.readWriteFunc = msIO_stdioWrite; default_contexts.stderr_context.cbData = (void *) stderr; default_contexts.next = NULL; default_contexts.thread_id = 0; is_msIO_initialized = MS_TRUE; } /* ==================================================================== */ /* ==================================================================== */ /* Stuff related to having a gdIOCtx operate through the msIO */ /* layer. */ /* ==================================================================== */ /* ==================================================================== */ typedef struct { #ifdef USE_GD gdIOCtx gd_io_ctx; #endif msIOContext *ms_io_ctx; } msIO_gdIOCtx; #ifdef USE_GD /************************************************************************/ /* msIO_gd_putC() */ /* */ /* A GD IO context callback to put a character, redirected */ /* through the msIO output context. */ /************************************************************************/ static void msIO_gd_putC( gdIOCtx *cbData, int out_char ) { msIO_gdIOCtx *merged_context = (msIO_gdIOCtx *) cbData; char out_char_as_char = (char) out_char; msIO_contextWrite( merged_context->ms_io_ctx, &out_char_as_char, 1 ); } /************************************************************************/ /* msIO_gd_putBuf() */ /* */ /* The GD IO context callback to put a buffer of data, */ /* redirected through the msIO output context. */ /************************************************************************/ static int msIO_gd_putBuf( gdIOCtx *cbData, const void *data, int byteCount ) { msIO_gdIOCtx *merged_context = (msIO_gdIOCtx *) cbData; return msIO_contextWrite( merged_context->ms_io_ctx, data, byteCount ); } #endif /************************************************************************/ /* msIO_getGDIOCtx() */ /* */ /* The returned context should be freed with free() when no */ /* longer needed. */ /************************************************************************/ #ifdef USE_GD gdIOCtx *msIO_getGDIOCtx( FILE *fp ) { msIO_gdIOCtx *merged_context; msIOContext *context = msIO_getHandler( fp ); if( context == NULL ) return NULL; merged_context = (msIO_gdIOCtx *) calloc(1,sizeof(msIO_gdIOCtx)); merged_context->gd_io_ctx.putC = msIO_gd_putC; merged_context->gd_io_ctx.putBuf = msIO_gd_putBuf; merged_context->ms_io_ctx = context; return (gdIOCtx *) merged_context; } #endif /* ==================================================================== */ /* ==================================================================== */ /* FastCGI output redirection functions. */ /* ==================================================================== */ /* ==================================================================== */ /************************************************************************/ /* msIO_needBinaryStdout() */ /* */ /* This function is intended to ensure that stdout is in binary */ /* mode. */ /* */ /* But don't do it we are using FastCGI. We will take care of */ /* doing it in the libfcgi library in that case for the normal */ /* cgi case, and for the fastcgi case the _setmode() call */ /* causes a crash. */ /************************************************************************/ int msIO_needBinaryStdout() { #if defined(_WIN32) && !defined(USE_FASTCGI) if(_setmode( _fileno(stdout), _O_BINARY) == -1) { msSetError(MS_IOERR, "Unable to change stdout to binary mode.", "msIO_needBinaryStdout()" ); return(MS_FAILURE); } #endif return MS_SUCCESS; } /************************************************************************/ /* msIO_needBinaryStdin() */ /* */ /* This function is intended to ensure that stdin is in binary */ /* mode. */ /* */ /* But don't do it we are using FastCGI. We will take care of */ /* doing it in the libfcgi library in that case for the normal */ /* cgi case, and for the fastcgi case the _setmode() call */ /* causes a crash. */ /************************************************************************/ int msIO_needBinaryStdin() { #if defined(_WIN32) && !defined(USE_FASTCGI) if(_setmode( _fileno(stdin), _O_BINARY) == -1) { msSetError(MS_IOERR, "Unable to change stdin to binary mode.", "msIO_needBinaryStdin()" ); return(MS_FAILURE); } #endif return MS_SUCCESS; } /* ==================================================================== */ /* memory buffer io handling functions. */ /* ==================================================================== */ /************************************************************************/ /* msIO_resetHandlers() */ /************************************************************************/ void msIO_resetHandlers() { msIOContextGroup *group = msIO_GetContextGroup(); if( group == NULL ) return; if( strcmp(group->stdin_context.label,"buffer") == 0 ) { msIOBuffer *buf = (msIOBuffer *) group->stdin_context.cbData; if( buf->data != NULL ) free( buf->data ); free( buf ); } if( strcmp(group->stdout_context.label,"buffer") == 0 ) { msIOBuffer *buf = (msIOBuffer *) group->stdout_context.cbData; if( buf->data != NULL ) free( buf->data ); free( buf ); } if( strcmp(group->stderr_context.label,"buffer") == 0 ) { msIOBuffer *buf = (msIOBuffer *) group->stderr_context.cbData; if( buf->data != NULL ) free( buf->data ); free( buf ); } msIO_installHandlers( NULL, NULL, NULL ); } /************************************************************************/ /* msIO_installStdoutToBuffer() */ /************************************************************************/ void msIO_installStdoutToBuffer() { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext context; context.label = "buffer"; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = calloc(sizeof(msIOBuffer),1); msIO_installHandlers( &group->stdin_context, &context, &group->stderr_context ); } /************************************************************************/ /* msIO_installStdinFromBuffer() */ /************************************************************************/ void msIO_installStdinFromBuffer() { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext context; context.label = "buffer"; context.write_channel = MS_FALSE; context.readWriteFunc = msIO_bufferRead; context.cbData = calloc(sizeof(msIOBuffer),1); msIO_installHandlers( &context, &group->stdout_context, &group->stderr_context ); } /************************************************************************/ /* msIO_stripStdoutBufferContentType() */ /* */ /* Strip off Content-Type header from buffer, and return to */ /* caller. Returned string is the callers responsibility to */ /* call msFree() on to deallocate. This function will return */ /* NULL if there is no Content-Type header. */ /************************************************************************/ char *msIO_stripStdoutBufferContentType() { /* -------------------------------------------------------------------- */ /* Find stdout buffer. */ /* -------------------------------------------------------------------- */ msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; char *content_type = NULL; int end_of_ct, start_of_data; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_stripStdoutBufferContentType" ); return NULL; } buf = (msIOBuffer *) ctx->cbData; /* -------------------------------------------------------------------- */ /* Return NULL if we don't have a Content-Type header. */ /* -------------------------------------------------------------------- */ if( buf->data_offset < 14 || strncasecmp((const char*) buf->data,"Content-Type: ",14) != 0 ) return NULL; /* -------------------------------------------------------------------- */ /* Find newline marker at end of content type argument. */ /* -------------------------------------------------------------------- */ end_of_ct = 13; while( end_of_ct+1 < buf->data_offset && buf->data[end_of_ct+1] != '\r' ) end_of_ct++; if( end_of_ct+1 == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-Type header.", "msIO_stripStdoutBufferContentType" ); return NULL; } /* -------------------------------------------------------------------- */ /* Continue on to the start of data ... */ /* Go to next line and skip if empty. */ /* -------------------------------------------------------------------- */ start_of_data = end_of_ct+3; if( start_of_data < buf->data_offset && buf->data[start_of_data] == '\r' ) start_of_data +=2; if( start_of_data == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-Type header.", "msIO_stripStdoutBufferContentType" ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy out content type. Note we go against the coding guidelines */ /* here and use strncpy() instead of strlcpy() as the source */ /* buffer may not be NULL terminated - strlcpy() requires NULL */ /* terminated sources (see issue #4672). */ /* -------------------------------------------------------------------- */ content_type = (char *) malloc(end_of_ct-14+2); strncpy( content_type, (const char *) buf->data + 14, end_of_ct - 14 + 2); content_type[end_of_ct-14+1] = '\0'; /* -------------------------------------------------------------------- */ /* Move data to front of buffer, and reset length. */ /* -------------------------------------------------------------------- */ memmove( buf->data, buf->data+start_of_data, buf->data_offset - start_of_data ); buf->data[buf->data_offset - start_of_data] = '\0'; buf->data_offset -= start_of_data; return content_type; } /************************************************************************/ /* msIO_stripStdoutBufferContentHeaders() */ /* */ /* Strip off Content-* headers from buffer. */ /************************************************************************/ void msIO_stripStdoutBufferContentHeaders() { /* -------------------------------------------------------------------- */ /* Find stdout buffer. */ /* -------------------------------------------------------------------- */ msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; int start_of_data; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_stripStdoutBufferContentHeaders" ); return; } buf = (msIOBuffer *) ctx->cbData; /* -------------------------------------------------------------------- */ /* Exit if we don't have any content-* header. */ /* -------------------------------------------------------------------- */ if( buf->data_offset < 8 || strncasecmp((const char*) buf->data,"Content-",8) != 0 ) return; /* -------------------------------------------------------------------- */ /* Loop over all content-* headers. */ /* -------------------------------------------------------------------- */ start_of_data = 0; while( buf->data_offset > start_of_data && strncasecmp((const char*) buf->data+start_of_data,"Content-",8) == 0 ) { /* -------------------------------------------------------------------- */ /* Find newline marker at end of content-* header argument. */ /* -------------------------------------------------------------------- */ start_of_data +=7; while( start_of_data+1 < buf->data_offset && buf->data[start_of_data+1] != '\r' ) start_of_data++; if( start_of_data+1 == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-* header.", "msIO_stripStdoutBufferContentHeaders" ); return; } /* -------------------------------------------------------------------- */ /* Go to next line. */ /* -------------------------------------------------------------------- */ start_of_data +=3; } /* -------------------------------------------------------------------- */ /* Continue on to the start of data ... */ /* Skip next line if empty. */ /* -------------------------------------------------------------------- */ if( start_of_data < buf->data_offset && buf->data[start_of_data] == '\r' ) start_of_data +=2; if( start_of_data == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-* header.", "msIO_stripStdoutBufferContentHeaders" ); return; } /* -------------------------------------------------------------------- */ /* Move data to front of buffer, and reset length. */ /* -------------------------------------------------------------------- */ memmove( buf->data, buf->data+start_of_data, buf->data_offset - start_of_data ); buf->data[buf->data_offset - start_of_data] = '\0'; buf->data_offset -= start_of_data; return; } /************************************************************************/ /* msIO_bufferWrite() */ /************************************************************************/ int msIO_bufferWrite( void *cbData, void *data, int byteCount ) { msIOBuffer *buf = (msIOBuffer *) cbData; /* ** Grow buffer if needed. */ if( buf->data_offset + byteCount > buf->data_len ) { buf->data_len = buf->data_len * 2 + byteCount + 100; if( buf->data == NULL ) buf->data = (unsigned char *) malloc(buf->data_len); else buf->data = (unsigned char *) realloc(buf->data, buf->data_len); if( buf->data == NULL ) { msSetError( MS_MEMERR, "Failed to allocate %d bytes for capture buffer.", "msIO_bufferWrite()", buf->data_len ); buf->data_len = 0; return 0; } } /* ** Copy result into buffer. */ memcpy( buf->data + buf->data_offset, data, byteCount ); buf->data_offset += byteCount; return byteCount; } /************************************************************************/ /* msIO_bufferRead() */ /************************************************************************/ int msIO_bufferRead( void *cbData, void *data, int byteCount ) { /* msIOBuffer *buf = (msIOBuffer *) cbData; */ /* not implemented yet. */ return 0; } mapserver-6.4.1/apache/0000755002461700001440000000000012261257215014535 5ustar tbonfortusersmapserver-6.4.1/apache/mod_mapserver.c0000644002461700001440000003354112261257215017552 0ustar tbonfortusers/* * mod_mapserver.c -- Apache sample wms module */ #include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "http_log.h" #include "ap_config.h" #include "apr.h" #include "apr_strings.h" #include "apr_tables.h" #include "apr_file_info.h" #include "../mapserver.h" /* for mapObj */ #include "../cgiutil.h" #include "../mapserv.h" module AP_MODULE_DECLARE_DATA mapserver_module; typedef struct { apr_pool_t *config_pool; apr_time_t mtime; char *mapfile_name; char *uri; mapObj *map; } mapserver_dir_config; /* These are the IO redirection hooks. They are mostly copied over from * mapio.c. Note that cbData contains Apache's request_rec! */ static int msIO_apacheWrite (void *cbData, void *data, int byteCount) { /* simply use the block writing function which is very similiar to fwrite */ return ap_rwrite (data, byteCount, (request_rec*) cbData); } static int msIO_apacheError (void *cbData, void *data, int byteCount) { /* error reporting is done through the log file... */ ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, (char*) data); return strlen ((char*) data); } int msIO_installApacheRedirect (request_rec *r) { msIOContext stdout_ctx, stderr_ctx; stdout_ctx.label = "apache"; stdout_ctx.write_channel = MS_TRUE; stdout_ctx.readWriteFunc = msIO_apacheWrite; stdout_ctx.cbData = (void*) r; stderr_ctx.label = "apache"; stderr_ctx.write_channel = MS_TRUE; stderr_ctx.readWriteFunc = msIO_apacheError; stderr_ctx.cbData = (void*) r; msIO_installHandlers (NULL, &stdout_ctx, &stderr_ctx); return MS_TRUE; } /* The maximum number of arguments we support. The number is taken from * cgiutil.h I think. It is only used for easier param decoding. */ #define WMS_MAX_ARGS 100 /* This is our simple query decoding function. Should be improved but for now * it works... */ static int mapserver_decode_args (apr_pool_t *p, char *args, char ***ParamNames, char ***ParamValues) { char **argv = NULL; int i; int n; int argc = 0; char *sep; /* alloc the name/value pointer list */ argv = (char**) apr_pcalloc (p, (WMS_MAX_ARGS + 1) * 2 * sizeof (char*)); *ParamNames = argv; *ParamValues = argv + WMS_MAX_ARGS + 1; /* No arguments? Then we're done */ if (!args) return 0; argv [0] = args; /* separate the arguments */ for (i = 1, n = 0; args [n] && (i < WMS_MAX_ARGS); n++) if (args [n] == '&') { argv [i++] = args + n + 1; args [n ] = '\0'; } /* eleminate empty args */ for (n = 0, i = 0; argv [i]; i++) if (*(argv [i]) != '\0') argv [n++] = argv [i]; else argv [i ] = NULL; /* argument count is the number of non-zero arguments! */ argc = n; /* split the name/value pairs */ for (i = 0; argv [i]; i++) { sep = strchr (argv [i], '='); if (!sep) continue; *sep = '\0'; argv [i + WMS_MAX_ARGS + 1] = (char*) apr_pstrdup (p, sep + 1); if (ap_unescape_url (argv [i + WMS_MAX_ARGS + 1]) == HTTP_BAD_REQUEST) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s: malformed URI, couldn't unescape parm %s", __func__, argv [i]); argv [i + WMS_MAX_ARGS + 1] = NULL; } else { plustospace (argv [i + WMS_MAX_ARGS + 1]); } } return argc; } static char* mapserver_read_post_data (request_rec *r) { int status; int size; long blen, rsize, rpos = 0; char *buffer = NULL; char buf [512]; if ((status = ap_setup_client_block (r, REQUEST_CHUNKED_ERROR)) != OK) return NULL; if (!ap_should_client_block (r)) return NULL; buffer = (char*) apr_palloc (r->pool, r->remaining + 1); size = r->remaining; buffer [size] = '\0'; if (!buffer) return NULL; while ((blen = ap_get_client_block (r, buf, sizeof (buf))) > 0) { if (rpos + blen > size) { rsize = blen - rpos; } else { rsize = blen; } memcpy ((char*) buffer + rpos, buf, rsize); rpos += rsize; } return buffer; } /* ** Extract Map File name from params and load it. ** Returns map object or NULL on error. */ static mapObj* msModuleLoadMap(mapservObj *mapserv, mapserver_dir_config *conf) { int i; /* OK, here's the magic: we take the mapObj from our stored config. * We will use a copy of it created by msCopyMap since MapServer * modifies the object at several places during request processing */ mapObj *map = msNewMapObj (); if(!map) return NULL; msCopyMap (map, conf->map); /* check for any %variable% substitutions here, also do any map_ changes, we do this here so WMS/WFS */ /* services can take advantage of these "vendor specific" extensions */ for(i=0; irequest->NumParams; i++) { /* ** a few CGI variables should be skipped altogether ** ** qstring: there is separate per layer validation for attribute queries and the substitution checks ** below conflict with that so we avoid it here */ if(strncasecmp(mapserv->request->ParamNames[i],"qstring",7) == 0) continue; if(strncasecmp(mapserv->request->ParamNames[i],"map_",4) == 0 || strncasecmp(mapserv->request->ParamNames[i],"map.",4) == 0) { /* check to see if there are any additions to the mapfile */ if(msUpdateMapFromURL(map, mapserv->request->ParamNames[i], mapserv->request->ParamValues[i]) != MS_SUCCESS) { msFreeMap(map); return NULL; } continue; } } msApplySubstitutions(map, mapserv->request->ParamNames, mapserv->request->ParamValues, mapserv->request->NumParams); msApplyDefaultSubstitutions(map); /* check to see if a ogc map context is passed as argument. if there */ /* is one load it */ for(i=0; irequest->NumParams; i++) { if(strcasecmp(mapserv->request->ParamNames[i],"context") == 0) { if(mapserv->request->ParamValues[i] && strlen(mapserv->request->ParamValues[i]) > 0) { if(strncasecmp(mapserv->request->ParamValues[i],"http",4) == 0) { if(msGetConfigOption(map, "CGI_CONTEXT_URL")) msLoadMapContextURL(map, mapserv->request->ParamValues[i], MS_FALSE); } else msLoadMapContext(map, mapserv->request->ParamValues[i], MS_FALSE); } } } /* * RFC-42 HTTP Cookie Forwarding * Here we set the http_cookie_data metadata to handle the * HTTP Cookie Forwarding. The content of this metadata is the cookie * content. In the future, this metadata will probably be replaced * by an object that is part of the mapObject that would contain * information on the application status (such as cookie). */ if( mapserv->request->httpcookiedata != NULL ) { msInsertHashTable( &(map->web.metadata), "http_cookie_data", mapserv->request->httpcookiedata ); } return map; } /*** * The main request handler. **/ static int mapserver_handler (request_rec *r) { /* aquire the apropriate configuration for this directory */ mapserver_dir_config *conf; conf = (mapserver_dir_config*) ap_get_module_config (r->per_dir_config, &mapserver_module); /* decline the request if there's no map configured */ if (!conf || !conf->map) return DECLINED; apr_finfo_t mapstat; if (apr_stat (&mapstat, conf->mapfile_name, APR_FINFO_MTIME, r->pool) == APR_SUCCESS) { if (apr_time_sec (mapstat.mtime) > apr_time_sec (conf->mtime)) { mapObj *newmap = msLoadMap (conf->mapfile_name, NULL); if (newmap) { msFreeMap (conf->map); conf->map = newmap; conf->mtime = mapstat.mtime; } else { ap_log_error (APLOG_MARK, APLOG_WARNING, 0, NULL, "unable to reload map file %s", conf->mapfile_name); } } } else { ap_log_error (APLOG_MARK, APLOG_WARNING, 0, NULL, "%s: unable to stat file %s", __func__, conf->mapfile_name); } /* make a copy of the URI so we can modify it safely */ char *uri = apr_pstrdup (r->pool, r->uri); int len = strlen (uri); int conf_uri_len = strlen (conf->uri); /* If the URI points to a subdirectory we want to decline. */ if (len > conf_uri_len) return DECLINED; int argc = 0; char **ParamNames = NULL; char **ParamValues = NULL; char *post_data = NULL; int szMethod = -1; char *szContentType = NULL; mapservObj *mapserv = NULL; /* Try decoding the query string */ if (r->method_number == M_GET) { argc = mapserver_decode_args (r->pool, (char*) apr_pstrdup (r->pool, r->args), &ParamNames, &ParamValues); szMethod = MS_GET_REQUEST; } else if (r->method_number == M_POST) { szContentType = (char*) apr_table_get (r->headers_in, "Content-Type"); post_data = mapserver_read_post_data (r); szMethod = MS_POST_REQUEST; if (strcmp (szContentType, "application/x-www-form-urlencoded") == 0) { argc = mapserver_decode_args (r->pool, (char*) apr_pstrdup (r->pool, r->args), &ParamNames, &ParamValues); } } else return HTTP_METHOD_NOT_ALLOWED; if (!argc && !post_data) return HTTP_BAD_REQUEST; /* Now we install the IO redirection. */ if (msIO_installApacheRedirect (r) != MS_TRUE) ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s: could not install apache redirect", __func__); mapserv = msAllocMapServObj(); mapserv->request->NumParams = argc; mapserv->request->ParamNames = ParamNames; mapserv->request->ParamValues = ParamValues; mapserv->request->type = (enum MS_REQUEST_TYPE) szMethod; mapserv->request->postrequest = post_data; mapserv->request->contenttype = szContentType; //mapserv->map = msModuleLoadMap(mapserv,conf); mapserv->map = conf->map; if(!mapserv->map) { msCGIWriteError(mapserv); goto end_request; } if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { msCGIWriteError(mapserv); goto end_request; } end_request: if(mapserv) { msCGIWriteLog(mapserv,MS_FALSE); mapserv->request->ParamNames = NULL; mapserv->request->ParamValues = NULL; mapserv->request->postrequest = NULL; mapserv->request->contenttype = NULL; mapserv->map = NULL; msFreeMapServObj(mapserv); } msResetErrorList(); /* Check if status was set inside MapServer functions. If it was, we * return it's value instead of simply OK. This is to support redirects * from maptemplate.c */ if (r->status == HTTP_MOVED_TEMPORARILY) return r->status; return OK; } /* This function will be called on startup to allow us to register our * handler. We don't do anything else yet... */ static void mapserver_register_hooks (apr_pool_t *p) { ap_hook_handler (mapserver_handler, NULL, NULL, APR_HOOK_MIDDLE); } /* That's the second part of the overall magic. This function will be called * when the configuration reaches the "WMS_Map" parameter. It will be passed * in as argument and should contain the full path and name of the map file. * We try to load it and store the resulting mapObj in the config of the * current directory. If we fail we throw a message... */ static const char* mapserver_set_map (cmd_parms *cmd, void *config, const char *arg) { mapserver_dir_config *conf = (mapserver_dir_config*) config; /* if the mapObj already exists the WMS_Map was given more than once - * may be the user forgot to comment something out... */ if (conf->map) { msWriteError (stderr); return (char*) apr_psprintf (cmd->temp_pool, "An MAP-file has already been registered for " "this URI - not accepting '%s'.", arg ); } /* Simply try loading the argument as map file. */ conf->mapfile_name = apr_pstrdup(cmd->pool, arg); conf->map = msLoadMap ((char*) arg, NULL); /* Ooops - we failed. We report it and fail. So beware: Always do a * configcheck before really restarting your web server! */ if (!conf->map) { msWriteError (stderr); return (char*) apr_psprintf (cmd->temp_pool, "The given MAP-file '%s' could not be loaded", arg); } apr_finfo_t status; if (apr_stat (&status, conf->mapfile_name, APR_FINFO_MTIME, cmd->pool) != APR_SUCCESS) { ap_log_error (APLOG_MARK, APLOG_WARNING, 0, NULL, "%s: unable to stat file %s", __func__, conf->mapfile_name); } conf->mtime = status.mtime; return NULL; } /* This function creates the (default) directory configuration. Well, we have * no defaults to set so we simply alloc the memory... */ static void* mapserver_create_dir_config (apr_pool_t *p, char *dir) { mapserver_dir_config *newconf; newconf = (mapserver_dir_config*) apr_pcalloc (p, sizeof (mapserver_dir_config)); newconf->config_pool = p; newconf->uri = apr_pstrdup (p, dir); newconf->map = NULL; newconf->mapfile_name = NULL; newconf->mtime = apr_time_from_sec (0); if (dir) { int len = strlen (dir); if (len > 1 && dir [len - 1] == '/' ) newconf->uri [len - 1] = '\0'; } return newconf; } /* This structure defines our single config option which takes exactly one * argument. */ static const command_rec mapserver_options[] = { AP_INIT_TAKE1( "Mapfile", mapserver_set_map, NULL, ACCESS_CONF, "WMS_Map " ), {NULL} }; /* The following structure declares everything Apache needs to treat us as * a module. Merging would mean inheriting from the parent directory but that * doesn't make much sense here since we would only inherit the map file... */ /* Dispatch list for API hooks */ module AP_MODULE_DECLARE_DATA mapserver_module = { STANDARD20_MODULE_STUFF, mapserver_create_dir_config, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ mapserver_options, /* table of config file commands */ mapserver_register_hooks /* register hooks */ }; mapserver-6.4.1/apache/CMakeLists.txt0000644002461700001440000000255712261257215017306 0ustar tbonfortusersadd_library(mod_mapserver MODULE mod_mapserver.c) target_link_libraries(mod_mapserver ${MAPSERVER_LIBMAPSERVER}) set_target_properties(mod_mapserver PROPERTIES PREFIX "") IF(APPLE) if(HTTPD_EXECUTABLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -bundle_loader ${HTTPD_EXECUTABLE}") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -bundle_loader ${HTTPD_EXECUTABLE}") endif(XCODE) else(HTTPD_EXECUTABLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -undefined dynamic_lookup") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -Wl,-undefined,dynamic_lookup") endif(XCODE) endif(HTTPD_EXECUTABLE) ENDIF(APPLE) find_package(APACHE) if(APACHE_FOUND) include_directories(${APACHE_INCLUDE_DIR}) else(APACHE_FOUND) report_mandatory_not_found(APACHE) endif(APACHE_FOUND) find_package(APR) if(APR_FOUND) include_directories(${APR_INCLUDE_DIR}) target_link_libraries(mod_mapserver ${APR_LIBRARY}) if(DEFINED APR_CPPFLAGS) add_definitions("${APR_CPPFLAGS}") endif(DEFINED APR_CPPFLAGS) else(APR_FOUND) report_mandatory_not_found(APR) endif(APR_FOUND) if(APACHE_MODULE_DIR) INSTALL(TARGETS mod_mapserver DESTINATION ${APACHE_MODULE_DIR}) endif(APACHE_MODULE_DIR) mapserver-6.4.1/mapchart.c0000644002461700001440000005367712261257215015301 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of dynamic charting (MS-RFC-29) * Author: Thomas Bonfort ( thomas.bonfort[at]gmail.com ) * ****************************************************************************** * 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. ****************************************************************************/ #include "mapserver.h" #define MS_CHART_TYPE_PIE 1 #define MS_CHART_TYPE_BAR 2 #define MS_CHART_TYPE_VBAR 3 /* ** check if an object of width w and height h placed at point x,y can fit in an image of width mw and height mh */ #define MS_CHART_FITS(x,y,w,h,mw,mh) (((x)-(w)/2.>0.)&&((x)+(w)/2.<(mw))&&((y)-(h)/2.>0.)&&((y)+(h)/2.)<(mh)) /* ** find a point on a shape. check if it fits in image ** returns ** MS_SUCCESS and point coordinates in 'p' if chart fits in image ** MS_FAILURE if no point could be found */ int findChartPoint(mapObj *map, shapeObj *shape, int width, int height, pointObj *center) { int middle,numpoints,idx,offset; double invcellsize = 1.0/map->cellsize; /*speed up MAP2IMAGE_X/Y_IC_DBL*/ switch(shape->type) { case MS_SHAPE_POINT: center->x=MS_MAP2IMAGE_X_IC_DBL(shape->line[0].point[0].x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(shape->line[0].point[0].y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; else return MS_FAILURE; break; case MS_SHAPE_LINE: /*loop through line segments starting from middle (alternate between before and after middle point) **first segment that fits is chosen */ middle=shape->line[0].numpoints/2; /*start with middle segment of line*/ numpoints=shape->line[0].numpoints; for(offset=1; offset<=middle; offset++) { idx=middle+offset; if(idxx=(shape->line[0].point[idx-1].x+shape->line[0].point[idx].x)/2.; center->y=(shape->line[0].point[idx-1].y+shape->line[0].point[idx].y)/2.; center->x=MS_MAP2IMAGE_X_IC_DBL(center->x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(center->y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; break; } idx=middle-offset; if(idx>=0) { center->x=(shape->line[0].point[idx].x+shape->line[0].point[idx+1].x)/2; center->y=(shape->line[0].point[idx].y+shape->line[0].point[idx+1].y)/2; center->x=MS_MAP2IMAGE_X_IC_DBL(center->x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(center->y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; break; } } return MS_FAILURE; break; case MS_SHAPE_POLYGON: msPolygonLabelPoint(shape, center, -1); center->x=MS_MAP2IMAGE_X_IC_DBL(center->x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(center->y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; else return MS_FAILURE; break; default: return MS_FAILURE; } } void drawRectangle(mapObj *map, imageObj *image, double mx, double my, double Mx, double My, styleObj *style) { shapeObj shape; lineObj line; pointObj point[5]; line.point = point; line.numpoints = 5; shape.line = &line; shape.numlines = 1; point[0].x = point[4].x = point[3].x = mx; point[0].y = point[4].y = point[1].y = my; point[1].x = point[2].x = Mx; point[2].y = point[3].y = My; msDrawShadeSymbol(&map->symbolset,image,&shape,style,1.0); } int msDrawVBarChart(mapObj *map, imageObj *image, pointObj *center, double *values, styleObj **styles, int numvalues, double barWidth) { int c; double left,bottom,cur; /*shortcut to pixel boundaries of the chart*/ double height = 0; for(c=0; cy+height/2.; left = center->x-barWidth/2.; for(c=0; cy-height/2.; bottom=center->y+height/2.; left=center->x-width/2.; shapeMaxVal=shapeMinVal=values[0]; for(c=1; cshapeMaxVal) shapeMaxVal=values[c]; if(values[c]bottom) ? bottom : vertOrigin; horizStart=left; /* color = gdImageColorAllocate(image->img.gd, 0,0,0); gdImageRectangle(image->img.gd, left-1,top-1, center.x+width/2.+1,bottom+1,color); */ for(c=0; cbottom) ? bottom : vertOrigin-barHeight; if(y!=vertOriginClipped) { /*don't draw bars of height == 0 (i.e. either values==0, or clipped)*/ if(values[c]>0) drawRectangle(map, image, horizStart, y, horizStart+barWidth-1, vertOriginClipped, styles[c]); else drawRectangle(map,image, horizStart, vertOriginClipped, horizStart+barWidth-1 , y, styles[c]); } horizStart+=barWidth; } return MS_SUCCESS; } int msDrawPieChart(mapObj *map, imageObj *image, pointObj *center, double diameter, double *values, styleObj **styles, int numvalues) { int i; double dTotal=0.,start=0; for(i=0; isymbolset,image, center, styles[i], diameter/2., start, start+angle); start+=angle; } return MS_SUCCESS; } int getNextShape(mapObj *map, layerObj *layer, double *values, int *nvalues, styleObj **styles, shapeObj *shape) { int status; int c; status = msLayerNextShape(layer, shape); if(status == MS_SUCCESS) { #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection))) msProjectShape(&layer->projection, &map->projection, shape); else layer->project = MS_FALSE; #endif if(msBindLayerToShape(layer, shape, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS) != MS_SUCCESS) return MS_FAILURE; /* error message is set in msBindLayerToShape() */ *nvalues = 0; for(c=0; cnumclasses; c++) { if(msEvalExpression(layer, shape, &(layer->class[c]->expression), layer->classitemindex) == MS_TRUE) { values[*nvalues]=(layer->class[c]->styles[0]->size); styles[*nvalues]=layer->class[c]->styles[0]; (*nvalues)++; } } } return status; } /* eventually add a class to the layer to get the diameter from an attribute */ int pieLayerProcessDynamicDiameter(layerObj *layer) { const char *chartRangeProcessingKey=NULL; char *attrib; double mindiameter=-1, maxdiameter, minvalue, maxvalue; classObj *newclass; styleObj *newstyle; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); if(chartSizeProcessingKey != NULL) return MS_FALSE; chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" ); if(chartRangeProcessingKey==NULL) return MS_FALSE; attrib = msSmallMalloc(strlen(chartRangeProcessingKey)+1); switch(sscanf(chartRangeProcessingKey,"%s %lf %lf %lf %lf",attrib, &mindiameter,&maxdiameter,&minvalue,&maxvalue)) { case 1: /*we only have the attribute*/ case 5: /*we have the attribute and the four range values*/ break; default: free(attrib); msSetError(MS_MISCERR, "Chart Layer format error for processing key \"CHART_RANGE\"", "msDrawChartLayer()"); return MS_FAILURE; } /*create a new class in the layer containing the wanted attribute * as the SIZE of its first STYLE*/ newclass=msGrowLayerClasses(layer); if(newclass==NULL) { free(attrib); return MS_FAILURE; } initClass(newclass); layer->numclasses++; /*create and attach a new styleObj to our temp class * and bind the wanted attribute to its SIZE */ newstyle=msGrowClassStyles(newclass); if(newstyle==NULL) { free(attrib); return MS_FAILURE; } initStyle(newstyle); newclass->numstyles++; newclass->name=(char*)msStrdup("__MS_SIZE_ATTRIBUTE_"); newstyle->bindings[MS_STYLE_BINDING_SIZE].item=msStrdup(attrib); newstyle->numbindings++; free(attrib); return MS_TRUE; } /* clean up the class added temporarily */ static void pieLayerCleanupDynamicDiameter(layerObj *layer) { if( layer->numclasses > 0 && EQUALN(layer->class[layer->numclasses - 1]->name, "__MS_SIZE_ATTRIBUTE_", 20) ) { classObj *c=msRemoveClass(layer, layer->numclasses - 1); freeClass(c); msFree(c); } } int msDrawPieChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartRangeProcessingKey=NULL; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); double diameter, mindiameter=-1, maxdiameter, minvalue, maxvalue, exponent=0; double *values; styleObj **styles; pointObj center; int numvalues = layer->numclasses; /* the number of classes to represent in the graph */ int numvalues_for_shape = 0; if(chartSizeProcessingKey==NULL) { chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" ); if(chartRangeProcessingKey==NULL) diameter=20; else { sscanf(chartRangeProcessingKey,"%*s %lf %lf %lf %lf %lf", &mindiameter,&maxdiameter,&minvalue,&maxvalue,&exponent); } } else { if(sscanf(chartSizeProcessingKey ,"%lf",&diameter)!=1) { msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawPieChartLayer()"); return MS_FAILURE; } } /* step through the target shapes */ msInitShape(&shape); values=(double*)calloc(numvalues,sizeof(double)); MS_CHECK_ALLOC(values, numvalues*sizeof(double), MS_FAILURE); styles = (styleObj**)malloc((numvalues)*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawPieChartLayer()", __FILE__, __LINE__, (unsigned int)(numvalues*sizeof(styleObj*))); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,&numvalues_for_shape,styles,&shape)) { if(chartRangeProcessingKey!=NULL) numvalues_for_shape--; if(numvalues_for_shape == 0) { msFreeShape(&shape); continue; } msDrawStartShape(map, layer, image, &shape); if(chartRangeProcessingKey!=NULL) { diameter = values[numvalues_for_shape]; if(mindiameter>=0) { if(diameter<=minvalue) diameter=mindiameter; else if(diameter>=maxvalue) diameter=maxdiameter; else { if (exponent <= 0) diameter=MS_NINT( mindiameter+ ((diameter-minvalue)/(maxvalue-minvalue))* (maxdiameter-mindiameter) ); else diameter=MS_NINT( mindiameter+ pow((diameter-minvalue)/(maxvalue-minvalue),1.0/exponent)* (maxdiameter-mindiameter) ); } } } if(findChartPoint(map, &shape, diameter, diameter, ¢er) == MS_SUCCESS) { status = msDrawPieChart(map,image, ¢er, diameter, values,styles,numvalues_for_shape); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; } int msDrawVBarChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); const char *chartScaleProcessingKey=msLayerGetProcessingKey( layer,"CHART_SCALE" ); double barWidth,scale=1.0; double *values; styleObj **styles; pointObj center; int numvalues = layer->numclasses; int numvalues_for_shape; if(chartSizeProcessingKey==NULL) { barWidth=20; } else { if(sscanf(chartSizeProcessingKey ,"%lf",&barWidth) != 1) { msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawVBarChartLayer()"); return MS_FAILURE; } } if(chartScaleProcessingKey) { if(sscanf(chartScaleProcessingKey,"%lf",&scale)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_SCALE\"", "msDrawVBarChartLayer()"); return MS_FAILURE; } } msInitShape(&shape); values=(double*)calloc(numvalues,sizeof(double)); MS_CHECK_ALLOC(values, numvalues*sizeof(double), MS_FAILURE); styles = (styleObj**)malloc(numvalues*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawVBarChartLayer()", __FILE__, __LINE__, (unsigned int)(numvalues*sizeof(styleObj*))); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,&numvalues_for_shape,styles,&shape)) { int i; double h=0; if(numvalues_for_shape == 0) { continue; } for(i=0; inumclasses; int numvalues_for_shape; if(chartSizeProcessingKey==NULL) { width=height=20; } else { switch(sscanf(chartSizeProcessingKey ,"%lf %lf",&width,&height)) { case 2: break; case 1: height = width; break; default: msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMax) { if(sscanf(barMax,"%lf",&barMaxVal)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_BAR_MAXVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMin) { if(sscanf(barMin,"%lf",&barMinVal)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_BAR_MINVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMin && barMax && barMinVal>=barMaxVal) { msSetError(MS_MISCERR, "\"CHART_BAR_MINVAL\" must be less than \"CHART_BAR_MAXVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } barWidth=(double)width/(double)layer->numclasses; if(!barWidth) { msSetError(MS_MISCERR, "Specified width of chart too small to fit given number of classes", "msDrawBarChartLayer()"); return MS_FAILURE; } msInitShape(&shape); values=(double*)calloc(numvalues,sizeof(double)); MS_CHECK_ALLOC(values, numvalues*sizeof(double), MS_FAILURE); styles = (styleObj**)malloc(numvalues*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawBarChartLayer()", __FILE__, __LINE__, (unsigned int)(numvalues*sizeof(styleObj*))); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,&numvalues_for_shape,styles,&shape)) { if(numvalues_for_shape == 0 ) continue; msDrawStartShape(map, layer, image, &shape); if(findChartPoint(map, &shape, width,height, ¢er)==MS_SUCCESS) { status = msDrawBarChart(map,image, ¢er, values, styles, numvalues_for_shape, width,height, (barMax!=NULL)?&barMaxVal:NULL, (barMin!=NULL)?&barMinVal:NULL, barWidth); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; } /** * Generic function to render chart layers. */ int msDrawChartLayer(mapObj *map, layerObj *layer, imageObj *image) { rectObj searchrect; const char *chartTypeProcessingKey=msLayerGetProcessingKey( layer,"CHART_TYPE" ); int chartType=MS_CHART_TYPE_PIE; int status = MS_FAILURE; if (image && map && layer) { if( !(MS_RENDERER_PLUGIN(image->format) )) { msSetError(MS_MISCERR, "chart drawing currently only supports GD and AGG renderers", "msDrawChartLayer()"); return MS_FAILURE; } if(chartTypeProcessingKey!=NULL) { if( strcasecmp(chartTypeProcessingKey,"PIE") == 0 ) { chartType=MS_CHART_TYPE_PIE; } else if( strcasecmp(chartTypeProcessingKey,"BAR") == 0 ) { chartType=MS_CHART_TYPE_BAR; } else if( strcasecmp(chartTypeProcessingKey,"VBAR") == 0 ) { chartType=MS_CHART_TYPE_VBAR; } else { msSetError(MS_MISCERR,"unknown chart type for processing key \"CHART_TYPE\", must be one of \"PIE\" or \"BAR\"", "msDrawChartLayer()"); return MS_FAILURE; } } if(chartType == MS_CHART_TYPE_PIE) { pieLayerProcessDynamicDiameter(layer); } /* open this layer */ status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; status = msLayerWhichItems(layer, MS_FALSE, NULL); if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); if(chartType == MS_CHART_TYPE_PIE) pieLayerCleanupDynamicDiameter(layer); return MS_SUCCESS; } else if(status != MS_SUCCESS) { msLayerClose(layer); if(chartType == MS_CHART_TYPE_PIE) pieLayerCleanupDynamicDiameter(layer); return MS_FAILURE; } switch(chartType) { case MS_CHART_TYPE_PIE: status = msDrawPieChartLayer(map, layer, image); break; case MS_CHART_TYPE_BAR: status = msDrawBarChartLayer(map, layer, image); break; case MS_CHART_TYPE_VBAR: status = msDrawVBarChartLayer(map, layer, image); break; default: return MS_FAILURE;/*shouldn't be here anyways*/ } msLayerClose(layer); if(chartType == MS_CHART_TYPE_PIE) pieLayerCleanupDynamicDiameter(layer); } return status; } mapserver-6.4.1/maperror.h0000644002461700001440000001407112261257215015317 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations for Error and Debug functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPERROR_H #define MAPERROR_H #ifdef __cplusplus extern "C" { #endif /*==================================================================== * maperror.c *====================================================================*/ #define MS_NOERR 0 /* general error codes */ #define MS_IOERR 1 #define MS_MEMERR 2 #define MS_TYPEERR 3 #define MS_SYMERR 4 #define MS_REGEXERR 5 #define MS_TTFERR 6 #define MS_DBFERR 7 #define MS_GDERR 8 #define MS_IDENTERR 9 #define MS_EOFERR 10 #define MS_PROJERR 11 #define MS_MISCERR 12 #define MS_CGIERR 13 #define MS_WEBERR 14 #define MS_IMGERR 15 #define MS_HASHERR 16 #define MS_JOINERR 17 #define MS_NOTFOUND 18 /* empty search results */ #define MS_SHPERR 19 #define MS_PARSEERR 20 #define MS_SDEERR 21 #define MS_OGRERR 22 #define MS_QUERYERR 23 #define MS_WMSERR 24 /* WMS server error */ #define MS_WMSCONNERR 25 /* WMS connectiontype error */ #define MS_ORACLESPATIALERR 26 #define MS_WFSERR 27 /* WFS server error */ #define MS_WFSCONNERR 28 /* WFS connectiontype error */ #define MS_MAPCONTEXTERR 29 /* Map Context error */ #define MS_HTTPERR 30 #define MS_CHILDERR 31 /* Errors involving arrays of child objects */ #define MS_WCSERR 32 #define MS_GEOSERR 33 #define MS_RECTERR 34 #define MS_TIMEERR 35 #define MS_GMLERR 36 #define MS_SOSERR 37 #define MS_NULLPARENTERR 38 #define MS_AGGERR 39 #define MS_OWSERR 40 #define MS_OGLERR 42 #define MS_RENDERERERR 43 #define MS_NUMERRORCODES 44 #define MESSAGELENGTH 2048 #define ROUTINELENGTH 64 #define MS_ERROR_LANGUAGE "en-US" #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #else #define MS_DLL_EXPORT #endif #ifndef MS_PRINT_FUNC_FORMAT #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP) #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) __attribute__((__format__ (__printf__, format_idx, arg_idx))) #else #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) #endif #endif typedef struct errorObj { int code; char routine[ROUTINELENGTH]; char message[MESSAGELENGTH]; int isreported; #ifndef SWIG struct errorObj *next; #endif } errorObj; /* ** Function prototypes */ MS_DLL_EXPORT errorObj *msGetErrorObj(void); MS_DLL_EXPORT void msResetErrorList(void); MS_DLL_EXPORT char *msGetVersion(void); MS_DLL_EXPORT int msGetVersionInt(void); MS_DLL_EXPORT char *msGetErrorString(char *delimiter); #ifndef SWIG MS_DLL_EXPORT void msSetError(int code, const char *message, const char *routine, ...) MS_PRINT_FUNC_FORMAT(2,4) ; MS_DLL_EXPORT void msWriteError(FILE *stream); MS_DLL_EXPORT void msWriteErrorXML(FILE *stream); MS_DLL_EXPORT char *msGetErrorCodeString(int code); MS_DLL_EXPORT char *msAddErrorDisplayString(char *source, errorObj *error); struct mapObj; MS_DLL_EXPORT void msWriteErrorImage(struct mapObj *map, char *filename, int blank); #endif /* SWIG */ /*==================================================================== * mapdebug.c (See also MS-RFC-28) *====================================================================*/ typedef enum { MS_DEBUGLEVEL_ERRORSONLY = 0, /* DEBUG OFF, log fatal errors */ MS_DEBUGLEVEL_DEBUG = 1, /* DEBUG ON */ MS_DEBUGLEVEL_TUNING = 2, /* Reports timing info */ MS_DEBUGLEVEL_V = 3, /* Verbose */ MS_DEBUGLEVEL_VV = 4, /* Very verbose */ MS_DEBUGLEVEL_VVV = 5 /* Very very verbose */ } debugLevel; #ifndef SWIG typedef enum { MS_DEBUGMODE_OFF, MS_DEBUGMODE_FILE, MS_DEBUGMODE_STDERR, MS_DEBUGMODE_STDOUT, MS_DEBUGMODE_WINDOWSDEBUG } debugMode; typedef struct debug_info_obj { debugLevel global_debug_level; debugMode debug_mode; char *errorfile; FILE *fp; /* The following 2 members are used only with USE_THREAD (but we won't #ifndef them) */ int thread_id; struct debug_info_obj *next; } debugInfoObj; MS_DLL_EXPORT void msDebug( const char * pszFormat, ... ) MS_PRINT_FUNC_FORMAT(1,2) ; MS_DLL_EXPORT int msSetErrorFile(const char *pszErrorFile, const char *pszRelToPath); MS_DLL_EXPORT void msCloseErrorFile( void ); MS_DLL_EXPORT const char *msGetErrorFile( void ); MS_DLL_EXPORT void msSetGlobalDebugLevel(int level); MS_DLL_EXPORT debugLevel msGetGlobalDebugLevel( void ); MS_DLL_EXPORT int msDebugInitFromEnv( void ); MS_DLL_EXPORT void msDebugCleanup( void ); #endif /* SWIG */ #ifdef __cplusplus } #endif #endif /* MAPERROR_H */ mapserver-6.4.1/mapsearch.c0000644002461700001440000005446712261257215015443 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various geospatial search operations. * Author: Steve Lime and the MapServer team. * * Notes: For information on point in polygon function please see: * * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html * * The appropriate copyright notice accompanies the funtion definition. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #define LASTVERT(v,n) ((v) == 0 ? n-2 : v-1) #define NEXTVERT(v,n) ((v) == n-2 ? 0 : v+1) /* ** Returns MS_TRUE if rectangles a and b overlap */ int msRectOverlap(rectObj *a, rectObj *b) { if(a->minx > b->maxx) return(MS_FALSE); if(a->maxx < b->minx) return(MS_FALSE); if(a->miny > b->maxy) return(MS_FALSE); if(a->maxy < b->miny) return(MS_FALSE); return(MS_TRUE); } /* ** Computes the intersection of two rectangles, updating the first ** to be only the intersection of the two. Returns MS_FALSE if ** the intersection is empty. */ int msRectIntersect( rectObj *a, const rectObj *b ) { if( a->maxx > b->maxx ) a->maxx = b->maxx; if( a->minx < b->minx ) a->minx = b->minx; if( a->maxy > b->maxy ) a->maxy = b->maxy; if( a->miny < b->miny ) a->miny = b->miny; if( a->maxx < a->minx || b->maxx < b->minx ) return MS_FALSE; else return MS_TRUE; } /* ** Returns MS_TRUE if rectangle a is contained in rectangle b */ int msRectContained(rectObj *a, rectObj *b) { if(a->minx >= b->minx && a->maxx <= b->maxx) if(a->miny >= b->miny && a->maxy <= b->maxy) return(MS_TRUE); return(MS_FALSE); } /* ** Merges rect b into rect a. Rect a changes, b does not. */ void msMergeRect(rectObj *a, rectObj *b) { a->minx = MS_MIN(a->minx, b->minx); a->maxx = MS_MAX(a->maxx, b->maxx); a->miny = MS_MIN(a->miny, b->miny); a->maxy = MS_MAX(a->maxy, b->maxy); } int msPointInRect(pointObj *p, rectObj *rect) { if(p->x < rect->minx) return(MS_FALSE); if(p->x > rect->maxx) return(MS_FALSE); if(p->y < rect->miny) return(MS_FALSE); if(p->y > rect->maxy) return(MS_FALSE); return(MS_TRUE); } int msPolygonDirection(lineObj *c) { double mx, my, area; int i, v=0, lv, nv; /* first find lowest, rightmost point of polygon */ mx = c->point[0].x; my = c->point[0].y; for(i=0; inumpoints-1; i++) { if((c->point[i].y < my) || ((c->point[i].y == my) && (c->point[i].x > mx))) { v = i; mx = c->point[i].x; my = c->point[i].y; } } lv = LASTVERT(v,c->numpoints); nv = NEXTVERT(v,c->numpoints); area = c->point[lv].x*c->point[v].y - c->point[lv].y*c->point[v].x + c->point[lv].y*c->point[nv].x - c->point[lv].x*c->point[nv].y + c->point[v].x*c->point[nv].y - c->point[nv].x*c->point[v].y; if(area > 0) return(1); /* counter clockwise orientation */ else if(area < 0) /* clockwise orientation */ return(-1); else return(0); /* shouldn't happen unless the polygon is self intersecting */ } /* ** Copyright (c) 1970-2003, Wm. Randolph Franklin ** ** 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: ** ** 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the ** following disclaimers. ** 2. Redistributions in binary form must reproduce the above copyright notice in the documentation and/or ** other materials provided with the distribution. ** 3. The name of W. Randolph Franklin may not be used to endorse or promote products derived from this ** Software without specific prior written permission. ** ** 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. */ int msPointInPolygon(pointObj *p, lineObj *c) { int i, j, status = MS_FALSE; for (i = 0, j = c->numpoints-1; i < c->numpoints; j = i++) { if ((((c->point[i].y<=p->y) && (p->ypoint[j].y)) || ((c->point[j].y<=p->y) && (p->ypoint[i].y))) && (p->x < (c->point[j].x - c->point[i].x) * (p->y - c->point[i].y) / (c->point[j].y - c->point[i].y) + c->point[i].x)) status = !status; } return status; } /* ** Note: the following functions are brute force implementations. Some fancy ** computational geometry algorithms would speed things up nicely in many ** cases. In due time... -SDL- */ int msIntersectSegments(pointObj *a, pointObj *b, pointObj *c, pointObj *d) /* from comp.graphics.alogorithms FAQ */ { double r, s; double denominator, numerator; numerator = ((a->y-c->y)*(d->x-c->x) - (a->x-c->x)*(d->y-c->y)); denominator = ((b->x-a->x)*(d->y-c->y) - (b->y-a->y)*(d->x-c->x)); if((denominator == 0) && (numerator == 0)) { /* lines are coincident, intersection is a line segement if it exists */ if(a->y == c->y) { /* coincident horizontally, check x's */ if(((a->x >= MS_MIN(c->x,d->x)) && (a->x <= MS_MAX(c->x,d->x))) || ((b->x >= MS_MIN(c->x,d->x)) && (b->x <= MS_MAX(c->x,d->x)))) return(MS_TRUE); else return(MS_FALSE); } else { /* test for y's will work fine for remaining cases */ if(((a->y >= MS_MIN(c->y,d->y)) && (a->y <= MS_MAX(c->y,d->y))) || ((b->y >= MS_MIN(c->y,d->y)) && (b->y <= MS_MAX(c->y,d->y)))) return(MS_TRUE); else return(MS_FALSE); } } if(denominator == 0) /* lines are parallel, can't intersect */ return(MS_FALSE); r = numerator/denominator; if((r<0) || (r>1)) return(MS_FALSE); /* no intersection */ numerator = ((a->y-c->y)*(b->x-a->x) - (a->x-c->x)*(b->y-a->y)); s = numerator/denominator; if((s<0) || (s>1)) return(MS_FALSE); /* no intersection */ return(MS_TRUE); } /* ** Instead of using ring orientation we count the number of parts the ** point falls in. If odd the point is in the polygon, if 0 or even ** then the point is in a hole or completely outside. */ int msIntersectPointPolygon(pointObj *point, shapeObj *poly) { int i; int status=MS_FALSE; for(i=0; inumlines; i++) { if(msPointInPolygon(point, &poly->line[i]) == MS_TRUE) /* ok, the point is in a line */ status = !status; } return(status); } int msIntersectMultipointPolygon(shapeObj *multipoint, shapeObj *poly) { int i,j; /* The change to loop through all the lines has been made for ticket * #2443 but is no more needed since ticket #2762. PostGIS now put all * points into a single line. */ for(i=0; inumlines; i++ ) { lineObj points = multipoint->line[i]; for(j=0; jnumlines; c1++) for(v1=1; v1line[c1].numpoints; v1++) for(c2=0; c2numlines; c2++) for(v2=1; v2line[c2].numpoints; v2++) if(msIntersectSegments(&(line1->line[c1].point[v1-1]), &(line1->line[c1].point[v1]), &(line2->line[c2].point[v2-1]), &(line2->line[c2].point[v2])) == MS_TRUE) return(MS_TRUE); return(MS_FALSE); } int msIntersectPolylinePolygon(shapeObj *line, shapeObj *poly) { int i; /* STEP 1: polygon might competely contain the polyline or one of it's parts (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(line->line[i].point[0]), poly) == MS_TRUE) /* this considers holes and multiple parts */ return(MS_TRUE); } /* STEP 2: look for intersecting line segments */ if (msIntersectPolylines(line, poly) == MS_TRUE) return (MS_TRUE); return(MS_FALSE); } int msIntersectPolygons(shapeObj *p1, shapeObj *p2) { int i; /* STEP 1: polygon 1 completely contains 2 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(p2->line[i].point[0]), p1) == MS_TRUE) /* this considers holes and multiple parts */ return(MS_TRUE); } /* STEP 2: polygon 2 completely contains 1 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(p1->line[i].point[0]), p2) == MS_TRUE) /* this considers holes and multiple parts */ return(MS_TRUE); } /* STEP 3: look for intersecting line segments */ if (msIntersectPolylines(p1, p2) == MS_TRUE) return(MS_TRUE); /* ** At this point we know there are are no intersections between edges. There may be other tests necessary ** but I haven't run into any cases that require them. */ return(MS_FALSE); } /* ** Distance computations */ double msDistancePointToPoint(pointObj *a, pointObj *b) { double d; d = sqrt(msSquareDistancePointToPoint(a, b)); return(d); } /* ** Quickly compute the square of the distance; avoids expensive sqrt() call on each invocation */ double msSquareDistancePointToPoint(pointObj *a, pointObj *b) { double dx, dy; dx = a->x - b->x; dy = a->y - b->y; return(dx*dx + dy*dy); } double msDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b) { return (sqrt(msSquareDistancePointToSegment(p, a, b))); } double msSquareDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b) { double l_squared; /* squared length of line ab */ double r,s; l_squared = msSquareDistancePointToPoint(a,b); if(l_squared == 0.0) /* a = b */ return(msSquareDistancePointToPoint(a,p)); r = ((a->y - p->y)*(a->y - b->y) - (a->x - p->x)*(b->x - a->x))/(l_squared); if(r > 1) /* perpendicular projection of P is on the forward extention of AB */ return(MS_MIN(msSquareDistancePointToPoint(p, b),msSquareDistancePointToPoint(p, a))); if(r < 0) /* perpendicular projection of P is on the backward extention of AB */ return(MS_MIN(msSquareDistancePointToPoint(p, b),msSquareDistancePointToPoint(p, a))); s = ((a->y - p->y)*(b->x - a->x) - (a->x - p->x)*(b->y - a->y))/l_squared; return(fabs(s*s*l_squared)); } #define SMALL_NUMBER 0.00000001 #define dot(u,v) ((u).x *(v).x + (u).y *(v).y) /* vector dot product */ #define norm(v) sqrt(dot(v,v)) #define slope(a,b) (((a)->y - (b)->y)/((a)->x - (b)->x)) /* Segment to segment distance code is a modified version of that found at: */ /* */ /* http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm */ /* */ /* Copyright 2001, softSurfer (www.softsurfer.com) */ /* This code may be freely used and modified for any purpose */ /* providing that this copyright notice is included with it. */ /* SoftSurfer makes no warranty for this code, and cannot be held */ /* liable for any real or imagined damage resulting from its use. */ /* Users of this code must verify correctness for their application. */ double msDistanceSegmentToSegment(pointObj *pa, pointObj *pb, pointObj *pc, pointObj *pd) { vectorObj dP; vectorObj u, v, w; double a, b, c, d, e; double D; double sc, sN, sD; /* N=numerator, D=demoninator */ double tc, tN, tD; /* check for strictly parallel segments first */ /* if(((pa->x == pb->x) && (pc->x == pd->x)) || (slope(pa,pb) == slope(pc,pd))) { // vertical (infinite slope) || otherwise parallel */ /* D = msDistancePointToSegment(pa, pc, pd); */ /* D = MS_MIN(D, msDistancePointToSegment(pb, pc, pd)); */ /* D = MS_MIN(D, msDistancePointToSegment(pc, pa, pb)); */ /* return(MS_MIN(D, msDistancePointToSegment(pd, pa, pb))); */ /* } */ u.x = pb->x - pa->x; /* u = pb - pa */ u.y = pb->y - pa->y; v.x = pd->x - pc->x; /* v = pd - pc */ v.y = pd->y - pc->y; w.x = pa->x - pc->x; /* w = pa - pc */ w.y = pa->y - pc->y; a = dot(u,u); b = dot(u,v); c = dot(v,v); d = dot(u,w); e = dot(v,w); D = a*c - b*b; sc = sN = sD = D; tc = tN = tD = D; /* compute the line parameters of the two closest points */ if(D < SMALL_NUMBER) { /* lines are parallel or almost parallel */ sN = 0.0; sD = 1.0; tN = e; tD = c; } else { /* get the closest points on the infinite lines */ sN = b*e - c*d; tN = a*e - b*d; if(sN < 0) { sN = 0.0; tN = e; tD = c; } else if(sN > sD) { sN = sD; tN = e + b; tD = c; } } if(tN < 0) { tN = 0.0; if(-d < 0) sN = 0.0; else if(-d > a) sN = sD; else { sN = -d; sD = a; } } else if(tN > tD) { tN = tD; if((-d + b) < 0) sN = 0.0; else if((-d + b) > a) sN = sD; else { sN = (-d + b); sD = a; } } /* finally do the division to get sc and tc */ sc = sN/sD; tc = tN/tD; dP.x = w.x + (sc*u.x) - (tc*v.x); dP.y = w.y + (sc*u.y) - (tc*v.y); return(norm(dP)); } double msDistancePointToShape(pointObj *point, shapeObj *shape) { double d; d = msSquareDistancePointToShape(point, shape); return(sqrt(d)); } /* ** As msDistancePointToShape; avoid expensive sqrt calls */ double msSquareDistancePointToShape(pointObj *point, shapeObj *shape) { int i, j; double dist, minDist=-1; switch(shape->type) { case(MS_SHAPE_POINT): for(j=0; jnumlines; j++) { for(i=0; iline[j].numpoints; i++) { dist = msSquareDistancePointToPoint(point, &(shape->line[j].point[i])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } break; case(MS_SHAPE_LINE): for(j=0; jnumlines; j++) { for(i=1; iline[j].numpoints; i++) { dist = msSquareDistancePointToSegment(point, &(shape->line[j].point[i-1]), &(shape->line[j].point[i])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } break; case(MS_SHAPE_POLYGON): if(msIntersectPointPolygon(point, shape)) minDist = 0; /* point is IN the shape */ else { /* treat shape just like a line */ for(j=0; jnumlines; j++) { for(i=1; iline[j].numpoints; i++) { dist = msSquareDistancePointToSegment(point, &(shape->line[j].point[i-1]), &(shape->line[j].point[i])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } break; default: break; } return(minDist); } double msDistanceShapeToShape(shapeObj *shape1, shapeObj *shape2) { int i,j,k,l; double dist, minDist=-1; switch(shape1->type) { case(MS_SHAPE_POINT): /* shape1 */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { dist = msSquareDistancePointToShape(&(shape1->line[i].point[j]), shape2); if((dist < minDist) || (minDist < 0)) minDist = dist; } } minDist = sqrt(minDist); break; case(MS_SHAPE_LINE): /* shape1 */ switch(shape2->type) { case(MS_SHAPE_POINT): for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { dist = msSquareDistancePointToShape(&(shape2->line[i].point[j]), shape1); if((dist < minDist) || (minDist < 0)) minDist = dist; } } minDist = sqrt(minDist); break; case(MS_SHAPE_LINE): for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; case(MS_SHAPE_POLYGON): /* shape2 (the polygon) could contain shape1 or one of it's parts */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape1->line[0].point[0]), shape2) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* check segment intersection and, if necessary, distance between segments */ for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; } break; case(MS_SHAPE_POLYGON): /* shape1 */ switch(shape2->type) { case(MS_SHAPE_POINT): for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { dist = msSquareDistancePointToShape(&(shape2->line[i].point[j]), shape1); if((dist < minDist) || (minDist < 0)) minDist = dist; } } minDist = sqrt(minDist); break; case(MS_SHAPE_LINE): /* shape1 (the polygon) could contain shape2 or one of it's parts */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape2->line[i].point[0]), shape1) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* check segment intersection and, if necessary, distance between segments */ for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; case(MS_SHAPE_POLYGON): /* shape1 completely contains shape2 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape2->line[i].point[0]), shape1) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* shape2 completely contains shape1 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape1->line[i].point[0]), shape2) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* check segment intersection and, if necessary, distance between segments */ for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; } break; } return(minDist); } mapserver-6.4.1/mapcairo.c0000644002461700001440000011764312261257215015267 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Cairo Rendering functions * Author: Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2009 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. *****************************************************************************/ #include "mapserver.h" #ifdef USE_CAIRO #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #else #include #include #endif #ifdef USE_SVG_CAIRO #include #else #ifdef USE_RSVG #include #ifndef LIBRSVG_CHECK_VERSION #include #endif #ifndef RSVG_CAIRO_H #include #endif #include #endif #endif #ifdef USE_GDAL #include #include #endif # include /* #include #include */ #include /* #include #include FT_FREETYPE_H */ typedef struct facecacheObj faceCacheObj; struct facecacheObj { cairo_font_face_t *face; FT_Face ftface; char *path; faceCacheObj *next; cairo_user_data_key_t facekey; }; int freeFaceCache(faceCacheObj *fc) { /* printf("***\nface %s has %d cairo references\n***\n",fc->path,cairo_font_face_get_reference_count(fc->face)); */ cairo_font_face_destroy(fc->face); FT_Done_Face(fc->ftface); free(fc->path); return MS_SUCCESS; } typedef struct { faceCacheObj *facecache; FT_Library library; /* dummy surface and context */ unsigned char dummydata[4]; cairo_surface_t *dummysurface; cairo_t *dummycr; } cairoCacheData; void initializeCache(void **vcache) { cairoCacheData *cache = (cairoCacheData*)malloc(sizeof(cairoCacheData)); *vcache = cache; cache->facecache = NULL; FT_Init_FreeType(&(cache->library)); /* dummy surface and context */ cache->dummysurface = cairo_image_surface_create_for_data(cache->dummydata, CAIRO_FORMAT_ARGB32, 1,1,4); cache->dummycr = cairo_create(cache->dummysurface); } int cleanupCairo(void *cache) { cairoCacheData *ccache = (cairoCacheData*)cache; if(ccache->dummycr) { cairo_destroy(ccache->dummycr); } if(ccache->dummysurface) { cairo_surface_destroy(ccache->dummysurface); } if(ccache->facecache) { faceCacheObj *next,*cur; cur = ccache->facecache; do { next = cur->next; freeFaceCache(cur); free(cur); cur=next; } while(cur); } if(ccache->library) FT_Done_FreeType(ccache->library); free(ccache); return MS_SUCCESS; } typedef struct { cairo_surface_t *surface; cairo_t *cr; bufferObj *outputStream; int use_alpha; } cairo_renderer; #define CAIRO_RENDERER(im) ((cairo_renderer*)(im->img.plugin)) int freeImageCairo(imageObj *img) { cairo_renderer *r = CAIRO_RENDERER(img); if(r) { cairo_destroy(r->cr); cairo_surface_finish(r->surface); cairo_surface_destroy(r->surface); if(r->outputStream) { msBufferFree(r->outputStream); free(r->outputStream); } free(r); } return MS_SUCCESS; } faceCacheObj *getFontFace(cairoCacheData *cache, const char *font) { faceCacheObj *newface = NULL; faceCacheObj *cur=cache->facecache; while(cur) { if(!strcmp(cur->path,font)) return cur; cur = cur->next; } newface = malloc(sizeof(faceCacheObj)); if(FT_New_Face(cache->library, font, 0, &(newface->ftface))) { msSetError(MS_RENDERERERR,"Freetype failed to open font %s","getFontFace()",font); free(newface); return NULL; } /* Try to select charmap */ if (!newface->ftface->charmap) { if( FT_Select_Charmap(newface->ftface, FT_ENCODING_MS_SYMBOL) ) FT_Select_Charmap(newface->ftface, FT_ENCODING_APPLE_ROMAN ); } newface->next = cache->facecache; cache->facecache = newface; newface->face = cairo_ft_font_face_create_for_ft_face(newface->ftface, 0); cairo_font_face_set_user_data (newface->face, &newface->facekey, &(newface->ftface), (cairo_destroy_func_t) NULL); // we call FT_Done_Face ourselves in freeFaceCache newface->path = msStrdup(font); return newface; } #define msCairoSetSourceColor(cr, c) cairo_set_source_rgba((cr),(c)->red/255.0,(c)->green/255.0,(c)->blue/255.0,(c)->alpha/255.0); int renderLineCairo(imageObj *img, shapeObj *p, strokeStyleObj *stroke) { int i,j; cairo_renderer *r = CAIRO_RENDERER(img); assert(stroke->color); cairo_new_path(r->cr); msCairoSetSourceColor(r->cr,stroke->color); for(i=0; inumlines; i++) { lineObj *l = &(p->line[i]); if(l->numpoints == 0) continue; cairo_move_to(r->cr,l->point[0].x,l->point[0].y); for(j=1; jnumpoints; j++) { cairo_line_to(r->cr,l->point[j].x,l->point[j].y); } } if(stroke->patternlength>0) { cairo_set_dash(r->cr,stroke->pattern,stroke->patternlength,-stroke->patternoffset); } switch(stroke->linecap) { case MS_CJC_BUTT: cairo_set_line_cap(r->cr,CAIRO_LINE_CAP_BUTT); break; case MS_CJC_SQUARE: cairo_set_line_cap(r->cr,CAIRO_LINE_CAP_SQUARE); break; case MS_CJC_ROUND: case MS_CJC_NONE: default: cairo_set_line_cap(r->cr,CAIRO_LINE_CAP_ROUND); } cairo_set_line_width (r->cr, stroke->width); cairo_stroke (r->cr); if(stroke->patternlength>0) { cairo_set_dash(r->cr,stroke->pattern,0,0); } return MS_SUCCESS; } int renderPolygonCairo(imageObj *img, shapeObj *p, colorObj *c) { cairo_renderer *r = CAIRO_RENDERER(img); int i,j; cairo_new_path(r->cr); cairo_set_fill_rule(r->cr,CAIRO_FILL_RULE_EVEN_ODD); msCairoSetSourceColor(r->cr,c); for(i=0; inumlines; i++) { lineObj *l = &(p->line[i]); cairo_move_to(r->cr,l->point[0].x,l->point[0].y); for(j=1; jnumpoints; j++) { cairo_line_to(r->cr,l->point[j].x,l->point[j].y); } cairo_close_path(r->cr); } cairo_fill(r->cr); return MS_SUCCESS; } int renderPolygonTiledCairo(imageObj *img, shapeObj *p, imageObj *tile) { int i,j; cairo_renderer *r = CAIRO_RENDERER(img); cairo_renderer *tileRenderer = CAIRO_RENDERER(tile); cairo_pattern_t *pattern = cairo_pattern_create_for_surface(tileRenderer->surface); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_set_source(r->cr, pattern); for (i = 0; i < p->numlines; i++) { lineObj *l = &(p->line[i]); cairo_move_to(r->cr, l->point[0].x, l->point[0].y); for (j = 1; j < l->numpoints; j++) { cairo_line_to(r->cr, l->point[j].x, l->point[j].y); } /* cairo_close_path(r->cr); */ } cairo_fill(r->cr); cairo_pattern_destroy(pattern); return MS_SUCCESS; } cairo_surface_t *createSurfaceFromBuffer(rasterBufferObj *b) { assert(b->type == MS_BUFFER_BYTE_RGBA); return cairo_image_surface_create_for_data (b->data.rgba.pixels, CAIRO_FORMAT_ARGB32, b->width, b->height, b->data.rgba.row_step); } int renderPixmapSymbolCairo(imageObj *img, double x, double y,symbolObj *symbol, symbolStyleObj *style) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_surface_t *im; rasterBufferObj *b = symbol->pixmap_buffer; assert(b); if(!symbol->renderer_cache) { symbol->renderer_cache = (void*)createSurfaceFromBuffer(b); } assert(symbol->renderer_cache); im=(cairo_surface_t*)symbol->renderer_cache; cairo_save(r->cr); if(style->rotation != 0 || style->scale != 1) { cairo_translate (r->cr, x,y); cairo_rotate (r->cr, -style->rotation); cairo_scale (r->cr, style->scale,style->scale); cairo_translate (r->cr, -0.5*b->width, -0.5*b->height); } else { cairo_translate (r->cr, MS_NINT(x-0.5*b->width),MS_NINT(y-0.5*b->height)); } cairo_set_source_surface (r->cr, im, 0, 0); cairo_paint (r->cr); cairo_restore(r->cr); return MS_SUCCESS; } int renderVectorSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { cairo_renderer *r = CAIRO_RENDERER(img); double ox=symbol->sizex*0.5,oy=symbol->sizey*0.5; int is_new = 1,i; cairo_new_path(r->cr); cairo_save(r->cr); cairo_translate(r->cr,x,y); cairo_scale(r->cr,style->scale,style->scale); cairo_rotate(r->cr,-style->rotation); cairo_translate(r->cr,-ox,-oy); for (i = 0; i < symbol->numpoints; i++) { if ((symbol->points[i].x == -99) && (symbol->points[i].y == -99)) { /* (PENUP) */ is_new = 1; } else { if (is_new) { cairo_move_to(r->cr,symbol->points[i].x,symbol->points[i].y); is_new = 0; } else { cairo_line_to(r->cr,symbol->points[i].x,symbol->points[i].y); } } } cairo_restore(r->cr); if(style->color) { msCairoSetSourceColor(r->cr,style->color); cairo_fill_preserve(r->cr); } if(style->outlinewidth>0) { msCairoSetSourceColor(r->cr,style->outlinecolor); cairo_set_line_width (r->cr, style->outlinewidth); cairo_stroke_preserve(r->cr); } cairo_new_path(r->cr); return MS_SUCCESS; } #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache { rasterBufferObj *pixmap_buffer; #ifdef USE_RSVG RsvgHandle *svgc; #else svg_cairo_t *svgc; #endif double scale,rotation; } ; #endif int renderSVGSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *cache; cairo_renderer *r = CAIRO_RENDERER(img); msPreloadSVGSymbol(symbol); assert(symbol->renderer_cache); cache = symbol->renderer_cache; cairo_save(r->cr); cairo_translate(r->cr,x,y); cairo_scale(r->cr,style->scale,style->scale); if (style->rotation != 0) { cairo_rotate(r->cr, -style->rotation); cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2)); } else cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2)); #ifdef USE_SVG_CAIRO { svg_cairo_status_t status; status = svg_cairo_render(cache->svgc, r->cr); if(status != SVG_CAIRO_STATUS_SUCCESS) { cairo_restore(r->cr); return MS_FAILURE; } } #else rsvg_handle_render_cairo(cache->svgc, r->cr); #endif cairo_restore(r->cr); return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif } int renderTruetypeSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *s) { int unicode; cairo_glyph_t glyph; cairo_text_extents_t extents; cairo_matrix_t trans; double ox,oy; cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); cairo_renderer *r = CAIRO_RENDERER(img); faceCacheObj *face = getFontFace(cache,symbol->full_font_path); if(!face) return MS_FAILURE; cairo_save(r->cr); cairo_set_font_face(r->cr,face->face); cairo_set_font_size(r->cr,s->scale*96/72.0); msUTF8ToUniChar(symbol->character, &unicode); if (face->ftface->charmap && face->ftface->charmap->encoding == FT_ENCODING_MS_SYMBOL) unicode |= 0xf000; glyph.index = FT_Get_Char_Index(face->ftface, unicode); glyph.x=0; glyph.y=0; cairo_glyph_extents(r->cr,&glyph,1,&extents); ox=extents.x_bearing+extents.width/2.; oy=extents.y_bearing+extents.height/2.; cairo_matrix_init_rotate(&trans,-s->rotation); cairo_matrix_transform_point(&trans,&ox,&oy); /* cairo_translate(cr,-extents.width/2,-extents.height/2); */ cairo_translate(r->cr,x-ox,y-oy); cairo_rotate(r->cr, -s->rotation); cairo_glyph_path(r->cr,&glyph,1); if (s->outlinewidth) { msCairoSetSourceColor(r->cr, s->outlinecolor); cairo_set_line_width(r->cr, s->outlinewidth + 1); cairo_stroke_preserve(r->cr); } if(s->color) { msCairoSetSourceColor(r->cr, s->color); cairo_fill_preserve(r->cr); } cairo_new_path(r->cr); cairo_restore(r->cr); return MS_SUCCESS; } int renderTileCairo(imageObj *img, imageObj *tile, double x, double y) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_surface_t *im = CAIRO_RENDERER(tile)->surface; int w = cairo_image_surface_get_width (im); int h = cairo_image_surface_get_height (im); cairo_save(r->cr); cairo_translate(r->cr, MS_NINT(x-0.5 * w), MS_NINT(y -0.5 * h)); cairo_set_source_surface(r->cr, im, 0, 0); cairo_pattern_set_filter (cairo_get_source (r->cr), CAIRO_FILTER_NEAREST); cairo_paint(r->cr); cairo_restore(r->cr); return MS_SUCCESS; } #define CAIROLINESPACE 1.33 int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *text, rectObj *rect, double **advances, int bAdjustBaseline) { cairoCacheData *cache = MS_RENDERER_CACHE(renderer); faceCacheObj* face = getFontFace(cache,fonts[0]); int curfontidx = 0; char *utfptr=text; int i,unicode; unsigned long previdx=0; faceCacheObj* prevface = face; int numglyphs = msGetNumGlyphs(text); cairo_glyph_t glyph; cairo_text_extents_t extents; double px=0,py=0; if(face == NULL) { return MS_FAILURE; } cairo_set_font_face(cache->dummycr,face->face); cairo_set_font_size(cache->dummycr,size*96/72.0); if(advances != NULL) { *advances = (double*)malloc(numglyphs*sizeof(double)); } for(i=0; idummycr, face->face); curfontidx = 0; } if (face->ftface->charmap && face->ftface->charmap->encoding == FT_ENCODING_MS_SYMBOL) unicode |= 0xf000; glyph.index = FT_Get_Char_Index(face->ftface, unicode); if (glyph.index == 0) { int j; for (j = 1; j < numfonts; j++) { curfontidx = j; face = getFontFace(cache, fonts[j]); glyph.index = FT_Get_Char_Index(face->ftface, unicode); if (glyph.index != 0) { cairo_set_font_face(cache->dummycr, face->face); break; } } } if( FT_HAS_KERNING((prevface->ftface)) && previdx ) { FT_Vector delta; FT_Get_Kerning( prevface->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta ); px += delta.x / 64.; } cairo_glyph_extents(cache->dummycr,&glyph,1,&extents); if(i==0) { rect->minx = px+extents.x_bearing; rect->miny = py+extents.y_bearing; rect->maxx = px+extents.x_bearing+extents.width; rect->maxy = py+(bAdjustBaseline?1:(extents.y_bearing+extents.height)); } else { rect->minx = MS_MIN(rect->minx,px+extents.x_bearing); rect->miny = MS_MIN(rect->miny,py+extents.y_bearing); rect->maxy = MS_MAX(rect->maxy,py+(bAdjustBaseline?1:(extents.y_bearing+extents.height))); rect->maxx = MS_MAX(rect->maxx,px+extents.x_bearing+extents.width); } if(advances!=NULL) (*advances)[i]=extents.x_advance; px += extents.x_advance; previdx=glyph.index; prevface = face; } return MS_SUCCESS; } int renderGlyphsCairo(imageObj *img,double x, double y, labelStyleObj *style, char *text) { cairo_renderer *r = CAIRO_RENDERER(img); cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); faceCacheObj* face = getFontFace(cache,style->fonts[0]); int curfontidx = 0; char *utfptr=text; int i,unicode; unsigned long previdx=0; faceCacheObj* prevface = face; int numglyphs = msGetNumGlyphs(text); cairo_glyph_t glyph; cairo_text_extents_t extents; double px=0,py=0; if(face == NULL) { return MS_FAILURE; } cairo_set_font_face(r->cr,face->face); cairo_set_font_size(r->cr,style->size*96/72.0); cairo_save(r->cr); cairo_translate(r->cr,MS_NINT(x),MS_NINT(y)); if(style->rotation != 0.0) cairo_rotate(r->cr, -style->rotation); for(i=0; isize*CAIROLINESPACE); px = 0; previdx=0; continue; } if(curfontidx != 0) { face = getFontFace(cache,style->fonts[0]); cairo_set_font_face(r->cr,face->face); curfontidx = 0; } if (face->ftface->charmap && face->ftface->charmap->encoding == FT_ENCODING_MS_SYMBOL) unicode |= 0xf000; glyph.index = FT_Get_Char_Index(face->ftface, unicode); if(glyph.index == 0) { int j; for(j=1; jnumfonts; j++) { curfontidx = j; face = getFontFace(cache,style->fonts[j]); glyph.index = FT_Get_Char_Index(face->ftface, unicode); if(glyph.index != 0) { cairo_set_font_face(r->cr,face->face); break; } } } if( FT_HAS_KERNING((prevface->ftface)) && previdx ) { FT_Vector delta; FT_Get_Kerning( prevface->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta ); px += delta.x / 64.; } cairo_glyph_extents(r->cr,&glyph,1,&extents); cairo_glyph_path(r->cr,&glyph,1); px += extents.x_advance; previdx=glyph.index; prevface=face; } if (style->outlinewidth > 0) { cairo_save(r->cr); msCairoSetSourceColor(r->cr, style->outlinecolor); cairo_set_line_width(r->cr, style->outlinewidth + 1); cairo_stroke_preserve(r->cr); cairo_restore(r->cr); } if(style->color) { msCairoSetSourceColor(r->cr, style->color); cairo_fill(r->cr); } cairo_new_path(r->cr); cairo_restore(r->cr); return MS_SUCCESS; } cairo_status_t _stream_write_fn(void *b, const unsigned char *data, unsigned int length) { msBufferAppend((bufferObj*)b,(void*)data,length); return CAIRO_STATUS_SUCCESS; } imageObj* createImageCairo(int width, int height, outputFormatObj *format,colorObj* bg) { imageObj *image = NULL; cairo_renderer *r=NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode!= MS_IMAGEMODE_RGBA) { msSetError(MS_MISCERR, "Cairo driver only supports RGB or RGBA pixel models.","msImageCreateCairo()"); return image; } if (width > 0 && height > 0) { image = (imageObj *) calloc(1, sizeof(imageObj)); r = (cairo_renderer*)calloc(1,sizeof(cairo_renderer)); if(!strcasecmp(format->driver,"cairo/pdf")) { r->outputStream = (bufferObj*)malloc(sizeof(bufferObj)); msBufferInit(r->outputStream); r->surface = cairo_pdf_surface_create_for_stream( _stream_write_fn, r->outputStream, width,height); } else if(!strcasecmp(format->driver,"cairo/svg")) { r->outputStream = (bufferObj*)malloc(sizeof(bufferObj)); msBufferInit(r->outputStream); r->surface = cairo_svg_surface_create_for_stream( _stream_write_fn, r->outputStream, width,height); } else if(!strcasecmp(format->driver,"cairo/winGDI") && format->device) { #if CAIRO_HAS_WIN32_SURFACE r->outputStream = NULL; r->surface = cairo_win32_surface_create(format->device); #else msSetError(MS_RENDERERERR, "Cannot create cairo image. Cairo was not compiled with support for the win32 backend.", "msImageCreateCairo()"); #endif } else if(!strcasecmp(format->driver,"cairo/winGDIPrint") && format->device) { #if CAIRO_HAS_WIN32_SURFACE r->outputStream = NULL; r->surface = cairo_win32_printing_surface_create(format->device); #else msSetError(MS_RENDERERERR, "Cannot create cairo image. Cairo was not compiled with support for the win32 backend.", "msImageCreateCairo()"); #endif } else { r->outputStream = NULL; r->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); } r->cr = cairo_create(r->surface); if(format->transparent || !bg || !MS_VALID_COLOR(*bg)) { r->use_alpha = 1; cairo_set_source_rgba (r->cr, 0,0,0,0); } else { r->use_alpha = 0; msCairoSetSourceColor(r->cr,bg); } cairo_save (r->cr); cairo_set_operator (r->cr, CAIRO_OPERATOR_SOURCE); cairo_paint (r->cr); cairo_restore (r->cr); cairo_set_line_cap (r->cr,CAIRO_LINE_CAP_ROUND); cairo_set_line_join(r->cr,CAIRO_LINE_JOIN_ROUND); image->img.plugin = (void*)r; } else { msSetError(MS_RENDERERERR, "Cannot create cairo image of size %dx%d.", "msImageCreateCairo()", width, height); } return image; } /* msSaveImagePostPDFProcessing() will call the GDAL PDF driver to add geospatial */ /* information to the regular PDF generated by cairo. This is only triggered if the */ /* GEO_ENCODING outputformat option is set (to ISO32000 or OGC_BP). Additionnal */ /* options can be provided by specifying outputformat options starting with */ /* METADATA_ITEM: prefix. For example METADATA_ITEM:PRODUCER=MapServer */ /* Those options are AUTHOR, CREATOR, CREATION_DATE, KEYWORDS, PRODUCER, SUBJECT, TITLE */ /* See http://gdal.org/frmt_pdf.html documentation. */ static void msTransformToGeospatialPDF(imageObj *img, mapObj *map, cairo_renderer *r) { /* We need a GDAL 1.10 PDF driver at runtime, but as far as the C API is concerned, GDAL 1.9 is */ /* largely sufficient. */ #if defined(USE_GDAL) && defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900 GDALDatasetH hDS = NULL; const char* pszGEO_ENCODING = NULL; GDALDriverH hPDFDriver = NULL; const char* pszVirtualIO = NULL; int bVirtualIO = FALSE; char* pszTmpFilename = NULL; VSILFILE* fp = NULL; if (map == NULL) return; pszGEO_ENCODING = msGetOutputFormatOption(img->format, "GEO_ENCODING", NULL); if (pszGEO_ENCODING == NULL) return; msGDALInitialize(); hPDFDriver = GDALGetDriverByName("PDF"); if (hPDFDriver == NULL) return; /* When compiled against libpoppler, the PDF driver is VirtualIO capable */ /* but not, when it is compiled against libpodofo. */ pszVirtualIO = GDALGetMetadataItem( hPDFDriver, GDAL_DCAP_VIRTUALIO, NULL ); if (pszVirtualIO) bVirtualIO = CSLTestBoolean(pszVirtualIO); if (bVirtualIO) pszTmpFilename = msTmpFile(map, NULL, "/vsimem/mscairopdf/", "pdf"); else pszTmpFilename = msTmpFile(map, map->mappath, NULL, "pdf"); /* Copy content of outputStream buffer into file */ fp = VSIFOpenL(pszTmpFilename, "wb"); if (fp == NULL) { msFree(pszTmpFilename); return; } VSIFWriteL(r->outputStream->data, 1, r->outputStream->size, fp); VSIFCloseL(fp); fp = NULL; hDS = GDALOpen(pszTmpFilename, GA_Update); if ( hDS != NULL ) { char* pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { double adfGeoTransform[6]; int i; /* Add user-specified options */ for( i = 0; i < img->format->numformatoptions; i++ ) { const char* pszOption = img->format->formatoptions[i]; if( strncasecmp(pszOption,"METADATA_ITEM:",14) == 0 ) { char* pszKey = NULL; const char* pszValue = CPLParseNameValue(pszOption + 14, &pszKey); if( pszKey != NULL ) { GDALSetMetadataItem(hDS, pszKey, pszValue, NULL); CPLFree(pszKey); } } } /* We need to rescale the geotransform because GDAL will not necessary */ /* open the PDF with the DPI that was used to generate it */ memcpy(adfGeoTransform, map->gt.geotransform, 6 * sizeof(double)); adfGeoTransform[1] = adfGeoTransform[1] * map->width / GDALGetRasterXSize(hDS); adfGeoTransform[5] = adfGeoTransform[5] * map->height / GDALGetRasterYSize(hDS); GDALSetGeoTransform(hDS, adfGeoTransform); GDALSetProjection(hDS, pszWKT); msFree( pszWKT ); pszWKT = NULL; CPLSetThreadLocalConfigOption("GDAL_PDF_GEO_ENCODING", pszGEO_ENCODING); GDALClose(hDS); hDS = NULL; CPLSetThreadLocalConfigOption("GDAL_PDF_GEO_ENCODING", NULL); /* We need to replace the buffer with the content of the GDAL file */ fp = VSIFOpenL(pszTmpFilename, "rb"); if( fp != NULL ) { int nFileSize; VSIFSeekL(fp, 0, SEEK_END); nFileSize = (int)VSIFTellL(fp); msBufferResize(r->outputStream, nFileSize); VSIFSeekL(fp, 0, SEEK_SET); VSIFReadL(r->outputStream->data, 1, nFileSize, fp); r->outputStream->size = nFileSize; VSIFCloseL(fp); fp = NULL; } } } if ( hDS != NULL ) GDALClose(hDS); VSIUnlink(pszTmpFilename); msFree(pszTmpFilename); #endif } int saveImageCairo(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { cairo_renderer *r = CAIRO_RENDERER(img); if(!strcasecmp(img->format->driver,"cairo/pdf") || !strcasecmp(img->format->driver,"cairo/svg")) { cairo_surface_finish (r->surface); if (map != NULL && !strcasecmp(img->format->driver,"cairo/pdf")) msTransformToGeospatialPDF(img, map, r); msIO_fwrite(r->outputStream->data,r->outputStream->size,1,fp); } else { /* not supported */ } return MS_SUCCESS; } unsigned char* saveImageBufferCairo(imageObj *img, int *size_ptr, outputFormatObj *format) { cairo_renderer *r = CAIRO_RENDERER(img); unsigned char *data; assert(!strcasecmp(img->format->driver,"cairo/pdf") || !strcasecmp(img->format->driver,"cairo/svg")); cairo_surface_finish (r->surface); data = msSmallMalloc(r->outputStream->size); memcpy(data,r->outputStream->data,r->outputStream->size); *size_ptr = (int)r->outputStream->size; return data; } int renderEllipseSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_save(r->cr); cairo_set_line_cap(r->cr, CAIRO_LINE_CAP_BUTT); cairo_set_line_join(r->cr, CAIRO_LINE_JOIN_MITER); cairo_translate(r->cr,x,y); cairo_rotate(r->cr,-style->rotation); cairo_scale(r->cr,symbol->sizex*style->scale/2,symbol->sizey*style->scale/2); cairo_arc (r->cr, 0,0,1, 0, 2 * MS_PI); cairo_restore(r->cr); if(style->color) { msCairoSetSourceColor(r->cr, style->color); cairo_fill_preserve(r->cr); } if(style->outlinewidth > 0) { cairo_set_line_width (r->cr, style->outlinewidth); msCairoSetSourceColor(r->cr, style->outlinecolor); cairo_stroke_preserve(r->cr); } cairo_new_path(r->cr); return MS_SUCCESS; } int startLayerVectorCairo(imageObj *img, mapObj *map, layerObj *layer) { if(layer->opacity<100) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_push_group (r->cr); } return MS_SUCCESS; } int closeLayerVectorCairo(imageObj *img, mapObj *map, layerObj *layer) { if(layer->opacity<100) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_pop_group_to_source (r->cr); cairo_paint_with_alpha (r->cr, layer->opacity*0.01); } return MS_SUCCESS; } int startLayerRasterCairo(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int closeLayerRasterCairo(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int getRasterBufferHandleCairo(imageObj *img, rasterBufferObj *rb) { unsigned char *pb; cairo_renderer *r = CAIRO_RENDERER(img); rb->type = MS_BUFFER_BYTE_RGBA; pb = cairo_image_surface_get_data(r->surface); rb->data.rgba.pixels = pb; rb->data.rgba.row_step = cairo_image_surface_get_stride(r->surface); rb->data.rgba.pixel_step=4; rb->width = cairo_image_surface_get_width(r->surface); rb->height = cairo_image_surface_get_height(r->surface); rb->data.rgba.r = &(pb[2]); rb->data.rgba.g = &(pb[1]); rb->data.rgba.b = &(pb[0]); if(r->use_alpha) rb->data.rgba.a = &(pb[3]); else rb->data.rgba.a = NULL; return MS_SUCCESS; } int getRasterBufferCopyCairo(imageObj *img, rasterBufferObj *rb) { cairo_renderer *r = CAIRO_RENDERER(img); unsigned char *pb; rb->type = MS_BUFFER_BYTE_RGBA; rb->data.rgba.row_step = cairo_image_surface_get_stride(r->surface); rb->data.rgba.pixel_step=4; rb->width = cairo_image_surface_get_width(r->surface); rb->height = cairo_image_surface_get_height(r->surface); pb = (unsigned char*)malloc(rb->height * rb->data.rgba.row_step * sizeof(unsigned char*)); memcpy(pb,cairo_image_surface_get_data(r->surface),rb->height * rb->data.rgba.row_step); rb->data.rgba.pixels = pb; rb->data.rgba.r = &(pb[2]); rb->data.rgba.g = &(pb[1]); rb->data.rgba.b = &(pb[0]); if(r->use_alpha) rb->data.rgba.a = &(pb[3]); else rb->data.rgba.a = NULL; return MS_SUCCESS; } int mergeRasterBufferCairo(imageObj *img, rasterBufferObj *rb, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { cairo_surface_t *src; cairo_renderer *r; /* not implemented for src,dst,width and height */ if(!rb->type == MS_BUFFER_BYTE_RGBA) { return MS_FAILURE; } r = CAIRO_RENDERER(img); src = cairo_image_surface_create_for_data(rb->data.rgba.pixels,CAIRO_FORMAT_ARGB32, rb->width,rb->height, rb->data.rgba.row_step); if(dstX||dstY||srcX||srcY||width!=img->width||height!=img->height) { cairo_set_source_surface (r->cr, src, dstX - srcX, dstY - srcY); cairo_rectangle (r->cr, dstX, dstY, width, height); cairo_fill (r->cr); } else { cairo_set_source_surface (r->cr,src,0,0); cairo_paint_with_alpha(r->cr,opacity); } cairo_surface_finish(src); cairo_surface_destroy(src); return MS_SUCCESS; } void freeSVGCache(symbolObj *s) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *cache = s->renderer_cache; assert(cache->svgc); #ifdef USE_SVG_CAIRO svg_cairo_destroy(cache->svgc); #else rsvg_handle_close(cache->svgc, NULL); #if LIBRSVG_CHECK_VERSION(2,35,0) g_object_unref(cache->svgc); #else rsvg_handle_free(cache->svgc); #endif #endif if(cache->pixmap_buffer) { msFreeRasterBuffer(cache->pixmap_buffer); free(cache->pixmap_buffer); } msFree(s->renderer_cache); #endif } int freeSymbolCairo(symbolObj *s) { if(!s->renderer_cache) return MS_SUCCESS; switch(s->type) { case MS_SYMBOL_VECTOR: cairo_path_destroy(s->renderer_cache); break; case MS_SYMBOL_PIXMAP: cairo_surface_destroy(s->renderer_cache); break; case MS_SYMBOL_SVG: freeSVGCache(s); break; } s->renderer_cache=NULL; return MS_SUCCESS; } int initializeRasterBufferCairo(rasterBufferObj *rb, int width, int height, int mode) { rb->type = MS_BUFFER_BYTE_RGBA; rb->width = width; rb->height = height; rb->data.rgba.pixel_step = 4; rb->data.rgba.row_step = width * 4; rb->data.rgba.pixels = (unsigned char*)calloc(width*height*4,sizeof(unsigned char)); rb->data.rgba.r = &(rb->data.rgba.pixels[2]); rb->data.rgba.g = &(rb->data.rgba.pixels[1]); rb->data.rgba.b = &(rb->data.rgba.pixels[0]); rb->data.rgba.a = &(rb->data.rgba.pixels[3]); return MS_SUCCESS; } int msPreloadSVGSymbol(symbolObj *symbol) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *cache; if(!symbol->renderer_cache) { cache = msSmallCalloc(1,sizeof(struct svg_symbol_cache)); symbol->renderer_free_func = &freeSVGCache; } else { cache = symbol->renderer_cache; } if(cache->svgc) return MS_SUCCESS; #ifdef USE_SVG_CAIRO { unsigned int svg_width, svg_height; int status; status = svg_cairo_create(&cache->svgc); if (status) { msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()"); return MS_FAILURE; } status = svg_cairo_parse(cache->svgc, symbol->full_pixmap_path); if (status) { msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()"); return MS_FAILURE; } svg_cairo_get_size (cache->svgc, &svg_width, &svg_height); if (svg_width == 0 || svg_height == 0) { msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()"); return MS_FAILURE; } symbol->sizex = svg_width; symbol->sizey = svg_height; } #else { RsvgDimensionData dim; cache->svgc = rsvg_handle_new_from_file(symbol->full_pixmap_path,NULL); if(!cache->svgc) { msSetError(MS_RENDERERERR,"failed to load svg file %s", "msPreloadSVGSymbol()", symbol->full_pixmap_path); } rsvg_handle_get_dimensions_sub (cache->svgc, &dim, NULL); symbol->sizex = dim.width; symbol->sizey = dim.height; } #endif symbol->renderer_cache = cache; return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but is not built with libsvgcairo", "msPreloadSVGSymbol()"); return MS_FAILURE; #endif } int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *svg_cache; symbolStyleObj pixstyle; symbolObj pixsymbol; if(img->format->renderer == MS_RENDER_WITH_GD) { msSetError(MS_MISCERR, "GD renderer does not support SVG symbols", "msRenderRasterizedSVGSymbol()"); return MS_FAILURE; } if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache; //already rendered at the right size and scale? return if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) { cairo_t *cr; cairo_surface_t *surface; unsigned char *pb; int width, height, surface_w, surface_h; /* need to recompute the pixmap */ if(svg_cache->pixmap_buffer) { msFreeRasterBuffer(svg_cache->pixmap_buffer); } else { svg_cache->pixmap_buffer = msSmallCalloc(1,sizeof(rasterBufferObj)); } //increase pixmap size to accomodate scaling/rotation if (style->scale != 1.0) { width = surface_w = (symbol->sizex * style->scale + 0.5); height = surface_h = (symbol->sizey * style->scale + 0.5); } else { width = surface_w = symbol->sizex; height = surface_h = symbol->sizey; } if (style->rotation != 0) { surface_w = MS_NINT(width * 1.415); surface_h = MS_NINT(height * 1.415); } surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h); cr = cairo_create(surface); if (style->rotation != 0) { cairo_translate(cr, surface_w / 2, surface_h / 2); cairo_rotate(cr, -style->rotation); cairo_translate(cr, -width / 2, -height / 2); } if (style->scale != 1.0) { cairo_scale(cr, style->scale, style->scale); } #ifdef USE_SVG_CAIRO if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) { return MS_FAILURE; } #else rsvg_handle_render_cairo(svg_cache->svgc, cr); #endif pb = cairo_image_surface_get_data(surface); //set up raster initializeRasterBufferCairo(svg_cache->pixmap_buffer, surface_w, surface_h, 0); memcpy(svg_cache->pixmap_buffer->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char)); svg_cache->scale = style->scale; svg_cache->rotation = style->rotation; cairo_destroy(cr); cairo_surface_destroy(surface); } assert(svg_cache->pixmap_buffer->height && svg_cache->pixmap_buffer->width); pixstyle = *style; pixstyle.rotation = 0.0; pixstyle.scale = 1.0; pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer; pixsymbol.type = MS_SYMBOL_PIXMAP; MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif } void msCairoCleanup() { cairo_debug_reset_static_data(); } #endif /*USE_CAIRO*/ int msPopulateRendererVTableCairoRaster( rendererVTableObj *renderer ) { #ifdef USE_CAIRO renderer->supports_pixel_buffer=1; renderer->supports_transparent_layers = 0; renderer->supports_svg = 1; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; initializeCache(&MS_RENDERER_CACHE(renderer)); renderer->startLayer = startLayerRasterCairo; renderer->endLayer = closeLayerRasterCairo; renderer->renderLineTiled = NULL; renderer->renderLine=&renderLineCairo; renderer->createImage=&createImageCairo; renderer->saveImage=&saveImageCairo; renderer->getRasterBufferHandle=&getRasterBufferHandleCairo; renderer->getRasterBufferCopy=&getRasterBufferCopyCairo; renderer->renderPolygon=&renderPolygonCairo; renderer->renderGlyphs=&renderGlyphsCairo; renderer->freeImage=&freeImageCairo; renderer->renderEllipseSymbol = &renderEllipseSymbolCairo; renderer->renderVectorSymbol = &renderVectorSymbolCairo; renderer->renderTruetypeSymbol = &renderTruetypeSymbolCairo; renderer->renderSVGSymbol = &renderSVGSymbolCairo; renderer->renderPixmapSymbol = &renderPixmapSymbolCairo; renderer->mergeRasterBuffer = &mergeRasterBufferCairo; renderer->getTruetypeTextBBox = &getTruetypeTextBBoxCairo; renderer->renderTile = &renderTileCairo; renderer->loadImageFromFile = &msLoadMSRasterBufferFromFile; renderer->renderPolygonTiled = &renderPolygonTiledCairo; renderer->freeSymbol = &freeSymbolCairo; renderer->cleanup = &cleanupCairo; return MS_SUCCESS; #else msSetError(MS_MISCERR, "Cairo Driver requested but MapServer is not built in", "msPopulateRendererVTableCairoRaster()"); return MS_FAILURE; #endif } int populateRendererVTableCairoVector( rendererVTableObj *renderer ) { #ifdef USE_CAIRO renderer->use_imagecache=0; renderer->supports_pixel_buffer=0; renderer->supports_transparent_layers = 1; renderer->supports_svg = 1; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; initializeCache(&MS_RENDERER_CACHE(renderer)); renderer->startLayer = startLayerVectorCairo; renderer->endLayer = closeLayerVectorCairo; renderer->renderLine=&renderLineCairo; renderer->renderLineTiled = NULL; renderer->createImage=&createImageCairo; renderer->saveImage=&saveImageCairo; renderer->saveImageBuffer = &saveImageBufferCairo; renderer->getRasterBufferHandle=&getRasterBufferHandleCairo; renderer->renderPolygon=&renderPolygonCairo; renderer->renderGlyphs=&renderGlyphsCairo; renderer->freeImage=&freeImageCairo; renderer->renderEllipseSymbol = &renderEllipseSymbolCairo; renderer->renderVectorSymbol = &renderVectorSymbolCairo; renderer->renderTruetypeSymbol = &renderTruetypeSymbolCairo; renderer->renderSVGSymbol = &renderSVGSymbolCairo; renderer->renderPixmapSymbol = &renderPixmapSymbolCairo; renderer->loadImageFromFile = &msLoadMSRasterBufferFromFile; renderer->mergeRasterBuffer = &mergeRasterBufferCairo; renderer->initializeRasterBuffer = initializeRasterBufferCairo; renderer->getTruetypeTextBBox = &getTruetypeTextBBoxCairo; renderer->renderTile = &renderTileCairo; renderer->renderPolygonTiled = &renderPolygonTiledCairo; renderer->freeSymbol = &freeSymbolCairo; renderer->cleanup = &cleanupCairo; return MS_SUCCESS; #else msSetError(MS_MISCERR, "Cairo Driver requested but MapServer is not built in", "msPopulateRendererVTableCairoRaster()"); return MS_FAILURE; #endif } int msPopulateRendererVTableCairoSVG( rendererVTableObj *renderer ) { return populateRendererVTableCairoVector(renderer); } int msPopulateRendererVTableCairoPDF( rendererVTableObj *renderer ) { return populateRendererVTableCairoVector(renderer); } mapserver-6.4.1/mapogcsld.c0000644002461700001440000063057212261257215015446 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC SLD implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #include "mapogcsld.h" #include "mapogcfilter.h" #include "mapserver.h" #ifdef USE_OGR #include "cpl_string.h" #endif #define SLD_LINE_SYMBOL_NAME "sld_line_symbol" #define SLD_LINE_SYMBOL_DASH_NAME "sld_line_symbol_dash" #define SLD_MARK_SYMBOL_SQUARE "sld_mark_symbol_square" #define SLD_MARK_SYMBOL_SQUARE_FILLED "sld_mark_symbol_square_filled" #define SLD_MARK_SYMBOL_CIRCLE "sld_mark_symbol_circle" #define SLD_MARK_SYMBOL_CIRCLE_FILLED "sld_mark_symbol_circle_filled" #define SLD_MARK_SYMBOL_TRIANGLE "sld_mark_symbol_triangle" #define SLD_MARK_SYMBOL_TRIANGLE_FILLED "sld_mark_symbol_triangle_filled" #define SLD_MARK_SYMBOL_STAR "sld_mark_symbol_star" #define SLD_MARK_SYMBOL_STAR_FILLED "sld_mark_symbol_star_filled" #define SLD_MARK_SYMBOL_CROSS "sld_mark_symbol_cross" #define SLD_MARK_SYMBOL_CROSS_FILLED "sld_mark_symbol_cross_filled" #define SLD_MARK_SYMBOL_X "sld_mark_symbol_x" #define SLD_MARK_SYMBOL_X_FILLED "sld_mark_symbol_x_filled" /************************************************************************/ /* msSLDApplySLDURL */ /* */ /* Use the SLD document given through a URL and apply the SLD */ /* on the map. Layer name and Named Layer's name parameter are */ /* used to do the match. */ /************************************************************************/ int msSLDApplySLDURL(mapObj *map, char *szURL, int iLayer, char *pszStyleLayerName, char **ppszLayerNames) { #ifdef USE_OGR /* needed for libcurl function msHTTPGetFile in maphttp.c */ #if defined(USE_CURL) char *pszSLDTmpFile = NULL; int status = 0; char *pszSLDbuf=NULL; FILE *fp = NULL; int nStatus = MS_FAILURE; if (map && szURL) { pszSLDTmpFile = msTmpFile(map, map->mappath, NULL, "sld.xml"); if (pszSLDTmpFile == NULL) { pszSLDTmpFile = msTmpFile(map, NULL, NULL, "sld.xml" ); } if (pszSLDTmpFile == NULL) { msSetError(MS_WMSERR, "Could not determine temporary file %s. Please make sure that the temporary path is set. The temporary path can be defined for example by setting TMPPATH in the map file. Please check the MapServer documentation on temporary path settings.", "msSLDApplySLDURL()", pszSLDTmpFile); } else { int nMaxRemoteSLDBytes; const char *pszMaxRemoteSLDBytes = msOWSLookupMetadata(&(map->web.metadata), "MO", "remote_sld_max_bytes"); if(!pszMaxRemoteSLDBytes) { nMaxRemoteSLDBytes = 1024*1024; /* 1 megaByte */ } else { nMaxRemoteSLDBytes = atoi(pszMaxRemoteSLDBytes); } if (msHTTPGetFile(szURL, pszSLDTmpFile, &status,-1, 0, 0, nMaxRemoteSLDBytes) == MS_SUCCESS) { if ((fp = fopen(pszSLDTmpFile, "rb")) != NULL) { int nBufsize=0; fseek(fp, 0, SEEK_END); nBufsize = ftell(fp); rewind(fp); pszSLDbuf = (char*)malloc((nBufsize+1)*sizeof(char)); fread(pszSLDbuf, 1, nBufsize, fp); fclose(fp); pszSLDbuf[nBufsize] = '\0'; unlink(pszSLDTmpFile); } } else { unlink(pszSLDTmpFile); msSetError(MS_WMSERR, "Could not open SLD %s and save it in a temporary file. Please make sure that the sld url is valid and that the temporary path is set. The temporary path can be defined for example by setting TMPPATH in the map file. Please check the MapServer documentation on temporary path settings.", "msSLDApplySLDURL", szURL); } if (pszSLDbuf) nStatus = msSLDApplySLD(map, pszSLDbuf, iLayer, pszStyleLayerName, ppszLayerNames); } } return nStatus; #else msSetError(MS_MISCERR, "WMS/WFS client support is not enabled .", "msSLDApplySLDURL()"); return(MS_FAILURE); #endif #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDApplySLDURL()"); return(MS_FAILURE); #endif /* USE_OGR */ } /************************************************************************/ /* msSLDApplySLD */ /* */ /* Parses the SLD into array of layers. Go through the map and */ /* compare the SLD layers and the map layers using the name. If */ /* they have the same name, copy the classes asscoaited with */ /* the SLD layers onto the map layers. */ /************************************************************************/ int msSLDApplySLD(mapObj *map, char *psSLDXML, int iLayer, char *pszStyleLayerName, char **ppszLayerNames) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) #ifdef USE_OGR int nLayers = 0; layerObj *pasLayers = NULL; int i, j, k, z, iClass; int bUseSpecificLayer = 0; const char *pszTmp = NULL; int bFreeTemplate = 0; int nLayerStatus = 0; int nStatus = MS_SUCCESS; /*const char *pszSLDNotSupported = NULL;*/ char *tmpfilename = NULL; const char *pszFullName = NULL; char szTmp[512]; char *pszTmp1=NULL; char *pszTmp2 = NULL; char *pszBuffer = NULL; layerObj *lp = NULL; char *pszSqlExpression=NULL; FilterEncodingNode *psExpressionNode =NULL; int bFailedExpression=0; pasLayers = msSLDParseSLD(map, psSLDXML, &nLayers); /* -------------------------------------------------------------------- */ /* If the same layer is given more that once, we need to */ /* duplicate it. */ /* -------------------------------------------------------------------- */ if (pasLayers && nLayers>0) { int l,m; for (m=0; mvtable) msInitializeVirtualTable(psTmpLayer); /*make the name unique*/ snprintf(tmpId, sizeof(tmpId), "%lx_%x_%d",(long)time(NULL),(int)getpid(), map->numlayers); if (psTmpLayer->name) msFree(psTmpLayer->name); psTmpLayer->name = strdup(tmpId); msFree(pasLayers[l].name); pasLayers[l].name = strdup(tmpId); msInsertLayer(map, psTmpLayer, -1); MS_REFCNT_DECR(psTmpLayer); } } } } if (pasLayers && nLayers > 0) { for (i=0; inumlayers; i++) { if (iLayer >=0 && iLayer< map->numlayers) { i = iLayer; bUseSpecificLayer = 1; } /* compare layer name to wms_name as well */ pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "MO", "name"); for (j=0; jname, pasLayers[j].name) == 0 || (pszTmp && strcasecmp(pszTmp, pasLayers[j].name) == 0))|| (GET_LAYER(map, i)->group && strcasecmp(GET_LAYER(map, i)->group, pasLayers[j].name) == 0))) || (bUseSpecificLayer && pszStyleLayerName && pasLayers[j].name && strcasecmp(pasLayers[j].name, pszStyleLayerName) == 0)) { #ifdef notdef /*this is a test code if we decide to flag some layers as not supporting SLD*/ pszSLDNotSupported = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "M", "SLD_NOT_SUPPORTED"); if (pszSLDNotSupported) { msSetError(MS_WMSERR, "Layer %s does not support SLD", "msSLDApplySLD", pasLayers[j].name); return MS_FAILURE; } #endif if ( pasLayers[j].numclasses > 0) { GET_LAYER(map, i)->type = pasLayers[j].type; for(k=0; knumclasses; k++) { if (GET_LAYER(map, i)->class[k] != NULL) { GET_LAYER(map, i)->class[k]->layer=NULL; if (freeClass(GET_LAYER(map, i)->class[k]) == MS_SUCCESS ) { msFree(GET_LAYER(map, i)->class[k]); GET_LAYER(map, i)->class[k] = NULL; } } } GET_LAYER(map, i)->numclasses = 0; /*unset the classgroup on the layer if it was set. This allows the layer to render with all the classes defined in the SLD*/ msFree(GET_LAYER(map, i)->classgroup); GET_LAYER(map, i)->classgroup = NULL; iClass = 0; for (k=0; k < pasLayers[j].numclasses; k++) { if (msGrowLayerClasses(GET_LAYER(map, i)) == NULL) return MS_FAILURE; initClass(GET_LAYER(map, i)->class[iClass]); msCopyClass(GET_LAYER(map, i)->class[iClass], pasLayers[j].class[k], NULL); GET_LAYER(map, i)->class[iClass]->layer = GET_LAYER(map, i); GET_LAYER(map, i)->class[iClass]->type = GET_LAYER(map, i)->type; GET_LAYER(map, i)->numclasses++; /*aliases may have been used as part of the sld text symbolizer for label element. Try to process it if that is the case #3114*/ if (msLayerOpen(GET_LAYER(map, i)) == MS_SUCCESS && msLayerGetItems(GET_LAYER(map, i)) == MS_SUCCESS) { if (GET_LAYER(map, i)->class[iClass]->text.string) { for(z=0; znumitems; z++) { if (!GET_LAYER(map, i)->items[z] || strlen(GET_LAYER(map, i)->items[z]) <= 0) continue; snprintf(szTmp, sizeof(szTmp), "%s_alias", GET_LAYER(map, i)->items[z]); pszFullName = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "G", szTmp); pszTmp1 = msStrdup( GET_LAYER(map, i)->class[iClass]->text.string); if (pszFullName != NULL && (strstr(pszTmp1, pszFullName) != NULL)) { char *tmpstr1= NULL; tmpstr1 = msReplaceSubstring(pszTmp1, pszFullName, GET_LAYER(map, i)->items[z]); pszTmp2 = (char *)malloc(sizeof(char)*(strlen(tmpstr1)+3)); sprintf(pszTmp2,"(%s)",tmpstr1); msLoadExpressionString(&(GET_LAYER(map, i)->class[iClass]->text), pszTmp2); msFree(pszTmp2); } msFree(pszTmp1); } } } iClass++; } } else { /*this is probably an SLD that uses Named styles*/ if (pasLayers[j].classgroup) { for (k=0; knumclasses; k++) { if (GET_LAYER(map, i)->class[k]->group && strcasecmp(GET_LAYER(map, i)->class[k]->group, pasLayers[j].classgroup) == 0) break; } if (k < GET_LAYER(map, i)->numclasses) { msFree( GET_LAYER(map, i)->classgroup); GET_LAYER(map, i)->classgroup = msStrdup(pasLayers[j].classgroup); } else { /* TODO we throw an exception ?*/ } } } if (pasLayers[j].labelitem) { if (GET_LAYER(map, i)->labelitem) free(GET_LAYER(map, i)->labelitem); GET_LAYER(map, i)->labelitem = msStrdup(pasLayers[j].labelitem); } if (pasLayers[j].classitem) { if (GET_LAYER(map, i)->classitem) free(GET_LAYER(map, i)->classitem); GET_LAYER(map, i)->classitem = msStrdup(pasLayers[j].classitem); } /* opacity for sld raster */ if (GET_LAYER(map, i)->type == MS_LAYER_RASTER && pasLayers[j].opacity != -1) GET_LAYER(map, i)->opacity = pasLayers[j].opacity; /* mark as auto-generate SLD */ if (GET_LAYER(map, i)->connectiontype == MS_WMS) msInsertHashTable(&(GET_LAYER(map, i)->metadata), "wms_sld_body", "auto" ); /* ==================================================================== */ /* if the SLD contained a spatial feature, the layerinfo */ /* parameter contains the node. Extract it and do a query on */ /* the layer. Insert also a metadata that will be used when */ /* rendering the final image. */ /* ==================================================================== */ if (pasLayers[j].layerinfo && (GET_LAYER(map, i)->type == MS_LAYER_POINT || GET_LAYER(map, i)->type == MS_LAYER_LINE || GET_LAYER(map, i)->type == MS_LAYER_POLYGON || GET_LAYER(map, i)->type == MS_LAYER_ANNOTATION || GET_LAYER(map, i)->type == MS_LAYER_TILEINDEX)) { FilterEncodingNode *psNode = NULL; msInsertHashTable(&(GET_LAYER(map, i)->metadata), "tmp_wms_sld_query", "true" ); psNode = (FilterEncodingNode *)pasLayers[j].layerinfo; /* -------------------------------------------------------------------- */ /* set the template on the classes so that the query works */ /* using classes. If there are no classes, set it at the layer level.*/ /* -------------------------------------------------------------------- */ if (GET_LAYER(map, i)->numclasses > 0) { for (k=0; knumclasses; k++) { if (!GET_LAYER(map, i)->class[k]->template) GET_LAYER(map, i)->class[k]->template = msStrdup("ttt.html"); } } else if (!GET_LAYER(map, i)->template) { bFreeTemplate = 1; GET_LAYER(map, i)->template = msStrdup("ttt.html"); } nLayerStatus = GET_LAYER(map, i)->status; GET_LAYER(map, i)->status = MS_ON; nStatus = FLTApplyFilterToLayer(psNode, map, GET_LAYER(map, i)->index); /* -------------------------------------------------------------------- */ /* nothing found is a valid, do not exit. */ /* -------------------------------------------------------------------- */ if (nStatus != MS_SUCCESS) { errorObj *ms_error; ms_error = msGetErrorObj(); if(ms_error->code == MS_NOTFOUND) nStatus = MS_SUCCESS; } GET_LAYER(map, i)->status = nLayerStatus; FLTFreeFilterEncodingNode(psNode); if ( bFreeTemplate) { free(GET_LAYER(map, i)->template); GET_LAYER(map, i)->template = NULL; } pasLayers[j].layerinfo=NULL; if( nStatus != MS_SUCCESS ) return nStatus; } else { /*in some cases it would make sense to concatenate all the class expressions and use it to set the filter on the layer. This could increase performace. Will do it for db types layers #2840*/ lp = GET_LAYER(map, i); if (lp->filter.string == NULL || (lp->filter.string && lp->filter.type == MS_EXPRESSION)) { if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_SDE || lp->connectiontype == MS_PLUGIN) { if (lp->numclasses > 0) { /*check first that all classes have an expression type. That is the only way we can concatenate them and set the filter expression*/ for (k=0; knumclasses; k++) { if (lp->class[k]->expression.type != MS_EXPRESSION) break; } if (k == lp->numclasses) { bFailedExpression = 0; for (k=0; knumclasses; k++) { if (pszBuffer == NULL) snprintf(szTmp, sizeof(szTmp), "%s", "(("); else snprintf(szTmp, sizeof(szTmp), "%s", " OR "); pszBuffer =msStringConcatenate(pszBuffer, szTmp); psExpressionNode = BuildExpressionTree(lp->class[k]->expression.string,NULL); if (psExpressionNode) { pszSqlExpression = FLTGetSQLExpression(psExpressionNode,lp); if (pszSqlExpression) { pszBuffer = msStringConcatenate(pszBuffer, pszSqlExpression); msFree(pszSqlExpression); } else { bFailedExpression =1; break; } FLTFreeFilterEncodingNode(psExpressionNode); } else { bFailedExpression =1; break; } } if (!bFailedExpression) { snprintf(szTmp, sizeof(szTmp), "%s", "))"); pszBuffer =msStringConcatenate(pszBuffer, szTmp); msLoadExpressionString(&lp->filter, pszBuffer); } msFree(pszBuffer); pszBuffer = NULL; } } } } } break; } } if (bUseSpecificLayer) break; } /* -------------------------------------------------------------------- */ /* if needed return a comma separated list of the layers found */ /* in the sld. */ /* -------------------------------------------------------------------- */ if (ppszLayerNames) { char *pszTmp = NULL; for (i=0; idebug == MS_DEBUGLEVEL_VVV) { tmpfilename = msTmpFile(map, map->mappath, NULL, "_sld.map"); if (tmpfilename == NULL) { tmpfilename = msTmpFile(map, NULL, NULL, "_sld.map" ); } if (tmpfilename) { msSaveMap(map,tmpfilename); msDebug("msApplySLD(): Map file after SLD was applied %s", tmpfilename); msFree(tmpfilename); } } return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDApplySLD()"); return(MS_FAILURE); #endif /* USE_OGR */ #else msSetError(MS_MISCERR, "OWS support is not available.", "msSLDApplySLD()"); return(MS_FAILURE); #endif } #ifdef USE_OGR /************************************************************************/ /* msSLDParseSLD */ /* */ /* Parse the sld document into layers : for each named layer */ /* there is one mapserver layer created with approproate */ /* classes and styles. */ /* Returns an array of mapserver layers. The pnLayres if */ /* provided will indicate the size of the returned array. */ /************************************************************************/ layerObj *msSLDParseSLD(mapObj *map, char *psSLDXML, int *pnLayers) { CPLXMLNode *psRoot = NULL; CPLXMLNode *psSLD, *psNamedLayer, *psChild, *psName; layerObj *pasLayers = NULL; int iLayer = 0; int nLayers = 0; if (map == NULL || psSLDXML == NULL || strlen(psSLDXML) <= 0 || (strstr(psSLDXML, "StyledLayerDescriptor") == NULL)) { msSetError(MS_WMSERR, "Invalid SLD document", ""); return NULL; } psRoot = CPLParseXMLString(psSLDXML); if( psRoot == NULL) { msSetError(MS_WMSERR, "Invalid SLD document : %s", "", psSLDXML); return NULL; } /* strip namespaces ogc and sld and gml */ CPLStripXMLNamespace(psRoot, "ogc", 1); CPLStripXMLNamespace(psRoot, "sld", 1); CPLStripXMLNamespace(psRoot, "gml", 1); CPLStripXMLNamespace(psRoot, "se", 1); /* -------------------------------------------------------------------- */ /* get the root element (Filter). */ /* -------------------------------------------------------------------- */ psChild = psRoot; psSLD = NULL; while( psChild != NULL ) { if (psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"StyledLayerDescriptor")) { psSLD = psChild; break; } else psChild = psChild->psNext; } if (!psSLD) { msSetError(MS_WMSERR, "Invalid SLD document : %s", "", psSLDXML); return NULL; } /* -------------------------------------------------------------------- */ /* Parse the named layers. */ /* -------------------------------------------------------------------- */ psNamedLayer = CPLGetXMLNode(psSLD, "NamedLayer"); while (psNamedLayer) { if (!psNamedLayer->pszValue || strcasecmp(psNamedLayer->pszValue, "NamedLayer") != 0) { psNamedLayer = psNamedLayer->psNext; continue; } psNamedLayer = psNamedLayer->psNext; nLayers++; } if (nLayers > 0) pasLayers = (layerObj *)malloc(sizeof(layerObj)*nLayers); else return NULL; psNamedLayer = CPLGetXMLNode(psSLD, "NamedLayer"); if (psNamedLayer) { iLayer = 0; while (psNamedLayer) { if (!psNamedLayer->pszValue || strcasecmp(psNamedLayer->pszValue, "NamedLayer") != 0) { psNamedLayer = psNamedLayer->psNext; continue; } psName = CPLGetXMLNode(psNamedLayer, "Name"); initLayer(&pasLayers[iLayer], map); if (psName && psName->psChild && psName->psChild->pszValue) pasLayers[iLayer].name = msStrdup(psName->psChild->pszValue); msSLDParseNamedLayer(psNamedLayer, &pasLayers[iLayer]); psNamedLayer = psNamedLayer->psNext; iLayer++; } } if (pnLayers) *pnLayers = nLayers; if (psRoot) CPLDestroyXMLNode(psRoot); return pasLayers; } double _msSLDParseSizeParameter(CPLXMLNode *psSize) { double dSize = 0; CPLXMLNode *psLiteral = NULL; if (psSize) { psLiteral = CPLGetXMLNode(psSize, "Literal"); if (psLiteral && psLiteral->psChild && psLiteral->psChild->pszValue) dSize = atof(psLiteral->psChild->pszValue); else if (psSize->psChild && psSize->psChild->pszValue) dSize = atof(psSize->psChild->pszValue); } return dSize; } /************************************************************************/ /* _SLDApplyRuleValues */ /* */ /* Utility function to set the scale, title/name for the */ /* classes created by a Rule. */ /************************************************************************/ void _SLDApplyRuleValues(CPLXMLNode *psRule, layerObj *psLayer, int nNewClasses) { int i=0; CPLXMLNode *psMinScale=NULL, *psMaxScale=NULL; CPLXMLNode *psName=NULL, *psTitle=NULL; double dfMinScale=0, dfMaxScale=0; char *pszName=NULL, *pszTitle=NULL; if (psRule && psLayer && nNewClasses > 0) { /* -------------------------------------------------------------------- */ /* parse minscale and maxscale. */ /* -------------------------------------------------------------------- */ psMinScale = CPLGetXMLNode(psRule, "MinScaleDenominator"); if (psMinScale && psMinScale->psChild && psMinScale->psChild->pszValue) dfMinScale = atof(psMinScale->psChild->pszValue); psMaxScale = CPLGetXMLNode(psRule, "MaxScaleDenominator"); if (psMaxScale && psMaxScale->psChild && psMaxScale->psChild->pszValue) dfMaxScale = atof(psMaxScale->psChild->pszValue); /* -------------------------------------------------------------------- */ /* parse name and title. */ /* -------------------------------------------------------------------- */ psName = CPLGetXMLNode(psRule, "Name"); if (psName && psName->psChild && psName->psChild->pszValue) pszName = psName->psChild->pszValue; psTitle = CPLGetXMLNode(psRule, "Title"); if (psTitle && psTitle->psChild && psTitle->psChild->pszValue) pszTitle = psTitle->psChild->pszValue; /* -------------------------------------------------------------------- */ /* set the scale to all the classes created by the rule. */ /* -------------------------------------------------------------------- */ if (dfMinScale > 0 || dfMaxScale > 0) { for (i=0; i 0) psLayer->class[psLayer->numclasses-1-i]->minscaledenom = dfMinScale; if (dfMaxScale) psLayer->class[psLayer->numclasses-1-i]->maxscaledenom = dfMaxScale; } } /* -------------------------------------------------------------------- */ /* set name and title to the classes created by the rule. */ /* -------------------------------------------------------------------- */ for (i=0; iclass[psLayer->numclasses-1-i]->name) { if (pszName) psLayer->class[psLayer->numclasses-1-i]->name = msStrdup(pszName); else if (pszTitle) psLayer->class[psLayer->numclasses-1-i]->name = msStrdup(pszTitle); else psLayer->class[psLayer->numclasses-1-i]->name = msStrdup("Unknown"); } } if (pszTitle) { for (i=0; iclass[psLayer->numclasses-1-i]->title = msStrdup(pszTitle); } } } } /************************************************************************/ /* msSLDParseNamedLayer */ /* */ /* Parse NamedLayer root. */ /************************************************************************/ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer) { CPLXMLNode *psFeatureTypeStyle, *psRule, *psUserStyle; CPLXMLNode *psSLDName = NULL, *psNamedStyle=NULL; CPLXMLNode *psElseFilter = NULL, *psFilter=NULL; CPLXMLNode *psTmpNode = NULL; FilterEncodingNode *psNode = NULL; int nNewClasses=0, nClassBeforeFilter=0, nClassAfterFilter=0; int nClassAfterRule=0, nClassBeforeRule=0; char *pszTmpFilter = NULL; layerObj *psCurrentLayer = NULL; const char *pszWmsName=NULL; int j=0; const char *key=NULL; if (!psRoot || !psLayer) return MS_FAILURE; psUserStyle = CPLGetXMLNode(psRoot, "UserStyle"); if (psUserStyle) { psFeatureTypeStyle = CPLGetXMLNode(psUserStyle, "FeatureTypeStyle"); if (psFeatureTypeStyle) { while (psFeatureTypeStyle && psFeatureTypeStyle->pszValue && strcasecmp(psFeatureTypeStyle->pszValue, "FeatureTypeStyle") == 0) { if (!psFeatureTypeStyle->pszValue || strcasecmp(psFeatureTypeStyle->pszValue, "FeatureTypeStyle") != 0) { psFeatureTypeStyle = psFeatureTypeStyle->psNext; continue; } /* -------------------------------------------------------------------- */ /* Parse rules with no Else filter. */ /* -------------------------------------------------------------------- */ psRule = CPLGetXMLNode(psFeatureTypeStyle, "Rule"); while (psRule) { if (!psRule->pszValue || strcasecmp(psRule->pszValue, "Rule") != 0) { psRule = psRule->psNext; continue; } /* used for scale setting */ nClassBeforeRule = psLayer->numclasses; psElseFilter = CPLGetXMLNode(psRule, "ElseFilter"); nClassBeforeFilter = psLayer->numclasses; if (psElseFilter == NULL) msSLDParseRule(psRule, psLayer); nClassAfterFilter = psLayer->numclasses; /* -------------------------------------------------------------------- */ /* Parse the filter and apply it to the latest class created by */ /* the rule. */ /* NOTE : Spatial Filter is not supported. */ /* -------------------------------------------------------------------- */ psFilter = CPLGetXMLNode(psRule, "Filter"); if (psFilter && psFilter->psChild && psFilter->psChild->pszValue) { CPLXMLNode *psTmpNextNode = NULL; /* clone the tree and set the next node to null */ /* so we only have the Filter node */ psTmpNode = CPLCloneXMLTree(psFilter); psTmpNextNode = psTmpNode->psNext; psTmpNode->psNext = NULL; pszTmpFilter = CPLSerializeXMLTree(psTmpNode); psTmpNode->psNext = psTmpNextNode; CPLDestroyXMLNode(psTmpNode); if (pszTmpFilter) { /* nTmp = strlen(psFilter->psChild->pszValue)+17; */ /* pszTmpFilter = malloc(sizeof(char)*nTmp); */ /* sprintf(pszTmpFilter,"%s", */ /* psFilter->psChild->pszValue); */ /* pszTmpFilter[nTmp-1]='\0'; */ psNode = FLTParseFilterEncoding(pszTmpFilter); CPLFree(pszTmpFilter); } if (psNode) { char *pszExpression = NULL; int i; /*preparse the filter for possible gml aliases set on the layer's metada: "gml_NA3DESC_alias" "alias_name" and filter could be alias_name #3079*/ for (j=0; jmap->numlayers; j++) { psCurrentLayer = GET_LAYER(psLayer->map, j); pszWmsName = msOWSLookupMetadata(&(psCurrentLayer->metadata), "MO", "name"); if ((psCurrentLayer->name && psLayer->name && strcasecmp(psCurrentLayer->name, psLayer->name) == 0) || (psCurrentLayer->group && psLayer->name && strcasecmp(psCurrentLayer->group, psLayer->name) == 0) || (psLayer->name && pszWmsName && strcasecmp(pszWmsName, psLayer->name) == 0)) break; } if (j < psLayer->map->numlayers) { /*make sure that the tmp layer has all the metadata that the orinal layer has, allowing to do parsing for such things as gml_attribute_type #3052*/ while (1) { key = msNextKeyFromHashTable(&psCurrentLayer->metadata, key); if (!key) break; else msInsertHashTable(&psLayer->metadata, key, msLookupHashTable(&psCurrentLayer->metadata, key)); } FLTPreParseFilterForAlias(psNode, psLayer->map, j, "G"); } pszExpression = FLTGetCommonExpression(psNode, psLayer); FLTFreeFilterEncodingNode(psNode); psNode = NULL; if (pszExpression) { nNewClasses = nClassAfterFilter - nClassBeforeFilter; for (i=0; i class[psLayer->numclasses-1-i]-> expression, pszExpression); } msFree(pszExpression); pszExpression = NULL; } } } nClassAfterRule = psLayer->numclasses; nNewClasses = nClassAfterRule - nClassBeforeRule; /* apply scale and title to newly created classes */ _SLDApplyRuleValues(psRule, psLayer, nNewClasses); /* TODO : parse legendgraphic */ psRule = psRule->psNext; } /* -------------------------------------------------------------------- */ /* First parse rules with the else filter. These rules will */ /* create the classes that are placed at the end of class */ /* list. (See how classes are applied to layers in function */ /* msSLDApplySLD). */ /* -------------------------------------------------------------------- */ psRule = CPLGetXMLNode(psFeatureTypeStyle, "Rule"); while (psRule) { if (!psRule->pszValue || strcasecmp(psRule->pszValue, "Rule") != 0) { psRule = psRule->psNext; continue; } psElseFilter = CPLGetXMLNode(psRule, "ElseFilter"); if (psElseFilter) { msSLDParseRule(psRule, psLayer); _SLDApplyRuleValues(psRule, psLayer, 1); } psRule = psRule->psNext; } psFeatureTypeStyle = psFeatureTypeStyle->psNext; } } } /* check for Named styles*/ else { psNamedStyle = CPLGetXMLNode(psRoot, "NamedStyle"); if (psNamedStyle) { psSLDName = CPLGetXMLNode(psNamedStyle, "Name"); if (psSLDName && psSLDName->psChild && psSLDName->psChild->pszValue) { msFree(psLayer->classgroup); psLayer->classgroup = msStrdup(psSLDName->psChild->pszValue); } } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParseRule(CPLXMLNode *psRoot, layerObj *psLayer) */ /* */ /* Parse a Rule node into classes for a spcific layer. */ /************************************************************************/ int msSLDParseRule(CPLXMLNode *psRoot, layerObj *psLayer) { CPLXMLNode *psLineSymbolizer = NULL; CPLXMLNode *psPolygonSymbolizer = NULL; CPLXMLNode *psPointSymbolizer = NULL; CPLXMLNode *psTextSymbolizer = NULL; CPLXMLNode *psRasterSymbolizer = NULL; int bSymbolizer = 0; int bNewClass=0, nSymbolizer=0; if (!psRoot || !psLayer) return MS_FAILURE; /* TODO : parse name of the rule */ /* -------------------------------------------------------------------- */ /* The SLD specs assumes here that a certain FeatureType can only have*/ /* rules for only one type of symbolizer. */ /* -------------------------------------------------------------------- */ /* ==================================================================== */ /* For each rule a new class is created. If there are more than */ /* one symbolizer of the same type, a style is added in the */ /* same class. */ /* ==================================================================== */ nSymbolizer =0; /* line symbolizer */ psLineSymbolizer = CPLGetXMLNode(psRoot, "LineSymbolizer"); while (psLineSymbolizer) { if (!psLineSymbolizer->pszValue || strcasecmp(psLineSymbolizer->pszValue, "LineSymbolizer") != 0) { psLineSymbolizer = psLineSymbolizer->psNext; continue; } bSymbolizer = 1; if (nSymbolizer == 0) bNewClass = 1; else bNewClass = 0; msSLDParseLineSymbolizer(psLineSymbolizer, psLayer, bNewClass); psLineSymbolizer = psLineSymbolizer->psNext; psLayer->type = MS_LAYER_LINE; nSymbolizer++; } /* Polygon symbolizer */ psPolygonSymbolizer = CPLGetXMLNode(psRoot, "PolygonSymbolizer"); while (psPolygonSymbolizer) { if (!psPolygonSymbolizer->pszValue || strcasecmp(psPolygonSymbolizer->pszValue, "PolygonSymbolizer") != 0) { psPolygonSymbolizer = psPolygonSymbolizer->psNext; continue; } bSymbolizer = 1; if (nSymbolizer == 0) bNewClass = 1; else bNewClass = 0; msSLDParsePolygonSymbolizer(psPolygonSymbolizer, psLayer, bNewClass); psPolygonSymbolizer = psPolygonSymbolizer->psNext; psLayer->type = MS_LAYER_POLYGON; nSymbolizer++; } /* Point Symbolizer */ psPointSymbolizer = CPLGetXMLNode(psRoot, "PointSymbolizer"); while (psPointSymbolizer) { if (!psPointSymbolizer->pszValue || strcasecmp(psPointSymbolizer->pszValue, "PointSymbolizer") != 0) { psPointSymbolizer = psPointSymbolizer->psNext; continue; } bSymbolizer = 1; if (nSymbolizer == 0) bNewClass = 1; else bNewClass = 0; msSLDParsePointSymbolizer(psPointSymbolizer, psLayer, bNewClass); psPointSymbolizer = psPointSymbolizer->psNext; psLayer->type = MS_LAYER_POINT; nSymbolizer++; } /* Text symbolizer */ /* ==================================================================== */ /* For text symbolizer, here is how it is translated into */ /* mapserver classes : */ /* - If there are other symbolizers(line, polygon, symbol), */ /* the label object created will be created in the same class */ /* (the last class) as the symbolizer. This allows o have for */ /* example of point layer with labels. */ /* - If there are no other symbolizers, a new clas will be */ /* created ocontain the label object. */ /* ==================================================================== */ psTextSymbolizer = CPLGetXMLNode(psRoot, "TextSymbolizer"); while (psTextSymbolizer && psTextSymbolizer->pszValue && strcasecmp(psTextSymbolizer->pszValue, "TextSymbolizer") == 0) { if (!psTextSymbolizer->pszValue || strcasecmp(psTextSymbolizer->pszValue, "TextSymbolizer") != 0) { psTextSymbolizer = psTextSymbolizer->psNext; continue; } if (nSymbolizer == 0) psLayer->type = MS_LAYER_ANNOTATION; msSLDParseTextSymbolizer(psTextSymbolizer, psLayer, bSymbolizer); psTextSymbolizer = psTextSymbolizer->psNext; } /* Raster symbolizer */ psRasterSymbolizer = CPLGetXMLNode(psRoot, "RasterSymbolizer"); while (psRasterSymbolizer && psRasterSymbolizer->pszValue && strcasecmp(psRasterSymbolizer->pszValue, "RasterSymbolizer") == 0) { if (!psRasterSymbolizer->pszValue || strcasecmp(psRasterSymbolizer->pszValue, "RasterSymbolizer") != 0) { psRasterSymbolizer = psRasterSymbolizer->psNext; continue; } msSLDParseRasterSymbolizer(psRasterSymbolizer, psLayer); psRasterSymbolizer = psRasterSymbolizer->psNext; psLayer->type = MS_LAYER_RASTER; } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParseLineSymbolizer(CPLXMLNode *psRoot, layerObj */ /* *psLayer) */ /* */ /* Parses the LineSymbolizer rule and creates a class in the */ /* layer. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Example of a rule : */ /* ... */ /* */ /* */ /* */ /* center-line */ /* */ /* */ /* #0000ff */ /* 5.0 */ /* 10.0 5 5 10*/ /* */ /* */ /* */ /* ... */ /************************************************************************/ int msSLDParseLineSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass) { int nClassId = 0; CPLXMLNode *psStroke=NULL, *psOffset=NULL; int iStyle = 0; if (!psRoot || !psLayer) return MS_FAILURE; psStroke = CPLGetXMLNode(psRoot, "Stroke"); if (psStroke) { if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); msSLDParseStroke(psStroke, psLayer->class[nClassId]->styles[iStyle], psLayer->map, 0); /*parse PerpendicularOffset SLD 1.1.10*/ psOffset = CPLGetXMLNode(psRoot, "PerpendicularOffset"); if (psOffset && psOffset->psChild && psOffset->psChild->pszValue) { psLayer->class[nClassId]->styles[iStyle]->offsetx = atoi(psOffset->psChild->pszValue); psLayer->class[nClassId]->styles[iStyle]->offsety = MS_STYLE_SINGLE_SIDED_OFFSET; } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParseStroke(CPLXMLNode *psStroke, styleObj */ /* *psStyle, int iColorParam) */ /* */ /* Parse Stroke content into a style object. */ /* The iColorParm is used to indicate which color object to use */ /* : */ /* 0 : for color */ /* 1 : outlinecolor */ /************************************************************************/ int msSLDParseStroke(CPLXMLNode *psStroke, styleObj *psStyle, mapObj *map, int iColorParam) { CPLXMLNode *psCssParam = NULL, *psGraphicFill=NULL; char *psStrkName = NULL; char *psColor = NULL; int nLength = 0; char *pszDashValue = NULL; if (!psStroke || !psStyle) return MS_FAILURE; /* parse css parameters */ psCssParam = CPLGetXMLNode(psStroke, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psStroke, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psStrkName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psStrkName) { if (strcasecmp(psStrkName, "stroke") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psColor = psCssParam->psChild->psNext->pszValue; if (psColor) { nLength = strlen(psColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && psColor[0] == '#') { if (iColorParam == 0) { psStyle->color.red = msHexToInt(psColor+1); psStyle->color.green = msHexToInt(psColor+3); psStyle->color.blue= msHexToInt(psColor+5); } else if (iColorParam == 1) { psStyle->outlinecolor.red = msHexToInt(psColor+1); psStyle->outlinecolor.green = msHexToInt(psColor+3); psStyle->outlinecolor.blue= msHexToInt(psColor+5); } else if (iColorParam == 2) { psStyle->backgroundcolor.red = msHexToInt(psColor+1); psStyle->backgroundcolor.green = msHexToInt(psColor+3); psStyle->backgroundcolor.blue= msHexToInt(psColor+5); } } } } else if (strcasecmp(psStrkName, "stroke-width") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { psStyle->width = atof(psCssParam->psChild->psNext->pszValue); } } else if (strcasecmp(psStrkName, "stroke-dasharray") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { int nDash = 0, i; char **aszValues = NULL; int nMaxDash; pszDashValue = msStrdup(psCssParam->psChild->psNext->pszValue); aszValues = msStringSplit(pszDashValue, ' ', &nDash); if (nDash > 0) { nMaxDash = nDash; if (nDash > MS_MAXPATTERNLENGTH) nMaxDash = MS_MAXPATTERNLENGTH; psStyle->patternlength = nMaxDash; for (i=0; ipattern[i] = atof(aszValues[i]); msFreeCharArray(aszValues, nDash); psStyle->linecap = MS_CJC_BUTT; } } } else if (strcasecmp(psStrkName, "stroke-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { if (iColorParam == 0) { psStyle->color.alpha = (int)(atof(psCssParam->psChild->psNext->pszValue)*255); } else { psStyle->outlinecolor.alpha = (int)(atof(psCssParam->psChild->psNext->pszValue)*255); } } } } psCssParam = psCssParam->psNext; } /* parse graphic fill or stroke */ /* graphic fill and graphic stroke pare parsed the same way : */ /* TODO : It seems inconsistent to me since the only diffrence */ /* between them seems to be fill (fill) or not fill (stroke). And */ /* then again the fill parameter can be used inside both elements. */ psGraphicFill = CPLGetXMLNode(psStroke, "GraphicFill"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, pszDashValue, psStyle, map, 0); psGraphicFill = CPLGetXMLNode(psStroke, "GraphicStroke"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, pszDashValue, psStyle, map, 0); if (pszDashValue) free(pszDashValue); return MS_SUCCESS; } /************************************************************************/ /* void msSLDParsePolygonSymbolizer(CPLXMLNode *psRoot, */ /* layerObj *psLayer) */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Here, the CssParameter names are fill instead of stroke and */ /* fill-opacity instead of stroke-opacity. None of the other CssParameters*/ /* in Stroke are available for filling and the default value for the fill color in this context is 50% gray (value #808080).*/ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* The default if neither an ExternalGraphic nor a Mark is specified is to use the default*/ /* mark of a square with a 50%-gray fill and a black outline, with a size of 6 pixels.*/ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* The WellKnownName element gives the well-known name of the shape of the mark.*/ /* Allowed values include at least square, circle, triangle, star, cross,*/ /* and x, though map servers may draw a different symbol instead if they don't have a*/ /* shape for all of these. The default WellKnownName is square. Renderings of these*/ /* marks may be made solid or hollow depending on Fill and Stroke elements.*/ /* */ /************************************************************************/ int msSLDParsePolygonSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass) { CPLXMLNode *psFill, *psStroke; int nClassId=0, iStyle=0; CPLXMLNode *psDisplacement=NULL, *psDisplacementX=NULL, *psDisplacementY=NULL; int nOffsetX=-1, nOffsetY=-1; if (!psRoot || !psLayer) return MS_FAILURE; /*parse displacement for SLD 1.1.0*/ psDisplacement = CPLGetXMLNode(psRoot, "Displacement"); if (psDisplacement) { psDisplacementX = CPLGetXMLNode(psDisplacement, "DisplacementX"); psDisplacementY = CPLGetXMLNode(psDisplacement, "DisplacementY"); /* psCssParam->psChild->psNext->pszValue) */ if (psDisplacementX && psDisplacementX->psChild && psDisplacementX->psChild->pszValue && psDisplacementY && psDisplacementY->psChild && psDisplacementY->psChild->pszValue) { nOffsetX = atoi(psDisplacementX->psChild->pszValue); nOffsetY = atoi(psDisplacementY->psChild->pszValue); } } psFill = CPLGetXMLNode(psRoot, "Fill"); if (psFill) { if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); msSLDParsePolygonFill(psFill, psLayer->class[nClassId]->styles[iStyle], psLayer->map); if (nOffsetX > 0 && nOffsetY > 0) { psLayer->class[nClassId]->styles[iStyle]->offsetx = nOffsetX; psLayer->class[nClassId]->styles[iStyle]->offsety = nOffsetY; } } /* stroke wich corresponds to the outilne in mapserver */ /* is drawn after the fill */ psStroke = CPLGetXMLNode(psRoot, "Stroke"); if (psStroke) { /* -------------------------------------------------------------------- */ /* there was a fill so add a style to the last class created */ /* by the fill */ /* -------------------------------------------------------------------- */ if (psFill && psLayer->numclasses > 0) { nClassId =psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); } else { if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); } msSLDParseStroke(psStroke, psLayer->class[nClassId]->styles[iStyle], psLayer->map, 1); if (nOffsetX > 0 && nOffsetY > 0) { psLayer->class[nClassId]->styles[iStyle]->offsetx = nOffsetX; psLayer->class[nClassId]->styles[iStyle]->offsety = nOffsetY; } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParsePolygonFill(CPLXMLNode *psFill, styleObj *psStyle, */ /* mapObj *map) */ /* */ /* Parse the Fill node for a polygon into a style. */ /************************************************************************/ int msSLDParsePolygonFill(CPLXMLNode *psFill, styleObj *psStyle, mapObj *map) { CPLXMLNode *psCssParam, *psGraphicFill; char *psColor=NULL, *psFillName=NULL; int nLength = 0; if (!psFill || !psStyle || !map) return MS_FAILURE; /* sets the default fill color defined in the spec #808080 */ psStyle->color.red = 128; psStyle->color.green = 128; psStyle->color.blue = 128; psCssParam = CPLGetXMLNode(psFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psFillName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psFillName) { if (strcasecmp(psFillName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psColor = psCssParam->psChild->psNext->pszValue; if (psColor) { nLength = strlen(psColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && psColor[0] == '#') { psStyle->color.red = msHexToInt(psColor+1); psStyle->color.green = msHexToInt(psColor+3); psStyle->color.blue= msHexToInt(psColor+5); } } } else if (strcasecmp(psFillName, "fill-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { psStyle->color.alpha = (int)(atof(psCssParam->psChild->psNext->pszValue)*255); } } } psCssParam = psCssParam->psNext; } /* graphic fill and graphic stroke pare parsed the same way : */ /* TODO : It seems inconsistent to me since the only diffrence */ /* between them seems to be fill (fill) or not fill (stroke). And */ /* then again the fill parameter can be used inside both elements. */ psGraphicFill = CPLGetXMLNode(psFill, "GraphicFill"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, NULL, psStyle, map, 0); psGraphicFill = CPLGetXMLNode(psFill, "GraphicStroke"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, NULL, psStyle, map, 0); return MS_SUCCESS; } /************************************************************************/ /* msSLDParseGraphicFillOrStroke */ /* */ /* Parse the GraphicFill Or GraphicStroke node : look for a */ /* Marker symbol and set the style for that symbol. */ /************************************************************************/ int msSLDParseGraphicFillOrStroke(CPLXMLNode *psRoot, char *pszDashValue, styleObj *psStyle, mapObj *map, int bPointLayer) { CPLXMLNode *psCssParam, *psGraphic, *psExternalGraphic, *psMark, *psSize; CPLXMLNode *psWellKnownName, *psStroke, *psFill; CPLXMLNode *psDisplacement=NULL, *psDisplacementX=NULL, *psDisplacementY=NULL; CPLXMLNode *psOpacity=NULL, *psRotation=NULL; char *psName=NULL, *psValue = NULL; int nLength = 0; char *pszSymbolName = NULL; int bFilled = 0; CPLXMLNode *psPropertyName=NULL; char szTmp[256]; bPointLayer=0; if (!psRoot || !psStyle || !map) return MS_FAILURE; /* ==================================================================== */ /* This a definition taken from the specification (11.3.2) : */ /* Graphics can either be referenced from an external URL in a common format (such as*/ /* GIF or SVG) or may be derived from a Mark. Multiple external URLs and marks may be*/ /* referenced with the semantic that they all provide the equivalent graphic in different*/ /* formats. */ /* */ /* For this reason, we only need to support one Mark and one */ /* ExtrnalGraphic ???? */ /* ==================================================================== */ psGraphic = CPLGetXMLNode(psRoot, "Graphic"); if (psGraphic) { /* extract symbol size */ psSize = CPLGetXMLNode(psGraphic, "Size"); if (psSize) psStyle->size = _msSLDParseSizeParameter(psSize); else { /*do not set a default for external symbols #2305*/ psExternalGraphic = CPLGetXMLNode(psGraphic, "ExternalGraphic"); if (!psExternalGraphic) psStyle->size = 6; /* default value */ } /*SLD 1.1.0 extract opacity, rotation, displacement*/ psOpacity = CPLGetXMLNode(psGraphic, "Opacity"); if (psOpacity && psOpacity->psChild && psOpacity->psChild->pszValue) psStyle->opacity = (int)(atof(psOpacity->psChild->pszValue) * 100); psRotation = CPLGetXMLNode(psGraphic, "Rotation"); if (psRotation) { psPropertyName = CPLGetXMLNode(psRotation, "PropertyName"); if (psPropertyName) { snprintf(szTmp, sizeof(szTmp), "%s", CPLGetXMLValue(psPropertyName, NULL, NULL)); psStyle->bindings[MS_STYLE_BINDING_ANGLE].item = msStrdup(szTmp); psStyle->numbindings++; } else { if (psRotation->psChild && psRotation->psChild->pszValue) psStyle->angle = atof(psRotation->psChild->pszValue); } } psDisplacement = CPLGetXMLNode(psGraphic, "Displacement"); if (psDisplacement) { psDisplacementX = CPLGetXMLNode(psDisplacement, "DisplacementX"); psDisplacementY = CPLGetXMLNode(psDisplacement, "DisplacementY"); /* psCssParam->psChild->psNext->pszValue) */ if (psDisplacementX && psDisplacementX->psChild && psDisplacementX->psChild->pszValue && psDisplacementY && psDisplacementY->psChild && psDisplacementY->psChild->pszValue) { psStyle->offsetx = atoi(psDisplacementX->psChild->pszValue); psStyle->offsety = atoi(psDisplacementY->psChild->pszValue); } } /* extract symbol */ psMark = CPLGetXMLNode(psGraphic, "Mark"); if (psMark) { pszSymbolName = NULL; psWellKnownName = CPLGetXMLNode(psMark, "WellKnownName"); if (psWellKnownName && psWellKnownName->psChild && psWellKnownName->psChild->pszValue) pszSymbolName = msStrdup(psWellKnownName->psChild->pszValue); /* default symbol is square */ if (!pszSymbolName || !*pszSymbolName || (strcasecmp(pszSymbolName, "square") != 0 && strcasecmp(pszSymbolName, "circle") != 0 && strcasecmp(pszSymbolName, "triangle") != 0 && strcasecmp(pszSymbolName, "star") != 0 && strcasecmp(pszSymbolName, "cross") != 0 && strcasecmp(pszSymbolName, "x") != 0)) { if (!pszSymbolName || !*pszSymbolName || msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_FALSE) < 0) { msFree(pszSymbolName); pszSymbolName = msStrdup("square"); } } /* check if the symbol should be filled or not */ psFill = CPLGetXMLNode(psMark, "Fill"); psStroke = CPLGetXMLNode(psMark, "Stroke"); if (psFill || psStroke) { if (psFill) bFilled = 1; else bFilled = 0; if (psFill) { psCssParam = CPLGetXMLNode(psFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psName && strcasecmp(psName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { nLength = strlen(psValue); if (nLength == 7 && psValue[0] == '#') { msSLDSetColorObject(psValue, &psStyle->color); } } } else if (psName && strcasecmp(psName, "fill-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { psStyle->color.alpha = (int)(atof(psValue)*255); } } psCssParam = psCssParam->psNext; } } if (psStroke) { psCssParam = CPLGetXMLNode(psStroke, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psStroke, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psName && strcasecmp(psName, "stroke") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { nLength = strlen(psValue); if (nLength == 7 && psValue[0] == '#') { msSLDSetColorObject(psValue, &psStyle->outlinecolor); } } } else if (psName && strcasecmp(psName, "stroke-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { psStyle->outlinecolor.alpha = (int)(atof(psValue)*255); } } else if (psName && strcasecmp(psName, "stroke-width") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { psStyle->width = atof(psValue); } } psCssParam = psCssParam->psNext; } } } /* set the default color if color is not not already set */ if ((psStyle->color.red < 0 || psStyle->color.green == -1 || psStyle->color.blue == -1) && (psStyle->outlinecolor.red == -1 || psStyle->outlinecolor.green == -1 || psStyle->outlinecolor.blue == -1)) { psStyle->color.red = 128; psStyle->color.green = 128; psStyle->color.blue = 128; } /* Get the corresponding symbol id */ psStyle->symbol = msSLDGetMarkSymbol(map, pszSymbolName, bFilled); if (psStyle->symbol > 0 && psStyle->symbol < map->symbolset.numsymbols) psStyle->symbolname = msStrdup(map->symbolset.symbol[psStyle->symbol]->name); } else { psExternalGraphic = CPLGetXMLNode(psGraphic, "ExternalGraphic"); if (psExternalGraphic) msSLDParseExternalGraphic(psExternalGraphic, psStyle, map); } msFree(pszSymbolName); } return MS_SUCCESS; } /************************************************************************/ /* msSLDGetMarkSymbol */ /* */ /* Get a Mark symbol using the name. Mark symbols can be */ /* square, circle, triangle, star, cross, x. */ /* If the symbol does not exsist add it to the symbol list. */ /************************************************************************/ int msSLDGetMarkSymbol(mapObj *map, char *pszSymbolName, int bFilled) { int nSymbolId = 0; symbolObj *psSymbol = NULL; if (!map || !pszSymbolName) return 0; if (strcasecmp(pszSymbolName, "square") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_SQUARE_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_SQUARE, MS_FALSE); } else if (strcasecmp(pszSymbolName, "circle") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CIRCLE_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CIRCLE, MS_FALSE); } else if (strcasecmp(pszSymbolName, "triangle") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_TRIANGLE_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_TRIANGLE, MS_FALSE); } else if (strcasecmp(pszSymbolName, "star") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_STAR_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_STAR, MS_FALSE); } else if (strcasecmp(pszSymbolName, "cross") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CROSS_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CROSS, MS_FALSE); } else if (strcasecmp(pszSymbolName, "x") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_X_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_X, MS_FALSE); } else { nSymbolId = msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_FALSE); } if (nSymbolId <= 0) { if( (psSymbol = msGrowSymbolSet(&(map->symbolset))) == NULL) return 0; /* returns 0 for no symbol */ nSymbolId = map->symbolset.numsymbols; map->symbolset.numsymbols++; initSymbol(psSymbol); psSymbol->inmapfile = MS_TRUE; psSymbol->sizex = 1; psSymbol->sizey = 1; if (strcasecmp(pszSymbolName, "square") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_SQUARE_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_SQUARE); psSymbol->type = MS_SYMBOL_VECTOR; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "circle") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CIRCLE_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CIRCLE); psSymbol->type = MS_SYMBOL_ELLIPSE; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->sizex = 1; psSymbol->sizey = 1; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "triangle") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_TRIANGLE_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_TRIANGLE); psSymbol->type = MS_SYMBOL_VECTOR; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "star") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_STAR_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_STAR); psSymbol->type = MS_SYMBOL_VECTOR; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.35; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.65; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.75; psSymbol->points[psSymbol->numpoints].y = 0.625; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.875; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0.75; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.125; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.25; psSymbol->points[psSymbol->numpoints].y = 0.625; psSymbol->numpoints++; } /* cross is like plus (+) since there is also X symbol ?? */ else if (strcasecmp(pszSymbolName, "cross") == 0) { /* NEVER FILL CROSS */ /* if (bFilled) */ /* psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CROSS_FILLED); */ /* else */ psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CROSS); psSymbol->type = MS_SYMBOL_VECTOR; /* if (bFilled) */ /* psSymbol->filled = MS_TRUE; */ psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = -99; psSymbol->points[psSymbol->numpoints].y = -99; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0.5; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0.5; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "x") == 0) { /* NEVER FILL X */ /* if (bFilled) */ /* psSymbol->name = msStrdup(SLD_MARK_SYMBOL_X_FILLED); */ /* else */ psSymbol->name = msStrdup(SLD_MARK_SYMBOL_X); psSymbol->type = MS_SYMBOL_VECTOR; /* if (bFilled) */ /* psSymbol->filled = MS_TRUE; */ psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = -99; psSymbol->points[psSymbol->numpoints].y = -99; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; } } return nSymbolId; } static const unsigned char PNGsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; /* 89 50 4E 47 0D 0A 1A 0A hex */ /************************************************************************/ /* msSLDGetGraphicSymbol */ /* */ /* Create a symbol entry for an inmap pixmap symbol. Returns */ /* the symbol id. */ /************************************************************************/ int msSLDGetGraphicSymbol(mapObj *map, char *pszFileName, char* extGraphicName, int nGap) { int nSymbolId = 0; symbolObj *psSymbol = NULL; if (map && pszFileName) { if( (psSymbol = msGrowSymbolSet(&(map->symbolset))) == NULL) return 0; /* returns 0 for no symbol */ nSymbolId = map->symbolset.numsymbols; map->symbolset.numsymbols++; initSymbol(psSymbol); psSymbol->inmapfile = MS_TRUE; psSymbol->type = MS_SYMBOL_PIXMAP; psSymbol->name = msStrdup(extGraphicName); psSymbol->imagepath = msStrdup(pszFileName); psSymbol->full_pixmap_path = msStrdup(pszFileName); } return nSymbolId; } /************************************************************************/ /* msSLDParsePointSymbolizer */ /* */ /* Parse point symbolizer. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /************************************************************************/ int msSLDParsePointSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass) { int nClassId = 0; int iStyle = 0; if (!psRoot || !psLayer) return MS_FAILURE; if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); msSLDParseGraphicFillOrStroke(psRoot, NULL, psLayer->class[nClassId]->styles[iStyle], psLayer->map, 1); return MS_SUCCESS; } /************************************************************************/ /* msSLDParseExternalGraphic */ /* */ /* Parse extrenal graphic node : download the symbol referneced */ /* by the URL and create a PIXMAP inmap symbol. Only GIF and */ /* PNG are supported. */ /************************************************************************/ int msSLDParseExternalGraphic(CPLXMLNode *psExternalGraphic, styleObj *psStyle, mapObj *map) { /* needed for libcurl function msHTTPGetFile in maphttp.c */ #if defined(USE_CURL) char *pszFormat = NULL; CPLXMLNode *psURL=NULL, *psFormat=NULL, *psTmp=NULL; char *pszURL=NULL; if (!psExternalGraphic || !psStyle || !map) return MS_FAILURE; psFormat = CPLGetXMLNode(psExternalGraphic, "Format"); if (psFormat && psFormat->psChild && psFormat->psChild->pszValue) pszFormat = psFormat->psChild->pszValue; /* supports GIF and PNG */ if (pszFormat && (strcasecmp(pszFormat, "GIF") == 0 || strcasecmp(pszFormat, "image/gif") == 0 || strcasecmp(pszFormat, "PNG") == 0 || strcasecmp(pszFormat, "image/png") == 0)) { /* */ psURL = CPLGetXMLNode(psExternalGraphic, "OnlineResource"); if (psURL && psURL->psChild) { psTmp = psURL->psChild; while (psTmp != NULL && psTmp->pszValue && strcasecmp(psTmp->pszValue, "xlink:href") != 0) { psTmp = psTmp->psNext; } if (psTmp && psTmp->psChild) { pszURL = (char*)psTmp->psChild->pszValue; /*external symbols using http will be automaticallly downloaded. The file should be saved in a temporary directory (msAddImageSymbol) #2305*/ psStyle->symbol = msGetSymbolIndex(&map->symbolset, pszURL, MS_TRUE); if (psStyle->symbol > 0 && psStyle->symbol < map->symbolset.numsymbols) psStyle->symbolname = msStrdup(map->symbolset.symbol[psStyle->symbol]->name); /* set the color parameter if not set. Does not make sense */ /* for pixmap but mapserver needs it. */ if (psStyle->color.red == -1 || psStyle->color.green || psStyle->color.blue) { psStyle->color.red = 0; psStyle->color.green = 0; psStyle->color.blue = 0; } } } } return MS_SUCCESS; #else return MS_FAILURE; #endif } /************************************************************************/ /* msSLDParseTextSymbolizer */ /* */ /* Parse text symbolizer. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Four types of CssParameter are allowed, font-family, font-style,*/ /* fontweight,and font-size. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* The coordinates are given as two floating-point numbers in */ /* the AnchorPointX and AnchorPointY elements each with values */ /* between 0.0 and 1.0 inclusive. The bounding box of the label */ /* to be rendered is considered to be in a coorindate space */ /* from 0.0 (lowerleft corner) to 1.0 (upper-right corner), and */ /* the anchor position is specified as a point in this */ /* space. The default point is X=0, Y=0.5, which is at the */ /* middle height of the lefthand side of the label. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /************************************************************************/ int msSLDParseTextSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bOtherSymboliser) { int nStyleId=0, nClassId=0; if (!psRoot || !psLayer) return MS_FAILURE; if (!bOtherSymboliser) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); nStyleId = 0; } else { nClassId = psLayer->numclasses - 1; if (nClassId >= 0)/* should always be true */ nStyleId = psLayer->class[nClassId]->numstyles -1; } if (nStyleId >= 0 && nClassId >= 0) /* should always be true */ msSLDParseTextParams(psRoot, psLayer, psLayer->class[nClassId]); return MS_SUCCESS; } /************************************************************************/ /* msSLDParseRasterSymbolizer */ /* */ /* Supports the ColorMap parameter in a Raster Symbolizer. In */ /* the ColorMap, only color and quantity are used here. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* SLD 1.1 */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /************************************************************************/ int msSLDParseRasterSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer) { CPLXMLNode *psColorMap = NULL, *psColorEntry = NULL, *psOpacity=NULL; char *pszColor=NULL, *pszQuantity=NULL; char *pszPreviousColor=NULL, *pszPreviousQuality=NULL; colorObj sColor; char szExpression[100]; int nClassId = 0; double dfOpacity = 1.0; char *pszLabel = NULL, *pszPreviousLabel = NULL; char *pch = NULL, *pchPrevious=NULL; CPLXMLNode *psNode=NULL, *psCategorize=NULL; char *pszTmp = NULL; int nValues=0, nThresholds=0; int i,nMaxValues= 100, nMaxThreshold=100; if (!psRoot || !psLayer) return MS_FAILURE; /* ==================================================================== */ /* The default opacity value is 0 : we set it here to -1 */ /* so that when testing the values in msSLDApplySLD (to be */ /* applied on the layer), we can assume that a value of 0 comes */ /* from the sld. */ /* ==================================================================== */ psLayer->opacity = -1; psOpacity = CPLGetXMLNode(psRoot, "Opacity"); if (psOpacity) { if (psOpacity->psChild && psOpacity->psChild->pszValue) dfOpacity = atof(psOpacity->psChild->pszValue); /* values in sld goes from 0.0 (for transparent) to 1.0 (for full opacity); */ if (dfOpacity >=0.0 && dfOpacity <=1.0) psLayer->opacity = (int)(dfOpacity * 100); else { msSetError(MS_WMSERR, "Invalid opacity value. Values should be between 0.0 and 1.0", "msSLDParseRasterSymbolizer()"); return MS_FAILURE; } } psColorMap = CPLGetXMLNode(psRoot, "ColorMap"); if (psColorMap) { psColorEntry = CPLGetXMLNode(psColorMap, "ColorMapEntry"); if (psColorEntry) { /*SLD 1.0*/ while (psColorEntry && psColorEntry->pszValue && strcasecmp(psColorEntry->pszValue, "ColorMapEntry") == 0) { pszColor = (char *)CPLGetXMLValue(psColorEntry, "color", NULL); pszQuantity = (char *)CPLGetXMLValue(psColorEntry, "quantity", NULL); pszLabel = (char *)CPLGetXMLValue(psColorEntry, "label", NULL); if (pszColor && pszQuantity) { if (pszPreviousColor && pszPreviousQuality) { if (strlen(pszPreviousColor) == 7 && pszPreviousColor[0] == '#' && strlen(pszColor) == 7 && pszColor[0] == '#') { sColor.red = msHexToInt(pszPreviousColor+1); sColor.green= msHexToInt(pszPreviousColor+3); sColor.blue = msHexToInt(pszPreviousColor+5); /* pszQuantity and pszPreviousQuality may be integer or float */ pchPrevious=strchr(pszPreviousQuality,'.'); pch=strchr(pszQuantity,'.'); if (pchPrevious==NULL && pch==NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d AND [pixel] < %d)", atoi(pszPreviousQuality), atoi(pszQuantity)); } else if (pchPrevious != NULL && pch==NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %f AND [pixel] < %d)", atof(pszPreviousQuality), atoi(pszQuantity)); } else if (pchPrevious == NULL && pch != NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d AND [pixel] < %f)", atoi(pszPreviousQuality), atof(pszQuantity)); } else { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %f AND [pixel] < %f)", atof(pszPreviousQuality), atof(pszQuantity)); } if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; else { initClass(psLayer->class[psLayer->numclasses]); psLayer->numclasses++; nClassId = psLayer->numclasses-1; /*set the class name using the label. If label not defined set it with the quantity*/ if (pszPreviousLabel) psLayer->class[nClassId]->name = msStrdup(pszPreviousLabel); else psLayer->class[nClassId]->name = msStrdup(pszPreviousQuality); msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); psLayer->class[nClassId]->styles[0]->color.red = sColor.red; psLayer->class[nClassId]->styles[0]->color.green = sColor.green; psLayer->class[nClassId]->styles[0]->color.blue = sColor.blue; if (psLayer->classitem && strcasecmp(psLayer->classitem, "[pixel]") != 0) free(psLayer->classitem); psLayer->classitem = msStrdup("[pixel]"); msLoadExpressionString(&psLayer->class[nClassId]->expression, szExpression); } } else { msSetError(MS_WMSERR, "Invalid ColorMap Entry.", "msSLDParseRasterSymbolizer()"); return MS_FAILURE; } } pszPreviousColor = pszColor; pszPreviousQuality = pszQuantity; pszPreviousLabel = pszLabel; } psColorEntry = psColorEntry->psNext; } /* do the last Color Map Entry */ if (pszColor && pszQuantity) { if (strlen(pszColor) == 7 && pszColor[0] == '#') { sColor.red = msHexToInt(pszColor+1); sColor.green= msHexToInt(pszColor+3); sColor.blue = msHexToInt(pszColor+5); /* pszQuantity may be integer or float */ pch=strchr(pszQuantity,'.'); if (pch==NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] = %d)", atoi(pszQuantity)); } else { snprintf(szExpression, sizeof(szExpression), "([pixel] = %f)", atof(pszQuantity)); } if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; else { initClass(psLayer->class[psLayer->numclasses]); psLayer->numclasses++; nClassId = psLayer->numclasses-1; msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); if (pszLabel) psLayer->class[nClassId]->name = msStrdup(pszLabel); else psLayer->class[nClassId]->name = msStrdup(pszQuantity); psLayer->class[nClassId]->numstyles = 1; psLayer->class[nClassId]->styles[0]->color.red = sColor.red; psLayer->class[nClassId]->styles[0]->color.green = sColor.green; psLayer->class[nClassId]->styles[0]->color.blue = sColor.blue; if (psLayer->classitem && strcasecmp(psLayer->classitem, "[pixel]") != 0) free(psLayer->classitem); psLayer->classitem = msStrdup("[pixel]"); msLoadExpressionString(&psLayer->class[nClassId]->expression, szExpression); } } } } else if ((psCategorize = CPLGetXMLNode(psColorMap, "Categorize"))) { char** papszValues = (char **)malloc(sizeof(char*)*nMaxValues); char** papszThresholds = (char **)malloc(sizeof(char*)*nMaxThreshold); psNode = CPLGetXMLNode(psCategorize, "Value"); while (psNode && psNode->pszValue && psNode->psChild && psNode->psChild->pszValue) { if (strcasecmp(psNode->pszValue, "Value") == 0) { papszValues[nValues] = psNode->psChild->pszValue; nValues++; if (nValues == nMaxValues) { nMaxValues +=100; papszValues = (char **)realloc(papszValues, sizeof(char*)*nMaxValues); } } else if (strcasecmp(psNode->pszValue, "Threshold") == 0) { papszThresholds[nThresholds] = psNode->psChild->pszValue; nThresholds++; if (nValues == nMaxThreshold) { nMaxThreshold += 100; papszThresholds = (char **)realloc(papszThresholds, sizeof(char*)*nMaxThreshold); } } psNode = psNode->psNext; } if (nValues == nThresholds+1) { /*free existing classes*/ for(i=0; inumclasses; i++) { if (psLayer->class[i] != NULL) { psLayer->class[i]->layer=NULL; if ( freeClass(psLayer->class[i]) == MS_SUCCESS ) { msFree(psLayer->class[i]); psLayer->class[i]=NULL; } } } psLayer->numclasses=0; for (i=0; i= %f AND [pixel] < %f)", atof(papszThresholds[i-1]), atof(papszThresholds[i])); else snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d AND [pixel] < %d)", atoi(papszThresholds[i-1]), atoi(papszThresholds[i])); } else { if (strchr(papszThresholds[i-1],'.')) snprintf(szExpression, sizeof(szExpression), "([pixel] >= %f)", atof(papszThresholds[i-1])); else snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d)", atoi(papszThresholds[i-1])); } if (msGrowLayerClasses(psLayer)) { initClass(psLayer->class[psLayer->numclasses]); psLayer->numclasses++; nClassId = psLayer->numclasses-1; msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); psLayer->class[nClassId]->numstyles = 1; psLayer->class[nClassId]->styles[0]->color.red = sColor.red; psLayer->class[nClassId]->styles[0]->color.green = sColor.green; psLayer->class[nClassId]->styles[0]->color.blue = sColor.blue; if (psLayer->classitem && strcasecmp(psLayer->classitem, "[pixel]") != 0) free(psLayer->classitem); psLayer->classitem = msStrdup("[pixel]"); msLoadExpressionString(&psLayer->class[nClassId]->expression, szExpression); } } } } free(papszValues); free(papszThresholds); } else { msSetError(MS_WMSERR, "Invalid SLD document. msSLDParseRaster", ""); return MS_FAILURE; } } return MS_SUCCESS; } /************************************************************************/ /* msSLDParseTextParams */ /* */ /* Parse text paramaters like font, placement and color. */ /************************************************************************/ int msSLDParseTextParams(CPLXMLNode *psRoot, layerObj *psLayer, classObj *psClass) { char szFontName[100]; double dfFontSize = 10; int bFontSet = 0; CPLXMLNode *psLabel=NULL, *psFont=NULL; CPLXMLNode *psCssParam = NULL; char *pszName=NULL, *pszFontFamily=NULL, *pszFontStyle=NULL; char *pszFontWeight=NULL; CPLXMLNode *psLabelPlacement=NULL, *psPointPlacement=NULL, *psLinePlacement=NULL; CPLXMLNode *psFill = NULL, *psPropertyName=NULL, *psHalo=NULL, *psHaloRadius=NULL, *psHaloFill=NULL; int nLength = 0; char *pszColor = NULL; /* char *pszItem = NULL; */ CPLXMLNode *psTmpNode = NULL; char *pszClassText = NULL; char szTmp[100]; labelObj *psLabelObj = NULL; szFontName[0]='\0'; if (!psRoot || !psClass || !psLayer) return MS_FAILURE; if(psClass->numlabels == 0) { if(msGrowClassLabels(psClass) == NULL) return(MS_FAILURE); initLabel(psClass->labels[0]); psClass->numlabels++; } psLabelObj = psClass->labels[0]; /*set the angle by default to auto. the angle can be modified Label Placement #2806*/ psLabelObj->anglemode = MS_AUTO; /* label */ /* support literal expression and propertyname - - Bug 1857 */ psLabel = CPLGetXMLNode(psRoot, "Label"); if (psLabel ) { psTmpNode = psLabel->psChild; psPropertyName = CPLGetXMLNode(psLabel, "PropertyName"); if (psPropertyName) { while (psTmpNode) { /* open bracket to get valid expression */ if (pszClassText == NULL) pszClassText = msStringConcatenate(pszClassText, "("); if (psTmpNode->eType == CXT_Text && psTmpNode->pszValue) { pszClassText = msStringConcatenate(pszClassText, psTmpNode->pszValue); } else if (psTmpNode->eType == CXT_Element && strcasecmp(psTmpNode->pszValue,"PropertyName") ==0 && CPLGetXMLValue(psTmpNode, NULL, NULL)) { snprintf(szTmp, sizeof(szTmp), "\"[%s]\"", CPLGetXMLValue(psTmpNode, NULL, NULL)); pszClassText = msStringConcatenate(pszClassText, szTmp); } psTmpNode = psTmpNode->psNext; } /* close bracket to get valid expression */ if (pszClassText != NULL) pszClassText = msStringConcatenate(pszClassText, ")"); } else { /* supports - */ if (psLabel->psChild && psLabel->psChild->pszValue) { pszClassText = msStringConcatenate(pszClassText, "(\"["); pszClassText = msStringConcatenate(pszClassText, psLabel->psChild->pszValue); pszClassText = msStringConcatenate(pszClassText, "]\")"); } } if (pszClassText) { /* pszItem) */ msLoadExpressionString(&psClass->text, pszClassText); free(pszClassText); /* font */ psFont = CPLGetXMLNode(psRoot, "Font"); if (psFont) { psCssParam = CPLGetXMLNode(psFont, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFont, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { pszName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (pszName) { if (strcasecmp(pszName, "font-family") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszFontFamily = psCssParam->psChild->psNext->pszValue; } /* normal, italic, oblique */ else if (strcasecmp(pszName, "font-style") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszFontStyle = psCssParam->psChild->psNext->pszValue; } /* normal or bold */ else if (strcasecmp(pszName, "font-weight") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszFontWeight = psCssParam->psChild->psNext->pszValue; } /* default is 10 pix */ else if (strcasecmp(pszName, "font-size") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) dfFontSize = atof(psCssParam->psChild->psNext->pszValue); if (dfFontSize <=0.0) dfFontSize = 10.0; } } psCssParam = psCssParam->psNext; } } /* -------------------------------------------------------------------- */ /* build the font name using the font font-family, font-style */ /* and font-weight. The name building uses a - between these */ /* parameters and the resulting name is compared to the list of */ /* available fonts. If the name exists, it will be used else we */ /* go to the bitmap fonts. */ /* -------------------------------------------------------------------- */ if (pszFontFamily) { snprintf(szFontName, sizeof(szFontName), "%s", pszFontFamily); if (pszFontWeight && strcasecmp(pszFontWeight, "normal") != 0) { strlcat(szFontName, "-", sizeof(szFontName)); strlcat(szFontName, pszFontWeight, sizeof(szFontName)); } if (pszFontStyle && strcasecmp(pszFontStyle, "normal") != 0) { strlcat(szFontName, "-", sizeof(szFontName)); strlcat(szFontName, pszFontStyle, sizeof(szFontName)); } if ((msLookupHashTable(&(psLayer->map->fontset.fonts), szFontName) !=NULL)) { bFontSet = 1; psLabelObj->font = msStrdup(szFontName); psLabelObj->type = MS_TRUETYPE; psLabelObj->size = dfFontSize; } } if (!bFontSet) { psLabelObj->type = MS_BITMAP; psLabelObj->size = MS_MEDIUM; } /* -------------------------------------------------------------------- */ /* parse the label placement. */ /* -------------------------------------------------------------------- */ psLabelPlacement = CPLGetXMLNode(psRoot, "LabelPlacement"); if (psLabelPlacement) { psPointPlacement = CPLGetXMLNode(psLabelPlacement, "PointPlacement"); psLinePlacement = CPLGetXMLNode(psLabelPlacement, "LinePlacement"); if (psPointPlacement) ParseTextPointPlacement(psPointPlacement, psClass); if (psLinePlacement) ParseTextLinePlacement(psLinePlacement, psClass); } /* -------------------------------------------------------------------- */ /* parse the halo parameter. */ /* -------------------------------------------------------------------- */ psHalo = CPLGetXMLNode(psRoot, "Halo"); if (psHalo) { psHaloRadius = CPLGetXMLNode(psHalo, "Radius"); if (psHaloRadius && psHaloRadius->psChild && psHaloRadius->psChild->pszValue) psLabelObj->outlinewidth = atoi(psHaloRadius->psChild->pszValue); psHaloFill = CPLGetXMLNode(psHalo, "Fill"); if (psHaloFill) { psCssParam = CPLGetXMLNode(psHaloFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psHaloFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { pszName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (pszName) { if (strcasecmp(pszName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszColor = psCssParam->psChild->psNext->pszValue; if (pszColor) { nLength = strlen(pszColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && pszColor[0] == '#') { psLabelObj->outlinecolor.red = msHexToInt(pszColor+1); psLabelObj->outlinecolor.green = msHexToInt(pszColor+3); psLabelObj->outlinecolor.blue = msHexToInt(pszColor+5); } } } } psCssParam = psCssParam->psNext; } } } /* -------------------------------------------------------------------- */ /* Parse the color */ /* -------------------------------------------------------------------- */ psFill = CPLGetXMLNode(psRoot, "Fill"); if (psFill) { psCssParam = CPLGetXMLNode(psFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { pszName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (pszName) { if (strcasecmp(pszName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszColor = psCssParam->psChild->psNext->pszValue; if (pszColor) { nLength = strlen(pszColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && pszColor[0] == '#') { psLabelObj->color.red = msHexToInt(pszColor+1); psLabelObj->color.green = msHexToInt(pszColor+3); psLabelObj->color.blue = msHexToInt(pszColor+5); } } } } psCssParam = psCssParam->psNext; } } }/* labelitem */ } return MS_SUCCESS; } /************************************************************************/ /* ParseTextPointPlacement */ /* */ /* point placement node for the text symbolizer. */ /************************************************************************/ int ParseTextPointPlacement(CPLXMLNode *psRoot, classObj *psClass) { CPLXMLNode *psAnchor, *psAnchorX, *psAnchorY; double dfAnchorX=0, dfAnchorY=0; CPLXMLNode *psDisplacement, *psDisplacementX, *psDisplacementY; CPLXMLNode *psRotation=NULL, *psPropertyName=NULL; char szTmp[100]; labelObj *psLabelObj = NULL; if (!psRoot || !psClass) return MS_FAILURE; if(psClass->numlabels == 0) { if(msGrowClassLabels(psClass) == NULL) return(MS_FAILURE); initLabel(psClass->labels[0]); psClass->numlabels++; } psLabelObj = psClass->labels[0]; /* init the label with the default position */ psLabelObj->position = MS_CL; /* -------------------------------------------------------------------- */ /* parse anchor point. see function msSLDParseTextSymbolizer */ /* for documentation. */ /* -------------------------------------------------------------------- */ psAnchor = CPLGetXMLNode(psRoot, "AnchorPoint"); if (psAnchor) { psAnchorX = CPLGetXMLNode(psAnchor, "AnchorPointX"); psAnchorY = CPLGetXMLNode(psAnchor, "AnchorPointY"); /* psCssParam->psChild->psNext->pszValue) */ if (psAnchorX && psAnchorX->psChild && psAnchorX->psChild->pszValue && psAnchorY && psAnchorY->psChild && psAnchorY->psChild->pszValue) { dfAnchorX = atof(psAnchorX->psChild->pszValue); dfAnchorY = atof(psAnchorY->psChild->pszValue); if ((dfAnchorX == 0 || dfAnchorX == 0.5 || dfAnchorX == 1) && (dfAnchorY == 0 || dfAnchorY == 0.5 || dfAnchorY == 1)) { if (dfAnchorX == 0 && dfAnchorY == 0) psLabelObj->position = MS_LL; if (dfAnchorX == 0 && dfAnchorY == 0.5) psLabelObj->position = MS_CL; if (dfAnchorX == 0 && dfAnchorY == 1) psLabelObj->position = MS_UL; if (dfAnchorX == 0.5 && dfAnchorY == 0) psLabelObj->position = MS_LC; if (dfAnchorX == 0.5 && dfAnchorY == 0.5) psLabelObj->position = MS_CC; if (dfAnchorX == 0.5 && dfAnchorY == 1) psLabelObj->position = MS_UC; if (dfAnchorX == 1 && dfAnchorY == 0) psLabelObj->position = MS_LR; if (dfAnchorX == 1 && dfAnchorY == 0.5) psLabelObj->position = MS_CR; if (dfAnchorX == 1 && dfAnchorY == 1) psLabelObj->position = MS_UR; } } } /* -------------------------------------------------------------------- */ /* Parse displacement */ /* -------------------------------------------------------------------- */ psDisplacement = CPLGetXMLNode(psRoot, "Displacement"); if (psDisplacement) { psDisplacementX = CPLGetXMLNode(psDisplacement, "DisplacementX"); psDisplacementY = CPLGetXMLNode(psDisplacement, "DisplacementY"); /* psCssParam->psChild->psNext->pszValue) */ if (psDisplacementX && psDisplacementX->psChild && psDisplacementX->psChild->pszValue && psDisplacementY && psDisplacementY->psChild && psDisplacementY->psChild->pszValue) { psLabelObj->offsetx = atoi(psDisplacementX->psChild->pszValue); psLabelObj->offsety = atoi(psDisplacementY->psChild->pszValue); } } /* -------------------------------------------------------------------- */ /* parse rotation. */ /* -------------------------------------------------------------------- */ psRotation = CPLGetXMLNode(psRoot, "Rotation"); if (psRotation) { psPropertyName = CPLGetXMLNode(psRotation, "PropertyName"); if (psPropertyName) { snprintf(szTmp, sizeof(szTmp), "%s", CPLGetXMLValue(psPropertyName, NULL, NULL)); psLabelObj->bindings[MS_LABEL_BINDING_ANGLE].item = msStrdup(szTmp); psLabelObj->numbindings++; } else { if (psRotation->psChild && psRotation->psChild->pszValue) psLabelObj->angle = atof(psRotation->psChild->pszValue); } } return MS_SUCCESS; } /************************************************************************/ /* ParseTextLinePlacement */ /* */ /* Lineplacement node fro the text symbolizer. */ /************************************************************************/ int ParseTextLinePlacement(CPLXMLNode *psRoot, classObj *psClass) { CPLXMLNode *psOffset = NULL, *psAligned=NULL; labelObj *psLabelObj = NULL; if (!psRoot || !psClass) return MS_FAILURE; if(psClass->numlabels == 0) { if(msGrowClassLabels(psClass) == NULL) return(MS_FAILURE); initLabel(psClass->labels[0]); psClass->numlabels++; } psLabelObj = psClass->labels[0]; /*if there is a line placement, we will assume that the best setting for mapserver would be for the text to follow the line #2806*/ psLabelObj->anglemode = MS_FOLLOW; /*sld 1.1.0 has a parameter IsAligned. default value is true*/ psAligned = CPLGetXMLNode(psRoot, "IsAligned"); if (psAligned && psAligned->psChild && psAligned->psChild->pszValue && strcasecmp(psAligned->psChild->pszValue, "false") == 0) { psLabelObj->anglemode = MS_NONE; } psOffset = CPLGetXMLNode(psRoot, "PerpendicularOffset"); if (psOffset && psOffset->psChild && psOffset->psChild->pszValue) { psLabelObj->offsetx = atoi(psOffset->psChild->pszValue); psLabelObj->offsety = MS_LABEL_PERPENDICULAR_OFFSET; /*if there is a PerpendicularOffset, we will assume that the best setting for mapserver would be to use angle=0 and the the offset #2806*/ /* since sld 1.1.0 introduces the IsAligned parameter, only set the angles if the parameter is not set*/ if (!psAligned) { psLabelObj->anglemode = MS_NONE; psLabelObj->offsety = psLabelObj->offsetx; } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDSetColorObject(char *psHexColor, colorObj */ /* *psColor) */ /* */ /* Utility function to exctract rgb values from an hexadecimal */ /* color string (format is : #aaff08) and set it in the color */ /* object. */ /************************************************************************/ int msSLDSetColorObject(char *psHexColor, colorObj *psColor) { if (psHexColor && psColor && strlen(psHexColor)== 7 && psHexColor[0] == '#') { psColor->red = msHexToInt(psHexColor+1); psColor->green = msHexToInt(psHexColor+3); psColor->blue= msHexToInt(psHexColor+5); } return MS_SUCCESS; } #endif /* -------------------------------------------------------------------- */ /* client sld support functions */ /* -------------------------------------------------------------------- */ /************************************************************************/ /* msSLDGenerateSLD(mapObj *map, int iLayer) */ /* */ /* Return an SLD document for all layers that are on or */ /* default. The second argument should be set to -1 to genarte */ /* on all layers. Or set to the layer index to generate an SLD */ /* for a specific layer. */ /* */ /* The caller should free the returned string. */ /************************************************************************/ char *msSLDGenerateSLD(mapObj *map, int iLayer, const char *pszVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) #ifdef USE_OGR char szTmp[500]; int i = 0; char *pszTmp = NULL; char *pszSLD = NULL; char *schemalocation = NULL; int sld_version = OWS_VERSION_NOTSET; sld_version = msOWSParseVersionString(pszVersion); if (sld_version == OWS_VERSION_NOTSET || (sld_version!= OWS_1_0_0 && sld_version!= OWS_1_1_0)) sld_version = OWS_1_0_0; if (map) { schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if (sld_version == OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "\n",schemalocation ); else snprintf(szTmp, sizeof(szTmp), "\n", schemalocation); free(schemalocation); pszSLD = msStringConcatenate(pszSLD, szTmp); if (iLayer < 0 || iLayer > map->numlayers -1) { for (i=0; inumlayers; i++) { pszTmp = msSLDGenerateSLDLayer(GET_LAYER(map, i), sld_version); if (pszTmp) { pszSLD= msStringConcatenate(pszSLD, pszTmp); free(pszTmp); } } } else { pszTmp = msSLDGenerateSLDLayer(GET_LAYER(map, iLayer), sld_version); if (pszTmp) { pszSLD = msStringConcatenate(pszSLD, pszTmp); free(pszTmp); } } snprintf(szTmp, sizeof(szTmp), "%s", "\n"); pszSLD = msStringConcatenate(pszSLD, szTmp); } return pszSLD; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDGenerateSLD()"); return NULL; #endif /* USE_OGR */ #else msSetError(MS_MISCERR, "OWS support is not available.", "msSLDGenerateSLDLayer()"); return NULL; #endif } /************************************************************************/ /* msSLDGetGraphicSLD */ /* */ /* Get an SLD for a style containg a symbol (Mark or external). */ /************************************************************************/ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer, int bNeedMarkSybol, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; int nSymbol = -1; symbolObj *psSymbol = NULL; char szTmp[512]; char *pszURL = NULL; char szFormat[4]; int i = 0, nLength = 0; int bFillColor = 0, bColorAvailable=0; int bGenerateDefaultSymbol = 0; char *pszSymbolName= NULL; char sNameSpace[10]; char sCssParam[30]; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sCssParam, "se:SvgParameter"); else strcpy(sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); if (psStyle && psLayer && psLayer->map) { nSymbol = -1; if (psStyle->symbol > 0) nSymbol = psStyle->symbol; else if (psStyle->symbolname) nSymbol = msGetSymbolIndex(&psLayer->map->symbolset, psStyle->symbolname, MS_FALSE); bGenerateDefaultSymbol = 0; if (bNeedMarkSybol && (nSymbol <=0 || nSymbol >= psLayer->map->symbolset.numsymbols)) bGenerateDefaultSymbol = 1; if (nSymbol > 0 && nSymbol < psLayer->map->symbolset.numsymbols) { psSymbol = psLayer->map->symbolset.symbol[nSymbol]; if (psSymbol->type == MS_SYMBOL_VECTOR || psSymbol->type == MS_SYMBOL_ELLIPSE) { /* Mark symbol */ if (psSymbol->name) { if (strcasecmp(psSymbol->name, "square") == 0 || strcasecmp(psSymbol->name, "circle") == 0 || strcasecmp(psSymbol->name, "triangle") == 0 || strcasecmp(psSymbol->name, "star") == 0 || strcasecmp(psSymbol->name, "cross") == 0 || strcasecmp(psSymbol->name, "x") == 0) pszSymbolName = msStrdup(psSymbol->name); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_square", 22) == 0) pszSymbolName = msStrdup("square"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_triangle", 24) == 0) pszSymbolName = msStrdup("triangle"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_circle", 22) == 0) pszSymbolName = msStrdup("circle"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_star", 20) == 0) pszSymbolName = msStrdup("star"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_cross", 21) == 0) pszSymbolName = msStrdup("cross"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_x", 17) == 0) pszSymbolName = msStrdup("X"); if (pszSymbolName) { colorObj sTmpColor; snprintf(szTmp, sizeof(szTmp), "<%sGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sMark>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sWellKnownName>%s\n", sNameSpace, pszSymbolName, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) { sTmpColor.red = psStyle->color.red; sTmpColor.green = psStyle->color.green; sTmpColor.blue = psStyle->color.blue; bFillColor =1; } else if (psStyle->outlinecolor.red != -1 && psStyle->outlinecolor.green != -1 && psStyle->outlinecolor.blue != -1) { sTmpColor.red = psStyle->outlinecolor.red; sTmpColor.green = psStyle->outlinecolor.green; sTmpColor.blue = psStyle->outlinecolor.blue; bFillColor = 0; } else { sTmpColor.red = 128; sTmpColor.green = 128; sTmpColor.blue = 128; bFillColor =1; } if (psLayer->type == MS_LAYER_POINT) { if (psSymbol->filled || bFillColor) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%02x%02x%02x\n", sCssParam,sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } else { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%02x%02x%02x\n", sCssParam, sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } } else { if (bFillColor) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%02x%02x%02x\n", sCssParam, sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } else { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%02x%02x%02x\n", sCssParam, sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } } pszSLD = msStringConcatenate(pszSLD, szTmp); if ((psLayer->type == MS_LAYER_POINT && psSymbol->filled) || bFillColor) snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); else snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->size > 0) { snprintf(szTmp, sizeof(szTmp), "<%sSize>%g\n", sNameSpace, psStyle->size, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (pszSymbolName) free(pszSymbolName); } } else bGenerateDefaultSymbol =1; } else if (psSymbol->type == MS_SYMBOL_PIXMAP) { if (psSymbol->name) { pszURL = msLookupHashTable(&(psLayer->metadata), "WMS_SLD_SYMBOL_URL"); if (!pszURL) pszURL = msLookupHashTable(&(psLayer->map->web.metadata), "WMS_SLD_SYMBOL_URL"); if (pszURL) { snprintf(szTmp, sizeof(szTmp), "<%sGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sExternalGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sOnlineResource xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:type=\"simple\" xlink:href=\"%s%s\"/>\n", sNameSpace, pszURL,psSymbol->imagepath); pszSLD = msStringConcatenate(pszSLD, szTmp); /* TODO : extract format from symbol */ szFormat[0] = '\0'; nLength = strlen(psSymbol->imagepath); if (nLength > 3) { for (i=0; i<=2; i++) szFormat[2-i] = psSymbol->imagepath[nLength-1-i]; szFormat[3] = '\0'; } if (strlen(szFormat) > 0 && ((strcasecmp (szFormat, "GIF") == 0) || (strcasecmp (szFormat, "PNG") == 0))) { if (strcasecmp (szFormat, "GIF") == 0) snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/gif\n", sNameSpace, sNameSpace); else snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/png\n", sNameSpace, sNameSpace); } else snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s\n", "image/gif", sNameSpace, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->size > 0) snprintf(szTmp, sizeof(szTmp), "<%sSize>%g\n", sNameSpace, psStyle->size, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } } } } if (bGenerateDefaultSymbol) { /* genrate a default square symbol */ snprintf(szTmp, sizeof(szTmp), "<%sGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sMark>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sWellKnownName>%s\n", sNameSpace, "square", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); bColorAvailable = 0; if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%02x%02x%02x\n", sCssParam, psStyle->color.red, psStyle->color.green, psStyle->color.blue, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); bColorAvailable = 1; } if (psStyle->outlinecolor.red != -1 && psStyle->outlinecolor.green != -1 && psStyle->outlinecolor.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"Stroke\">#%02x%02x%02x\n", sCssParam, psStyle->outlinecolor.red, psStyle->outlinecolor.green, psStyle->outlinecolor.blue, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); bColorAvailable = 1; } if (!bColorAvailable) { /* default color */ snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">%s\n", sCssParam, "#808080", sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->size > 0) snprintf(szTmp, sizeof(szTmp), "<%sSize>%g\n", sNameSpace, psStyle->size, sNameSpace); else snprintf(szTmp, sizeof(szTmp), "<%sSize>%d\n", sNameSpace,1,sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } } return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGenerateLineSLD */ /* */ /* Generate SLD for a Line layer. */ /************************************************************************/ char *msSLDGenerateLineSLD(styleObj *psStyle, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; char szTmp[100]; char szHexColor[7]; int nSymbol = -1; int i = 0; double dfSize = 1.0; char *pszDashArray = NULL; char *pszGraphicSLD = NULL; char sCssParam[30]; char sNameSpace[10]; if ( msCheckParentPointer(psLayer->map,"map")==MS_FAILURE ) return NULL; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy( sCssParam, "se:SvgParameter"); else strcpy( sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); snprintf(szTmp, sizeof(szTmp), "<%sLineSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 0, nVersion); if (pszGraphicSLD) { snprintf(szTmp, sizeof(szTmp), "<%sGraphicStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); free(pszGraphicSLD); pszGraphicSLD = NULL; } if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) sprintf(szHexColor,"%02x%02x%02x",psStyle->color.red, psStyle->color.green,psStyle->color.blue); else sprintf(szHexColor,"%02x%02x%02x",psStyle->outlinecolor.red, psStyle->outlinecolor.green,psStyle->outlinecolor.blue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); if(psStyle->color.alpha != 255 && psStyle->color.alpha!=-1) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-opacity\">%.2f\n", sCssParam, (float)psStyle->color.alpha/255.0, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } nSymbol = -1; if (psStyle->symbol >= 0) nSymbol = psStyle->symbol; else if (psStyle->symbolname) nSymbol = msGetSymbolIndex(&psLayer->map->symbolset, psStyle->symbolname, MS_FALSE); if (nSymbol <0) dfSize = 1.0; else { if (psStyle->size > 0) dfSize = psStyle->size; else if (psStyle->width > 0) dfSize = psStyle->width; else dfSize = 1; } snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-width\">%.2f\n", sCssParam, dfSize, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); /* -------------------------------------------------------------------- */ /* dash array */ /* -------------------------------------------------------------------- */ if (psStyle->patternlength > 0) { for (i=0; ipatternlength; i++) { snprintf(szTmp, sizeof(szTmp), "%.2f ", psStyle->pattern[i]); pszDashArray = msStringConcatenate(pszDashArray, szTmp); } snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-dasharray\">%s\n", sCssParam, pszDashArray, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGeneratePolygonSLD */ /* */ /* Generate SLD for a Polygon layer. */ /************************************************************************/ char *msSLDGeneratePolygonSLD(styleObj *psStyle, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char szTmp[100]; char *pszSLD = NULL; char szHexColor[7]; char *pszGraphicSLD = NULL; double dfSize; char sCssParam[30]; char sNameSpace[10]; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sCssParam, "se:SvgParameter"); else strcpy(sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); snprintf(szTmp, sizeof(szTmp), "<%sPolygonSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* fill */ if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 0, nVersion); if (pszGraphicSLD) { snprintf(szTmp, sizeof(szTmp), "<%sGraphicFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); free(pszGraphicSLD); pszGraphicSLD = NULL; } sprintf(szHexColor,"%02x%02x%02x",psStyle->color.red, psStyle->color.green,psStyle->color.blue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); if(psStyle->color.alpha != 255 && psStyle->color.alpha!=-1) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill-opacity\">%.2f\n", sCssParam, (float)psStyle->color.alpha/255, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } /* stroke */ if (psStyle->outlinecolor.red != -1 && psStyle->outlinecolor.green != -1 && psStyle->outlinecolor.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* If there is a symbol to be used for sroke, the color in the */ /* style sholud be set to -1. Else It won't apply here. */ if (psStyle->color.red == -1 && psStyle->color.green == -1 && psStyle->color.blue == -1) { pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 0, nVersion); if (pszGraphicSLD) { snprintf(szTmp, sizeof(szTmp), "<%sGraphicFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); free(pszGraphicSLD); pszGraphicSLD = NULL; } } sprintf(szHexColor,"%02x%02x%02x",psStyle->outlinecolor.red, psStyle->outlinecolor.green, psStyle->outlinecolor.blue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); dfSize = 1.0; if (psStyle->size > 0) dfSize = psStyle->size; else if (psStyle->width > 0) dfSize = psStyle->width; snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-width\">%.2f\n", sCssParam,dfSize,sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGeneratePointSLD */ /* */ /* Generate SLD for a Point layer. */ /************************************************************************/ char *msSLDGeneratePointSLD(styleObj *psStyle, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; char *pszGraphicSLD = NULL; char szTmp[100]; char sNameSpace[10]; sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); snprintf(szTmp, sizeof(szTmp), "<%sPointSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 1, nVersion); if (pszGraphicSLD) { pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); free(pszGraphicSLD); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGenerateTextSLD */ /* */ /* Generate a TextSymboliser SLD xml based on the class's label */ /* object. */ /************************************************************************/ char *msSLDGenerateTextSLD(classObj *psClass, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; char szTmp[100]; char **aszFontsParts = NULL; int nFontParts = 0; char szHexColor[7]; int nColorRed=-1, nColorGreen=-1, nColorBlue=-1; double dfAnchorX = 0.5, dfAnchorY = 0.5; int i = 0; char sCssParam[30]; char sNameSpace[10]; labelObj *psLabelObj = NULL; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sCssParam, "se:SvgParameter"); else strcpy(sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); if (psClass && psLayer && psLayer->labelitem && strlen(psLayer->labelitem) > 0 && psClass->numlabels > 0) { psLabelObj = psClass->labels[0]; snprintf(szTmp, sizeof(szTmp), "<%sTextSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sLabel>%s\n", sNameSpace, psLayer->labelitem, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* -------------------------------------------------------------------- */ /* only true type fonts are exported. Font name should be */ /* something like arial-bold-italic. There are 3 parts to the */ /* name font-family, font-style (italic, oblique, nomal), */ /* font-weight (bold, normal). These 3 elements are separated */ /* with -. */ /* -------------------------------------------------------------------- */ if (psLabelObj->type == MS_TRUETYPE && psLabelObj->font) { aszFontsParts = msStringSplit(psLabelObj->font, '-', &nFontParts); if (nFontParts > 0) { snprintf(szTmp, sizeof(szTmp), "<%sFont>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* assuming first one is font-family */ snprintf(szTmp, sizeof(szTmp), "<%s name=\"font-family\">%s\n", sCssParam, aszFontsParts[0], sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); for (i=1; i%s\n", sCssParam, aszFontsParts[i], sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } else if (strcasecmp(aszFontsParts[i], "bold") == 0) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"font-weight\">%s\n", sCssParam, aszFontsParts[i], sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } } /* size */ if (psLabelObj->size > 0) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"font-size\">%.2f\n", sCssParam, psLabelObj->size, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); msFreeCharArray(aszFontsParts, nFontParts); } } /* label placement */ snprintf(szTmp, sizeof(szTmp), "<%sLabelPlacement>\n<%sPointPlacement>\n", sNameSpace, sNameSpace ); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sAnchorPoint>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psLabelObj->position == MS_LL) { dfAnchorX =0; dfAnchorY = 0; } else if (psLabelObj->position == MS_CL) { dfAnchorX =0; dfAnchorY = 0.5; } else if (psLabelObj->position == MS_UL) { dfAnchorX =0; dfAnchorY = 1; } else if (psLabelObj->position == MS_LC) { dfAnchorX =0.5; dfAnchorY = 0; } else if (psLabelObj->position == MS_CC) { dfAnchorX =0.5; dfAnchorY = 0.5; } else if (psLabelObj->position == MS_UC) { dfAnchorX =0.5; dfAnchorY = 1; } else if (psLabelObj->position == MS_LR) { dfAnchorX =1; dfAnchorY = 0; } else if (psLabelObj->position == MS_CR) { dfAnchorX =1; dfAnchorY = 0.5; } else if (psLabelObj->position == MS_UR) { dfAnchorX =1; dfAnchorY = 1; } snprintf(szTmp, sizeof(szTmp), "<%sAnchorPointX>%.1f\n", sNameSpace, dfAnchorX, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sAnchorPointY>%.1f\n", sNameSpace, dfAnchorY, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* displacement */ if (psLabelObj->offsetx > 0 || psLabelObj->offsety > 0) { snprintf(szTmp, sizeof(szTmp), "<%sDisplacement>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psLabelObj->offsetx > 0) { snprintf(szTmp, sizeof(szTmp), "<%sDisplacementX>%d\n", sNameSpace, psLabelObj->offsetx, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } if (psLabelObj->offsety > 0) { snprintf(szTmp, sizeof(szTmp), "<%sDisplacementY>%d\n", sNameSpace, psLabelObj->offsety, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } /* rotation */ if (psLabelObj->angle > 0) { snprintf(szTmp, sizeof(szTmp), "<%sRotation>%.2f\n", sNameSpace, psLabelObj->angle, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } /* TODO : support Halo parameter => shadow */ snprintf(szTmp, sizeof(szTmp), "\n\n", sNameSpace, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* color */ if (psLabelObj->color.red != -1 && psLabelObj->color.green != -1 && psLabelObj->color.blue != -1) { nColorRed = psLabelObj->color.red; nColorGreen = psLabelObj->color.green; nColorBlue = psLabelObj->color.blue; } else if (psLabelObj->outlinecolor.red != -1 && psLabelObj->outlinecolor.green != -1 && psLabelObj->outlinecolor.blue != -1) { nColorRed = psLabelObj->outlinecolor.red; nColorGreen = psLabelObj->outlinecolor.green; nColorBlue = psLabelObj->outlinecolor.blue; } if (nColorRed >= 0 && nColorGreen >= 0 && nColorBlue >=0) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace ); pszSLD = msStringConcatenate(pszSLD, szTmp); sprintf(szHexColor,"%02x%02x%02x",nColorRed, nColorGreen, nColorBlue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGenerateSLDLayer */ /* */ /* Genrate an SLD XML string based on the layer's classes. */ /************************************************************************/ char *msSLDGenerateSLDLayer(layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) #ifdef USE_OGR char szTmp[100]; char *pszTmpName = NULL; int i, j; styleObj *psStyle = NULL; char *pszFilter = NULL; char *pszFinalSLD = NULL; char *pszSLD = NULL; const char *pszTmp = NULL; double dfMinScale =-1, dfMaxScale = -1; const char *pszWfsFilter= NULL; char *pszEncoded = NULL, *pszWfsFilterEncoded=NULL; if (psLayer && (psLayer->status == MS_ON || psLayer->status == MS_DEFAULT) && (psLayer->type == MS_LAYER_POINT || psLayer->type == MS_LAYER_LINE || psLayer->type == MS_LAYER_POLYGON || psLayer->type == MS_LAYER_ANNOTATION)) { snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); pszTmp = msOWSLookupMetadata(&(psLayer->metadata), "MO", "name"); if (pszTmp) { pszEncoded = msEncodeHTMLEntities(pszTmp); if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", pszEncoded); else snprintf(szTmp, sizeof(szTmp), "%s\n", pszEncoded); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); msFree(pszEncoded); } else if (psLayer->name) { pszEncoded = msEncodeHTMLEntities(psLayer->name); pszTmpName = (char *)malloc(sizeof(char)*(strlen(pszEncoded)+100)); if (nVersion > OWS_1_0_0) sprintf(pszTmpName, "%s\n", pszEncoded); else sprintf(pszTmpName, "%s\n", pszEncoded); msFree(pszEncoded); pszFinalSLD = msStringConcatenate(pszFinalSLD, pszTmpName); msFree(pszTmpName); pszTmpName=NULL; } else { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", "NamedLayer"); else snprintf(szTmp, sizeof(szTmp), "%s\n", "NamedLayer"); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); pszWfsFilter = msLookupHashTable(&(psLayer->metadata), "wfs_filter"); if (pszWfsFilter) pszWfsFilterEncoded = msEncodeHTMLEntities(pszWfsFilter); if (psLayer->numclasses > 0) { for (i=0; inumclasses; i++) { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); /* if class has a name, use it as the RULE name */ if (psLayer->class[i]->name) { pszEncoded = msEncodeHTMLEntities(psLayer->class[i]->name); pszTmpName = (char *)malloc(sizeof(char)*(strlen(pszEncoded)+100)); if (nVersion > OWS_1_0_0) sprintf(pszTmpName, "%s\n", pszEncoded); else sprintf(pszTmpName, "%s\n", pszEncoded); msFree(pszEncoded); pszFinalSLD = msStringConcatenate(pszFinalSLD, pszTmpName); msFree(pszTmpName); pszTmpName=NULL; } /* -------------------------------------------------------------------- */ /* get the Filter if there is a class expression. */ /* -------------------------------------------------------------------- */ pszFilter = msSLDGetFilter(psLayer->class[i] , pszWfsFilter);/* pszWfsFilterEncoded); */ if (pszFilter) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszFilter); free(pszFilter); } /* -------------------------------------------------------------------- */ /* generate the min/max scale. */ /* -------------------------------------------------------------------- */ dfMinScale = -1.0; if (psLayer->class[i]->minscaledenom > 0) dfMinScale = psLayer->class[i]->minscaledenom; else if (psLayer->minscaledenom > 0) dfMinScale = psLayer->minscaledenom; else if (psLayer->map && psLayer->map->web.minscaledenom > 0) dfMinScale = psLayer->map->web.minscaledenom; if (dfMinScale > 0) { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%f\n", dfMinScale); else snprintf(szTmp, sizeof(szTmp), "%f\n", dfMinScale); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } dfMaxScale = -1.0; if (psLayer->class[i]->maxscaledenom > 0) dfMaxScale = psLayer->class[i]->maxscaledenom; else if (psLayer->maxscaledenom > 0) dfMaxScale = psLayer->maxscaledenom; else if (psLayer->map && psLayer->map->web.maxscaledenom > 0) dfMaxScale = psLayer->map->web.maxscaledenom; if (dfMaxScale > 0) { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%f\n", dfMaxScale); else snprintf(szTmp, sizeof(szTmp), "%f\n", dfMaxScale); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } /* -------------------------------------------------------------------- */ /* Line symbolizer. */ /* */ /* Right now only generates a stroke element containing css */ /* parameters. */ /* Lines using symbols TODO (specially for dash lines) */ /* -------------------------------------------------------------------- */ if (psLayer->type == MS_LAYER_LINE) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGenerateLineSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } else if (psLayer->type == MS_LAYER_POLYGON) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGeneratePolygonSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } else if (psLayer->type == MS_LAYER_POINT) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGeneratePointSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } else if (psLayer->type == MS_LAYER_ANNOTATION) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGeneratePointSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } /* label if it exists */ pszSLD = msSLDGenerateTextSLD(psLayer->class[i], psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } } if (pszWfsFilterEncoded) msFree(pszWfsFilterEncoded); if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } return pszFinalSLD; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDGenerateSLDLayer()"); return NULL; #endif /* USE_OGR */ #else msSetError(MS_MISCERR, "OWS support is not available.", "msSLDGenerateSLDLayer()"); return NULL; #endif } #ifdef USE_OGR char *msSLDGetComparisonValue(char *pszExpression) { char *pszValue = NULL; if (!pszExpression) return NULL; if (strstr(pszExpression, "<=") || strstr(pszExpression, " le ")) pszValue = msStrdup("PropertyIsLessThanOrEqualTo"); else if (strstr(pszExpression, "=~")) pszValue = msStrdup("PropertyIsLike"); else if (strstr(pszExpression, "~*")) pszValue = msStrdup("PropertyIsLike"); else if (strstr(pszExpression, ">=") || strstr(pszExpression, " ge ")) pszValue = msStrdup("PropertyIsGreaterThanOrEqualTo"); else if (strstr(pszExpression, "!=") || strstr(pszExpression, " ne ")) pszValue = msStrdup("PropertyIsNotEqualTo"); else if (strstr(pszExpression, "=") || strstr(pszExpression, " eq ")) pszValue = msStrdup("PropertyIsEqualTo"); else if (strstr(pszExpression, "<") || strstr(pszExpression, " lt ")) pszValue = msStrdup("PropertyIsLessThan"); else if (strstr(pszExpression, ">") || strstr(pszExpression, " gt ")) pszValue = msStrdup("PropertyIsGreaterThan"); return pszValue; } char *msSLDGetLogicalOperator(char *pszExpression) { if (!pszExpression) return NULL; /* TODO for NOT */ if(strstr(pszExpression, " AND ") || strstr(pszExpression, "AND(")) return msStrdup("And"); if(strstr(pszExpression, " OR ") || strstr(pszExpression, "OR(")) return msStrdup("Or"); if(strstr(pszExpression, "NOT ") || strstr(pszExpression, "NOT(")) return msStrdup("Not"); return NULL; } char *msSLDGetRightExpressionOfOperator(char *pszExpression) { char *pszAnd = NULL, *pszOr = NULL, *pszNot=NULL; pszAnd = strstr(pszExpression, " AND "); if (!pszAnd) pszAnd = strstr(pszExpression, " and "); if (pszAnd) return msStrdup(pszAnd+4); else { pszOr = strstr(pszExpression, " OR "); if (!pszOr) pszOr = strstr(pszExpression, " or "); if (pszOr) return msStrdup(pszOr+3); else { pszNot = strstr(pszExpression, "NOT "); if (!pszNot) pszNot = strstr(pszExpression, "not "); if (!pszNot) pszNot = strstr(pszExpression, "NOT("); if (!pszNot) pszNot = strstr(pszExpression, "not("); if (pszNot) return msStrdup(pszNot+4); } } return NULL; } char *msSLDGetLeftExpressionOfOperator(char *pszExpression) { char *pszReturn = NULL; int nLength = 0, i =0, iReturn=0; if (!pszExpression || (nLength = strlen(pszExpression)) <=0) return NULL; pszReturn = (char *)malloc(sizeof(char)*(nLength+1)); pszReturn[0] = '\0'; if (strstr(pszExpression, " AND ") || strstr(pszExpression, " and ")) { for (i=0; i 1) { pszAttributeName = msStrdup(aszValues[0]); pszAttributeValue = msStrdup(aszValues[1]); msFreeCharArray(aszValues, nTokens); } else { nLength = strlen(pszExpression); pszAttributeName = (char *)malloc(sizeof(char)*(nLength+1)); iValue = 0; for (i=0; i 2 && strcasecmp(pszComparionValue, "PropertyIsLike") == 0) { int len = strlen(pszFinalAttributeValue); msStringTrimBlanks(pszFinalAttributeValue); if (pszFinalAttributeValue[0] == '/' && (pszFinalAttributeValue[len-1] == '/' || (pszFinalAttributeValue[len-1] == 'i' && pszFinalAttributeValue[len-2] == '/'))) { if (pszFinalAttributeValue[len-1] == '/') pszFinalAttributeValue[len-1] = '\0'; else pszFinalAttributeValue[len-2] = '\0'; memmove(pszFinalAttributeValue, pszFinalAttributeValue + ((pszFinalAttributeValue[1] == '^') ? 2 : 1), len-1); /*replace wild card string .* with * */ pszFinalAttributeValue = msReplaceSubstring(pszFinalAttributeValue, ".*", "*"); } } return pszFinalAttributeValue; } } char *msSLDGetAttributeName(char *pszExpression, char *pszComparionValue) { return msSLDGetAttributeNameOrValue(pszExpression, pszComparionValue, 1); } char *msSLDGetAttributeValue(char *pszExpression, char *pszComparionValue) { return msSLDGetAttributeNameOrValue(pszExpression, pszComparionValue, 0); } /************************************************************************/ /* BuildExpressionTree */ /* */ /* Build a filter expression node based on mapserver's class */ /* expression. This is limited to simple expressions like : */ /* A = B, A < B, A <= B, A > B, A >= B, A != B */ /* It also handles one level of logical expressions : */ /* A AND B */ /* A OR B */ /* NOT A */ /************************************************************************/ FilterEncodingNode *BuildExpressionTree(char *pszExpression, FilterEncodingNode *psNode) { int nLength = 0; int nOperators=0; char *pszFinalExpression = NULL; char *pszComparionValue=NULL, *pszAttibuteName=NULL; char *pszAttibuteValue=NULL; char *pszLeftExpression=NULL, *pszRightExpression=NULL, *pszOperator=NULL; if (!pszExpression || (nLength = strlen(pszExpression)) <=0) return NULL; pszFinalExpression = (char *)malloc(sizeof(char)*(nLength+1)); pszFinalExpression[0] = '\0'; /* -------------------------------------------------------------------- */ /* First we check how many logical operators are there : */ /* - if none : It means It is a comparision operator (like =, */ /* >, >= .... We get the comparison value as well as the */ /* attribute and the attribut's value and assign it to the node */ /* passed in argument. */ /* - if there is one operator, we assign the operator to the */ /* node and adds the expressions into the left and right nodes. */ /* -------------------------------------------------------------------- */ nOperators = msSLDNumberOfLogicalOperators(pszExpression); if (nOperators == 0) { if (!psNode) psNode = FLTCreateFilterEncodingNode(); pszComparionValue = msSLDGetComparisonValue(pszExpression); pszAttibuteName = msSLDGetAttributeName(pszExpression, pszComparionValue); pszAttibuteValue = msSLDGetAttributeValue(pszExpression, pszComparionValue); if (pszComparionValue && pszAttibuteName && pszAttibuteValue) { psNode->eType = FILTER_NODE_TYPE_COMPARISON; psNode->pszValue = msStrdup(pszComparionValue); psNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psNode->psLeftNode->pszValue = msStrdup(pszAttibuteName); psNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psNode->psRightNode->pszValue = msStrdup(pszAttibuteValue); if (strcasecmp(pszComparionValue, "PropertyIsLike") == 0) { psNode->pOther = (FEPropertyIsLike *)malloc(sizeof(FEPropertyIsLike)); ((FEPropertyIsLike *)psNode->pOther)->bCaseInsensitive = 0; ((FEPropertyIsLike *)psNode->pOther)->pszWildCard = msStrdup("*"); ((FEPropertyIsLike *)psNode->pOther)->pszSingleChar = msStrdup("#"); ((FEPropertyIsLike *)psNode->pOther)->pszEscapeChar = msStrdup("!"); } free(pszComparionValue); free(pszAttibuteName); free(pszAttibuteValue); } return psNode; } else if (nOperators == 1) { pszOperator = msSLDGetLogicalOperator(pszExpression); if (pszOperator) { if (!psNode) psNode = FLTCreateFilterEncodingNode(); psNode->eType = FILTER_NODE_TYPE_LOGICAL; psNode->pszValue = msStrdup(pszOperator); free(pszOperator); pszLeftExpression = msSLDGetLeftExpressionOfOperator(pszExpression); pszRightExpression = msSLDGetRightExpressionOfOperator(pszExpression); if (pszLeftExpression || pszRightExpression) { if (pszLeftExpression) { pszComparionValue = msSLDGetComparisonValue(pszLeftExpression); pszAttibuteName = msSLDGetAttributeName(pszLeftExpression, pszComparionValue); pszAttibuteValue = msSLDGetAttributeValue(pszLeftExpression, pszComparionValue); if (pszComparionValue && pszAttibuteName && pszAttibuteValue) { psNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->eType = FILTER_NODE_TYPE_COMPARISON; psNode->psLeftNode->pszValue = msStrdup(pszComparionValue); psNode->psLeftNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psNode->psLeftNode->psLeftNode->pszValue = msStrdup(pszAttibuteName); psNode->psLeftNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psNode->psLeftNode->psRightNode->pszValue = msStrdup(pszAttibuteValue); free(pszComparionValue); free(pszAttibuteName); free(pszAttibuteValue); } } if (pszRightExpression) { pszComparionValue = msSLDGetComparisonValue(pszRightExpression); pszAttibuteName = msSLDGetAttributeName(pszRightExpression, pszComparionValue); pszAttibuteValue = msSLDGetAttributeValue(pszRightExpression, pszComparionValue); if (pszComparionValue && pszAttibuteName && pszAttibuteValue) { psNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->eType = FILTER_NODE_TYPE_COMPARISON; psNode->psRightNode->pszValue = msStrdup(pszComparionValue); psNode->psRightNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psNode->psRightNode->psLeftNode->pszValue = msStrdup(pszAttibuteName); psNode->psRightNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psNode->psRightNode->psRightNode->pszValue = msStrdup(pszAttibuteValue); free(pszComparionValue); free(pszAttibuteName); free(pszAttibuteValue); } } } } return psNode; } else return NULL; } char *msSLDBuildFilterEncoding(FilterEncodingNode *psNode) { char *pszTmp = NULL; char szTmp[200]; char *pszExpression = NULL; if (!psNode) return NULL; if (psNode->eType == FILTER_NODE_TYPE_COMPARISON && psNode->pszValue && psNode->psLeftNode && psNode->psLeftNode->pszValue && psNode->psRightNode && psNode->psRightNode->pszValue) { snprintf(szTmp, sizeof(szTmp), "%s%s", psNode->pszValue, psNode->psLeftNode->pszValue, psNode->psRightNode->pszValue, psNode->pszValue); pszExpression = msStrdup(szTmp); } else if (psNode->eType == FILTER_NODE_TYPE_LOGICAL && psNode->pszValue && ((psNode->psLeftNode && psNode->psLeftNode->pszValue) || (psNode->psRightNode && psNode->psRightNode->pszValue))) { snprintf(szTmp, sizeof(szTmp), "", psNode->pszValue); pszExpression = msStringConcatenate(pszExpression, szTmp); if (psNode->psLeftNode) { pszTmp = msSLDBuildFilterEncoding(psNode->psLeftNode); if (pszTmp) { pszExpression = msStringConcatenate(pszExpression, pszTmp); free(pszTmp); } } if (psNode->psRightNode) { pszTmp = msSLDBuildFilterEncoding(psNode->psRightNode); if (pszTmp) { pszExpression = msStringConcatenate(pszExpression, pszTmp); free(pszTmp); } } snprintf(szTmp, sizeof(szTmp), "", psNode->pszValue); pszExpression = msStringConcatenate(pszExpression, szTmp); } return pszExpression; } char *msSLDParseLogicalExpression(char *pszExpression, const char *pszWfsFilter) { FilterEncodingNode *psNode = NULL; char *pszFLTExpression = NULL; char *pszTmp = NULL; if (!pszExpression || strlen(pszExpression) <=0) return NULL; /* psNode = BuildExpressionTree(pszExpression, NULL); */ psNode = BuildExpressionTree(pszExpression, NULL); if (psNode) { pszFLTExpression = msSLDBuildFilterEncoding(psNode); if (pszFLTExpression) { pszTmp = msStringConcatenate(pszTmp, ""); if (pszWfsFilter) { pszTmp = msStringConcatenate(pszTmp, ""); pszTmp = msStringConcatenate(pszTmp, (char *)pszWfsFilter); } pszTmp = msStringConcatenate(pszTmp, pszFLTExpression); if (pszWfsFilter) pszTmp = msStringConcatenate(pszTmp, ""); pszTmp = msStringConcatenate(pszTmp, "\n"); free(pszFLTExpression); pszFLTExpression = pszTmp; } } return pszFLTExpression; } /************************************************************************/ /* char *msSLDParseExpression(char *pszExpression) */ /* */ /* Return an OGC filter for a mapserver locgical expression. */ /* TODO : move function to mapogcfilter.c */ /************************************************************************/ char *msSLDParseExpression(char *pszExpression) { int nElements = 0; char **aszElements = NULL; char szBuffer[500]; char szFinalAtt[40]; char szFinalValue[40]; char szAttribute[40]; char szValue[40]; int i=0, nLength=0, iAtt=0, iVal=0; int bStartCopy=0, bSinglequote=0, bDoublequote=0; char *pszFilter = NULL; if (!pszExpression) return NULL; nLength = strlen(pszExpression); aszElements = msStringSplit(pszExpression, ' ', &nElements); szFinalAtt[0] = '\0'; szFinalValue[0] = '\0'; for (i=0; i 0 && i < nElements-1) { snprintf(szAttribute, sizeof(szAttribute), "%s", aszElements[i-1]); snprintf(szValue, sizeof(szValue), "%s", aszElements[i+1]); /* parse attribute */ nLength = strlen(szAttribute); if (nLength > 0) { iAtt = 0; for (i=0; i 0) { if (szValue[0] == '\'') bSinglequote = 1; else if (szValue[0] == '\"') bDoublequote = 1; else snprintf(szFinalValue, sizeof(szFinalValue), "%s", szValue); iVal = 0; if (bSinglequote || bDoublequote) { for (i=1; i 0 && strlen(szFinalValue) >0) { snprintf(szBuffer, sizeof(szBuffer), "%s%s", szFinalAtt, szFinalValue); pszFilter = msStrdup(szBuffer); } } } return pszFilter; } /************************************************************************/ /* msSLDConvertRegexExpToOgcIsLike */ /* */ /* Convert mapserver regex expression to ogc is like propoery */ /* exprssion. */ /* */ /* Review bug 1644 for details. Here are the current rules: */ /* */ /* The filter encoding property like is more limited compared */ /* to regular expressiosn that can be built in mapserver. I */ /* think we should define what is possible to convert properly */ /* and do those, and also identify potential problems. Example : */ /* - any time there is a .* in the expression it will be */ /* converted to * */ /* - any other character plus all the metacharcters . ^ $ * + */ /* ? { [ ] \ | ( ) would be outputed as is. (In case of */ /* mapserver, when we read the the ogc filter expression, we */ /* convert the wild card chracter to .*, and we convert the */ /* single chracter to . and the escpae character to \ all */ /* other are outputed as is) */ /* - the ogc tag would look like */ /* */ /* - type of potential problem : */ /* * if an expression is like /T (star)/ it will be */ /* converted to T* which is not correct. */ /* */ /************************************************************************/ char *msSLDConvertRegexExpToOgcIsLike(char *pszRegex) { char szBuffer[1024]; int iBuffer = 0, i=0; int nLength = 0; if (!pszRegex || strlen(pszRegex) == 0) return NULL; szBuffer[0] = '\0'; nLength = strlen(pszRegex); while (i < nLength) { if (pszRegex[i] != '.') { szBuffer[iBuffer++] = pszRegex[i]; i++; } else { if (iexpression.string) { /* string expression */ if (psClass->expression.type == MS_STRING) { if (psClass->layer && psClass->layer->classitem) { if (pszWfsFilter) snprintf(szBuffer, sizeof(szBuffer), "%s%s%s\n", pszWfsFilter, psClass->layer->classitem, psClass->expression.string); else snprintf(szBuffer, sizeof(szBuffer), "%s%s\n", psClass->layer->classitem, psClass->expression.string); pszFilter = msStrdup(szBuffer); } } else if (psClass->expression.type == MS_EXPRESSION) { pszFilter = msSLDParseLogicalExpression(psClass->expression.string, pszWfsFilter); } else if (psClass->expression.type == MS_REGEX) { if (psClass->layer && psClass->layer->classitem && psClass->expression.string) { pszOgcFilter = msSLDConvertRegexExpToOgcIsLike(psClass->expression.string); if (pszWfsFilter) snprintf(szBuffer, sizeof(szBuffer), "%s%s%s\n", pszWfsFilter, psClass->layer->classitem, pszOgcFilter); else snprintf(szBuffer, sizeof(szBuffer), "%s%s\n", psClass->layer->classitem, pszOgcFilter); free(pszOgcFilter); pszFilter = msStrdup(szBuffer); } } } else if (pszWfsFilter) { snprintf(szBuffer, sizeof(szBuffer), "%s\n", pszWfsFilter); pszFilter = msStrdup(szBuffer); } return pszFilter; } #endif mapserver-6.4.1/shp2img.c0000644002461700001440000002407612261257215015042 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Commandline .map rendering utility, mostly for testing. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maptime.h" int main(int argc, char *argv[]) { int i,j,k; mapObj *map=NULL; imageObj *image = NULL; char **layers=NULL; int num_layers=0; int layer_found=0; char *outfile=NULL; /* no -o sends image to STDOUT */ int iterations = 1; int draws = 0; for(i=1; i= MS_DEBUGLEVEL_TUNING) msGettimeofday(&requeststarttime, NULL); if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } /* ---- check the number of arguments, return syntax if not correct ---- */ if( argc < 3 ) { fprintf(stdout, "\nPurpose: convert a mapfile to an image\n\n"); fprintf(stdout, "Syntax: shp2img -m mapfile [-o image] [-e minx miny maxx maxy] [-s sizex sizey]\n" " [-l \"layer1 [layers2...]\"] [-i format]\n" " [-all_debug n] [-map_debug n] [-layer_debug n] [-p n] [-c n] [-d layername datavalue]\n"); fprintf(stdout," -m mapfile: Map file to operate on - required\n" ); fprintf(stdout," -i format: Override the IMAGETYPE value to pick output format\n" ); fprintf(stdout," -o image: output filename (stdout if not provided)\n"); fprintf(stdout," -e minx miny maxx maxy: extents to render\n"); fprintf(stdout," -s sizex sizey: output image size\n"); fprintf(stdout," -l layers: layers / groups to enable - make sure they are quoted and space separated if more than one listed\n" ); fprintf(stdout," -all_debug n: Set debug level for map and all layers\n" ); fprintf(stdout," -map_debug n: Set map debug level\n" ); fprintf(stdout," -layer_debug layer_name n: Set layer debug level\n" ); fprintf(stdout," -c n: draw map n number of times\n" ); fprintf(stdout," -p n: pause for n seconds after reading the map\n" ); fprintf(stdout," -d layername datavalue: change DATA value for layer\n" ); exit(0); } if ( msSetup() != MS_SUCCESS ) { msWriteError(stderr); exit(1); } /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if ( msDebugInitFromEnv() != MS_SUCCESS ) { msWriteError(stderr); msCleanup(0); exit(1); } for(i=1; iimagetype ); map->imagetype = msStrdup( argv[i+1] ); msApplyOutputFormat( &(map->outputformat), format, map->transparent, map->interlace, map->imagequality ); } i+=1; } if(strcmp(argv[i],"-d") == 0) { /* swap layer data */ for(j=0; jnumlayers; j++) { if(strcmp(GET_LAYER(map, j)->name, argv[i+1]) == 0) { free(GET_LAYER(map, j)->data); GET_LAYER(map, j)->data = msStrdup(argv[i+2]); break; } } i+=2; } if(strcmp(argv[i], "-all_debug") == 0 && i < argc-1 ) { /* global debug */ int debug_level = atoi(argv[++i]); /* msSetGlobalDebugLevel() already called. Just need to force debug * level in map and all layers */ map->debug = debug_level; for(j=0; jnumlayers; j++) { GET_LAYER(map, j)->debug = debug_level; } } if(strcmp(argv[i], "-map_debug") == 0 && i < argc-1 ) { /* debug */ map->debug = atoi(argv[++i]); /* Send output to stderr by default */ if (msGetErrorFile() == NULL) msSetErrorFile("stderr", NULL); } if(strcmp(argv[i], "-layer_debug") == 0 && i < argc-1 ) { /* debug */ const char *layer_name = argv[++i]; int debug_level = atoi(argv[++i]); int got_layer = 0; for(j=0; jnumlayers; j++) { if(strcmp(GET_LAYER(map, j)->name,layer_name) == 0 ) { GET_LAYER(map, j)->debug = debug_level; got_layer = 1; } } if( !got_layer ) fprintf( stderr, " Did not find layer '%s' from -layer_debug switch.\n", layer_name ); /* Send output to stderr by default */ if (msGetErrorFile() == NULL) msSetErrorFile("stderr", NULL); } if(strcmp(argv[i],"-e") == 0) { /* change extent */ if( argc <= i+4 ) { fprintf( stderr, "Argument -e needs 4 space separated numbers as argument.\n" ); msCleanup(0); exit(1); } map->extent.minx = atof(argv[i+1]); map->extent.miny = atof(argv[i+2]); map->extent.maxx = atof(argv[i+3]); map->extent.maxy = atof(argv[i+4]); i+=4; } if (strcmp(argv[i], "-s") == 0) { msMapSetSize(map, atoi(argv[i+1]), atoi(argv[i+2])); i+=2; } if(strcmp(argv[i],"-l") == 0) { /* load layer list */ layers = msStringSplit(argv[i+1], ' ', &(num_layers)); for(j=0; jnumlayers; k++) { if((GET_LAYER(map, k)->name && strcasecmp(GET_LAYER(map, k)->name, layers[j]) == 0) || (GET_LAYER(map, k)->group && strcasecmp(GET_LAYER(map, k)->group, layers[j]) == 0)) { layer_found = 1; break; } } if (layer_found==0) { fprintf(stderr, "Layer (-l) \"%s\" not found\n", layers[j]); msCleanup(0); exit(1); } } for(j=0; jnumlayers; j++) { if(GET_LAYER(map, j)->status == MS_DEFAULT) continue; else { GET_LAYER(map, j)->status = MS_OFF; for(k=0; kname && strcasecmp(GET_LAYER(map, j)->name, layers[k]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[k]) == 0)) { GET_LAYER(map, j)->status = MS_ON; break; } } } } msFreeCharArray(layers, num_layers); i+=1; } } image = msDrawMap(map, MS_FALSE); if(!image) { msWriteError(stderr); msFreeMap(map); msCleanup(0); exit(1); } if( msSaveImage(map, image, outfile) != MS_SUCCESS ) { msWriteError(stderr); } msFreeImage(image); msFreeMap(map); if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("shp2img total time: %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCleanup(0); } /* for(draws=0; draws #ifndef _WIN32 #include #include #endif #include #ifdef NEED_NONBLOCKING_STDERR #include #endif #ifdef _WIN32 #include /* OutputDebugStringA() */ #endif #ifndef USE_THREAD debugInfoObj *msGetDebugInfoObj() { static debugInfoObj debuginfo = {MS_DEBUGLEVEL_ERRORSONLY, MS_DEBUGMODE_OFF, NULL, NULL }; return &debuginfo; } #else static debugInfoObj *debuginfo_list = NULL; debugInfoObj *msGetDebugInfoObj() { debugInfoObj *link; int thread_id; debugInfoObj *ret_obj; msAcquireLock( TLOCK_DEBUGOBJ ); thread_id = msGetThreadId(); /* find link for this thread */ for( link = debuginfo_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} /* If the target thread link is already at the head of the list were ok */ if( debuginfo_list != NULL && debuginfo_list->thread_id == thread_id ) { } /* We don't have one ... initialize one. */ else if( link == NULL || link->next == NULL ) { debugInfoObj *new_link; new_link = (debugInfoObj *) malloc(sizeof(debugInfoObj)); if (new_link != NULL) { new_link->next = debuginfo_list; new_link->thread_id = thread_id; new_link->global_debug_level = MS_DEBUGLEVEL_ERRORSONLY; new_link->debug_mode = MS_DEBUGMODE_OFF; new_link->errorfile = NULL; new_link->fp = NULL; } else msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGetDebugInfoObj()", (unsigned int)sizeof(debugInfoObj)); debuginfo_list = new_link; } /* If the link is not already at the head of the list, promote it */ else if( link != NULL && link->next != NULL ) { debugInfoObj *target = link->next; link->next = link->next->next; target->next = debuginfo_list; debuginfo_list = target; } ret_obj = debuginfo_list; msReleaseLock( TLOCK_DEBUGOBJ ); return ret_obj; } #endif /* msSetErrorFile() ** ** Set output target, ready to write to it, open file if necessary ** ** If pszRelToPath != NULL then we will try to make the value relative to ** this path if it is not absolute already and it's not one of the special ** values (stderr, stdout, windowsdebug) ** ** Returns MS_SUCCESS/MS_FAILURE */ int msSetErrorFile(const char *pszErrorFile, const char *pszRelToPath) { char extended_path[MS_MAXPATHLEN]; debugInfoObj *debuginfo = msGetDebugInfoObj(); if (strcmp(pszErrorFile, "stderr") != 0 && strcmp(pszErrorFile, "stdout") != 0 && strcmp(pszErrorFile, "windowsdebug") != 0) { /* Try to make the path relative */ if(msBuildPath(extended_path, pszRelToPath, pszErrorFile) == NULL) return MS_FAILURE; pszErrorFile = extended_path; } if (debuginfo && debuginfo->errorfile && pszErrorFile && strcmp(debuginfo->errorfile, pszErrorFile) == 0) { /* Nothing to do, already writing to the right place */ return MS_SUCCESS; } /* Close current output file if any */ msCloseErrorFile(); /* NULL or empty target will just close current output and return */ if (pszErrorFile == NULL || *pszErrorFile == '\0') return MS_SUCCESS; if (strcmp(pszErrorFile, "stderr") == 0) { debuginfo->fp = stderr; debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->debug_mode = MS_DEBUGMODE_STDERR; } else if (strcmp(pszErrorFile, "stdout") == 0) { debuginfo->fp = stdout; debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->debug_mode = MS_DEBUGMODE_STDOUT; } else if (strcmp(pszErrorFile, "windowsdebug") == 0) { #ifdef _WIN32 debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->fp = NULL; debuginfo->debug_mode = MS_DEBUGMODE_WINDOWSDEBUG; #else msSetError(MS_MISCERR, "'MS_ERRORFILE windowsdebug' is available only on Windows platforms.", "msSetErrorFile()"); return MS_FAILURE; #endif } else { debuginfo->fp = fopen(pszErrorFile, "a"); if (debuginfo->fp == NULL) { msSetError(MS_MISCERR, "Failed to open MS_ERRORFILE %s", "msSetErrorFile()", pszErrorFile); return MS_FAILURE; } debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->debug_mode = MS_DEBUGMODE_FILE; } return MS_SUCCESS; } /* msCloseErrorFile() ** ** Close current output file (if one is open) and reset related members */ void msCloseErrorFile() { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo && debuginfo->debug_mode != MS_DEBUGMODE_OFF) { if (debuginfo->fp && debuginfo->debug_mode == MS_DEBUGMODE_FILE) fclose(debuginfo->fp); if (debuginfo->fp && (debuginfo->debug_mode == MS_DEBUGMODE_STDERR || debuginfo->debug_mode == MS_DEBUGMODE_STDOUT)) fflush(debuginfo->fp); /* just flush stderr or stdout */ debuginfo->fp = NULL; msFree(debuginfo->errorfile); debuginfo->errorfile = NULL; debuginfo->debug_mode = MS_DEBUGMODE_OFF; } } /* msGetErrorFile() ** ** Returns name of current error file ** ** Returns NULL if not set. */ const char *msGetErrorFile() { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo) return debuginfo->errorfile; return NULL; } /* Set/Get the current global debug level value, used as default value for ** new map and layer objects and to control msDebug() calls outside of ** the context of mapObj or layerObj. ** */ void msSetGlobalDebugLevel(int level) { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo) debuginfo->global_debug_level = (debugLevel)level; } debugLevel msGetGlobalDebugLevel() { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo) return debuginfo->global_debug_level; return MS_DEBUGLEVEL_ERRORSONLY; } /* msDebugInitFromEnv() ** ** Init debug state from MS_ERRORFILE and MS_DEBUGLEVEL env vars if set ** ** Returns MS_SUCCESS/MS_FAILURE */ int msDebugInitFromEnv() { const char *val; if( (val=getenv( "MS_ERRORFILE" )) != NULL ) { if ( msSetErrorFile(val, NULL) != MS_SUCCESS ) return MS_FAILURE; } if( (val=getenv( "MS_DEBUGLEVEL" )) != NULL ) msSetGlobalDebugLevel(atoi(val)); return MS_SUCCESS; } /* msDebugCleanup() ** ** Called by msCleanup to remove info related to this thread. */ void msDebugCleanup() { /* make sure file is closed */ msCloseErrorFile(); #ifdef USE_THREAD { int thread_id = msGetThreadId(); debugInfoObj *link; msAcquireLock( TLOCK_DEBUGOBJ ); /* find link for this thread */ for( link = debuginfo_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} if( link->thread_id == thread_id ) { /* presumably link is at head of list. */ if( debuginfo_list == link ) debuginfo_list = link->next; free( link ); } else if( link->next != NULL && link->next->thread_id == thread_id ) { debugInfoObj *next_link = link->next; link->next = link->next->next; free( next_link ); } msReleaseLock( TLOCK_DEBUGOBJ ); } #endif } /* msDebug() ** ** Outputs/logs messages to the MS_ERRORFILE if one is set ** (see msSetErrorFile()) ** */ void msDebug( const char * pszFormat, ... ) { va_list args; debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo == NULL || debuginfo->debug_mode == MS_DEBUGMODE_OFF) return; /* Don't waste time here! */ if (debuginfo->fp) { /* Writing to a stdio file handle */ #if defined(USE_FASTCGI) /* It seems the FastCGI stuff inserts a timestamp anyways, so */ /* we might as well skip this one if writing to stderr w/ FastCGI. */ if (debuginfo->debug_mode != MS_DEBUGMODE_STDERR) #endif { struct mstimeval tv; time_t t; msGettimeofday(&tv, NULL); t = tv.tv_sec; msIO_fprintf(debuginfo->fp, "[%s].%ld ", msStringChop(ctime(&t)), (long)tv.tv_usec); } va_start(args, pszFormat); msIO_vfprintf(debuginfo->fp, pszFormat, args); va_end(args); } #ifdef _WIN32 else if (debuginfo->debug_mode == MS_DEBUGMODE_WINDOWSDEBUG) { /* Writing to Windows Debug Console */ char szMessage[MESSAGELENGTH]; va_start(args, pszFormat); vsnprintf( szMessage, MESSAGELENGTH, pszFormat, args ); va_end(args); szMessage[MESSAGELENGTH-1] = '\0'; OutputDebugStringA(szMessage); } #endif } mapserver-6.4.1/maplibxml2.h0000644002461700001440000000407412261257215015541 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: libxml2 convenience wrapper functions include file * Author: Tom Kralidis (tomkralidis@hotmail.com) * ****************************************************************************** * Copyright (c) 2007, Tom Kralidis * * 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 MAPLIBXML2_H #define MAPLIBXML2_H #ifdef USE_LIBXML2 #include #include #include #include #include #include xmlXPathObjectPtr msLibXml2GetXPath(xmlDocPtr doc, xmlXPathContextPtr context, xmlChar *xpath); void msLibXml2GenerateList(xmlNodePtr psParent, xmlNsPtr psNs, const char *elname, const char *values, char delim); const char *msLibXml2GetXPathTree(xmlDocPtr doc, xmlXPathObjectPtr xpath); #endif /* defined(USE_LIBXML2) */ #endif /* MAPLIBXML2_H */ mapserver-6.4.1/mapgml.h0000644002461700001440000000417212261257215014746 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Headers for mapgml.c. shapeObj to GML output via MapServer * queries. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPGML_H #define MAPGML_H #ifdef USE_LIBXML2 #include #include #define MS_GML_NAMESPACE_URI "http://www.opengis.net/gml" #define MS_GML_NAMESPACE_PREFIX "gml" xmlNodePtr msGML3BoundedBy(xmlNsPtr psNs, double minx, double miny, double maxx, double maxy, const char *psEpsg); xmlNodePtr msGML3TimePeriod(xmlNsPtr psNs, char *pszStart, char *pszEnd); xmlNodePtr msGML3TimeInstant(xmlNsPtr psNs, char *timeInstant); xmlNodePtr msGML3Point(xmlNsPtr psNs, const char *psSrsName, const char *id, double x, double y); #endif /* USE_LIBXML2 */ #endif mapserver-6.4.1/xmlmapfile/0000755002461700001440000000000012261257216015453 5ustar tbonfortusersmapserver-6.4.1/xmlmapfile/mapfile.xsl0000644002461700001440000020153412261257216017625 0ustar tbonfortusers "" mapserver-6.4.1/xmlmapfile/tests/0000755002461700001440000000000012261257215016614 5ustar tbonfortusersmapserver-6.4.1/xmlmapfile/tests/symbolset.xml0000644002461700001440000000157612261257215021370 0ustar tbonfortusers FALSE C TRUE serif /tmp/test.gif 0 FALSE C TRUE serif /tmp/test.gif 123 mapserver-6.4.1/xmlmapfile/tests/layerset.xml0000644002461700001440000001335412261257215021174 0ustar tbonfortusers ON (length('[NAME_E]') < 8) group1 /home/myusername/layer1.png 6 15 24000 50 1000000 10 12 261 myText1 group1 population 3.3 (type=’road’ and size < 2) /ddea/i 20 region1 user=nobody password=****** dbname=dbname host=localhost port=5432 SDE ../data 1 FALSE -180.0 -90.0 180.0 90.0 POINT(2000 2500) (type=’road’ and size < 2) pop
http://mapgears.com/templates/myfooter1.html
DDMMSS 5.0 0.5 0.07 1.0 0.05 0.01 group1
http://mapgears.com/templates/myHeader1.html
user=nobody password=****** dbname=dbname host=localhost port=5432 POSTGRESQL ID ./data/lookup.dbf
IDENT
ON myLabel1 2334342 100000 ![orthoquads] layerName 250000 300000 Cities The Cities Norm 120000 ALPHA myPlugin.lib TRUE CLOSE_CONNECTION=DEFER SCALE=AUTO init=epsg:4326 ellps=WGS84 datum=WGS84 [orthoquads] METERS Go 24000 tiger/index.shp LOCATION 5 DD TRUE METERS ^[a-zA-Z\-]+$ ^[A-Z]{2}[0-9]{6}$
mapserver-6.4.1/xmlmapfile/tests/mapfile-test.xml0000644002461700001440000001531412261257215021734 0ustar tbonfortusers 10 http://mapgears.com/context/mapgears.xml dfas2klaed2v 3384knkju3k23 /tmp/ms_error.txt $#[a-e]? 2 72 -180.0 -90.0 180.0 90.0 ../etc/fonts.txt png /tmp/myLayerSet.map /tmp/AnotherLayerSet.map LR FALSE 2048 GDAL/GTIFF tiff TILED=YES TRANSPARENCY=TRUE FLOAT32 image/tiff OFF AGG/PNG png TILED=YES RGBA image/png ON proj=utm ellps=GRS80 datum=NAD83 zone=15 units=m north no_defs -10.0 -9.0 10.0 9.0 /home/myusername/ref1.png star 3 24 4 72 CENTER 5 LR TRUE ON NAUTICALMILES 24000 ../data FALSE C TRUE serif /tmp/test.gif 123 FALSE C TRUE serif /tmp/test.gif 123 /tmp/mySymbolSet.sym [$ir-wz]*.html MILES text/html ../errors/queryfail1.html ../errors/error1.html
../templates/footer1.html
../templates/header.html
/tmp/ms_tmp/ /ms_tmp/ text/html ../logs/ms.log 240000 ../templates/maxtemplate1.html Cities The Cities Norm 120000 ../templates/mintemplate1.html text/html ^[a-zA-Z\-]+$ ^[A-Z]{2}[0-9]{6}$
mapserver-6.4.1/xmlmapfile/mapfile.xsd0000644002461700001440000010210212261257216017604 0ustar tbonfortusers mapserver-6.4.1/mapsymbol.c0000644002461700001440000007710612261257215015476 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: symbolObj related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include /* variable number of function arguments support */ #include /* since the parser handles time/date we need this */ #include "mapserver.h" #include "mapfile.h" #include "mapcopy.h" #include "mapthread.h" extern int msyylex(void); /* lexer globals */ extern void msyyrestart(FILE *); extern double msyynumber; extern char *msyystring_buffer; extern int msyylineno; extern FILE *msyyin; extern int msyystate; static const unsigned char PNGsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; /* 89 50 4E 47 0D 0A 1A 0A hex */ static const unsigned char JPEGsig[3] = {255, 216, 255}; /* FF D8 FF hex */ void freeImageCache(struct imageCacheObj *ic) { if(ic) { freeImageCache(ic->next); /* free any children */ msFreeRasterBuffer(&(ic->img)); free(ic); } return; } /* ** msSymbolGetDefaultSize() ** ** Return the default size of a symbol. ** Note: The size of a symbol is the height. Everywhere in the code, the width ** is adjusted to the size that becomes the height. ** See mapgd.c // size ~ height in pixels */ double msSymbolGetDefaultSize(symbolObj *s) { double size; if(s == NULL) return 1; switch(s->type) { case(MS_SYMBOL_TRUETYPE): size = 1; break; case(MS_SYMBOL_PIXMAP): assert(s->pixmap_buffer != NULL); if(s->pixmap_buffer == NULL) return 1; /* FIXME */ size = (double)s->pixmap_buffer->height; break; case(MS_SYMBOL_SVG): size = 1; #if defined(USE_SVG_CAIRO) || defined (USE_RSVG) assert(s->renderer_cache != NULL); size = s->sizey; #endif break; default: /* vector and ellipses, scalable */ size = (s->sizey<=0)?s->sizex:s->sizey; break; } if(size <= 0) return 1; return size; } void initSymbol(symbolObj *s) { MS_REFCNT_INIT(s); s->type = MS_SYMBOL_VECTOR; s->transparent = MS_FALSE; s->transparentcolor = 0; s->sizex = 1; s->sizey = 1; s->filled = MS_FALSE; s->numpoints=0; s->renderer=NULL; s->renderer_free_func = NULL; s->renderer_cache = NULL; s->pixmap_buffer=NULL; s->imagepath = NULL; s->name = NULL; s->inmapfile = MS_FALSE; s->antialias = MS_FALSE; s->font = NULL; s->full_font_path = NULL; s->full_pixmap_path = NULL; s->character = NULL; s->anchorpoint_x = s->anchorpoint_y = 0.5; } int msFreeSymbol(symbolObj *s) { if(!s) return MS_FAILURE; if( MS_REFCNT_DECR_IS_NOT_ZERO(s) ) { return MS_FAILURE; } if(s->name) free(s->name); if(s->renderer_free_func) { s->renderer_free_func(s); } else { if(s->renderer!=NULL) { s->renderer->freeSymbol(s); } } if(s->pixmap_buffer) { msFreeRasterBuffer(s->pixmap_buffer); free(s->pixmap_buffer); } if(s->font) free(s->font); msFree(s->full_font_path); msFree(s->full_pixmap_path); if(s->imagepath) free(s->imagepath); if(s->character) free(s->character); return MS_SUCCESS; } int loadSymbol(symbolObj *s, char *symbolpath) { int done=MS_FALSE; char szPath[MS_MAXPATHLEN]; initSymbol(s); for(;;) { switch(msyylex()) { case(ANCHORPOINT): if(getDouble(&(s->anchorpoint_x)) == -1) return MS_FAILURE; if(getDouble(&(s->anchorpoint_y)) == -1) return MS_FAILURE; if(s->anchorpoint_x<0 || s->anchorpoint_x>1 || s->anchorpoint_y<0 || s->anchorpoint_y>1) { msSetError(MS_SYMERR, "ANCHORPOINT must be between 0 and 1", "loadSymbol()"); return(-1); } break; case(ANTIALIAS): if((s->antialias = getSymbol(2,MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(CHARACTER): if(getString(&s->character) == MS_FAILURE) return(-1); break; case(END): /* do some error checking */ if((s->type == MS_SYMBOL_SVG) && (s->imagepath == NULL)) { msSetError(MS_SYMERR, "Symbol of type SVG has no file path specified.", "loadSymbol()"); return(-1); } if((s->type == MS_SYMBOL_PIXMAP) && (s->full_pixmap_path == NULL)) { msSetError(MS_SYMERR, "Symbol of type PIXMAP has no image data.", "loadSymbol()"); return(-1); } if(((s->type == MS_SYMBOL_ELLIPSE) || (s->type == MS_SYMBOL_VECTOR)) && (s->numpoints == 0)) { msSetError(MS_SYMERR, "Symbol of type VECTOR or ELLIPSE has no point data.", "loadSymbol()"); return(-1); } if(s->type == MS_SYMBOL_VECTOR) { double minx = s->points[0].x; double miny = s->points[0].y; /* should only negative points be shifted? (#4116)*/ int shiftpositive = ((s->anchorpoint_x!=0.5)||(s->anchorpoint_y!=0.5)); int i; for(i=1; inumpoints; i++) { if(s->points[i].x != -99 && s->points[i].y != -99) { if(s->points[i].xpoints[i].x; if(s->points[i].ypoints[i].y; } } if(minx<0 || miny<0 || (shiftpositive && (minx!=0 || miny!=0))) { for(i=0; inumpoints; i++) { if(s->points[i].x != -99 && s->points[i].y != -99) { s->points[i].x -= minx; s->points[i].y -= miny; } } s->sizex -= minx; s->sizey -= miny; } } return(0); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadSymbol()"); return(-1); break; case(FILLED): if((s->filled = getSymbol(2,MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(FONT): if(getString(&s->font) == MS_FAILURE) return(-1); break; case(IMAGE): if(msyylex() != MS_STRING) { /* get image location from next token */ msSetError(MS_TYPEERR, "Parsing error near (%s):(line %d)", "loadSymbol()", msyystring_buffer, msyylineno); return(-1); } s->full_pixmap_path = msStrdup(msBuildPath(szPath, symbolpath, msyystring_buffer)); /* Set imagepath */ s->imagepath = msStrdup(msyystring_buffer); break; case(NAME): if(getString(&s->name) == MS_FAILURE) return(-1); break; case(POINTS): done = MS_FALSE; s->sizex = 0; s->sizey = 0; for(;;) { switch(msyylex()) { case(END): done = MS_TRUE; break; case(MS_NUMBER): s->points[s->numpoints].x = atof(msyystring_buffer); /* grab the x */ if(getDouble(&(s->points[s->numpoints].y)) == -1) return(-1); /* grab the y */ if(s->points[s->numpoints].x!=-99) { s->sizex = MS_MAX(s->sizex, s->points[s->numpoints].x); s->sizey = MS_MAX(s->sizey, s->points[s->numpoints].y); } s->numpoints++; break; default: msSetError(MS_TYPEERR, "Parsing error near (%s):(line %d)", "loadSymbol()", msyystring_buffer, msyylineno); return(-1); } if(done == MS_TRUE) break; } break; case(TRANSPARENT): s->transparent = MS_TRUE; if(getInteger(&(s->transparentcolor)) == -1) return(-1); break; case(TYPE): if((s->type = getSymbol(8,MS_SYMBOL_VECTOR,MS_SYMBOL_ELLIPSE,MS_SYMBOL_PIXMAP,MS_SYMBOL_SIMPLE,MS_TRUETYPE,MS_SYMBOL_HATCH,MS_SYMBOL_SVG)) == -1) return(-1); if(s->type == MS_TRUETYPE) /* TrueType keyword is valid several place in map files and symbol files, this simplifies the lexer */ s->type = MS_SYMBOL_TRUETYPE; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadSymbol()", msyystring_buffer, msyylineno); return(-1); } /* end switch */ } /* end for */ } void writeSymbol(symbolObj *s, FILE *stream) { int i; msIO_fprintf(stream, " SYMBOL\n"); if(s->name != NULL) msIO_fprintf(stream, " NAME \"%s\"\n", s->name); switch (s->type) { case(MS_SYMBOL_HATCH): msIO_fprintf(stream, " TYPE HATCH\n"); break; case(MS_SYMBOL_PIXMAP): msIO_fprintf(stream, " TYPE PIXMAP\n"); if(s->imagepath != NULL) msIO_fprintf(stream, " IMAGE \"%s\"\n", s->imagepath); msIO_fprintf(stream, " TRANSPARENT %d\n", s->transparentcolor); break; case(MS_SYMBOL_TRUETYPE): msIO_fprintf(stream, " TYPE TRUETYPE\n"); if(s->antialias == MS_TRUE) msIO_fprintf(stream, " ANTIALIAS TRUE\n"); if (s->character != NULL) msIO_fprintf(stream, " CHARACTER \"%s\"\n", s->character); if (s->font != NULL) msIO_fprintf(stream, " FONT \"%s\"\n", s->font); break; default: if(s->type == MS_SYMBOL_ELLIPSE) msIO_fprintf(stream, " TYPE ELLIPSE\n"); else if(s->type == MS_SYMBOL_VECTOR) msIO_fprintf(stream, " TYPE VECTOR\n"); else if(s->type == MS_SYMBOL_SVG) msIO_fprintf(stream, " TYPE SVG\n"); else msIO_fprintf(stream, " TYPE SIMPLE\n"); if(s->filled == MS_TRUE) msIO_fprintf(stream, " FILLED TRUE\n"); if(s->imagepath != NULL) msIO_fprintf(stream, " IMAGE \"%s\"\n", s->imagepath); /* POINTS */ if(s->numpoints != 0) { msIO_fprintf(stream, " POINTS\n"); for(i=0; inumpoints; i++) { msIO_fprintf(stream, " %g %g\n", s->points[i].x, s->points[i].y); } msIO_fprintf(stream, " END\n"); } break; } msIO_fprintf(stream, " END\n\n"); } /* ** Little helper function to allow us to build symbol files on-the-fly ** from just a file name. ** ** Returns the symbol index or -1 if it could not be added. */ int msAddImageSymbol(symbolSetObj *symbolset, char *filename) { char szPath[MS_MAXPATHLEN]; symbolObj *symbol=NULL; if(!symbolset) { msSetError(MS_SYMERR, "Symbol structure unallocated.", "msAddImageSymbol()"); return(-1); } if(!filename || strlen(filename) == 0) return(-1); /* Allocate/init memory for new symbol if needed */ if (msGrowSymbolSet(symbolset) == NULL) return -1; symbol = symbolset->symbol[symbolset->numsymbols]; #ifdef USE_CURL if (strncasecmp(filename, "http", 4) == 0) { char *tmpfullfilename = NULL; char *tmpfilename = NULL; char *tmppath = NULL; int status = 0; char szPath[MS_MAXPATHLEN]; int bCheckLocalCache = MS_TRUE; tmppath = msTmpPath(NULL, NULL, NULL); if (tmppath) { tmpfilename = msEncodeUrl(filename); tmpfullfilename = msBuildPath(szPath, tmppath, tmpfilename); if (tmpfullfilename) { /*use the url for now as a caching mechanism*/ if (msHTTPGetFile(filename, tmpfullfilename, &status, -1, bCheckLocalCache, 0, 1024*1024 /* 1 MegaByte */) == MS_SUCCESS) { symbol->imagepath = msStrdup(tmpfullfilename); symbol->full_pixmap_path = msStrdup(tmpfullfilename); } else { unlink(tmpfullfilename); msFree(tmpfilename); msFree(tmppath); return MS_FAILURE; } } msFree(tmpfilename); msFree(tmppath); } } #endif /*if the http did not work, allow it to be treated as a file*/ if (!symbol->full_pixmap_path) { if(symbolset->map) { symbol->full_pixmap_path = msStrdup(msBuildPath(szPath, symbolset->map->mappath, filename)); } else { symbol->full_pixmap_path = msStrdup(msBuildPath(szPath, NULL, filename)); } symbol->imagepath = msStrdup(filename); } symbol->name = msStrdup(filename); symbol->type = MS_SYMBOL_PIXMAP; return(symbolset->numsymbols++); } int msFreeSymbolSet(symbolSetObj *symbolset) { int i; freeImageCache(symbolset->imagecache); for(i=0; inumsymbols; i++) { if (symbolset->symbol[i]!=NULL) { if ( msFreeSymbol((symbolset->symbol[i])) == MS_SUCCESS ) { msFree(symbolset->symbol[i]); symbolset->symbol[i]=NULL; } } } msFree(symbolset->symbol); /* no need to deal with fontset, it's a pointer */ return MS_SUCCESS; } void msInitSymbolSet(symbolSetObj *symbolset) { symbolset->filename = NULL; symbolset->imagecache = NULL; symbolset->imagecachesize = 0; /* 0 symbols in the cache */ symbolset->fontset = NULL; symbolset->map = NULL; symbolset->numsymbols = 0; symbolset->maxsymbols = 0; symbolset->symbol = NULL; /* Alloc symbol[] array and ensure there is at least 1 symbol: * symbol 0 which is the default symbol with all default params. */ if (msGrowSymbolSet(symbolset) == NULL) return; /* alloc failed */ symbolset->symbol[0]->type = MS_SYMBOL_ELLIPSE; symbolset->symbol[0]->filled = MS_TRUE; symbolset->symbol[0]->numpoints = 1; symbolset->symbol[0]->points[0].x = 1; symbolset->symbol[0]->points[0].y = 1; /* Just increment numsymbols to reserve symbol 0. * initSymbol() has already been called */ symbolset->numsymbols = 1; } /* ** Ensure there is at least one free entry in the symbol array of this ** symbolSetObj. Grow the allocated symbol[] array if necessary and ** allocate a new symbol for symbol[numsymbols] if there is not already one ** and call initSymbol() on it. ** ** This function is safe to use for the initial allocation of the symbol[] ** array as well (i.e. when maxsymbols==0 and symbol==NULL) ** ** Returns a reference to the new symbolObj on success, NULL on error. */ symbolObj *msGrowSymbolSet( symbolSetObj *symbolset ) { /* Do we need to increase the size of symbol[] by MS_SYMBOL_ALLOCSIZE? */ if (symbolset->numsymbols == symbolset->maxsymbols) { int i; if (symbolset->maxsymbols == 0) { /* Initial allocation of array */ symbolset->maxsymbols += MS_SYMBOL_ALLOCSIZE; symbolset->numsymbols = 0; symbolset->symbol = (symbolObj**)malloc(symbolset->maxsymbols*sizeof(symbolObj*)); } else { /* realloc existing array */ symbolset->maxsymbols += MS_SYMBOL_ALLOCSIZE; symbolset->symbol = (symbolObj**)realloc(symbolset->symbol, symbolset->maxsymbols*sizeof(symbolObj*)); } if (symbolset->symbol == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for symbol array.", "msGrowSymbolSet()"); return NULL; } for(i=symbolset->numsymbols; imaxsymbols; i++) symbolset->symbol[i] = NULL; } if (symbolset->symbol[symbolset->numsymbols]==NULL) { symbolset->symbol[symbolset->numsymbols]=(symbolObj*)malloc(sizeof(symbolObj)); if (symbolset->symbol[symbolset->numsymbols]==NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for a symbolObj", "msGrowSymbolSet()"); return NULL; } } /* Always call initSymbol() even if we didn't allocate a new symbolObj * Since it's possible to dynamically remove/reuse symbols */ initSymbol(symbolset->symbol[symbolset->numsymbols]); return symbolset->symbol[symbolset->numsymbols]; } /* --------------------------------------------------------------------------- msLoadSymbolSet and loadSymbolSet msLoadSymbolSet wraps calls to loadSymbolSet with mutex acquisition and release. It should be used everywhere outside the mapfile loading phase of an application. loadSymbolSet should only be used when a mutex exists. It does not check for existence of a mutex! See bug 339 for more details -- SG. ------------------------------------------------------------------------ */ int msLoadSymbolSet(symbolSetObj *symbolset, mapObj *map) { int retval = MS_FAILURE; msAcquireLock( TLOCK_PARSER ); retval = loadSymbolSet( symbolset, map ); msReleaseLock( TLOCK_PARSER ); return retval; } int loadSymbolSet(symbolSetObj *symbolset, mapObj *map) { int status=1; char szPath[MS_MAXPATHLEN], *pszSymbolPath=NULL; int foundSymbolSetToken=MS_FALSE; int token; if(!symbolset) { msSetError(MS_SYMERR, "Symbol structure unallocated.", "loadSymbolSet()"); return(-1); } symbolset->map = (mapObj *)map; if(!symbolset->filename) return(0); /* ** Open the file */ if((msyyin = fopen(msBuildPath(szPath, symbolset->map->mappath, symbolset->filename), "r")) == NULL) { msSetError(MS_IOERR, "(%s)", "loadSymbolSet()", symbolset->filename); return(-1); } pszSymbolPath = msGetPath(szPath); msyystate = MS_TOKENIZE_FILE; /* restore lexer state to INITIAL, and do return comments */ msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 0; /* reset line counter */ msyyrestart(msyyin); /* flush the scanner - there's a better way but this works for now */ /* ** Read the symbol file */ for(;;) { token = msyylex(); if(!foundSymbolSetToken && token != SYMBOLSET) { msSetError(MS_IDENTERR, "First token must be SYMBOLSET, this doesn't look like a symbol file.", "msLoadSymbolSet()"); return(-1); } switch(token) { case(END): case(EOF): status = 0; break; case(SYMBOL): /* Allocate/init memory for new symbol if needed */ if (msGrowSymbolSet(symbolset) == NULL) { status = -1; } else if((loadSymbol((symbolset->symbol[symbolset->numsymbols]), pszSymbolPath) == -1)) status = -1; else symbolset->numsymbols++; break; case(SYMBOLSET): foundSymbolSetToken = MS_TRUE; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadSymbolSet()", msyystring_buffer, msyylineno); status = -1; } /* end switch */ if(status != 1) break; } /* end for */ fclose(msyyin); msyyin = NULL; free(pszSymbolPath); return(status); } /* ** Returns the size, in pixels, of a marker symbol defined by a specific style and scalefactor. Used for annotation ** layer collision avoidance. A marker is made up of a number of styles so the calling code must either do the looping ** itself or call this function for the bottom style which should be the largest. */ int msGetMarkerSize(symbolSetObj *symbolset, styleObj *style, double *width, double *height, double scalefactor) { rectObj rect; int size; symbolObj *symbol; *width = *height = 0; /* set a starting value */ if(style->symbol > symbolset->numsymbols || style->symbol < 0) return(MS_FAILURE); /* no such symbol, 0 is OK */ if(style->symbol == 0) { /* single point */ *width = 1; *height = 1; return(MS_SUCCESS); } symbol = symbolset->symbol[style->symbol]; if (symbol->type == MS_SYMBOL_PIXMAP && !symbol->pixmap_buffer) { if (MS_SUCCESS != msPreloadImageSymbol(MS_MAP_RENDERER(symbolset->map), symbol)) return MS_FAILURE; } if(symbol->type == MS_SYMBOL_SVG && !symbol->renderer_cache) { #if defined(USE_SVG_CAIRO) || defined (USE_RSVG) if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msGetMarkerSize()"); return MS_FAILURE; #endif } if(style->size == -1) { size = ( msSymbolGetDefaultSize(symbol) * scalefactor ); } else size = (style->size*scalefactor); size = MS_MAX(size, style->minsize); size = MS_MIN(size, style->maxsize); switch(symbol->type) { case(MS_SYMBOL_TRUETYPE): if(msGetTruetypeTextBBox(MS_MAP_RENDERER(symbolset->map),symbol->font,symbolset->fontset,size,symbol->character,&rect,NULL,0) != MS_SUCCESS) return(MS_FAILURE); *width = MS_MAX(*width, rect.maxx - rect.minx); *height = MS_MAX(*height, rect.maxy - rect.miny); break; case(MS_SYMBOL_PIXMAP): if(size == 1) { *width = MS_MAX(*width, symbol->pixmap_buffer->width); *height = MS_MAX(*height, symbol->pixmap_buffer->height); } else { *width = MS_MAX(*width, (((double)size/(double)symbol->pixmap_buffer->height) * symbol->pixmap_buffer->width)); *height = MS_MAX(*height, size); } break; default: /* vector and ellipses, scalable */ if(style->size > 0) { *width = MS_MAX(*width, ((size/symbol->sizey) * symbol->sizex)); *height = MS_MAX(*height, size); } else { /* use symbol defaults */ *width = MS_MAX(*width, symbol->sizex); *height = MS_MAX(*height, symbol->sizey); } break; } return(MS_SUCCESS); } /* * Add a default new symbol. If the symbol name exists * return the id of the symbol. */ int msAddNewSymbol(mapObj *map, char *name) { int i = 0; if (!map || !name) return -1; i = msGetSymbolIndex(&map->symbolset, name, MS_TRUE); if (i >= 0) return i; /* Allocate memory for new symbol if needed */ if (msGrowSymbolSet(&(map->symbolset)) == NULL) return -1; i = map->symbolset.numsymbols; map->symbolset.symbol[i]->name = msStrdup(name); map->symbolset.numsymbols++; return i; } /* msAppendSymbol and msRemoveSymbol are part of the work to resolve * MapServer bug 579. * http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=579 */ int msAppendSymbol(symbolSetObj *symbolset, symbolObj *symbol) { /* Allocate memory for new symbol if needed */ if (msGrowSymbolSet(symbolset) == NULL) return -1; /* we need to free the symbolObj that was already allocated as we are going to replace it with the provided symbolObj*. Not the most efficient technique, but this function should be rarely called, and in any case only by mapscript. Another option could be to use msCopySymbol(), in which case the call to MS_REFCNT_INCR(symbol) should be removed.*/ if(symbolset->symbol[symbolset->numsymbols]) { msFreeSymbol(symbolset->symbol[symbolset->numsymbols]); msFree(symbolset->symbol[symbolset->numsymbols]); } symbolset->symbol[symbolset->numsymbols]=symbol; MS_REFCNT_INCR(symbol); return symbolset->numsymbols++; } symbolObj *msRemoveSymbol(symbolSetObj *symbolset, int nSymbolIndex) { int i; symbolObj *symbol; if (symbolset->numsymbols == 1) { msSetError(MS_CHILDERR, "Cannot remove a symbolset's sole symbol", "removeSymbol()"); return NULL; } else if (nSymbolIndex < 0 || nSymbolIndex >= symbolset->numsymbols) { msSetError(MS_CHILDERR, "Cannot remove symbol, invalid nSymbolIndex %d", "removeSymbol()", nSymbolIndex); return NULL; } else { symbol=symbolset->symbol[nSymbolIndex]; for (i=nSymbolIndex+1; inumsymbols; i++) { symbolset->symbol[i-1] = symbolset->symbol[i]; } symbolset->symbol[i-1]=NULL; symbolset->numsymbols--; MS_REFCNT_DECR(symbol); /* update symbol references in the map */ if (symbolset->map) { int l,c,s,lb; layerObj *layer; classObj *cl; styleObj *style; labelObj *label; for (l = 0; l < symbolset->map->numlayers; l++) { layer = GET_LAYER(symbolset->map, l); for (c = 0; c < layer->numclasses; c++) { cl = layer->class[c]; for (s = 0; s < cl->numstyles; s++) { style = cl->styles[s]; if (style->symbol >= nSymbolIndex) --style->symbol; } for (lb = 0; lb < cl->numlabels; lb++) { label = cl->labels[lb]; for (s = 0; s < label->numstyles; s++) { style = label->styles[s]; if (style->symbol >= nSymbolIndex) --style->symbol; } } } } } return symbol; } } int msSaveSymbolSetStream(symbolSetObj *symbolset, FILE *stream) { int i; if (!symbolset || !stream) { msSetError(MS_SYMERR, "Cannot save symbolset.", "msSaveSymbolSetStream()"); return MS_FAILURE; } /* Don't ever write out the default symbol at index 0 */ for (i=1; inumsymbols; i++) { if(!symbolset->symbol[i]->inmapfile) writeSymbol((symbolset->symbol[i]), stream); } return MS_SUCCESS; } int msSaveSymbolSet(symbolSetObj *symbolset, const char *filename) { FILE *stream; int retval; if (!filename || strlen(filename) == 0) { msSetError(MS_SYMERR, "Invalid filename.", "msSaveSymbolSet()"); return MS_FAILURE; } stream = fopen(filename, "w"); if (stream) { fprintf(stream, "SYMBOLSET\n"); retval = msSaveSymbolSetStream(symbolset, stream); fprintf(stream, "END\n"); fclose(stream); } else { msSetError(MS_SYMERR, "Could not write to %s", "msSaveSymbolSet()", filename); retval = MS_FAILURE; } return retval; } int msLoadImageSymbol(symbolObj *symbol, const char *filename) { msFree(symbol->full_pixmap_path); symbol->full_pixmap_path = msStrdup(filename); return MS_SUCCESS; } int msPreloadImageSymbol(rendererVTableObj *renderer, symbolObj *symbol) { if(symbol->pixmap_buffer && symbol->renderer == renderer) return MS_SUCCESS; if(symbol->pixmap_buffer) { /* other renderer was used, start again */ msFreeRasterBuffer(symbol->pixmap_buffer); } else { symbol->pixmap_buffer = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); } if(MS_SUCCESS != renderer->loadImageFromFile(symbol->full_pixmap_path, symbol->pixmap_buffer)) { /* Free pixmap_buffer already allocated */ free(symbol->pixmap_buffer); symbol->pixmap_buffer = NULL; return MS_FAILURE; } symbol->renderer = renderer; symbol->sizex = symbol->pixmap_buffer->width; symbol->sizey = symbol->pixmap_buffer->height; return MS_SUCCESS; } /*********************************************************************** * msCopySymbol() * * * * Copy a symbolObj, using mapfile.c:initSymbol(), msCopyPoint() * * gdImageCreate(), gdImageCopy() * **********************************************************************/ int msCopySymbol(symbolObj *dst, symbolObj *src, mapObj *map) { int i; initSymbol(dst); MS_COPYSTRING(dst->name, src->name); MS_COPYSTELEM(type); MS_COPYSTELEM(inmapfile); /* map is a special case */ dst->map = map; MS_COPYSTELEM(sizex); MS_COPYSTELEM(sizey); MS_COPYSTELEM(anchorpoint_x); MS_COPYSTELEM(anchorpoint_y); for (i=0; i < src->numpoints; i++) { MS_COPYPOINT(&(dst->points[i]), &(src->points[i])); } MS_COPYSTELEM(numpoints); MS_COPYSTELEM(filled); MS_COPYSTRING(dst->imagepath, src->imagepath); MS_COPYSTELEM(transparent); MS_COPYSTELEM(transparentcolor); MS_COPYSTRING(dst->character, src->character); MS_COPYSTELEM(antialias); MS_COPYSTRING(dst->font, src->font); MS_COPYSTRING(dst->full_pixmap_path,src->full_pixmap_path); return(MS_SUCCESS); } /*********************************************************************** * msCopySymbolSet() * * * * Copy a symbolSetObj using msCopyFontSet(), msCopySymbol() * **********************************************************************/ int msCopySymbolSet(symbolSetObj *dst, symbolSetObj *src, mapObj *map) { int i, return_value; MS_COPYSTRING(dst->filename, src->filename); dst->map = map; dst->fontset = &(map->fontset); /* Copy child symbols */ for (i = 0; i < src->numsymbols; i++) { if (msGrowSymbolSet(dst) == NULL) return MS_FAILURE; return_value = msCopySymbol(dst->symbol[i], src->symbol[i], map); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR,"Failed to copy symbol.","msCopySymbolSet()"); return(MS_FAILURE); } dst->numsymbols++; } /* MS_COPYSTELEM(imagecachesize); */ /* I have a feeling that the code below is not quite right - Sean */ /*copyProperty(&(dst->imagecache), &(src->imagecache), sizeof(struct imageCacheObj)); */ dst->imagecachesize = 0; /* since we are not copying the cache set the cache to NUNLL and the size to 0 (bug 1521) */ dst->imagecache = NULL; return(MS_SUCCESS); } static void get_bbox(pointObj *poiList, int numpoints, double *minx, double *miny, double *maxx, double *maxy) { int j; *minx = *maxx = poiList[0].x; *miny = *maxy = poiList[0].y; for(j=1; jtype == MS_SYMBOL_VECTOR); */ newSymbol = (symbolObj *) malloc(sizeof(symbolObj)); msCopySymbol(newSymbol, symbol, NULL); /* TODO: do we really want to do this for all symbol types? */ angle_rad = (MS_DEG_TO_RAD*angle); sin_a = sin(angle_rad); cos_a = cos(angle_rad); dp_x = symbol->sizex * .5; /* get the shift vector at 0,0 */ dp_y = symbol->sizey * .5; /* center at 0,0 and rotate; then move back */ for( i=0; i < symbol->numpoints; i++) { /* don't rotate PENUP commands (TODO: should use a constant here) */ if ((symbol->points[i].x == -99.0) || (symbol->points[i].x == -99.0) ) { newSymbol->points[i].x = -99.0; newSymbol->points[i].y = -99.0; continue; } newSymbol->points[i].x = dp_x + ((symbol->points[i].x-dp_x)*cos_a - (symbol->points[i].y-dp_y)*sin_a); newSymbol->points[i].y = dp_y + ((symbol->points[i].x-dp_x)*sin_a + (symbol->points[i].y-dp_y)*cos_a); } /* get the new bbox of the symbol, because we need it to get the new dimensions of the new symbol */ get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy); if ( (fabs(minx)>TOL) || (fabs(miny)>TOL) ) { xcor = minx*-1.0; /* symbols always start at 0,0 so get the shift vector */ ycor = miny*-1.0; for( i=0; i < newSymbol->numpoints; i++) { if ((newSymbol->points[i].x == -99.0) || (newSymbol->points[i].x == -99.0)) continue; newSymbol->points[i].x = newSymbol->points[i].x + xcor; newSymbol->points[i].y = newSymbol->points[i].y + ycor; } /* update the bbox to get the final dimension values for the symbol */ get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy); } newSymbol->sizex = maxx; newSymbol->sizey = maxy; return newSymbol; } mapserver-6.4.1/mapsmoothing.c0000644002461700001440000002121312261257215016164 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: RFC94 Shape smoothing * Author: Alan Boudreault (aboudreault@mapgears.com) * Author: Daniel Morissette (dmorissette@mapgears.com) * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include "mapserver.h" #define FP_EPSILON 1e-12 #define FP_EQ(a, b) (fabs((a)-(b)) < FP_EPSILON) /* Internal Use, represent a line window (points) */ typedef struct { int pos; /* current point position in line */ int size; int index; /* index of the current point in points array */ lineObj *line; int lineIsRing; /* closed ring? */ pointObj **points; } lineWindow; static void initLineWindow(lineWindow *lw, lineObj *line, int size) { lw->pos = -1; lw->lineIsRing = MS_FALSE; lw->size = size; lw->line = line; lw->index = floor(lw->size/2); /* index of current position in points array */ lw->points = (pointObj**)msSmallMalloc(sizeof(pointObj*)*size); if ( (line->numpoints >= 2) && ((FP_EQ(line->point[0].x, line->point[line->numpoints-1].x)) && (FP_EQ(line->point[0].y, line->point[line->numpoints-1].y))) ) { lw->lineIsRing = 1; } } static void freeLineWindow(lineWindow *lw) { free(lw->points); } static int nextLineWindow(lineWindow *lw) { int i; if (++lw->pos >= lw->line->numpoints) return MS_DONE; lw->points[lw->index] = &lw->line->point[lw->pos]; for (i=0;iindex;++i) { int r, l; r = lw->pos-(i+1); l = lw->pos+(i+1); /* adjust values */ if ((r < 0) && lw->lineIsRing) r = lw->line->numpoints-(i+2); if ((l >= lw->line->numpoints) && lw->lineIsRing) l = 1+(l-lw->line->numpoints); /* return if the window in not valid.. */ if (r<0 || l>=lw->line->numpoints) return MS_FALSE; lw->points[lw->index-(i+1)] = &lw->line->point[r]; lw->points[lw->index+(i+1)] = &lw->line->point[l]; } return MS_TRUE; } /* Calculates the distance ratio between the total distance of a path and the distance between the first and last point (to detect a loop). */ static double computePathDistanceRatio(pointObj **points, int len) { double sum; int i; for (sum=0,i=1;inumlines; i++) free(newShape->line[i].point); newShape->numlines = 0; if (newShape->line) free(newShape->line); for (i=0;inumlines;++i) { const int windowSize = 5; int res; lineWindow lw; lineObj line = {0, NULL}; initLineWindow(&lw, &shape->line[i], windowSize); msAddLine(newShape, &line); while ((res = nextLineWindow(&lw)) != MS_DONE) { double ratio = 0; pointObj point; if (lw.lineIsRing && lw.pos==lw.line->numpoints-1) { point = newShape->line[i].point[0]; msAddPointToLine(&newShape->line[i], &point); continue; } if (res == MS_FALSE) { /* invalid window */ msAddPointToLine(&newShape->line[i], lw.points[lw.index]); continue; } if (!force) ratio = computePathDistanceRatio(lw.points, windowSize); if (force || (ratio > 1.3)) { point.x = (lw.line->point[lw.pos].x + lw.points[lw.index-1]->x)/2; point.y = (lw.line->point[lw.pos].y + lw.points[lw.index-1]->y)/2; msAddPointToLine(&newShape->line[i], &point); } point = lw.line->point[lw.pos]; msAddPointToLine(&newShape->line[i], &point); if (force || (ratio > 1.3)) { point.x = (lw.line->point[lw.pos].x + lw.points[lw.index+1]->x)/2; point.y = (lw.line->point[lw.pos].y + lw.points[lw.index+1]->y)/2; msAddPointToLine(&newShape->line[i], &point); } } freeLineWindow(&lw); } msFreeShape(shape); return MS_SUCCESS; } shapeObj* msSmoothShapeSIA(shapeObj *shape, int ss, int si, char *preprocessing) { int i, j; pointObj *p; double *coeff; shapeObj *newShape; newShape = (shapeObj *) msSmallMalloc(sizeof (shapeObj)); msInitShape(newShape); if (ss < 3) ss = 3; if (si < 1) si = 1; /* Apply preprocessing */ if (preprocessing) { if (strcasecmp(preprocessing, "all") == 0) processShapePathDistance(shape, MS_TRUE); else if (strcasecmp(preprocessing, "angle") == 0) processShapePathDistance(shape, MS_FALSE); } p = (pointObj *) msSmallMalloc(ss*sizeof(pointObj)); coeff = (double *) msSmallMalloc(ss*sizeof (double)); for (i=0;i 1 && i>0) { msInitShape(&initialShape); msCopyShape(shape, &initialShape); /* Clean our shape object */ for (j=0; j < newShape->numlines; ++j) free(newShape->line[j].point); newShape->numlines = 0; if (newShape->line) free(newShape->line); shape = &initialShape; } for (j=0;jnumlines;++j) { int k, ws, res; lineObj newLine = {0,NULL}; lineWindow lw; /* determine if we can use the ss for this line */ ws = ss; if (ws >= shape->line[j].numpoints) { ws = shape->line[j].numpoints-1; } if (ws%2==0) ws-=1; initLineWindow(&lw, &shape->line[j], ws); msAddLine(newShape, &newLine); coeff[lw.index] = 1; for (k=0;kline[j], lw.points[lw.index]); continue; } /* Apply Coefficient */ p[lw.index] = *lw.points[lw.index]; for (k=0; kline[j], &point); } freeLineWindow(&lw); } if (i>0) { msFreeShape(shape); shape = newShape; } } free(p); free(coeff); return newShape; } mapserver-6.4.1/maplexer.c0000644002461700001440000061514312261257215015307 0ustar tbonfortusers#line 2 "/home/even/mapserver/git/mapserver/maplexer.c" #line 4 "/home/even/mapserver/git/mapserver/maplexer.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define yy_create_buffer msyy_create_buffer #define yy_delete_buffer msyy_delete_buffer #define yy_flex_debug msyy_flex_debug #define yy_init_buffer msyy_init_buffer #define yy_flush_buffer msyy_flush_buffer #define yy_load_buffer_state msyy_load_buffer_state #define yy_switch_to_buffer msyy_switch_to_buffer #define yyin msyyin #define yyleng msyyleng #define yylex msyylex #define yylineno msyylineno #define yyout msyyout #define yyrestart msyyrestart #define yytext msyytext #define yywrap msyywrap #define yyalloc msyyalloc #define yyrealloc msyyrealloc #define yyfree msyyfree #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE msyyrestart(msyyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int msyyleng; extern FILE *msyyin, *msyyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up msyytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up msyytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via msyyrestart()), so that the user can continue scanning by * just pointing msyyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when msyytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int msyyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow msyywrap()'s to do buffer switches * instead of setting up a fresh msyyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void msyyrestart (FILE *input_file ); void msyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE msyy_create_buffer (FILE *file,int size ); void msyy_delete_buffer (YY_BUFFER_STATE b ); void msyy_flush_buffer (YY_BUFFER_STATE b ); void msyypush_buffer_state (YY_BUFFER_STATE new_buffer ); void msyypop_buffer_state (void ); static void msyyensure_buffer_stack (void ); static void msyy_load_buffer_state (void ); static void msyy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER msyy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE msyy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE msyy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE msyy_scan_bytes (yyconst char *bytes,int len ); void *msyyalloc (yy_size_t ); void *msyyrealloc (void *,yy_size_t ); void msyyfree (void * ); #define yy_new_buffer msyy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ msyyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ msyy_create_buffer(msyyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ msyyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ msyy_create_buffer(msyyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *msyyin = (FILE *) 0, *msyyout = (FILE *) 0; typedef int yy_state_type; extern int msyylineno; int msyylineno = 1; extern char *msyytext; #define yytext_ptr msyytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up msyytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ msyyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 333 #define YY_END_OF_BUFFER 334 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[1930] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 334, 331, 1, 329, 322, 2, 331, 331, 315, 328, 315, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 331, 331, 330, 330, 3, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 1, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 332, 1, 1, 6, 327, 332, 327, 332, 316, 316, 10, 7, 9, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 330, 13, 330, 333, 1, 333, 333, 325, 323, 323, 324, 1, 2, 0, 320, 315, 315, 328, 315, 328, 0, 328, 319, 315, 0, 328, 328, 328, 328, 328, 328, 328, 328, 232, 328, 328, 328, 236, 328, 237, 328, 328, 242, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 254, 328, 328, 257, 328, 258, 328, 328, 328, 328, 328, 328, 328, 328, 328, 269, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 212, 328, 328, 296, 297, 328, 298, 328, 328, 328, 328, 328, 328, 328, 328, 328, 0, 308, 0, 321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 328, 328, 328, 236, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 269, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 8, 0, 5, 0, 316, 316, 316, 0, 316, 0, 12, 14, 7, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 16, 12, 10, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 312, 0, 0, 317, 15, 0, 326, 0, 325, 323, 323, 324, 315, 0, 0, 328, 315, 319, 318, 315, 0, 0, 315, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 238, 328, 328, 328, 328, 328, 328, 328, 328, 328, 66, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 81, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 122, 123, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 267, 268, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 284, 328, 328, 328, 328, 328, 328, 328, 328, 328, 290, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 222, 303, 328, 224, 304, 328, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 0, 306, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 267, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 0, 0, 0, 0, 0, 316, 316, 0, 0, 316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 315, 318, 0, 315, 328, 328, 328, 328, 328, 328, 227, 328, 328, 328, 328, 328, 328, 328, 231, 328, 328, 328, 328, 328, 328, 328, 328, 328, 59, 328, 328, 328, 328, 63, 328, 328, 328, 328, 328, 328, 328, 328, 328, 246, 328, 328, 328, 76, 328, 328, 328, 80, 328, 328, 328, 83, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 101, 328, 328, 328, 328, 328, 328, 328, 328, 255, 328, 256, 328, 126, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 157, 328, 265, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 195, 328, 328, 328, 328, 328, 328, 328, 207, 328, 292, 328, 328, 328, 328, 294, 218, 328, 328, 328, 328, 328, 328, 328, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, 0, 0, 328, 328, 59, 328, 76, 328, 328, 328, 328, 328, 328, 328, 195, 328, 328, 294, 313, 0, 316, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 314, 41, 305, 328, 43, 328, 328, 228, 328, 328, 229, 328, 328, 328, 328, 328, 328, 234, 328, 51, 328, 55, 328, 328, 328, 328, 328, 61, 328, 328, 328, 328, 244, 64, 328, 67, 328, 328, 245, 328, 328, 328, 328, 328, 328, 78, 328, 328, 248, 328, 328, 86, 249, 328, 328, 88, 328, 328, 97, 328, 328, 174, 328, 328, 328, 328, 105, 253, 328, 115, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 262, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 263, 328, 240, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 276, 328, 328, 328, 328, 328, 328, 328, 328, 280, 328, 328, 328, 328, 328, 328, 328, 328, 282, 283, 188, 328, 328, 328, 328, 328, 328, 288, 328, 328, 198, 328, 204, 328, 328, 328, 328, 211, 328, 328, 328, 328, 299, 219, 328, 328, 328, 328, 223, 43, 51, 0, 0, 0, 105, 115, 0, 0, 0, 0, 0, 0, 198, 0, 219, 328, 55, 328, 328, 328, 328, 328, 328, 328, 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 328, 328, 328, 328, 328, 328, 230, 328, 49, 233, 328, 235, 328, 328, 328, 328, 56, 328, 328, 328, 328, 328, 328, 62, 328, 328, 328, 328, 69, 328, 72, 73, 247, 328, 75, 328, 328, 328, 328, 87, 250, 328, 328, 328, 328, 328, 328, 251, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 114, 116, 117, 328, 328, 124, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 259, 328, 260, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 266, 158, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 275, 274, 279, 173, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 281, 328, 183, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 286, 287, 328, 289, 197, 328, 200, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 221, 302, 0, 69, 0, 0, 117, 0, 0, 0, 0, 0, 0, 328, 200, 328, 35, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 33, 0, 0, 0, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 54, 328, 328, 301, 328, 328, 241, 328, 243, 328, 328, 328, 71, 328, 77, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 96, 328, 328, 328, 328, 103, 328, 328, 328, 328, 328, 328, 328, 328, 328, 119, 328, 328, 127, 328, 328, 328, 328, 328, 328, 328, 328, 136, 328, 328, 328, 328, 328, 142, 328, 328, 328, 328, 328, 328, 328, 153, 328, 328, 328, 328, 328, 159, 328, 160, 328, 328, 328, 328, 328, 172, 328, 328, 277, 328, 278, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 210, 328, 328, 328, 328, 328, 328, 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 328, 328, 20, 0, 32, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 309, 328, 328, 328, 328, 328, 47, 328, 328, 328, 328, 328, 328, 328, 328, 328, 65, 328, 328, 328, 328, 328, 328, 84, 328, 328, 328, 328, 328, 95, 328, 328, 328, 102, 328, 328, 328, 328, 328, 328, 328, 328, 328, 120, 328, 328, 328, 328, 328, 328, 328, 328, 132, 328, 328, 139, 140, 141, 328, 328, 328, 328, 328, 328, 149, 328, 328, 156, 264, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 171, 328, 328, 175, 328, 328, 177, 328, 328, 328, 181, 328, 328, 328, 328, 185, 328, 190, 328, 328, 285, 328, 328, 328, 328, 328, 328, 328, 205, 94, 328, 209, 328, 328, 328, 293, 295, 300, 328, 0, 0, 0, 0, 181, 0, 0, 190, 0, 205, 34, 0, 29, 37, 0, 0, 31, 24, 0, 19, 0, 0, 328, 328, 44, 328, 46, 328, 50, 328, 52, 328, 328, 328, 39, 328, 328, 70, 328, 328, 328, 85, 328, 92, 93, 328, 90, 328, 99, 100, 328, 328, 328, 328, 108, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 135, 328, 328, 328, 328, 328, 328, 328, 328, 328, 152, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 40, 182, 328, 328, 328, 328, 328, 328, 328, 194, 196, 199, 328, 203, 328, 208, 213, 217, 328, 328, 0, 0, 90, 0, 182, 0, 0, 0, 0, 0, 0, 27, 0, 0, 328, 226, 328, 328, 53, 38, 57, 328, 328, 68, 74, 328, 328, 89, 328, 98, 104, 252, 106, 328, 328, 328, 328, 328, 328, 125, 128, 328, 328, 328, 328, 328, 328, 328, 328, 143, 328, 328, 328, 328, 328, 328, 328, 328, 328, 270, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 239, 328, 178, 179, 328, 184, 328, 186, 189, 191, 328, 193, 328, 328, 328, 328, 220, 0, 89, 179, 186, 0, 23, 26, 28, 25, 0, 0, 42, 328, 328, 328, 60, 328, 328, 328, 328, 107, 328, 328, 328, 328, 328, 129, 130, 134, 131, 328, 328, 328, 138, 144, 328, 151, 148, 328, 328, 155, 328, 271, 328, 328, 328, 328, 328, 328, 328, 328, 328, 169, 328, 273, 291, 328, 180, 328, 192, 201, 328, 328, 328, 216, 0, 216, 0, 0, 328, 48, 328, 328, 79, 328, 91, 328, 328, 328, 118, 328, 328, 328, 137, 328, 328, 154, 328, 328, 161, 162, 163, 328, 165, 328, 328, 328, 328, 328, 328, 328, 328, 328, 215, 0, 0, 0, 328, 328, 187, 82, 109, 111, 113, 328, 328, 133, 328, 150, 261, 272, 328, 328, 328, 328, 170, 328, 328, 328, 328, 328, 187, 0, 0, 328, 58, 328, 328, 328, 328, 147, 328, 166, 167, 328, 176, 145, 328, 328, 214, 0, 310, 45, 328, 328, 121, 146, 328, 328, 328, 206, 311, 328, 328, 328, 328, 202, 328, 328, 328, 328, 110, 112, 328, 328, 328, 168, 328, 328, 164, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 1, 1, 9, 10, 11, 12, 13, 14, 1, 15, 16, 17, 18, 18, 19, 18, 18, 18, 18, 18, 18, 18, 1, 1, 20, 21, 22, 1, 1, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[85] = { 0, 1, 1, 2, 1, 3, 1, 4, 1, 1, 5, 1, 1, 1, 1, 6, 7, 7, 7, 7, 1, 6, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 8, 9, 6, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1 } ; static yyconst flex_int16_t yy_base[1949] = { 0, 0, 0, 84, 0, 168, 0, 252, 0, 335, 339, 340, 341, 945, 4408, 350, 4408, 4408, 0, 930, 340, 342, 400, 357, 351, 400, 460, 421, 468, 401, 484, 482, 400, 320, 335, 533, 534, 473, 585, 593, 321, 549, 640, 646, 655, 496, 700, 0, 885, 849, 4408, 4408, 4408, 329, 333, 341, 375, 391, 520, 406, 394, 394, 412, 537, 405, 410, 459, 533, 375, 607, 466, 707, 716, 702, 595, 665, 471, 570, 532, 723, 663, 476, 752, 761, 724, 763, 772, 782, 538, 4408, 840, 846, 906, 835, 872, 827, 836, 838, 842, 796, 350, 746, 716, 588, 760, 647, 467, 526, 762, 573, 832, 835, 762, 639, 832, 648, 714, 838, 321, 680, 744, 4408, 4408, 866, 746, 739, 0, 777, 815, 868, 878, 0, 717, 700, 888, 893, 0, 895, 620, 686, 953, 835, 910, 873, 870, 949, 843, 913, 842, 940, 862, 951, 0, 866, 896, 881, 954, 947, 0, 896, 899, 0, 960, 955, 952, 955, 987, 970, 950, 1001, 958, 1017, 964, 1011, 962, 962, 964, 1015, 1018, 1004, 1027, 1018, 1030, 1062, 1027, 1027, 1012, 1026, 1068, 0, 1071, 1028, 0, 1036, 0, 1065, 1071, 1113, 1033, 1060, 1077, 1086, 1074, 1067, 1082, 1091, 1098, 1085, 1102, 1114, 1110, 1113, 1118, 1131, 1132, 1137, 1130, 1170, 1141, 1131, 1152, 1149, 1148, 1160, 1180, 1165, 1146, 1187, 1162, 1177, 1193, 1186, 1189, 1184, 1214, 1186, 0, 0, 1196, 0, 1193, 1202, 1213, 1220, 1209, 1225, 1211, 1219, 1238, 617, 4408, 566, 560, 1237, 1247, 1243, 1230, 1250, 1253, 1245, 1240, 1242, 1253, 1255, 1262, 1238, 1240, 1266, 1259, 1269, 568, 1288, 4408, 1263, 1286, 1270, 1275, 1296, 1270, 1285, 1295, 1297, 1295, 1300, 1304, 1298, 1313, 1320, 1295, 1323, 1320, 1307, 1318, 1312, 1328, 0, 1315, 1331, 1318, 1324, 1343, 1338, 1338, 1358, 1337, 1367, 1357, 1361, 1360, 1361, 1354, 1367, 4408, 534, 4408, 524, 1391, 1395, 1412, 929, 1416, 1385, 4408, 4408, 4408, 4408, 1391, 1392, 1373, 1396, 1401, 1395, 1413, 1409, 1405, 1408, 4408, 1403, 1410, 4408, 1405, 4408, 1425, 1413, 1422, 1421, 1418, 1418, 502, 1442, 1443, 1449, 4408, 473, 330, 4408, 4408, 505, 4408, 483, 0, 4408, 4408, 4408, 1480, 1487, 530, 564, 795, 1433, 0, 1485, 1499, 905, 907, 1451, 1454, 1478, 1475, 1479, 1488, 1483, 1488, 1496, 1496, 1498, 1490, 1481, 1499, 1486, 1487, 1490, 1506, 1491, 1492, 1497, 1538, 0, 1513, 1494, 1546, 1497, 1504, 1513, 1518, 1504, 1511, 0, 1533, 1531, 1551, 1540, 1540, 1541, 1550, 1551, 1545, 1546, 1564, 1555, 0, 1556, 1557, 1552, 1569, 1553, 1573, 1577, 1573, 1577, 1598, 1580, 1566, 1583, 1596, 1597, 1605, 1603, 1615, 1614, 1610, 1618, 1621, 1606, 1622, 1623, 0, 0, 1618, 1619, 1661, 1624, 1642, 1630, 1633, 1715, 1639, 1626, 1631, 1666, 1652, 1677, 1670, 1668, 0, 473, 1686, 1689, 1693, 1677, 1677, 1680, 1703, 1720, 1701, 1696, 1729, 1723, 1714, 1739, 1726, 1738, 1726, 1746, 1748, 1758, 1757, 1746, 1753, 1762, 1757, 1760, 0, 1773, 1775, 1765, 1776, 1779, 1774, 1786, 1769, 1780, 0, 1792, 1783, 1780, 1777, 1795, 1779, 1793, 1801, 1793, 1807, 1806, 1808, 1801, 1818, 1820, 1804, 0, 0, 1810, 0, 0, 1816, 1821, 1815, 1822, 1838, 1838, 1841, 1843, 1844, 4408, 1841, 1835, 1849, 1841, 1845, 1853, 1847, 1848, 1846, 4408, 405, 4408, 1848, 1853, 1855, 1869, 1872, 1870, 1858, 1861, 1876, 1878, 1886, 1883, 1889, 1890, 1877, 1891, 1887, 1902, 1894, 1901, 1907, 1908, 1913, 1900, 1913, 1899, 382, 331, 379, 368, 916, 1043, 1924, 1959, 1098, 1149, 1927, 1915, 1925, 1919, 1915, 1918, 1934, 1933, 1925, 1935, 1948, 1949, 1950, 4408, 1940, 1950, 1949, 1952, 1949, 1967, 1964, 1953, 1961, 1977, 1015, 1603, 1463, 4408, 1689, 1694, 1966, 1980, 1968, 1981, 1967, 1990, 373, 1985, 1974, 1982, 1975, 1998, 1983, 2000, 0, 2002, 2009, 2001, 1996, 1996, 2001, 2011, 2016, 2011, 2016, 2020, 2010, 2030, 2032, 0, 2023, 2036, 2017, 2039, 2027, 2043, 2035, 2048, 2033, 0, 2050, 2051, 2044, 2042, 2059, 2062, 2068, 0, 2052, 2055, 2068, 2059, 2065, 2074, 2078, 2068, 2084, 2086, 2072, 2070, 2087, 2079, 2080, 0, 2088, 2095, 2089, 2093, 2102, 2095, 2097, 2111, 0, 2103, 2134, 2113, 0, 2103, 2108, 2117, 2124, 2126, 2120, 2134, 2118, 2142, 2138, 2141, 2132, 2151, 2138, 2139, 2139, 2143, 2149, 2157, 2162, 2164, 2158, 2168, 2190, 2172, 2169, 2161, 2174, 2173, 0, 2179, 0, 2190, 2196, 2176, 2193, 2194, 2198, 2191, 2201, 2206, 2212, 2213, 2208, 2220, 2214, 2205, 2208, 2221, 2209, 2227, 2213, 2230, 2235, 2216, 2240, 2242, 2232, 2238, 2235, 2257, 2252, 2251, 2244, 2263, 2263, 2266, 2258, 2269, 2263, 2265, 2258, 2268, 2264, 2262, 2280, 2272, 2283, 2281, 0, 2282, 0, 2285, 2278, 2283, 2289, 2287, 0, 2295, 2293, 2296, 2313, 2315, 2308, 2317, 0, 2321, 2310, 2325, 2317, 2330, 2324, 2319, 2325, 2336, 2317, 2326, 2333, 2342, 4408, 2344, 2331, 2333, 2334, 2337, 0, 2344, 0, 2354, 2345, 2355, 2353, 2364, 2359, 2354, 0, 2362, 2367, 0, 4408, 2391, 2395, 4408, 2368, 2380, 2384, 2396, 2379, 2394, 2386, 2395, 2384, 2388, 2389, 2389, 2399, 2408, 2402, 2395, 2399, 2410, 2410, 2422, 2391, 2410, 4408, 0, 0, 2404, 0, 2424, 2415, 0, 2413, 2424, 0, 2435, 2425, 2439, 2429, 2434, 2452, 0, 2454, 2454, 2455, 2447, 2459, 2465, 2448, 2469, 2470, 0, 2461, 2455, 2458, 2458, 0, 0, 2470, 0, 2461, 2462, 0, 2466, 2481, 2469, 2465, 2484, 2475, 0, 2475, 2480, 0, 2500, 2486, 0, 0, 2491, 2509, 2522, 2498, 2517, 0, 2521, 2511, 0, 2526, 2502, 2529, 2526, 2554, 0, 2530, 0, 2528, 2543, 2548, 2535, 2533, 2552, 2541, 2549, 2570, 2561, 2559, 2569, 2579, 2584, 2561, 2587, 2577, 2588, 2580, 2594, 2578, 0, 2575, 2598, 2580, 2586, 2605, 2593, 2589, 2597, 2611, 2587, 2615, 2606, 2618, 0, 2609, 0, 2624, 2617, 2610, 2613, 2619, 2618, 2636, 2631, 2626, 2646, 2648, 2633, 2638, 2635, 2639, 2643, 2640, 2647, 2648, 2657, 2661, 2666, 2659, 2652, 2670, 2668, 2666, 2666, 2682, 2675, 2682, 2672, 2677, 2675, 0, 0, 2705, 2680, 2680, 2692, 2706, 2708, 2700, 0, 2711, 2698, 2710, 2709, 0, 2723, 2727, 2715, 2712, 0, 2731, 2727, 2729, 2712, 0, 0, 2721, 2745, 2730, 2733, 0, 4408, 4408, 2734, 2734, 2755, 4408, 4408, 2753, 2759, 2752, 2764, 2749, 2769, 4408, 2757, 4408, 2769, 0, 2759, 2778, 2761, 2777, 2786, 2771, 2779, 2791, 2790, 2779, 2792, 2790, 2798, 2787, 2799, 2802, 2808, 2814, 2797, 2811, 2819, 4408, 2815, 2819, 2822, 2827, 2819, 2808, 2832, 2836, 2824, 2823, 2836, 2833, 2829, 2840, 0, 2847, 0, 0, 2834, 0, 2838, 2837, 2841, 2859, 0, 2847, 2850, 2849, 2856, 2853, 2860, 0, 2872, 2864, 2862, 2873, 0, 2881, 0, 2880, 0, 2872, 0, 2878, 2893, 2874, 2891, 0, 0, 2882, 2887, 2902, 2884, 2882, 2892, 0, 2906, 2902, 2914, 2915, 2911, 2914, 2918, 2902, 2928, 2915, 2911, 2931, 2930, 0, 0, 2931, 2923, 2934, 2925, 2929, 2932, 2934, 2935, 2933, 2952, 2951, 2941, 2952, 2960, 2963, 2953, 2952, 0, 2953, 0, 2960, 2958, 2959, 2960, 2961, 2960, 2979, 2984, 2980, 2988, 2990, 2981, 2979, 2989, 3001, 0, 0, 3000, 374, 2981, 2991, 3008, 3010, 2992, 3006, 3005, 3000, 0, 0, 0, 0, 3015, 3012, 3012, 3010, 3026, 3032, 3015, 3019, 3019, 3025, 3041, 3023, 0, 3031, 0, 3024, 3049, 3049, 3035, 3055, 3054, 3046, 3058, 3061, 3066, 0, 0, 3059, 0, 0, 3052, 3056, 3058, 3059, 3077, 3077, 3064, 3074, 3074, 3090, 3081, 3080, 3092, 3080, 0, 0, 3086, 4408, 3087, 3079, 4408, 3085, 3106, 3094, 3095, 3115, 3116, 3093, 0, 3101, 4408, 4408, 3098, 3111, 3107, 3124, 3116, 3120, 3113, 3128, 3136, 4408, 3126, 3137, 3125, 3131, 3131, 4408, 3148, 3150, 335, 3138, 3149, 3158, 3141, 3158, 3145, 3151, 3162, 3154, 3165, 0, 3164, 3171, 0, 3163, 3178, 0, 3175, 0, 3181, 3182, 3177, 0, 3176, 0, 3183, 3188, 3191, 3188, 3193, 3202, 3187, 3207, 3194, 3200, 0, 3206, 3212, 3205, 3215, 0, 3212, 3219, 3222, 3208, 3223, 3205, 3217, 3215, 3225, 0, 3228, 3236, 0, 3238, 3248, 3229, 3244, 3236, 3238, 3249, 3259, 0, 3256, 3254, 3259, 3267, 3264, 0, 3261, 3271, 3253, 3266, 3259, 3259, 3277, 0, 3274, 3274, 3279, 3283, 3278, 0, 3278, 0, 3278, 3304, 3287, 3313, 3285, 0, 3308, 3305, 0, 3298, 0, 3301, 3318, 3304, 3321, 3322, 3316, 3320, 3332, 3336, 3336, 3335, 3326, 3339, 3331, 3336, 3341, 3349, 3340, 3347, 3344, 3346, 3364, 3368, 3369, 3369, 3373, 3369, 0, 3382, 3370, 3371, 3385, 3386, 3374, 3384, 3382, 3384, 3382, 3390, 3385, 3400, 3397, 3389, 3392, 3433, 3406, 4408, 3393, 4408, 3400, 3395, 4408, 3398, 3417, 3425, 3412, 3408, 3430, 3433, 4408, 3439, 3443, 4408, 3438, 3435, 3432, 3439, 3441, 0, 3438, 3440, 3439, 3448, 3456, 3450, 3464, 3468, 3453, 0, 3461, 3463, 3475, 3468, 3471, 3488, 0, 3480, 3492, 3490, 3487, 3496, 0, 3501, 3498, 3487, 0, 3495, 3492, 3504, 3500, 3501, 3496, 3497, 3496, 3500, 3507, 3496, 3497, 3511, 3509, 3527, 3513, 3528, 3537, 3535, 3520, 3549, 0, 0, 0, 3526, 3541, 3539, 3555, 3538, 3553, 3559, 3542, 3564, 0, 0, 3555, 3570, 3558, 3573, 3560, 3567, 3559, 3577, 3564, 3584, 3559, 3573, 0, 3577, 3568, 0, 3572, 3585, 0, 3586, 3586, 3591, 0, 3599, 3609, 3597, 3600, 0, 3606, 0, 3607, 3618, 0, 3613, 3600, 3619, 3611, 3620, 3633, 3616, 3621, 0, 3614, 0, 3634, 3627, 3636, 0, 0, 0, 3627, 3623, 3631, 3642, 3634, 4408, 3646, 3640, 4408, 3654, 0, 4408, 3657, 4408, 4408, 3636, 3643, 4408, 3650, 3673, 4408, 3667, 3669, 3662, 3669, 0, 3680, 0, 3672, 0, 3671, 0, 3683, 3675, 3674, 0, 3675, 3685, 0, 3687, 3692, 3696, 0, 3685, 0, 0, 3695, 0, 3690, 0, 0, 3701, 3690, 3706, 3712, 0, 3714, 3718, 3713, 3711, 3724, 3722, 3723, 3726, 3731, 3718, 3740, 0, 3727, 3740, 3737, 3727, 3744, 3747, 3746, 3734, 3756, 0, 3756, 3753, 3743, 3755, 3751, 3761, 3748, 3758, 3767, 3760, 3772, 3767, 3759, 3770, 3766, 3761, 3776, 3785, 3786, 3786, 3797, 3796, 3791, 3806, 0, 0, 3793, 3789, 3797, 3799, 3799, 3801, 3814, 0, 0, 0, 3811, 0, 3823, 0, 3804, 0, 3812, 3813, 3808, 3812, 4408, 3818, 4408, 3819, 3821, 3832, 3836, 3826, 3826, 4408, 3836, 3833, 3829, 0, 3848, 3852, 0, 0, 3840, 3853, 3860, 0, 0, 3855, 3856, 0, 3853, 0, 0, 0, 0, 3854, 3874, 3877, 3863, 3884, 3862, 0, 0, 3882, 3869, 3881, 3878, 3891, 3879, 3890, 3890, 0, 3891, 3878, 3891, 3891, 3893, 3904, 3905, 3899, 3888, 0, 3905, 3900, 3902, 3928, 3920, 3917, 3914, 3916, 3924, 3932, 3938, 3924, 3927, 0, 3947, 0, 0, 3929, 0, 3949, 0, 0, 0, 3933, 0, 3947, 3934, 3941, 3953, 0, 3948, 4408, 4408, 4408, 3938, 4408, 4408, 4408, 4408, 3940, 3963, 0, 3950, 3950, 3950, 0, 3961, 3963, 3966, 3966, 0, 3981, 3982, 3990, 3977, 3979, 0, 0, 0, 0, 3985, 3985, 3997, 0, 0, 3996, 0, 0, 3994, 4005, 0, 4006, 0, 4011, 3995, 4006, 3996, 4010, 4000, 4010, 4011, 4012, 0, 4008, 0, 0, 4024, 0, 4018, 0, 4030, 4015, 4028, 4013, 0, 4024, 4408, 4044, 4030, 4034, 0, 4039, 4043, 0, 4047, 0, 4056, 4057, 4045, 0, 4058, 4064, 4059, 0, 4048, 4062, 0, 4057, 4066, 0, 0, 0, 4061, 0, 4054, 4055, 4068, 4071, 4077, 4086, 4085, 4089, 4076, 0, 4083, 4075, 4094, 4085, 4103, 0, 0, 4111, 4113, 0, 4092, 4107, 0, 4117, 0, 0, 0, 4109, 4121, 4124, 4128, 0, 4129, 4130, 4122, 4119, 4119, 4408, 4142, 321, 4123, 0, 4137, 4138, 4139, 4140, 0, 4130, 0, 0, 4149, 0, 0, 4139, 4142, 0, 302, 4408, 0, 4144, 4145, 0, 0, 4147, 4147, 4150, 0, 4408, 4155, 4162, 4175, 4168, 0, 4168, 4171, 4183, 4173, 0, 0, 4176, 4177, 4184, 0, 4182, 4180, 0, 4408, 4251, 4260, 4269, 4278, 4282, 4289, 4298, 4307, 4310, 4319, 4328, 4337, 4346, 4355, 4364, 4371, 4380, 4389, 4398 } ; static yyconst flex_int16_t yy_def[1949] = { 0, 1929, 1, 1929, 3, 1929, 5, 1929, 7, 1930, 1930, 1931, 1931, 1929, 1929, 1929, 1929, 1929, 1932, 1933, 1929, 1934, 1935, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1936, 1937, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1938, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 35, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1940, 1929, 1929, 1929, 1929, 1929, 1941, 1942, 1943, 1929, 1929, 1929, 1929, 1932, 1933, 1933, 1929, 1929, 1934, 1934, 1934, 1944, 1935, 1934, 1929, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1936, 1929, 1937, 1937, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1945, 1929, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1946, 1929, 1947, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1939, 1939, 1929, 1940, 1948, 1929, 1929, 1941, 1929, 1942, 1943, 1929, 1929, 1929, 1929, 1929, 1929, 1934, 1934, 1929, 1934, 1929, 1929, 1929, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1945, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1946, 1946, 1947, 1947, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1939, 1948, 1948, 1929, 1929, 1929, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1939, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1929, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1939, 1939, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1939, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1929, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 1934, 0, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929 } ; static yyconst flex_int16_t yy_nxt[4493] = { 0, 14, 15, 16, 15, 15, 14, 17, 18, 14, 17, 19, 14, 14, 14, 20, 21, 22, 23, 23, 14, 14, 14, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 47, 48, 14, 14, 14, 14, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 47, 49, 14, 14, 14, 14, 14, 14, 50, 51, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 52, 14, 14, 14, 14, 14, 14, 53, 14, 54, 55, 56, 14, 14, 14, 57, 14, 14, 58, 59, 14, 14, 60, 61, 62, 63, 64, 65, 14, 66, 14, 14, 14, 67, 14, 14, 52, 14, 53, 14, 54, 55, 56, 14, 14, 14, 57, 14, 14, 58, 59, 14, 14, 60, 61, 62, 63, 64, 65, 14, 66, 14, 14, 14, 14, 51, 14, 14, 51, 14, 15, 50, 68, 15, 14, 17, 14, 14, 17, 19, 14, 14, 14, 20, 21, 22, 23, 23, 14, 14, 14, 69, 70, 71, 72, 73, 74, 75, 76, 77, 47, 78, 79, 80, 81, 82, 83, 47, 84, 85, 86, 87, 47, 88, 47, 47, 47, 14, 14, 14, 14, 14, 69, 70, 71, 72, 73, 74, 75, 76, 77, 47, 78, 79, 80, 81, 82, 83, 47, 84, 85, 86, 87, 47, 88, 47, 47, 47, 49, 51, 14, 14, 51, 89, 90, 50, 91, 90, 92, 93, 89, 94, 95, 89, 89, 89, 89, 96, 97, 89, 98, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 89, 109, 89, 89, 110, 89, 111, 112, 89, 89, 113, 114, 115, 89, 89, 116, 89, 89, 89, 117, 89, 89, 89, 118, 102, 103, 104, 105, 106, 107, 108, 89, 109, 89, 89, 110, 89, 111, 112, 89, 89, 113, 114, 115, 89, 89, 116, 89, 89, 89, 89, 119, 89, 120, 121, 123, 818, 123, 123, 123, 124, 123, 123, 125, 124, 127, 127, 125, 128, 128, 130, 1910, 130, 130, 134, 185, 135, 135, 137, 137, 186, 323, 215, 253, 187, 254, 255, 138, 354, 324, 1900, 142, 355, 135, 135, 130, 818, 130, 130, 607, 573, 355, 143, 144, 1418, 145, 185, 1343, 129, 129, 851, 186, 146, 215, 253, 187, 254, 255, 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 143, 144, 141, 145, 575, 139, 256, 139, 147, 170, 146, 257, 148, 171, 260, 575, 149, 172, 573, 261, 182, 183, 262, 173, 263, 150, 174, 184, 151, 160, 267, 268, 161, 162, 139, 139, 139, 256, 139, 147, 170, 545, 257, 148, 171, 260, 163, 149, 172, 164, 261, 182, 183, 262, 173, 263, 150, 174, 184, 151, 160, 267, 268, 161, 162, 139, 139, 139, 139, 139, 152, 269, 153, 723, 275, 154, 155, 163, 358, 156, 164, 200, 157, 180, 293, 158, 159, 165, 166, 167, 179, 324, 175, 168, 180, 201, 176, 358, 181, 169, 177, 152, 269, 153, 241, 275, 154, 155, 242, 178, 156, 355, 200, 157, 180, 293, 158, 159, 165, 166, 167, 179, 324, 175, 168, 180, 201, 176, 258, 181, 169, 177, 259, 608, 608, 241, 271, 271, 352, 242, 178, 188, 195, 189, 288, 190, 196, 264, 187, 191, 197, 334, 192, 265, 245, 193, 246, 216, 194, 258, 575, 217, 198, 259, 266, 218, 199, 368, 368, 272, 573, 219, 188, 195, 189, 288, 190, 196, 264, 187, 191, 197, 334, 192, 265, 245, 193, 246, 216, 194, 286, 287, 217, 198, 337, 266, 218, 199, 202, 203, 328, 209, 219, 170, 545, 210, 204, 171, 205, 211, 206, 283, 212, 207, 208, 213, 329, 284, 214, 366, 367, 286, 287, 368, 368, 337, 273, 252, 274, 202, 203, 328, 209, 252, 170, 146, 210, 204, 171, 205, 211, 206, 283, 212, 207, 208, 213, 329, 284, 214, 220, 221, 222, 250, 230, 223, 224, 273, 231, 274, 225, 343, 232, 332, 226, 236, 146, 227, 233, 228, 346, 234, 229, 175, 237, 291, 238, 333, 235, 292, 239, 220, 221, 222, 240, 230, 223, 224, 369, 231, 285, 225, 343, 232, 332, 226, 236, 133, 227, 233, 228, 346, 234, 229, 175, 237, 291, 238, 333, 235, 292, 239, 243, 244, 133, 240, 245, 152, 246, 153, 247, 285, 280, 281, 278, 248, 276, 161, 279, 277, 347, 289, 158, 282, 358, 290, 302, 326, 358, 136, 218, 327, 356, 243, 244, 136, 341, 245, 152, 246, 153, 247, 325, 280, 281, 278, 248, 276, 161, 279, 277, 347, 289, 158, 282, 294, 290, 302, 326, 298, 136, 218, 327, 295, 335, 205, 136, 299, 303, 304, 296, 297, 330, 300, 307, 331, 301, 341, 308, 336, 305, 342, 236, 361, 309, 306, 294, 310, 368, 368, 298, 237, 322, 311, 295, 335, 205, 239, 299, 303, 304, 296, 297, 330, 300, 307, 331, 301, 341, 308, 336, 305, 342, 236, 361, 309, 306, 130, 310, 130, 130, 362, 237, 130, 311, 130, 130, 316, 239, 317, 317, 318, 318, 320, 338, 317, 317, 312, 344, 349, 319, 370, 345, 130, 321, 130, 130, 340, 350, 339, 363, 315, 362, 363, 351, 130, 314, 130, 130, 313, 381, 384, 373, 373, 352, 338, 374, 374, 312, 344, 349, 319, 370, 345, 387, 321, 375, 390, 340, 350, 339, 364, 364, 376, 142, 351, 135, 135, 137, 137, 365, 381, 384, 363, 391, 143, 392, 138, 374, 374, 374, 374, 312, 371, 371, 387, 252, 375, 390, 577, 577, 250, 372, 382, 376, 397, 398, 133, 576, 576, 1929, 365, 577, 577, 383, 391, 143, 392, 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 372, 382, 141, 397, 398, 139, 377, 139, 385, 393, 378, 388, 383, 395, 386, 396, 399, 379, 401, 402, 400, 403, 408, 380, 411, 389, 1929, 406, 407, 394, 414, 419, 420, 421, 139, 139, 139, 377, 139, 385, 393, 378, 388, 404, 395, 386, 396, 399, 379, 401, 402, 400, 403, 408, 380, 411, 389, 405, 406, 407, 394, 414, 419, 420, 421, 139, 139, 139, 139, 139, 422, 409, 412, 423, 404, 410, 413, 415, 426, 416, 417, 424, 427, 418, 428, 429, 434, 425, 405, 1929, 435, 436, 437, 577, 577, 1929, 445, 446, 607, 457, 355, 422, 409, 412, 423, 1929, 410, 413, 415, 426, 416, 417, 424, 427, 418, 428, 429, 434, 425, 430, 431, 435, 436, 437, 438, 432, 442, 445, 446, 451, 457, 443, 444, 458, 463, 447, 433, 448, 449, 464, 439, 465, 440, 450, 459, 452, 466, 441, 581, 581, 430, 431, 460, 467, 461, 438, 432, 442, 462, 468, 451, 469, 443, 444, 458, 463, 447, 433, 448, 449, 464, 439, 465, 440, 450, 459, 452, 466, 441, 453, 454, 455, 472, 460, 467, 461, 470, 456, 471, 462, 468, 473, 469, 474, 475, 478, 480, 476, 481, 581, 581, 479, 489, 482, 477, 1929, 490, 491, 492, 1929, 453, 454, 455, 472, 493, 494, 1929, 470, 456, 471, 498, 499, 473, 502, 474, 475, 478, 480, 476, 481, 483, 484, 479, 489, 482, 477, 485, 490, 491, 492, 486, 487, 500, 488, 503, 493, 494, 495, 496, 504, 510, 498, 499, 505, 502, 507, 514, 508, 1929, 515, 497, 483, 484, 509, 506, 516, 501, 485, 517, 511, 518, 486, 487, 500, 488, 503, 519, 512, 495, 496, 504, 510, 520, 521, 505, 522, 507, 514, 508, 513, 515, 497, 523, 524, 509, 506, 516, 501, 525, 517, 511, 518, 526, 527, 528, 529, 532, 519, 512, 530, 533, 534, 535, 520, 521, 536, 522, 538, 539, 540, 513, 541, 542, 523, 524, 543, 375, 382, 537, 525, 546, 1929, 531, 526, 527, 528, 529, 532, 271, 271, 530, 533, 534, 535, 549, 550, 536, 378, 538, 539, 540, 404, 541, 542, 379, 407, 543, 375, 382, 537, 380, 546, 547, 531, 548, 409, 552, 425, 554, 551, 415, 272, 553, 417, 557, 549, 550, 555, 378, 558, 443, 559, 404, 432, 453, 379, 407, 460, 560, 561, 562, 380, 471, 547, 556, 548, 409, 552, 425, 554, 551, 415, 563, 553, 417, 557, 564, 479, 555, 487, 558, 443, 559, 566, 432, 453, 565, 567, 460, 560, 561, 562, 500, 471, 568, 556, 507, 510, 569, 570, 571, 580, 580, 563, 509, 581, 581, 564, 479, 506, 487, 318, 318, 320, 566, 317, 317, 565, 567, 314, 319, 582, 583, 500, 321, 568, 584, 507, 510, 569, 570, 571, 318, 318, 587, 509, 578, 578, 585, 586, 506, 319, 590, 588, 591, 579, 592, 593, 594, 595, 314, 319, 582, 583, 596, 321, 589, 584, 597, 598, 599, 600, 602, 601, 1929, 587, 609, 603, 604, 585, 586, 1929, 319, 590, 588, 591, 579, 592, 593, 594, 595, 605, 612, 608, 608, 596, 613, 589, 1929, 597, 598, 599, 600, 602, 601, 352, 352, 609, 603, 604, 364, 364, 352, 366, 366, 371, 371, 608, 608, 365, 614, 615, 605, 612, 372, 610, 610, 613, 616, 611, 611, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 1929, 636, 637, 365, 614, 615, 640, 641, 372, 642, 643, 644, 616, 645, 1929, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 636, 637, 638, 646, 647, 640, 641, 634, 642, 643, 644, 648, 645, 635, 649, 650, 651, 652, 654, 639, 655, 656, 657, 659, 660, 653, 661, 662, 663, 664, 633, 665, 658, 638, 646, 647, 666, 667, 634, 668, 671, 672, 648, 673, 635, 649, 650, 651, 652, 654, 639, 655, 656, 657, 659, 660, 653, 661, 662, 663, 664, 669, 665, 658, 674, 670, 675, 666, 667, 676, 668, 671, 672, 678, 673, 679, 680, 681, 682, 677, 683, 684, 685, 686, 687, 688, 1929, 607, 700, 844, 703, 1929, 669, 704, 1929, 674, 670, 675, 701, 715, 676, 716, 702, 717, 678, 1929, 679, 680, 681, 682, 677, 683, 684, 685, 686, 687, 688, 689, 690, 700, 691, 703, 692, 693, 704, 694, 718, 719, 695, 701, 715, 696, 716, 702, 717, 697, 698, 720, 721, 699, 611, 611, 722, 1929, 724, 611, 611, 725, 689, 690, 728, 691, 729, 692, 693, 730, 694, 718, 719, 695, 726, 731, 696, 734, 727, 735, 697, 698, 720, 721, 699, 705, 706, 722, 707, 724, 708, 709, 725, 710, 732, 728, 711, 729, 740, 736, 730, 738, 733, 712, 713, 726, 731, 714, 734, 727, 735, 741, 739, 743, 744, 745, 705, 706, 742, 707, 746, 708, 709, 737, 710, 732, 747, 711, 748, 740, 736, 749, 738, 733, 712, 713, 750, 751, 714, 752, 753, 754, 741, 739, 743, 744, 745, 755, 756, 742, 758, 746, 759, 760, 737, 761, 762, 747, 763, 748, 757, 764, 749, 765, 766, 767, 768, 750, 751, 769, 752, 753, 754, 770, 771, 772, 773, 774, 755, 756, 775, 758, 776, 759, 760, 777, 761, 762, 779, 763, 778, 757, 764, 782, 765, 766, 767, 768, 780, 783, 769, 784, 785, 786, 770, 771, 772, 773, 774, 787, 781, 775, 788, 776, 789, 790, 777, 791, 792, 779, 793, 778, 794, 795, 782, 796, 797, 798, 799, 780, 783, 800, 784, 785, 786, 801, 802, 803, 634, 804, 787, 781, 638, 788, 805, 789, 790, 653, 791, 792, 806, 793, 807, 794, 795, 669, 796, 797, 798, 799, 808, 676, 800, 810, 702, 811, 801, 802, 803, 634, 804, 809, 726, 638, 812, 805, 732, 813, 653, 738, 756, 806, 814, 807, 815, 816, 669, 817, 778, 578, 578, 808, 676, 1929, 810, 702, 811, 821, 579, 822, 823, 824, 809, 726, 825, 812, 826, 732, 813, 827, 738, 756, 828, 814, 829, 815, 816, 830, 817, 778, 819, 819, 831, 832, 820, 820, 833, 834, 821, 579, 822, 823, 824, 835, 836, 825, 837, 826, 838, 839, 827, 840, 841, 828, 1929, 829, 842, 843, 830, 845, 846, 352, 847, 831, 832, 848, 849, 833, 834, 352, 850, 852, 853, 854, 835, 836, 855, 837, 856, 838, 839, 857, 840, 841, 858, 352, 859, 842, 843, 860, 845, 846, 862, 847, 863, 864, 848, 849, 865, 866, 867, 850, 852, 853, 854, 868, 871, 855, 861, 856, 872, 869, 857, 870, 873, 858, 874, 859, 875, 876, 860, 877, 878, 862, 879, 863, 864, 880, 881, 865, 866, 867, 882, 883, 884, 885, 868, 871, 886, 861, 887, 872, 869, 888, 870, 873, 889, 874, 890, 875, 876, 891, 877, 878, 892, 879, 893, 894, 880, 881, 895, 896, 897, 882, 883, 884, 885, 898, 899, 886, 900, 887, 901, 902, 888, 903, 904, 889, 905, 890, 906, 909, 891, 907, 910, 892, 911, 893, 894, 912, 908, 895, 896, 897, 913, 914, 915, 918, 898, 899, 919, 900, 920, 901, 902, 921, 903, 904, 922, 905, 923, 906, 909, 924, 907, 910, 916, 911, 925, 926, 912, 908, 930, 917, 927, 913, 914, 915, 918, 931, 928, 919, 932, 920, 933, 934, 921, 935, 936, 922, 937, 923, 929, 938, 924, 939, 940, 916, 941, 925, 926, 942, 943, 930, 917, 927, 947, 948, 949, 1929, 931, 928, 950, 932, 951, 933, 934, 952, 935, 936, 953, 937, 944, 929, 938, 956, 939, 940, 945, 941, 954, 957, 942, 943, 955, 958, 959, 947, 948, 949, 946, 960, 961, 950, 962, 951, 963, 964, 952, 965, 966, 953, 967, 944, 968, 969, 956, 970, 971, 945, 974, 954, 957, 972, 975, 955, 958, 959, 973, 976, 977, 946, 960, 961, 978, 962, 979, 963, 964, 980, 965, 966, 981, 967, 982, 968, 969, 983, 970, 971, 984, 974, 985, 986, 972, 975, 987, 988, 989, 973, 976, 977, 990, 991, 992, 978, 993, 979, 994, 995, 980, 996, 997, 981, 998, 982, 999, 1000, 983, 1005, 1003, 984, 1001, 985, 986, 1006, 1002, 987, 988, 989, 1004, 1007, 1008, 990, 991, 992, 1009, 993, 1010, 994, 995, 1011, 996, 997, 1012, 998, 1013, 999, 1000, 1014, 1005, 1003, 1015, 1001, 1016, 1017, 1006, 1002, 1018, 1019, 1020, 1004, 1007, 1008, 1021, 1022, 1023, 1009, 1024, 1010, 1025, 1026, 1011, 1027, 1028, 1012, 1029, 1013, 1030, 1031, 1014, 1032, 1033, 1015, 1034, 1016, 1017, 1035, 1036, 1018, 1019, 1020, 1037, 907, 1038, 1021, 1022, 1023, 954, 1024, 1039, 1025, 1026, 1040, 1027, 1028, 1041, 1029, 1042, 1030, 1031, 1043, 1032, 1033, 1044, 1034, 820, 820, 1035, 1036, 820, 820, 1045, 1037, 907, 1038, 1046, 1047, 1048, 954, 1049, 1039, 1050, 1051, 1040, 1052, 1053, 1041, 1054, 1042, 1055, 1056, 1043, 1057, 1058, 1044, 1059, 1060, 1061, 352, 1063, 1065, 1062, 1045, 1066, 1064, 1067, 1046, 1047, 1048, 1068, 1049, 1069, 1050, 1051, 1070, 1052, 1053, 352, 1054, 1071, 1055, 1056, 1072, 1057, 1058, 1073, 1059, 1060, 1061, 352, 1074, 1065, 1062, 1075, 1066, 1064, 1067, 1076, 1079, 1077, 1068, 1078, 1069, 1080, 1081, 1070, 1082, 1083, 1084, 1085, 1071, 1086, 1087, 1072, 1088, 1089, 1073, 1090, 1091, 1092, 1093, 1074, 1094, 1095, 1075, 1096, 1097, 1098, 1076, 1079, 1077, 1099, 1078, 1100, 1080, 1081, 1101, 1082, 1083, 1084, 1085, 1102, 1086, 1087, 1103, 1088, 1089, 1104, 1090, 1091, 1092, 1093, 1105, 1094, 1095, 1112, 1096, 1097, 1098, 1113, 1114, 1115, 1099, 1106, 1100, 1117, 1118, 1101, 1119, 1120, 1929, 1116, 1102, 1107, 1929, 1103, 1108, 1109, 1104, 1929, 1110, 1111, 1126, 1105, 1127, 1128, 1112, 1129, 1130, 1131, 1113, 1114, 1115, 1132, 1106, 1121, 1117, 1118, 1122, 1119, 1120, 1123, 1116, 1133, 1107, 1124, 1134, 1108, 1109, 1135, 1125, 1110, 1111, 1126, 1136, 1127, 1128, 1137, 1129, 1130, 1131, 1138, 1139, 1140, 1132, 1141, 1121, 1142, 1143, 1122, 1144, 1145, 1123, 1146, 1133, 1147, 1124, 1134, 1148, 1149, 1135, 1125, 1150, 1151, 1152, 1136, 1153, 1154, 1137, 1155, 1156, 1157, 1138, 1139, 1140, 1158, 1141, 1159, 1142, 1143, 1160, 1144, 1145, 1161, 1146, 1162, 1147, 1163, 1164, 1148, 1149, 1165, 1166, 1150, 1151, 1152, 1167, 1153, 1154, 1168, 1155, 1156, 1157, 1169, 1170, 1171, 1158, 1172, 1159, 1173, 1174, 1160, 1175, 1176, 1161, 1177, 1162, 1178, 1163, 1164, 1179, 1180, 1165, 1166, 1181, 1184, 1185, 1167, 1182, 1186, 1168, 1187, 1188, 1190, 1169, 1170, 1171, 1183, 1172, 1189, 1173, 1174, 1191, 1175, 1176, 1192, 1177, 1193, 1178, 1194, 1195, 1179, 1180, 1196, 1197, 1181, 1184, 1185, 1201, 1182, 1186, 1202, 1187, 1188, 1190, 1198, 1203, 1199, 1183, 1204, 1189, 1205, 1206, 1191, 1207, 1208, 1192, 1209, 1193, 1210, 1194, 1195, 1211, 1200, 1196, 1197, 1212, 1213, 1215, 1201, 1216, 1217, 1202, 1214, 1219, 1220, 1198, 1203, 1199, 1221, 1204, 1218, 1205, 1206, 1222, 1207, 1208, 1223, 1209, 1224, 1210, 1225, 1226, 1211, 1200, 1229, 1227, 1212, 1213, 1215, 1230, 1216, 1217, 1231, 1214, 1219, 1220, 1232, 1233, 1234, 1221, 1235, 1218, 1228, 1077, 1222, 1078, 1093, 1223, 1106, 1224, 1116, 1225, 1226, 1123, 1236, 1229, 1227, 1178, 1237, 1238, 1230, 1239, 1125, 1231, 1240, 1241, 1242, 1232, 1233, 1234, 1243, 1235, 1244, 1228, 1077, 1245, 1078, 1093, 1246, 1106, 1247, 1116, 1248, 1249, 1123, 1236, 1250, 1251, 1178, 1237, 1238, 1252, 1239, 1125, 1253, 1240, 1241, 1242, 1254, 1255, 1256, 1243, 1258, 1244, 352, 1257, 1245, 1260, 1259, 1246, 1261, 1247, 1262, 1248, 1249, 1263, 1264, 1250, 1251, 1265, 1266, 1267, 1252, 1268, 1269, 1253, 1270, 1271, 352, 1254, 1255, 1256, 352, 1258, 1272, 1273, 1274, 1275, 1260, 1259, 1276, 1261, 1277, 1262, 1278, 1279, 1263, 1264, 1280, 1281, 1265, 1266, 1267, 1282, 1268, 1269, 1283, 1270, 1271, 1284, 1285, 1286, 1287, 1288, 1289, 1272, 1273, 1274, 1275, 1290, 1291, 1276, 1292, 1277, 1293, 1278, 1279, 1294, 1295, 1280, 1281, 1296, 1297, 1298, 1282, 1299, 1300, 1283, 1301, 1302, 1284, 1285, 1286, 1287, 1288, 1289, 1303, 1304, 1305, 1306, 1290, 1291, 1308, 1292, 1309, 1293, 1310, 1307, 1294, 1295, 1311, 1312, 1296, 1297, 1298, 1313, 1299, 1300, 1314, 1301, 1302, 1315, 1316, 1317, 1318, 1319, 1320, 1303, 1304, 1305, 1306, 1321, 1322, 1308, 1323, 1309, 1324, 1310, 1307, 1325, 1326, 1311, 1312, 1327, 1328, 1329, 1313, 1330, 1331, 1314, 1332, 1333, 1315, 1316, 1317, 1318, 1319, 1320, 1334, 1335, 1336, 1337, 1321, 1322, 1338, 1323, 1339, 1324, 1340, 1341, 1325, 1326, 1342, 1344, 1327, 1328, 1329, 1345, 1330, 1331, 1346, 1332, 1333, 1347, 1348, 1349, 1350, 1351, 1352, 1334, 1335, 1336, 1337, 1353, 1354, 1338, 1355, 1339, 1356, 1340, 1341, 1357, 1358, 1342, 1344, 1359, 1360, 1361, 1345, 1362, 1363, 1346, 1364, 1365, 1347, 1348, 1349, 1350, 1351, 1352, 1366, 1367, 1368, 1369, 1353, 1354, 1370, 1355, 1371, 1356, 1372, 1373, 1357, 1358, 1375, 1376, 1359, 1360, 1361, 1377, 1362, 1363, 1378, 1364, 1365, 1379, 1380, 1374, 1381, 1382, 1383, 1366, 1367, 1368, 1369, 1384, 1385, 1370, 1386, 1371, 1387, 1372, 1373, 1388, 1389, 1375, 1376, 1390, 1391, 1392, 1377, 1393, 1394, 1378, 1395, 1396, 1379, 1380, 1374, 1381, 1382, 1383, 1397, 1398, 1399, 1400, 1384, 1385, 1401, 1386, 1402, 1387, 1403, 1404, 1388, 1389, 1405, 1406, 1390, 1391, 1392, 1407, 1393, 1394, 1408, 1395, 1396, 1409, 1410, 1411, 1412, 1413, 1414, 1397, 1398, 1399, 1400, 1415, 1416, 1401, 1419, 1402, 1417, 1403, 1404, 1420, 1421, 1405, 1406, 1422, 1423, 1424, 1407, 1425, 1426, 1408, 1427, 1428, 1409, 1410, 1411, 1412, 1413, 1414, 352, 1429, 352, 1430, 1415, 1416, 1431, 1419, 1432, 1417, 1433, 1434, 1420, 1421, 1435, 1436, 1422, 1423, 1424, 1437, 1425, 1426, 1438, 1427, 1428, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1429, 1446, 1430, 1447, 1448, 1431, 1449, 1432, 1450, 1433, 1434, 1451, 1452, 1435, 1436, 1453, 1454, 1455, 1437, 1456, 1457, 1438, 1458, 1459, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1460, 1446, 1461, 1447, 1448, 1462, 1449, 1463, 1450, 1464, 1465, 1451, 1452, 1466, 1467, 1453, 1454, 1455, 1468, 1456, 1457, 1469, 1458, 1459, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1460, 1477, 1461, 1478, 1479, 1462, 1480, 1463, 1481, 1464, 1465, 1482, 1483, 1466, 1467, 1484, 1485, 1486, 1468, 1487, 1488, 1469, 1489, 1490, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1493, 1477, 1499, 1478, 1479, 1491, 1480, 1500, 1481, 1501, 1502, 1482, 1483, 1494, 1495, 1484, 1485, 1486, 1503, 1487, 1488, 1504, 1489, 1490, 1496, 1492, 1497, 1505, 1506, 1507, 1498, 1493, 1508, 1499, 1509, 1510, 1491, 1511, 1500, 1512, 1501, 1502, 1513, 1514, 1494, 1495, 1515, 1516, 1517, 1503, 1518, 1519, 1504, 1520, 1521, 1496, 1492, 1497, 1505, 1506, 1507, 1498, 1522, 1508, 1523, 1509, 1510, 1524, 1511, 1525, 1512, 1526, 1527, 1513, 1514, 1528, 1529, 1515, 1516, 1517, 1530, 1518, 1519, 1531, 1520, 1521, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1522, 1539, 1523, 1540, 1541, 1524, 1542, 1525, 1543, 1526, 1527, 1544, 1545, 1528, 1529, 1546, 1547, 1548, 1530, 1549, 1550, 1531, 1929, 1551, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1552, 1539, 1553, 1540, 1541, 1554, 1542, 1555, 1543, 1494, 1495, 1544, 1545, 1556, 1557, 1546, 1547, 1548, 1558, 1549, 1550, 1560, 1497, 1551, 1561, 1562, 1498, 1563, 1564, 1559, 1565, 1552, 1566, 1553, 1567, 1568, 1554, 1569, 1555, 1570, 1494, 1495, 352, 1571, 1556, 1557, 352, 1572, 1573, 1558, 1574, 1575, 1560, 1497, 1576, 1561, 1562, 1498, 1563, 1564, 1559, 1565, 1577, 1566, 1578, 1567, 1568, 1579, 1569, 1580, 1570, 1581, 1582, 1583, 1571, 1584, 1585, 1586, 1572, 1573, 1587, 1574, 1575, 1588, 1589, 1576, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1577, 1597, 1578, 1598, 1599, 1579, 1600, 1580, 1601, 1581, 1582, 1583, 1602, 1584, 1585, 1586, 1603, 1604, 1587, 1605, 1606, 1588, 1589, 1607, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1608, 1597, 1609, 1598, 1599, 1610, 1600, 1611, 1601, 1612, 1613, 1614, 1602, 1615, 1616, 1617, 1603, 1604, 1618, 1605, 1606, 1619, 1620, 1607, 1621, 1622, 1623, 1624, 1625, 1626, 1629, 1608, 1630, 1609, 1632, 1627, 1610, 1633, 1611, 1634, 1612, 1613, 1614, 1628, 1615, 1616, 1617, 1635, 1631, 1618, 1636, 1637, 1619, 1620, 1638, 1621, 1622, 1623, 1624, 1625, 1626, 1629, 1639, 1630, 1640, 1632, 1627, 1641, 1633, 1642, 1634, 1643, 1644, 1645, 1628, 1646, 1647, 1648, 1635, 1631, 1649, 1636, 1637, 1650, 1651, 1638, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1639, 1659, 1640, 1660, 1661, 1641, 1662, 1642, 1663, 1643, 1644, 1645, 1664, 1646, 1647, 1648, 1665, 1666, 1649, 1667, 1668, 1650, 1651, 1669, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1670, 1659, 1673, 1660, 1661, 1671, 1662, 1672, 1663, 1674, 1675, 1676, 1664, 1677, 1678, 1679, 1665, 1666, 1680, 1667, 1668, 1681, 352, 1669, 352, 1682, 1683, 1684, 1685, 1686, 1687, 1670, 1688, 1673, 1689, 1690, 1671, 1691, 1672, 1692, 1674, 1675, 1676, 1693, 1677, 1678, 1679, 1694, 1695, 1680, 1696, 1697, 1681, 1698, 1699, 1700, 1682, 1683, 1684, 1685, 1686, 1687, 1701, 1688, 1702, 1689, 1690, 1703, 1691, 1704, 1692, 1705, 1706, 1707, 1693, 1708, 1709, 1710, 1694, 1695, 1711, 1696, 1697, 1712, 1698, 1699, 1700, 1713, 1714, 1715, 1716, 1717, 1718, 1701, 1719, 1702, 1720, 1721, 1703, 1722, 1704, 1723, 1705, 1706, 1707, 1724, 1708, 1709, 1710, 1725, 1726, 1711, 1727, 1728, 1712, 1729, 1730, 1731, 1713, 1714, 1715, 1716, 1717, 1718, 1732, 1719, 1733, 1720, 1721, 1734, 1722, 1735, 1723, 1736, 1737, 1738, 1724, 1739, 1740, 1741, 1725, 1726, 1742, 1727, 1728, 1743, 1729, 1730, 1731, 1744, 1745, 1746, 1747, 1748, 1749, 1732, 1750, 1733, 1751, 1752, 1734, 1753, 1735, 1754, 1736, 1737, 1738, 1755, 1739, 1740, 1741, 1756, 1757, 1742, 1758, 1760, 1743, 1761, 1759, 1762, 1744, 1745, 1746, 1747, 1748, 1749, 1763, 1750, 352, 1751, 1752, 352, 1753, 1764, 1754, 1765, 1766, 1767, 1755, 1768, 1769, 1770, 1756, 1757, 1771, 1758, 1760, 1772, 1761, 1759, 1762, 1773, 1774, 1775, 1776, 1777, 1778, 1763, 1779, 1780, 1781, 1782, 1783, 1784, 1764, 1785, 1765, 1766, 1767, 1786, 1768, 1769, 1770, 1787, 1788, 1771, 1789, 1790, 1772, 1791, 1792, 1793, 1773, 1774, 1775, 1776, 1777, 1778, 1794, 1779, 1780, 1781, 1782, 1783, 1784, 1795, 1785, 1796, 1797, 1798, 1786, 1799, 1800, 1801, 1787, 1788, 1802, 1789, 1790, 1803, 1791, 1792, 1793, 1804, 1805, 1806, 1807, 1808, 1809, 1794, 1810, 1811, 1812, 1814, 1815, 1816, 1795, 1929, 1796, 1797, 1798, 1818, 1799, 1800, 1801, 352, 1819, 1802, 1817, 1813, 1803, 1820, 1821, 1822, 1804, 1805, 1806, 1807, 1808, 1809, 1823, 1810, 1811, 1812, 1814, 1815, 1816, 1824, 352, 1825, 1826, 1827, 1818, 1828, 1829, 1830, 1831, 1819, 1832, 1817, 1813, 1833, 1820, 1821, 1822, 1834, 1835, 1836, 1837, 1838, 1839, 1823, 1840, 1841, 1842, 1843, 1844, 1845, 1824, 1846, 1825, 1826, 1827, 1847, 1828, 1829, 1830, 1831, 1848, 1832, 1849, 1850, 1833, 1851, 1852, 1853, 1834, 1835, 1836, 1837, 1838, 1839, 1856, 1840, 1841, 1842, 1843, 1844, 1845, 1854, 1846, 1857, 1855, 1858, 1847, 352, 1859, 1860, 1861, 1848, 1862, 1849, 1850, 1863, 1851, 1852, 1853, 1864, 1865, 352, 1866, 1867, 1868, 1856, 1869, 1870, 1871, 1872, 1873, 1874, 1854, 1875, 1857, 1855, 1858, 1876, 1877, 1859, 1860, 1861, 1878, 1862, 1879, 1880, 1863, 1882, 1883, 1881, 1864, 1865, 352, 1866, 1867, 1868, 1884, 1869, 1870, 1871, 1872, 1873, 1874, 1885, 1875, 1886, 1887, 1888, 1876, 1877, 1889, 352, 1890, 1878, 1891, 1879, 1880, 1892, 1882, 1883, 1881, 1893, 1894, 1895, 1896, 1897, 1898, 1884, 1929, 1901, 1902, 1903, 1904, 1905, 1885, 1899, 1886, 1887, 1888, 1906, 1907, 1889, 1908, 1890, 1909, 1891, 1911, 1912, 1892, 1913, 1914, 1915, 1893, 1894, 1895, 1896, 1897, 1898, 1916, 352, 1901, 1902, 1903, 1904, 1905, 1917, 1899, 1918, 1919, 1920, 1906, 1907, 1921, 1908, 1922, 1909, 1923, 1911, 1912, 1924, 1913, 1914, 1915, 1925, 1926, 1927, 1928, 1929, 1929, 1916, 1929, 1929, 1929, 1929, 1929, 1929, 1917, 1929, 1918, 1919, 1920, 1929, 1929, 1921, 1929, 1922, 1929, 1923, 1929, 1929, 1924, 1929, 1929, 1929, 1925, 1926, 1927, 1928, 122, 122, 122, 122, 122, 122, 122, 122, 122, 126, 126, 126, 126, 126, 126, 126, 126, 126, 131, 1929, 131, 131, 131, 131, 131, 131, 131, 132, 1929, 132, 132, 132, 132, 132, 132, 132, 136, 136, 140, 140, 140, 140, 140, 140, 140, 140, 140, 249, 249, 249, 249, 249, 249, 249, 249, 249, 251, 1929, 251, 251, 251, 251, 251, 251, 251, 270, 1929, 270, 348, 348, 348, 348, 348, 348, 348, 348, 348, 353, 353, 353, 353, 353, 353, 353, 353, 353, 357, 357, 357, 357, 357, 357, 357, 357, 357, 359, 359, 359, 359, 359, 359, 359, 359, 359, 360, 360, 360, 1929, 1929, 360, 360, 1929, 360, 139, 139, 139, 139, 139, 139, 139, 139, 139, 544, 1929, 1929, 544, 544, 1929, 544, 572, 572, 572, 1929, 572, 572, 572, 572, 572, 574, 574, 574, 574, 1929, 574, 574, 574, 574, 606, 606, 606, 606, 606, 606, 606, 606, 606, 13, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929 } ; static yyconst flex_int16_t yy_chk[4493] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 573, 9, 9, 10, 9, 10, 10, 9, 10, 11, 12, 10, 11, 12, 15, 1899, 15, 15, 20, 33, 20, 20, 21, 21, 34, 100, 40, 53, 34, 54, 55, 21, 118, 100, 1882, 23, 118, 23, 23, 68, 575, 68, 68, 354, 573, 354, 23, 24, 1259, 24, 33, 1166, 11, 12, 618, 34, 24, 40, 53, 34, 54, 55, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 24, 22, 24, 575, 22, 56, 22, 25, 29, 24, 57, 25, 29, 59, 574, 25, 29, 572, 60, 32, 32, 61, 29, 62, 25, 29, 32, 25, 27, 64, 65, 27, 27, 22, 22, 22, 56, 22, 25, 29, 544, 57, 25, 29, 59, 27, 25, 29, 27, 60, 32, 32, 61, 29, 62, 25, 29, 32, 25, 27, 64, 65, 27, 27, 22, 22, 22, 22, 22, 26, 66, 26, 465, 70, 26, 26, 27, 359, 26, 27, 37, 26, 76, 81, 26, 26, 28, 28, 28, 31, 106, 30, 28, 31, 37, 30, 357, 31, 28, 30, 26, 66, 26, 45, 70, 26, 26, 45, 30, 26, 353, 37, 26, 76, 81, 26, 26, 28, 28, 28, 31, 106, 30, 28, 31, 37, 30, 58, 31, 28, 30, 58, 366, 366, 45, 67, 67, 348, 45, 30, 35, 36, 35, 78, 35, 36, 63, 78, 35, 36, 107, 35, 63, 88, 35, 88, 41, 35, 58, 315, 41, 36, 58, 63, 41, 36, 367, 367, 67, 313, 41, 35, 36, 35, 78, 35, 36, 63, 78, 35, 36, 107, 35, 63, 88, 35, 88, 41, 35, 77, 77, 41, 36, 109, 63, 41, 36, 38, 38, 103, 39, 41, 74, 270, 39, 38, 74, 38, 39, 38, 74, 39, 38, 38, 39, 103, 74, 39, 138, 138, 77, 77, 138, 138, 109, 69, 252, 69, 38, 38, 103, 39, 251, 74, 69, 39, 38, 74, 38, 39, 38, 74, 39, 38, 38, 39, 103, 74, 39, 42, 42, 42, 249, 43, 42, 42, 69, 43, 69, 42, 113, 43, 105, 42, 44, 69, 42, 43, 42, 115, 43, 42, 75, 44, 80, 44, 105, 43, 80, 44, 42, 42, 42, 44, 43, 42, 42, 139, 43, 75, 42, 113, 43, 105, 42, 44, 133, 42, 43, 42, 115, 43, 42, 75, 44, 80, 44, 105, 43, 80, 44, 46, 46, 132, 44, 46, 71, 46, 71, 46, 75, 73, 73, 72, 46, 71, 72, 72, 71, 116, 79, 71, 73, 125, 79, 84, 102, 124, 79, 84, 102, 120, 46, 46, 79, 119, 46, 71, 46, 71, 46, 101, 73, 73, 72, 46, 71, 72, 72, 71, 116, 79, 71, 73, 82, 79, 84, 102, 83, 79, 84, 102, 82, 108, 82, 79, 83, 85, 85, 82, 82, 104, 83, 86, 104, 83, 112, 86, 108, 85, 112, 87, 127, 86, 85, 82, 86, 368, 368, 83, 87, 99, 87, 82, 108, 82, 87, 83, 85, 85, 82, 82, 104, 83, 86, 104, 83, 112, 86, 108, 85, 112, 87, 127, 86, 85, 90, 86, 90, 90, 128, 87, 91, 87, 91, 91, 96, 87, 96, 96, 97, 97, 98, 110, 98, 98, 111, 114, 117, 97, 141, 114, 123, 98, 123, 123, 111, 117, 110, 129, 95, 128, 129, 117, 130, 94, 130, 130, 93, 146, 148, 143, 143, 117, 110, 143, 143, 111, 114, 117, 97, 141, 114, 150, 98, 144, 153, 111, 117, 110, 134, 134, 144, 135, 117, 135, 135, 137, 137, 134, 146, 148, 129, 154, 135, 155, 137, 373, 373, 374, 374, 92, 142, 142, 150, 49, 144, 153, 576, 576, 48, 142, 147, 144, 159, 160, 19, 319, 319, 13, 134, 319, 319, 147, 154, 135, 155, 137, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 142, 147, 140, 159, 160, 140, 145, 140, 149, 156, 145, 151, 147, 157, 149, 157, 162, 145, 163, 164, 162, 165, 168, 145, 170, 151, 0, 167, 167, 156, 172, 174, 175, 176, 140, 140, 140, 145, 140, 149, 156, 145, 151, 166, 157, 149, 157, 162, 145, 163, 164, 162, 165, 168, 145, 170, 151, 166, 167, 167, 156, 172, 174, 175, 176, 140, 140, 140, 140, 140, 177, 169, 171, 178, 166, 169, 171, 173, 179, 173, 173, 178, 180, 173, 181, 182, 184, 178, 166, 0, 185, 186, 187, 577, 577, 0, 191, 193, 606, 198, 606, 177, 169, 171, 178, 0, 169, 171, 173, 179, 173, 173, 178, 180, 173, 181, 182, 184, 178, 183, 183, 185, 186, 187, 188, 183, 190, 191, 193, 196, 198, 190, 190, 199, 202, 195, 183, 195, 195, 203, 188, 204, 188, 195, 200, 196, 205, 188, 580, 580, 183, 183, 200, 206, 201, 188, 183, 190, 201, 207, 196, 208, 190, 190, 199, 202, 195, 183, 195, 195, 203, 188, 204, 188, 195, 200, 196, 205, 188, 197, 197, 197, 210, 200, 206, 201, 209, 197, 209, 201, 207, 211, 208, 212, 213, 214, 215, 213, 216, 581, 581, 214, 218, 216, 213, 0, 219, 220, 221, 0, 197, 197, 197, 210, 222, 223, 0, 209, 197, 209, 225, 226, 211, 228, 212, 213, 214, 215, 213, 216, 217, 217, 214, 218, 216, 213, 217, 219, 220, 221, 217, 217, 227, 217, 229, 222, 223, 224, 224, 230, 233, 225, 226, 231, 228, 232, 235, 232, 0, 238, 224, 217, 217, 232, 231, 240, 227, 217, 241, 234, 242, 217, 217, 227, 217, 229, 243, 234, 224, 224, 230, 233, 244, 245, 231, 246, 232, 235, 232, 234, 238, 224, 247, 248, 232, 231, 240, 227, 253, 241, 234, 242, 254, 255, 256, 257, 259, 243, 234, 258, 260, 261, 262, 244, 245, 263, 246, 264, 265, 266, 234, 267, 268, 247, 248, 269, 273, 275, 263, 253, 276, 0, 258, 254, 255, 256, 257, 259, 271, 271, 258, 260, 261, 262, 278, 279, 263, 274, 264, 265, 266, 280, 267, 268, 274, 281, 269, 273, 275, 263, 274, 276, 277, 258, 277, 282, 283, 285, 286, 282, 284, 271, 284, 284, 288, 278, 279, 287, 274, 289, 290, 291, 280, 287, 292, 274, 281, 293, 294, 296, 297, 274, 298, 277, 287, 277, 282, 283, 285, 286, 282, 284, 299, 284, 284, 288, 300, 301, 287, 302, 289, 290, 291, 303, 287, 292, 300, 304, 293, 294, 296, 297, 305, 298, 306, 287, 308, 309, 307, 310, 311, 321, 321, 299, 308, 321, 321, 300, 301, 307, 302, 316, 316, 317, 303, 317, 317, 300, 304, 326, 316, 327, 328, 305, 317, 306, 329, 308, 309, 307, 310, 311, 318, 318, 331, 308, 320, 320, 330, 330, 307, 318, 333, 332, 334, 320, 335, 337, 338, 340, 326, 316, 327, 328, 342, 317, 332, 329, 343, 344, 345, 346, 347, 346, 0, 331, 369, 349, 350, 330, 330, 0, 318, 333, 332, 334, 320, 335, 337, 338, 340, 351, 375, 608, 608, 342, 376, 332, 0, 343, 344, 345, 346, 347, 346, 349, 350, 369, 349, 350, 364, 364, 351, 365, 365, 371, 371, 365, 365, 364, 377, 378, 351, 375, 371, 372, 372, 376, 379, 372, 372, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 0, 398, 399, 364, 377, 378, 401, 402, 371, 403, 404, 405, 379, 406, 0, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 398, 399, 400, 408, 409, 401, 402, 396, 403, 404, 405, 410, 406, 396, 411, 412, 413, 414, 415, 400, 416, 417, 418, 419, 421, 414, 422, 423, 424, 425, 396, 426, 418, 400, 408, 409, 427, 428, 396, 429, 431, 432, 410, 433, 396, 411, 412, 413, 414, 415, 400, 416, 417, 418, 419, 421, 414, 422, 423, 424, 425, 430, 426, 418, 434, 430, 435, 427, 428, 436, 429, 431, 432, 437, 433, 438, 439, 440, 441, 436, 442, 443, 444, 445, 448, 449, 0, 607, 451, 607, 453, 0, 430, 454, 0, 434, 430, 435, 452, 456, 436, 457, 452, 458, 437, 0, 438, 439, 440, 441, 436, 442, 443, 444, 445, 448, 449, 450, 450, 451, 450, 453, 450, 450, 454, 450, 459, 460, 450, 452, 456, 450, 457, 452, 458, 450, 450, 461, 462, 450, 610, 610, 463, 0, 466, 611, 611, 467, 450, 450, 469, 450, 470, 450, 450, 471, 450, 459, 460, 450, 468, 472, 450, 474, 468, 475, 450, 450, 461, 462, 450, 455, 455, 463, 455, 466, 455, 455, 467, 455, 473, 469, 455, 470, 478, 476, 471, 477, 473, 455, 455, 468, 472, 455, 474, 468, 475, 479, 477, 480, 481, 482, 455, 455, 479, 455, 483, 455, 455, 476, 455, 473, 484, 455, 485, 478, 476, 486, 477, 473, 455, 455, 487, 488, 455, 489, 490, 491, 479, 477, 480, 481, 482, 493, 494, 479, 495, 483, 496, 497, 476, 498, 499, 484, 500, 485, 494, 501, 486, 503, 504, 505, 506, 487, 488, 507, 489, 490, 491, 508, 509, 510, 511, 512, 493, 494, 513, 495, 514, 496, 497, 515, 498, 499, 516, 500, 515, 494, 501, 518, 503, 504, 505, 506, 517, 521, 507, 524, 525, 526, 508, 509, 510, 511, 512, 527, 517, 513, 528, 514, 529, 530, 515, 531, 532, 516, 534, 515, 535, 536, 518, 537, 538, 539, 540, 517, 521, 541, 524, 525, 526, 542, 546, 547, 548, 549, 527, 517, 550, 528, 551, 529, 530, 552, 531, 532, 553, 534, 554, 535, 536, 555, 537, 538, 539, 540, 556, 557, 541, 558, 559, 560, 542, 546, 547, 548, 549, 557, 561, 550, 562, 551, 563, 564, 552, 565, 566, 553, 567, 554, 568, 569, 555, 570, 571, 578, 578, 556, 557, 0, 558, 559, 560, 582, 578, 583, 584, 585, 557, 561, 586, 562, 587, 563, 564, 588, 565, 566, 589, 567, 590, 568, 569, 591, 570, 571, 579, 579, 592, 593, 579, 579, 594, 596, 582, 578, 583, 584, 585, 597, 598, 586, 599, 587, 600, 601, 588, 602, 603, 589, 0, 590, 604, 605, 591, 612, 613, 603, 614, 592, 593, 615, 616, 594, 596, 604, 617, 619, 620, 621, 597, 598, 622, 599, 623, 600, 601, 624, 602, 603, 625, 605, 627, 604, 605, 628, 612, 613, 629, 614, 630, 631, 615, 616, 632, 633, 634, 617, 619, 620, 621, 635, 637, 622, 628, 623, 638, 636, 624, 636, 639, 625, 640, 627, 642, 643, 628, 644, 645, 629, 646, 630, 631, 647, 648, 632, 633, 634, 649, 650, 652, 653, 635, 637, 654, 628, 655, 638, 636, 656, 636, 639, 657, 640, 658, 642, 643, 660, 644, 645, 661, 646, 662, 663, 647, 648, 664, 665, 666, 649, 650, 652, 653, 667, 668, 654, 669, 655, 670, 671, 656, 672, 673, 657, 674, 658, 676, 678, 660, 677, 679, 661, 680, 662, 663, 681, 677, 664, 665, 666, 682, 683, 685, 687, 667, 668, 689, 669, 690, 670, 671, 691, 672, 673, 692, 674, 693, 676, 678, 694, 677, 679, 686, 680, 695, 696, 681, 677, 698, 686, 697, 682, 683, 685, 687, 699, 697, 689, 700, 690, 701, 702, 691, 703, 704, 692, 705, 693, 697, 706, 694, 707, 708, 686, 709, 695, 696, 710, 711, 698, 686, 697, 713, 714, 715, 0, 699, 697, 716, 700, 717, 701, 702, 719, 703, 704, 721, 705, 712, 697, 706, 723, 707, 708, 712, 709, 722, 724, 710, 711, 722, 725, 726, 713, 714, 715, 712, 727, 728, 716, 729, 717, 730, 731, 719, 732, 733, 721, 734, 712, 735, 736, 723, 737, 738, 712, 740, 722, 724, 739, 741, 722, 725, 726, 739, 742, 743, 712, 727, 728, 744, 729, 745, 730, 731, 746, 732, 733, 747, 734, 748, 735, 736, 749, 737, 738, 750, 740, 751, 752, 739, 741, 753, 754, 755, 739, 742, 743, 756, 757, 758, 744, 759, 745, 760, 761, 746, 762, 763, 747, 764, 748, 765, 766, 749, 771, 769, 750, 767, 751, 752, 772, 767, 753, 754, 755, 769, 773, 774, 756, 757, 758, 775, 759, 777, 760, 761, 778, 762, 763, 779, 764, 780, 765, 766, 781, 771, 769, 782, 767, 783, 785, 772, 767, 786, 787, 788, 769, 773, 774, 789, 790, 791, 775, 792, 777, 793, 794, 778, 795, 796, 779, 797, 780, 799, 800, 781, 801, 802, 782, 803, 783, 785, 805, 807, 786, 787, 788, 808, 809, 810, 789, 790, 791, 811, 792, 812, 793, 794, 813, 795, 796, 815, 797, 816, 799, 800, 822, 801, 802, 823, 803, 819, 819, 805, 807, 820, 820, 824, 808, 809, 810, 825, 826, 827, 811, 828, 812, 829, 830, 813, 831, 832, 815, 833, 816, 834, 835, 822, 836, 837, 823, 838, 839, 840, 842, 842, 847, 841, 824, 849, 843, 850, 825, 826, 827, 852, 828, 853, 829, 830, 855, 831, 832, 843, 833, 856, 834, 835, 857, 836, 837, 858, 838, 839, 840, 841, 859, 847, 841, 860, 849, 843, 850, 862, 864, 863, 852, 863, 853, 865, 866, 855, 867, 868, 869, 870, 856, 872, 873, 857, 874, 875, 858, 878, 880, 881, 881, 859, 883, 884, 860, 885, 886, 887, 862, 864, 863, 888, 863, 890, 865, 866, 891, 867, 868, 869, 870, 893, 872, 873, 894, 874, 875, 897, 878, 880, 881, 881, 898, 883, 884, 900, 885, 886, 887, 901, 903, 904, 888, 899, 890, 906, 907, 891, 908, 909, 0, 904, 893, 899, 0, 894, 899, 899, 897, 0, 899, 899, 912, 898, 914, 915, 900, 916, 917, 918, 901, 903, 904, 919, 899, 910, 906, 907, 910, 908, 909, 910, 904, 920, 899, 910, 921, 899, 899, 922, 910, 899, 899, 912, 923, 914, 915, 924, 916, 917, 918, 925, 926, 927, 919, 928, 910, 929, 930, 910, 931, 932, 910, 933, 920, 934, 910, 921, 936, 937, 922, 910, 938, 939, 940, 923, 941, 942, 924, 943, 944, 945, 925, 926, 927, 946, 928, 947, 929, 930, 948, 931, 932, 950, 933, 952, 934, 953, 954, 936, 937, 955, 956, 938, 939, 940, 957, 941, 942, 958, 943, 944, 945, 959, 960, 961, 946, 962, 947, 963, 964, 948, 965, 966, 950, 967, 952, 968, 953, 954, 969, 970, 955, 956, 971, 973, 974, 957, 972, 975, 958, 976, 977, 978, 959, 960, 961, 972, 962, 977, 963, 964, 979, 965, 966, 980, 967, 981, 968, 982, 983, 969, 970, 984, 985, 971, 973, 974, 989, 972, 975, 990, 976, 977, 978, 988, 991, 988, 972, 992, 977, 993, 994, 979, 996, 997, 980, 998, 981, 999, 982, 983, 1001, 988, 984, 985, 1002, 1003, 1004, 989, 1006, 1007, 990, 1003, 1008, 1009, 988, 991, 988, 1012, 992, 1007, 993, 994, 1013, 996, 997, 1014, 998, 1015, 999, 1019, 1020, 1001, 988, 1024, 1021, 1002, 1003, 1004, 1025, 1006, 1007, 1026, 1003, 1008, 1009, 1027, 1028, 1029, 1012, 1031, 1007, 1021, 1033, 1013, 1033, 1035, 1014, 1036, 1015, 1037, 1019, 1020, 1038, 1039, 1024, 1021, 1040, 1041, 1042, 1025, 1043, 1038, 1026, 1044, 1045, 1046, 1027, 1028, 1029, 1047, 1031, 1048, 1021, 1033, 1049, 1033, 1035, 1050, 1036, 1051, 1037, 1052, 1053, 1038, 1039, 1054, 1055, 1040, 1041, 1042, 1057, 1043, 1038, 1058, 1044, 1045, 1046, 1059, 1060, 1061, 1047, 1063, 1048, 1062, 1062, 1049, 1065, 1064, 1050, 1066, 1051, 1067, 1052, 1053, 1068, 1069, 1054, 1055, 1070, 1072, 1075, 1057, 1077, 1078, 1058, 1079, 1080, 1063, 1059, 1060, 1061, 1064, 1063, 1082, 1083, 1084, 1085, 1065, 1064, 1086, 1066, 1087, 1067, 1089, 1090, 1068, 1069, 1091, 1092, 1070, 1072, 1075, 1094, 1077, 1078, 1096, 1079, 1080, 1098, 1100, 1101, 1102, 1103, 1106, 1082, 1083, 1084, 1085, 1107, 1108, 1086, 1109, 1087, 1110, 1089, 1090, 1111, 1113, 1091, 1092, 1114, 1115, 1116, 1094, 1117, 1118, 1096, 1119, 1120, 1098, 1100, 1101, 1102, 1103, 1106, 1121, 1122, 1123, 1124, 1107, 1108, 1125, 1109, 1128, 1110, 1129, 1124, 1111, 1113, 1130, 1131, 1114, 1115, 1116, 1132, 1117, 1118, 1133, 1119, 1120, 1134, 1135, 1136, 1137, 1138, 1139, 1121, 1122, 1123, 1124, 1140, 1141, 1125, 1142, 1128, 1143, 1129, 1124, 1144, 1146, 1130, 1131, 1148, 1149, 1150, 1132, 1151, 1152, 1133, 1153, 1154, 1134, 1135, 1136, 1137, 1138, 1139, 1155, 1156, 1157, 1158, 1140, 1141, 1159, 1142, 1160, 1143, 1161, 1162, 1144, 1146, 1165, 1167, 1148, 1149, 1150, 1168, 1151, 1152, 1169, 1153, 1154, 1170, 1171, 1172, 1173, 1174, 1179, 1155, 1156, 1157, 1158, 1180, 1181, 1159, 1182, 1160, 1183, 1161, 1162, 1184, 1185, 1165, 1167, 1186, 1187, 1188, 1168, 1189, 1190, 1169, 1192, 1194, 1170, 1171, 1172, 1173, 1174, 1179, 1195, 1196, 1197, 1198, 1180, 1181, 1199, 1182, 1200, 1183, 1201, 1202, 1184, 1185, 1203, 1206, 1186, 1187, 1188, 1209, 1189, 1190, 1210, 1192, 1194, 1211, 1212, 1202, 1213, 1214, 1215, 1195, 1196, 1197, 1198, 1216, 1217, 1199, 1218, 1200, 1219, 1201, 1202, 1220, 1221, 1203, 1206, 1222, 1225, 1227, 1209, 1228, 1230, 1210, 1231, 1232, 1211, 1212, 1202, 1213, 1214, 1215, 1233, 1234, 1235, 1236, 1216, 1217, 1238, 1218, 1241, 1219, 1242, 1243, 1220, 1221, 1244, 1245, 1222, 1225, 1227, 1246, 1228, 1230, 1247, 1231, 1232, 1248, 1249, 1251, 1252, 1253, 1254, 1233, 1234, 1235, 1236, 1255, 1257, 1238, 1260, 1241, 1258, 1242, 1243, 1261, 1262, 1244, 1245, 1263, 1264, 1265, 1246, 1266, 1267, 1247, 1268, 1269, 1248, 1249, 1251, 1252, 1253, 1254, 1257, 1271, 1258, 1272, 1255, 1257, 1274, 1260, 1275, 1258, 1277, 1279, 1261, 1262, 1280, 1281, 1263, 1264, 1265, 1283, 1266, 1267, 1285, 1268, 1269, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1271, 1293, 1272, 1294, 1296, 1274, 1297, 1275, 1298, 1277, 1279, 1299, 1301, 1280, 1281, 1302, 1303, 1304, 1283, 1305, 1306, 1285, 1307, 1308, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1309, 1293, 1311, 1294, 1296, 1312, 1297, 1314, 1298, 1315, 1316, 1299, 1301, 1317, 1318, 1302, 1303, 1304, 1319, 1305, 1306, 1320, 1307, 1308, 1321, 1323, 1324, 1325, 1326, 1327, 1329, 1309, 1330, 1311, 1331, 1332, 1312, 1333, 1314, 1334, 1315, 1316, 1335, 1337, 1317, 1318, 1338, 1339, 1340, 1319, 1341, 1343, 1320, 1343, 1345, 1321, 1323, 1324, 1325, 1326, 1327, 1329, 1347, 1330, 1349, 1331, 1332, 1346, 1333, 1351, 1334, 1352, 1354, 1335, 1337, 1348, 1348, 1338, 1339, 1340, 1356, 1341, 1343, 1357, 1343, 1345, 1348, 1346, 1348, 1358, 1359, 1360, 1348, 1347, 1361, 1349, 1362, 1363, 1346, 1364, 1351, 1365, 1352, 1354, 1366, 1367, 1348, 1348, 1368, 1369, 1370, 1356, 1371, 1372, 1357, 1373, 1374, 1348, 1346, 1348, 1358, 1359, 1360, 1348, 1375, 1361, 1376, 1362, 1363, 1377, 1364, 1378, 1365, 1378, 1379, 1366, 1367, 1380, 1381, 1368, 1369, 1370, 1382, 1371, 1372, 1384, 1373, 1374, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1375, 1392, 1376, 1393, 1394, 1377, 1395, 1378, 1396, 1378, 1379, 1397, 1398, 1380, 1381, 1399, 1401, 1403, 1382, 1405, 1406, 1384, 0, 1408, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1409, 1392, 1410, 1393, 1394, 1411, 1395, 1412, 1396, 1400, 1400, 1397, 1398, 1413, 1414, 1399, 1401, 1403, 1416, 1405, 1406, 1419, 1400, 1408, 1420, 1421, 1400, 1422, 1423, 1417, 1425, 1409, 1426, 1410, 1427, 1428, 1411, 1429, 1412, 1430, 1400, 1400, 1416, 1431, 1413, 1414, 1417, 1432, 1433, 1416, 1435, 1436, 1419, 1400, 1437, 1420, 1421, 1400, 1422, 1423, 1417, 1425, 1438, 1426, 1439, 1427, 1428, 1440, 1429, 1442, 1430, 1443, 1444, 1445, 1431, 1446, 1448, 1449, 1432, 1433, 1450, 1435, 1436, 1452, 1453, 1437, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1438, 1461, 1439, 1462, 1463, 1440, 1464, 1442, 1465, 1443, 1444, 1445, 1466, 1446, 1448, 1449, 1467, 1468, 1450, 1469, 1470, 1452, 1453, 1471, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1472, 1461, 1476, 1462, 1463, 1477, 1464, 1478, 1465, 1479, 1480, 1481, 1466, 1482, 1483, 1484, 1467, 1468, 1487, 1469, 1470, 1488, 1489, 1471, 1490, 1491, 1492, 1493, 1494, 1495, 1497, 1472, 1498, 1476, 1500, 1496, 1477, 1501, 1478, 1503, 1479, 1480, 1481, 1496, 1482, 1483, 1484, 1504, 1498, 1487, 1506, 1507, 1488, 1489, 1508, 1490, 1491, 1492, 1493, 1494, 1495, 1497, 1510, 1498, 1511, 1500, 1496, 1512, 1501, 1513, 1503, 1515, 1517, 1518, 1496, 1520, 1521, 1522, 1504, 1498, 1523, 1506, 1507, 1524, 1525, 1508, 1526, 1527, 1529, 1531, 1532, 1533, 1537, 1510, 1538, 1511, 1539, 1540, 1512, 1541, 1513, 1543, 1515, 1517, 1518, 1544, 1520, 1521, 1522, 1546, 1549, 1523, 1552, 1553, 1524, 1525, 1555, 1526, 1527, 1529, 1531, 1532, 1533, 1537, 1556, 1538, 1560, 1539, 1540, 1558, 1541, 1559, 1543, 1561, 1563, 1565, 1544, 1567, 1569, 1570, 1546, 1549, 1571, 1552, 1553, 1573, 1558, 1555, 1559, 1574, 1576, 1577, 1578, 1580, 1583, 1556, 1585, 1560, 1588, 1589, 1558, 1590, 1559, 1591, 1561, 1563, 1565, 1593, 1567, 1569, 1570, 1594, 1595, 1571, 1596, 1597, 1573, 1598, 1599, 1600, 1574, 1576, 1577, 1578, 1580, 1583, 1601, 1585, 1602, 1588, 1589, 1603, 1590, 1605, 1591, 1606, 1607, 1608, 1593, 1609, 1610, 1611, 1594, 1595, 1612, 1596, 1597, 1613, 1598, 1599, 1600, 1615, 1616, 1617, 1618, 1619, 1620, 1601, 1621, 1602, 1622, 1623, 1603, 1624, 1605, 1625, 1606, 1607, 1608, 1626, 1609, 1610, 1611, 1627, 1628, 1612, 1629, 1630, 1613, 1631, 1632, 1633, 1615, 1616, 1617, 1618, 1619, 1620, 1634, 1621, 1635, 1622, 1623, 1636, 1624, 1637, 1625, 1638, 1641, 1642, 1626, 1643, 1644, 1645, 1627, 1628, 1646, 1629, 1630, 1647, 1631, 1632, 1633, 1651, 1653, 1655, 1657, 1658, 1659, 1634, 1660, 1635, 1662, 1664, 1636, 1665, 1637, 1666, 1638, 1641, 1642, 1667, 1643, 1644, 1645, 1668, 1669, 1646, 1671, 1673, 1647, 1675, 1672, 1676, 1651, 1653, 1655, 1657, 1658, 1659, 1679, 1660, 1672, 1662, 1664, 1671, 1665, 1680, 1666, 1681, 1684, 1685, 1667, 1687, 1692, 1693, 1668, 1669, 1694, 1671, 1673, 1695, 1675, 1672, 1676, 1696, 1697, 1700, 1701, 1702, 1703, 1679, 1704, 1705, 1706, 1707, 1709, 1710, 1680, 1711, 1681, 1684, 1685, 1712, 1687, 1692, 1693, 1713, 1714, 1694, 1715, 1716, 1695, 1717, 1719, 1720, 1696, 1697, 1700, 1701, 1702, 1703, 1721, 1704, 1705, 1706, 1707, 1709, 1710, 1722, 1711, 1723, 1724, 1725, 1712, 1726, 1727, 1728, 1713, 1714, 1729, 1715, 1716, 1730, 1717, 1719, 1720, 1731, 1733, 1736, 1738, 1742, 1744, 1721, 1745, 1746, 1747, 1749, 1753, 1758, 1722, 0, 1723, 1724, 1725, 1761, 1726, 1727, 1728, 1758, 1762, 1729, 1759, 1747, 1730, 1763, 1765, 1766, 1731, 1733, 1736, 1738, 1742, 1744, 1767, 1745, 1746, 1747, 1749, 1753, 1758, 1768, 1759, 1770, 1771, 1772, 1761, 1773, 1774, 1779, 1780, 1762, 1781, 1759, 1747, 1784, 1763, 1765, 1766, 1787, 1788, 1790, 1792, 1793, 1794, 1767, 1795, 1796, 1797, 1798, 1799, 1800, 1768, 1802, 1770, 1771, 1772, 1805, 1773, 1774, 1779, 1780, 1807, 1781, 1809, 1810, 1784, 1811, 1812, 1814, 1787, 1788, 1790, 1792, 1793, 1794, 1818, 1795, 1796, 1797, 1798, 1799, 1800, 1816, 1802, 1820, 1817, 1821, 1805, 1817, 1823, 1825, 1826, 1807, 1827, 1809, 1810, 1829, 1811, 1812, 1814, 1830, 1831, 1816, 1833, 1834, 1836, 1818, 1837, 1841, 1843, 1844, 1845, 1846, 1816, 1847, 1820, 1817, 1821, 1848, 1849, 1823, 1825, 1826, 1850, 1827, 1851, 1853, 1829, 1855, 1856, 1854, 1830, 1831, 1854, 1833, 1834, 1836, 1857, 1837, 1841, 1843, 1844, 1845, 1846, 1860, 1847, 1861, 1863, 1864, 1848, 1849, 1866, 1855, 1870, 1850, 1871, 1851, 1853, 1872, 1855, 1856, 1854, 1873, 1875, 1876, 1877, 1878, 1879, 1857, 0, 1883, 1885, 1886, 1887, 1888, 1860, 1881, 1861, 1863, 1864, 1890, 1893, 1866, 1896, 1870, 1897, 1871, 1902, 1903, 1872, 1906, 1907, 1908, 1873, 1875, 1876, 1877, 1878, 1879, 1911, 1881, 1883, 1885, 1886, 1887, 1888, 1912, 1881, 1913, 1914, 1916, 1890, 1893, 1917, 1896, 1918, 1897, 1919, 1902, 1903, 1922, 1906, 1907, 1908, 1923, 1924, 1926, 1927, 0, 0, 1911, 0, 0, 0, 0, 0, 0, 1912, 0, 1913, 1914, 1916, 0, 0, 1917, 0, 1918, 0, 1919, 0, 0, 1922, 0, 0, 0, 1923, 1924, 1926, 1927, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1931, 1932, 0, 1932, 1932, 1932, 1932, 1932, 1932, 1932, 1933, 0, 1933, 1933, 1933, 1933, 1933, 1933, 1933, 1934, 1934, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1935, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1936, 1937, 0, 1937, 1937, 1937, 1937, 1937, 1937, 1937, 1938, 0, 1938, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1939, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1940, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1941, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1942, 1943, 1943, 1943, 0, 0, 1943, 1943, 0, 1943, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1944, 1945, 0, 0, 1945, 1945, 0, 1945, 1946, 1946, 1946, 0, 1946, 1946, 1946, 1946, 1946, 1947, 1947, 1947, 1947, 0, 1947, 1947, 1947, 1947, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1948, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929, 1929 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int msyy_flex_debug; int msyy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *msyytext; #line 1 "/home/even/mapserver/git/mapserver/maplexer.l" #line 2 "/home/even/mapserver/git/mapserver/maplexer.l" /* ** READ ME FIRST! ** ** When this file is altered, it is necessary to do "make lexer". Due to ** problems detailed in #2310 the lexer is no longer automatically rebuilt ** when maplexer.l is altered. */ /* C declarations */ #include #include #include #include #include #include "mapserver.h" #include "maperror.h" #include "mapfile.h" #include "maptime.h" #include "mapsymbol.h" #include "mapparser.h" #include "mapprimitive.h" /* msyylineno is required for flex 2.5.4 and older, but is already defined by * flex 2.5.31 (bug 975). * Unfortunately there is no clean way to differenciate the two versions, * so we use the symbol YY_CURRENT_BUFFER_LVALUE to base our test since it * was not present in 2.5.4 and is present in 2.5.31. Hopefully that won't * put us in trouble with other versions. If that happens then we can * switch to using autoconf to detect the version. */ #ifndef YY_CURRENT_BUFFER_LVALUE int msyylineno = 1; #endif int msyysource=MS_STRING_TOKENS; double msyynumber; int msyystate=MS_TOKENIZE_DEFAULT; char *msyystring=NULL; char *msyybasepath=NULL; char *msyystring_buffer_ptr; int msyystring_buffer_size = 256; int msyystring_size; char msyystring_begin; char *msyystring_buffer = NULL; int msyystring_icase = MS_FALSE; int msyystring_return_state; int msyystring_begin_state; int msyystring_size_tmp; int msyyreturncomments = 0; #define MS_LEXER_STRING_REALLOC(string, string_size, max_size, string_ptr) \ if (string_size >= max_size) { \ msyystring_size_tmp = max_size; \ max_size = ((max_size*2) > string_size) ? max_size*2 : string_size+1; \ string = (char *) msSmallRealloc(string, sizeof(char *) * max_size); \ string_ptr = string; \ string_ptr += msyystring_size_tmp; \ } #define MS_LEXER_RETURN_TOKEN(token) \ MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), \ msyystring_buffer_size, msyystring_buffer_ptr); \ strcpy(msyystring_buffer, msyytext); \ return(token); #define MAX_INCLUDE_DEPTH 5 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_lineno[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; char path[MS_MAXPATHLEN]; #line 2192 "/home/even/mapserver/git/mapserver/maplexer.c" #define INITIAL 0 #define URL_VARIABLE 1 #define URL_STRING 2 #define EXPRESSION_STRING 3 #define INCLUDE 4 #define MSSTRING 5 #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int msyylex_destroy (void ); int msyyget_debug (void ); void msyyset_debug (int debug_flag ); YY_EXTRA_TYPE msyyget_extra (void ); void msyyset_extra (YY_EXTRA_TYPE user_defined ); FILE *msyyget_in (void ); void msyyset_in (FILE * in_str ); FILE *msyyget_out (void ); void msyyset_out (FILE * out_str ); int msyyget_leng (void ); char *msyyget_text (void ); int msyyget_lineno (void ); void msyyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int msyywrap (void ); #else extern int msyywrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( msyytext, msyyleng, 1, msyyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( msyyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( msyyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, msyyin))==0 && ferror(msyyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(msyyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int msyylex (void); #define YY_DECL int msyylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after msyytext and msyyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 85 "/home/even/mapserver/git/mapserver/maplexer.l" if (msyystring_buffer == NULL) msyystring_buffer = (char*) msSmallMalloc(sizeof(char) * msyystring_buffer_size); msyystring_buffer[0] = '\0'; msyystring_buffer_size = 0; switch(msyystate) { case(MS_TOKENIZE_DEFAULT): break; case(MS_TOKENIZE_FILE): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyysource=MS_FILE_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_STRING): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_STRING_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_URL_VARIABLE): BEGIN(URL_VARIABLE); msyystring_begin_state = URL_VARIABLE; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; (void) yyunput; /* just to avoid warning about it being unrefed */ break; case(MS_TOKENIZE_URL_STRING): BEGIN(URL_STRING); msyystring_begin_state = URL_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; return(0); break; case(MS_TOKENIZE_EXPRESSION): BEGIN(EXPRESSION_STRING); msyystring_begin_state = EXPRESSION_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; break; case(99): BEGIN(INITIAL); /* may not need this one */ msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; return(0); break; default: break; } #line 2450 "/home/even/mapserver/git/mapserver/maplexer.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! msyyin ) msyyin = stdin; if ( ! msyyout ) msyyout = stdout; if ( ! YY_CURRENT_BUFFER ) { msyyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = msyy_create_buffer(msyyin,YY_BUF_SIZE ); } msyy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of msyytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1930 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 4408 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 158 "/home/even/mapserver/git/mapserver/maplexer.l" ; YY_BREAK case 2: YY_RULE_SETUP #line 160 "/home/even/mapserver/git/mapserver/maplexer.l" { if (msyyreturncomments) return(MS_COMMENT); } YY_BREAK case 3: YY_RULE_SETUP #line 162 "/home/even/mapserver/git/mapserver/maplexer.l" ; YY_BREAK case 4: YY_RULE_SETUP #line 164 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_OR); } YY_BREAK case 5: YY_RULE_SETUP #line 165 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_AND); } YY_BREAK case 6: YY_RULE_SETUP #line 166 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_NOT); } YY_BREAK case 7: YY_RULE_SETUP #line 167 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_EQ); } YY_BREAK case 8: YY_RULE_SETUP #line 168 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_NE); } YY_BREAK case 9: YY_RULE_SETUP #line 169 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GT); } YY_BREAK case 10: YY_RULE_SETUP #line 170 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LT); } YY_BREAK case 11: YY_RULE_SETUP #line 171 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GE); } YY_BREAK case 12: YY_RULE_SETUP #line 172 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LE); } YY_BREAK case 13: YY_RULE_SETUP #line 173 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_RE); } YY_BREAK case 14: YY_RULE_SETUP #line 175 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IEQ); } YY_BREAK case 15: YY_RULE_SETUP #line 176 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IRE); } YY_BREAK case 16: YY_RULE_SETUP #line 178 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IN); } YY_BREAK case 17: YY_RULE_SETUP #line 180 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_AREA); } YY_BREAK case 18: YY_RULE_SETUP #line 181 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_LENGTH); } YY_BREAK case 19: YY_RULE_SETUP #line 182 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_TOSTRING); } YY_BREAK case 20: YY_RULE_SETUP #line 183 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_COMMIFY); } YY_BREAK case 21: YY_RULE_SETUP #line 184 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_ROUND); } YY_BREAK case 22: YY_RULE_SETUP #line 186 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_BUFFER); } YY_BREAK case 23: YY_RULE_SETUP #line 187 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_DIFFERENCE); } YY_BREAK case 24: YY_RULE_SETUP #line 188 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFY); } YY_BREAK case 25: YY_RULE_SETUP #line 189 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFYPT); } YY_BREAK case 26: YY_RULE_SETUP #line 190 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_GENERALIZE); } YY_BREAK case 27: YY_RULE_SETUP #line 191 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SMOOTHSIA); } YY_BREAK case 28: YY_RULE_SETUP #line 193 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_INTERSECTS); } YY_BREAK case 29: YY_RULE_SETUP #line 194 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DISJOINT); } YY_BREAK case 30: YY_RULE_SETUP #line 195 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_TOUCHES); } YY_BREAK case 31: YY_RULE_SETUP #line 196 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_OVERLAPS); } YY_BREAK case 32: YY_RULE_SETUP #line 197 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CROSSES); } YY_BREAK case 33: YY_RULE_SETUP #line 198 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_WITHIN); } YY_BREAK case 34: YY_RULE_SETUP #line 199 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CONTAINS); } YY_BREAK case 35: YY_RULE_SETUP #line 200 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_BEYOND); } YY_BREAK case 36: YY_RULE_SETUP #line 201 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DWITHIN); } YY_BREAK case 37: YY_RULE_SETUP #line 203 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_FROMTEXT); } YY_BREAK case 38: YY_RULE_SETUP #line 205 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(COLORRANGE); } YY_BREAK case 39: YY_RULE_SETUP #line 206 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DATARANGE); } YY_BREAK case 40: YY_RULE_SETUP #line 207 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(RANGEITEM); } YY_BREAK case 41: YY_RULE_SETUP #line 209 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ALIGN); } YY_BREAK case 42: YY_RULE_SETUP #line 210 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ANCHORPOINT); } YY_BREAK case 43: YY_RULE_SETUP #line 211 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ANGLE); } YY_BREAK case 44: YY_RULE_SETUP #line 212 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ANTIALIAS); } YY_BREAK case 45: YY_RULE_SETUP #line 213 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(BACKGROUNDCOLOR); } YY_BREAK case 46: YY_RULE_SETUP #line 214 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(BANDSITEM); } YY_BREAK case 47: YY_RULE_SETUP #line 215 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(BINDVALS); } YY_BREAK case 48: YY_RULE_SETUP #line 216 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(BROWSEFORMAT); } YY_BREAK case 49: YY_RULE_SETUP #line 217 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(BUFFER); } YY_BREAK case 50: YY_RULE_SETUP #line 218 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CHARACTER); } YY_BREAK case 51: YY_RULE_SETUP #line 219 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CLASS); } YY_BREAK case 52: YY_RULE_SETUP #line 220 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CLASSITEM); } YY_BREAK case 53: YY_RULE_SETUP #line 221 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CLASSGROUP); } YY_BREAK case 54: YY_RULE_SETUP #line 222 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CLUSTER); } YY_BREAK case 55: YY_RULE_SETUP #line 223 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(COLOR); } YY_BREAK case 56: YY_RULE_SETUP #line 224 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CONFIG); } YY_BREAK case 57: YY_RULE_SETUP #line 225 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CONNECTION); } YY_BREAK case 58: YY_RULE_SETUP #line 226 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(CONNECTIONTYPE); } YY_BREAK case 59: YY_RULE_SETUP #line 227 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DATA); } YY_BREAK case 60: YY_RULE_SETUP #line 228 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DATAPATTERN); } YY_BREAK case 61: YY_RULE_SETUP #line 229 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DEBUG); } YY_BREAK case 62: YY_RULE_SETUP #line 230 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DRIVER); } YY_BREAK case 63: YY_RULE_SETUP #line 231 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DUMP); } YY_BREAK case 64: YY_RULE_SETUP #line 232 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(EMPTY); } YY_BREAK case 65: YY_RULE_SETUP #line 233 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ENCODING); } YY_BREAK case 66: YY_RULE_SETUP #line 234 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(END); } YY_BREAK case 67: YY_RULE_SETUP #line 235 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ERROR); } YY_BREAK case 68: YY_RULE_SETUP #line 236 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(EXPRESSION); } YY_BREAK case 69: YY_RULE_SETUP #line 237 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(EXTENT); } YY_BREAK case 70: YY_RULE_SETUP #line 238 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(EXTENSION); } YY_BREAK case 71: YY_RULE_SETUP #line 239 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FEATURE); } YY_BREAK case 72: YY_RULE_SETUP #line 240 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FILLED); } YY_BREAK case 73: YY_RULE_SETUP #line 241 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FILTER); } YY_BREAK case 74: YY_RULE_SETUP #line 242 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FILTERITEM); } YY_BREAK case 75: YY_RULE_SETUP #line 243 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FOOTER); } YY_BREAK case 76: YY_RULE_SETUP #line 244 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FONT); } YY_BREAK case 77: YY_RULE_SETUP #line 245 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FONTSET); } YY_BREAK case 78: YY_RULE_SETUP #line 246 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FORCE); } YY_BREAK case 79: YY_RULE_SETUP #line 247 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FORMATOPTION); } YY_BREAK case 80: YY_RULE_SETUP #line 248 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(FROM); } YY_BREAK case 81: YY_RULE_SETUP #line 249 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(GAP); } YY_BREAK case 82: YY_RULE_SETUP #line 250 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(GEOMTRANSFORM); } YY_BREAK case 83: YY_RULE_SETUP #line 251 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(GRID); } YY_BREAK case 84: YY_RULE_SETUP #line 252 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(GRIDSTEP); } YY_BREAK case 85: YY_RULE_SETUP #line 253 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(GRATICULE); } YY_BREAK case 86: YY_RULE_SETUP #line 254 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(GROUP); } YY_BREAK case 87: YY_RULE_SETUP #line 255 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(HEADER); } YY_BREAK case 88: YY_RULE_SETUP #line 256 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGE); } YY_BREAK case 89: YY_RULE_SETUP #line 257 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGECOLOR); } YY_BREAK case 90: YY_RULE_SETUP #line 258 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGETYPE); } YY_BREAK case 91: YY_RULE_SETUP #line 259 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEQUALITY); } YY_BREAK case 92: YY_RULE_SETUP #line 260 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEMODE); } YY_BREAK case 93: YY_RULE_SETUP #line 261 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEPATH); } YY_BREAK case 94: YY_RULE_SETUP #line 262 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TEMPPATH); } YY_BREAK case 95: YY_RULE_SETUP #line 263 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEURL); } YY_BREAK case 96: YY_RULE_SETUP #line 264 "/home/even/mapserver/git/mapserver/maplexer.l" { BEGIN(INCLUDE); } YY_BREAK case 97: YY_RULE_SETUP #line 265 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(INDEX); } YY_BREAK case 98: YY_RULE_SETUP #line 266 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(INITIALGAP); } YY_BREAK case 99: YY_RULE_SETUP #line 267 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(INTERLACE); } YY_BREAK case 100: YY_RULE_SETUP #line 268 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(INTERVALS); } YY_BREAK case 101: YY_RULE_SETUP #line 269 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(JOIN); } YY_BREAK case 102: YY_RULE_SETUP #line 270 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(KEYIMAGE); } YY_BREAK case 103: YY_RULE_SETUP #line 271 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(KEYSIZE); } YY_BREAK case 104: YY_RULE_SETUP #line 272 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(KEYSPACING); } YY_BREAK case 105: YY_RULE_SETUP #line 273 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABEL); } YY_BREAK case 106: YY_RULE_SETUP #line 274 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELCACHE); } YY_BREAK case 107: YY_RULE_SETUP #line 275 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELFORMAT); } YY_BREAK case 108: YY_RULE_SETUP #line 276 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELITEM); } YY_BREAK case 109: YY_RULE_SETUP #line 277 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMAXSCALE); } YY_BREAK case 110: YY_RULE_SETUP #line 278 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMAXSCALEDENOM); } YY_BREAK case 111: YY_RULE_SETUP #line 279 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMINSCALE); } YY_BREAK case 112: YY_RULE_SETUP #line 280 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMINSCALEDENOM); } YY_BREAK case 113: YY_RULE_SETUP #line 281 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELREQUIRES); } YY_BREAK case 114: YY_RULE_SETUP #line 282 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LATLON); } YY_BREAK case 115: YY_RULE_SETUP #line 283 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LAYER); } YY_BREAK case 116: YY_RULE_SETUP #line 284 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LEADER); } YY_BREAK case 117: YY_RULE_SETUP #line 285 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LEGEND); } YY_BREAK case 118: YY_RULE_SETUP #line 286 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LEGENDFORMAT); } YY_BREAK case 119: YY_RULE_SETUP #line 287 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LINECAP); } YY_BREAK case 120: YY_RULE_SETUP #line 288 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LINEJOIN); } YY_BREAK case 121: YY_RULE_SETUP #line 289 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LINEJOINMAXSIZE); } YY_BREAK case 122: YY_RULE_SETUP #line 290 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(LOG); } YY_BREAK case 123: YY_RULE_SETUP #line 291 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAP); } YY_BREAK case 124: YY_RULE_SETUP #line 292 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MARKER); } YY_BREAK case 125: YY_RULE_SETUP #line 293 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MARKERSIZE); } YY_BREAK case 126: YY_RULE_SETUP #line 294 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MASK); } YY_BREAK case 127: YY_RULE_SETUP #line 295 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXARCS); } YY_BREAK case 128: YY_RULE_SETUP #line 296 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXBOXSIZE); } YY_BREAK case 129: YY_RULE_SETUP #line 297 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXDISTANCE); } YY_BREAK case 130: YY_RULE_SETUP #line 298 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXFEATURES); } YY_BREAK case 131: YY_RULE_SETUP #line 299 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXINTERVAL); } YY_BREAK case 132: YY_RULE_SETUP #line 300 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSCALE); } YY_BREAK case 133: YY_RULE_SETUP #line 301 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSCALEDENOM); } YY_BREAK case 134: YY_RULE_SETUP #line 302 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXGEOWIDTH); } YY_BREAK case 135: YY_RULE_SETUP #line 303 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXLENGTH); } YY_BREAK case 136: YY_RULE_SETUP #line 304 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSIZE); } YY_BREAK case 137: YY_RULE_SETUP #line 305 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSUBDIVIDE); } YY_BREAK case 138: YY_RULE_SETUP #line 306 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXTEMPLATE); } YY_BREAK case 139: YY_RULE_SETUP #line 307 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXWIDTH); } YY_BREAK case 140: YY_RULE_SETUP #line 308 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(METADATA); } YY_BREAK case 141: YY_RULE_SETUP #line 309 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MIMETYPE); } YY_BREAK case 142: YY_RULE_SETUP #line 310 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINARCS); } YY_BREAK case 143: YY_RULE_SETUP #line 311 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINBOXSIZE); } YY_BREAK case 144: YY_RULE_SETUP #line 312 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINDISTANCE); } YY_BREAK case 145: YY_RULE_SETUP #line 313 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(REPEATDISTANCE); } YY_BREAK case 146: YY_RULE_SETUP #line 314 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXOVERLAPANGLE); } YY_BREAK case 147: YY_RULE_SETUP #line 315 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINFEATURESIZE); } YY_BREAK case 148: YY_RULE_SETUP #line 316 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MININTERVAL); } YY_BREAK case 149: YY_RULE_SETUP #line 317 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSCALE); } YY_BREAK case 150: YY_RULE_SETUP #line 318 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSCALEDENOM); } YY_BREAK case 151: YY_RULE_SETUP #line 319 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINGEOWIDTH); } YY_BREAK case 152: YY_RULE_SETUP #line 320 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINLENGTH); } YY_BREAK case 153: YY_RULE_SETUP #line 321 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSIZE); } YY_BREAK case 154: YY_RULE_SETUP #line 322 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSUBDIVIDE); } YY_BREAK case 155: YY_RULE_SETUP #line 323 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINTEMPLATE); } YY_BREAK case 156: YY_RULE_SETUP #line 324 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MINWIDTH); } YY_BREAK case 157: YY_RULE_SETUP #line 325 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(NAME); } YY_BREAK case 158: YY_RULE_SETUP #line 326 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OFFSET); } YY_BREAK case 159: YY_RULE_SETUP #line 327 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OFFSITE); } YY_BREAK case 160: YY_RULE_SETUP #line 328 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OPACITY); } YY_BREAK case 161: YY_RULE_SETUP #line 329 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OUTLINECOLOR); } YY_BREAK case 162: YY_RULE_SETUP #line 330 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OUTLINEWIDTH); } YY_BREAK case 163: YY_RULE_SETUP #line 331 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OUTPUTFORMAT); } YY_BREAK case 164: YY_RULE_SETUP #line 332 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYBACKGROUNDCOLOR); } YY_BREAK case 165: YY_RULE_SETUP #line 333 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYCOLOR); } YY_BREAK case 166: YY_RULE_SETUP #line 334 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYMAXSIZE); } YY_BREAK case 167: YY_RULE_SETUP #line 335 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYMINSIZE); } YY_BREAK case 168: YY_RULE_SETUP #line 336 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYOUTLINECOLOR); } YY_BREAK case 169: YY_RULE_SETUP #line 337 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYSIZE); } YY_BREAK case 170: YY_RULE_SETUP #line 338 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYSYMBOL); } YY_BREAK case 171: YY_RULE_SETUP #line 339 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(PARTIALS); } YY_BREAK case 172: YY_RULE_SETUP #line 340 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(PATTERN); } YY_BREAK case 173: YY_RULE_SETUP #line 341 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(POINTS); } YY_BREAK case 174: YY_RULE_SETUP #line 342 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(ITEMS); } YY_BREAK case 175: YY_RULE_SETUP #line 343 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(POSITION); } YY_BREAK case 176: YY_RULE_SETUP #line 344 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(POSTLABELCACHE); } YY_BREAK case 177: YY_RULE_SETUP #line 345 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(PRIORITY); } YY_BREAK case 178: YY_RULE_SETUP #line 346 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(PROCESSING); } YY_BREAK case 179: YY_RULE_SETUP #line 347 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(PROJECTION); } YY_BREAK case 180: YY_RULE_SETUP #line 348 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(QUERYFORMAT); } YY_BREAK case 181: YY_RULE_SETUP #line 349 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(QUERYMAP); } YY_BREAK case 182: YY_RULE_SETUP #line 350 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(REFERENCE); } YY_BREAK case 183: YY_RULE_SETUP #line 351 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(REGION); } YY_BREAK case 184: YY_RULE_SETUP #line 352 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(RELATIVETO); } YY_BREAK case 185: YY_RULE_SETUP #line 353 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(REQUIRES); } YY_BREAK case 186: YY_RULE_SETUP #line 354 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(RESOLUTION); } YY_BREAK case 187: YY_RULE_SETUP #line 355 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(DEFRESOLUTION); } YY_BREAK case 188: YY_RULE_SETUP #line 356 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALE); } YY_BREAK case 189: YY_RULE_SETUP #line 357 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALEDENOM); } YY_BREAK case 190: YY_RULE_SETUP #line 358 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALEBAR); } YY_BREAK case 191: YY_RULE_SETUP #line 359 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALETOKEN); } YY_BREAK case 192: YY_RULE_SETUP #line 360 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SHADOWCOLOR); } YY_BREAK case 193: YY_RULE_SETUP #line 361 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SHADOWSIZE); } YY_BREAK case 194: YY_RULE_SETUP #line 362 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SHAPEPATH); } YY_BREAK case 195: YY_RULE_SETUP #line 363 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SIZE); } YY_BREAK case 196: YY_RULE_SETUP #line 364 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SIZEUNITS); } YY_BREAK case 197: YY_RULE_SETUP #line 365 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(STATUS); } YY_BREAK case 198: YY_RULE_SETUP #line 366 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(STYLE); } YY_BREAK case 199: YY_RULE_SETUP #line 367 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(STYLEITEM); } YY_BREAK case 200: YY_RULE_SETUP #line 368 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOL); } YY_BREAK case 201: YY_RULE_SETUP #line 369 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOLSCALE); } YY_BREAK case 202: YY_RULE_SETUP #line 370 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOLSCALEDENOM); } YY_BREAK case 203: YY_RULE_SETUP #line 371 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOLSET); } YY_BREAK case 204: YY_RULE_SETUP #line 372 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TABLE); } YY_BREAK case 205: YY_RULE_SETUP #line 373 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TEMPLATE); } YY_BREAK case 206: YY_RULE_SETUP #line 374 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TEMPLATEPATTERN); } YY_BREAK case 207: YY_RULE_SETUP #line 375 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TEXT); } YY_BREAK case 208: YY_RULE_SETUP #line 376 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TILEINDEX); } YY_BREAK case 209: YY_RULE_SETUP #line 377 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TILEITEM); } YY_BREAK case 210: YY_RULE_SETUP #line 378 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TILESRS); } YY_BREAK case 211: YY_RULE_SETUP #line 379 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TITLE); } YY_BREAK case 212: YY_RULE_SETUP #line 380 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TO); } YY_BREAK case 213: YY_RULE_SETUP #line 381 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TOLERANCE); } YY_BREAK case 214: YY_RULE_SETUP #line 382 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TOLERANCEUNITS); } YY_BREAK case 215: YY_RULE_SETUP #line 383 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TRANSPARENCY); } YY_BREAK case 216: YY_RULE_SETUP #line 384 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TRANSPARENT); } YY_BREAK case 217: YY_RULE_SETUP #line 385 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TRANSFORM); } YY_BREAK case 218: YY_RULE_SETUP #line 386 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(TYPE); } YY_BREAK case 219: YY_RULE_SETUP #line 387 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(UNITS); } YY_BREAK case 220: YY_RULE_SETUP #line 388 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(VALIDATION); } YY_BREAK case 221: YY_RULE_SETUP #line 389 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(VALUES); } YY_BREAK case 222: YY_RULE_SETUP #line 390 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(WEB); } YY_BREAK case 223: YY_RULE_SETUP #line 391 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(WIDTH); } YY_BREAK case 224: YY_RULE_SETUP #line 392 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(WKT); } YY_BREAK case 225: YY_RULE_SETUP #line 393 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(WRAP); } YY_BREAK case 226: YY_RULE_SETUP #line 395 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_ANNOTATION); } YY_BREAK case 227: YY_RULE_SETUP #line 396 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_AUTO); } YY_BREAK case 228: YY_RULE_SETUP #line 397 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_AUTO2); } YY_BREAK case 229: YY_RULE_SETUP #line 398 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_BEVEL); } YY_BREAK case 230: YY_RULE_SETUP #line 399 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_BITMAP); } YY_BREAK case 231: YY_RULE_SETUP #line 400 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_BUTT); } YY_BREAK case 232: YY_RULE_SETUP #line 401 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CC); } YY_BREAK case 233: YY_RULE_SETUP #line 402 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ALIGN_CENTER); } YY_BREAK case 234: YY_RULE_SETUP #line 403 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_CHART); } YY_BREAK case 235: YY_RULE_SETUP #line 404 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_CIRCLE); } YY_BREAK case 236: YY_RULE_SETUP #line 405 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CL); } YY_BREAK case 237: YY_RULE_SETUP #line 406 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CR); } YY_BREAK case 238: YY_RULE_SETUP #line 407 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DB_CSV); } YY_BREAK case 239: YY_RULE_SETUP #line 408 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DB_POSTGRES); } YY_BREAK case 240: YY_RULE_SETUP #line 409 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DB_MYSQL); } YY_BREAK case 241: YY_RULE_SETUP #line 410 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DEFAULT); } YY_BREAK case 242: YY_RULE_SETUP #line 411 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DD); } YY_BREAK case 243: YY_RULE_SETUP #line 412 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_ELLIPSE); } YY_BREAK case 244: YY_RULE_SETUP #line 413 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_EMBED); } YY_BREAK case 245: YY_RULE_SETUP #line 414 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_FALSE); } YY_BREAK case 246: YY_RULE_SETUP #line 415 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_FEET); } YY_BREAK case 247: YY_RULE_SETUP #line 416 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_FOLLOW); } YY_BREAK case 248: YY_RULE_SETUP #line 417 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_GIANT); } YY_BREAK case 249: YY_RULE_SETUP #line 418 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_HATCH); } YY_BREAK case 250: YY_RULE_SETUP #line 419 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_HILITE); } YY_BREAK case 251: YY_RULE_SETUP #line 420 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_INCHES); } YY_BREAK case 252: YY_RULE_SETUP #line 421 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_KILOMETERS); } YY_BREAK case 253: YY_RULE_SETUP #line 422 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LARGE); } YY_BREAK case 254: YY_RULE_SETUP #line 423 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LC); } YY_BREAK case 255: YY_RULE_SETUP #line 424 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ALIGN_LEFT); } YY_BREAK case 256: YY_RULE_SETUP #line 425 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_LINE); } YY_BREAK case 257: YY_RULE_SETUP #line 426 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LL); } YY_BREAK case 258: YY_RULE_SETUP #line 427 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LR); } YY_BREAK case 259: YY_RULE_SETUP #line 428 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_MEDIUM); } YY_BREAK case 260: YY_RULE_SETUP #line 429 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_METERS); } YY_BREAK case 261: YY_RULE_SETUP #line 430 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_NAUTICALMILES); } YY_BREAK case 262: YY_RULE_SETUP #line 431 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_MILES); } YY_BREAK case 263: YY_RULE_SETUP #line 432 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_MITER); } YY_BREAK case 264: YY_RULE_SETUP #line 433 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_MULTIPLE); } YY_BREAK case 265: YY_RULE_SETUP #line 434 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_NONE); } YY_BREAK case 266: YY_RULE_SETUP #line 435 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_NORMAL); } YY_BREAK case 267: YY_RULE_SETUP #line 436 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_OFF); } YY_BREAK case 268: YY_RULE_SETUP #line 437 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_OGR); } YY_BREAK case 269: YY_RULE_SETUP #line 438 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ON); } YY_BREAK case 270: YY_RULE_SETUP #line 439 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_ONE); } YY_BREAK case 271: YY_RULE_SETUP #line 440 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_MANY); } YY_BREAK case 272: YY_RULE_SETUP #line 441 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ORACLESPATIAL); } YY_BREAK case 273: YY_RULE_SETUP #line 442 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_PERCENTAGES); } YY_BREAK case 274: YY_RULE_SETUP #line 443 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_PIXMAP); } YY_BREAK case 275: YY_RULE_SETUP #line 444 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_PIXELS); } YY_BREAK case 276: YY_RULE_SETUP #line 445 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_POINT); } YY_BREAK case 277: YY_RULE_SETUP #line 446 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_POLYGON); } YY_BREAK case 278: YY_RULE_SETUP #line 447 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_POSTGIS); } YY_BREAK case 279: YY_RULE_SETUP #line 448 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_PLUGIN); } YY_BREAK case 280: YY_RULE_SETUP #line 449 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_QUERY); } YY_BREAK case 281: YY_RULE_SETUP #line 450 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_RASTER); } YY_BREAK case 282: YY_RULE_SETUP #line 451 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ALIGN_RIGHT); } YY_BREAK case 283: YY_RULE_SETUP #line 452 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_ROUND); } YY_BREAK case 284: YY_RULE_SETUP #line 453 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SDE); } YY_BREAK case 285: YY_RULE_SETUP #line 454 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SELECTED); } YY_BREAK case 286: YY_RULE_SETUP #line 455 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SIMPLE); } YY_BREAK case 287: YY_RULE_SETUP #line 456 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SINGLE); } YY_BREAK case 288: YY_RULE_SETUP #line 457 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SMALL); } YY_BREAK case 289: YY_RULE_SETUP #line 458 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_SQUARE); } YY_BREAK case 290: YY_RULE_SETUP #line 459 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SVG); } YY_BREAK case 291: YY_RULE_SETUP #line 460 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(POLAROFFSET); } YY_BREAK case 292: YY_RULE_SETUP #line 461 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TINY); } YY_BREAK case 293: YY_RULE_SETUP #line 462 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_TRIANGLE); } YY_BREAK case 294: YY_RULE_SETUP #line 463 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TRUE); } YY_BREAK case 295: YY_RULE_SETUP #line 464 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TRUETYPE); } YY_BREAK case 296: YY_RULE_SETUP #line 465 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UC); } YY_BREAK case 297: YY_RULE_SETUP #line 466 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UL); } YY_BREAK case 298: YY_RULE_SETUP #line 467 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UR); } YY_BREAK case 299: YY_RULE_SETUP #line 468 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UNION); } YY_BREAK case 300: YY_RULE_SETUP #line 469 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UVRASTER); } YY_BREAK case 301: YY_RULE_SETUP #line 470 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CONTOUR); } YY_BREAK case 302: YY_RULE_SETUP #line 471 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_VECTOR); } YY_BREAK case 303: YY_RULE_SETUP #line 472 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_WFS); } YY_BREAK case 304: YY_RULE_SETUP #line 473 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_WMS); } YY_BREAK case 305: YY_RULE_SETUP #line 474 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_GD_ALPHA); } YY_BREAK case 306: YY_RULE_SETUP #line 476 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_STRING); } YY_BREAK case 307: YY_RULE_SETUP #line 484 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } YY_BREAK case 308: /* rule 308 can match eol */ YY_RULE_SETUP #line 494 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_BINDING); } YY_BREAK case 309: YY_RULE_SETUP #line 503 "/home/even/mapserver/git/mapserver/maplexer.l" { /* attribute binding - shape (fixed value) */ return(MS_TOKEN_BINDING_SHAPE); } YY_BREAK case 310: YY_RULE_SETUP #line 507 "/home/even/mapserver/git/mapserver/maplexer.l" { /* attribute binding - map cellsize */ return(MS_TOKEN_BINDING_MAP_CELLSIZE); } YY_BREAK case 311: YY_RULE_SETUP #line 511 "/home/even/mapserver/git/mapserver/maplexer.l" { /* attribute binding - data cellsize */ return(MS_TOKEN_BINDING_DATA_CELLSIZE); } YY_BREAK case 312: /* rule 312 can match eol */ YY_RULE_SETUP #line 515 "/home/even/mapserver/git/mapserver/maplexer.l" { /* attribute binding - numeric (no quotes) */ msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_DOUBLE); } YY_BREAK case 313: /* rule 313 can match eol */ YY_RULE_SETUP #line 524 "/home/even/mapserver/git/mapserver/maplexer.l" { /* attribute binding - string (single or double quotes) */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_STRING); } YY_BREAK case 314: /* rule 314 can match eol */ YY_RULE_SETUP #line 533 "/home/even/mapserver/git/mapserver/maplexer.l" { /* attribute binding - time */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_TIME); } YY_BREAK case 315: YY_RULE_SETUP #line 543 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } YY_BREAK case 316: YY_RULE_SETUP #line 551 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_TOKEN_LITERAL_NUMBER); } YY_BREAK case 317: /* rule 317 can match eol */ YY_RULE_SETUP #line 559 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_LITERAL_TIME); } YY_BREAK case 318: /* rule 318 can match eol */ YY_RULE_SETUP #line 568 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_IREGEX); } YY_BREAK case 319: /* rule 319 can match eol */ YY_RULE_SETUP #line 577 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_REGEX); } YY_BREAK case 320: YY_RULE_SETUP #line 586 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_EXPRESSION); } YY_BREAK case 321: YY_RULE_SETUP #line 595 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_LIST); } YY_BREAK case 322: YY_RULE_SETUP #line 604 "/home/even/mapserver/git/mapserver/maplexer.l" { msyystring_return_state = MS_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } YY_BREAK case 323: YY_RULE_SETUP #line 612 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); if (msyystring_begin == msyytext[0]) { BEGIN(msyystring_begin_state); *msyystring_buffer_ptr = '\0'; if (msyystring_return_state == MS_STRING) { if (msyystring_icase && strlen(msyytext)==2) { msyystring_icase = MS_FALSE; // reset return MS_ISTRING; } else return MS_STRING; } return msyystring_return_state; } else { ++msyystring_size; *msyystring_buffer_ptr++ = *msyytext; if (strlen(msyytext)==2) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = msyytext[1]; } } } YY_BREAK case 324: YY_RULE_SETUP #line 642 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; if (strlen(msyytext) == 2) *msyystring_buffer_ptr++ = msyytext[1]; else *msyystring_buffer_ptr++ = msyytext[0]; } YY_BREAK case 325: /* rule 325 can match eol */ YY_RULE_SETUP #line 653 "/home/even/mapserver/git/mapserver/maplexer.l" { char *yptr = msyytext; while ( *yptr ) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = *yptr++; } } YY_BREAK case 326: /* rule 326 can match eol */ YY_RULE_SETUP #line 663 "/home/even/mapserver/git/mapserver/maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; if(include_stack_ptr >= MAX_INCLUDE_DEPTH) { msSetError(MS_IOERR, "Includes nested to deeply.", "msyylex()"); return(-1); } include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; /* save state */ include_lineno[include_stack_ptr] = msyylineno; include_stack_ptr++; msyyin = fopen(msBuildPath(path, msyybasepath, msyytext), "r"); if(!msyyin) { msSetError(MS_IOERR, "Error opening included file \"%s\".", "msyylex()", msyytext); return(-1); } msyy_switch_to_buffer( msyy_create_buffer(msyyin, YY_BUF_SIZE) ); msyylineno = 1; BEGIN(INITIAL); } YY_BREAK case 327: YY_RULE_SETUP #line 688 "/home/even/mapserver/git/mapserver/maplexer.l" { msyystring_return_state = MS_TOKEN_LITERAL_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } YY_BREAK case 328: YY_RULE_SETUP #line 696 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_STRING); } YY_BREAK case 329: /* rule 329 can match eol */ YY_RULE_SETUP #line 703 "/home/even/mapserver/git/mapserver/maplexer.l" { msyylineno++; } YY_BREAK case YY_STATE_EOF(INITIAL): #line 705 "/home/even/mapserver/git/mapserver/maplexer.l" { if( --include_stack_ptr < 0 ) return(EOF); /* end of main file */ else { fclose(YY_CURRENT_BUFFER->yy_input_file); msyy_delete_buffer( YY_CURRENT_BUFFER ); msyy_switch_to_buffer(include_stack[include_stack_ptr]); msyylineno = include_lineno[include_stack_ptr]; } } YY_BREAK case 330: /* rule 330 can match eol */ YY_RULE_SETUP #line 716 "/home/even/mapserver/git/mapserver/maplexer.l" { return(0); } YY_BREAK case 331: YY_RULE_SETUP #line 720 "/home/even/mapserver/git/mapserver/maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(0); } YY_BREAK case 332: YY_RULE_SETUP #line 726 "/home/even/mapserver/git/mapserver/maplexer.l" { return(msyytext[0]); } YY_BREAK case 333: YY_RULE_SETUP #line 727 "/home/even/mapserver/git/mapserver/maplexer.l" ECHO; YY_BREAK #line 4416 "/home/even/mapserver/git/mapserver/maplexer.c" case YY_STATE_EOF(URL_VARIABLE): case YY_STATE_EOF(URL_STRING): case YY_STATE_EOF(EXPRESSION_STRING): case YY_STATE_EOF(INCLUDE): case YY_STATE_EOF(MSSTRING): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed msyyin at a new source and called * msyylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = msyyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( msyywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * msyytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of msyylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ msyyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; msyyrestart(msyyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) msyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 84); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1930 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 84; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1930 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 1929); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up msyytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ msyyrestart(msyyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( msyywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve msyytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void msyyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ msyyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = msyy_create_buffer(msyyin,YY_BUF_SIZE ); } msyy_init_buffer(YY_CURRENT_BUFFER,input_file ); msyy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void msyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * msyypop_buffer_state(); * msyypush_buffer_state(new_buffer); */ msyyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; msyy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (msyywrap()) processing, but the only time this flag * is looked at is after msyywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void msyy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; msyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE msyy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) msyyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in msyy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) msyyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in msyy_create_buffer()" ); b->yy_is_our_buffer = 1; msyy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with msyy_create_buffer() * */ void msyy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) msyyfree((void *) b->yy_ch_buf ); msyyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a msyyrestart() or at EOF. */ static void msyy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; msyy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then msyy_init_buffer was _probably_ * called from msyyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void msyy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) msyy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void msyypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; msyyensure_buffer_stack(); /* This block is copied from msyy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from msyy_switch_to_buffer. */ msyy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void msyypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; msyy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { msyy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void msyyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)msyyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in msyyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)msyyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in msyyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE msyy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) msyyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in msyy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; msyy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to msyylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * msyy_scan_bytes() instead. */ YY_BUFFER_STATE msyy_scan_string (yyconst char * yystr ) { return msyy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to msyylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE msyy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) msyyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in msyy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = msyy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in msyy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up msyytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ msyytext[msyyleng] = (yy_hold_char); \ (yy_c_buf_p) = msyytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ msyyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int msyyget_lineno (void) { return msyylineno; } /** Get the input stream. * */ FILE *msyyget_in (void) { return msyyin; } /** Get the output stream. * */ FILE *msyyget_out (void) { return msyyout; } /** Get the length of the current token. * */ int msyyget_leng (void) { return msyyleng; } /** Get the current token. * */ char *msyyget_text (void) { return msyytext; } /** Set the current line number. * @param line_number * */ void msyyset_lineno (int line_number ) { msyylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see msyy_switch_to_buffer */ void msyyset_in (FILE * in_str ) { msyyin = in_str ; } void msyyset_out (FILE * out_str ) { msyyout = out_str ; } int msyyget_debug (void) { return msyy_flex_debug; } void msyyset_debug (int bdebug ) { msyy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from msyylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT msyyin = stdin; msyyout = stdout; #else msyyin = (FILE *) 0; msyyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * msyylex_init() */ return 0; } /* msyylex_destroy is for both reentrant and non-reentrant scanners. */ int msyylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ msyy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; msyypop_buffer_state(); } /* Destroy the stack itself. */ msyyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * msyylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *msyyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *msyyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void msyyfree (void * ptr ) { free( (char *) ptr ); /* see msyyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 727 "/home/even/mapserver/git/mapserver/maplexer.l" /* ** Any extra C functions */ int msyywrap() /* override */ { return(1); } int msyyerror(char *s) { msSetError(MS_PARSEERR, "%s", "msyyparse()", s); return(0); } mapserver-6.4.1/classobject.c0000644002461700001440000001502312261257215015755 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions for operating on a classObj that don't belong in a * more specific file such as mapfile.c. * Adapted from mapobject.c. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 2004, Sean Gillies * * 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. ****************************************************************************/ #include "mapserver.h" #ifdef USE_GDAL # include "gdal.h" # include "cpl_conv.h" #endif /* ** Add a label to a classObj (order doesn't matter for labels like it does with styles) */ int msAddLabelToClass(classObj *class, labelObj *label) { if (!label) { msSetError(MS_CHILDERR, "Can't add a NULL label.", "msAddLabelToClass()"); return MS_FAILURE; } if (msGrowClassLabels(class) == NULL) return MS_FAILURE; /* msGrowClassLabels will alloc the label, free it in this case */ free(class->labels[class->numlabels]); class->labels[class->numlabels] = label; MS_REFCNT_INCR(label); class->numlabels++; return MS_SUCCESS; } /* ** Remove a label from a classObj. */ labelObj *msRemoveLabelFromClass(classObj *class, int nLabelIndex) { int i; labelObj *label; if (nLabelIndex < 0 || nLabelIndex >= class->numlabels) { msSetError(MS_CHILDERR, "Cannot remove label, invalid index %d", "msRemoveLabelFromClass()", nLabelIndex); return NULL; } else { label=class->labels[nLabelIndex]; for (i=nLabelIndex; inumlabels-1; i++) { class->labels[i]=class->labels[i+1]; } class->labels[class->numlabels-1]=NULL; class->numlabels--; MS_REFCNT_DECR(label); return label; } } /** * Move the style up inside the array of styles. */ int msMoveStyleUp(classObj *class, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (class && nStyleIndex < class->numstyles && nStyleIndex >0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, class->styles[nStyleIndex]); msCopyStyle(class->styles[nStyleIndex], class->styles[nStyleIndex-1]); msCopyStyle(class->styles[nStyleIndex-1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveStyleUp()", nStyleIndex); return (MS_FAILURE); } /** * Move the style down inside the array of styles. */ int msMoveStyleDown(classObj *class, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (class && nStyleIndex < class->numstyles-1 && nStyleIndex >=0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, class->styles[nStyleIndex]); msCopyStyle(class->styles[nStyleIndex], class->styles[nStyleIndex+1]); msCopyStyle(class->styles[nStyleIndex+1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveStyleDown()", nStyleIndex); return (MS_FAILURE); } /* Moved here from mapscript.i * * Returns the index at which the style was inserted * */ int msInsertStyle(classObj *class, styleObj *style, int nStyleIndex) { int i; if (!style) { msSetError(MS_CHILDERR, "Can't insert a NULL Style", "msInsertStyle()"); return -1; } /* Ensure there is room for a new style */ if (msGrowClassStyles(class) == NULL) { return -1; } /* Catch attempt to insert past end of styles array */ else if (nStyleIndex >= class->numstyles) { msSetError(MS_CHILDERR, "Cannot insert style beyond index %d", "insertStyle()", class->numstyles-1); return -1; } else if (nStyleIndex < 0) { /* Insert at the end by default */ class->styles[class->numstyles]=style; MS_REFCNT_INCR(style); class->numstyles++; return class->numstyles-1; } else if (nStyleIndex >= 0 && nStyleIndex < class->numstyles) { /* Move styles existing at the specified nStyleIndex or greater */ /* to a higher nStyleIndex */ for (i=class->numstyles-1; i>=nStyleIndex; i--) { class->styles[i+1] = class->styles[i]; } class->styles[nStyleIndex]=style; MS_REFCNT_INCR(style); class->numstyles++; return nStyleIndex; } else { msSetError(MS_CHILDERR, "Invalid nStyleIndex", "insertStyle()"); return -1; } } styleObj *msRemoveStyle(classObj *class, int nStyleIndex) { int i; styleObj *style; if (nStyleIndex < 0 || nStyleIndex >= class->numstyles) { msSetError(MS_CHILDERR, "Cannot remove style, invalid nStyleIndex %d", "removeStyle()", nStyleIndex); return NULL; } else { style=class->styles[nStyleIndex]; for (i=nStyleIndex; inumstyles-1; i++) { class->styles[i]=class->styles[i+1]; } class->styles[class->numstyles-1]=NULL; class->numstyles--; MS_REFCNT_DECR(style); return style; } } /** * Delete the style identified by the index and shift * styles that follows the deleted style. */ int msDeleteStyle(classObj *class, int nStyleIndex) { int i = 0; if (class && nStyleIndex < class->numstyles && nStyleIndex >=0) { if (freeStyle(class->styles[nStyleIndex]) == MS_SUCCESS) msFree(class->styles[nStyleIndex]); for (i=nStyleIndex; i< class->numstyles-1; i++) { class->styles[i] = class->styles[i+1]; } class->styles[class->numstyles-1] = NULL; class->numstyles--; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msDeleteStyle()", nStyleIndex); return (MS_FAILURE); } mapserver-6.4.1/maplayer.c0000644002461700001440000016462112261257215015304 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of most layerObj functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maptime.h" #include "mapogcfilter.h" #include "mapthread.h" #include "mapfile.h" #include "mapparser.h" #include static int populateVirtualTable(layerVTableObj *vtable); /* ** Iteminfo is a layer parameter that holds information necessary to retrieve an individual item for ** a particular source. It is an array built from a list of items. The type of iteminfo will vary by ** source. For shapefiles and OGR it is simply an array of integers where each value is an index for ** the item. For SDE it's a ESRI specific type that contains index and column type information. Two ** helper functions below initialize and free that structure member which is used locally by layer ** specific functions. */ int msLayerInitItemInfo(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerInitItemInfo(layer); } void msLayerFreeItemInfo(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return; } layer->vtable->LayerFreeItemInfo(layer); } int msLayerRestoreFromScaletokens(layerObj *layer) { if(!layer->scaletokens) { return MS_SUCCESS; } if(layer->orig_data) { msFree(layer->data); layer->data = layer->orig_data; layer->orig_data = NULL; } if(layer->orig_tileindex) { msFree(layer->tileindex); layer->tileindex = layer->orig_tileindex; layer->orig_tileindex = NULL; } if(layer->orig_tileitem) { msFree(layer->tileitem); layer->tileitem = layer->orig_tileitem; layer->orig_tileitem = NULL; } if(layer->orig_filter) { msLoadExpressionString(&(layer->filter),layer->orig_filter); msFree(layer->orig_filter); layer->orig_filter = NULL; } if(layer->orig_filteritem) { msFree(layer->filteritem); layer->filteritem = layer->orig_filteritem; layer->orig_filteritem = NULL; } return MS_SUCCESS; } int msLayerApplyScaletokens(layerObj *layer, double scale) { int i; if(!layer->scaletokens) { return MS_SUCCESS; } msLayerRestoreFromScaletokens(layer); for(i=0;inumscaletokens;i++) { scaleTokenObj *st = &layer->scaletokens[i]; scaleTokenEntryObj *ste = NULL; if(scale<=0) { ste = &(st->tokens[0]); /* no scale defined, use first entry */ } else { int tokenindex=0; while(tokenindexn_entries) { ste = &(st->tokens[tokenindex]); if(scale < ste->maxscale && scale >= ste->minscale) break; /* current token is the correct one */ tokenindex++; ste = NULL; } } assert(ste); if(layer->data && strstr(layer->data,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->data (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } layer->orig_data = layer->data; layer->data = msStrdup(layer->data); layer->data = msReplaceSubstring(layer->data,st->name,ste->value); } if(layer->tileindex && strstr(layer->tileindex,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->tileindex (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } layer->orig_tileindex = layer->tileindex; layer->tileindex = msStrdup(layer->tileindex); layer->tileindex = msReplaceSubstring(layer->tileindex,st->name,ste->value); } if(layer->tileitem && strstr(layer->tileitem,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->tileitem (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } layer->orig_tileitem = layer->tileitem; layer->tileitem = msStrdup(layer->tileitem); layer->tileitem = msReplaceSubstring(layer->tileitem,st->name,ste->value); } if(layer->filteritem && strstr(layer->filteritem,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->filteritem (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } layer->orig_filteritem = layer->filteritem; layer->filteritem = msStrdup(layer->filteritem); layer->filteritem = msReplaceSubstring(layer->filteritem,st->name,ste->value); } if(layer->filter.string && strstr(layer->filter.string,st->name)) { char *tmpval; if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->filter (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } layer->orig_filter = msStrdup(layer->filter.string); tmpval = msStrdup(layer->filter.string); tmpval = msReplaceSubstring(tmpval,st->name,ste->value); if(msLoadExpressionString(&(layer->filter),tmpval) == -1) return(MS_FAILURE); /* loadExpression() cleans up previously allocated expression */ msFree(tmpval); } } return MS_SUCCESS; } /* ** Does exactly what it implies, readies a layer for processing. */ int msLayerOpen(layerObj *layer) { int rv; /* RFC-86 Scale dependant token replacements*/ rv = msLayerApplyScaletokens(layer,(layer->map)?layer->map->scaledenom:-1); if (rv != MS_SUCCESS) return rv; /* RFC-69 clustering support */ if (layer->cluster.region) return msClusterLayerOpen(layer); if(layer->features && layer->connectiontype != MS_GRATICULE ) layer->connectiontype = MS_INLINE; if(layer->tileindex && layer->connectiontype == MS_SHAPEFILE) layer->connectiontype = MS_TILED_SHAPEFILE; if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS) layer->connectiontype = MS_RASTER; if ( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerOpen(layer); } /* ** Returns MS_TRUE if layer has been opened using msLayerOpen(), MS_FALSE otherwise */ int msLayerIsOpen(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerIsOpen(layer); } /* ** Returns MS_TRUE is a layer supports the common expression/filter syntax (RFC 64) and MS_FALSE otherwise. */ int msLayerSupportsCommonFilters(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerSupportsCommonFilters(layer); } /* ** Performs a spatial, and optionally an attribute based feature search. The function basically ** prepares things so that candidate features can be accessed by query or drawing functions. For ** OGR and shapefiles this sets an internal bit vector that indicates whether a particular feature ** is to processed. For SDE it executes an SQL statement on the SDE server. Once run the msLayerNextShape ** function should be called to actually access the shapes. ** ** Note that for shapefiles we apply any maxfeatures constraint at this point. That may be the only ** connection type where this is feasible. */ int msLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerWhichShapes(layer, rect, isQuery); } /* ** Called after msWhichShapes has been called to actually retrieve shapes within a given area ** and matching a vendor specific filter (i.e. layer FILTER attribute). ** ** Shapefiles: NULL shapes (shapes with attributes but NO vertices are skipped) */ int msLayerNextShape(layerObj *layer, shapeObj *shape) { int rv; if ( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } /* At the end of switch case (default -> break; -> return MS_FAILURE), * was following TODO ITEM: */ /* TO DO! This is where dynamic joins will happen. Joined attributes will be */ /* tagged on to the main attributes with the naming scheme [join name].[item name]. */ /* We need to leverage the iteminfo (I think) at this point */ rv = layer->vtable->LayerNextShape(layer, shape); /* RFC89 Apply Layer GeomTransform */ if(layer->_geomtransform.type != MS_GEOMTRANSFORM_NONE && rv == MS_SUCCESS) { rv = msGeomTransformShape(layer->map, layer, shape); } return rv; } /* ** Used to retrieve a shape from a result set by index. Result sets are created by the various ** msQueryBy...() functions. The index is assigned by the data source. */ /* int msLayerResultsGetShape(layerObj *layer, shapeObj *shape, int tile, long record) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerResultsGetShape(layer, shape, tile, record); } */ /* ** Used to retrieve a shape by index. All data sources must be capable of random access using ** a record number(s) of some sort. */ int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { int rv; if( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if(rv != MS_SUCCESS) return rv; } /* ** TODO: This is where dynamic joins could happen. Joined attributes would be ** tagged on to the main attributes with the naming scheme [join name].[item name]. */ rv = layer->vtable->LayerGetShape(layer, shape, record); /* RFC89 Apply Layer GeomTransform */ if(layer->_geomtransform.type != MS_GEOMTRANSFORM_NONE && rv == MS_SUCCESS) { rv = msGeomTransformShape(layer->map, layer, shape); } return rv; } /* ** Closes resources used by a particular layer. */ void msLayerClose(layerObj *layer) { int i,j,k; /* no need for items once the layer is closed */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } /* clear out items used as part of expressions (bug #2702) -- what about the layer filter? */ freeExpressionTokens(&(layer->filter)); freeExpressionTokens(&(layer->cluster.group)); freeExpressionTokens(&(layer->cluster.filter)); for(i=0; inumclasses; i++) { freeExpressionTokens(&(layer->class[i]->expression)); freeExpressionTokens(&(layer->class[i]->text)); for(j=0; jclass[i]->numstyles; j++) freeExpressionTokens(&(layer->class[i]->styles[j]->_geomtransform)); for(k=0; kclass[i]->numlabels; k++) { freeExpressionTokens(&(layer->class[i]->labels[k]->expression)); freeExpressionTokens(&(layer->class[i]->labels[k]->text)); } } if (layer->vtable) { layer->vtable->LayerClose(layer); } msLayerRestoreFromScaletokens(layer); } /* ** Retrieves a list of attributes available for this layer. Most sources also set the iteminfo array ** at this point. This function is used when processing query results to expose attributes to query ** templates. At that point all attributes are fair game. */ int msLayerGetItems(layerObj *layer) { const char *itemNames; /* clean up any previously allocated instances */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } /* At the end of switch case (default -> break; -> return MS_FAILURE), * was following TODO ITEM: */ /* TO DO! Need to add any joined itemd on to the core layer items, one long list! */ itemNames = msLayerGetProcessingKey( layer, "ITEMS" ); if (itemNames) { layer->items = msStringSplit(itemNames, ',', &layer->numitems); /* populate the iteminfo array */ return (msLayerInitItemInfo(layer)); } else return layer->vtable->LayerGetItems(layer); } /* ** Returns extent of spatial coverage for a layer. ** ** If layer->extent is set then this value is used, otherwise the ** driver-specific implementation is called (this can be expensive). ** ** If layer is not already opened then it is opened and closed (so this ** function can be called on both opened or closed layers). ** ** Returns MS_SUCCESS/MS_FAILURE. */ int msLayerGetExtent(layerObj *layer, rectObj *extent) { int need_to_close = MS_FALSE, status = MS_SUCCESS; if (MS_VALID_EXTENT(layer->extent)) { *extent = layer->extent; return MS_SUCCESS; } if (!msLayerIsOpen(layer)) { if (msLayerOpen(layer) != MS_SUCCESS) return MS_FAILURE; need_to_close = MS_TRUE; } if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) { if (need_to_close) msLayerClose(layer); return rv; } } status = layer->vtable->LayerGetExtent(layer, extent); if (need_to_close) msLayerClose(layer); return(status); } int msLayerGetItemIndex(layerObj *layer, char *item) { int i; for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i], item) == 0) return(i); } return -1; /* item not found */ } static int string2list(char **list, int *listsize, char *string) { int i; for(i=0; i<(*listsize); i++) if(strcasecmp(list[i], string) == 0) { /* printf("string2list (duplicate): %s %d\n", string, i); */ return(i); } list[i] = msStrdup(string); (*listsize)++; /* printf("string2list: %s %d\n", string, i); */ return(i); } extern int msyylex(void); extern int msyylex_destroy(void); extern int msyystate; extern char *msyystring; /* string to tokenize */ extern double msyynumber; /* token containers */ extern char *msyystring_buffer; int msTokenizeExpression(expressionObj *expression, char **list, int *listsize) { tokenListNodeObjPtr node; int token; /* TODO: make sure the constants can't somehow reference invalid expression types */ /* if(expression->type != MS_EXPRESSION && expression->type != MS_GEOMTRANSFORM_EXPRESSION) return MS_SUCCESS; */ msAcquireLock(TLOCK_PARSER); msyystate = MS_TOKENIZE_EXPRESSION; msyystring = expression->string; /* the thing we're tokenizing */ while((token = msyylex()) != 0) { /* keep processing tokens until the end of the string (\0) */ if((node = (tokenListNodeObjPtr) malloc(sizeof(tokenListNodeObj))) == NULL) { msSetError(MS_MEMERR, NULL, "msTokenizeExpression()"); goto parse_error; } node->tailifhead = NULL; node->next = NULL; switch(token) { case MS_TOKEN_LITERAL_NUMBER: node->token = token; node->tokenval.dblval = msyynumber; break; case MS_TOKEN_LITERAL_STRING: node->token = token; node->tokenval.strval = msStrdup(msyystring_buffer); break; case MS_TOKEN_LITERAL_TIME: node->token = token; msTimeInit(&(node->tokenval.tmval)); if(msParseTime(msyystring_buffer, &(node->tokenval.tmval)) != MS_TRUE) { msSetError(MS_PARSEERR, "Parsing time value failed.", "msTokenizeExpression()"); goto parse_error; } break; case MS_TOKEN_BINDING_DOUBLE: /* we've encountered an attribute (binding) reference */ case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: case MS_TOKEN_BINDING_TIME: node->token = token; /* binding type */ node->tokenval.bindval.item = msStrdup(msyystring_buffer); if(list) node->tokenval.bindval.index = string2list(list, listsize, msyystring_buffer); break; case MS_TOKEN_BINDING_SHAPE: node->token = token; break; case MS_TOKEN_BINDING_MAP_CELLSIZE: node->token = token; break; case MS_TOKEN_BINDING_DATA_CELLSIZE: node->token = token; break; case MS_TOKEN_FUNCTION_FROMTEXT: /* we want to process a shape from WKT once and not for every feature being evaluated */ if((token = msyylex()) != 40) { /* ( */ msSetError(MS_PARSEERR, "Parsing fromText function failed.", "msTokenizeExpression()"); goto parse_error; } if((token = msyylex()) != MS_TOKEN_LITERAL_STRING) { msSetError(MS_PARSEERR, "Parsing fromText function failed.", "msTokenizeExpression()"); goto parse_error; } node->token = MS_TOKEN_LITERAL_SHAPE; node->tokenval.shpval = msShapeFromWKT(msyystring_buffer); if(!node->tokenval.shpval) { msSetError(MS_PARSEERR, "Parsing fromText function failed, WKT processing failed.", "msTokenizeExpression()"); goto parse_error; } /* todo: perhaps process optional args (e.g. projection) */ if((token = msyylex()) != 41) { /* ) */ msSetError(MS_PARSEERR, "Parsing fromText function failed.", "msTokenizeExpression()"); goto parse_error; } break; default: node->token = token; /* for everything else */ break; } /* add node to token list */ if(expression->tokens == NULL) { expression->tokens = node; } else { if(expression->tokens->tailifhead != NULL) /* this should never be NULL, but just in case */ expression->tokens->tailifhead->next = node; /* put the node at the end of the list */ } /* repoint the head of the list to the end - our new element this causes a loop if we are at the head, be careful not to walk in a loop */ expression->tokens->tailifhead = node; } expression->curtoken = expression->tokens; /* point at the first token */ msReleaseLock(TLOCK_PARSER); return MS_SUCCESS; parse_error: msReleaseLock(TLOCK_PARSER); return MS_FAILURE; } /* ** This function builds a list of items necessary to draw or query a particular layer by ** examining the contents of the various xxxxitem parameters and expressions. That list is ** then used to set the iteminfo variable. */ int msLayerWhichItems(layerObj *layer, int get_all, char *metadata) { int i, j, k, l, rv; int nt=0; if (!layer->vtable) { rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } /* Cleanup any previous item selection */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } /* ** need a count of potential items/attributes needed */ /* layer level counts */ layer->classitemindex = -1; layer->filteritemindex = -1; layer->styleitemindex = -1; layer->labelitemindex = -1; if(layer->classitem) nt++; if(layer->filteritem) nt++; if(layer->styleitem && strcasecmp(layer->styleitem, "AUTO") != 0) nt++; if(layer->filter.type == MS_EXPRESSION) nt += msCountChars(layer->filter.string, '['); if(layer->cluster.group.type == MS_EXPRESSION) nt += msCountChars(layer->cluster.group.string, '['); if(layer->cluster.filter.type == MS_EXPRESSION) nt += msCountChars(layer->cluster.filter.string, '['); if(layer->labelitem) nt++; if(layer->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) msTokenizeExpression(&layer->_geomtransform, layer->items, &(layer->numitems)); /* class level counts */ for(i=0; inumclasses; i++) { for(j=0; jclass[i]->numstyles; j++) { if(layer->class[i]->styles[j]->rangeitem) nt++; nt += layer->class[i]->styles[j]->numbindings; if(layer->class[i]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) nt += msCountChars(layer->class[i]->styles[j]->_geomtransform.string, '['); } if(layer->class[i]->expression.type == MS_EXPRESSION) nt += msCountChars(layer->class[i]->expression.string, '['); for(l=0; lclass[i]->numlabels; l++) { nt += layer->class[i]->labels[l]->numbindings; for(j=0; jclass[i]->labels[l]->numstyles; j++) { if(layer->class[i]->labels[l]->styles[j]->rangeitem) nt++; nt += layer->class[i]->labels[l]->styles[j]->numbindings; if(layer->class[i]->labels[l]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) nt += msCountChars(layer->class[i]->labels[l]->styles[j]->_geomtransform.string, '['); } if(layer->class[i]->labels[l]->expression.type == MS_EXPRESSION) nt += msCountChars(layer->class[i]->labels[l]->expression.string, '['); if(layer->class[i]->labels[l]->text.type == MS_EXPRESSION || (layer->class[i]->labels[l]->text.string && strchr(layer->class[i]->labels[l]->text.string,'[') != NULL && strchr(layer->class[i]->labels[l]->text.string,']') != NULL)) nt += msCountChars(layer->class[i]->labels[l]->text.string, '['); } if(layer->class[i]->text.type == MS_EXPRESSION || (layer->class[i]->text.string && strchr(layer->class[i]->text.string,'[') != NULL && strchr(layer->class[i]->text.string,']') != NULL)) nt += msCountChars(layer->class[i]->text.string, '['); } /* ** allocate space for the item list (worse case size) */ /* always retrieve all items in some cases */ if(layer->connectiontype == MS_INLINE || get_all == MS_TRUE || (layer->map->outputformat && layer->map->outputformat->renderer == MS_RENDER_WITH_KML)) { msLayerGetItems(layer); if(nt > 0) /* need to realloc the array to accept the possible new items*/ layer->items = (char **)msSmallRealloc(layer->items, sizeof(char *)*(layer->numitems + nt)); } else { rv = layer->vtable->LayerCreateItems(layer, nt); if(rv != MS_SUCCESS) return rv; } /* ** build layer item list, compute item indexes for explicity item references (e.g. classitem) or item bindings */ if(nt > 0) { /* layer items */ if(layer->classitem) layer->classitemindex = string2list(layer->items, &(layer->numitems), layer->classitem); if(layer->filteritem) layer->filteritemindex = string2list(layer->items, &(layer->numitems), layer->filteritem); if(layer->styleitem && strcasecmp(layer->styleitem, "AUTO") != 0) layer->styleitemindex = string2list(layer->items, &(layer->numitems), layer->styleitem); if(layer->labelitem) layer->labelitemindex = string2list(layer->items, &(layer->numitems), layer->labelitem); /* layer classes */ for(i=0; inumclasses; i++) { /* class expression */ if(layer->class[i]->expression.type == MS_EXPRESSION) msTokenizeExpression(&(layer->class[i]->expression), layer->items, &(layer->numitems)); /* class styles (items, bindings, geomtransform) */ for(j=0; jclass[i]->numstyles; j++) { if(layer->class[i]->styles[j]->rangeitem) layer->class[i]->styles[j]->rangeitemindex = string2list(layer->items, &(layer->numitems), layer->class[i]->styles[j]->rangeitem); for(k=0; kclass[i]->styles[j]->bindings[k].item) layer->class[i]->styles[j]->bindings[k].index = string2list(layer->items, &(layer->numitems), layer->class[i]->styles[j]->bindings[k].item); if(layer->class[i]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) msTokenizeExpression(&(layer->class[i]->styles[j]->_geomtransform), layer->items, &(layer->numitems)); } /* class labels and label styles (items, bindings, geomtransform) */ for(l=0; lclass[i]->numlabels; l++) { for(j=0; jclass[i]->labels[l]->numstyles; j++) { if(layer->class[i]->labels[l]->styles[j]->rangeitem) layer->class[i]->labels[l]->styles[j]->rangeitemindex = string2list(layer->items, &(layer->numitems), layer->class[i]->labels[l]->styles[j]->rangeitem); for(k=0; kclass[i]->labels[l]->styles[j]->bindings[k].item) layer->class[i]->labels[l]->styles[j]->bindings[k].index = string2list(layer->items, &(layer->numitems), layer->class[i]->labels[l]->styles[j]->bindings[k].item); if(layer->class[i]->labels[l]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) msTokenizeExpression(&(layer->class[i]->labels[l]->styles[j]->_geomtransform), layer->items, &(layer->numitems)); } for(k=0; kclass[i]->labels[l]->bindings[k].item) layer->class[i]->labels[l]->bindings[k].index = string2list(layer->items, &(layer->numitems), layer->class[i]->labels[l]->bindings[k].item); /* label expression */ if(layer->class[i]->labels[l]->expression.type == MS_EXPRESSION) msTokenizeExpression(&(layer->class[i]->labels[l]->expression), layer->items, &(layer->numitems)); /* label text */ if(layer->class[i]->labels[l]->text.type == MS_EXPRESSION || (layer->class[i]->labels[l]->text.string && strchr(layer->class[i]->labels[l]->text.string,'[') != NULL && strchr(layer->class[i]->labels[l]->text.string,']') != NULL)) msTokenizeExpression(&(layer->class[i]->labels[l]->text), layer->items, &(layer->numitems)); } /* class text */ if(layer->class[i]->text.type == MS_EXPRESSION || (layer->class[i]->text.string && strchr(layer->class[i]->text.string,'[') != NULL && strchr(layer->class[i]->text.string,']') != NULL)) msTokenizeExpression(&(layer->class[i]->text), layer->items, &(layer->numitems)); } /* layer filter */ if(layer->filter.type == MS_EXPRESSION) msTokenizeExpression(&(layer->filter), layer->items, &(layer->numitems)); /* cluster expressions */ if(layer->cluster.group.type == MS_EXPRESSION) msTokenizeExpression(&(layer->cluster.group), layer->items, &(layer->numitems)); if(layer->cluster.filter.type == MS_EXPRESSION) msTokenizeExpression(&(layer->cluster.filter), layer->items, &(layer->numitems)); } if(metadata) { char **tokens; int n = 0; int j; int bFound = 0; tokens = msStringSplit(metadata, ',', &n); if(tokens) { for(i=0; inumitems; j++) { if(strcmp(tokens[i], layer->items[j]) == 0) { bFound = 1; break; } } if(!bFound) { layer->numitems++; layer->items = (char **)msSmallRealloc(layer->items, sizeof(char *)*(layer->numitems)); layer->items[layer->numitems-1] = msStrdup(tokens[i]); } } msFreeCharArray(tokens, n); } } /* populate the iteminfo array */ if(layer->numitems == 0) return(MS_SUCCESS); return(msLayerInitItemInfo(layer)); } /* ** A helper function to set the items to be retrieved with a particular shape. Unused at the moment but will be used ** from within MapScript. Should not need modification. */ int msLayerSetItems(layerObj *layer, char **items, int numitems) { int i; /* Cleanup any previous item selection */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } /* now allocate and set the layer item parameters */ layer->items = (char **)malloc(sizeof(char *)*numitems); MS_CHECK_ALLOC(layer->items, sizeof(char *)*numitems, MS_FAILURE); for(i=0; iitems[i] = msStrdup(items[i]); layer->numitems = numitems; /* populate the iteminfo array */ return(msLayerInitItemInfo(layer)); return(MS_SUCCESS); } /* ** Fills a classObj with style info from the specified shape. This is used ** with STYLEITEM AUTO when rendering shapes. ** For optimal results, this should be called immediately after ** GetNextShape() or GetShape() so that the shape doesn't have to be read ** twice. ** */ int msLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerGetAutoStyle(map, layer, c, shape); } /* ** Fills a classObj with style info from the specified attribute. This is used ** with STYLEITEM "attribute" when rendering shapes. ** */ int msLayerGetFeatureStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { char* stylestring; if (layer->styleitem && layer->styleitemindex >=0) { stylestring = shape->values[layer->styleitemindex]; /* try to find out the current style format */ if (strncasecmp(stylestring,"style",5) == 0) { resetClassStyle(c); c->layer = layer; if (msMaybeAllocateClassStyle(c, 0)) return(MS_FAILURE); msUpdateStyleFromString(c->styles[0], stylestring, MS_FALSE); if(c->styles[0]->symbolname) { if((c->styles[0]->symbol = msGetSymbolIndex(&(map->symbolset), c->styles[0]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class of layer %s.", "msLayerGetFeatureStyle()", c->styles[0]->symbolname, layer->name); return MS_FAILURE; } } } else if (strncasecmp(stylestring,"class",5) == 0) { if (strcasestr(stylestring, " style ") != NULL) { /* reset style if stylestring contains style definitions */ resetClassStyle(c); c->layer = layer; } msUpdateClassFromString(c, stylestring, MS_FALSE); } else if (strncasecmp(stylestring,"pen",3) == 0 || strncasecmp(stylestring,"brush",5) == 0 || strncasecmp(stylestring,"symbol",6) == 0 || strncasecmp(stylestring,"label",5) == 0) { msOGRUpdateStyleFromString(map, layer, c, stylestring); } else { resetClassStyle(c); } return MS_SUCCESS; } return MS_FAILURE; } /* Returns the number of inline feature of a layer */ int msLayerGetNumFeatures(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerGetNumFeatures(layer); } void msLayerSetProcessingKey( layerObj *layer, const char *key, const char *value) { int len = strlen(key); int i; char *directive = NULL; if( value != NULL ) { directive = (char *) msSmallMalloc(strlen(key)+strlen(value)+2); sprintf( directive, "%s=%s", key, value ); } for( i = 0; i < layer->numprocessing; i++ ) { if( strncasecmp( key, layer->processing[i], len ) == 0 && layer->processing[i][len] == '=' ) { free( layer->processing[i] ); /* ** Either replace the existing entry with a new one or ** clear the entry. */ if( directive != NULL ) layer->processing[i] = directive; else { layer->processing[i] = layer->processing[layer->numprocessing-1]; layer->processing[layer->numprocessing-1] = NULL; layer->numprocessing--; } return; } } /* otherwise add the directive at the end. */ if( directive != NULL ) { msLayerAddProcessing( layer, directive ); free( directive ); } } void msLayerAddProcessing( layerObj *layer, const char *directive ) { layer->numprocessing++; if( layer->numprocessing == 1 ) layer->processing = (char **) msSmallMalloc(2*sizeof(char *)); else layer->processing = (char **) msSmallRealloc(layer->processing, sizeof(char*) * (layer->numprocessing+1) ); layer->processing[layer->numprocessing-1] = msStrdup(directive); layer->processing[layer->numprocessing] = NULL; } char *msLayerGetProcessing( layerObj *layer, int proc_index) { if (proc_index < 0 || proc_index >= layer->numprocessing) { msSetError(MS_CHILDERR, "Invalid processing index.", "msLayerGetProcessing()"); return NULL; } else { return layer->processing[proc_index]; } } char *msLayerGetProcessingKey( layerObj *layer, const char *key ) { int i, len = strlen(key); for( i = 0; i < layer->numprocessing; i++ ) { if( strncasecmp(layer->processing[i],key,len) == 0 && layer->processing[i][len] == '=' ) return layer->processing[i] + len + 1; } return NULL; } /************************************************************************/ /* msLayerGetMaxFeaturesToDraw */ /* */ /* Check to see if maxfeaturestodraw is set as a metadata or an */ /* output format option. Used for vector layers to limit the */ /* number of fatures rendered. */ /************************************************************************/ int msLayerGetMaxFeaturesToDraw(layerObj *layer, outputFormatObj *format) { int nMaxFeatures = -1; const char *pszTmp = NULL; if (layer) { nMaxFeatures = layer->maxfeatures; pszTmp = msLookupHashTable(&layer->metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); else { pszTmp = msLookupHashTable(&layer->map->web.metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); } } if(format) { if (nMaxFeatures < 0) nMaxFeatures = atoi(msGetOutputFormatOption( format, "maxfeaturestodraw", "-1")); } return nMaxFeatures; } int msLayerClearProcessing( layerObj *layer ) { if (layer->numprocessing > 0) { msFreeCharArray( layer->processing, layer->numprocessing ); layer->processing = NULL; layer->numprocessing = 0; } return layer->numprocessing; } int makeTimeFilter(layerObj *lp, const char *timestring, const char *timefield, const int addtimebacktics) { char **atimes, **tokens = NULL; int numtimes,i, ntmp = 0; char *pszBuffer = NULL; int bOnlyExistingFilter = 0; if (!lp || !timestring || !timefield) return MS_FALSE; /* parse the time string. We support dicrete times (eg 2004-09-21), */ /* multiple times (2004-09-21, 2004-09-22, ...) */ /* and range(s) (2004-09-21/2004-09-25, 2004-09-27/2004-09-29) */ if (strstr(timestring, ",") == NULL && strstr(timestring, "/") == NULL) { /* discrete time */ /* if(lp->filteritem) free(lp->filteritem); lp->filteritem = msStrdup(timefield); if (&lp->filter) freeExpression(&lp->filter); */ if (&lp->filter) { /* if the filter is set and it's a sting type, concatenate it with the time. If not just free it */ if (lp->filter.string && lp->filter.type == MS_STRING) { pszBuffer = msStringConcatenate(pszBuffer, "(("); pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); } else { freeExpression(&lp->filter); } } pszBuffer = msStringConcatenate(pszBuffer, "("); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " = "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, (char *)timestring); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, ")"); /* if there was a filter, It was concatenate with an And ans should be closed*/ if(&lp->filter && lp->filter.string && lp->filter.type == MS_STRING) { pszBuffer = msStringConcatenate(pszBuffer, ")"); } loadExpressionString(&lp->filter, pszBuffer); if (pszBuffer) msFree(pszBuffer); return MS_TRUE; } atimes = msStringSplit(timestring, ',', &numtimes); if (atimes == NULL || numtimes < 1) return MS_FALSE; if (numtimes >= 1) { if (&lp->filter && lp->filter.string && lp->filter.type == MS_STRING) { pszBuffer = msStringConcatenate(pszBuffer, "(("); pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); /*this flag is used to indicate that the buffer contains only the existing filter. It is set to 0 when time filter parts are added to the buffer */ bOnlyExistingFilter = 1; } else freeExpression(&lp->filter); /* check to see if we have ranges by parsing the first entry */ tokens = msStringSplit(atimes[0], '/', &ntmp); if (ntmp == 2) { /* ranges */ msFreeCharArray(tokens, ntmp); for (i=0; i 0 && bOnlyExistingFilter == 0) pszBuffer = msStringConcatenate(pszBuffer, " OR "); else pszBuffer = msStringConcatenate(pszBuffer, "("); bOnlyExistingFilter = 0; pszBuffer = msStringConcatenate(pszBuffer, "("); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " >= "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, tokens[0]); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, " AND "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " <= "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, tokens[1]); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, ")"); } msFreeCharArray(tokens, ntmp); } if (pszBuffer && strlen(pszBuffer) > 0 && bOnlyExistingFilter == 0) pszBuffer = msStringConcatenate(pszBuffer, ")"); } else if (ntmp == 1) { /* multiple times */ msFreeCharArray(tokens, ntmp); pszBuffer = msStringConcatenate(pszBuffer, "("); for (i=0; i 0) pszBuffer = msStringConcatenate(pszBuffer, " OR "); pszBuffer = msStringConcatenate(pszBuffer, "("); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " = "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, atimes[i]); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, ")"); } pszBuffer = msStringConcatenate(pszBuffer, ")"); } else { msFreeCharArray(atimes, numtimes); return MS_FALSE; } msFreeCharArray(atimes, numtimes); /* load the string to the filter */ if (pszBuffer && strlen(pszBuffer) > 0) { if(&lp->filter && lp->filter.string && lp->filter.type == MS_STRING) pszBuffer = msStringConcatenate(pszBuffer, ")"); /* if(lp->filteritem) free(lp->filteritem); lp->filteritem = msStrdup(timefield); */ loadExpressionString(&lp->filter, pszBuffer); if (pszBuffer) msFree(pszBuffer); } return MS_TRUE; } return MS_FALSE; } /** set the filter parameter for a time filter **/ int msLayerSetTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { if ( ! lp->vtable) { int rv = msInitializeVirtualTable(lp); if (rv != MS_SUCCESS) return rv; } return lp->vtable->LayerSetTimeFilter(lp, timestring, timefield); } int msLayerMakeBackticsTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { return makeTimeFilter(lp, timestring, timefield, MS_TRUE); } int msLayerMakePlainTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { return makeTimeFilter(lp, timestring, timefield, MS_FALSE); } /* * Dummies / default actions for layers */ int LayerDefaultInitItemInfo(layerObj *layer) { return MS_SUCCESS; } void LayerDefaultFreeItemInfo(layerObj *layer) { return; } int LayerDefaultOpen(layerObj *layer) { return MS_FAILURE; } int LayerDefaultIsOpen(layerObj *layer) { return MS_FALSE; } int LayerDefaultWhichShapes(layerObj *layer, rectObj rect, int isQuery) { return MS_SUCCESS; } int LayerDefaultNextShape(layerObj *layer, shapeObj *shape) { return MS_FAILURE; } int LayerDefaultGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { return MS_FAILURE; } int LayerDefaultClose(layerObj *layer) { return MS_SUCCESS; } int LayerDefaultGetItems(layerObj *layer) { return MS_SUCCESS; /* returning no items is legit */ } int msLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { #ifdef USE_OGR return FLTLayerApplyCondSQLFilterToLayer(psNode, map, iLayerIndex); #else return MS_FAILURE; #endif } int msLayerSupportsPaging(layerObj *layer) { if (layer && ((layer->connectiontype == MS_ORACLESPATIAL) || (layer->connectiontype == MS_POSTGIS)) ) return MS_TRUE; return MS_FALSE; } int msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { #ifdef USE_OGR return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex); #else return MS_FAILURE; #endif } int msLayerGetPaging(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to initialize virtual table", "msLayerGetPaging()"); return MS_FAILURE; } } return layer->vtable->LayerGetPaging(layer); } void msLayerEnablePaging(layerObj *layer, int value) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to initialize virtual table", "msLayerEnablePaging()"); return; } } return layer->vtable->LayerEnablePaging(layer, value); } int LayerDefaultGetExtent(layerObj *layer, rectObj *extent) { return MS_FAILURE; } int LayerDefaultGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj *shape) { msSetError(MS_MISCERR, "'STYLEITEM AUTO' not supported for this data source.", "msLayerGetAutoStyle()"); return MS_FAILURE; } int LayerDefaultCloseConnection(layerObj *layer) { return MS_SUCCESS; } int LayerDefaultCreateItems(layerObj *layer, const int nt) { if (nt > 0) { layer->items = (char **)calloc(nt, sizeof(char *)); /* should be more than enough space */ MS_CHECK_ALLOC(layer->items, sizeof(char *), MS_FAILURE); layer->numitems = 0; } return MS_SUCCESS; } int LayerDefaultGetNumFeatures(layerObj *layer) { msSetError(MS_SHPERR, "Not an inline layer", "msLayerGetNumFeatures()"); return MS_FAILURE; } int LayerDefaultAutoProjection(layerObj *layer, projectionObj* projection) { msSetError(MS_MISCERR, "This data driver does not implement AUTO projection support", "LayerDefaultAutoProjection()"); return MS_FAILURE; } int LayerDefaultSupportsCommonFilters(layerObj *layer) { return MS_FALSE; } int msLayerDefaultGetPaging(layerObj *layer) { return MS_FALSE; } void msLayerDefaultEnablePaging(layerObj *layer, int value) { return; } /************************************************************************/ /* LayerDefaultEscapeSQLParam */ /* */ /* Default function used to escape strings and avoid sql */ /* injection. Specific drivers should redefine if an escaping */ /* function is available in the driver. */ /************************************************************************/ char *LayerDefaultEscapeSQLParam(layerObj *layer, const char* pszString) { char *pszEscapedStr=NULL; if (pszString) { int nSrcLen; char c; int i=0, j=0; nSrcLen = (int)strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 2 * nSrcLen + 1); for(i = 0, j = 0; i < nSrcLen; i++) { c = pszString[i]; if (c == '\'') { pszEscapedStr[j++] = '\''; pszEscapedStr[j++] = '\''; } else if (c == '\\') { pszEscapedStr[j++] = '\\'; pszEscapedStr[j++] = '\\'; } else pszEscapedStr[j++] = c; } pszEscapedStr[j] = 0; } return pszEscapedStr; } /************************************************************************/ /* LayerDefaultEscapePropertyName */ /* */ /* Return the property name in a properly escaped and quoted form. */ /************************************************************************/ char *LayerDefaultEscapePropertyName(layerObj *layer, const char* pszString) { char* pszEscapedStr=NULL; int i, j = 0; if (layer && pszString && strlen(pszString) > 0) { int nLength = strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 1 + 2 * nLength + 1 + 1); pszEscapedStr[j++] = '"'; for (i=0; iconnectiontype = connectiontype; /* For internal types, library_str is ignored */ if (connectiontype == MS_PLUGIN) { int rv; msFree(layer->plugin_library); msFree(layer->plugin_library_original); layer->plugin_library_original = msStrdup(library_str); rv = msBuildPluginLibraryPath(&layer->plugin_library, layer->plugin_library_original, layer->map); if (rv != MS_SUCCESS) { return rv; } } return msInitializeVirtualTable(layer) ; } static int populateVirtualTable(layerVTableObj *vtable) { assert(vtable != NULL); vtable->LayerSupportsCommonFilters = LayerDefaultSupportsCommonFilters; vtable->LayerInitItemInfo = LayerDefaultInitItemInfo; vtable->LayerFreeItemInfo = LayerDefaultFreeItemInfo; vtable->LayerOpen = LayerDefaultOpen; vtable->LayerIsOpen = LayerDefaultIsOpen; vtable->LayerWhichShapes = LayerDefaultWhichShapes; vtable->LayerNextShape = LayerDefaultNextShape; /* vtable->LayerResultsGetShape = LayerDefaultResultsGetShape; */ vtable->LayerGetShape = LayerDefaultGetShape; vtable->LayerClose = LayerDefaultClose; vtable->LayerGetItems = LayerDefaultGetItems; vtable->LayerGetExtent = LayerDefaultGetExtent; vtable->LayerGetAutoStyle = LayerDefaultGetAutoStyle; vtable->LayerCloseConnection = LayerDefaultCloseConnection; vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; vtable->LayerApplyFilterToLayer = msLayerApplyPlainFilterToLayer; vtable->LayerCreateItems = LayerDefaultCreateItems; vtable->LayerGetNumFeatures = LayerDefaultGetNumFeatures; vtable->LayerGetAutoProjection = LayerDefaultAutoProjection; vtable->LayerEscapeSQLParam = LayerDefaultEscapeSQLParam; vtable->LayerEscapePropertyName = LayerDefaultEscapePropertyName; vtable->LayerEnablePaging = msLayerDefaultEnablePaging; vtable->LayerGetPaging = msLayerDefaultGetPaging; return MS_SUCCESS; } static int createVirtualTable(layerVTableObj **vtable) { *vtable = malloc(sizeof(**vtable)); MS_CHECK_ALLOC(*vtable, sizeof(**vtable), MS_FAILURE); return populateVirtualTable(*vtable); } static int destroyVirtualTable(layerVTableObj **vtable) { memset(*vtable, 0, sizeof(**vtable)); msFree(*vtable); *vtable = NULL; return MS_SUCCESS; } int msInitializeVirtualTable(layerObj *layer) { if (layer->vtable) { destroyVirtualTable(&layer->vtable); } createVirtualTable(&layer->vtable); if(layer->features && layer->connectiontype != MS_GRATICULE ) layer->connectiontype = MS_INLINE; if(layer->tileindex && layer->connectiontype == MS_SHAPEFILE) layer->connectiontype = MS_TILED_SHAPEFILE; if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS) layer->connectiontype = MS_RASTER; switch(layer->connectiontype) { case(MS_INLINE): return(msINLINELayerInitializeVirtualTable(layer)); break; case(MS_SHAPEFILE): return(msSHPLayerInitializeVirtualTable(layer)); break; case(MS_TILED_SHAPEFILE): return(msTiledSHPLayerInitializeVirtualTable(layer)); break; case(MS_SDE): return(msSDELayerInitializeVirtualTable(layer)); break; case(MS_OGR): return(msOGRLayerInitializeVirtualTable(layer)); break; case(MS_POSTGIS): return(msPostGISLayerInitializeVirtualTable(layer)); break; case(MS_WMS): /* WMS should be treated as a raster layer */ return(msRASTERLayerInitializeVirtualTable(layer)); break; case(MS_ORACLESPATIAL): return(msOracleSpatialLayerInitializeVirtualTable(layer)); break; case(MS_WFS): return(msWFSLayerInitializeVirtualTable(layer)); break; case(MS_GRATICULE): return(msGraticuleLayerInitializeVirtualTable(layer)); break; case(MS_RASTER): return(msRASTERLayerInitializeVirtualTable(layer)); break; case(MS_PLUGIN): return(msPluginLayerInitializeVirtualTable(layer)); break; case(MS_UNION): return(msUnionLayerInitializeVirtualTable(layer)); break; case(MS_UVRASTER): return(msUVRASTERLayerInitializeVirtualTable(layer)); break; case(MS_CONTOUR): return(msContourLayerInitializeVirtualTable(layer)); break; default: msSetError(MS_MISCERR, "Unknown connectiontype, it was %d", "msInitializeVirtualTable()", layer->connectiontype); return MS_FAILURE; break; } /* not reached */ return MS_FAILURE; } /* * INLINE: Virtual table functions */ typedef struct { rectObj searchrect; int is_relative; /* relative coordinates? */ } msINLINELayerInfo; int msINLINELayerIsOpen(layerObj *layer) { if (layer->currentfeature) return(MS_TRUE); else return(MS_FALSE); } msINLINELayerInfo *msINLINECreateLayerInfo(void) { msINLINELayerInfo *layerinfo = msSmallMalloc(sizeof(msINLINELayerInfo)); layerinfo->searchrect.minx = -1.0; layerinfo->searchrect.miny = -1.0; layerinfo->searchrect.maxx = -1.0; layerinfo->searchrect.maxy = -1.0; layerinfo->is_relative = MS_FALSE; return layerinfo; } int msINLINELayerOpen(layerObj *layer) { msINLINELayerInfo *layerinfo; if (layer->layerinfo) { if (layer->debug) { msDebug("msINLINELayerOpen: Layer is already open!\n"); } return MS_SUCCESS; /* already open */ } /* ** Initialize the layerinfo **/ layerinfo = msINLINECreateLayerInfo(); layer->currentfeature = layer->features; /* point to the begining of the feature list */ layer->layerinfo = (void*)layerinfo; return(MS_SUCCESS); } int msINLINELayerClose(layerObj *layer) { if (layer->layerinfo) { free(layer->layerinfo); layer->layerinfo = NULL; } return MS_SUCCESS; } int msINLINELayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msINLINELayerInfo *layerinfo = NULL; layerinfo = (msINLINELayerInfo*) layer->layerinfo; layerinfo->searchrect = rect; layerinfo->is_relative = (layer->transform != MS_FALSE && layer->transform != MS_TRUE); return MS_SUCCESS; } /* Author: Cristoph Spoerri and Sean Gillies */ int msINLINELayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { int i=0; featureListNodeObjPtr current; int shapeindex = record->shapeindex; /* only index necessary */ current = layer->features; while (current!=NULL && i!=shapeindex) { i++; current = current->next; } if (current == NULL) { msSetError(MS_SHPERR, "No inline feature with this index.", "msINLINELayerGetShape()"); return MS_FAILURE; } if (msCopyShape(&(current->shape), shape) != MS_SUCCESS) { msSetError(MS_SHPERR, "Cannot retrieve inline shape. There some problem with the shape", "msINLINELayerGetShape()"); return MS_FAILURE; } /* check for the expected size of the values array */ if (layer->numitems > shape->numvalues) { shape->values = (char **)msSmallRealloc(shape->values, sizeof(char *)*(layer->numitems)); for (i = shape->numvalues; i < layer->numitems; i++) shape->values[i] = msStrdup(""); } msComputeBounds(shape); return MS_SUCCESS; } int msINLINELayerNextShape(layerObj *layer, shapeObj *shape) { msINLINELayerInfo *layerinfo = NULL; shapeObj * s; layerinfo = (msINLINELayerInfo*) layer->layerinfo; while (1) { if( ! (layer->currentfeature)) { /* out of features */ return(MS_DONE); } s = &(layer->currentfeature->shape); layer->currentfeature = layer->currentfeature->next; msComputeBounds(s); if (layerinfo->is_relative || msRectOverlap(&s->bounds, &layerinfo->searchrect)) { msCopyShape(s, shape); /* check for the expected size of the values array */ if (layer->numitems > shape->numvalues) { int i; shape->values = (char **)msSmallRealloc(shape->values, sizeof(char *)*(layer->numitems)); for (i = shape->numvalues; i < layer->numitems; i++) shape->values[i] = msStrdup(""); } break; } } return(MS_SUCCESS); } int msINLINELayerGetNumFeatures(layerObj *layer) { int i = 0; featureListNodeObjPtr current; current = layer->features; while (current != NULL) { i++; current = current->next; } return i; } /* Returns an escaped string */ char *msLayerEscapeSQLParam(layerObj *layer, const char*pszString) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return ""; } return layer->vtable->LayerEscapeSQLParam(layer, pszString); } char *msLayerEscapePropertyName(layerObj *layer, const char*pszString) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return ""; } return layer->vtable->LayerEscapePropertyName(layer, pszString); } int msINLINELayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); /* layer->vtable->LayerInitItemInfo, use default */ /* layer->vtable->LayerFreeItemInfo, use default */ layer->vtable->LayerOpen = msINLINELayerOpen; layer->vtable->LayerIsOpen = msINLINELayerIsOpen; layer->vtable->LayerWhichShapes = msINLINELayerWhichShapes; layer->vtable->LayerNextShape = msINLINELayerNextShape; layer->vtable->LayerGetShape = msINLINELayerGetShape; layer->vtable->LayerClose = msINLINELayerClose; /* layer->vtable->LayerGetItems, use default */ /* * Original code contained following * TODO: need to compute extents */ /* layer->vtable->LayerGetExtent, use default */ /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCreateItems, use default */ layer->vtable->LayerGetNumFeatures = msINLINELayerGetNumFeatures; /*layer->vtable->LayerEscapeSQLParam, use default*/ /*layer->vtable->LayerEscapePropertyName, use default*/ /* layer->vtable->LayerEnablePaging, use default */ /* layer->vtable->LayerGetPaging, use default */ return MS_SUCCESS; } mapserver-6.4.1/renderers/0000755002461700001440000000000012261257215015305 5ustar tbonfortusersmapserver-6.4.1/renderers/agg/0000755002461700001440000000000012261257215016043 5ustar tbonfortusersmapserver-6.4.1/renderers/agg/LICENSE0000644002461700001440000000067012261257215017053 0ustar tbonfortusersThe Anti-Grain Geometry Project A high quality rendering engine for C++ http://antigrain.com Anti-Grain Geometry - Version 2.4 Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. mapserver-6.4.1/renderers/agg/authors0000644002461700001440000000012512261257215017451 0ustar tbonfortusersAnti-Grain Geometry - Version 2.4 Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) mapserver-6.4.1/renderers/agg/src/0000755002461700001440000000000012261257215016632 5ustar tbonfortusersmapserver-6.4.1/renderers/agg/src/agg_svg_parser.cpp0000644002461700001440000006557712261257215022353 0ustar tbonfortusers//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG parser. // //---------------------------------------------------------------------------- #include #include #include #include "agg_svg_parser.h" #include "expat.h" namespace mapserver { namespace svg { struct named_color { char name[22]; int8u r, g, b, a; }; named_color colors[] = { { "aliceblue",240,248,255, 255 }, { "antiquewhite",250,235,215, 255 }, { "aqua",0,255,255, 255 }, { "aquamarine",127,255,212, 255 }, { "azure",240,255,255, 255 }, { "beige",245,245,220, 255 }, { "bisque",255,228,196, 255 }, { "black",0,0,0, 255 }, { "blanchedalmond",255,235,205, 255 }, { "blue",0,0,255, 255 }, { "blueviolet",138,43,226, 255 }, { "brown",165,42,42, 255 }, { "burlywood",222,184,135, 255 }, { "cadetblue",95,158,160, 255 }, { "chartreuse",127,255,0, 255 }, { "chocolate",210,105,30, 255 }, { "coral",255,127,80, 255 }, { "cornflowerblue",100,149,237, 255 }, { "cornsilk",255,248,220, 255 }, { "crimson",220,20,60, 255 }, { "cyan",0,255,255, 255 }, { "darkblue",0,0,139, 255 }, { "darkcyan",0,139,139, 255 }, { "darkgoldenrod",184,134,11, 255 }, { "darkgray",169,169,169, 255 }, { "darkgreen",0,100,0, 255 }, { "darkgrey",169,169,169, 255 }, { "darkkhaki",189,183,107, 255 }, { "darkmagenta",139,0,139, 255 }, { "darkolivegreen",85,107,47, 255 }, { "darkorange",255,140,0, 255 }, { "darkorchid",153,50,204, 255 }, { "darkred",139,0,0, 255 }, { "darksalmon",233,150,122, 255 }, { "darkseagreen",143,188,143, 255 }, { "darkslateblue",72,61,139, 255 }, { "darkslategray",47,79,79, 255 }, { "darkslategrey",47,79,79, 255 }, { "darkturquoise",0,206,209, 255 }, { "darkviolet",148,0,211, 255 }, { "deeppink",255,20,147, 255 }, { "deepskyblue",0,191,255, 255 }, { "dimgray",105,105,105, 255 }, { "dimgrey",105,105,105, 255 }, { "dodgerblue",30,144,255, 255 }, { "firebrick",178,34,34, 255 }, { "floralwhite",255,250,240, 255 }, { "forestgreen",34,139,34, 255 }, { "fuchsia",255,0,255, 255 }, { "gainsboro",220,220,220, 255 }, { "ghostwhite",248,248,255, 255 }, { "gold",255,215,0, 255 }, { "goldenrod",218,165,32, 255 }, { "gray",128,128,128, 255 }, { "green",0,128,0, 255 }, { "greenyellow",173,255,47, 255 }, { "grey",128,128,128, 255 }, { "honeydew",240,255,240, 255 }, { "hotpink",255,105,180, 255 }, { "indianred",205,92,92, 255 }, { "indigo",75,0,130, 255 }, { "ivory",255,255,240, 255 }, { "khaki",240,230,140, 255 }, { "lavender",230,230,250, 255 }, { "lavenderblush",255,240,245, 255 }, { "lawngreen",124,252,0, 255 }, { "lemonchiffon",255,250,205, 255 }, { "lightblue",173,216,230, 255 }, { "lightcoral",240,128,128, 255 }, { "lightcyan",224,255,255, 255 }, { "lightgoldenrodyellow",250,250,210, 255 }, { "lightgray",211,211,211, 255 }, { "lightgreen",144,238,144, 255 }, { "lightgrey",211,211,211, 255 }, { "lightpink",255,182,193, 255 }, { "lightsalmon",255,160,122, 255 }, { "lightseagreen",32,178,170, 255 }, { "lightskyblue",135,206,250, 255 }, { "lightslategray",119,136,153, 255 }, { "lightslategrey",119,136,153, 255 }, { "lightsteelblue",176,196,222, 255 }, { "lightyellow",255,255,224, 255 }, { "lime",0,255,0, 255 }, { "limegreen",50,205,50, 255 }, { "linen",250,240,230, 255 }, { "magenta",255,0,255, 255 }, { "maroon",128,0,0, 255 }, { "mediumaquamarine",102,205,170, 255 }, { "mediumblue",0,0,205, 255 }, { "mediumorchid",186,85,211, 255 }, { "mediumpurple",147,112,219, 255 }, { "mediumseagreen",60,179,113, 255 }, { "mediumslateblue",123,104,238, 255 }, { "mediumspringgreen",0,250,154, 255 }, { "mediumturquoise",72,209,204, 255 }, { "mediumvioletred",199,21,133, 255 }, { "midnightblue",25,25,112, 255 }, { "mintcream",245,255,250, 255 }, { "mistyrose",255,228,225, 255 }, { "moccasin",255,228,181, 255 }, { "navajowhite",255,222,173, 255 }, { "navy",0,0,128, 255 }, { "oldlace",253,245,230, 255 }, { "olive",128,128,0, 255 }, { "olivedrab",107,142,35, 255 }, { "orange",255,165,0, 255 }, { "orangered",255,69,0, 255 }, { "orchid",218,112,214, 255 }, { "palegoldenrod",238,232,170, 255 }, { "palegreen",152,251,152, 255 }, { "paleturquoise",175,238,238, 255 }, { "palevioletred",219,112,147, 255 }, { "papayawhip",255,239,213, 255 }, { "peachpuff",255,218,185, 255 }, { "peru",205,133,63, 255 }, { "pink",255,192,203, 255 }, { "plum",221,160,221, 255 }, { "powderblue",176,224,230, 255 }, { "purple",128,0,128, 255 }, { "red",255,0,0, 255 }, { "rosybrown",188,143,143, 255 }, { "royalblue",65,105,225, 255 }, { "saddlebrown",139,69,19, 255 }, { "salmon",250,128,114, 255 }, { "sandybrown",244,164,96, 255 }, { "seagreen",46,139,87, 255 }, { "seashell",255,245,238, 255 }, { "sienna",160,82,45, 255 }, { "silver",192,192,192, 255 }, { "skyblue",135,206,235, 255 }, { "slateblue",106,90,205, 255 }, { "slategray",112,128,144, 255 }, { "slategrey",112,128,144, 255 }, { "snow",255,250,250, 255 }, { "springgreen",0,255,127, 255 }, { "steelblue",70,130,180, 255 }, { "tan",210,180,140, 255 }, { "teal",0,128,128, 255 }, { "thistle",216,191,216, 255 }, { "tomato",255,99,71, 255 }, { "turquoise",64,224,208, 255 }, { "violet",238,130,238, 255 }, { "wheat",245,222,179, 255 }, { "white",255,255,255, 255 }, { "whitesmoke",245,245,245, 255 }, { "yellow",255,255,0, 255 }, { "yellowgreen",154,205,50, 255 }, { "zzzzzzzzzzz",0,0,0, 0 } }; //------------------------------------------------------------------------ parser::~parser() { delete [] m_attr_value; delete [] m_attr_name; delete [] m_buf; delete [] m_title; } //------------------------------------------------------------------------ parser::parser(path_renderer& path) : m_path(path), m_tokenizer(), m_buf(new char[buf_size]), m_title(new char[256]), m_title_len(0), m_title_flag(false), m_path_flag(false), m_attr_name(new char[128]), m_attr_value(new char[1024]), m_attr_name_len(127), m_attr_value_len(1023) { m_title[0] = 0; } //------------------------------------------------------------------------ void parser::parse(const char* fname) { char msg[1024]; XML_Parser p = XML_ParserCreate(NULL); if(p == 0) { throw exception("Couldn't allocate memory for parser"); } XML_SetUserData(p, this); XML_SetElementHandler(p, start_element, end_element); XML_SetCharacterDataHandler(p, content); FILE* fd = fopen(fname, "r"); if(fd == 0) { sprintf(msg, "Couldn't open file %s", fname); throw exception(msg); } bool done = false; do { size_t len = fread(m_buf, 1, buf_size, fd); done = len < buf_size; if(!XML_Parse(p, m_buf, len, done)) { sprintf(msg, "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(p)), (int)XML_GetCurrentLineNumber(p)); throw exception(msg); } } while(!done); fclose(fd); XML_ParserFree(p); char* ts = m_title; while(*ts) { if(*ts < ' ') *ts = ' '; ++ts; } } //------------------------------------------------------------------------ void parser::start_element(void* data, const char* el, const char** attr) { parser& self = *(parser*)data; if(strcmp(el, "title") == 0) { self.m_title_flag = true; } else if(strcmp(el, "g") == 0) { self.m_path.push_attr(); self.parse_attr(attr); } else if(strcmp(el, "path") == 0) { if(self.m_path_flag) { throw exception("start_element: Nested path"); } self.m_path.begin_path(); self.parse_path(attr); self.m_path.end_path(); self.m_path_flag = true; } else if(strcmp(el, "rect") == 0) { self.parse_rect(attr); } else if(strcmp(el, "line") == 0) { self.parse_line(attr); } else if(strcmp(el, "polyline") == 0) { self.parse_poly(attr, false); } else if(strcmp(el, "polygon") == 0) { self.parse_poly(attr, true); } //else //if(strcmp(el, "") == 0) //{ //} // . . . } //------------------------------------------------------------------------ void parser::end_element(void* data, const char* el) { parser& self = *(parser*)data; if(strcmp(el, "title") == 0) { self.m_title_flag = false; } else if(strcmp(el, "g") == 0) { self.m_path.pop_attr(); } else if(strcmp(el, "path") == 0) { self.m_path_flag = false; } //else //if(strcmp(el, "") == 0) //{ //} // . . . } //------------------------------------------------------------------------ void parser::content(void* data, const char* s, int len) { parser& self = *(parser*)data; // m_title_flag signals that the tag is being parsed now. // The following code concatenates the pieces of content of the <title> tag. if(self.m_title_flag) { if(len + self.m_title_len > 255) len = 255 - self.m_title_len; if(len > 0) { memcpy(self.m_title + self.m_title_len, s, len); self.m_title_len += len; self.m_title[self.m_title_len] = 0; } } } //------------------------------------------------------------------------ void parser::parse_attr(const char** attr) { int i; for(i = 0; attr[i]; i += 2) { if(strcmp(attr[i], "style") == 0) { parse_style(attr[i + 1]); } else { parse_attr(attr[i], attr[i + 1]); } } } //------------------------------------------------------------- void parser::parse_path(const char** attr) { int i; for(i = 0; attr[i]; i += 2) { // The <path> tag can consist of the path itself ("d=") // as well as of other parameters like "style=", "transform=", etc. // In the last case we simply rely on the function of parsing // attributes (see 'else' branch). if(strcmp(attr[i], "d") == 0) { m_tokenizer.set_path_str(attr[i + 1]); m_path.parse_path(m_tokenizer); } else { // Create a temporary single pair "name-value" in order // to avoid multiple calls for the same attribute. const char* tmp[4]; tmp[0] = attr[i]; tmp[1] = attr[i + 1]; tmp[2] = 0; tmp[3] = 0; parse_attr(tmp); } } } //------------------------------------------------------------- int cmp_color(const void* p1, const void* p2) { return strcmp(((named_color*)p1)->name, ((named_color*)p2)->name); } //------------------------------------------------------------- rgba8 parse_color(const char* str) { while(*str == ' ') ++str; unsigned c = 0; if(*str == '#') { sscanf(str + 1, "%x", &c); return rgb8_packed(c); } else { named_color c; unsigned len = strlen(str); if(len > sizeof(c.name) - 1) { throw exception("parse_color: Invalid color name '%s'", str); } strcpy(c.name, str); const void* p = bsearch(&c, colors, sizeof(colors) / sizeof(colors[0]), sizeof(colors[0]), cmp_color); if(p == 0) { throw exception("parse_color: Invalid color name '%s'", str); } const named_color* pc = (const named_color*)p; return rgba8(pc->r, pc->g, pc->b, pc->a); } } double parse_double(const char* str) { while(*str == ' ') ++str; return atof(str); } //------------------------------------------------------------- bool parser::parse_attr(const char* name, const char* value) { if(strcmp(name, "style") == 0) { parse_style(value); } else if(strcmp(name, "fill") == 0) { if(strcmp(value, "none") == 0) { m_path.fill_none(); } else { m_path.fill(parse_color(value)); } } else if(strcmp(name, "fill-opacity") == 0) { m_path.fill_opacity(parse_double(value)); } else if(strcmp(name, "stroke") == 0) { if(strcmp(value, "none") == 0) { m_path.stroke_none(); } else { m_path.stroke(parse_color(value)); } } else if(strcmp(name, "stroke-width") == 0) { m_path.stroke_width(parse_double(value)); } else if(strcmp(name, "stroke-linecap") == 0) { if(strcmp(value, "butt") == 0) m_path.line_cap(butt_cap); else if(strcmp(value, "round") == 0) m_path.line_cap(round_cap); else if(strcmp(value, "square") == 0) m_path.line_cap(square_cap); } else if(strcmp(name, "stroke-linejoin") == 0) { if(strcmp(value, "miter") == 0) m_path.line_join(miter_join); else if(strcmp(value, "round") == 0) m_path.line_join(round_join); else if(strcmp(value, "bevel") == 0) m_path.line_join(bevel_join); } else if(strcmp(name, "stroke-miterlimit") == 0) { m_path.miter_limit(parse_double(value)); } else if(strcmp(name, "stroke-opacity") == 0) { m_path.stroke_opacity(parse_double(value)); } else if(strcmp(name, "transform") == 0) { parse_transform(value); } //else //if(strcmp(el, "<OTHER_ATTRIBUTES>") == 0) //{ //} // . . . else { return false; } return true; } //------------------------------------------------------------- void parser::copy_name(const char* start, const char* end) { unsigned len = unsigned(end - start); if(m_attr_name_len == 0 || len > m_attr_name_len) { delete [] m_attr_name; m_attr_name = new char[len + 1]; m_attr_name_len = len; } if(len) memcpy(m_attr_name, start, len); m_attr_name[len] = 0; } //------------------------------------------------------------- void parser::copy_value(const char* start, const char* end) { unsigned len = unsigned(end - start); if(m_attr_value_len == 0 || len > m_attr_value_len) { delete [] m_attr_value; m_attr_value = new char[len + 1]; m_attr_value_len = len; } if(len) memcpy(m_attr_value, start, len); m_attr_value[len] = 0; } //------------------------------------------------------------- bool parser::parse_name_value(const char* nv_start, const char* nv_end) { const char* str = nv_start; while(str < nv_end && *str != ':') ++str; const char* val = str; // Right Trim while(str > nv_start && (*str == ':' || isspace(*str))) --str; ++str; copy_name(nv_start, str); while(val < nv_end && (*val == ':' || isspace(*val))) ++val; copy_value(val, nv_end); return parse_attr(m_attr_name, m_attr_value); } //------------------------------------------------------------- void parser::parse_style(const char* str) { while(*str) { // Left Trim while(*str && isspace(*str)) ++str; const char* nv_start = str; while(*str && *str != ';') ++str; const char* nv_end = str; // Right Trim while(nv_end > nv_start && (*nv_end == ';' || isspace(*nv_end))) --nv_end; ++nv_end; parse_name_value(nv_start, nv_end); if(*str) ++str; } } //------------------------------------------------------------- void parser::parse_rect(const char** attr) { int i; double x = 0.0; double y = 0.0; double w = 0.0; double h = 0.0; m_path.begin_path(); for(i = 0; attr[i]; i += 2) { if(!parse_attr(attr[i], attr[i + 1])) { if(strcmp(attr[i], "x") == 0) x = parse_double(attr[i + 1]); if(strcmp(attr[i], "y") == 0) y = parse_double(attr[i + 1]); if(strcmp(attr[i], "width") == 0) w = parse_double(attr[i + 1]); if(strcmp(attr[i], "height") == 0) h = parse_double(attr[i + 1]); // rx - to be implemented // ry - to be implemented } } if(w != 0.0 && h != 0.0) { if(w < 0.0) throw exception("parse_rect: Invalid width: %f", w); if(h < 0.0) throw exception("parse_rect: Invalid height: %f", h); m_path.move_to(x, y); m_path.line_to(x + w, y); m_path.line_to(x + w, y + h); m_path.line_to(x, y + h); m_path.close_subpath(); } m_path.end_path(); } //------------------------------------------------------------- void parser::parse_line(const char** attr) { int i; double x1 = 0.0; double y1 = 0.0; double x2 = 0.0; double y2 = 0.0; m_path.begin_path(); for(i = 0; attr[i]; i += 2) { if(!parse_attr(attr[i], attr[i + 1])) { if(strcmp(attr[i], "x1") == 0) x1 = parse_double(attr[i + 1]); if(strcmp(attr[i], "y1") == 0) y1 = parse_double(attr[i + 1]); if(strcmp(attr[i], "x2") == 0) x2 = parse_double(attr[i + 1]); if(strcmp(attr[i], "y2") == 0) y2 = parse_double(attr[i + 1]); } } m_path.move_to(x1, y1); m_path.line_to(x2, y2); m_path.end_path(); } //------------------------------------------------------------- void parser::parse_poly(const char** attr, bool close_flag) { int i; double x = 0.0; double y = 0.0; m_path.begin_path(); for(i = 0; attr[i]; i += 2) { if(!parse_attr(attr[i], attr[i + 1])) { if(strcmp(attr[i], "points") == 0) { m_tokenizer.set_path_str(attr[i + 1]); if(!m_tokenizer.next()) { throw exception("parse_poly: Too few coordinates"); } x = m_tokenizer.last_number(); if(!m_tokenizer.next()) { throw exception("parse_poly: Too few coordinates"); } y = m_tokenizer.last_number(); m_path.move_to(x, y); while(m_tokenizer.next()) { x = m_tokenizer.last_number(); if(!m_tokenizer.next()) { throw exception("parse_poly: Odd number of coordinates"); } y = m_tokenizer.last_number(); m_path.line_to(x, y); } } } } if(close_flag) { m_path.close_subpath(); } m_path.end_path(); } //------------------------------------------------------------- void parser::parse_transform(const char* str) { while(*str) { if(islower(*str)) { if(strncmp(str, "matrix", 6) == 0) str += parse_matrix(str); else if(strncmp(str, "translate", 9) == 0) str += parse_translate(str); else if(strncmp(str, "rotate", 6) == 0) str += parse_rotate(str); else if(strncmp(str, "scale", 5) == 0) str += parse_scale(str); else if(strncmp(str, "skewX", 5) == 0) str += parse_skew_x(str); else if(strncmp(str, "skewY", 5) == 0) str += parse_skew_y(str); else { ++str; } } else { ++str; } } } //------------------------------------------------------------- static bool is_numeric(char c) { return strchr("0123456789+-.eE", c) != 0; } //------------------------------------------------------------- static unsigned parse_transform_args(const char* str, double* args, unsigned max_na, unsigned* na) { *na = 0; const char* ptr = str; while(*ptr && *ptr != '(') ++ptr; if(*ptr == 0) { throw exception("parse_transform_args: Invalid syntax"); } const char* end = ptr; while(*end && *end != ')') ++end; if(*end == 0) { throw exception("parse_transform_args: Invalid syntax"); } while(ptr < end) { if(is_numeric(*ptr)) { if(*na >= max_na) { throw exception("parse_transform_args: Too many arguments"); } args[(*na)++] = atof(ptr); while(ptr < end && is_numeric(*ptr)) ++ptr; } else { ++ptr; } } return unsigned(end - str); } //------------------------------------------------------------- unsigned parser::parse_matrix(const char* str) { double args[6]; unsigned na = 0; unsigned len = parse_transform_args(str, args, 6, &na); if(na != 6) { throw exception("parse_matrix: Invalid number of arguments"); } m_path.transform().premultiply(trans_affine(args[0], args[1], args[2], args[3], args[4], args[5])); return len; } //------------------------------------------------------------- unsigned parser::parse_translate(const char* str) { double args[2]; unsigned na = 0; unsigned len = parse_transform_args(str, args, 2, &na); if(na == 1) args[1] = 0.0; m_path.transform().premultiply(trans_affine_translation(args[0], args[1])); return len; } //------------------------------------------------------------- unsigned parser::parse_rotate(const char* str) { double args[3]; unsigned na = 0; unsigned len = parse_transform_args(str, args, 3, &na); if(na == 1) { m_path.transform().premultiply(trans_affine_rotation(deg2rad(args[0]))); } else if(na == 3) { trans_affine t = trans_affine_translation(-args[1], -args[2]); t *= trans_affine_rotation(deg2rad(args[0])); t *= trans_affine_translation(args[1], args[2]); m_path.transform().premultiply(t); } else { throw exception("parse_rotate: Invalid number of arguments"); } return len; } //------------------------------------------------------------- unsigned parser::parse_scale(const char* str) { double args[2]; unsigned na = 0; unsigned len = parse_transform_args(str, args, 2, &na); if(na == 1) args[1] = args[0]; m_path.transform().premultiply(trans_affine_scaling(args[0], args[1])); return len; } //------------------------------------------------------------- unsigned parser::parse_skew_x(const char* str) { double arg; unsigned na = 0; unsigned len = parse_transform_args(str, &arg, 1, &na); m_path.transform().premultiply(trans_affine_skewing(deg2rad(arg), 0.0)); return len; } //------------------------------------------------------------- unsigned parser::parse_skew_y(const char* str) { double arg; unsigned na = 0; unsigned len = parse_transform_args(str, &arg, 1, &na); m_path.transform().premultiply(trans_affine_skewing(0.0, deg2rad(arg))); return len; } } } ���������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_line_profile_aa.cpp�������������������������������������������0000644�0024617�0000144�00000006745�12261257215�023300� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_renderer_outline_aa.h" namespace mapserver { //--------------------------------------------------------------------- void line_profile_aa::width(double w) { if(w < 0.0) w = 0.0; if(w < m_smoother_width) w += w; else w += m_smoother_width; w *= 0.5; w -= m_smoother_width; double s = m_smoother_width; if(w < 0.0) { s += w; w = 0.0; } set(w, s); } //--------------------------------------------------------------------- line_profile_aa::value_type* line_profile_aa::profile(double w) { m_subpixel_width = uround(w * subpixel_scale); unsigned size = m_subpixel_width + subpixel_scale * 6; if(size > m_profile.size()) { m_profile.resize(size); } return &m_profile[0]; } //--------------------------------------------------------------------- void line_profile_aa::set(double center_width, double smoother_width) { double base_val = 1.0; if(center_width == 0.0) center_width = 1.0 / subpixel_scale; if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_scale; double width = center_width + smoother_width; if(width < m_min_width) { double k = width / m_min_width; base_val *= k; center_width /= k; smoother_width /= k; } value_type* ch = profile(center_width + smoother_width); unsigned subpixel_center_width = unsigned(center_width * subpixel_scale); unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_scale); value_type* ch_center = ch + subpixel_scale*2; value_type* ch_smoother = ch_center + subpixel_center_width; unsigned i; unsigned val = m_gamma[unsigned(base_val * aa_mask)]; ch = ch_center; for(i = 0; i < subpixel_center_width; i++) { *ch++ = (value_type)val; } for(i = 0; i < subpixel_smoother_width; i++) { *ch_smoother++ = m_gamma[unsigned((base_val - base_val * (double(i) / subpixel_smoother_width)) * aa_mask)]; } unsigned n_smoother = profile_size() - subpixel_smoother_width - subpixel_center_width - subpixel_scale*2; val = m_gamma[0]; for(i = 0; i < n_smoother; i++) { *ch_smoother++ = (value_type)val; } ch = ch_center; for(i = 0; i < subpixel_scale*2; i++) { *--ch = *ch_center++; } } } ���������������������������mapserver-6.4.1/renderers/agg/src/agg_vpgen_clip_polygon.cpp����������������������������������������0000644�0024617�0000144�00000007277�12261257215�024066� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_vpgen_clip_polygon.h" #include "../include/agg_clip_liang_barsky.h" namespace mapserver { //------------------------------------------------------------------------ // Determine the clipping code of the vertex according to the // Cyrus-Beck line clipping algorithm // // | | // 0110 | 0010 | 0011 // | | // -------+--------+-------- clip_box.y2 // | | // 0100 | 0000 | 0001 // | | // -------+--------+-------- clip_box.y1 // | | // 1100 | 1000 | 1001 // | | // clip_box.x1 clip_box.x2 // // unsigned vpgen_clip_polygon::clipping_flags(double x, double y) { if(x < m_clip_box.x1) { if(y > m_clip_box.y2) return 6; if(y < m_clip_box.y1) return 12; return 4; } if(x > m_clip_box.x2) { if(y > m_clip_box.y2) return 3; if(y < m_clip_box.y1) return 9; return 1; } if(y > m_clip_box.y2) return 2; if(y < m_clip_box.y1) return 8; return 0; } //---------------------------------------------------------------------------- void vpgen_clip_polygon::reset() { m_vertex = 0; m_num_vertices = 0; } //---------------------------------------------------------------------------- void vpgen_clip_polygon::move_to(double x, double y) { m_vertex = 0; m_num_vertices = 0; m_clip_flags = clipping_flags(x, y); if(m_clip_flags == 0) { m_x[0] = x; m_y[0] = y; m_num_vertices = 1; } m_x1 = x; m_y1 = y; m_cmd = path_cmd_move_to; } //---------------------------------------------------------------------------- void vpgen_clip_polygon::line_to(double x, double y) { m_vertex = 0; m_num_vertices = 0; unsigned flags = clipping_flags(x, y); if(m_clip_flags == flags) { if(flags == 0) { m_x[0] = x; m_y[0] = y; m_num_vertices = 1; } } else { m_num_vertices = clip_liang_barsky(m_x1, m_y1, x, y, m_clip_box, m_x, m_y); } m_clip_flags = flags; m_x1 = x; m_y1 = y; } //---------------------------------------------------------------------------- unsigned vpgen_clip_polygon::vertex(double* x, double* y) { if(m_vertex < m_num_vertices) { *x = m_x[m_vertex]; *y = m_y[m_vertex]; ++m_vertex; unsigned cmd = m_cmd; m_cmd = path_cmd_line_to; return cmd; } return path_cmd_stop; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_trans_warp_magnifier.cpp��������������������������������������0000644�0024617�0000144�00000004212�12261257215�024354� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_trans_warp_magnifier.h" namespace mapserver { //------------------------------------------------------------------------ void trans_warp_magnifier::transform(double* x, double* y) const { double dx = *x - m_xc; double dy = *y - m_yc; double r = sqrt(dx * dx + dy * dy); if(r < m_radius) { *x = m_xc + dx * m_magn; *y = m_yc + dy * m_magn; return; } double m = (r + m_radius * (m_magn - 1.0)) / r; *x = m_xc + dx * m; *y = m_yc + dy * m; } //------------------------------------------------------------------------ void trans_warp_magnifier::inverse_transform(double* x, double* y) const { // New version by Andrew Skalkin //----------------- double dx = *x - m_xc; double dy = *y - m_yc; double r = sqrt(dx * dx + dy * dy); if(r < m_radius * m_magn) { *x = m_xc + dx / m_magn; *y = m_yc + dy / m_magn; } else { double rnew = r - m_radius * (m_magn - 1.0); *x = m_xc + rnew * dx / r; *y = m_yc + rnew * dy / r; } // Old version //----------------- //trans_warp_magnifier t(*this); //t.magnification(1.0 / m_magn); //t.radius(m_radius * m_magn); //t.transform(x, y); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vcgen_dash.cpp������������������������������������������������0000644�0024617�0000144�00000015675�12261257215�022273� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Line dash generator // //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_vcgen_dash.h" #include "../include/agg_shorten_path.h" namespace mapserver { //------------------------------------------------------------------------ vcgen_dash::vcgen_dash() : m_total_dash_len(0.0), m_num_dashes(0), m_dash_start(0.0), m_shorten(0.0), m_curr_dash_start(0.0), m_curr_dash(0), m_src_vertices(), m_closed(0), m_status(initial), m_src_vertex(0) { } //------------------------------------------------------------------------ void vcgen_dash::remove_all_dashes() { m_total_dash_len = 0.0; m_num_dashes = 0; m_curr_dash_start = 0.0; m_curr_dash = 0; } //------------------------------------------------------------------------ void vcgen_dash::add_dash(double dash_len, double gap_len) { if(m_num_dashes < max_dashes) { m_total_dash_len += dash_len + gap_len; m_dashes[m_num_dashes++] = dash_len; m_dashes[m_num_dashes++] = gap_len; } } //------------------------------------------------------------------------ void vcgen_dash::dash_start(double ds) { m_dash_start = ds; calc_dash_start(fabs(ds)); } //------------------------------------------------------------------------ void vcgen_dash::calc_dash_start(double ds) { m_curr_dash = 0; m_curr_dash_start = 0.0; while(ds > 0.0) { if(ds > m_dashes[m_curr_dash]) { ds -= m_dashes[m_curr_dash]; ++m_curr_dash; m_curr_dash_start = 0.0; if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; } else { m_curr_dash_start = ds; ds = 0.0; } } } //------------------------------------------------------------------------ void vcgen_dash::remove_all() { m_status = initial; m_src_vertices.remove_all(); m_closed = 0; } //------------------------------------------------------------------------ void vcgen_dash::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist(x, y)); } else { m_closed = get_close_flag(cmd); } } } //------------------------------------------------------------------------ void vcgen_dash::rewind(unsigned) { if(m_status == initial) { m_src_vertices.close(m_closed != 0); shorten_path(m_src_vertices, m_shorten, m_closed); } m_status = ready; m_src_vertex = 0; } //------------------------------------------------------------------------ unsigned vcgen_dash::vertex(double* x, double* y) { unsigned cmd = path_cmd_move_to; while(!is_stop(cmd)) { switch(m_status) { case initial: rewind(0); case ready: if(m_num_dashes < 2 || m_src_vertices.size() < 2) { cmd = path_cmd_stop; break; } m_status = polyline; m_src_vertex = 1; m_v1 = &m_src_vertices[0]; m_v2 = &m_src_vertices[1]; m_curr_rest = m_v1->dist; *x = m_v1->x; *y = m_v1->y; if(m_dash_start >= 0.0) calc_dash_start(m_dash_start); return path_cmd_move_to; case polyline: { double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; unsigned cmd = (m_curr_dash & 1) ? path_cmd_move_to : path_cmd_line_to; if(m_curr_rest > dash_rest) { m_curr_rest -= dash_rest; ++m_curr_dash; if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; m_curr_dash_start = 0.0; *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist; *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist; } else { m_curr_dash_start += m_curr_rest; *x = m_v2->x; *y = m_v2->y; ++m_src_vertex; m_v1 = m_v2; m_curr_rest = m_v1->dist; if(m_closed) { if(m_src_vertex > m_src_vertices.size()) { m_status = stop; } else { m_v2 = &m_src_vertices [ (m_src_vertex >= m_src_vertices.size()) ? 0 : m_src_vertex ]; } } else { if(m_src_vertex >= m_src_vertices.size()) { m_status = stop; } else { m_v2 = &m_src_vertices[m_src_vertex]; } } } return cmd; } break; case stop: cmd = path_cmd_stop; break; } } return path_cmd_stop; } } �������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_arrowhead.cpp�������������������������������������������������0000644�0024617�0000144�00000007123�12261257215�022133� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Simple arrowhead/arrowtail generator // //---------------------------------------------------------------------------- #include "../include/agg_arrowhead.h" namespace mapserver { //------------------------------------------------------------------------ arrowhead::arrowhead() : m_head_d1(1.0), m_head_d2(1.0), m_head_d3(1.0), m_head_d4(0.0), m_tail_d1(1.0), m_tail_d2(1.0), m_tail_d3(1.0), m_tail_d4(0.0), m_head_flag(false), m_tail_flag(false), m_curr_id(0), m_curr_coord(0) { } //------------------------------------------------------------------------ void arrowhead::rewind(unsigned path_id) { m_curr_id = path_id; m_curr_coord = 0; if(path_id == 0) { if(!m_tail_flag) { m_cmd[0] = path_cmd_stop; return; } m_coord[0] = m_tail_d1; m_coord[1] = 0.0; m_coord[2] = m_tail_d1 - m_tail_d4; m_coord[3] = m_tail_d3; m_coord[4] = -m_tail_d2 - m_tail_d4; m_coord[5] = m_tail_d3; m_coord[6] = -m_tail_d2; m_coord[7] = 0.0; m_coord[8] = -m_tail_d2 - m_tail_d4; m_coord[9] = -m_tail_d3; m_coord[10] = m_tail_d1 - m_tail_d4; m_coord[11] = -m_tail_d3; m_cmd[0] = path_cmd_move_to; m_cmd[1] = path_cmd_line_to; m_cmd[2] = path_cmd_line_to; m_cmd[3] = path_cmd_line_to; m_cmd[4] = path_cmd_line_to; m_cmd[5] = path_cmd_line_to; m_cmd[7] = path_cmd_end_poly | path_flags_close | path_flags_ccw; m_cmd[6] = path_cmd_stop; return; } if(path_id == 1) { if(!m_head_flag) { m_cmd[0] = path_cmd_stop; return; } m_coord[0] = -m_head_d1; m_coord[1] = 0.0; m_coord[2] = m_head_d2 + m_head_d4; m_coord[3] = -m_head_d3; m_coord[4] = m_head_d2; m_coord[5] = 0.0; m_coord[6] = m_head_d2 + m_head_d4; m_coord[7] = m_head_d3; m_cmd[0] = path_cmd_move_to; m_cmd[1] = path_cmd_line_to; m_cmd[2] = path_cmd_line_to; m_cmd[3] = path_cmd_line_to; m_cmd[4] = path_cmd_end_poly | path_flags_close | path_flags_ccw; m_cmd[5] = path_cmd_stop; return; } } //------------------------------------------------------------------------ unsigned arrowhead::vertex(double* x, double* y) { if(m_curr_id < 2) { unsigned curr_idx = m_curr_coord * 2; *x = m_coord[curr_idx]; *y = m_coord[curr_idx + 1]; return m_cmd[m_curr_coord++]; } return path_cmd_stop; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_svg_path_renderer.cpp�����������������������������������������0000644�0024617�0000144�00000026265�12261257215�023670� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG path renderer. // //---------------------------------------------------------------------------- #include <stdio.h> #include "agg_svg_path_renderer.h" namespace mapserver { namespace svg { //------------------------------------------------------------------------ path_renderer::path_renderer() : m_curved(m_storage), m_curved_count(m_curved), m_curved_stroked(m_curved_count), m_curved_stroked_trans(m_curved_stroked, m_transform), m_curved_trans(m_curved_count, m_transform), m_curved_trans_contour(m_curved_trans) { m_curved_trans_contour.auto_detect_orientation(false); } //------------------------------------------------------------------------ void path_renderer::remove_all() { m_storage.remove_all(); m_attr_storage.remove_all(); m_attr_stack.remove_all(); m_transform.reset(); } //------------------------------------------------------------------------ void path_renderer::begin_path() { push_attr(); unsigned idx = m_storage.start_new_path(); m_attr_storage.add(path_attributes(cur_attr(), idx)); } //------------------------------------------------------------------------ void path_renderer::end_path() { if(m_attr_storage.size() == 0) { throw exception("end_path : The path was not begun"); } path_attributes attr = cur_attr(); unsigned idx = m_attr_storage[m_attr_storage.size() - 1].index; attr.index = idx; m_attr_storage[m_attr_storage.size() - 1] = attr; pop_attr(); } //------------------------------------------------------------------------ void path_renderer::move_to(double x, double y, bool rel) // M, m { if(rel) m_storage.rel_to_abs(&x, &y); m_storage.move_to(x, y); } //------------------------------------------------------------------------ void path_renderer::line_to(double x, double y, bool rel) // L, l { if(rel) m_storage.rel_to_abs(&x, &y); m_storage.line_to(x, y); } //------------------------------------------------------------------------ void path_renderer::hline_to(double x, bool rel) // H, h { double x2 = 0.0; double y2 = 0.0; if(m_storage.total_vertices()) { m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); if(rel) x += x2; m_storage.line_to(x, y2); } } //------------------------------------------------------------------------ void path_renderer::vline_to(double y, bool rel) // V, v { double x2 = 0.0; double y2 = 0.0; if(m_storage.total_vertices()) { m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); if(rel) y += y2; m_storage.line_to(x2, y); } } //------------------------------------------------------------------------ void path_renderer::curve3(double x1, double y1, // Q, q double x, double y, bool rel) { if(rel) { m_storage.rel_to_abs(&x1, &y1); m_storage.rel_to_abs(&x, &y); } m_storage.curve3(x1, y1, x, y); } //------------------------------------------------------------------------ void path_renderer::curve3(double x, double y, bool rel) // T, t { // throw exception("curve3(x, y) : NOT IMPLEMENTED YET"); if(rel) { m_storage.curve3_rel(x, y); } else { m_storage.curve3(x, y); } } //------------------------------------------------------------------------ void path_renderer::curve4(double x1, double y1, // C, c double x2, double y2, double x, double y, bool rel) { if(rel) { m_storage.rel_to_abs(&x1, &y1); m_storage.rel_to_abs(&x2, &y2); m_storage.rel_to_abs(&x, &y); } m_storage.curve4(x1, y1, x2, y2, x, y); } //------------------------------------------------------------------------ void path_renderer::curve4(double x2, double y2, // S, s double x, double y, bool rel) { //throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET"); if(rel) { m_storage.curve4_rel(x2, y2, x, y); } else { m_storage.curve4(x2, y2, x, y); } } //------------------------------------------------------------------------ void path_renderer::close_subpath() { m_storage.end_poly(path_flags_close); } //------------------------------------------------------------------------ path_attributes& path_renderer::cur_attr() { if(m_attr_stack.size() == 0) { throw exception("cur_attr : Attribute stack is empty"); } return m_attr_stack[m_attr_stack.size() - 1]; } //------------------------------------------------------------------------ void path_renderer::push_attr() { m_attr_stack.add(m_attr_stack.size() ? m_attr_stack[m_attr_stack.size() - 1] : path_attributes()); } //------------------------------------------------------------------------ void path_renderer::pop_attr() { if(m_attr_stack.size() == 0) { throw exception("pop_attr : Attribute stack is empty"); } m_attr_stack.remove_last(); } //------------------------------------------------------------------------ void path_renderer::fill(const rgba8& f) { path_attributes& attr = cur_attr(); attr.fill_color = f; attr.fill_flag = true; } //------------------------------------------------------------------------ void path_renderer::stroke(const rgba8& s) { path_attributes& attr = cur_attr(); attr.stroke_color = s; attr.stroke_flag = true; } //------------------------------------------------------------------------ void path_renderer::even_odd(bool flag) { cur_attr().even_odd_flag = flag; } //------------------------------------------------------------------------ void path_renderer::stroke_width(double w) { cur_attr().stroke_width = w; } //------------------------------------------------------------------------ void path_renderer::fill_none() { cur_attr().fill_flag = false; } //------------------------------------------------------------------------ void path_renderer::stroke_none() { cur_attr().stroke_flag = false; } //------------------------------------------------------------------------ void path_renderer::fill_opacity(double op) { cur_attr().fill_color.opacity(op); } //------------------------------------------------------------------------ void path_renderer::stroke_opacity(double op) { cur_attr().stroke_color.opacity(op); } //------------------------------------------------------------------------ void path_renderer::line_join(line_join_e join) { cur_attr().line_join = join; } //------------------------------------------------------------------------ void path_renderer::line_cap(line_cap_e cap) { cur_attr().line_cap = cap; } //------------------------------------------------------------------------ void path_renderer::miter_limit(double ml) { cur_attr().miter_limit = ml; } //------------------------------------------------------------------------ trans_affine& path_renderer::transform() { return cur_attr().transform; } //------------------------------------------------------------------------ void path_renderer::parse_path(path_tokenizer& tok) { while(tok.next()) { double arg[10]; char cmd = tok.last_command(); unsigned i; switch(cmd) { case 'M': case 'm': arg[0] = tok.last_number(); arg[1] = tok.next(cmd); move_to(arg[0], arg[1], cmd == 'm'); break; case 'L': case 'l': arg[0] = tok.last_number(); arg[1] = tok.next(cmd); line_to(arg[0], arg[1], cmd == 'l'); break; case 'V': case 'v': vline_to(tok.last_number(), cmd == 'v'); break; case 'H': case 'h': hline_to(tok.last_number(), cmd == 'h'); break; case 'Q': case 'q': arg[0] = tok.last_number(); for(i = 1; i < 4; i++) { arg[i] = tok.next(cmd); } curve3(arg[0], arg[1], arg[2], arg[3], cmd == 'q'); break; case 'T': case 't': arg[0] = tok.last_number(); arg[1] = tok.next(cmd); curve3(arg[0], arg[1], cmd == 't'); break; case 'C': case 'c': arg[0] = tok.last_number(); for(i = 1; i < 6; i++) { arg[i] = tok.next(cmd); } curve4(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], cmd == 'c'); break; case 'S': case 's': arg[0] = tok.last_number(); for(i = 1; i < 4; i++) { arg[i] = tok.next(cmd); } curve4(arg[0], arg[1], arg[2], arg[3], cmd == 's'); break; case 'A': case 'a': throw exception("parse_path: Command A: NOT IMPLEMENTED YET"); case 'Z': case 'z': close_subpath(); break; default: { char buf[100]; sprintf(buf, "parse_path: Invalid Command %c", cmd); throw exception(buf); } } } } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_font_freetype.cpp���������������������������������������������0000644�0024617�0000144�00000126274�12261257215�023041� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include <stdio.h> #include "../include/agg_font_freetype.h" #include "../include/agg_bitset_iterator.h" #include "../include/agg_renderer_scanline.h" namespace mapserver { //------------------------------------------------------------------------------ // // This code implements the AUTODIN II polynomial // The variable corresponding to the macro argument "crc" should // be an unsigned long. // Oroginal code by Spencer Garrett <srg@quick.com> // // generated using the AUTODIN II polynomial // x^32 + x^26 + x^23 + x^22 + x^16 + // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 // //------------------------------------------------------------------------------ static const unsigned crc32tab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; //------------------------------------------------------------------------------ static unsigned calc_crc32(const unsigned char* buf, unsigned size) { unsigned crc = (unsigned)~0; const unsigned char* p; unsigned len = 0; unsigned nr = size; for (len += nr, p = buf; nr--; ++p) { crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; } return ~crc; } //------------------------------------------------------------------------ static inline int dbl_to_plain_fx(double d) { return int(d * 65536.0); } //------------------------------------------------------------------------ static inline double int26p6_to_dbl(int p) { return double(p) / 64.0; } //------------------------------------------------------------------------ static inline int dbl_to_int26p6(double p) { return int(p * 64.0 + 0.5); } //------------------------------------------------------------------------ template<class PathStorage> bool decompose_ft_outline(const FT_Outline& outline, bool flip_y, const trans_affine& mtx, PathStorage& path) { typedef typename PathStorage::value_type value_type; FT_Vector v_last; FT_Vector v_control; FT_Vector v_start; double x1, y1, x2, y2, x3, y3; FT_Vector* point; FT_Vector* limit; char* tags; int n; // index of contour in outline int first; // index of first point in contour char tag; // current point's state first = 0; for(n = 0; n < outline.n_contours; n++) { int last; // index of last point in contour last = outline.contours[n]; limit = outline.points + last; v_start = outline.points[first]; v_last = outline.points[last]; v_control = v_start; point = outline.points + first; tags = outline.tags + first; tag = FT_CURVE_TAG(tags[0]); // A contour cannot start with a cubic control point! if(tag == FT_CURVE_TAG_CUBIC) return false; // check first point to determine origin if( tag == FT_CURVE_TAG_CONIC) { // first point is conic control. Yes, this happens. if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) { // start at last point if it is on the curve v_start = v_last; limit--; } else { // if both first and last points are conic, // start at their middle and record its position // for closure v_start.x = (v_start.x + v_last.x) / 2; v_start.y = (v_start.y + v_last.y) / 2; v_last = v_start; } point--; tags--; } x1 = int26p6_to_dbl(v_start.x); y1 = int26p6_to_dbl(v_start.y); if(flip_y) y1 = -y1; mtx.transform(&x1, &y1); path.move_to(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1))); while(point < limit) { point++; tags++; tag = FT_CURVE_TAG(tags[0]); switch(tag) { case FT_CURVE_TAG_ON: // emit a single line_to { x1 = int26p6_to_dbl(point->x); y1 = int26p6_to_dbl(point->y); if(flip_y) y1 = -y1; mtx.transform(&x1, &y1); path.line_to(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1))); //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); continue; } case FT_CURVE_TAG_CONIC: // consume conic arcs { v_control.x = point->x; v_control.y = point->y; Do_Conic: if(point < limit) { FT_Vector vec; FT_Vector v_middle; point++; tags++; tag = FT_CURVE_TAG(tags[0]); vec.x = point->x; vec.y = point->y; if(tag == FT_CURVE_TAG_ON) { x1 = int26p6_to_dbl(v_control.x); y1 = int26p6_to_dbl(v_control.y); x2 = int26p6_to_dbl(vec.x); y2 = int26p6_to_dbl(vec.y); if(flip_y) { y1 = -y1; y2 = -y2; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); path.curve3(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1)), value_type(dbl_to_int26p6(x2)), value_type(dbl_to_int26p6(y2))); continue; } if(tag != FT_CURVE_TAG_CONIC) return false; v_middle.x = (v_control.x + vec.x) / 2; v_middle.y = (v_control.y + vec.y) / 2; x1 = int26p6_to_dbl(v_control.x); y1 = int26p6_to_dbl(v_control.y); x2 = int26p6_to_dbl(v_middle.x); y2 = int26p6_to_dbl(v_middle.y); if(flip_y) { y1 = -y1; y2 = -y2; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); path.curve3(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1)), value_type(dbl_to_int26p6(x2)), value_type(dbl_to_int26p6(y2))); //path.curve3(conv(v_control.x), // flip_y ? -conv(v_control.y) : conv(v_control.y), // conv(v_middle.x), // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); v_control = vec; goto Do_Conic; } x1 = int26p6_to_dbl(v_control.x); y1 = int26p6_to_dbl(v_control.y); x2 = int26p6_to_dbl(v_start.x); y2 = int26p6_to_dbl(v_start.y); if(flip_y) { y1 = -y1; y2 = -y2; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); path.curve3(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1)), value_type(dbl_to_int26p6(x2)), value_type(dbl_to_int26p6(y2))); //path.curve3(conv(v_control.x), // flip_y ? -conv(v_control.y) : conv(v_control.y), // conv(v_start.x), // flip_y ? -conv(v_start.y) : conv(v_start.y)); goto Close; } default: // FT_CURVE_TAG_CUBIC { FT_Vector vec1, vec2; if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) { return false; } vec1.x = point[0].x; vec1.y = point[0].y; vec2.x = point[1].x; vec2.y = point[1].y; point += 2; tags += 2; if(point <= limit) { FT_Vector vec; vec.x = point->x; vec.y = point->y; x1 = int26p6_to_dbl(vec1.x); y1 = int26p6_to_dbl(vec1.y); x2 = int26p6_to_dbl(vec2.x); y2 = int26p6_to_dbl(vec2.y); x3 = int26p6_to_dbl(vec.x); y3 = int26p6_to_dbl(vec.y); if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); mtx.transform(&x3, &y3); path.curve4(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1)), value_type(dbl_to_int26p6(x2)), value_type(dbl_to_int26p6(y2)), value_type(dbl_to_int26p6(x3)), value_type(dbl_to_int26p6(y3))); //path.curve4(conv(vec1.x), // flip_y ? -conv(vec1.y) : conv(vec1.y), // conv(vec2.x), // flip_y ? -conv(vec2.y) : conv(vec2.y), // conv(vec.x), // flip_y ? -conv(vec.y) : conv(vec.y)); continue; } x1 = int26p6_to_dbl(vec1.x); y1 = int26p6_to_dbl(vec1.y); x2 = int26p6_to_dbl(vec2.x); y2 = int26p6_to_dbl(vec2.y); x3 = int26p6_to_dbl(v_start.x); y3 = int26p6_to_dbl(v_start.y); if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); mtx.transform(&x3, &y3); path.curve4(value_type(dbl_to_int26p6(x1)), value_type(dbl_to_int26p6(y1)), value_type(dbl_to_int26p6(x2)), value_type(dbl_to_int26p6(y2)), value_type(dbl_to_int26p6(x3)), value_type(dbl_to_int26p6(y3))); //path.curve4(conv(vec1.x), // flip_y ? -conv(vec1.y) : conv(vec1.y), // conv(vec2.x), // flip_y ? -conv(vec2.y) : conv(vec2.y), // conv(v_start.x), // flip_y ? -conv(v_start.y) : conv(v_start.y)); goto Close; } } } path.close_polygon(); Close: first = last + 1; } return true; } //------------------------------------------------------------------------ template<class Scanline, class ScanlineStorage> void decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, int x, int y, bool flip_y, Scanline& sl, ScanlineStorage& storage) { int i; const int8u* buf = (const int8u*)bitmap.buffer; int pitch = bitmap.pitch; sl.reset(x, x + bitmap.width); storage.prepare(); if(flip_y) { buf += bitmap.pitch * (bitmap.rows - 1); y += bitmap.rows; pitch = -pitch; } for(i = 0; i < bitmap.rows; i++) { sl.reset_spans(); bitset_iterator bits(buf, 0); int j; for(j = 0; j < bitmap.width; j++) { if(bits.bit()) sl.add_cell(x + j, cover_full); ++bits; } buf += pitch; if(sl.num_spans()) { sl.finalize(y - i - 1); storage.render(sl); } } } //------------------------------------------------------------------------ template<class Rasterizer, class Scanline, class ScanlineStorage> void decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, int x, int y, bool flip_y, Rasterizer& ras, Scanline& sl, ScanlineStorage& storage) { int i, j; const int8u* buf = (const int8u*)bitmap.buffer; int pitch = bitmap.pitch; sl.reset(x, x + bitmap.width); storage.prepare(); if(flip_y) { buf += bitmap.pitch * (bitmap.rows - 1); y += bitmap.rows; pitch = -pitch; } for(i = 0; i < bitmap.rows; i++) { sl.reset_spans(); const int8u* p = buf; for(j = 0; j < bitmap.width; j++) { if(*p) sl.add_cell(x + j, ras.apply_gamma(*p)); ++p; } buf += pitch; if(sl.num_spans()) { sl.finalize(y - i - 1); storage.render(sl); } } } //------------------------------------------------------------------------ font_engine_freetype_base::~font_engine_freetype_base() { unsigned i; for(i = 0; i < m_num_faces; ++i) { delete [] m_face_names[i]; FT_Done_Face(m_faces[i]); } delete [] m_face_names; delete [] m_faces; delete [] m_signature; if(m_library_initialized) FT_Done_FreeType(m_library); } //------------------------------------------------------------------------ font_engine_freetype_base::font_engine_freetype_base(bool flag32, unsigned max_faces) : m_flag32(flag32), m_change_stamp(0), m_last_error(0), m_name(0), m_name_len(256-16-1), m_face_index(0), m_char_map(FT_ENCODING_NONE), m_signature(new char [256+256-16]), m_height(0), m_width(0), m_hinting(true), m_flip_y(false), m_library_initialized(false), m_library(0), m_faces(new FT_Face [max_faces]), m_face_names(new char* [max_faces]), m_num_faces(0), m_max_faces(max_faces), m_cur_face(0), m_resolution(0), m_glyph_rendering(glyph_ren_native_gray8), m_glyph_index(0), m_data_size(0), m_data_type(glyph_data_invalid), m_bounds(1,1,0,0), m_advance_x(0.0), m_advance_y(0.0), m_path16(), m_path32(), m_curves16(m_path16), m_curves32(m_path32), m_scanline_aa(), m_scanline_bin(), m_scanlines_aa(), m_scanlines_bin(), m_rasterizer() { m_curves16.approximation_scale(4.0); m_curves32.approximation_scale(4.0); m_last_error = FT_Init_FreeType(&m_library); if(m_last_error == 0) m_library_initialized = true; } //------------------------------------------------------------------------ void font_engine_freetype_base::resolution(unsigned dpi) { m_resolution = dpi; update_char_size(); } //------------------------------------------------------------------------ int font_engine_freetype_base::find_face(const char* face_name) const { unsigned i; for(i = 0; i < m_num_faces; ++i) { if(strcmp(face_name, m_face_names[i]) == 0) return i; } return -1; } //------------------------------------------------------------------------ double font_engine_freetype_base::ascender() const { if(m_cur_face) { return m_cur_face->ascender * height() / m_cur_face->height; } return 0.0; } //------------------------------------------------------------------------ double font_engine_freetype_base::descender() const { if(m_cur_face) { return m_cur_face->descender * height() / m_cur_face->height; } return 0.0; } //------------------------------------------------------------------------ bool font_engine_freetype_base::load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type, const char* font_mem, const long font_mem_size) { bool ret = false; if(m_library_initialized) { m_last_error = 0; int idx = find_face(font_name); if(idx >= 0) { m_cur_face = m_faces[idx]; m_name = m_face_names[idx]; } else { if(m_num_faces >= m_max_faces) { delete [] m_face_names[0]; FT_Done_Face(m_faces[0]); memcpy(m_faces, m_faces + 1, (m_max_faces - 1) * sizeof(FT_Face)); memcpy(m_face_names, m_face_names + 1, (m_max_faces - 1) * sizeof(char*)); m_num_faces = m_max_faces - 1; } if (font_mem && font_mem_size) { m_last_error = FT_New_Memory_Face(m_library, (const FT_Byte*)font_mem, font_mem_size, face_index, &m_faces[m_num_faces]); } else { m_last_error = FT_New_Face(m_library, font_name, face_index, &m_faces[m_num_faces]); } if(m_last_error == 0) { m_face_names[m_num_faces] = new char [strlen(font_name) + 1]; strcpy(m_face_names[m_num_faces], font_name); m_cur_face = m_faces[m_num_faces]; m_name = m_face_names[m_num_faces]; ++m_num_faces; } else { m_face_names[m_num_faces] = 0; m_cur_face = 0; m_name = 0; } if( FT_Select_Charmap(m_cur_face, FT_ENCODING_UNICODE) ) { if( FT_Select_Charmap(m_cur_face, FT_ENCODING_MS_SYMBOL) ) { if( FT_Select_Charmap(m_cur_face, FT_ENCODING_APPLE_ROMAN) ) { m_char_map = FT_ENCODING_NONE; } else { m_char_map = FT_ENCODING_APPLE_ROMAN; } } else { m_char_map = FT_ENCODING_MS_SYMBOL; } } else { m_char_map = FT_ENCODING_UNICODE; } } if(m_last_error == 0) { ret = true; switch(ren_type) { case glyph_ren_native_mono: m_glyph_rendering = glyph_ren_native_mono; break; case glyph_ren_native_gray8: m_glyph_rendering = glyph_ren_native_gray8; break; case glyph_ren_outline: if(FT_IS_SCALABLE(m_cur_face)) { m_glyph_rendering = glyph_ren_outline; } else { m_glyph_rendering = glyph_ren_native_gray8; } break; case glyph_ren_agg_mono: if(FT_IS_SCALABLE(m_cur_face)) { m_glyph_rendering = glyph_ren_agg_mono; } else { m_glyph_rendering = glyph_ren_native_mono; } break; case glyph_ren_agg_gray8: if(FT_IS_SCALABLE(m_cur_face)) { m_glyph_rendering = glyph_ren_agg_gray8; } else { m_glyph_rendering = glyph_ren_native_gray8; } break; } update_signature(); } } return ret; } //------------------------------------------------------------------------ bool font_engine_freetype_base::attach(const char* file_name) { if(m_cur_face) { m_last_error = FT_Attach_File(m_cur_face, file_name); return m_last_error == 0; } return false; } //------------------------------------------------------------------------ unsigned font_engine_freetype_base::num_faces() const { if(m_cur_face) { return m_cur_face->num_faces; } return 0; } //------------------------------------------------------------------------ bool font_engine_freetype_base::char_map(FT_Encoding char_map) { if(m_cur_face) { m_last_error = FT_Select_Charmap(m_cur_face, m_char_map); if(m_last_error == 0) { update_signature(); return true; } } return false; } //------------------------------------------------------------------------ bool font_engine_freetype_base::height(double h) { m_height = int(h * 64.0); if(m_cur_face) { update_char_size(); return true; } return false; } //------------------------------------------------------------------------ bool font_engine_freetype_base::width(double w) { m_width = int(w * 64.0); if(m_cur_face) { update_char_size(); return true; } return false; } //------------------------------------------------------------------------ void font_engine_freetype_base::hinting(bool h) { m_hinting = h; if(m_cur_face) { update_signature(); } } //------------------------------------------------------------------------ void font_engine_freetype_base::flip_y(bool f) { m_flip_y = f; if(m_cur_face) { update_signature(); } } //------------------------------------------------------------------------ void font_engine_freetype_base::transform(const trans_affine& affine) { m_affine = affine; if(m_cur_face) { update_signature(); } } //------------------------------------------------------------------------ void font_engine_freetype_base::update_signature() { if(m_cur_face && m_name) { unsigned name_len = strlen(m_name); if(name_len > m_name_len) { delete [] m_signature; m_signature = new char [name_len + 32 + 256]; m_name_len = name_len + 32 - 1; } unsigned gamma_hash = 0; if(m_glyph_rendering == glyph_ren_native_gray8 || m_glyph_rendering == glyph_ren_agg_mono || m_glyph_rendering == glyph_ren_agg_gray8) { unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale]; unsigned i; for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i) { gamma_table[i] = m_rasterizer.apply_gamma(i); } gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table)); } sprintf(m_signature, "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X", m_name, m_char_map, m_face_index, int(m_glyph_rendering), m_resolution, m_height, m_width, int(m_hinting), int(m_flip_y), gamma_hash); if(m_glyph_rendering == glyph_ren_outline || m_glyph_rendering == glyph_ren_agg_mono || m_glyph_rendering == glyph_ren_agg_gray8) { double mtx[6]; char buf[100]; m_affine.store_to(mtx); sprintf(buf, ",%08X%08X%08X%08X%08X%08X", dbl_to_plain_fx(mtx[0]), dbl_to_plain_fx(mtx[1]), dbl_to_plain_fx(mtx[2]), dbl_to_plain_fx(mtx[3]), dbl_to_plain_fx(mtx[4]), dbl_to_plain_fx(mtx[5])); strcat(m_signature, buf); } ++m_change_stamp; } } //------------------------------------------------------------------------ void font_engine_freetype_base::update_char_size() { if(m_cur_face) { if(m_resolution) { FT_Set_Char_Size(m_cur_face, m_width, // char_width in 1/64th of points m_height, // char_height in 1/64th of points m_resolution, // horizontal device resolution m_resolution); // vertical device resolution } else { FT_Set_Pixel_Sizes(m_cur_face, m_width >> 6, // pixel_width m_height >> 6); // pixel_height } update_signature(); } } //------------------------------------------------------------------------ bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code) { /* FT_ENCODING_MS_SYMBOL hack inspired from GD's gdft.c: */ /* I do not know the significance of the constant 0xf000. */ /* It was determined by inspection of the character codes */ /* stored in Microsoft font symbol.ttf */ if (m_cur_face->charmap && m_cur_face->charmap->encoding == FT_ENCODING_MS_SYMBOL) glyph_code |= 0xf000; m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code); m_last_error = FT_Load_Glyph(m_cur_face, m_glyph_index, m_hinting ? FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP : FT_LOAD_NO_HINTING|FT_LOAD_NO_BITMAP); // m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); if(m_last_error == 0) { switch(m_glyph_rendering) { case glyph_ren_native_mono: m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO); if(m_last_error == 0) { decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap, m_cur_face->glyph->bitmap_left, m_flip_y ? -m_cur_face->glyph->bitmap_top : m_cur_face->glyph->bitmap_top, m_flip_y, m_scanline_bin, m_scanlines_bin); m_bounds.x1 = m_scanlines_bin.min_x(); m_bounds.y1 = m_scanlines_bin.min_y(); m_bounds.x2 = m_scanlines_bin.max_x() + 1; m_bounds.y2 = m_scanlines_bin.max_y() + 1; m_data_size = m_scanlines_bin.byte_size(); m_data_type = glyph_data_mono; m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); return true; } break; case glyph_ren_native_gray8: m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL); if(m_last_error == 0) { decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap, m_cur_face->glyph->bitmap_left, m_flip_y ? -m_cur_face->glyph->bitmap_top : m_cur_face->glyph->bitmap_top, m_flip_y, m_rasterizer, m_scanline_aa, m_scanlines_aa); m_bounds.x1 = m_scanlines_aa.min_x(); m_bounds.y1 = m_scanlines_aa.min_y(); m_bounds.x2 = m_scanlines_aa.max_x() + 1; m_bounds.y2 = m_scanlines_aa.max_y() + 1; m_data_size = m_scanlines_aa.byte_size(); m_data_type = glyph_data_gray8; m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); return true; } break; case glyph_ren_outline: if(m_last_error == 0) { if(m_flag32) { m_path32.remove_all(); if(decompose_ft_outline(m_cur_face->glyph->outline, m_flip_y, m_affine, m_path32)) { rect_d bnd = m_path32.bounding_rect(); m_data_size = m_path32.byte_size(); m_data_type = glyph_data_outline; m_bounds.x1 = int(floor(bnd.x1)); m_bounds.y1 = int(floor(bnd.y1)); m_bounds.x2 = int(ceil(bnd.x2)); m_bounds.y2 = int(ceil(bnd.y2)); m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); m_affine.transform(&m_advance_x, &m_advance_y); return true; } } else { m_path16.remove_all(); if(decompose_ft_outline(m_cur_face->glyph->outline, m_flip_y, m_affine, m_path16)) { rect_d bnd = m_path16.bounding_rect(); m_data_size = m_path16.byte_size(); m_data_type = glyph_data_outline; m_bounds.x1 = int(floor(bnd.x1)); m_bounds.y1 = int(floor(bnd.y1)); m_bounds.x2 = int(ceil(bnd.x2)); m_bounds.y2 = int(ceil(bnd.y2)); m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); m_affine.transform(&m_advance_x, &m_advance_y); return true; } } } return false; case glyph_ren_agg_mono: if(m_last_error == 0) { m_rasterizer.reset(); if(m_flag32) { m_path32.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, m_flip_y, m_affine, m_path32); m_rasterizer.add_path(m_curves32); } else { m_path16.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, m_flip_y, m_affine, m_path16); m_rasterizer.add_path(m_curves16); } m_scanlines_bin.prepare(); // Remove all render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin); m_bounds.x1 = m_scanlines_bin.min_x(); m_bounds.y1 = m_scanlines_bin.min_y(); m_bounds.x2 = m_scanlines_bin.max_x() + 1; m_bounds.y2 = m_scanlines_bin.max_y() + 1; m_data_size = m_scanlines_bin.byte_size(); m_data_type = glyph_data_mono; m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); m_affine.transform(&m_advance_x, &m_advance_y); return true; } return false; case glyph_ren_agg_gray8: if(m_last_error == 0) { m_rasterizer.reset(); if(m_flag32) { m_path32.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, m_flip_y, m_affine, m_path32); m_rasterizer.add_path(m_curves32); } else { m_path16.remove_all(); decompose_ft_outline(m_cur_face->glyph->outline, m_flip_y, m_affine, m_path16); m_rasterizer.add_path(m_curves16); } m_scanlines_aa.prepare(); // Remove all render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa); m_bounds.x1 = m_scanlines_aa.min_x(); m_bounds.y1 = m_scanlines_aa.min_y(); m_bounds.x2 = m_scanlines_aa.max_x() + 1; m_bounds.y2 = m_scanlines_aa.max_y() + 1; m_data_size = m_scanlines_aa.byte_size(); m_data_type = glyph_data_gray8; m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); m_affine.transform(&m_advance_x, &m_advance_y); return true; } return false; } } return false; } //------------------------------------------------------------------------ void font_engine_freetype_base::write_glyph_to(int8u* data) const { if(data && m_data_size) { switch(m_data_type) { default: return; case glyph_data_mono: m_scanlines_bin.serialize(data); break; case glyph_data_gray8: m_scanlines_aa.serialize(data); break; case glyph_data_outline: if(m_flag32) { m_path32.serialize(data); } else { m_path16.serialize(data); } break; case glyph_data_invalid: break; } } } //------------------------------------------------------------------------ bool font_engine_freetype_base::add_kerning(unsigned first, unsigned second, double* x, double* y) { if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face)) { FT_Vector delta; FT_Get_Kerning(m_cur_face, first, second, FT_KERNING_DEFAULT, &delta); double dx = int26p6_to_dbl(delta.x); double dy = int26p6_to_dbl(delta.y); if(m_glyph_rendering == glyph_ren_outline || m_glyph_rendering == glyph_ren_agg_mono || m_glyph_rendering == glyph_ren_agg_gray8) { m_affine.transform_2x2(&dx, &dy); } *x += dx; *y += dy; return true; } return false; } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_trans_double_path.cpp�����������������������������������������0000644�0024617�0000144�00000017737�12261257215�023670� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_math.h" #include "../include/agg_trans_double_path.h" namespace mapserver { //------------------------------------------------------------------------ trans_double_path::trans_double_path() : m_kindex1(0.0), m_kindex2(0.0), m_base_length(0.0), m_base_height(1.0), m_status1(initial), m_status2(initial), m_preserve_x_scale(true) { } //------------------------------------------------------------------------ void trans_double_path::reset() { m_src_vertices1.remove_all(); m_src_vertices2.remove_all(); m_kindex1 = 0.0; m_kindex1 = 0.0; m_status1 = initial; m_status2 = initial; } //------------------------------------------------------------------------ void trans_double_path::move_to1(double x, double y) { if(m_status1 == initial) { m_src_vertices1.modify_last(vertex_dist(x, y)); m_status1 = making_path; } else { line_to1(x, y); } } //------------------------------------------------------------------------ void trans_double_path::line_to1(double x, double y) { if(m_status1 == making_path) { m_src_vertices1.add(vertex_dist(x, y)); } } //------------------------------------------------------------------------ void trans_double_path::move_to2(double x, double y) { if(m_status2 == initial) { m_src_vertices2.modify_last(vertex_dist(x, y)); m_status2 = making_path; } else { line_to2(x, y); } } //------------------------------------------------------------------------ void trans_double_path::line_to2(double x, double y) { if(m_status2 == making_path) { m_src_vertices2.add(vertex_dist(x, y)); } } //------------------------------------------------------------------------ double trans_double_path::finalize_path(vertex_storage& vertices) { unsigned i; double dist; double d; vertices.close(false); if(vertices.size() > 2) { if(vertices[vertices.size() - 2].dist * 10.0 < vertices[vertices.size() - 3].dist) { d = vertices[vertices.size() - 3].dist + vertices[vertices.size() - 2].dist; vertices[vertices.size() - 2] = vertices[vertices.size() - 1]; vertices.remove_last(); vertices[vertices.size() - 2].dist = d; } } dist = 0; for(i = 0; i < vertices.size(); i++) { vertex_dist& v = vertices[i]; d = v.dist; v.dist = dist; dist += d; } return (vertices.size() - 1) / dist; } //------------------------------------------------------------------------ void trans_double_path::finalize_paths() { if(m_status1 == making_path && m_src_vertices1.size() > 1 && m_status2 == making_path && m_src_vertices2.size() > 1) { m_kindex1 = finalize_path(m_src_vertices1); m_kindex2 = finalize_path(m_src_vertices2); m_status1 = ready; m_status2 = ready; } } //------------------------------------------------------------------------ double trans_double_path::total_length1() const { if(m_base_length >= 1e-10) return m_base_length; return (m_status1 == ready) ? m_src_vertices1[m_src_vertices1.size() - 1].dist : 0.0; } //------------------------------------------------------------------------ double trans_double_path::total_length2() const { if(m_base_length >= 1e-10) return m_base_length; return (m_status2 == ready) ? m_src_vertices2[m_src_vertices2.size() - 1].dist : 0.0; } //------------------------------------------------------------------------ void trans_double_path::transform1(const vertex_storage& vertices, double kindex, double kx, double *x, double* y) const { double x1 = 0.0; double y1 = 0.0; double dx = 1.0; double dy = 1.0; double d = 0.0; double dd = 1.0; *x *= kx; if(*x < 0.0) { // Extrapolation on the left //-------------------------- x1 = vertices[0].x; y1 = vertices[0].y; dx = vertices[1].x - x1; dy = vertices[1].y - y1; dd = vertices[1].dist - vertices[0].dist; d = *x; } else if(*x > vertices[vertices.size() - 1].dist) { // Extrapolation on the right //-------------------------- unsigned i = vertices.size() - 2; unsigned j = vertices.size() - 1; x1 = vertices[j].x; y1 = vertices[j].y; dx = x1 - vertices[i].x; dy = y1 - vertices[i].y; dd = vertices[j].dist - vertices[i].dist; d = *x - vertices[j].dist; } else { // Interpolation //-------------------------- unsigned i = 0; unsigned j = vertices.size() - 1; if(m_preserve_x_scale) { unsigned k; for(i = 0; (j - i) > 1; ) { if(*x < vertices[k = (i + j) >> 1].dist) { j = k; } else { i = k; } } d = vertices[i].dist; dd = vertices[j].dist - d; d = *x - d; } else { i = unsigned(*x * kindex); j = i + 1; dd = vertices[j].dist - vertices[i].dist; d = ((*x * kindex) - i) * dd; } x1 = vertices[i].x; y1 = vertices[i].y; dx = vertices[j].x - x1; dy = vertices[j].y - y1; } *x = x1 + dx * d / dd; *y = y1 + dy * d / dd; } //------------------------------------------------------------------------ void trans_double_path::transform(double *x, double *y) const { if(m_status1 == ready && m_status2 == ready) { if(m_base_length > 1e-10) { *x *= m_src_vertices1[m_src_vertices1.size() - 1].dist / m_base_length; } double x1 = *x; double y1 = *y; double x2 = *x; double y2 = *y; double dd = m_src_vertices2[m_src_vertices2.size() - 1].dist / m_src_vertices1[m_src_vertices1.size() - 1].dist; transform1(m_src_vertices1, m_kindex1, 1.0, &x1, &y1); transform1(m_src_vertices2, m_kindex2, dd, &x2, &y2); *x = x1 + *y * (x2 - x1) / m_base_height; *y = y1 + *y * (y2 - y1) / m_base_height; } } } ���������������������������������mapserver-6.4.1/renderers/agg/src/agg_image_filters.cpp���������������������������������������������0000644�0024617�0000144�00000007001�12261257215�022764� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Filtering class image_filter_lut implemantation // //---------------------------------------------------------------------------- #include "../include/agg_image_filters.h" namespace mapserver { //-------------------------------------------------------------------- void image_filter_lut::realloc_lut(double radius) { m_radius = radius; m_diameter = uceil(radius) * 2; m_start = -int(m_diameter / 2 - 1); unsigned size = m_diameter << image_subpixel_shift; if(size > m_weight_array.size()) { m_weight_array.resize(size); } } //-------------------------------------------------------------------- // This function normalizes integer values and corrects the rounding // errors. It doesn't do anything with the source floating point values // (m_weight_array_dbl), it corrects only integers according to the rule // of 1.0 which means that any sum of pixel weights must be equal to 1.0. // So, the filter function must produce a graph of the proper shape. //-------------------------------------------------------------------- void image_filter_lut::normalize() { unsigned i; int flip = 1; for(i = 0; i < image_subpixel_scale; i++) { for(;;) { int sum = 0; unsigned j; for(j = 0; j < m_diameter; j++) { sum += m_weight_array[j * image_subpixel_scale + i]; } if(sum == image_filter_scale) break; double k = double(image_filter_scale) / double(sum); sum = 0; for(j = 0; j < m_diameter; j++) { sum += m_weight_array[j * image_subpixel_scale + i] = iround(m_weight_array[j * image_subpixel_scale + i] * k); } sum -= image_filter_scale; int inc = (sum > 0) ? -1 : 1; for(j = 0; j < m_diameter && sum; j++) { flip ^= 1; unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2; int v = m_weight_array[idx * image_subpixel_scale + i]; if(v < image_filter_scale) { m_weight_array[idx * image_subpixel_scale + i] += inc; sum += inc; } } } } unsigned pivot = m_diameter << (image_subpixel_shift - 1); for(i = 0; i < pivot; i++) { m_weight_array[pivot + i] = m_weight_array[pivot - i]; } unsigned end = (diameter() << image_subpixel_shift) - 1; m_weight_array[0] = m_weight_array[end]; } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_rounded_rect.cpp����������������������������������������������0000644�0024617�0000144�00000012141�12261257215�022630� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Rounded rectangle vertex generator // //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_rounded_rect.h" namespace mapserver { //------------------------------------------------------------------------ rounded_rect::rounded_rect(double x1, double y1, double x2, double y2, double r) : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), m_rx1(r), m_ry1(r), m_rx2(r), m_ry2(r), m_rx3(r), m_ry3(r), m_rx4(r), m_ry4(r) { if(x1 > x2) { m_x1 = x2; m_x2 = x1; } if(y1 > y2) { m_y1 = y2; m_y2 = y1; } } //-------------------------------------------------------------------- void rounded_rect::rect(double x1, double y1, double x2, double y2) { m_x1 = x1; m_y1 = y1; m_x2 = x2; m_y2 = y2; if(x1 > x2) { m_x1 = x2; m_x2 = x1; } if(y1 > y2) { m_y1 = y2; m_y2 = y1; } } //-------------------------------------------------------------------- void rounded_rect::radius(double r) { m_rx1 = m_ry1 = m_rx2 = m_ry2 = m_rx3 = m_ry3 = m_rx4 = m_ry4 = r; } //-------------------------------------------------------------------- void rounded_rect::radius(double rx, double ry) { m_rx1 = m_rx2 = m_rx3 = m_rx4 = rx; m_ry1 = m_ry2 = m_ry3 = m_ry4 = ry; } //-------------------------------------------------------------------- void rounded_rect::radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top) { m_rx1 = m_rx2 = rx_bottom; m_rx3 = m_rx4 = rx_top; m_ry1 = m_ry2 = ry_bottom; m_ry3 = m_ry4 = ry_top; } //-------------------------------------------------------------------- void rounded_rect::radius(double rx1, double ry1, double rx2, double ry2, double rx3, double ry3, double rx4, double ry4) { m_rx1 = rx1; m_ry1 = ry1; m_rx2 = rx2; m_ry2 = ry2; m_rx3 = rx3; m_ry3 = ry3; m_rx4 = rx4; m_ry4 = ry4; } //-------------------------------------------------------------------- void rounded_rect::normalize_radius() { double dx = fabs(m_y2 - m_y1); double dy = fabs(m_x2 - m_x1); double k = 1.0; double t; t = dx / (m_rx1 + m_rx2); if(t < k) k = t; t = dx / (m_rx3 + m_rx4); if(t < k) k = t; t = dy / (m_ry1 + m_ry2); if(t < k) k = t; t = dy / (m_ry3 + m_ry4); if(t < k) k = t; if(k < 1.0) { m_rx1 *= k; m_ry1 *= k; m_rx2 *= k; m_ry2 *= k; m_rx3 *= k; m_ry3 *= k; m_rx4 *= k; m_ry4 *= k; } } //-------------------------------------------------------------------- void rounded_rect::rewind(unsigned) { m_status = 0; } //-------------------------------------------------------------------- unsigned rounded_rect::vertex(double* x, double* y) { unsigned cmd = path_cmd_stop; switch(m_status) { case 0: m_arc.init(m_x1 + m_rx1, m_y1 + m_ry1, m_rx1, m_ry1, pi, pi+pi*0.5); m_arc.rewind(0); m_status++; case 1: cmd = m_arc.vertex(x, y); if(is_stop(cmd)) m_status++; else return cmd; case 2: m_arc.init(m_x2 - m_rx2, m_y1 + m_ry2, m_rx2, m_ry2, pi+pi*0.5, 0.0); m_arc.rewind(0); m_status++; case 3: cmd = m_arc.vertex(x, y); if(is_stop(cmd)) m_status++; else return path_cmd_line_to; case 4: m_arc.init(m_x2 - m_rx3, m_y2 - m_ry3, m_rx3, m_ry3, 0.0, pi*0.5); m_arc.rewind(0); m_status++; case 5: cmd = m_arc.vertex(x, y); if(is_stop(cmd)) m_status++; else return path_cmd_line_to; case 6: m_arc.init(m_x1 + m_rx4, m_y2 - m_ry4, m_rx4, m_ry4, pi*0.5, pi); m_arc.rewind(0); m_status++; case 7: cmd = m_arc.vertex(x, y); if(is_stop(cmd)) m_status++; else return path_cmd_line_to; case 8: cmd = path_cmd_end_poly | path_flags_close | path_flags_ccw; m_status++; break; } return cmd; } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_arc.cpp�������������������������������������������������������0000644�0024617�0000144�00000006132�12261257215�020723� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Arc vertex generator // //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_arc.h" namespace mapserver { //------------------------------------------------------------------------ arc::arc(double x, double y, double rx, double ry, double a1, double a2, bool ccw) : m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0) { normalize(a1, a2, ccw); } //------------------------------------------------------------------------ void arc::init(double x, double y, double rx, double ry, double a1, double a2, bool ccw) { m_x = x; m_y = y; m_rx = rx; m_ry = ry; normalize(a1, a2, ccw); } //------------------------------------------------------------------------ void arc::approximation_scale(double s) { m_scale = s; if(m_initialized) { normalize(m_start, m_end, m_ccw); } } //------------------------------------------------------------------------ void arc::rewind(unsigned) { m_path_cmd = path_cmd_move_to; m_angle = m_start; } //------------------------------------------------------------------------ unsigned arc::vertex(double* x, double* y) { if(is_stop(m_path_cmd)) return path_cmd_stop; if((m_angle < m_end - m_da/4) != m_ccw) { *x = m_x + cos(m_end) * m_rx; *y = m_y + sin(m_end) * m_ry; m_path_cmd = path_cmd_stop; return path_cmd_line_to; } *x = m_x + cos(m_angle) * m_rx; *y = m_y + sin(m_angle) * m_ry; m_angle += m_da; unsigned pf = m_path_cmd; m_path_cmd = path_cmd_line_to; return pf; } //------------------------------------------------------------------------ void arc::normalize(double a1, double a2, bool ccw) { double ra = (fabs(m_rx) + fabs(m_ry)) / 2; m_da = acos(ra / (ra + 0.125 / m_scale)) * 2; if(ccw) { while(a2 < a1) a2 += pi * 2.0; } else { while(a1 < a2) a1 += pi * 2.0; m_da = -m_da; } m_ccw = ccw; m_start = a1; m_end = a2; m_initialized = true; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vcgen_bspline.cpp���������������������������������������������0000644�0024617�0000144�00000015011�12261257215�022770� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_vcgen_bspline.h" namespace mapserver { //------------------------------------------------------------------------ vcgen_bspline::vcgen_bspline() : m_src_vertices(), m_spline_x(), m_spline_y(), m_interpolation_step(1.0/50.0), m_closed(0), m_status(initial), m_src_vertex(0) { } //------------------------------------------------------------------------ void vcgen_bspline::remove_all() { m_src_vertices.remove_all(); m_closed = 0; m_status = initial; m_src_vertex = 0; } //------------------------------------------------------------------------ void vcgen_bspline::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(point_d(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(point_d(x, y)); } else { m_closed = get_close_flag(cmd); } } } //------------------------------------------------------------------------ void vcgen_bspline::rewind(unsigned) { m_cur_abscissa = 0.0; m_max_abscissa = 0.0; m_src_vertex = 0; if(m_status == initial && m_src_vertices.size() > 2) { if(m_closed) { m_spline_x.init(m_src_vertices.size() + 8); m_spline_y.init(m_src_vertices.size() + 8); m_spline_x.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).x); m_spline_y.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).y); m_spline_x.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].x); m_spline_y.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].y); m_spline_x.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].x); m_spline_y.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].y); m_spline_x.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].x); m_spline_y.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].y); } else { m_spline_x.init(m_src_vertices.size()); m_spline_y.init(m_src_vertices.size()); } unsigned i; for(i = 0; i < m_src_vertices.size(); i++) { double x = m_closed ? i + 4 : i; m_spline_x.add_point(x, m_src_vertices[i].x); m_spline_y.add_point(x, m_src_vertices[i].y); } m_cur_abscissa = 0.0; m_max_abscissa = m_src_vertices.size() - 1; if(m_closed) { m_cur_abscissa = 4.0; m_max_abscissa += 5.0; m_spline_x.add_point(m_src_vertices.size() + 4, m_src_vertices[0].x); m_spline_y.add_point(m_src_vertices.size() + 4, m_src_vertices[0].y); m_spline_x.add_point(m_src_vertices.size() + 5, m_src_vertices[1].x); m_spline_y.add_point(m_src_vertices.size() + 5, m_src_vertices[1].y); m_spline_x.add_point(m_src_vertices.size() + 6, m_src_vertices[2].x); m_spline_y.add_point(m_src_vertices.size() + 6, m_src_vertices[2].y); m_spline_x.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).x); m_spline_y.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).y); } m_spline_x.prepare(); m_spline_y.prepare(); } m_status = ready; } //------------------------------------------------------------------------ unsigned vcgen_bspline::vertex(double* x, double* y) { unsigned cmd = path_cmd_line_to; while(!is_stop(cmd)) { switch(m_status) { case initial: rewind(0); case ready: if(m_src_vertices.size() < 2) { cmd = path_cmd_stop; break; } if(m_src_vertices.size() == 2) { *x = m_src_vertices[m_src_vertex].x; *y = m_src_vertices[m_src_vertex].y; m_src_vertex++; if(m_src_vertex == 1) return path_cmd_move_to; if(m_src_vertex == 2) return path_cmd_line_to; cmd = path_cmd_stop; break; } cmd = path_cmd_move_to; m_status = polygon; m_src_vertex = 0; case polygon: if(m_cur_abscissa >= m_max_abscissa) { if(m_closed) { m_status = end_poly; break; } else { *x = m_src_vertices[m_src_vertices.size() - 1].x; *y = m_src_vertices[m_src_vertices.size() - 1].y; m_status = end_poly; return path_cmd_line_to; } } *x = m_spline_x.get_stateful(m_cur_abscissa); *y = m_spline_y.get_stateful(m_cur_abscissa); m_src_vertex++; m_cur_abscissa += m_interpolation_step; return (m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; case end_poly: m_status = stop; return path_cmd_end_poly | m_closed; case stop: return path_cmd_stop; } } return cmd; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vcgen_smooth_poly1.cpp����������������������������������������0000644�0024617�0000144�00000015561�12261257215�024003� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Smooth polygon generator // //---------------------------------------------------------------------------- #include "../include/agg_vcgen_smooth_poly1.h" namespace mapserver { //------------------------------------------------------------------------ vcgen_smooth_poly1::vcgen_smooth_poly1() : m_src_vertices(), m_smooth_value(0.5), m_closed(0), m_status(initial), m_src_vertex(0) { } //------------------------------------------------------------------------ void vcgen_smooth_poly1::remove_all() { m_src_vertices.remove_all(); m_closed = 0; m_status = initial; } //------------------------------------------------------------------------ void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist(x, y)); } else { m_closed = get_close_flag(cmd); } } } //------------------------------------------------------------------------ void vcgen_smooth_poly1::rewind(unsigned) { if(m_status == initial) { m_src_vertices.close(m_closed != 0); } m_status = ready; m_src_vertex = 0; } //------------------------------------------------------------------------ void vcgen_smooth_poly1::calculate(const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, const vertex_dist& v3) { double k1 = v0.dist / (v0.dist + v1.dist); double k2 = v1.dist / (v1.dist + v2.dist); double xm1 = v0.x + (v2.x - v0.x) * k1; double ym1 = v0.y + (v2.y - v0.y) * k1; double xm2 = v1.x + (v3.x - v1.x) * k2; double ym2 = v1.y + (v3.y - v1.y) * k2; m_ctrl1_x = v1.x + m_smooth_value * (v2.x - xm1); m_ctrl1_y = v1.y + m_smooth_value * (v2.y - ym1); m_ctrl2_x = v2.x + m_smooth_value * (v1.x - xm2); m_ctrl2_y = v2.y + m_smooth_value * (v1.y - ym2); } //------------------------------------------------------------------------ unsigned vcgen_smooth_poly1::vertex(double* x, double* y) { unsigned cmd = path_cmd_line_to; while(!is_stop(cmd)) { switch(m_status) { case initial: rewind(0); case ready: if(m_src_vertices.size() < 2) { cmd = path_cmd_stop; break; } if(m_src_vertices.size() == 2) { *x = m_src_vertices[m_src_vertex].x; *y = m_src_vertices[m_src_vertex].y; m_src_vertex++; if(m_src_vertex == 1) return path_cmd_move_to; if(m_src_vertex == 2) return path_cmd_line_to; cmd = path_cmd_stop; break; } cmd = path_cmd_move_to; m_status = polygon; m_src_vertex = 0; case polygon: if(m_closed) { if(m_src_vertex >= m_src_vertices.size()) { *x = m_src_vertices[0].x; *y = m_src_vertices[0].y; m_status = end_poly; return path_cmd_curve4; } } else { if(m_src_vertex >= m_src_vertices.size() - 1) { *x = m_src_vertices[m_src_vertices.size() - 1].x; *y = m_src_vertices[m_src_vertices.size() - 1].y; m_status = end_poly; return path_cmd_curve3; } } calculate(m_src_vertices.prev(m_src_vertex), m_src_vertices.curr(m_src_vertex), m_src_vertices.next(m_src_vertex), m_src_vertices.next(m_src_vertex + 1)); *x = m_src_vertices[m_src_vertex].x; *y = m_src_vertices[m_src_vertex].y; m_src_vertex++; if(m_closed) { m_status = ctrl1; return ((m_src_vertex == 1) ? path_cmd_move_to : path_cmd_curve4); } else { if(m_src_vertex == 1) { m_status = ctrl_b; return path_cmd_move_to; } if(m_src_vertex >= m_src_vertices.size() - 1) { m_status = ctrl_e; return path_cmd_curve3; } m_status = ctrl1; return path_cmd_curve4; } break; case ctrl_b: *x = m_ctrl2_x; *y = m_ctrl2_y; m_status = polygon; return path_cmd_curve3; case ctrl_e: *x = m_ctrl1_x; *y = m_ctrl1_y; m_status = polygon; return path_cmd_curve3; case ctrl1: *x = m_ctrl1_x; *y = m_ctrl1_y; m_status = ctrl2; return path_cmd_curve4; case ctrl2: *x = m_ctrl2_x; *y = m_ctrl2_y; m_status = polygon; return path_cmd_curve4; case end_poly: m_status = stop; return path_cmd_end_poly | m_closed; case stop: return path_cmd_stop; } } return cmd; } } �����������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/autogen.sh��������������������������������������������������������0000644�0024617�0000144�00000000446�12261257215�020634� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# autogen.sh # # invoke the auto* tools to create the configureation system # build aclocal.m4 aclocal # build the configure script autoconf # set up libtool libtoolize --force # invoke automake automake --foreign --add-missing # and finally invoke our new configure ./configure $* # end ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_bspline.cpp���������������������������������������������������0000644�0024617�0000144�00000017324�12261257215�021617� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class bspline // //---------------------------------------------------------------------------- #include "../include/agg_bspline.h" namespace mapserver { //------------------------------------------------------------------------ bspline::bspline() : m_max(0), m_num(0), m_x(0), m_y(0), m_last_idx(-1) { } //------------------------------------------------------------------------ bspline::bspline(int num) : m_max(0), m_num(0), m_x(0), m_y(0), m_last_idx(-1) { init(num); } //------------------------------------------------------------------------ bspline::bspline(int num, const double* x, const double* y) : m_max(0), m_num(0), m_x(0), m_y(0), m_last_idx(-1) { init(num, x, y); } //------------------------------------------------------------------------ void bspline::init(int max) { if(max > 2 && max > m_max) { m_am.resize(max * 3); m_max = max; m_x = &m_am[m_max]; m_y = &m_am[m_max * 2]; } m_num = 0; m_last_idx = -1; } //------------------------------------------------------------------------ void bspline::add_point(double x, double y) { if(m_num < m_max) { m_x[m_num] = x; m_y[m_num] = y; ++m_num; } } //------------------------------------------------------------------------ void bspline::prepare() { if(m_num > 2) { int i, k, n1; double* temp; double* r; double* s; double h, p, d, f, e; for(k = 0; k < m_num; k++) { m_am[k] = 0.0; } n1 = 3 * m_num; pod_array<double> al(n1); temp = &al[0]; for(k = 0; k < n1; k++) { temp[k] = 0.0; } r = temp + m_num; s = temp + m_num * 2; n1 = m_num - 1; d = m_x[1] - m_x[0]; e = (m_y[1] - m_y[0]) / d; for(k = 1; k < n1; k++) { h = d; d = m_x[k + 1] - m_x[k]; f = e; e = (m_y[k + 1] - m_y[k]) / d; al[k] = d / (d + h); r[k] = 1.0 - al[k]; s[k] = 6.0 * (e - f) / (h + d); } for(k = 1; k < n1; k++) { p = 1.0 / (r[k] * al[k - 1] + 2.0); al[k] *= -p; s[k] = (s[k] - r[k] * s[k - 1]) * p; } m_am[n1] = 0.0; al[n1 - 1] = s[n1 - 1]; m_am[n1 - 1] = al[n1 - 1]; for(k = n1 - 2, i = 0; i < m_num - 2; i++, k--) { al[k] = al[k] * al[k + 1] + s[k]; m_am[k] = al[k]; } } m_last_idx = -1; } //------------------------------------------------------------------------ void bspline::init(int num, const double* x, const double* y) { if(num > 2) { init(num); int i; for(i = 0; i < num; i++) { add_point(*x++, *y++); } prepare(); } m_last_idx = -1; } //------------------------------------------------------------------------ void bspline::bsearch(int n, const double *x, double x0, int *i) { int j = n - 1; int k; for(*i = 0; (j - *i) > 1; ) { if(x0 < x[k = (*i + j) >> 1]) j = k; else *i = k; } } //------------------------------------------------------------------------ double bspline::interpolation(double x, int i) const { int j = i + 1; double d = m_x[i] - m_x[j]; double h = x - m_x[j]; double r = m_x[i] - x; double p = d * d / 6.0; return (m_am[j] * r * r * r + m_am[i] * h * h * h) / 6.0 / d + ((m_y[j] - m_am[j] * p) * r + (m_y[i] - m_am[i] * p) * h) / d; } //------------------------------------------------------------------------ double bspline::extrapolation_left(double x) const { double d = m_x[1] - m_x[0]; return (-d * m_am[1] / 6 + (m_y[1] - m_y[0]) / d) * (x - m_x[0]) + m_y[0]; } //------------------------------------------------------------------------ double bspline::extrapolation_right(double x) const { double d = m_x[m_num - 1] - m_x[m_num - 2]; return (d * m_am[m_num - 2] / 6 + (m_y[m_num - 1] - m_y[m_num - 2]) / d) * (x - m_x[m_num - 1]) + m_y[m_num - 1]; } //------------------------------------------------------------------------ double bspline::get(double x) const { if(m_num > 2) { int i; // Extrapolation on the left if(x < m_x[0]) return extrapolation_left(x); // Extrapolation on the right if(x >= m_x[m_num - 1]) return extrapolation_right(x); // Interpolation bsearch(m_num, m_x, x, &i); return interpolation(x, i); } return 0.0; } //------------------------------------------------------------------------ double bspline::get_stateful(double x) const { if(m_num > 2) { // Extrapolation on the left if(x < m_x[0]) return extrapolation_left(x); // Extrapolation on the right if(x >= m_x[m_num - 1]) return extrapolation_right(x); if(m_last_idx >= 0) { // Check if x is not in current range if(x < m_x[m_last_idx] || x > m_x[m_last_idx + 1]) { // Check if x between next points (most probably) if(m_last_idx < m_num - 2 && x >= m_x[m_last_idx + 1] && x <= m_x[m_last_idx + 2]) { ++m_last_idx; } else if(m_last_idx > 0 && x >= m_x[m_last_idx - 1] && x <= m_x[m_last_idx]) { // x is between pevious points --m_last_idx; } else { // Else perform full search bsearch(m_num, m_x, x, &m_last_idx); } } return interpolation(x, m_last_idx); } else { // Interpolation bsearch(m_num, m_x, x, &m_last_idx); return interpolation(x, m_last_idx); } } return 0.0; } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_svg_path_tokenizer.cpp����������������������������������������0000644�0024617�0000144�00000010326�12261257215�024063� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG path tokenizer. // //---------------------------------------------------------------------------- #include <string.h> #include <stdlib.h> #include <stdio.h> #include "agg_svg_exception.h" #include "agg_svg_path_tokenizer.h" namespace mapserver { namespace svg { //------------------------------------------------------------------------ const char path_tokenizer::s_commands[] = "+-MmZzLlHhVvCcSsQqTtAaFfPp"; const char path_tokenizer::s_numeric[] = ".Ee0123456789"; const char path_tokenizer::s_separators[] = " ,\t\n\r"; //------------------------------------------------------------------------ path_tokenizer::path_tokenizer() : m_path(0), m_last_number(0.0), m_last_command(0) { init_char_mask(m_commands_mask, s_commands); init_char_mask(m_numeric_mask, s_numeric); init_char_mask(m_separators_mask, s_separators); } //------------------------------------------------------------------------ void path_tokenizer::set_path_str(const char* str) { m_path = str; m_last_command = 0; m_last_number = 0.0; } //------------------------------------------------------------------------ void path_tokenizer::init_char_mask(char* mask, const char* char_set) { memset(mask, 0, 256/8); while(*char_set) { unsigned c = unsigned(*char_set++) & 0xFF; mask[c >> 3] |= 1 << (c & 7); } } //------------------------------------------------------------------------ bool path_tokenizer::next() { if(m_path == 0) return false; // Skip all white spaces and other garbage while(*m_path && !is_command(*m_path) && !is_numeric(*m_path)) { if(!is_separator(*m_path)) { char buf[100]; sprintf(buf, "path_tokenizer::next : Invalid Character %c", *m_path); throw exception(buf); } m_path++; } if(*m_path == 0) return false; if(is_command(*m_path)) { // Check if the command is a numeric sign character if(*m_path == '-' || *m_path == '+') { return parse_number(); } m_last_command = *m_path++; while(*m_path && is_separator(*m_path)) m_path++; if(*m_path == 0) return true; } return parse_number(); } //------------------------------------------------------------------------ double path_tokenizer::next(char cmd) { if(!next()) throw exception("parse_path: Unexpected end of path"); if(last_command() != cmd) { char buf[100]; sprintf(buf, "parse_path: Command %c: bad or missing parameters", cmd); throw exception(buf); } return last_number(); } //------------------------------------------------------------------------ bool path_tokenizer::parse_number() { char buf[256]; // Should be enough for any number char* buf_ptr = buf; // Copy all sign characters while((buf_ptr < buf+255 && *m_path == '-') || *m_path == '+') { *buf_ptr++ = *m_path++; } // Copy all numeric characters while(buf_ptr < buf+255 && is_numeric(*m_path)) { *buf_ptr++ = *m_path++; } *buf_ptr = 0; m_last_number = atof(buf); return true; } } //namespace svg } //namespace mapserver ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_line_aa_basics.cpp��������������������������������������������0000644�0024617�0000144�00000005777�12261257215�023110� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_line_aa_basics.h" namespace mapserver { //------------------------------------------------------------------------- // The number of the octant is determined as a 3-bit value as follows: // bit 0 = vertical flag // bit 1 = sx < 0 // bit 2 = sy < 0 // // [N] shows the number of the orthogonal quadrant // <M> shows the number of the diagonal quadrant // <1> // [1] | [0] // . (3)011 | 001(1) . // . | . // . | . // . | . // (2)010 .|. 000(0) // <2> ----------.+.----------- <0> // (6)110 . | . 100(4) // . | . // . | . // . | . // (7)111 | 101(5) // [2] | [3] // <3> // 0,1,2,3,4,5,6,7 const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; //------------------------------------------------------------------------- void bisectrix(const line_parameters& l1, const line_parameters& l2, int* x, int* y) { double k = double(l2.len) / double(l1.len); double tx = l2.x2 - (l2.x1 - l1.x1) * k; double ty = l2.y2 - (l2.y1 - l1.y1) * k; //All bisectrices must be on the right of the line //If the next point is on the left (l1 => l2.2) //then the bisectix should be rotated by 180 degrees. if(double(l2.x2 - l2.x1) * double(l2.y1 - l1.y1) < double(l2.y2 - l2.y1) * double(l2.x1 - l1.x1) + 100.0) { tx -= (tx - l2.x1) * 2.0; ty -= (ty - l2.y1) * 2.0; } // Check if the bisectrix is too short double dx = tx - l2.x1; double dy = ty - l2.y1; if((int)sqrt(dx * dx + dy * dy) < line_subpixel_scale) { *x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1; *y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1; return; } *x = iround(tx); *y = iround(ty); } } �mapserver-6.4.1/renderers/agg/src/copying�����������������������������������������������������������0000644�0024617�0000144�00000000673�12261257215�020233� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������The Anti-Grain Geometry Project A high quality rendering engine for C++ http://antigrain.com Anti-Grain Geometry - Version 2.4 Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. ���������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_trans_single_path.cpp�����������������������������������������0000644�0024617�0000144�00000014717�12261257215�023672� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_math.h" #include "../include/agg_vertex_sequence.h" #include "../include/agg_trans_single_path.h" namespace mapserver { //------------------------------------------------------------------------ trans_single_path::trans_single_path() : m_base_length(0.0), m_kindex(0.0), m_status(initial), m_preserve_x_scale(true) { } //------------------------------------------------------------------------ void trans_single_path::reset() { m_src_vertices.remove_all(); m_kindex = 0.0; m_status = initial; } //------------------------------------------------------------------------ void trans_single_path::move_to(double x, double y) { if(m_status == initial) { m_src_vertices.modify_last(vertex_dist(x, y)); m_status = making_path; } else { line_to(x, y); } } //------------------------------------------------------------------------ void trans_single_path::line_to(double x, double y) { if(m_status == making_path) { m_src_vertices.add(vertex_dist(x, y)); } } //------------------------------------------------------------------------ void trans_single_path::finalize_path() { if(m_status == making_path && m_src_vertices.size() > 1) { unsigned i; double dist; double d; m_src_vertices.close(false); if(m_src_vertices.size() > 2) { if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 < m_src_vertices[m_src_vertices.size() - 3].dist) { d = m_src_vertices[m_src_vertices.size() - 3].dist + m_src_vertices[m_src_vertices.size() - 2].dist; m_src_vertices[m_src_vertices.size() - 2] = m_src_vertices[m_src_vertices.size() - 1]; m_src_vertices.remove_last(); m_src_vertices[m_src_vertices.size() - 2].dist = d; } } dist = 0.0; for(i = 0; i < m_src_vertices.size(); i++) { vertex_dist& v = m_src_vertices[i]; double d = v.dist; v.dist = dist; dist += d; } m_kindex = (m_src_vertices.size() - 1) / dist; m_status = ready; } } //------------------------------------------------------------------------ double trans_single_path::total_length() const { if(m_base_length >= 1e-10) return m_base_length; return (m_status == ready) ? m_src_vertices[m_src_vertices.size() - 1].dist : 0.0; } //------------------------------------------------------------------------ void trans_single_path::transform(double *x, double *y) const { if(m_status == ready) { if(m_base_length > 1e-10) { *x *= m_src_vertices[m_src_vertices.size() - 1].dist / m_base_length; } double x1 = 0.0; double y1 = 0.0; double dx = 1.0; double dy = 1.0; double d = 0.0; double dd = 1.0; if(*x < 0.0) { // Extrapolation on the left //-------------------------- x1 = m_src_vertices[0].x; y1 = m_src_vertices[0].y; dx = m_src_vertices[1].x - x1; dy = m_src_vertices[1].y - y1; dd = m_src_vertices[1].dist - m_src_vertices[0].dist; d = *x; } else if(*x > m_src_vertices[m_src_vertices.size() - 1].dist) { // Extrapolation on the right //-------------------------- unsigned i = m_src_vertices.size() - 2; unsigned j = m_src_vertices.size() - 1; x1 = m_src_vertices[j].x; y1 = m_src_vertices[j].y; dx = x1 - m_src_vertices[i].x; dy = y1 - m_src_vertices[i].y; dd = m_src_vertices[j].dist - m_src_vertices[i].dist; d = *x - m_src_vertices[j].dist; } else { // Interpolation //-------------------------- unsigned i = 0; unsigned j = m_src_vertices.size() - 1; if(m_preserve_x_scale) { unsigned k; for(i = 0; (j - i) > 1; ) { if(*x < m_src_vertices[k = (i + j) >> 1].dist) { j = k; } else { i = k; } } d = m_src_vertices[i].dist; dd = m_src_vertices[j].dist - d; d = *x - d; } else { i = unsigned(*x * m_kindex); j = i + 1; dd = m_src_vertices[j].dist - m_src_vertices[i].dist; d = ((*x * m_kindex) - i) * dd; } x1 = m_src_vertices[i].x; y1 = m_src_vertices[i].y; dx = m_src_vertices[j].x - x1; dy = m_src_vertices[j].y - y1; } double x2 = x1 + dx * d / dd; double y2 = y1 + dy * d / dd; *x = x2 - *y * dy / dd; *y = y2 + *y * dx / dd; } } } �������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vcgen_stroke.cpp����������������������������������������������0000644�0024617�0000144�00000015515�12261257215�022654� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Stroke generator // //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_vcgen_stroke.h" #include "../include/agg_shorten_path.h" namespace mapserver { //------------------------------------------------------------------------ vcgen_stroke::vcgen_stroke() : m_stroker(), m_src_vertices(), m_out_vertices(), m_shorten(0.0), m_closed(0), m_status(initial), m_src_vertex(0), m_out_vertex(0) { } //------------------------------------------------------------------------ void vcgen_stroke::remove_all() { m_src_vertices.remove_all(); m_closed = 0; m_status = initial; } //------------------------------------------------------------------------ void vcgen_stroke::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist(x, y)); } else { m_closed = get_close_flag(cmd); } } } //------------------------------------------------------------------------ void vcgen_stroke::rewind(unsigned) { if(m_status == initial) { m_src_vertices.close(m_closed != 0); shorten_path(m_src_vertices, m_shorten, m_closed); if(m_src_vertices.size() < 3) m_closed = 0; } m_status = ready; m_src_vertex = 0; m_out_vertex = 0; } //------------------------------------------------------------------------ unsigned vcgen_stroke::vertex(double* x, double* y) { unsigned cmd = path_cmd_line_to; while(!is_stop(cmd)) { switch(m_status) { case initial: rewind(0); case ready: if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) { cmd = path_cmd_stop; break; } m_status = m_closed ? outline1 : cap1; cmd = path_cmd_move_to; m_src_vertex = 0; m_out_vertex = 0; break; case cap1: m_stroker.calc_cap(m_out_vertices, m_src_vertices[0], m_src_vertices[1], m_src_vertices[0].dist); m_src_vertex = 1; m_prev_status = outline1; m_status = out_vertices; m_out_vertex = 0; break; case cap2: m_stroker.calc_cap(m_out_vertices, m_src_vertices[m_src_vertices.size() - 1], m_src_vertices[m_src_vertices.size() - 2], m_src_vertices[m_src_vertices.size() - 2].dist); m_prev_status = outline2; m_status = out_vertices; m_out_vertex = 0; break; case outline1: if(m_closed) { if(m_src_vertex >= m_src_vertices.size()) { m_prev_status = close_first; m_status = end_poly1; break; } } else { if(m_src_vertex >= m_src_vertices.size() - 1) { m_status = cap2; break; } } m_stroker.calc_join(m_out_vertices, m_src_vertices.prev(m_src_vertex), m_src_vertices.curr(m_src_vertex), m_src_vertices.next(m_src_vertex), m_src_vertices.prev(m_src_vertex).dist, m_src_vertices.curr(m_src_vertex).dist); ++m_src_vertex; m_prev_status = m_status; m_status = out_vertices; m_out_vertex = 0; break; case close_first: m_status = outline2; cmd = path_cmd_move_to; case outline2: if(m_src_vertex <= unsigned(m_closed == 0)) { m_status = end_poly2; m_prev_status = stop; break; } --m_src_vertex; m_stroker.calc_join(m_out_vertices, m_src_vertices.next(m_src_vertex), m_src_vertices.curr(m_src_vertex), m_src_vertices.prev(m_src_vertex), m_src_vertices.curr(m_src_vertex).dist, m_src_vertices.prev(m_src_vertex).dist); m_prev_status = m_status; m_status = out_vertices; m_out_vertex = 0; break; case out_vertices: if(m_out_vertex >= m_out_vertices.size()) { m_status = m_prev_status; } else { const point_d& c = m_out_vertices[m_out_vertex++]; *x = c.x; *y = c.y; return cmd; } break; case end_poly1: m_status = m_prev_status; return path_cmd_end_poly | path_flags_close | path_flags_ccw; case end_poly2: m_status = m_prev_status; return path_cmd_end_poly | path_flags_close | path_flags_cw; case stop: cmd = path_cmd_stop; break; } } return cmd; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vcgen_markers_term.cpp����������������������������������������0000644�0024617�0000144�00000006365�12261257215�024043� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Terminal markers generator (arrowhead/arrowtail) // //---------------------------------------------------------------------------- #include "../include/agg_vcgen_markers_term.h" namespace mapserver { //------------------------------------------------------------------------ void vcgen_markers_term::remove_all() { m_markers.remove_all(); } //------------------------------------------------------------------------ void vcgen_markers_term::add_vertex(double x, double y, unsigned cmd) { if(is_move_to(cmd)) { if(m_markers.size() & 1) { // Initial state, the first coordinate was added. // If two of more calls of start_vertex() occures // we just modify the last one. m_markers.modify_last(coord_type(x, y)); } else { m_markers.add(coord_type(x, y)); } } else { if(is_vertex(cmd)) { if(m_markers.size() & 1) { // Initial state, the first coordinate was added. // Add three more points, 0,1,1,0 m_markers.add(coord_type(x, y)); m_markers.add(m_markers[m_markers.size() - 1]); m_markers.add(m_markers[m_markers.size() - 3]); } else { if(m_markers.size()) { // Replace two last points: 0,1,1,0 -> 0,1,2,1 m_markers[m_markers.size() - 1] = m_markers[m_markers.size() - 2]; m_markers[m_markers.size() - 2] = coord_type(x, y); } } } } } //------------------------------------------------------------------------ void vcgen_markers_term::rewind(unsigned path_id) { m_curr_id = path_id * 2; m_curr_idx = m_curr_id; } //------------------------------------------------------------------------ unsigned vcgen_markers_term::vertex(double* x, double* y) { if(m_curr_id > 2 || m_curr_idx >= m_markers.size()) { return path_cmd_stop; } const coord_type& c = m_markers[m_curr_idx]; *x = c.x; *y = c.y; if(m_curr_idx & 1) { m_curr_idx += 3; return path_cmd_line_to; } ++m_curr_idx; return path_cmd_move_to; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/clipper.cpp�������������������������������������������������������0000644�0024617�0000144�00000306630�12261257215�021004� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************************* * * * Author : Angus Johnson * * Version : 4.6.3 * * Date : 11 November 2011 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2011 * * * * License: * * Use, modification & distribution is subject to Boost Software License Ver 1. * * http://www.boost.org/LICENSE_1_0.txt * * * * Attributions: * * The code in this library is an extension of Bala Vatti's clipping algorithm: * * "A generic solution to polygon clipping" * * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * * http://portal.acm.org/citation.cfm?id=129906 * * * * Computer graphics and geometric modeling: implementation and algorithms * * By Max K. Agoston * * Springer; 1 edition (January 4, 2005) * * http://books.google.com/books?q=vatti+clipping+agoston * * * * See also: * * "Polygon Offsetting by Computing Winding Numbers" * * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * * September 24-28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ /******************************************************************************* * * * This is a translation of the Delphi Clipper library and the naming style * * used has retained a Delphi flavour. * * * *******************************************************************************/ #include "../include/clipper.hpp" #include <cmath> #include <vector> #include <algorithm> #include <stdexcept> #include <cstring> #include <cstdlib> #include <ostream> namespace ClipperLib { static long64 const loRange = 1518500249; //sqrt(2^63 -1)/2 static long64 const hiRange = 6521908912666391106LL; //sqrt(2^127 -1)/2 static double const pi = 3.141592653589793238; enum Direction { dRightToLeft, dLeftToRight }; enum RangeTest { rtLo, rtHi, rtError }; #define HORIZONTAL (-1.0E+40) #define TOLERANCE (1.0e-20) #define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) #define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) inline long64 Abs(long64 val) { if (val < 0) return -val; else return val; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Int128 class (enables safe math on signed 64bit integers) // eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 // Int128 val2((long64)9223372036854775807); // Int128 val3 = val1 * val2; // val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) //------------------------------------------------------------------------------ class Int128 { public: Int128(long64 _lo = 0) { hi = 0; if (_lo < 0) { lo = -_lo; Negate(*this); } else lo = _lo; } Int128(const Int128 &val): hi(val.hi), lo(val.lo){} long64 operator = (const long64 &val) { hi = 0; lo = Abs(val); if (val < 0) Negate(*this); return val; } bool operator == (const Int128 &val) const {return (hi == val.hi && lo == val.lo);} bool operator != (const Int128 &val) const { return !(*this == val);} bool operator > (const Int128 &val) const { if (hi > val.hi) return true; else if (hi < val.hi) return false; else return ulong64(lo) > ulong64(val.lo); } bool operator < (const Int128 &val) const { if (hi < val.hi) return true; else if (hi > val.hi) return false; else return ulong64(lo) < ulong64(val.lo); } Int128& operator += (const Int128 &rhs) { hi += rhs.hi; lo += rhs.lo; if (ulong64(lo) < ulong64(rhs.lo)) hi++; return *this; } Int128 operator + (const Int128 &rhs) const { Int128 result(*this); result+= rhs; return result; } Int128& operator -= (const Int128 &rhs) { Int128 tmp(rhs); Negate(tmp); *this += tmp; return *this; } Int128 operator - (const Int128 &rhs) const { Int128 result(*this); result-= rhs; return result; } Int128 operator * (const Int128 &rhs) const { if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) throw "Int128 operator*: overflow error"; bool negate = (hi < 0) != (rhs.hi < 0); Int128 tmp(*this); if (tmp.hi < 0) Negate(tmp); ulong64 int1Hi = ulong64(tmp.lo) >> 32; ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); tmp = rhs; if (tmp.hi < 0) Negate(tmp); ulong64 int2Hi = ulong64(tmp.lo) >> 32; ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); //nb: see comments in clipper.pas ulong64 a = int1Hi * int2Hi; ulong64 b = int1Lo * int2Lo; ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; tmp.hi = long64(a + (c >> 32)); tmp.lo = long64(c << 32); tmp.lo += long64(b); if (ulong64(tmp.lo) < b) tmp.hi++; if (negate) Negate(tmp); return tmp; } Int128 operator/ (const Int128 &rhs) const { if (rhs.lo == 0 && rhs.hi == 0) throw "Int128 operator/: divide by zero"; bool negate = (rhs.hi < 0) != (hi < 0); Int128 result(*this), denom(rhs); if (result.hi < 0) Negate(result); if (denom.hi < 0) Negate(denom); if (denom > result) return Int128(0); //result is only a fraction of 1 Negate(denom); Int128 p(0); for (int i = 0; i < 128; ++i) { p.hi = p.hi << 1; if (p.lo < 0) p.hi++; p.lo = long64(p.lo) << 1; if (result.hi < 0) p.lo++; result.hi = result.hi << 1; if (result.lo < 0) result.hi++; result.lo = long64(result.lo) << 1; Int128 p2(p); p += denom; if (p.hi < 0) p = p2; else result.lo++; } if (negate) Negate(result); return result; } double AsDouble() const { const double shift64 = 18446744073709551616.0; //2^64 const double bit64 = 9223372036854775808.0; if (hi < 0) { Int128 tmp(*this); Negate(tmp); if (tmp.lo < 0) return (double)tmp.lo - bit64 - tmp.hi * shift64; else return -(double)tmp.lo - tmp.hi * shift64; } else if (lo < 0) return -(double)lo + bit64 + hi * shift64; else return (double)lo + (double)hi * shift64; } //for bug testing ... std::string AsString() const { std::string result; unsigned char r = 0; Int128 tmp(0), val(*this); if (hi < 0) Negate(val); result.resize(50); std::string::size_type i = result.size() -1; while (val.hi != 0 || val.lo != 0) { Div10(val, tmp, r); result[i--] = char('0' + r); val = tmp; } if (hi < 0) result[i--] = '-'; result.erase(0,i+1); if (result.size() == 0) result = "0"; return result; } private: long64 hi; long64 lo; static void Negate(Int128 &val) { if (val.lo == 0) { if( val.hi == 0) return; val.lo = ~val.lo; val.hi = ~val.hi +1; } else { val.lo = ~val.lo +1; val.hi = ~val.hi; } } //debugging only ... void Div10(const Int128 val, Int128& result, unsigned char & remainder) const { remainder = 0; result = 0; for (int i = 63; i >= 0; --i) { if ((val.hi & ((long64)1 << i)) != 0) remainder = char((remainder * 2) + 1); else remainder *= char(2); if (remainder >= 10) { result.hi += ((long64)1 << i); remainder -= char(10); } } for (int i = 63; i >= 0; --i) { if ((val.lo & ((long64)1 << i)) != 0) remainder = char((remainder * 2) + 1); else remainder *= char(2); if (remainder >= 10) { result.lo += ((long64)1 << i); remainder -= char(10); } } } }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ RangeTest TestRange(const Polygon &pts) { RangeTest result = rtLo; for (Polygon::size_type i = 0; i < pts.size(); ++i) { if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) return rtError; else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) result = rtHi; } return result; } //------------------------------------------------------------------------------ bool Orientation(const Polygon &poly) { int highI = (int)poly.size() -1; if (highI < 2) return false; bool UseFullInt64Range = false; int j = 0, jplus, jminus; for (int i = 0; i <= highI; ++i) { if (Abs(poly[i].X) > hiRange || Abs(poly[i].Y) > hiRange) throw "Coordinate exceeds range bounds."; if (Abs(poly[i].X) > loRange || Abs(poly[i].Y) > loRange) UseFullInt64Range = true; if (poly[i].Y < poly[j].Y) continue; if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; }; if (j == highI) jplus = 0; else jplus = j +1; if (j == 0) jminus = highI; else jminus = j -1; IntPoint vec1, vec2; //get cross product of vectors of the edges adjacent to highest point ... vec1.X = poly[j].X - poly[jminus].X; vec1.Y = poly[j].Y - poly[jminus].Y; vec2.X = poly[jplus].X - poly[j].X; vec2.Y = poly[jplus].Y - poly[j].Y; if (UseFullInt64Range) { Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - Int128(vec2.X) * Int128(vec1.Y); return cross > 0; } else { return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; } } //------------------------------------------------------------------------------ bool Orientation(OutRec *outRec, bool UseFullInt64Range) { OutPt *opBottom = outRec->pts, *op = outRec->pts->next; while (op != outRec->pts) { if (op->pt.Y >= opBottom->pt.Y) { if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) opBottom = op; } op = op->next; } IntPoint vec1, vec2; vec1.X = op->pt.X - op->prev->pt.X; vec1.Y = op->pt.Y - op->prev->pt.Y; vec2.X = op->next->pt.X - op->pt.X; vec2.Y = op->next->pt.Y - op->pt.Y; if (UseFullInt64Range) { Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - Int128(vec2.X) * Int128(vec1.Y); return cross > 0; } else { return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; } } //------------------------------------------------------------------------------ inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) { return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); } //------------------------------------------------------------------------------ double Area(const Polygon &poly) { int highI = (int)poly.size() -1; if (highI < 2) return 0; bool UseFullInt64Range; RangeTest rt = TestRange(poly); switch (rt) { case rtLo: UseFullInt64Range = false; break; case rtHi: UseFullInt64Range = true; break; default: throw "Coordinate exceeds range bounds."; } if (UseFullInt64Range) { Int128 a(0); a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - Int128(poly[0].X) * Int128(poly[highI].Y); for (int i = 0; i < highI; ++i) a += Int128(poly[i].X) * Int128(poly[i+1].Y) - Int128(poly[i+1].X) * Int128(poly[i].Y); return a.AsDouble() / 2; } else { double a; a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; for (int i = 0; i < highI; ++i) a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; return a/2; } } //------------------------------------------------------------------------------ bool PointIsVertex(const IntPoint &pt, OutPt *pp) { OutPt *pp2 = pp; do { if (PointsEqual(pp2->pt, pt)) return true; pp2 = pp2->next; } while (pp2 != pp); return false; } //------------------------------------------------------------------------------ bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) { OutPt *pp2 = pp; bool result = false; if (UseFullInt64Range) { do { if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) result = !result; pp2 = pp2->next; } while (pp2 != pp); } else { do { if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; pp2 = pp2->next; } while (pp2 != pp); } return result; } //------------------------------------------------------------------------------ bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) { if (e1.ybot == e1.ytop) return (e2.ybot == e2.ytop); else if (e1.xbot == e1.xtop) return (e2.xbot == e2.xtop); else if (UseFullInt64Range) return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); } //------------------------------------------------------------------------------ bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, bool UseFullInt64Range) { if (pt1.Y == pt2.Y) return (pt2.Y == pt3.Y); else if (pt1.X == pt2.X) return (pt2.X == pt3.X); else if (UseFullInt64Range) return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); } //------------------------------------------------------------------------------ bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) { if (pt1.Y == pt2.Y) return (pt3.Y == pt4.Y); else if (pt1.X == pt2.X) return (pt3.X == pt4.X); else if (UseFullInt64Range) return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); } //------------------------------------------------------------------------------ double GetDx(const IntPoint pt1, const IntPoint pt2) { if (pt1.Y == pt2.Y) return HORIZONTAL; else return (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); } //--------------------------------------------------------------------------- void SetDx(TEdge &e) { if (e.ybot == e.ytop) e.dx = HORIZONTAL; else e.dx = (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); } //--------------------------------------------------------------------------- void SwapSides(TEdge &edge1, TEdge &edge2) { EdgeSide side = edge1.side; edge1.side = edge2.side; edge2.side = side; } //------------------------------------------------------------------------------ void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) { int outIdx = edge1.outIdx; edge1.outIdx = edge2.outIdx; edge2.outIdx = outIdx; } //------------------------------------------------------------------------------ inline long64 Round(double val) { if ((val < 0)) return static_cast<long64>(val - 0.5); else return static_cast<long64>(val + 0.5); } //------------------------------------------------------------------------------ long64 TopX(TEdge &edge, const long64 currentY) { if( currentY == edge.ytop ) return edge.xtop; return edge.xbot + Round(edge.dx *(currentY - edge.ybot)); } //------------------------------------------------------------------------------ long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) { //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y if (currentY >= pt1.Y) return pt1.X; else if (currentY == pt2.Y) return pt2.X; else if (pt1.X == pt2.X) return pt1.X; else { double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); return Round(pt1.X + (currentY - pt1.Y) *q); } } //------------------------------------------------------------------------------ bool IntersectPoint(TEdge &edge1, TEdge &edge2, IntPoint &ip, bool UseFullInt64Range) { double b1, b2; if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; else if (NEAR_ZERO(edge1.dx)) { ip.X = edge1.xbot; if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) { ip.Y = edge2.ybot; } else { b2 = edge2.ybot - (edge2.xbot/edge2.dx); ip.Y = Round(ip.X/edge2.dx + b2); } } else if (NEAR_ZERO(edge2.dx)) { ip.X = edge2.xbot; if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) { ip.Y = edge1.ybot; } else { b1 = edge1.ybot - (edge1.xbot/edge1.dx); ip.Y = Round(ip.X/edge1.dx + b1); } } else { b1 = edge1.xbot - edge1.ybot * edge1.dx; b2 = edge2.xbot - edge2.ybot * edge2.dx; b2 = (b2-b1)/(edge1.dx - edge2.dx); ip.Y = Round(b2); ip.X = Round(edge1.dx * b2 + b1); } return //can be *so close* to the top of one edge that the rounded Y equals one ytop ... (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || (ip.Y > edge1.ytop && ip.Y > edge2.ytop); } //------------------------------------------------------------------------------ void ReversePolyPtLinks(OutPt &pp) { OutPt *pp1, *pp2; pp1 = &pp; do { pp2 = pp1->next; pp1->next = pp1->prev; pp1->prev = pp2; pp1 = pp2; } while( pp1 != &pp ); } //------------------------------------------------------------------------------ void DisposeOutPts(OutPt*& pp) { if (pp == 0) return; pp->prev->next = 0; while( pp ) { OutPt *tmpPp = pp; pp = pp->next; delete tmpPp ; } } //------------------------------------------------------------------------------ void InitEdge(TEdge *e, TEdge *eNext, TEdge *ePrev, const IntPoint &pt, PolyType polyType) { std::memset( e, 0, sizeof( TEdge )); e->next = eNext; e->prev = ePrev; e->xcurr = pt.X; e->ycurr = pt.Y; if (e->ycurr >= e->next->ycurr) { e->xbot = e->xcurr; e->ybot = e->ycurr; e->xtop = e->next->xcurr; e->ytop = e->next->ycurr; e->windDelta = 1; } else { e->xtop = e->xcurr; e->ytop = e->ycurr; e->xbot = e->next->xcurr; e->ybot = e->next->ycurr; e->windDelta = -1; } SetDx(*e); e->polyType = polyType; e->outIdx = -1; } //------------------------------------------------------------------------------ inline void SwapX(TEdge &e) { //swap horizontal edges' top and bottom x's so they follow the natural //progression of the bounds - ie so their xbots will align with the //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] e.xcurr = e.xtop; e.xtop = e.xbot; e.xbot = e.xcurr; } //------------------------------------------------------------------------------ void SwapPoints(IntPoint &pt1, IntPoint &pt2) { IntPoint tmp = pt1; pt1 = pt2; pt2 = tmp; } //------------------------------------------------------------------------------ bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) { //precondition: segments are colinear. if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) { if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; return pt1.X < pt2.X; } else { if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; return pt1.Y > pt2.Y; } } //------------------------------------------------------------------------------ OutPt* PolygonBottom(OutPt* pp) { OutPt* p = pp->next; OutPt* result = pp; while (p != pp) { if (p->pt.Y > result->pt.Y) result = p; else if (p->pt.Y == result->pt.Y && p->pt.X < result->pt.X) result = p; p = p->next; } return result; } //------------------------------------------------------------------------------ bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) { //outPt1 & outPt2 => the overlap segment (if the function returns true) if (!pp) return false; OutPt* pp2 = pp; IntPoint pt1a = pt1, pt2a = pt2; do { if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && SlopesEqual(pt1a, pt2a, pp->pt, true) && GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) return true; pp = pp->next; } while (pp != pp2); return false; } //------------------------------------------------------------------------------ bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3) { if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); } //------------------------------------------------------------------------------ OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) { if (p1 == p2) throw "JoinError"; OutPt* result = new OutPt; result->pt = pt; if (p2 == p1->next) { p1->next = result; p2->prev = result; result->next = p2; result->prev = p1; } else { p2->next = result; p1->prev = result; result->next = p1; result->prev = p2; } return result; } //------------------------------------------------------------------------------ // ClipperBase class methods ... //------------------------------------------------------------------------------ ClipperBase::ClipperBase() //constructor { m_MinimaList = 0; m_CurrentLM = 0; m_UseFullRange = true; } //------------------------------------------------------------------------------ ClipperBase::~ClipperBase() //destructor { Clear(); } //------------------------------------------------------------------------------ bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) { int len = (int)pg.size(); if (len < 3) return false; Polygon p(len); p[0] = pg[0]; int j = 0; long64 maxVal; if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; for (int i = 0; i < len; ++i) { if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) { if (m_UseFullRange) throw "Coordinate exceeds range bounds"; maxVal = hiRange; if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) throw "Coordinate exceeds range bounds"; m_UseFullRange = true; } if (i == 0 || PointsEqual(p[j], pg[i])) continue; else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) { if (PointsEqual(p[j-1], pg[i])) j--; } else j++; p[j] = pg[i]; } if (j < 2) return false; len = j+1; for (;;) { //nb: test for point equality before testing slopes ... if (PointsEqual(p[j], p[0])) j--; else if (PointsEqual(p[0], p[1]) || SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) p[0] = p[j--]; else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) { for (int i = 2; i <= j; ++i) p[i-1] = p[i]; j--; } //exit loop if nothing is changed or there are too few vertices ... if (j == len-1 || j < 2) break; len = j +1; } if (len < 3) return false; //create a new edge array ... TEdge *edges = new TEdge [len]; m_edges.push_back(edges); //convert vertices to a double-linked-list of edges and initialize ... edges[0].xcurr = p[0].X; edges[0].ycurr = p[0].Y; InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); for (int i = len-2; i > 0; --i) InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates //increase downward so the 'highest' edge will have the smallest ytop) ... TEdge *e = &edges[0]; TEdge *eHighest = e; do { e->xcurr = e->xbot; e->ycurr = e->ybot; if (e->ytop < eHighest->ytop) eHighest = e; e = e->next; } while ( e != &edges[0]); //make sure eHighest is positioned so the following loop works safely ... if (eHighest->windDelta > 0) eHighest = eHighest->next; if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; //finally insert each local minima ... e = eHighest; do { e = AddBoundsToLML(e); } while( e != eHighest ); return true; } //------------------------------------------------------------------------------ void ClipperBase::InsertLocalMinima(LocalMinima *newLm) { if( ! m_MinimaList ) { m_MinimaList = newLm; } else if( newLm->Y >= m_MinimaList->Y ) { newLm->next = m_MinimaList; m_MinimaList = newLm; } else { LocalMinima* tmpLm = m_MinimaList; while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) tmpLm = tmpLm->next; newLm->next = tmpLm->next; tmpLm->next = newLm; } } //------------------------------------------------------------------------------ TEdge* ClipperBase::AddBoundsToLML(TEdge *e) { //Starting at the top of one bound we progress to the bottom where there's //a local minima. We then go to the top of the next bound. These two bounds //form the left and right (or right and left) bounds of the local minima. e->nextInLML = 0; e = e->next; for (;;) { if (NEAR_EQUAL(e->dx, HORIZONTAL)) { //nb: proceed through horizontals when approaching from their right, // but break on horizontal minima if approaching from their left. // This ensures 'local minima' are always on the left of horizontals. if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; if (e->xtop != e->prev->xbot) SwapX(*e); e->nextInLML = e->prev; } else if (e->ycurr == e->prev->ycurr) break; else e->nextInLML = e->prev; e = e->next; } //e and e.prev are now at a local minima ... LocalMinima* newLm = new LocalMinima; newLm->next = 0; newLm->Y = e->prev->ybot; if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound { if (e->xbot != e->prev->xbot) SwapX(*e); newLm->leftBound = e->prev; newLm->rightBound = e; } else if (e->dx < e->prev->dx) { newLm->leftBound = e->prev; newLm->rightBound = e; } else { newLm->leftBound = e; newLm->rightBound = e->prev; } newLm->leftBound->side = esLeft; newLm->rightBound->side = esRight; InsertLocalMinima( newLm ); for (;;) { if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; e->nextInLML = e->next; e = e->next; if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); } return e->next; } //------------------------------------------------------------------------------ bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) { bool result = true; for (Polygons::size_type i = 0; i < ppg.size(); ++i) if (AddPolygon(ppg[i], polyType)) result = false; return result; } //------------------------------------------------------------------------------ void ClipperBase::Clear() { DisposeLocalMinimaList(); for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; m_edges.clear(); m_UseFullRange = false; } //------------------------------------------------------------------------------ void ClipperBase::Reset() { m_CurrentLM = m_MinimaList; if( !m_CurrentLM ) return; //ie nothing to process //reset all edges ... LocalMinima* lm = m_MinimaList; while( lm ) { TEdge* e = lm->leftBound; while( e ) { e->xcurr = e->xbot; e->ycurr = e->ybot; e->side = esLeft; e->outIdx = -1; e = e->nextInLML; } e = lm->rightBound; while( e ) { e->xcurr = e->xbot; e->ycurr = e->ybot; e->side = esRight; e->outIdx = -1; e = e->nextInLML; } lm = lm->next; } } //------------------------------------------------------------------------------ void ClipperBase::DisposeLocalMinimaList() { while( m_MinimaList ) { LocalMinima* tmpLm = m_MinimaList->next; delete m_MinimaList; m_MinimaList = tmpLm; } m_CurrentLM = 0; } //------------------------------------------------------------------------------ void ClipperBase::PopLocalMinima() { if( ! m_CurrentLM ) return; m_CurrentLM = m_CurrentLM->next; } //------------------------------------------------------------------------------ IntRect ClipperBase::GetBounds() { IntRect result; LocalMinima* lm = m_MinimaList; if (!lm) { result.left = result.top = result.right = result.bottom = 0; return result; } result.left = lm->leftBound->xbot; result.top = lm->leftBound->ybot; result.right = lm->leftBound->xbot; result.bottom = lm->leftBound->ybot; while (lm) { if (lm->leftBound->ybot > result.bottom) result.bottom = lm->leftBound->ybot; TEdge* e = lm->leftBound; for (;;) { TEdge* bottomE = e; while (e->nextInLML) { if (e->xbot < result.left) result.left = e->xbot; if (e->xbot > result.right) result.right = e->xbot; e = e->nextInLML; } if (e->xbot < result.left) result.left = e->xbot; if (e->xbot > result.right) result.right = e->xbot; if (e->xtop < result.left) result.left = e->xtop; if (e->xtop > result.right) result.right = e->xtop; if (e->ytop < result.top) result.top = e->ytop; if (bottomE == lm->leftBound) e = lm->rightBound; else break; } lm = lm->next; } return result; } //------------------------------------------------------------------------------ // TClipper methods ... //------------------------------------------------------------------------------ Clipper::Clipper() : ClipperBase() //constructor { m_Scanbeam = 0; m_ActiveEdges = 0; m_SortedEdges = 0; m_IntersectNodes = 0; m_ExecuteLocked = false; m_UseFullRange = false; m_ReverseOutput = false; } //------------------------------------------------------------------------------ Clipper::~Clipper() //destructor { Clear(); DisposeScanbeamList(); } //------------------------------------------------------------------------------ void Clipper::Clear() { if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor DisposeAllPolyPts(); ClipperBase::Clear(); } //------------------------------------------------------------------------------ void Clipper::DisposeScanbeamList() { while ( m_Scanbeam ) { Scanbeam* sb2 = m_Scanbeam->next; delete m_Scanbeam; m_Scanbeam = sb2; } } //------------------------------------------------------------------------------ void Clipper::Reset() { ClipperBase::Reset(); m_Scanbeam = 0; m_ActiveEdges = 0; m_SortedEdges = 0; LocalMinima* lm = m_MinimaList; while (lm) { InsertScanbeam(lm->Y); InsertScanbeam(lm->leftBound->ytop); lm = lm->next; } } //------------------------------------------------------------------------------ bool Clipper::Execute(ClipType clipType, Polygons &solution, PolyFillType subjFillType, PolyFillType clipFillType) { if( m_ExecuteLocked ) return false; m_ExecuteLocked = true; solution.resize(0); m_SubjFillType = subjFillType; m_ClipFillType = clipFillType; m_ClipType = clipType; bool succeeded = ExecuteInternal(false); if (succeeded) BuildResult(solution); m_ExecuteLocked = false; return succeeded; } //------------------------------------------------------------------------------ bool Clipper::Execute(ClipType clipType, ExPolygons &solution, PolyFillType subjFillType, PolyFillType clipFillType) { if( m_ExecuteLocked ) return false; m_ExecuteLocked = true; solution.resize(0); m_SubjFillType = subjFillType; m_ClipFillType = clipFillType; m_ClipType = clipType; bool succeeded = ExecuteInternal(true); if (succeeded) BuildResultEx(solution); m_ExecuteLocked = false; return succeeded; } //------------------------------------------------------------------------------ bool PolySort(OutRec *or1, OutRec *or2) { if (or1 == or2) return false; if (!or1->pts || !or2->pts) { if (or1->pts != or2->pts) { if (or1->pts) return true; else return false; } else return false; } int i1, i2; if (or1->isHole) i1 = or1->FirstLeft->idx; else i1 = or1->idx; if (or2->isHole) i2 = or2->FirstLeft->idx; else i2 = or2->idx; int result = i1 - i2; if (result == 0 && (or1->isHole != or2->isHole)) { if (or1->isHole) return false; else return true; } else return result < 0; } //------------------------------------------------------------------------------ OutRec* FindAppendLinkEnd(OutRec *outRec) { while (outRec->AppendLink) outRec = outRec->AppendLink; return outRec; } //------------------------------------------------------------------------------ void Clipper::FixHoleLinkage(OutRec *outRec) { OutRec *tmp; if (outRec->bottomPt) tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; else tmp = outRec->FirstLeft; if (outRec == tmp) throw clipperException("HoleLinkage error"); if (tmp) { if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); if (tmp == outRec) tmp = 0; else if (tmp->isHole) { FixHoleLinkage(tmp); tmp = tmp->FirstLeft; } } outRec->FirstLeft = tmp; if (!tmp) outRec->isHole = false; outRec->AppendLink = 0; } //------------------------------------------------------------------------------ bool Clipper::ExecuteInternal(bool fixHoleLinkages) { bool succeeded; try { Reset(); if (!m_CurrentLM ) return true; long64 botY = PopScanbeam(); do { InsertLocalMinimaIntoAEL(botY); ClearHorzJoins(); ProcessHorizontals(); long64 topY = PopScanbeam(); succeeded = ProcessIntersections(botY, topY); if (!succeeded) break; ProcessEdgesAtTopOfScanbeam(topY); botY = topY; } while( m_Scanbeam ); } catch(...) { succeeded = false; } if (succeeded) { //tidy up output polygons and fix orientations where necessary ... for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { OutRec *outRec = m_PolyOuts[i]; if (!outRec->pts) continue; FixupOutPolygon(*outRec); if (!outRec->pts) continue; if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); if (outRec->isHole == (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) ReversePolyPtLinks(*outRec->pts); } JoinCommonEdges(fixHoleLinkages); if (fixHoleLinkages) std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); } ClearJoins(); ClearHorzJoins(); return succeeded; } //------------------------------------------------------------------------------ void Clipper::InsertScanbeam(const long64 Y) { if( !m_Scanbeam ) { m_Scanbeam = new Scanbeam; m_Scanbeam->next = 0; m_Scanbeam->Y = Y; } else if( Y > m_Scanbeam->Y ) { Scanbeam* newSb = new Scanbeam; newSb->Y = Y; newSb->next = m_Scanbeam; m_Scanbeam = newSb; } else { Scanbeam* sb2 = m_Scanbeam; while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; if( Y == sb2->Y ) return; //ie ignores duplicates Scanbeam* newSb = new Scanbeam; newSb->Y = Y; newSb->next = sb2->next; sb2->next = newSb; } } //------------------------------------------------------------------------------ long64 Clipper::PopScanbeam() { long64 Y = m_Scanbeam->Y; Scanbeam* sb2 = m_Scanbeam; m_Scanbeam = m_Scanbeam->next; delete sb2; return Y; } //------------------------------------------------------------------------------ void Clipper::DisposeAllPolyPts(){ for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) DisposeOutRec(i); m_PolyOuts.clear(); } //------------------------------------------------------------------------------ void Clipper::DisposeOutRec(PolyOutList::size_type index, bool ignorePts) { OutRec *outRec = m_PolyOuts[index]; if (!ignorePts && outRec->pts) DisposeOutPts(outRec->pts); delete outRec; m_PolyOuts[index] = 0; } //------------------------------------------------------------------------------ void Clipper::SetWindingCount(TEdge &edge) { TEdge *e = edge.prevInAEL; //find the edge of the same polytype that immediately preceeds 'edge' in AEL while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; if ( !e ) { edge.windCnt = edge.windDelta; edge.windCnt2 = 0; e = m_ActiveEdges; //ie get ready to calc windCnt2 } else if ( IsEvenOddFillType(edge) ) { //EvenOdd filling ... edge.windCnt = 1; edge.windCnt2 = e->windCnt2; e = e->nextInAEL; //ie get ready to calc windCnt2 } else { //nonZero, Positive or Negative filling ... if ( e->windCnt * e->windDelta < 0 ) { if (Abs(e->windCnt) > 1) { if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; else edge.windCnt = e->windCnt + edge.windDelta; } else edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; } else { if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; else if ( e->windCnt + edge.windDelta == 0 ) edge.windCnt = e->windCnt; else edge.windCnt = e->windCnt + edge.windDelta; } edge.windCnt2 = e->windCnt2; e = e->nextInAEL; //ie get ready to calc windCnt2 } //update windCnt2 ... if ( IsEvenOddAltFillType(edge) ) { //EvenOdd filling ... while ( e != &edge ) { edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; e = e->nextInAEL; } } else { //nonZero, Positive or Negative filling ... while ( e != &edge ) { edge.windCnt2 += e->windDelta; e = e->nextInAEL; } } } //------------------------------------------------------------------------------ bool Clipper::IsEvenOddFillType(const TEdge& edge) const { if (edge.polyType == ptSubject) return m_SubjFillType == pftEvenOdd; else return m_ClipFillType == pftEvenOdd; } //------------------------------------------------------------------------------ bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const { if (edge.polyType == ptSubject) return m_ClipFillType == pftEvenOdd; else return m_SubjFillType == pftEvenOdd; } //------------------------------------------------------------------------------ bool Clipper::IsContributing(const TEdge& edge) const { PolyFillType pft, pft2; if (edge.polyType == ptSubject) { pft = m_SubjFillType; pft2 = m_ClipFillType; } else { pft = m_ClipFillType; pft2 = m_SubjFillType; } switch(pft) { case pftEvenOdd: case pftNonZero: if (Abs(edge.windCnt) != 1) return false; break; case pftPositive: if (edge.windCnt != 1) return false; break; default: //pftNegative if (edge.windCnt != -1) return false; } switch(m_ClipType) { case ctIntersection: switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.windCnt2 != 0); case pftPositive: return (edge.windCnt2 > 0); default: return (edge.windCnt2 < 0); } case ctUnion: switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.windCnt2 == 0); case pftPositive: return (edge.windCnt2 <= 0); default: return (edge.windCnt2 >= 0); } case ctDifference: if (edge.polyType == ptSubject) switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.windCnt2 == 0); case pftPositive: return (edge.windCnt2 <= 0); default: return (edge.windCnt2 >= 0); } else switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.windCnt2 != 0); case pftPositive: return (edge.windCnt2 > 0); default: return (edge.windCnt2 < 0); } default: return true; } } //------------------------------------------------------------------------------ void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) { if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) { AddOutPt( e1, e2, pt ); e2->outIdx = e1->outIdx; e1->side = esLeft; e2->side = esRight; } else { AddOutPt( e2, e1, pt ); e1->outIdx = e2->outIdx; e1->side = esRight; e2->side = esLeft; } } //------------------------------------------------------------------------------ void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) { AddOutPt( e1, 0, pt ); if( e1->outIdx == e2->outIdx ) { e1->outIdx = -1; e2->outIdx = -1; } else AppendPolygon( e1, e2 ); } //------------------------------------------------------------------------------ void Clipper::AddEdgeToSEL(TEdge *edge) { //SEL pointers in PEdge are reused to build a list of horizontal edges. //However, we don't need to worry about order with horizontal edge processing. if( !m_SortedEdges ) { m_SortedEdges = edge; edge->prevInSEL = 0; edge->nextInSEL = 0; } else { edge->nextInSEL = m_SortedEdges; edge->prevInSEL = 0; m_SortedEdges->prevInSEL = edge; m_SortedEdges = edge; } } //------------------------------------------------------------------------------ void Clipper::CopyAELToSEL() { TEdge* e = m_ActiveEdges; m_SortedEdges = e; if (!m_ActiveEdges) return; m_SortedEdges->prevInSEL = 0; e = e->nextInAEL; while ( e ) { e->prevInSEL = e->prevInAEL; e->prevInSEL->nextInSEL = e; e->nextInSEL = 0; e = e->nextInAEL; } } //------------------------------------------------------------------------------ void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) { JoinRec* jr = new JoinRec; if (e1OutIdx >= 0) jr->poly1Idx = e1OutIdx; else jr->poly1Idx = e1->outIdx; jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); jr->pt1b = IntPoint(e1->xtop, e1->ytop); if (e2OutIdx >= 0) jr->poly2Idx = e2OutIdx; else jr->poly2Idx = e2->outIdx; jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); jr->pt2b = IntPoint(e2->xtop, e2->ytop); m_Joins.push_back(jr); } //------------------------------------------------------------------------------ void Clipper::ClearJoins() { for (JoinList::size_type i = 0; i < m_Joins.size(); i++) delete m_Joins[i]; m_Joins.resize(0); } //------------------------------------------------------------------------------ void Clipper::AddHorzJoin(TEdge *e, int idx) { HorzJoinRec* hj = new HorzJoinRec; hj->edge = e; hj->savedIdx = idx; m_HorizJoins.push_back(hj); } //------------------------------------------------------------------------------ void Clipper::ClearHorzJoins() { for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) delete m_HorizJoins[i]; m_HorizJoins.resize(0); } //------------------------------------------------------------------------------ void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) { while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) { TEdge* lb = m_CurrentLM->leftBound; TEdge* rb = m_CurrentLM->rightBound; InsertEdgeIntoAEL( lb ); InsertScanbeam( lb->ytop ); InsertEdgeIntoAEL( rb ); if (IsEvenOddFillType(*lb)) { lb->windDelta = 1; rb->windDelta = 1; } else { rb->windDelta = -lb->windDelta; } SetWindingCount( *lb ); rb->windCnt = lb->windCnt; rb->windCnt2 = lb->windCnt2; if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) { //nb: only rightbounds can have a horizontal bottom edge AddEdgeToSEL( rb ); InsertScanbeam( rb->nextInLML->ytop ); } else InsertScanbeam( rb->ytop ); if( IsContributing(*lb) ) AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); //if output polygons share an edge, they'll need joining later ... if (lb->outIdx >= 0 && lb->prevInAEL && lb->prevInAEL->outIdx >= 0 && lb->prevInAEL->xcurr == lb->xbot && SlopesEqual(*lb, *lb->prevInAEL, m_UseFullRange)) AddJoin(lb, lb->prevInAEL); //if any output polygons share an edge, they'll need joining later ... if (rb->outIdx >= 0) { if (NEAR_EQUAL(rb->dx, HORIZONTAL)) { for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) { IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. HorzJoinRec* hj = m_HorizJoins[i]; //if horizontals rb and hj.edge overlap, flag for joining later ... if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), IntPoint(hj->edge->xtop, hj->edge->ytop), IntPoint(rb->xbot, rb->ybot), IntPoint(rb->xtop, rb->ytop), pt, pt2)) AddJoin(hj->edge, rb, hj->savedIdx); } } } if( lb->nextInAEL != rb ) { if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) AddJoin(rb, rb->prevInAEL); TEdge* e = lb->nextInAEL; IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); while( e != rb ) { if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); //nb: For calculating winding counts etc, IntersectEdges() assumes //that param1 will be to the right of param2 ABOVE the intersection ... IntersectEdges( rb , e , pt , ipNone); //order important here e = e->nextInAEL; } } PopLocalMinima(); } } //------------------------------------------------------------------------------ void Clipper::DeleteFromAEL(TEdge *e) { TEdge* AelPrev = e->prevInAEL; TEdge* AelNext = e->nextInAEL; if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted if( AelPrev ) AelPrev->nextInAEL = AelNext; else m_ActiveEdges = AelNext; if( AelNext ) AelNext->prevInAEL = AelPrev; e->nextInAEL = 0; e->prevInAEL = 0; } //------------------------------------------------------------------------------ void Clipper::DeleteFromSEL(TEdge *e) { TEdge* SelPrev = e->prevInSEL; TEdge* SelNext = e->nextInSEL; if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted if( SelPrev ) SelPrev->nextInSEL = SelNext; else m_SortedEdges = SelNext; if( SelNext ) SelNext->prevInSEL = SelPrev; e->nextInSEL = 0; e->prevInSEL = 0; } //------------------------------------------------------------------------------ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, const IntPoint &pt, IntersectProtects protects) { //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before //e2 in AEL except when e1 is being inserted at the intersection point ... bool e1stops = !(ipLeft & protects) && !e1->nextInLML && e1->xtop == pt.X && e1->ytop == pt.Y; bool e2stops = !(ipRight & protects) && !e2->nextInLML && e2->xtop == pt.X && e2->ytop == pt.Y; bool e1Contributing = ( e1->outIdx >= 0 ); bool e2contributing = ( e2->outIdx >= 0 ); //update winding counts... //assumes that e1 will be to the right of e2 ABOVE the intersection if ( e1->polyType == e2->polyType ) { if ( IsEvenOddFillType( *e1) ) { int oldE1WindCnt = e1->windCnt; e1->windCnt = e2->windCnt; e2->windCnt = oldE1WindCnt; } else { if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; else e1->windCnt += e2->windDelta; if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; else e2->windCnt -= e1->windDelta; } } else { if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; } PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; if (e1->polyType == ptSubject) { e1FillType = m_SubjFillType; e1FillType2 = m_ClipFillType; } else { e1FillType = m_ClipFillType; e1FillType2 = m_SubjFillType; } if (e2->polyType == ptSubject) { e2FillType = m_SubjFillType; e2FillType2 = m_ClipFillType; } else { e2FillType = m_ClipFillType; e2FillType2 = m_SubjFillType; } long64 e1Wc, e2Wc; switch (e1FillType) { case pftPositive: e1Wc = e1->windCnt; break; case pftNegative: e1Wc = -e1->windCnt; break; default: e1Wc = Abs(e1->windCnt); } switch(e2FillType) { case pftPositive: e2Wc = e2->windCnt; break; case pftNegative: e2Wc = -e2->windCnt; break; default: e2Wc = Abs(e2->windCnt); } if ( e1Contributing && e2contributing ) { if ( e1stops || e2stops || (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || (e1->polyType != e2->polyType && m_ClipType != ctXor) ) AddLocalMaxPoly(e1, e2, pt); else DoBothEdges( e1, e2, pt ); } else if ( e1Contributing ) { if ((e2Wc == 0 || e2Wc == 1) && (m_ClipType != ctIntersection || e2->polyType == ptSubject || (e2->windCnt2 != 0))) DoEdge1(e1, e2, pt); } else if ( e2contributing ) { if ((e1Wc == 0 || e1Wc == 1) && (m_ClipType != ctIntersection || e1->polyType == ptSubject || (e1->windCnt2 != 0))) DoEdge2(e1, e2, pt); } else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) { //neither edge is currently contributing ... long64 e1Wc2, e2Wc2; switch (e1FillType2) { case pftPositive: e1Wc2 = e1->windCnt2; break; case pftNegative : e1Wc2 = -e1->windCnt2; break; default: e1Wc2 = Abs(e1->windCnt2); } switch (e2FillType2) { case pftPositive: e2Wc2 = e2->windCnt2; break; case pftNegative: e2Wc2 = -e2->windCnt2; break; default: e2Wc2 = Abs(e2->windCnt2); } if (e1->polyType != e2->polyType) AddLocalMinPoly(e1, e2, pt); else if (e1Wc == 1 && e2Wc == 1) switch( m_ClipType ) { case ctIntersection: if (e1Wc2 > 0 && e2Wc2 > 0) AddLocalMinPoly(e1, e2, pt); break; case ctUnion: if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) AddLocalMinPoly(e1, e2, pt); break; case ctDifference: if ((e1->polyType == ptClip && e2->polyType == ptClip && e1Wc2 > 0 && e2Wc2 > 0) || (e1->polyType == ptSubject && e2->polyType == ptSubject && e1Wc2 <= 0 && e2Wc2 <= 0)) AddLocalMinPoly(e1, e2, pt); break; case ctXor: AddLocalMinPoly(e1, e2, pt); } else SwapSides( *e1, *e2 ); } if( (e1stops != e2stops) && ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) { SwapSides( *e1, *e2 ); SwapPolyIndexes( *e1, *e2 ); } //finally, delete any non-contributing maxima edges ... if( e1stops ) DeleteFromAEL( e1 ); if( e2stops ) DeleteFromAEL( e2 ); } //------------------------------------------------------------------------------ void Clipper::SetHoleState(TEdge *e, OutRec *outRec) { bool isHole = false; TEdge *e2 = e->prevInAEL; while (e2) { if (e2->outIdx >= 0) { isHole = !isHole; if (! outRec->FirstLeft) outRec->FirstLeft = m_PolyOuts[e2->outIdx]; } e2 = e2->prevInAEL; } if (isHole) outRec->isHole = true; } //------------------------------------------------------------------------------ bool GetNextNonDupOutPt(OutPt* pp, OutPt*& next) { next = pp->next; while (next != pp && PointsEqual(pp->pt, next->pt)) next = next->next; return next != pp; } //------------------------------------------------------------------------------ bool GetPrevNonDupOutPt(OutPt* pp, OutPt*& prev) { prev = pp->prev; while (prev != pp && PointsEqual(pp->pt, prev->pt)) prev = prev->prev; return prev != pp; } //------------------------------------------------------------------------------ OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) { //work out which polygon fragment has the correct hole state ... OutPt *outPt1 = outRec1->bottomPt; OutPt *outPt2 = outRec2->bottomPt; if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; else if (outPt1->pt.X < outPt2->pt.X) return outRec1; else if (outPt1->pt.X > outPt2->pt.X) return outRec2; else if (outRec1->bottomE2 == 0) return outRec2; else if (outRec2->bottomE2 == 0) return outRec1; else { long64 y1 = std::max(outRec1->bottomE1->ybot, outRec1->bottomE2->ybot); long64 y2 = std::max(outRec2->bottomE1->ybot, outRec2->bottomE2->ybot); if (y2 == y1 || (y1 > outPt1->pt.Y && y2 > outPt1->pt.Y)) { double dx1 = std::max(outRec1->bottomE1->dx, outRec1->bottomE2->dx); double dx2 = std::max(outRec2->bottomE1->dx, outRec2->bottomE2->dx); if (dx2 > dx1) return outRec2; else return outRec1; } else if (y2 > y1) return outRec2; else return outRec1; } } //------------------------------------------------------------------------------ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) { //get the start and ends of both output polygons ... OutRec *outRec1 = m_PolyOuts[e1->outIdx]; OutRec *outRec2 = m_PolyOuts[e2->outIdx]; OutRec *holeStateRec = GetLowermostRec(outRec1, outRec2); //fixup hole status ... if (holeStateRec == outRec2) outRec1->isHole = outRec2->isHole; else outRec2->isHole = outRec1->isHole; OutPt* p1_lft = outRec1->pts; OutPt* p1_rt = p1_lft->prev; OutPt* p2_lft = outRec2->pts; OutPt* p2_rt = p2_lft->prev; EdgeSide side; //join e2 poly onto e1 poly and delete pointers to e2 ... if( e1->side == esLeft ) { if( e2->side == esLeft ) { //z y x a b c ReversePolyPtLinks(*p2_lft); p2_lft->next = p1_lft; p1_lft->prev = p2_lft; p1_rt->next = p2_rt; p2_rt->prev = p1_rt; outRec1->pts = p2_rt; } else { //x y z a b c p2_rt->next = p1_lft; p1_lft->prev = p2_rt; p2_lft->prev = p1_rt; p1_rt->next = p2_lft; outRec1->pts = p2_lft; } side = esLeft; } else { if( e2->side == esRight ) { //a b c z y x ReversePolyPtLinks( *p2_lft ); p1_rt->next = p2_rt; p2_rt->prev = p1_rt; p2_lft->next = p1_lft; p1_lft->prev = p2_lft; } else { //a b c x y z p1_rt->next = p2_lft; p2_lft->prev = p1_rt; p1_lft->prev = p2_rt; p2_rt->next = p1_lft; } side = esRight; } if (holeStateRec == outRec2) { outRec1->bottomPt = outRec2->bottomPt; outRec1->bottomPt->idx = outRec1->idx; outRec1->bottomE1 = outRec2->bottomE1; outRec1->bottomE2 = outRec2->bottomE2; if (outRec2->FirstLeft != outRec1) outRec1->FirstLeft = outRec2->FirstLeft; } outRec2->pts = 0; outRec2->bottomPt = 0; outRec2->AppendLink = outRec1; int OKIdx = e1->outIdx; int ObsoleteIdx = e2->outIdx; e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly e2->outIdx = -1; TEdge* e = m_ActiveEdges; while( e ) { if( e->outIdx == ObsoleteIdx ) { e->outIdx = OKIdx; e->side = side; break; } e = e->nextInAEL; } for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) { if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; } for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) { if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) m_HorizJoins[i]->savedIdx = OKIdx; } } //------------------------------------------------------------------------------ OutRec* Clipper::CreateOutRec() { OutRec* result = new OutRec; result->isHole = false; result->FirstLeft = 0; result->AppendLink = 0; result->pts = 0; result->bottomPt = 0; return result; } //------------------------------------------------------------------------------ void Clipper::AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt) { bool ToFront = (e->side == esLeft); if( e->outIdx < 0 ) { OutRec *outRec = CreateOutRec(); m_PolyOuts.push_back(outRec); outRec->idx = (int)m_PolyOuts.size()-1; e->outIdx = outRec->idx; OutPt* op = new OutPt; outRec->pts = op; outRec->bottomE1 = e; outRec->bottomE2 = altE; outRec->bottomPt = op; op->pt = pt; op->idx = outRec->idx; op->next = op; op->prev = op; SetHoleState(e, outRec); } else { OutRec *outRec = m_PolyOuts[e->outIdx]; OutPt* op = outRec->pts; if ((ToFront && PointsEqual(pt, op->pt)) || (!ToFront && PointsEqual(pt, op->prev->pt))) return; OutPt* op2 = new OutPt; op2->pt = pt; op2->idx = outRec->idx; if (op2->pt.Y == outRec->bottomPt->pt.Y && op2->pt.X < outRec->bottomPt->pt.X) { outRec->bottomPt = op2; outRec->bottomE1 = e; outRec->bottomE2 = altE; } op2->next = op; op2->prev = op->prev; op2->prev->next = op2; op->prev = op2; if (ToFront) outRec->pts = op2; } } //------------------------------------------------------------------------------ void Clipper::ProcessHorizontals() { TEdge* horzEdge = m_SortedEdges; while( horzEdge ) { DeleteFromSEL( horzEdge ); ProcessHorizontal( horzEdge ); horzEdge = m_SortedEdges; } } //------------------------------------------------------------------------------ bool Clipper::IsTopHorz(const long64 XPos) { TEdge* e = m_SortedEdges; while( e ) { if( ( XPos >= std::min(e->xcurr, e->xtop) ) && ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; e = e->nextInSEL; } return true; } //------------------------------------------------------------------------------ bool IsMinima(TEdge *e) { return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); } //------------------------------------------------------------------------------ bool IsMaxima(TEdge *e, const long64 Y) { return e && e->ytop == Y && !e->nextInLML; } //------------------------------------------------------------------------------ bool IsIntermediate(TEdge *e, const long64 Y) { return e->ytop == Y && e->nextInLML; } //------------------------------------------------------------------------------ TEdge *GetMaximaPair(TEdge *e) { if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) return e->prev; else return e->next; } //------------------------------------------------------------------------------ void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) { if( !edge1->nextInAEL && !edge1->prevInAEL ) return; if( !edge2->nextInAEL && !edge2->prevInAEL ) return; if( edge1->nextInAEL == edge2 ) { TEdge* next = edge2->nextInAEL; if( next ) next->prevInAEL = edge1; TEdge* prev = edge1->prevInAEL; if( prev ) prev->nextInAEL = edge2; edge2->prevInAEL = prev; edge2->nextInAEL = edge1; edge1->prevInAEL = edge2; edge1->nextInAEL = next; } else if( edge2->nextInAEL == edge1 ) { TEdge* next = edge1->nextInAEL; if( next ) next->prevInAEL = edge2; TEdge* prev = edge2->prevInAEL; if( prev ) prev->nextInAEL = edge1; edge1->prevInAEL = prev; edge1->nextInAEL = edge2; edge2->prevInAEL = edge1; edge2->nextInAEL = next; } else { TEdge* next = edge1->nextInAEL; TEdge* prev = edge1->prevInAEL; edge1->nextInAEL = edge2->nextInAEL; if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; edge1->prevInAEL = edge2->prevInAEL; if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; edge2->nextInAEL = next; if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; edge2->prevInAEL = prev; if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; } if( !edge1->prevInAEL ) m_ActiveEdges = edge1; else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; } //------------------------------------------------------------------------------ void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) { if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; if( edge1->nextInSEL == edge2 ) { TEdge* next = edge2->nextInSEL; if( next ) next->prevInSEL = edge1; TEdge* prev = edge1->prevInSEL; if( prev ) prev->nextInSEL = edge2; edge2->prevInSEL = prev; edge2->nextInSEL = edge1; edge1->prevInSEL = edge2; edge1->nextInSEL = next; } else if( edge2->nextInSEL == edge1 ) { TEdge* next = edge1->nextInSEL; if( next ) next->prevInSEL = edge2; TEdge* prev = edge2->prevInSEL; if( prev ) prev->nextInSEL = edge1; edge1->prevInSEL = prev; edge1->nextInSEL = edge2; edge2->prevInSEL = edge1; edge2->nextInSEL = next; } else { TEdge* next = edge1->nextInSEL; TEdge* prev = edge1->prevInSEL; edge1->nextInSEL = edge2->nextInSEL; if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; edge1->prevInSEL = edge2->prevInSEL; if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; edge2->nextInSEL = next; if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; edge2->prevInSEL = prev; if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; } if( !edge1->prevInSEL ) m_SortedEdges = edge1; else if( !edge2->prevInSEL ) m_SortedEdges = edge2; } //------------------------------------------------------------------------------ TEdge* GetNextInAEL(TEdge *e, Direction dir) { if( dir == dLeftToRight ) return e->nextInAEL; else return e->prevInAEL; } //------------------------------------------------------------------------------ void Clipper::ProcessHorizontal(TEdge *horzEdge) { Direction dir; long64 horzLeft, horzRight; if( horzEdge->xcurr < horzEdge->xtop ) { horzLeft = horzEdge->xcurr; horzRight = horzEdge->xtop; dir = dLeftToRight; } else { horzLeft = horzEdge->xtop; horzRight = horzEdge->xcurr; dir = dRightToLeft; } TEdge* eMaxPair; if( horzEdge->nextInLML ) eMaxPair = 0; else eMaxPair = GetMaximaPair(horzEdge); TEdge* e = GetNextInAEL( horzEdge , dir ); while( e ) { TEdge* eNext = GetNextInAEL( e, dir ); if (eMaxPair || ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) { //ok, so far it looks like we're still in range of the horizontal edge if ( e->xcurr == horzEdge->xtop && !eMaxPair ) { if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) { //if output polygons share an edge, they'll need joining later ... if (horzEdge->outIdx >= 0 && e->outIdx >= 0) AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); break; //we've reached the end of the horizontal line } else if (e->dx < horzEdge->nextInLML->dx) //we really have got to the end of the intermediate horz edge so quit. //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. break; } if( e == eMaxPair ) { //horzEdge is evidently a maxima horizontal and we've arrived at its end. if (dir == dLeftToRight) IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); else IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); return; } else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) { //An overlapping horizontal edge. Overlapping horizontal edges are //processed as if layered with the current horizontal edge (horizEdge) //being infinitesimally lower that the next (e). Therfore, we //intersect with e only if e.xcurr is within the bounds of horzEdge ... if( dir == dLeftToRight ) IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); else IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); } else if( dir == dLeftToRight ) { IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); } else { IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); } SwapPositionsInAEL( horzEdge, e ); } else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; e = eNext; } //end while if( horzEdge->nextInLML ) { if( horzEdge->outIdx >= 0 ) AddOutPt( horzEdge, 0, IntPoint(horzEdge->xtop, horzEdge->ytop)); UpdateEdgeIntoAEL( horzEdge ); } else { if ( horzEdge->outIdx >= 0 ) IntersectEdges( horzEdge, eMaxPair, IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); DeleteFromAEL(eMaxPair); DeleteFromAEL(horzEdge); } } //------------------------------------------------------------------------------ void Clipper::UpdateEdgeIntoAEL(TEdge *&e) { if( !e->nextInLML ) throw clipperException("UpdateEdgeIntoAEL: invalid call"); TEdge* AelPrev = e->prevInAEL; TEdge* AelNext = e->nextInAEL; e->nextInLML->outIdx = e->outIdx; if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; else m_ActiveEdges = e->nextInLML; if( AelNext ) AelNext->prevInAEL = e->nextInLML; e->nextInLML->side = e->side; e->nextInLML->windDelta = e->windDelta; e->nextInLML->windCnt = e->windCnt; e->nextInLML->windCnt2 = e->windCnt2; e = e->nextInLML; e->prevInAEL = AelPrev; e->nextInAEL = AelNext; if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); } //------------------------------------------------------------------------------ bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) { if( !m_ActiveEdges ) return true; try { BuildIntersectList(botY, topY); if ( !m_IntersectNodes) return true; if ( FixupIntersections() ) ProcessIntersectList(); else return false; } catch(...) { m_SortedEdges = 0; DisposeIntersectNodes(); throw clipperException("ProcessIntersections error"); } return true; } //------------------------------------------------------------------------------ void Clipper::DisposeIntersectNodes() { while ( m_IntersectNodes ) { IntersectNode* iNode = m_IntersectNodes->next; delete m_IntersectNodes; m_IntersectNodes = iNode; } } //------------------------------------------------------------------------------ void Clipper::BuildIntersectList(const long64 botY, const long64 topY) { if ( !m_ActiveEdges ) return; //prepare for sorting ... TEdge* e = m_ActiveEdges; e->tmpX = TopX( *e, topY ); m_SortedEdges = e; m_SortedEdges->prevInSEL = 0; e = e->nextInAEL; while( e ) { e->prevInSEL = e->prevInAEL; e->prevInSEL->nextInSEL = e; e->nextInSEL = 0; e->tmpX = TopX( *e, topY ); e = e->nextInAEL; } //bubblesort ... bool isModified = true; while( isModified && m_SortedEdges ) { isModified = false; e = m_SortedEdges; while( e->nextInSEL ) { TEdge *eNext = e->nextInSEL; IntPoint pt; if(e->tmpX > eNext->tmpX && IntersectPoint(*e, *eNext, pt, m_UseFullRange)) { if (pt.Y > botY) { pt.Y = botY; pt.X = TopX(*e, pt.Y); } AddIntersectNode( e, eNext, pt ); SwapPositionsInSEL(e, eNext); isModified = true; } else e = eNext; } if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; else break; } m_SortedEdges = 0; } //------------------------------------------------------------------------------ bool Process1Before2(IntersectNode &node1, IntersectNode &node2) { bool result; if (node1.pt.Y == node2.pt.Y) { if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) { result = node2.pt.X > node1.pt.X; if (node2.edge1->dx > 0) return !result; else return result; } else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) { result = node2.pt.X > node1.pt.X; if (node2.edge2->dx > 0) return !result; else return result; } else return node2.pt.X > node1.pt.X; } else return node1.pt.Y > node2.pt.Y; } //------------------------------------------------------------------------------ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) { IntersectNode* newNode = new IntersectNode; newNode->edge1 = e1; newNode->edge2 = e2; newNode->pt = pt; newNode->next = 0; if( !m_IntersectNodes ) m_IntersectNodes = newNode; else if( Process1Before2(*newNode, *m_IntersectNodes) ) { newNode->next = m_IntersectNodes; m_IntersectNodes = newNode; } else { IntersectNode* iNode = m_IntersectNodes; while( iNode->next && Process1Before2(*iNode->next, *newNode) ) iNode = iNode->next; newNode->next = iNode->next; iNode->next = newNode; } } //------------------------------------------------------------------------------ void Clipper::ProcessIntersectList() { while( m_IntersectNodes ) { IntersectNode* iNode = m_IntersectNodes->next; { IntersectEdges( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); } delete m_IntersectNodes; m_IntersectNodes = iNode; } } //------------------------------------------------------------------------------ void Clipper::DoMaxima(TEdge *e, long64 topY) { TEdge* eMaxPair = GetMaximaPair(e); long64 X = e->xtop; TEdge* eNext = e->nextInAEL; while( eNext != eMaxPair ) { if (!eNext) throw clipperException("DoMaxima error"); IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); eNext = eNext->nextInAEL; } if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) { DeleteFromAEL( e ); DeleteFromAEL( eMaxPair ); } else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) { IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); } else throw clipperException("DoMaxima error"); } //------------------------------------------------------------------------------ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) { TEdge* e = m_ActiveEdges; while( e ) { //1. process maxima, treating them as if they're 'bent' horizontal edges, // but exclude maxima with horizontal edges. nb: e can't be a horizontal. if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) { //'e' might be removed from AEL, as may any following edges so ... TEdge* ePrior = e->prevInAEL; DoMaxima(e, topY); if( !ePrior ) e = m_ActiveEdges; else e = ePrior->nextInAEL; } else { //2. promote horizontal edges, otherwise update xcurr and ycurr ... if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) { if (e->outIdx >= 0) { AddOutPt(e, 0, IntPoint(e->xtop, e->ytop)); for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) { IntPoint pt, pt2; HorzJoinRec* hj = m_HorizJoins[i]; if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), IntPoint(hj->edge->xtop, hj->edge->ytop), IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); } AddHorzJoin(e->nextInLML, e->outIdx); } UpdateEdgeIntoAEL(e); AddEdgeToSEL(e); } else { //this just simplifies horizontal processing ... e->xcurr = TopX( *e, topY ); e->ycurr = topY; } e = e->nextInAEL; } } //3. Process horizontals at the top of the scanbeam ... ProcessHorizontals(); //4. Promote intermediate vertices ... e = m_ActiveEdges; while( e ) { if( IsIntermediate( e, topY ) ) { if( e->outIdx >= 0 ) AddOutPt(e, 0, IntPoint(e->xtop,e->ytop)); UpdateEdgeIntoAEL(e); //if output polygons share an edge, they'll need joining later ... if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), IntPoint(e->xbot,e->ybot), IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) { AddOutPt(e->prevInAEL, 0, IntPoint(e->xbot, e->ybot)); AddJoin(e, e->prevInAEL); } else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && e->nextInAEL->ycurr > e->nextInAEL->ytop && e->nextInAEL->ycurr < e->nextInAEL->ybot && e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), IntPoint(e->xbot,e->ybot), IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) { AddOutPt(e->nextInAEL, 0, IntPoint(e->xbot, e->ybot)); AddJoin(e, e->nextInAEL); } } e = e->nextInAEL; } } //------------------------------------------------------------------------------ void Clipper::FixupOutPolygon(OutRec &outRec) { //FixupOutPolygon() - removes duplicate points and simplifies consecutive //parallel edges by removing the middle vertex. OutPt *lastOK = 0; outRec.pts = outRec.bottomPt; OutPt *pp = outRec.bottomPt; for (;;) { if (pp->prev == pp || pp->prev == pp->next ) { DisposeOutPts(pp); outRec.pts = 0; outRec.bottomPt = 0; return; } //test for duplicate points and for same slope (cross-product) ... if ( PointsEqual(pp->pt, pp->next->pt) || SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) { lastOK = 0; OutPt *tmp = pp; if (pp == outRec.bottomPt) { if (tmp->prev->pt.Y > tmp->next->pt.Y) outRec.bottomPt = tmp->prev; else outRec.bottomPt = tmp->next; outRec.pts = outRec.bottomPt; outRec.bottomPt->idx = outRec.idx; } pp->prev->next = pp->next; pp->next->prev = pp->prev; pp = pp->prev; delete tmp; } else if (pp == lastOK) break; else { if (!lastOK) lastOK = pp; pp = pp->next; } } } //------------------------------------------------------------------------------ void Clipper::BuildResult(Polygons &polys) { int k = 0; polys.resize(m_PolyOuts.size()); for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { if (m_PolyOuts[i]->pts) { Polygon* pg = &polys[k]; pg->clear(); OutPt* p = m_PolyOuts[i]->pts; do { pg->push_back(p->pt); p = p->next; } while (p != m_PolyOuts[i]->pts); //make sure each polygon has at least 3 vertices ... if (pg->size() < 3) pg->clear(); else k++; } } polys.resize(k); } //------------------------------------------------------------------------------ void Clipper::BuildResultEx(ExPolygons &polys) { PolyOutList::size_type i = 0; int k = 0; polys.resize(0); polys.reserve(m_PolyOuts.size()); while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) { ExPolygon epg; OutPt* p = m_PolyOuts[i]->pts; do { epg.outer.push_back(p->pt); p = p->next; } while (p != m_PolyOuts[i]->pts); i++; //make sure polygons have at least 3 vertices ... if (epg.outer.size() < 3) continue; while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) { Polygon pg; p = m_PolyOuts[i]->pts; do { pg.push_back(p->pt); p = p->next; } while (p != m_PolyOuts[i]->pts); epg.holes.push_back(pg); i++; } polys.push_back(epg); k++; } polys.resize(k); } //------------------------------------------------------------------------------ void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) { TEdge *e1 = int1.edge1; TEdge *e2 = int1.edge2; IntPoint p = int1.pt; int1.edge1 = int2.edge1; int1.edge2 = int2.edge2; int1.pt = int2.pt; int2.edge1 = e1; int2.edge2 = e2; int2.pt = p; } //------------------------------------------------------------------------------ bool Clipper::FixupIntersections() { if ( !m_IntersectNodes->next ) return true; CopyAELToSEL(); IntersectNode *int1 = m_IntersectNodes; IntersectNode *int2 = m_IntersectNodes->next; while (int2) { TEdge *e1 = int1->edge1; TEdge *e2; if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; else { //The current intersection is out of order, so try and swap it with //a subsequent intersection ... while (int2) { if (int2->edge1->nextInSEL == int2->edge2 || int2->edge1->prevInSEL == int2->edge2) break; else int2 = int2->next; } if ( !int2 ) return false; //oops!!! //found an intersect node that can be swapped ... SwapIntersectNodes(*int1, *int2); e1 = int1->edge1; e2 = int1->edge2; } SwapPositionsInSEL(e1, e2); int1 = int1->next; int2 = int1->next; } m_SortedEdges = 0; //finally, check the last intersection too ... return (int1->edge1->prevInSEL == int1->edge2 || int1->edge1->nextInSEL == int1->edge2); } //------------------------------------------------------------------------------ bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) { if (e2.xcurr == e1.xcurr) return e2.dx > e1.dx; else return e2.xcurr < e1.xcurr; } //------------------------------------------------------------------------------ void Clipper::InsertEdgeIntoAEL(TEdge *edge) { edge->prevInAEL = 0; edge->nextInAEL = 0; if( !m_ActiveEdges ) { m_ActiveEdges = edge; } else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) { edge->nextInAEL = m_ActiveEdges; m_ActiveEdges->prevInAEL = edge; m_ActiveEdges = edge; } else { TEdge* e = m_ActiveEdges; while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) e = e->nextInAEL; edge->nextInAEL = e->nextInAEL; if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; edge->prevInAEL = e; e->nextInAEL = edge; } } //---------------------------------------------------------------------- void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) { AddOutPt(edge1, edge2, pt); SwapSides(*edge1, *edge2); SwapPolyIndexes(*edge1, *edge2); } //---------------------------------------------------------------------- void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) { AddOutPt(edge2, edge1, pt); SwapSides(*edge1, *edge2); SwapPolyIndexes(*edge1, *edge2); } //---------------------------------------------------------------------- void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) { AddOutPt(edge1, edge2, pt); AddOutPt(edge2, edge1, pt); SwapSides( *edge1 , *edge2 ); SwapPolyIndexes( *edge1 , *edge2 ); } //---------------------------------------------------------------------- void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) { //when a polygon is split into 2 polygons, make sure any holes the original //polygon contained link to the correct polygon ... for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { OutRec *orec = m_PolyOuts[i]; if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) orec->FirstLeft = outRec2; } } //---------------------------------------------------------------------- void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) { //if a hole is owned by outRec2 then make it owned by outRec1 ... for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && m_PolyOuts[i]->FirstLeft == outRec2) m_PolyOuts[i]->FirstLeft = outRec1; } //---------------------------------------------------------------------- void Clipper::JoinCommonEdges(bool fixHoleLinkages) { for (JoinList::size_type i = 0; i < m_Joins.size(); i++) { JoinRec* j = m_Joins[i]; OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; OutPt *pp1a = outRec1->pts; OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; OutPt *pp2a = outRec2->pts; IntPoint pt1 = j->pt2a, pt2 = j->pt2b; IntPoint pt3 = j->pt1a, pt4 = j->pt1b; if (!FindSegment(pp1a, pt1, pt2)) continue; if (j->poly1Idx == j->poly2Idx) { //we're searching the same polygon for overlapping segments so //segment 2 mustn't be the same as segment 1 ... pp2a = pp1a->next; if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; } else if (!FindSegment(pp2a, pt3, pt4)) continue; if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; OutPt *p1, *p2, *p3, *p4; OutPt *prev = pp1a->prev; //get p1 & p2 polypts - the overlap start & endpoints on poly1 if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; else if (PointsEqual(prev->pt, pt1)) p1 = prev; else p1 = InsertPolyPtBetween(pp1a, prev, pt1); if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; else if (PointsEqual(prev->pt, pt2)) p2 = prev; else if ((p1 == pp1a) || (p1 == prev)) p2 = InsertPolyPtBetween(pp1a, prev, pt2); else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) p2 = InsertPolyPtBetween(pp1a, p1, pt2); else p2 = InsertPolyPtBetween(p1, prev, pt2); //get p3 & p4 polypts - the overlap start & endpoints on poly2 prev = pp2a->prev; if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; else if (PointsEqual(prev->pt, pt1)) p3 = prev; else p3 = InsertPolyPtBetween(pp2a, prev, pt1); if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; else if (PointsEqual(prev->pt, pt2)) p4 = prev; else if ((p3 == pp2a) || (p3 == prev)) p4 = InsertPolyPtBetween(pp2a, prev, pt2); else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) p4 = InsertPolyPtBetween(pp2a, p3, pt2); else p4 = InsertPolyPtBetween(p3, prev, pt2); //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... if (p1->next == p2 && p3->prev == p4) { p1->next = p3; p3->prev = p1; p2->prev = p4; p4->next = p2; } else if (p1->prev == p2 && p3->next == p4) { p1->prev = p3; p3->next = p1; p2->next = p4; p4->prev = p2; } else continue; //an orientation is probably wrong if (j->poly2Idx == j->poly1Idx) { //instead of joining two polygons, we've just created a new one by //splitting one polygon into two. outRec1->pts = PolygonBottom(p1); outRec1->bottomPt = outRec1->pts; outRec1->bottomPt->idx = outRec1->idx; outRec2 = CreateOutRec(); m_PolyOuts.push_back(outRec2); outRec2->idx = (int)m_PolyOuts.size()-1; j->poly2Idx = outRec2->idx; outRec2->pts = PolygonBottom(p2); outRec2->bottomPt = outRec2->pts; outRec2->bottomPt->idx = outRec2->idx; if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) { outRec2->isHole = !outRec1->isHole; outRec2->FirstLeft = outRec1; if (outRec2->isHole == Orientation(outRec2, m_UseFullRange)) ReversePolyPtLinks(*outRec2->pts); } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) { outRec2->isHole = outRec1->isHole; outRec1->isHole = !outRec2->isHole; outRec2->FirstLeft = outRec1->FirstLeft; outRec1->FirstLeft = outRec2; if (outRec1->isHole == Orientation(outRec1, m_UseFullRange)) ReversePolyPtLinks(*outRec1->pts); } else { outRec2->isHole = outRec1->isHole; outRec2->FirstLeft = outRec1->FirstLeft; //make sure any contained holes now link to the correct polygon ... if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); } //now fixup any subsequent joins that match this polygon for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) { JoinRec* j2 = m_Joins[k]; if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) j2->poly1Idx = j->poly2Idx; if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) j2->poly2Idx = j->poly2Idx; } //now cleanup redundant edges too ... FixupOutPolygon(*outRec1); FixupOutPolygon(*outRec2); } else { //joined 2 polygons together ... //make sure any holes contained by outRec2 now link to outRec1 ... if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); //delete the obsolete pointer ... int OKIdx = outRec1->idx; int ObsoleteIdx = outRec2->idx; outRec2->pts = 0; outRec2->bottomPt = 0; outRec2->AppendLink = outRec1; //holes are practically always joined to outers, not vice versa ... if (outRec1->isHole && !outRec2->isHole) outRec1->isHole = false; //now fixup any subsequent Joins that match this polygon for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) { JoinRec* j2 = m_Joins[k]; if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; } //now cleanup redundant edges too ... if (outRec1->pts) FixupOutPolygon(*outRec1); else FixupOutPolygon(*outRec2); } } } //------------------------------------------------------------------------------ void ReversePoints(Polygon& p) { std::reverse(p.begin(), p.end()); } //------------------------------------------------------------------------------ void ReversePoints(Polygons& p) { for (Polygons::size_type i = 0; i < p.size(); ++i) ReversePoints(p[i]); } //------------------------------------------------------------------------------ // OffsetPolygon functions ... //------------------------------------------------------------------------------ struct DoublePoint { double X; double Y; DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} }; //------------------------------------------------------------------------------ Polygon BuildArc(const IntPoint &pt, const double a1, const double a2, const double r) { int steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); Polygon result(steps); int n = steps - 1; double da = (a2 - a1) / n; double a = a1; for (int i = 0; i <= n; ++i) { result[i].X = pt.X + Round(std::cos(a)*r); result[i].Y = pt.Y + Round(std::sin(a)*r); a += da; } return result; } //------------------------------------------------------------------------------ DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) { if(pt2.X == pt1.X && pt2.Y == pt1.Y) return DoublePoint(0, 0); double dx = (double)(pt2.X - pt1.X); double dy = (double)(pt2.Y - pt1.Y); double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); dx *= f; dy *= f; return DoublePoint(dy, -dx); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ class PolyOffsetBuilder { private: Polygons m_p; Polygon* m_curr_poly; std::vector<DoublePoint> normals; double m_delta, m_RMin, m_R; size_t m_i, m_j, m_k; static const int buffLength = 128; JoinType m_jointype; public: PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, double delta, JoinType jointype, double MiterLimit) { //nb precondition - out_polys != ptsin_polys if (NEAR_ZERO(delta)) { out_polys = in_polys; return; } this->m_p = in_polys; this->m_delta = delta; this->m_jointype = jointype; if (MiterLimit <= 1) MiterLimit = 1; m_RMin = 2/(MiterLimit*MiterLimit); double deltaSq = delta*delta; out_polys.clear(); out_polys.resize(in_polys.size()); for (m_i = 0; m_i < in_polys.size(); m_i++) { m_curr_poly = &out_polys[m_i]; size_t len = in_polys[m_i].size(); if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; //when 'shrinking' polygons - to minimize artefacts //strip those polygons that have an area < pi * delta^2 ... double a1 = Area(in_polys[m_i]); if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area if (len == 0 || (len < 3 && delta <= 0)) continue; else if (len == 1) { Polygon arc; arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); out_polys[m_i] = arc; continue; } //build normals ... normals.clear(); normals.resize(len); normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); for (m_j = 0; m_j < len -1; ++m_j) normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); m_k = len -1; for (m_j = 0; m_j < len; ++m_j) { switch (jointype) { case jtMiter: { m_R = 1 + (normals[m_j].X*normals[m_k].X + normals[m_j].Y*normals[m_k].Y); if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); break; } case jtSquare: DoSquare(); break; case jtRound: DoRound(); break; } m_k = m_j; } } //finally, clean up untidy corners using Clipper ... Clipper clpr; clpr.AddPolygons(out_polys, ptSubject); if (delta > 0) { if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) out_polys.clear(); } else { IntRect r = clpr.GetBounds(); Polygon outer(4); outer[0] = IntPoint(r.left - 10, r.bottom + 10); outer[1] = IntPoint(r.right + 10, r.bottom + 10); outer[2] = IntPoint(r.right + 10, r.top - 10); outer[3] = IntPoint(r.left - 10, r.top - 10); clpr.AddPolygon(outer, ptSubject); if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) { out_polys.erase(out_polys.begin()); ReversePoints(out_polys); } else out_polys.clear(); } } //------------------------------------------------------------------------------ private: void AddPoint(const IntPoint& pt) { Polygon::size_type len = m_curr_poly->size(); if (len == m_curr_poly->capacity()) m_curr_poly->reserve(len + buffLength); m_curr_poly->push_back(pt); } //------------------------------------------------------------------------------ void DoSquare(double mul = 1.0) { IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) { double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); a1 = std::fabs(a2 - a1); if (a1 > pi) a1 = pi * 2 - a1; double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), (long64)(pt1.Y + normals[m_k].X * dx)); AddPoint(pt1); pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), (long64)(pt2.Y -normals[m_j].X * dx)); AddPoint(pt2); } else { AddPoint(pt1); AddPoint(m_p[m_i][m_j]); AddPoint(pt2); } } //------------------------------------------------------------------------------ void DoMiter() { if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) { double q = m_delta / m_R; AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + (normals[m_k].X + normals[m_j].X) * q), (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); } else { IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); AddPoint(pt1); AddPoint(m_p[m_i][m_j]); AddPoint(pt2); } } //------------------------------------------------------------------------------ void DoRound() { IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); AddPoint(pt1); //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) { if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) { double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); if (m_delta > 0 && a2 < a1) a2 += pi *2; else if (m_delta < 0 && a2 > a1) a2 -= pi *2; Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); for (Polygon::size_type m = 0; m < arc.size(); m++) AddPoint(arc[m]); } } else AddPoint(m_p[m_i][m_j]); AddPoint(pt2); } //-------------------------------------------------------------------------- }; //end PolyOffsetBuilder //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, double delta, JoinType jointype, double MiterLimit) { if (&out_polys == &in_polys) { Polygons poly2(in_polys); PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); } else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); } //------------------------------------------------------------------------------ std::ostream& operator <<(std::ostream &s, IntPoint& p) { s << p.X << ' ' << p.Y << "\n"; return s; } //------------------------------------------------------------------------------ std::ostream& operator <<(std::ostream &s, Polygon &p) { for (Polygon::size_type i = 0; i < p.size(); i++) s << p[i]; s << "\n"; return s; } //------------------------------------------------------------------------------ std::ostream& operator <<(std::ostream &s, Polygons &p) { for (Polygons::size_type i = 0; i < p.size(); i++) s << p[i]; s << "\n"; return s; } //------------------------------------------------------------------------------ } //ClipperLib namespace ��������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/readme������������������������������������������������������������0000644�0024617�0000144�00000000317�12261257215�020013� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Use automake to build the library. If automake is not available you still can use the old make. There is a very simple Makefile that can be used. Note that if you use automake it will overwrite Makefile. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_gsv_text.cpp��������������������������������������������������0000644�0024617�0000144�00000100375�12261257215�022025� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Class gsv_text // //---------------------------------------------------------------------------- #include <string.h> #include <stdio.h> #include "../include/agg_gsv_text.h" #include "../include/agg_bounding_rect.h" namespace mapserver { int8u gsv_default_font[] = { 0x40,0x00,0x6c,0x0f,0x15,0x00,0x0e,0x00,0xf9,0xff, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0d,0x0a,0x0d,0x0a,0x46,0x6f,0x6e,0x74,0x20,0x28, 0x63,0x29,0x20,0x4d,0x69,0x63,0x72,0x6f,0x50,0x72, 0x6f,0x66,0x20,0x32,0x37,0x20,0x53,0x65,0x70,0x74, 0x65,0x6d,0x62,0x2e,0x31,0x39,0x38,0x39,0x00,0x0d, 0x0a,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x00,0x12,0x00,0x34,0x00,0x46,0x00,0x94,0x00, 0xd0,0x00,0x2e,0x01,0x3e,0x01,0x64,0x01,0x8a,0x01, 0x98,0x01,0xa2,0x01,0xb4,0x01,0xba,0x01,0xc6,0x01, 0xcc,0x01,0xf0,0x01,0xfa,0x01,0x18,0x02,0x38,0x02, 0x44,0x02,0x68,0x02,0x98,0x02,0xa2,0x02,0xde,0x02, 0x0e,0x03,0x24,0x03,0x40,0x03,0x48,0x03,0x52,0x03, 0x5a,0x03,0x82,0x03,0xec,0x03,0xfa,0x03,0x26,0x04, 0x4c,0x04,0x6a,0x04,0x7c,0x04,0x8a,0x04,0xb6,0x04, 0xc4,0x04,0xca,0x04,0xe0,0x04,0xee,0x04,0xf8,0x04, 0x0a,0x05,0x18,0x05,0x44,0x05,0x5e,0x05,0x8e,0x05, 0xac,0x05,0xd6,0x05,0xe0,0x05,0xf6,0x05,0x00,0x06, 0x12,0x06,0x1c,0x06,0x28,0x06,0x36,0x06,0x48,0x06, 0x4e,0x06,0x60,0x06,0x6e,0x06,0x74,0x06,0x84,0x06, 0xa6,0x06,0xc8,0x06,0xe6,0x06,0x08,0x07,0x2c,0x07, 0x3c,0x07,0x68,0x07,0x7c,0x07,0x8c,0x07,0xa2,0x07, 0xb0,0x07,0xb6,0x07,0xd8,0x07,0xec,0x07,0x10,0x08, 0x32,0x08,0x54,0x08,0x64,0x08,0x88,0x08,0x98,0x08, 0xac,0x08,0xb6,0x08,0xc8,0x08,0xd2,0x08,0xe4,0x08, 0xf2,0x08,0x3e,0x09,0x48,0x09,0x94,0x09,0xc2,0x09, 0xc4,0x09,0xd0,0x09,0xe2,0x09,0x04,0x0a,0x0e,0x0a, 0x26,0x0a,0x34,0x0a,0x4a,0x0a,0x66,0x0a,0x70,0x0a, 0x7e,0x0a,0x8e,0x0a,0x9a,0x0a,0xa6,0x0a,0xb4,0x0a, 0xd8,0x0a,0xe2,0x0a,0xf6,0x0a,0x18,0x0b,0x22,0x0b, 0x32,0x0b,0x56,0x0b,0x60,0x0b,0x6e,0x0b,0x7c,0x0b, 0x8a,0x0b,0x9c,0x0b,0x9e,0x0b,0xb2,0x0b,0xc2,0x0b, 0xd8,0x0b,0xf4,0x0b,0x08,0x0c,0x30,0x0c,0x56,0x0c, 0x72,0x0c,0x90,0x0c,0xb2,0x0c,0xce,0x0c,0xe2,0x0c, 0xfe,0x0c,0x10,0x0d,0x26,0x0d,0x36,0x0d,0x42,0x0d, 0x4e,0x0d,0x5c,0x0d,0x78,0x0d,0x8c,0x0d,0x8e,0x0d, 0x90,0x0d,0x92,0x0d,0x94,0x0d,0x96,0x0d,0x98,0x0d, 0x9a,0x0d,0x9c,0x0d,0x9e,0x0d,0xa0,0x0d,0xa2,0x0d, 0xa4,0x0d,0xa6,0x0d,0xa8,0x0d,0xaa,0x0d,0xac,0x0d, 0xae,0x0d,0xb0,0x0d,0xb2,0x0d,0xb4,0x0d,0xb6,0x0d, 0xb8,0x0d,0xba,0x0d,0xbc,0x0d,0xbe,0x0d,0xc0,0x0d, 0xc2,0x0d,0xc4,0x0d,0xc6,0x0d,0xc8,0x0d,0xca,0x0d, 0xcc,0x0d,0xce,0x0d,0xd0,0x0d,0xd2,0x0d,0xd4,0x0d, 0xd6,0x0d,0xd8,0x0d,0xda,0x0d,0xdc,0x0d,0xde,0x0d, 0xe0,0x0d,0xe2,0x0d,0xe4,0x0d,0xe6,0x0d,0xe8,0x0d, 0xea,0x0d,0xec,0x0d,0x0c,0x0e,0x26,0x0e,0x48,0x0e, 0x64,0x0e,0x88,0x0e,0x92,0x0e,0xa6,0x0e,0xb4,0x0e, 0xd0,0x0e,0xee,0x0e,0x02,0x0f,0x16,0x0f,0x26,0x0f, 0x3c,0x0f,0x58,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x10,0x80, 0x05,0x95,0x00,0x72,0x00,0xfb,0xff,0x7f,0x01,0x7f, 0x01,0x01,0xff,0x01,0x05,0xfe,0x05,0x95,0xff,0x7f, 0x00,0x7a,0x01,0x86,0xff,0x7a,0x01,0x87,0x01,0x7f, 0xfe,0x7a,0x0a,0x87,0xff,0x7f,0x00,0x7a,0x01,0x86, 0xff,0x7a,0x01,0x87,0x01,0x7f,0xfe,0x7a,0x05,0xf2, 0x0b,0x95,0xf9,0x64,0x0d,0x9c,0xf9,0x64,0xfa,0x91, 0x0e,0x00,0xf1,0xfa,0x0e,0x00,0x04,0xfc,0x08,0x99, 0x00,0x63,0x04,0x9d,0x00,0x63,0x04,0x96,0xff,0x7f, 0x01,0x7f,0x01,0x01,0x00,0x01,0xfe,0x02,0xfd,0x01, 0xfc,0x00,0xfd,0x7f,0xfe,0x7e,0x00,0x7e,0x01,0x7e, 0x01,0x7f,0x02,0x7f,0x06,0x7e,0x02,0x7f,0x02,0x7e, 0xf2,0x89,0x02,0x7e,0x02,0x7f,0x06,0x7e,0x02,0x7f, 0x01,0x7f,0x01,0x7e,0x00,0x7c,0xfe,0x7e,0xfd,0x7f, 0xfc,0x00,0xfd,0x01,0xfe,0x02,0x00,0x01,0x01,0x01, 0x01,0x7f,0xff,0x7f,0x10,0xfd,0x15,0x95,0xee,0x6b, 0x05,0x95,0x02,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7f, 0xfe,0x00,0xfe,0x02,0x00,0x02,0x01,0x02,0x02,0x01, 0x02,0x00,0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01, 0x02,0x01,0xfc,0xf2,0xfe,0x7f,0xff,0x7e,0x00,0x7e, 0x02,0x7e,0x02,0x00,0x02,0x01,0x01,0x02,0x00,0x02, 0xfe,0x02,0xfe,0x00,0x07,0xf9,0x15,0x8d,0xff,0x7f, 0x01,0x7f,0x01,0x01,0x00,0x01,0xff,0x01,0xff,0x00, 0xff,0x7f,0xff,0x7e,0xfe,0x7b,0xfe,0x7d,0xfe,0x7e, 0xfe,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,0x00,0x03, 0x01,0x02,0x06,0x04,0x02,0x02,0x01,0x02,0x00,0x02, 0xff,0x02,0xfe,0x01,0xfe,0x7f,0xff,0x7e,0x00,0x7e, 0x01,0x7d,0x02,0x7d,0x05,0x79,0x02,0x7e,0x03,0x7f, 0x01,0x00,0x01,0x01,0x00,0x01,0xf1,0xfe,0xfe,0x01, 0xff,0x02,0x00,0x03,0x01,0x02,0x02,0x02,0x00,0x86, 0x01,0x7e,0x08,0x75,0x02,0x7e,0x02,0x7f,0x05,0x80, 0x05,0x93,0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e, 0xff,0x7e,0xff,0x7f,0x06,0xf1,0x0b,0x99,0xfe,0x7e, 0xfe,0x7d,0xfe,0x7c,0xff,0x7b,0x00,0x7c,0x01,0x7b, 0x02,0x7c,0x02,0x7d,0x02,0x7e,0xfe,0x9e,0xfe,0x7c, 0xff,0x7d,0xff,0x7b,0x00,0x7c,0x01,0x7b,0x01,0x7d, 0x02,0x7c,0x05,0x85,0x03,0x99,0x02,0x7e,0x02,0x7d, 0x02,0x7c,0x01,0x7b,0x00,0x7c,0xff,0x7b,0xfe,0x7c, 0xfe,0x7d,0xfe,0x7e,0x02,0x9e,0x02,0x7c,0x01,0x7d, 0x01,0x7b,0x00,0x7c,0xff,0x7b,0xff,0x7d,0xfe,0x7c, 0x09,0x85,0x08,0x95,0x00,0x74,0xfb,0x89,0x0a,0x7a, 0x00,0x86,0xf6,0x7a,0x0d,0xf4,0x0d,0x92,0x00,0x6e, 0xf7,0x89,0x12,0x00,0x04,0xf7,0x06,0x81,0xff,0x7f, 0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,0xff,0x7e, 0xff,0x7f,0x06,0x84,0x04,0x89,0x12,0x00,0x04,0xf7, 0x05,0x82,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, 0x05,0xfe,0x00,0xfd,0x0e,0x18,0x00,0xeb,0x09,0x95, 0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7d,0x01,0x7b, 0x02,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x03, 0x01,0x05,0x00,0x03,0xff,0x05,0xfe,0x03,0xfd,0x01, 0xfe,0x00,0x0b,0xeb,0x06,0x91,0x02,0x01,0x03,0x03, 0x00,0x6b,0x09,0x80,0x04,0x90,0x00,0x01,0x01,0x02, 0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7f, 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7d,0xf6,0x76, 0x0e,0x00,0x03,0x80,0x05,0x95,0x0b,0x00,0xfa,0x78, 0x03,0x00,0x02,0x7f,0x01,0x7f,0x01,0x7d,0x00,0x7e, 0xff,0x7d,0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01, 0xff,0x01,0xff,0x02,0x11,0xfc,0x0d,0x95,0xf6,0x72, 0x0f,0x00,0xfb,0x8e,0x00,0x6b,0x07,0x80,0x0f,0x95, 0xf6,0x00,0xff,0x77,0x01,0x01,0x03,0x01,0x03,0x00, 0x03,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,0xff,0x7d, 0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x01, 0xff,0x02,0x11,0xfc,0x10,0x92,0xff,0x02,0xfd,0x01, 0xfe,0x00,0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7b, 0x01,0x7c,0x02,0x7e,0x03,0x7f,0x01,0x00,0x03,0x01, 0x02,0x02,0x01,0x03,0x00,0x01,0xff,0x03,0xfe,0x02, 0xfd,0x01,0xff,0x00,0xfd,0x7f,0xfe,0x7e,0xff,0x7d, 0x10,0xf9,0x11,0x95,0xf6,0x6b,0xfc,0x95,0x0e,0x00, 0x03,0xeb,0x08,0x95,0xfd,0x7f,0xff,0x7e,0x00,0x7e, 0x01,0x7e,0x02,0x7f,0x04,0x7f,0x03,0x7f,0x02,0x7e, 0x01,0x7e,0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f, 0xfc,0x00,0xfd,0x01,0xff,0x01,0xff,0x02,0x00,0x03, 0x01,0x02,0x02,0x02,0x03,0x01,0x04,0x01,0x02,0x01, 0x01,0x02,0x00,0x02,0xff,0x02,0xfd,0x01,0xfc,0x00, 0x0c,0xeb,0x10,0x8e,0xff,0x7d,0xfe,0x7e,0xfd,0x7f, 0xff,0x00,0xfd,0x01,0xfe,0x02,0xff,0x03,0x00,0x01, 0x01,0x03,0x02,0x02,0x03,0x01,0x01,0x00,0x03,0x7f, 0x02,0x7e,0x01,0x7c,0x00,0x7b,0xff,0x7b,0xfe,0x7d, 0xfd,0x7f,0xfe,0x00,0xfd,0x01,0xff,0x02,0x10,0xfd, 0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, 0x00,0xf4,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, 0x05,0xfe,0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01, 0xff,0x01,0x01,0xf3,0xff,0x7f,0xff,0x01,0x01,0x01, 0x01,0x7f,0x00,0x7e,0xff,0x7e,0xff,0x7f,0x06,0x84, 0x14,0x92,0xf0,0x77,0x10,0x77,0x04,0x80,0x04,0x8c, 0x12,0x00,0xee,0xfa,0x12,0x00,0x04,0xfa,0x04,0x92, 0x10,0x77,0xf0,0x77,0x14,0x80,0x03,0x90,0x00,0x01, 0x01,0x02,0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f, 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f, 0xfc,0x7e,0x00,0x7d,0x00,0xfb,0xff,0x7f,0x01,0x7f, 0x01,0x01,0xff,0x01,0x09,0xfe,0x12,0x8d,0xff,0x02, 0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xff,0x7f,0xff,0x7d, 0x00,0x7d,0x01,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, 0x01,0x02,0xfb,0x88,0xfe,0x7e,0xff,0x7d,0x00,0x7d, 0x01,0x7e,0x01,0x7f,0x07,0x8b,0xff,0x78,0x00,0x7e, 0x02,0x7f,0x02,0x00,0x02,0x02,0x01,0x03,0x00,0x02, 0xff,0x03,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfd,0x01, 0xfd,0x00,0xfd,0x7f,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, 0xff,0x7d,0x00,0x7d,0x01,0x7d,0x01,0x7e,0x02,0x7e, 0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,0x02,0x01, 0x01,0x01,0xfe,0x8d,0xff,0x78,0x00,0x7e,0x01,0x7f, 0x08,0xfb,0x09,0x95,0xf8,0x6b,0x08,0x95,0x08,0x6b, 0xf3,0x87,0x0a,0x00,0x04,0xf9,0x04,0x95,0x00,0x6b, 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e, 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x80, 0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d, 0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,0x11,0x80, 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00, 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b, 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00, 0x02,0x01,0x02,0x02,0x01,0x02,0x03,0xfb,0x04,0x95, 0x00,0x6b,0x00,0x95,0x07,0x00,0x03,0x7f,0x02,0x7e, 0x01,0x7e,0x01,0x7d,0x00,0x7b,0xff,0x7d,0xff,0x7e, 0xfe,0x7e,0xfd,0x7f,0xf9,0x00,0x11,0x80,0x04,0x95, 0x00,0x6b,0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00, 0xf8,0xf5,0x0d,0x00,0x02,0x80,0x04,0x95,0x00,0x6b, 0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,0x06,0xf5, 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00, 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b, 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00, 0x02,0x01,0x02,0x02,0x01,0x02,0x00,0x03,0xfb,0x80, 0x05,0x00,0x03,0xf8,0x04,0x95,0x00,0x6b,0x0e,0x95, 0x00,0x6b,0xf2,0x8b,0x0e,0x00,0x04,0xf5,0x04,0x95, 0x00,0x6b,0x04,0x80,0x0c,0x95,0x00,0x70,0xff,0x7d, 0xff,0x7f,0xfe,0x7f,0xfe,0x00,0xfe,0x01,0xff,0x01, 0xff,0x03,0x00,0x02,0x0e,0xf9,0x04,0x95,0x00,0x6b, 0x0e,0x95,0xf2,0x72,0x05,0x85,0x09,0x74,0x03,0x80, 0x04,0x95,0x00,0x6b,0x00,0x80,0x0c,0x00,0x01,0x80, 0x04,0x95,0x00,0x6b,0x00,0x95,0x08,0x6b,0x08,0x95, 0xf8,0x6b,0x08,0x95,0x00,0x6b,0x04,0x80,0x04,0x95, 0x00,0x6b,0x00,0x95,0x0e,0x6b,0x00,0x95,0x00,0x6b, 0x04,0x80,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e, 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02, 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02, 0xfe,0x01,0xfc,0x00,0x0d,0xeb,0x04,0x95,0x00,0x6b, 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e, 0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00, 0x11,0xf6,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e, 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02, 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02, 0xfe,0x01,0xfc,0x00,0x03,0xef,0x06,0x7a,0x04,0x82, 0x04,0x95,0x00,0x6b,0x00,0x95,0x09,0x00,0x03,0x7f, 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f, 0xfd,0x7f,0xf7,0x00,0x07,0x80,0x07,0x75,0x03,0x80, 0x11,0x92,0xfe,0x02,0xfd,0x01,0xfc,0x00,0xfd,0x7f, 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x02,0x7f, 0x06,0x7e,0x02,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d, 0xfe,0x7e,0xfd,0x7f,0xfc,0x00,0xfd,0x01,0xfe,0x02, 0x11,0xfd,0x08,0x95,0x00,0x6b,0xf9,0x95,0x0e,0x00, 0x01,0xeb,0x04,0x95,0x00,0x71,0x01,0x7d,0x02,0x7e, 0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x02,0x01,0x03, 0x00,0x0f,0x04,0xeb,0x01,0x95,0x08,0x6b,0x08,0x95, 0xf8,0x6b,0x09,0x80,0x02,0x95,0x05,0x6b,0x05,0x95, 0xfb,0x6b,0x05,0x95,0x05,0x6b,0x05,0x95,0xfb,0x6b, 0x07,0x80,0x03,0x95,0x0e,0x6b,0x00,0x95,0xf2,0x6b, 0x11,0x80,0x01,0x95,0x08,0x76,0x00,0x75,0x08,0x95, 0xf8,0x76,0x09,0xf5,0x11,0x95,0xf2,0x6b,0x00,0x95, 0x0e,0x00,0xf2,0xeb,0x0e,0x00,0x03,0x80,0x03,0x93, 0x00,0x6c,0x01,0x94,0x00,0x6c,0xff,0x94,0x05,0x00, 0xfb,0xec,0x05,0x00,0x02,0x81,0x00,0x95,0x0e,0x68, 0x00,0x83,0x06,0x93,0x00,0x6c,0x01,0x94,0x00,0x6c, 0xfb,0x94,0x05,0x00,0xfb,0xec,0x05,0x00,0x03,0x81, 0x03,0x87,0x08,0x05,0x08,0x7b,0xf0,0x80,0x08,0x04, 0x08,0x7c,0x03,0xf9,0x01,0x80,0x10,0x00,0x01,0x80, 0x06,0x95,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7f, 0x01,0x01,0xff,0x01,0x05,0xef,0x0f,0x8e,0x00,0x72, 0x00,0x8b,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f, 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd, 0x04,0x95,0x00,0x6b,0x00,0x8b,0x02,0x02,0x02,0x01, 0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e, 0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,0xfe,0x01, 0xfe,0x02,0x0f,0xfd,0x0f,0x8b,0xfe,0x02,0xfe,0x01, 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, 0x02,0x02,0x03,0xfd,0x0f,0x95,0x00,0x6b,0x00,0x8b, 0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xfe,0x7e, 0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,0x02,0x7f, 0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,0x03,0x88, 0x0c,0x00,0x00,0x02,0xff,0x02,0xff,0x01,0xfe,0x01, 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, 0x02,0x02,0x03,0xfd,0x0a,0x95,0xfe,0x00,0xfe,0x7f, 0xff,0x7d,0x00,0x6f,0xfd,0x8e,0x07,0x00,0x03,0xf2, 0x0f,0x8e,0x00,0x70,0xff,0x7d,0xff,0x7f,0xfe,0x7f, 0xfd,0x00,0xfe,0x01,0x09,0x91,0xfe,0x02,0xfe,0x01, 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, 0x02,0x02,0x04,0xfd,0x04,0x95,0x00,0x6b,0x00,0x8a, 0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d, 0x00,0x76,0x04,0x80,0x03,0x95,0x01,0x7f,0x01,0x01, 0xff,0x01,0xff,0x7f,0x01,0xf9,0x00,0x72,0x04,0x80, 0x05,0x95,0x01,0x7f,0x01,0x01,0xff,0x01,0xff,0x7f, 0x01,0xf9,0x00,0x6f,0xff,0x7d,0xfe,0x7f,0xfe,0x00, 0x09,0x87,0x04,0x95,0x00,0x6b,0x0a,0x8e,0xf6,0x76, 0x04,0x84,0x07,0x78,0x02,0x80,0x04,0x95,0x00,0x6b, 0x04,0x80,0x04,0x8e,0x00,0x72,0x00,0x8a,0x03,0x03, 0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,0x00,0x76, 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f, 0x01,0x7d,0x00,0x76,0x04,0x80,0x04,0x8e,0x00,0x72, 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f, 0x01,0x7d,0x00,0x76,0x04,0x80,0x08,0x8e,0xfe,0x7f, 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x01,0x03, 0x00,0x02,0xff,0x03,0xfe,0x02,0xfe,0x01,0xfd,0x00, 0x0b,0xf2,0x04,0x8e,0x00,0x6b,0x00,0x92,0x02,0x02, 0x02,0x01,0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d, 0x00,0x7e,0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00, 0xfe,0x01,0xfe,0x02,0x0f,0xfd,0x0f,0x8e,0x00,0x6b, 0x00,0x92,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f, 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd, 0x04,0x8e,0x00,0x72,0x00,0x88,0x01,0x03,0x02,0x02, 0x02,0x01,0x03,0x00,0x01,0xf2,0x0e,0x8b,0xff,0x02, 0xfd,0x01,0xfd,0x00,0xfd,0x7f,0xff,0x7e,0x01,0x7e, 0x02,0x7f,0x05,0x7f,0x02,0x7f,0x01,0x7e,0x00,0x7f, 0xff,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02, 0x0e,0xfd,0x05,0x95,0x00,0x6f,0x01,0x7d,0x02,0x7f, 0x02,0x00,0xf8,0x8e,0x07,0x00,0x03,0xf2,0x04,0x8e, 0x00,0x76,0x01,0x7d,0x02,0x7f,0x03,0x00,0x02,0x01, 0x03,0x03,0x00,0x8a,0x00,0x72,0x04,0x80,0x02,0x8e, 0x06,0x72,0x06,0x8e,0xfa,0x72,0x08,0x80,0x03,0x8e, 0x04,0x72,0x04,0x8e,0xfc,0x72,0x04,0x8e,0x04,0x72, 0x04,0x8e,0xfc,0x72,0x07,0x80,0x03,0x8e,0x0b,0x72, 0x00,0x8e,0xf5,0x72,0x0e,0x80,0x02,0x8e,0x06,0x72, 0x06,0x8e,0xfa,0x72,0xfe,0x7c,0xfe,0x7e,0xfe,0x7f, 0xff,0x00,0x0f,0x87,0x0e,0x8e,0xf5,0x72,0x00,0x8e, 0x0b,0x00,0xf5,0xf2,0x0b,0x00,0x03,0x80,0x09,0x99, 0xfe,0x7f,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e, 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xfe,0x7e,0x01,0x8e, 0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e, 0x00,0x7e,0xff,0x7e,0xfc,0x7e,0x04,0x7e,0x01,0x7e, 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e, 0x01,0x7e,0xff,0x8e,0x02,0x7e,0x00,0x7e,0xff,0x7e, 0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f, 0x02,0x7f,0x05,0x87,0x04,0x95,0x00,0x77,0x00,0xfd, 0x00,0x77,0x04,0x80,0x05,0x99,0x02,0x7f,0x01,0x7f, 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e, 0x00,0x7e,0x02,0x7e,0xff,0x8e,0x01,0x7e,0x00,0x7e, 0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e, 0x04,0x7e,0xfc,0x7e,0xff,0x7e,0x00,0x7e,0x01,0x7e, 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0x01,0x8e, 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e, 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfe,0x7f,0x09,0x87, 0x03,0x86,0x00,0x02,0x01,0x03,0x02,0x01,0x02,0x00, 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01, 0x01,0x02,0xee,0xfe,0x01,0x02,0x02,0x01,0x02,0x00, 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01, 0x01,0x03,0x00,0x02,0x03,0xf4,0x10,0x80,0x03,0x80, 0x07,0x15,0x08,0x6b,0xfe,0x85,0xf5,0x00,0x10,0xfb, 0x0d,0x95,0xf6,0x00,0x00,0x6b,0x0a,0x00,0x02,0x02, 0x00,0x08,0xfe,0x02,0xf6,0x00,0x0e,0xf4,0x03,0x80, 0x00,0x15,0x0a,0x00,0x02,0x7e,0x00,0x7e,0x00,0x7d, 0x00,0x7e,0xfe,0x7f,0xf6,0x00,0x0a,0x80,0x02,0x7e, 0x01,0x7e,0x00,0x7d,0xff,0x7d,0xfe,0x7f,0xf6,0x00, 0x10,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,0xff,0x7e, 0x03,0xed,0x03,0xfd,0x00,0x03,0x02,0x00,0x00,0x12, 0x02,0x03,0x0a,0x00,0x00,0x6b,0x02,0x00,0x00,0x7d, 0xfe,0x83,0xf4,0x00,0x11,0x80,0x0f,0x80,0xf4,0x00, 0x00,0x15,0x0c,0x00,0xff,0xf6,0xf5,0x00,0x0f,0xf5, 0x04,0x95,0x07,0x76,0x00,0x0a,0x07,0x80,0xf9,0x76, 0x00,0x75,0xf8,0x80,0x07,0x0c,0x09,0xf4,0xf9,0x0c, 0x09,0xf4,0x03,0x92,0x02,0x03,0x07,0x00,0x03,0x7d, 0x00,0x7b,0xfc,0x7e,0x04,0x7d,0x00,0x7a,0xfd,0x7e, 0xf9,0x00,0xfe,0x02,0x06,0x89,0x02,0x00,0x06,0xf5, 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0x02,0x80, 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0xf8,0x96, 0x03,0x00,0x07,0xea,0x03,0x80,0x00,0x15,0x0c,0x80, 0xf7,0x76,0xfd,0x00,0x03,0x80,0x0a,0x75,0x03,0x80, 0x03,0x80,0x07,0x13,0x02,0x02,0x03,0x00,0x00,0x6b, 0x02,0x80,0x03,0x80,0x00,0x15,0x09,0x6b,0x09,0x15, 0x00,0x6b,0x03,0x80,0x03,0x80,0x00,0x15,0x00,0xf6, 0x0d,0x00,0x00,0x8a,0x00,0x6b,0x03,0x80,0x07,0x80, 0xfd,0x00,0xff,0x03,0x00,0x04,0x00,0x07,0x00,0x04, 0x01,0x02,0x03,0x01,0x06,0x00,0x03,0x7f,0x01,0x7e, 0x01,0x7c,0x00,0x79,0xff,0x7c,0xff,0x7d,0xfd,0x00, 0xfa,0x00,0x0e,0x80,0x03,0x80,0x00,0x15,0x0c,0x00, 0x00,0x6b,0x02,0x80,0x03,0x80,0x00,0x15,0x0a,0x00, 0x02,0x7f,0x01,0x7d,0x00,0x7b,0xff,0x7e,0xfe,0x7f, 0xf6,0x00,0x10,0xf7,0x11,0x8f,0xff,0x03,0xff,0x02, 0xfe,0x01,0xfa,0x00,0xfd,0x7f,0xff,0x7e,0x00,0x7c, 0x00,0x79,0x00,0x7b,0x01,0x7e,0x03,0x00,0x06,0x00, 0x02,0x00,0x01,0x03,0x01,0x02,0x03,0xfb,0x03,0x95, 0x0c,0x00,0xfa,0x80,0x00,0x6b,0x09,0x80,0x03,0x95, 0x00,0x77,0x06,0x7a,0x06,0x06,0x00,0x09,0xfa,0xf1, 0xfa,0x7a,0x0e,0x80,0x03,0x87,0x00,0x0b,0x02,0x02, 0x03,0x00,0x02,0x7e,0x01,0x02,0x04,0x00,0x02,0x7e, 0x00,0x75,0xfe,0x7e,0xfc,0x00,0xff,0x01,0xfe,0x7f, 0xfd,0x00,0xfe,0x02,0x07,0x8e,0x00,0x6b,0x09,0x80, 0x03,0x80,0x0e,0x15,0xf2,0x80,0x0e,0x6b,0x03,0x80, 0x03,0x95,0x00,0x6b,0x0e,0x00,0x00,0x7d,0xfe,0x98, 0x00,0x6b,0x05,0x80,0x03,0x95,0x00,0x75,0x02,0x7d, 0x0a,0x00,0x00,0x8e,0x00,0x6b,0x02,0x80,0x03,0x95, 0x00,0x6b,0x10,0x00,0x00,0x15,0xf8,0x80,0x00,0x6b, 0x0a,0x80,0x03,0x95,0x00,0x6b,0x10,0x00,0x00,0x15, 0xf8,0x80,0x00,0x6b,0x0a,0x00,0x00,0x7d,0x02,0x83, 0x10,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02, 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0x89,0x00,0x6b, 0x03,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02, 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0xf4,0x03,0x92, 0x02,0x03,0x07,0x00,0x03,0x7d,0x00,0x70,0xfd,0x7e, 0xf9,0x00,0xfe,0x02,0x03,0x89,0x09,0x00,0x02,0xf5, 0x03,0x80,0x00,0x15,0x00,0xf5,0x07,0x00,0x00,0x08, 0x02,0x03,0x06,0x00,0x02,0x7d,0x00,0x70,0xfe,0x7e, 0xfa,0x00,0xfe,0x02,0x00,0x08,0x0c,0xf6,0x0f,0x80, 0x00,0x15,0xf6,0x00,0xfe,0x7d,0x00,0x79,0x02,0x7e, 0x0a,0x00,0xf4,0xf7,0x07,0x09,0x07,0xf7,0x03,0x8c, 0x01,0x02,0x01,0x01,0x05,0x00,0x02,0x7f,0x01,0x7e, 0x00,0x74,0x00,0x86,0xff,0x01,0xfe,0x01,0xfb,0x00, 0xff,0x7f,0xff,0x7f,0x00,0x7c,0x01,0x7e,0x01,0x00, 0x05,0x00,0x02,0x00,0x01,0x02,0x03,0xfe,0x04,0x8e, 0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7e,0x00,0x77, 0xff,0x7e,0xfe,0x7f,0xfc,0x00,0xfe,0x01,0xff,0x02, 0x00,0x09,0x01,0x02,0x02,0x02,0x03,0x01,0x02,0x01, 0x01,0x01,0x01,0x02,0x02,0xeb,0x03,0x80,0x00,0x15, 0x03,0x00,0x02,0x7e,0x00,0x7b,0xfe,0x7e,0xfd,0x00, 0x03,0x80,0x04,0x00,0x03,0x7e,0x00,0x78,0xfd,0x7e, 0xf9,0x00,0x0c,0x80,0x03,0x8c,0x02,0x02,0x02,0x01, 0x03,0x00,0x02,0x7f,0x01,0x7d,0xfe,0x7e,0xf9,0x7d, 0xff,0x7e,0x00,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01, 0x02,0x01,0x02,0xfe,0x0d,0x8c,0xff,0x02,0xfe,0x01, 0xfc,0x00,0xfe,0x7f,0xff,0x7e,0x00,0x77,0x01,0x7e, 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x02,0x00,0x0f, 0xff,0x02,0xfe,0x01,0xf9,0x00,0x0c,0xeb,0x03,0x88, 0x0a,0x00,0x00,0x02,0x00,0x03,0xfe,0x02,0xfa,0x00, 0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,0x01,0x7f, 0x06,0x00,0x02,0x02,0x03,0xfe,0x03,0x8f,0x06,0x77, 0x06,0x09,0xfa,0x80,0x00,0x71,0xff,0x87,0xfb,0x79, 0x07,0x87,0x05,0x79,0x02,0x80,0x03,0x8d,0x02,0x02, 0x06,0x00,0x02,0x7e,0x00,0x7d,0xfc,0x7d,0x04,0x7e, 0x00,0x7d,0xfe,0x7e,0xfa,0x00,0xfe,0x02,0x04,0x85, 0x02,0x00,0x06,0xf9,0x03,0x8f,0x00,0x73,0x01,0x7e, 0x07,0x00,0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e, 0x03,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x07,0x00, 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0xf8,0x90, 0x03,0x00,0x08,0xf0,0x03,0x80,0x00,0x15,0x00,0xf3, 0x02,0x00,0x06,0x07,0xfa,0xf9,0x07,0x78,0x03,0x80, 0x03,0x80,0x04,0x0c,0x02,0x03,0x04,0x00,0x00,0x71, 0x02,0x80,0x03,0x80,0x00,0x0f,0x06,0x77,0x06,0x09, 0x00,0x71,0x02,0x80,0x03,0x80,0x00,0x0f,0x0a,0xf1, 0x00,0x0f,0xf6,0xf8,0x0a,0x00,0x02,0xf9,0x05,0x80, 0xff,0x01,0xff,0x04,0x00,0x05,0x01,0x03,0x01,0x02, 0x06,0x00,0x02,0x7e,0x00,0x7d,0x00,0x7b,0x00,0x7c, 0xfe,0x7f,0xfa,0x00,0x0b,0x80,0x03,0x80,0x00,0x0f, 0x00,0xfb,0x01,0x03,0x01,0x02,0x05,0x00,0x02,0x7e, 0x01,0x7d,0x00,0x76,0x03,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, 0x10,0x80,0x0a,0x8f,0x02,0x7f,0x01,0x7e,0x00,0x76, 0xff,0x7f,0xfe,0x7f,0xfb,0x00,0xff,0x01,0xff,0x01, 0x00,0x0a,0x01,0x02,0x01,0x01,0x05,0x00,0xf9,0x80, 0x00,0x6b,0x0c,0x86,0x0d,0x8a,0xff,0x03,0xfe,0x02, 0xfb,0x00,0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c, 0x01,0x7f,0x05,0x00,0x02,0x01,0x01,0x03,0x03,0xfc, 0x03,0x80,0x00,0x0f,0x00,0xfb,0x01,0x03,0x01,0x02, 0x04,0x00,0x01,0x7e,0x01,0x7d,0x00,0x76,0x00,0x8a, 0x01,0x03,0x02,0x02,0x03,0x00,0x02,0x7e,0x01,0x7d, 0x00,0x76,0x03,0x80,0x03,0x8f,0x00,0x74,0x01,0x7e, 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x01,0x00,0x8d, 0x00,0x6e,0xff,0x7e,0xfe,0x7f,0xfb,0x00,0xfe,0x01, 0x0c,0x85,0x03,0x8d,0x01,0x02,0x03,0x00,0x02,0x7e, 0x01,0x02,0x03,0x00,0x02,0x7e,0x00,0x74,0xfe,0x7f, 0xfd,0x00,0xff,0x01,0xfe,0x7f,0xfd,0x00,0xff,0x01, 0x00,0x0c,0x06,0x82,0x00,0x6b,0x08,0x86,0x03,0x80, 0x0a,0x0f,0xf6,0x80,0x0a,0x71,0x03,0x80,0x03,0x8f, 0x00,0x73,0x01,0x7e,0x07,0x00,0x02,0x02,0x00,0x0d, 0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,0x03,0x8f, 0x00,0x79,0x02,0x7e,0x08,0x00,0x00,0x89,0x00,0x71, 0x02,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00, 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00, 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x80, 0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,0x02,0x02, 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,0x02,0x02, 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82, 0x03,0x8d,0x00,0x02,0x02,0x00,0x00,0x71,0x08,0x00, 0x02,0x02,0x00,0x06,0xfe,0x02,0xf8,0x00,0x0c,0xf6, 0x03,0x8f,0x00,0x71,0x07,0x00,0x02,0x02,0x00,0x06, 0xfe,0x02,0xf9,0x00,0x0c,0x85,0x00,0x71,0x02,0x80, 0x03,0x8f,0x00,0x71,0x07,0x00,0x03,0x02,0x00,0x06, 0xfd,0x02,0xf9,0x00,0x0c,0xf6,0x03,0x8d,0x02,0x02, 0x06,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfa,0x00, 0xfe,0x02,0x04,0x85,0x06,0x00,0x02,0xf9,0x03,0x80, 0x00,0x0f,0x00,0xf8,0x04,0x00,0x00,0x06,0x02,0x02, 0x04,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfc,0x00, 0xfe,0x02,0x00,0x05,0x0a,0xf9,0x0d,0x80,0x00,0x0f, 0xf7,0x00,0xff,0x7e,0x00,0x7b,0x01,0x7e,0x09,0x00, 0xf6,0xfa,0x04,0x06,0x08,0xfa }; //------------------------------------------------------------------------- gsv_text::gsv_text() : m_x(0.0), m_y(0.0), m_start_x(0.0), m_width(10.0), m_height(0.0), m_space(0.0), m_line_space(0.0), m_text(m_chr), m_text_buf(), m_cur_chr(m_chr), m_font(gsv_default_font), m_loaded_font(), m_status(initial), m_big_endian(false), m_flip(false) { m_chr[0] = m_chr[1] = 0; int t = 1; if(*(char*)&t == 0) m_big_endian = true; } //------------------------------------------------------------------------- void gsv_text::font(const void* font) { m_font = font; if(m_font == 0) m_font = &m_loaded_font[0]; } //------------------------------------------------------------------------- void gsv_text::size(double height, double width) { m_height = height; m_width = width; } //------------------------------------------------------------------------- void gsv_text::space(double space) { m_space = space; } //------------------------------------------------------------------------- void gsv_text::line_space(double line_space) { m_line_space = line_space; } //------------------------------------------------------------------------- void gsv_text::start_point(double x, double y) { m_x = m_start_x = x; m_y = y; //if(m_flip) m_y += m_height; } //------------------------------------------------------------------------- void gsv_text::load_font(const char* file) { m_loaded_font.resize(0); FILE* fd = fopen(file, "rb"); if(fd) { unsigned len; fseek(fd, 0l, SEEK_END); len = ftell(fd); fseek(fd, 0l, SEEK_SET); if(len > 0) { m_loaded_font.resize(len); fread(&m_loaded_font[0], 1, len, fd); m_font = &m_loaded_font[0]; } fclose(fd); } } //------------------------------------------------------------------------- void gsv_text::text(const char* text) { if(text == 0) { m_chr[0] = 0; m_text = m_chr; return; } unsigned new_size = strlen(text) + 1; if(new_size > m_text_buf.size()) { m_text_buf.resize(new_size); } memcpy(&m_text_buf[0], text, new_size); m_text = &m_text_buf[0]; } //------------------------------------------------------------------------- void gsv_text::rewind(unsigned) { m_status = initial; if(m_font == 0) return; m_indices = (int8u*)m_font; double base_height = value(m_indices + 4); m_indices += value(m_indices); m_glyphs = (int8*)(m_indices + 257*2); m_h = m_height / base_height; m_w = (m_width == 0.0) ? m_h : m_width / base_height; if(m_flip) m_h = -m_h; m_cur_chr = m_text; } //------------------------------------------------------------------------- unsigned gsv_text::vertex(double* x, double* y) { unsigned idx; int8 yc, yf; int dx, dy; bool quit = false; while(!quit) { switch(m_status) { case initial: if(m_font == 0) { quit = true; break; } m_status = next_char; case next_char: if(*m_cur_chr == 0) { quit = true; break; } idx = (*m_cur_chr++) & 0xFF; if(idx == '\n') { m_x = m_start_x; m_y -= m_flip ? -m_height - m_line_space : m_height + m_line_space; break; } idx <<= 1; m_bglyph = m_glyphs + value(m_indices + idx); m_eglyph = m_glyphs + value(m_indices + idx + 2); m_status = start_glyph; case start_glyph: *x = m_x; *y = m_y; m_status = glyph; return path_cmd_move_to; case glyph: if(m_bglyph >= m_eglyph) { m_status = next_char; m_x += m_space; break; } dx = int(*m_bglyph++); yf = (yc = *m_bglyph++) & 0x80; yc <<= 1; yc >>= 1; dy = int(yc); m_x += double(dx) * m_w; m_y += double(dy) * m_h; *x = m_x; *y = m_y; return yf ? path_cmd_move_to : path_cmd_line_to; } } return path_cmd_stop; } //------------------------------------------------------------------------- double gsv_text::text_width() { double x1, y1, x2, y2; bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2); return x2 - x1; } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_bezier_arc.cpp������������������������������������������������0000644�0024617�0000144�00000020736�12261257215�022271� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., // 4, 7, 10, or 13 vertices. // //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_bezier_arc.h" namespace mapserver { // This epsilon is used to prevent us from adding degenerate curves // (converging to a single point). // The value isn't very critical. Function arc_to_bezier() has a limit // of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve // becomes inaccurate. But slight exceeding is quite appropriate. //-------------------------------------------------bezier_arc_angle_epsilon const double bezier_arc_angle_epsilon = 0.01; //------------------------------------------------------------arc_to_bezier void arc_to_bezier(double cx, double cy, double rx, double ry, double start_angle, double sweep_angle, double* curve) { double x0 = cos(sweep_angle / 2.0); double y0 = sin(sweep_angle / 2.0); double tx = (1.0 - x0) * 4.0 / 3.0; double ty = y0 - tx * x0 / y0; double px[4]; double py[4]; px[0] = x0; py[0] = -y0; px[1] = x0 + tx; py[1] = -ty; px[2] = x0 + tx; py[2] = ty; px[3] = x0; py[3] = y0; double sn = sin(start_angle + sweep_angle / 2.0); double cs = cos(start_angle + sweep_angle / 2.0); unsigned i; for(i = 0; i < 4; i++) { curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn); curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs); } } //------------------------------------------------------------------------ void bezier_arc::init(double x, double y, double rx, double ry, double start_angle, double sweep_angle) { start_angle = fmod(start_angle, 2.0 * pi); if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi; if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi; if(fabs(sweep_angle) < 1e-10) { m_num_vertices = 4; m_cmd = path_cmd_line_to; m_vertices[0] = x + rx * cos(start_angle); m_vertices[1] = y + ry * sin(start_angle); m_vertices[2] = x + rx * cos(start_angle + sweep_angle); m_vertices[3] = y + ry * sin(start_angle + sweep_angle); return; } double total_sweep = 0.0; double local_sweep = 0.0; double prev_sweep; m_num_vertices = 2; m_cmd = path_cmd_curve4; bool done = false; do { if(sweep_angle < 0.0) { prev_sweep = total_sweep; local_sweep = -pi * 0.5; total_sweep -= pi * 0.5; if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { local_sweep = sweep_angle - prev_sweep; done = true; } } else { prev_sweep = total_sweep; local_sweep = pi * 0.5; total_sweep += pi * 0.5; if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { local_sweep = sweep_angle - prev_sweep; done = true; } } arc_to_bezier(x, y, rx, ry, start_angle, local_sweep, m_vertices + m_num_vertices - 2); m_num_vertices += 6; start_angle += local_sweep; } while(!done && m_num_vertices < 26); } //-------------------------------------------------------------------- void bezier_arc_svg::init(double x0, double y0, double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x2, double y2) { m_radii_ok = true; if(rx < 0.0) rx = -rx; if(ry < 0.0) ry = -rx; // Calculate the middle point between // the current and the final points //------------------------ double dx2 = (x0 - x2) / 2.0; double dy2 = (y0 - y2) / 2.0; double cos_a = cos(angle); double sin_a = sin(angle); // Calculate (x1, y1) //------------------------ double x1 = cos_a * dx2 + sin_a * dy2; double y1 = -sin_a * dx2 + cos_a * dy2; // Ensure radii are large enough //------------------------ double prx = rx * rx; double pry = ry * ry; double px1 = x1 * x1; double py1 = y1 * y1; // Check that radii are large enough //------------------------ double radii_check = px1/prx + py1/pry; if(radii_check > 1.0) { rx = sqrt(radii_check) * rx; ry = sqrt(radii_check) * ry; prx = rx * rx; pry = ry * ry; if(radii_check > 10.0) m_radii_ok = false; } // Calculate (cx1, cy1) //------------------------ double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0; double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1); double coef = sign * sqrt((sq < 0) ? 0 : sq); double cx1 = coef * ((rx * y1) / ry); double cy1 = coef * -((ry * x1) / rx); // // Calculate (cx, cy) from (cx1, cy1) //------------------------ double sx2 = (x0 + x2) / 2.0; double sy2 = (y0 + y2) / 2.0; double cx = sx2 + (cos_a * cx1 - sin_a * cy1); double cy = sy2 + (sin_a * cx1 + cos_a * cy1); // Calculate the start_angle (angle1) and the sweep_angle (dangle) //------------------------ double ux = (x1 - cx1) / rx; double uy = (y1 - cy1) / ry; double vx = (-x1 - cx1) / rx; double vy = (-y1 - cy1) / ry; double p, n; // Calculate the angle start //------------------------ n = sqrt(ux*ux + uy*uy); p = ux; // (1 * ux) + (0 * uy) sign = (uy < 0) ? -1.0 : 1.0; double v = p / n; if(v < -1.0) v = -1.0; if(v > 1.0) v = 1.0; double start_angle = sign * acos(v); // Calculate the sweep angle //------------------------ n = sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)); p = ux * vx + uy * vy; sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0; v = p / n; if(v < -1.0) v = -1.0; if(v > 1.0) v = 1.0; double sweep_angle = sign * acos(v); if(!sweep_flag && sweep_angle > 0) { sweep_angle -= pi * 2.0; } else if (sweep_flag && sweep_angle < 0) { sweep_angle += pi * 2.0; } // We can now build and transform the resulting arc //------------------------ m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle); trans_affine mtx = trans_affine_rotation(angle); mtx *= trans_affine_translation(cx, cy); for(unsigned i = 2; i < m_arc.num_vertices()-2; i += 2) { mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1); } // We must make sure that the starting and ending points // exactly coincide with the initial (x0,y0) and (x2,y2) m_arc.vertices()[0] = x0; m_arc.vertices()[1] = y0; if(m_arc.num_vertices() > 2) { m_arc.vertices()[m_arc.num_vertices() - 2] = x2; m_arc.vertices()[m_arc.num_vertices() - 1] = y2; } } } ����������������������������������mapserver-6.4.1/renderers/agg/src/agg_sqrt_tables.cpp�����������������������������������������������0000644�0024617�0000144�00000020412�12261257215�022476� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // static tables for fast integer sqrt // //---------------------------------------------------------------------------- #include "../include/agg_basics.h" namespace mapserver { int16u g_sqrt_table[1024] = //----------g_sqrt_table { 0, 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585, 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890, 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864, 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618, 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212, 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684, 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058, 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351, 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576, 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743, 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859, 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931, 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963, 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960, 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924, 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859, 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768, 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652, 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514, 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354, 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175, 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978, 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763, 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533, 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287, 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028, 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755, 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469, 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171, 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861, 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541, 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210, 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869, 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519, 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160, 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791, 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415, 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030, 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637, 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237, 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830, 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416, 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995, 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567, 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134, 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694, 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248, 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797, 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340, 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877, 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410, 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937, 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459, 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977, 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490, 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999, 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503, 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002, 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498, 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989, 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477, 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960, 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440, 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916, 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388, 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857, 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323, 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785, 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243, 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699, 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151, 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504 }; int8 g_elder_bit_table[256] = //---------g_elder_bit_table { 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vcgen_contour.cpp���������������������������������������������0000644�0024617�0000144�00000012021�12261257215�023023� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Contour generator // //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_vcgen_contour.h" namespace mapserver { //------------------------------------------------------------------------ vcgen_contour::vcgen_contour() : m_stroker(), m_width(1), m_src_vertices(), m_out_vertices(), m_status(initial), m_src_vertex(0), m_closed(0), m_orientation(0), m_auto_detect(false) { } //------------------------------------------------------------------------ void vcgen_contour::remove_all() { m_src_vertices.remove_all(); m_closed = 0; m_orientation = 0; m_status = initial; } //------------------------------------------------------------------------ void vcgen_contour::add_vertex(double x, double y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist(x, y)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist(x, y)); } else { if(is_end_poly(cmd)) { m_closed = get_close_flag(cmd); if(m_orientation == path_flags_none) { m_orientation = get_orientation(cmd); } } } } } //------------------------------------------------------------------------ void vcgen_contour::rewind(unsigned) { if(m_status == initial) { m_src_vertices.close(true); if(m_auto_detect) { if(!is_oriented(m_orientation)) { m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ? path_flags_ccw : path_flags_cw; } } if(is_oriented(m_orientation)) { m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); } } m_status = ready; m_src_vertex = 0; } //------------------------------------------------------------------------ unsigned vcgen_contour::vertex(double* x, double* y) { unsigned cmd = path_cmd_line_to; while(!is_stop(cmd)) { switch(m_status) { case initial: rewind(0); case ready: if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) { cmd = path_cmd_stop; break; } m_status = outline; cmd = path_cmd_move_to; m_src_vertex = 0; m_out_vertex = 0; case outline: if(m_src_vertex >= m_src_vertices.size()) { m_status = end_poly; break; } m_stroker.calc_join(m_out_vertices, m_src_vertices.prev(m_src_vertex), m_src_vertices.curr(m_src_vertex), m_src_vertices.next(m_src_vertex), m_src_vertices.prev(m_src_vertex).dist, m_src_vertices.curr(m_src_vertex).dist); ++m_src_vertex; m_status = out_vertices; m_out_vertex = 0; case out_vertices: if(m_out_vertex >= m_out_vertices.size()) { m_status = outline; } else { const point_d& c = m_out_vertices[m_out_vertex++]; *x = c.x; *y = c.y; return cmd; } break; case end_poly: if(!m_closed) return path_cmd_stop; m_status = stop; return path_cmd_end_poly | path_flags_close | path_flags_ccw; case stop: return path_cmd_stop; } } return cmd; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vpgen_clip_polyline.cpp���������������������������������������0000644�0024617�0000144�00000004657�12261257215�024231� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_vpgen_clip_polyline.h" #include "../include/agg_clip_liang_barsky.h" namespace mapserver { //---------------------------------------------------------------------------- void vpgen_clip_polyline::reset() { m_vertex = 0; m_num_vertices = 0; m_move_to = false; } //---------------------------------------------------------------------------- void vpgen_clip_polyline::move_to(double x, double y) { m_vertex = 0; m_num_vertices = 0; m_x1 = x; m_y1 = y; m_move_to = true; } //---------------------------------------------------------------------------- void vpgen_clip_polyline::line_to(double x, double y) { double x2 = x; double y2 = y; unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); m_vertex = 0; m_num_vertices = 0; if((flags & 4) == 0) { if((flags & 1) != 0 || m_move_to) { m_x[0] = m_x1; m_y[0] = m_y1; m_cmd[0] = path_cmd_move_to; m_num_vertices = 1; } m_x[m_num_vertices] = x2; m_y[m_num_vertices] = y2; m_cmd[m_num_vertices++] = path_cmd_line_to; m_move_to = (flags & 2) != 0; } m_x1 = x; m_y1 = y; } //---------------------------------------------------------------------------- unsigned vpgen_clip_polyline::vertex(double* x, double* y) { if(m_vertex < m_num_vertices) { *x = m_x[m_vertex]; *y = m_y[m_vertex]; return m_cmd[m_vertex++]; } return path_cmd_stop; } } ���������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_curves.cpp����������������������������������������������������0000644�0024617�0000144�00000046264�12261257215�021477� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_curves.h" #include "../include/agg_math.h" namespace mapserver { //------------------------------------------------------------------------ const double curve_distance_epsilon = 1e-30; const double curve_collinearity_epsilon = 1e-30; const double curve_angle_tolerance_epsilon = 0.01; enum curve_recursion_limit_e { curve_recursion_limit = 32 }; //------------------------------------------------------------------------ void curve3_inc::approximation_scale(double s) { m_scale = s; } //------------------------------------------------------------------------ double curve3_inc::approximation_scale() const { return m_scale; } //------------------------------------------------------------------------ void curve3_inc::init(double x1, double y1, double x2, double y2, double x3, double y3) { m_start_x = x1; m_start_y = y1; m_end_x = x3; m_end_y = y3; double dx1 = x2 - x1; double dy1 = y2 - y1; double dx2 = x3 - x2; double dy2 = y3 - y2; double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2); m_num_steps = uround(len * 0.25 * m_scale); if(m_num_steps < 4) { m_num_steps = 4; } double subdivide_step = 1.0 / m_num_steps; double subdivide_step2 = subdivide_step * subdivide_step; double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2; double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2; m_saved_fx = m_fx = x1; m_saved_fy = m_fy = y1; m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step); m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step); m_ddfx = tmpx * 2.0; m_ddfy = tmpy * 2.0; m_step = m_num_steps; } //------------------------------------------------------------------------ void curve3_inc::rewind(unsigned) { if(m_num_steps == 0) { m_step = -1; return; } m_step = m_num_steps; m_fx = m_saved_fx; m_fy = m_saved_fy; m_dfx = m_saved_dfx; m_dfy = m_saved_dfy; } //------------------------------------------------------------------------ unsigned curve3_inc::vertex(double* x, double* y) { if(m_step < 0) return path_cmd_stop; if(m_step == m_num_steps) { *x = m_start_x; *y = m_start_y; --m_step; return path_cmd_move_to; } if(m_step == 0) { *x = m_end_x; *y = m_end_y; --m_step; return path_cmd_line_to; } m_fx += m_dfx; m_fy += m_dfy; m_dfx += m_ddfx; m_dfy += m_ddfy; *x = m_fx; *y = m_fy; --m_step; return path_cmd_line_to; } //------------------------------------------------------------------------ void curve3_div::init(double x1, double y1, double x2, double y2, double x3, double y3) { m_points.remove_all(); m_distance_tolerance_square = 0.5 / m_approximation_scale; m_distance_tolerance_square *= m_distance_tolerance_square; bezier(x1, y1, x2, y2, x3, y3); m_count = 0; } //------------------------------------------------------------------------ void curve3_div::recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, unsigned level) { if(level > curve_recursion_limit) { return; } // Calculate all the mid-points of the line segments //---------------------- double x12 = (x1 + x2) / 2; double y12 = (y1 + y2) / 2; double x23 = (x2 + x3) / 2; double y23 = (y2 + y3) / 2; double x123 = (x12 + x23) / 2; double y123 = (y12 + y23) / 2; double dx = x3-x1; double dy = y3-y1; double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx)); double da; if(d > curve_collinearity_epsilon) { // Regular case //----------------- if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy)) { // If the curvature doesn't exceed the distance_tolerance value // we tend to finish subdivisions. //---------------------- if(m_angle_tolerance < curve_angle_tolerance_epsilon) { m_points.add(point_d(x123, y123)); return; } // Angle & Cusp Condition //---------------------- da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); if(da >= pi) da = 2*pi - da; if(da < m_angle_tolerance) { // Finally we can stop the recursion //---------------------- m_points.add(point_d(x123, y123)); return; } } } else { // Collinear case //------------------ da = dx*dx + dy*dy; if(da == 0) { d = calc_sq_distance(x1, y1, x2, y2); } else { d = ((x2 - x1)*dx + (y2 - y1)*dy) / da; if(d > 0 && d < 1) { // Simple collinear case, 1---2---3 // We can leave just two endpoints return; } if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1); else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3); else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy); } if(d < m_distance_tolerance_square) { m_points.add(point_d(x2, y2)); return; } } // Continue subdivision //---------------------- recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1); recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1); } //------------------------------------------------------------------------ void curve3_div::bezier(double x1, double y1, double x2, double y2, double x3, double y3) { m_points.add(point_d(x1, y1)); recursive_bezier(x1, y1, x2, y2, x3, y3, 0); m_points.add(point_d(x3, y3)); } //------------------------------------------------------------------------ void curve4_inc::approximation_scale(double s) { m_scale = s; } //------------------------------------------------------------------------ double curve4_inc::approximation_scale() const { return m_scale; } #if defined(_MSC_VER) && _MSC_VER <= 1200 //------------------------------------------------------------------------ static double MSC60_fix_ICE(double v) { return v; } #endif //------------------------------------------------------------------------ void curve4_inc::init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { m_start_x = x1; m_start_y = y1; m_end_x = x4; m_end_y = y4; double dx1 = x2 - x1; double dy1 = y2 - y1; double dx2 = x3 - x2; double dy2 = y3 - y2; double dx3 = x4 - x3; double dy3 = y4 - y3; double len = (sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2) + sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale; #if defined(_MSC_VER) && _MSC_VER <= 1200 m_num_steps = uround(MSC60_fix_ICE(len)); #else m_num_steps = uround(len); #endif if(m_num_steps < 4) { m_num_steps = 4; } double subdivide_step = 1.0 / m_num_steps; double subdivide_step2 = subdivide_step * subdivide_step; double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step; double pre1 = 3.0 * subdivide_step; double pre2 = 3.0 * subdivide_step2; double pre4 = 6.0 * subdivide_step2; double pre5 = 6.0 * subdivide_step3; double tmp1x = x1 - x2 * 2.0 + x3; double tmp1y = y1 - y2 * 2.0 + y3; double tmp2x = (x2 - x3) * 3.0 - x1 + x4; double tmp2y = (y2 - y3) * 3.0 - y1 + y4; m_saved_fx = m_fx = x1; m_saved_fy = m_fy = y1; m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3; m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3; m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5; m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5; m_dddfx = tmp2x * pre5; m_dddfy = tmp2y * pre5; m_step = m_num_steps; } //------------------------------------------------------------------------ void curve4_inc::rewind(unsigned) { if(m_num_steps == 0) { m_step = -1; return; } m_step = m_num_steps; m_fx = m_saved_fx; m_fy = m_saved_fy; m_dfx = m_saved_dfx; m_dfy = m_saved_dfy; m_ddfx = m_saved_ddfx; m_ddfy = m_saved_ddfy; } //------------------------------------------------------------------------ unsigned curve4_inc::vertex(double* x, double* y) { if(m_step < 0) return path_cmd_stop; if(m_step == m_num_steps) { *x = m_start_x; *y = m_start_y; --m_step; return path_cmd_move_to; } if(m_step == 0) { *x = m_end_x; *y = m_end_y; --m_step; return path_cmd_line_to; } m_fx += m_dfx; m_fy += m_dfy; m_dfx += m_ddfx; m_dfy += m_ddfy; m_ddfx += m_dddfx; m_ddfy += m_dddfy; *x = m_fx; *y = m_fy; --m_step; return path_cmd_line_to; } //------------------------------------------------------------------------ void curve4_div::init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { m_points.remove_all(); m_distance_tolerance_square = 0.5 / m_approximation_scale; m_distance_tolerance_square *= m_distance_tolerance_square; bezier(x1, y1, x2, y2, x3, y3, x4, y4); m_count = 0; } //------------------------------------------------------------------------ void curve4_div::recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, unsigned level) { if(level > curve_recursion_limit) { return; } // Calculate all the mid-points of the line segments //---------------------- double x12 = (x1 + x2) / 2; double y12 = (y1 + y2) / 2; double x23 = (x2 + x3) / 2; double y23 = (y2 + y3) / 2; double x34 = (x3 + x4) / 2; double y34 = (y3 + y4) / 2; double x123 = (x12 + x23) / 2; double y123 = (y12 + y23) / 2; double x234 = (x23 + x34) / 2; double y234 = (y23 + y34) / 2; double x1234 = (x123 + x234) / 2; double y1234 = (y123 + y234) / 2; // Try to approximate the full cubic curve by a single straight line //------------------ double dx = x4-x1; double dy = y4-y1; double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); double da1, da2, k; switch((int(d2 > curve_collinearity_epsilon) << 1) + int(d3 > curve_collinearity_epsilon)) { case 0: // All collinear OR p1==p4 //---------------------- k = dx*dx + dy*dy; if(k == 0) { d2 = calc_sq_distance(x1, y1, x2, y2); d3 = calc_sq_distance(x4, y4, x3, y3); } else { k = 1 / k; da1 = x2 - x1; da2 = y2 - y1; d2 = k * (da1*dx + da2*dy); da1 = x3 - x1; da2 = y3 - y1; d3 = k * (da1*dx + da2*dy); if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) { // Simple collinear case, 1---2---3---4 // We can leave just two endpoints return; } if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1); else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4); else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy); if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1); else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4); else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy); } if(d2 > d3) { if(d2 < m_distance_tolerance_square) { m_points.add(point_d(x2, y2)); return; } } else { if(d3 < m_distance_tolerance_square) { m_points.add(point_d(x3, y3)); return; } } break; case 1: // p1,p2,p4 are collinear, p3 is significant //---------------------- if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) { if(m_angle_tolerance < curve_angle_tolerance_epsilon) { m_points.add(point_d(x23, y23)); return; } // Angle Condition //---------------------- da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2)); if(da1 >= pi) da1 = 2*pi - da1; if(da1 < m_angle_tolerance) { m_points.add(point_d(x2, y2)); m_points.add(point_d(x3, y3)); return; } if(m_cusp_limit != 0.0) { if(da1 > m_cusp_limit) { m_points.add(point_d(x3, y3)); return; } } } break; case 2: // p1,p3,p4 are collinear, p2 is significant //---------------------- if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) { if(m_angle_tolerance < curve_angle_tolerance_epsilon) { m_points.add(point_d(x23, y23)); return; } // Angle Condition //---------------------- da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); if(da1 >= pi) da1 = 2*pi - da1; if(da1 < m_angle_tolerance) { m_points.add(point_d(x2, y2)); m_points.add(point_d(x3, y3)); return; } if(m_cusp_limit != 0.0) { if(da1 > m_cusp_limit) { m_points.add(point_d(x2, y2)); return; } } } break; case 3: // Regular case //----------------- if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) { // If the curvature doesn't exceed the distance_tolerance value // we tend to finish subdivisions. //---------------------- if(m_angle_tolerance < curve_angle_tolerance_epsilon) { m_points.add(point_d(x23, y23)); return; } // Angle & Cusp Condition //---------------------- k = atan2(y3 - y2, x3 - x2); da1 = fabs(k - atan2(y2 - y1, x2 - x1)); da2 = fabs(atan2(y4 - y3, x4 - x3) - k); if(da1 >= pi) da1 = 2*pi - da1; if(da2 >= pi) da2 = 2*pi - da2; if(da1 + da2 < m_angle_tolerance) { // Finally we can stop the recursion //---------------------- m_points.add(point_d(x23, y23)); return; } if(m_cusp_limit != 0.0) { if(da1 > m_cusp_limit) { m_points.add(point_d(x2, y2)); return; } if(da2 > m_cusp_limit) { m_points.add(point_d(x3, y3)); return; } } } break; } // Continue subdivision //---------------------- recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); } //------------------------------------------------------------------------ void curve4_div::bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { m_points.add(point_d(x1, y1)); recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); m_points.add(point_d(x4, y4)); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_trans_affine.cpp����������������������������������������������0000644�0024617�0000144�00000014113�12261257215�022613� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Affine transformations // //---------------------------------------------------------------------------- #include "../include/agg_trans_affine.h" namespace mapserver { //------------------------------------------------------------------------ const trans_affine& trans_affine::parl_to_parl(const double* src, const double* dst) { sx = src[2] - src[0]; shy = src[3] - src[1]; shx = src[4] - src[0]; sy = src[5] - src[1]; tx = src[0]; ty = src[1]; invert(); multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1], dst[4] - dst[0], dst[5] - dst[1], dst[0], dst[1])); return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::rect_to_parl(double x1, double y1, double x2, double y2, const double* parl) { double src[6]; src[0] = x1; src[1] = y1; src[2] = x2; src[3] = y1; src[4] = x2; src[5] = y2; parl_to_parl(src, parl); return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::parl_to_rect(const double* parl, double x1, double y1, double x2, double y2) { double dst[6]; dst[0] = x1; dst[1] = y1; dst[2] = x2; dst[3] = y1; dst[4] = x2; dst[5] = y2; parl_to_parl(parl, dst); return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::multiply(const trans_affine& m) { double t0 = sx * m.sx + shy * m.shx; double t2 = shx * m.sx + sy * m.shx; double t4 = tx * m.sx + ty * m.shx + m.tx; shy = sx * m.shy + shy * m.sy; sy = shx * m.shy + sy * m.sy; ty = tx * m.shy + ty * m.sy + m.ty; sx = t0; shx = t2; tx = t4; return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::invert() { double d = determinant_reciprocal(); double t0 = sy * d; sy = sx * d; shy = -shy * d; shx = -shx * d; double t4 = -tx * t0 - ty * shx; ty = -tx * shy - ty * sy; sx = t0; tx = t4; return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::flip_x() { sx = -sx; shy = -shy; tx = -tx; return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::flip_y() { shx = -shx; sy = -sy; ty = -ty; return *this; } //------------------------------------------------------------------------ const trans_affine& trans_affine::reset() { sx = sy = 1.0; shy = shx = tx = ty = 0.0; return *this; } //------------------------------------------------------------------------ bool trans_affine::is_identity(double epsilon) const { return is_equal_eps(sx, 1.0, epsilon) && is_equal_eps(shy, 0.0, epsilon) && is_equal_eps(shx, 0.0, epsilon) && is_equal_eps(sy, 1.0, epsilon) && is_equal_eps(tx, 0.0, epsilon) && is_equal_eps(ty, 0.0, epsilon); } //------------------------------------------------------------------------ bool trans_affine::is_valid(double epsilon) const { return fabs(sx) > epsilon && fabs(sy) > epsilon; } //------------------------------------------------------------------------ bool trans_affine::is_equal(const trans_affine& m, double epsilon) const { return is_equal_eps(sx, m.sx, epsilon) && is_equal_eps(shy, m.shy, epsilon) && is_equal_eps(shx, m.shx, epsilon) && is_equal_eps(sy, m.sy, epsilon) && is_equal_eps(tx, m.tx, epsilon) && is_equal_eps(ty, m.ty, epsilon); } //------------------------------------------------------------------------ double trans_affine::rotation() const { double x1 = 0.0; double y1 = 0.0; double x2 = 1.0; double y2 = 0.0; transform(&x1, &y1); transform(&x2, &y2); return atan2(y2-y1, x2-x1); } //------------------------------------------------------------------------ void trans_affine::translation(double* dx, double* dy) const { *dx = tx; *dy = ty; } //------------------------------------------------------------------------ void trans_affine::scaling(double* x, double* y) const { double x1 = 0.0; double y1 = 0.0; double x2 = 1.0; double y2 = 1.0; trans_affine t(*this); t *= trans_affine_rotation(-rotation()); t.transform(&x1, &y1); t.transform(&x2, &y2); *x = x2 - x1; *y = y2 - y1; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/configure.in������������������������������������������������������0000644�0024617�0000144�00000000364�12261257215�021146� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������AC_INIT(src/agg_arc.cpp) # give me a source file, any source file... AM_INIT_AUTOMAKE(agg, 2.0.0) AC_PROG_LN_S AC_PROG_CC AC_PROG_CPP AC_PROG_CXX AC_PROG_LIBTOOL AC_OUTPUT( Makefile gpc/Makefile src/Makefile src/ctrl/Makefile ) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/Makefile.am�������������������������������������������������������0000644�0024617�0000144�00000002334�12261257215�020670� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SUBDIRS = ctrl . platform INCLUDES = -I$(top_srcdir)/include lib_LTLIBRARIES = libagg.la libagg_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@ libagg_la_SOURCES = agg_arc.cpp \ agg_arrowhead.cpp \ agg_bezier_arc.cpp \ agg_bspline.cpp \ agg_curves.cpp \ agg_embedded_raster_fonts.cpp \ agg_gsv_text.cpp \ agg_image_filters.cpp \ agg_line_aa_basics.cpp \ agg_line_profile_aa.cpp \ agg_rounded_rect.cpp \ agg_sqrt_tables.cpp \ agg_trans_affine.cpp \ agg_trans_double_path.cpp \ agg_trans_single_path.cpp \ agg_trans_warp_magnifier.cpp \ agg_vcgen_bspline.cpp \ agg_vcgen_contour.cpp \ agg_vcgen_dash.cpp \ agg_vcgen_markers_term.cpp \ agg_vcgen_smooth_poly1.cpp \ agg_vcgen_stroke.cpp \ agg_vpgen_clip_polygon.cpp \ agg_vpgen_clip_polyline.cpp \ agg_vpgen_segmentator.cpp if ENABLE_GPC GPCLD=$(top_builddir)/gpc/libagggpc.la else GPCLD= endif if ENABLE_CTRL CTRLLD=$(top_builddir)/src/ctrl/libaggctrl.la else CTRLLD= endif libagg_la_LIBADD = $(GPCLD) $(CTRLLD) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_vpgen_segmentator.cpp�����������������������������������������0000644�0024617�0000144�00000003656�12261257215�023715� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include <math.h> #include "../include/agg_vpgen_segmentator.h" namespace mapserver { void vpgen_segmentator::move_to(double x, double y) { m_x1 = x; m_y1 = y; m_dx = 0.0; m_dy = 0.0; m_dl = 2.0; m_ddl = 2.0; m_cmd = path_cmd_move_to; } void vpgen_segmentator::line_to(double x, double y) { m_x1 += m_dx; m_y1 += m_dy; m_dx = x - m_x1; m_dy = y - m_y1; double len = sqrt(m_dx * m_dx + m_dy * m_dy) * m_approximation_scale; if(len < 1e-30) len = 1e-30; m_ddl = 1.0 / len; m_dl = (m_cmd == path_cmd_move_to) ? 0.0 : m_ddl; if(m_cmd == path_cmd_stop) m_cmd = path_cmd_line_to; } unsigned vpgen_segmentator::vertex(double* x, double* y) { if(m_cmd == path_cmd_stop) return path_cmd_stop; unsigned cmd = m_cmd; m_cmd = path_cmd_line_to; if(m_dl >= 1.0 - m_ddl) { m_dl = 1.0; m_cmd = path_cmd_stop; *x = m_x1 + m_dx; *y = m_y1 + m_dy; return cmd; } *x = m_x1 + m_dx * m_dl; *y = m_y1 + m_dy * m_dl; m_dl += m_ddl; return cmd; } } ����������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/src/agg_embedded_raster_fonts.cpp�������������������������������������0000644�0024617�0000144�00001402041�12261257215�024500� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #include "../include/agg_embedded_raster_fonts.h" namespace mapserver { const int8u gse4x6[] = { 6, 0, 32, 128-32, 0x00,0x00,0x07,0x00,0x0e,0x00,0x15,0x00,0x1c,0x00,0x23,0x00,0x2a,0x00,0x31,0x00,0x38,0x00, 0x3f,0x00,0x46,0x00,0x4d,0x00,0x54,0x00,0x5b,0x00,0x62,0x00,0x69,0x00,0x70,0x00,0x77,0x00, 0x7e,0x00,0x85,0x00,0x8c,0x00,0x93,0x00,0x9a,0x00,0xa1,0x00,0xa8,0x00,0xaf,0x00,0xb6,0x00, 0xbd,0x00,0xc4,0x00,0xcb,0x00,0xd2,0x00,0xd9,0x00,0xe0,0x00,0xe7,0x00,0xee,0x00,0xf5,0x00, 0xfc,0x00,0x03,0x01,0x0a,0x01,0x11,0x01,0x18,0x01,0x1f,0x01,0x26,0x01,0x2d,0x01,0x34,0x01, 0x3b,0x01,0x42,0x01,0x49,0x01,0x50,0x01,0x57,0x01,0x5e,0x01,0x65,0x01,0x6c,0x01,0x73,0x01, 0x7a,0x01,0x81,0x01,0x88,0x01,0x8f,0x01,0x96,0x01,0x9d,0x01,0xa4,0x01,0xab,0x01,0xb2,0x01, 0xb9,0x01,0xc0,0x01,0xc7,0x01,0xce,0x01,0xd5,0x01,0xdc,0x01,0xe3,0x01,0xea,0x01,0xf1,0x01, 0xf8,0x01,0xff,0x01,0x06,0x02,0x0d,0x02,0x14,0x02,0x1b,0x02,0x22,0x02,0x29,0x02,0x30,0x02, 0x37,0x02,0x3e,0x02,0x45,0x02,0x4c,0x02,0x53,0x02,0x5a,0x02,0x61,0x02,0x68,0x02,0x6f,0x02, 0x76,0x02,0x7d,0x02,0x84,0x02,0x8b,0x02,0x92,0x02,0x99,0x02, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x40,0x40,0x40,0x00,0x40,0x00, 4, // 0x22 '"' 0xa0,0xa0,0x00,0x00,0x00,0x00, 4, // 0x23 '#' 0x60,0xf0,0x60,0xf0,0x60,0x00, 4, // 0x24 '$' 0x40,0x60,0xc0,0x60,0xc0,0x40, 4, // 0x25 '%' 0xa0,0x20,0x40,0x80,0xa0,0x00, 4, // 0x26 '&' 0xe0,0xa0,0x50,0xa0,0xd0,0x00, 4, // 0x27 ''' 0x40,0x40,0x00,0x00,0x00,0x00, 4, // 0x28 '(' 0x20,0x40,0x40,0x40,0x20,0x00, 4, // 0x29 ')' 0x40,0x20,0x20,0x20,0x40,0x00, 4, // 0x2a '*' 0xa0,0x40,0xe0,0x40,0xa0,0x00, 4, // 0x2b '+' 0x40,0x40,0xe0,0x40,0x40,0x00, 4, // 0x2c ',' 0x00,0x00,0x00,0x40,0x40,0x80, 4, // 0x2d '-' 0x00,0x00,0xe0,0x00,0x00,0x00, 4, // 0x2e '.' 0x00,0x00,0x00,0x00,0x40,0x00, 4, // 0x2f '/' 0x10,0x20,0x20,0x40,0x40,0x80, 4, // 0x30 '0' 0xe0,0xa0,0xa0,0xa0,0xe0,0x00, 4, // 0x31 '1' 0x40,0xc0,0x40,0x40,0xe0,0x00, 4, // 0x32 '2' 0xe0,0xa0,0x20,0x40,0xe0,0x00, 4, // 0x33 '3' 0xe0,0x20,0x40,0x20,0xe0,0x00, 4, // 0x34 '4' 0xa0,0xa0,0xe0,0x20,0x20,0x00, 4, // 0x35 '5' 0xe0,0x80,0xc0,0x20,0xc0,0x00, 4, // 0x36 '6' 0x40,0x80,0xe0,0xa0,0xe0,0x00, 4, // 0x37 '7' 0xe0,0xa0,0x20,0x40,0x40,0x00, 4, // 0x38 '8' 0xe0,0xa0,0x40,0xa0,0xe0,0x00, 4, // 0x39 '9' 0xe0,0xa0,0xe0,0x20,0xc0,0x00, 4, // 0x3a ':' 0x00,0x40,0x00,0x40,0x00,0x00, 4, // 0x3b ';' 0x00,0x40,0x00,0x40,0x40,0x80, 4, // 0x3c '<' 0x20,0x40,0x80,0x40,0x20,0x00, 4, // 0x3d '=' 0x00,0xe0,0x00,0xe0,0x00,0x00, 4, // 0x3e '>' 0x80,0x40,0x20,0x40,0x80,0x00, 4, // 0x3f '?' 0xc0,0x20,0x40,0x00,0x40,0x00, 4, // 0x40 '@' 0x40,0xa0,0xe0,0xe0,0x80,0x60, 4, // 0x41 'A' 0x40,0xa0,0xe0,0xa0,0xa0,0x00, 4, // 0x42 'B' 0xc0,0xa0,0xc0,0xa0,0xc0,0x00, 4, // 0x43 'C' 0x60,0x80,0x80,0x80,0x60,0x00, 4, // 0x44 'D' 0xc0,0xa0,0xa0,0xa0,0xc0,0x00, 4, // 0x45 'E' 0xe0,0x80,0xc0,0x80,0xe0,0x00, 4, // 0x46 'F' 0xe0,0x80,0xc0,0x80,0x80,0x00, 4, // 0x47 'G' 0x60,0x80,0xa0,0xa0,0x40,0x00, 4, // 0x48 'H' 0xa0,0xa0,0xe0,0xa0,0xa0,0x00, 4, // 0x49 'I' 0xe0,0x40,0x40,0x40,0xe0,0x00, 4, // 0x4a 'J' 0x20,0x20,0x20,0x20,0xa0,0x40, 4, // 0x4b 'K' 0xa0,0xa0,0xc0,0xc0,0xa0,0x00, 4, // 0x4c 'L' 0x80,0x80,0x80,0x80,0xe0,0x00, 4, // 0x4d 'M' 0xa0,0xe0,0xa0,0xa0,0xa0,0x00, 4, // 0x4e 'N' 0x90,0xd0,0xb0,0x90,0x90,0x00, 4, // 0x4f 'O' 0x40,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x50 'P' 0xc0,0xa0,0xa0,0xc0,0x80,0x00, 4, // 0x51 'Q' 0x40,0xa0,0xa0,0xa0,0x60,0x00, 4, // 0x52 'R' 0xc0,0xa0,0xa0,0xc0,0xa0,0x00, 4, // 0x53 'S' 0x60,0x80,0x40,0x20,0xc0,0x00, 4, // 0x54 'T' 0xe0,0x40,0x40,0x40,0x40,0x00, 4, // 0x55 'U' 0xa0,0xa0,0xa0,0xa0,0xe0,0x00, 4, // 0x56 'V' 0xa0,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x57 'W' 0xa0,0xa0,0xa0,0xe0,0xa0,0x00, 4, // 0x58 'X' 0xa0,0xa0,0x40,0xa0,0xa0,0x00, 4, // 0x59 'Y' 0xa0,0xa0,0x40,0x40,0x40,0x00, 4, // 0x5a 'Z' 0xe0,0x20,0x40,0x80,0xe0,0x00, 4, // 0x5b '[' 0xc0,0x80,0x80,0x80,0xc0,0x00, 4, // 0x5c '\' 0x80,0x40,0x40,0x20,0x20,0x10, 4, // 0x5d ']' 0xc0,0x40,0x40,0x40,0xc0,0x00, 4, // 0x5e '^' 0x40,0xa0,0x00,0x00,0x00,0x00, 4, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0xf0, 4, // 0x60 '`' 0x40,0x20,0x00,0x00,0x00,0x00, 4, // 0x61 'a' 0x00,0x60,0xa0,0xa0,0x70,0x00, 4, // 0x62 'b' 0x80,0x80,0xc0,0xa0,0xc0,0x00, 4, // 0x63 'c' 0x00,0x60,0x80,0x80,0x60,0x00, 4, // 0x64 'd' 0x20,0x20,0x60,0xa0,0x60,0x00, 4, // 0x65 'e' 0x00,0x40,0xe0,0x80,0x60,0x00, 4, // 0x66 'f' 0x20,0x40,0xe0,0x40,0x40,0x00, 4, // 0x67 'g' 0x00,0x60,0xa0,0x60,0x20,0xc0, 4, // 0x68 'h' 0x80,0x80,0xc0,0xa0,0xa0,0x00, 4, // 0x69 'i' 0x40,0x00,0xc0,0x40,0xe0,0x00, 4, // 0x6a 'j' 0x40,0x00,0xc0,0x40,0x40,0x80, 4, // 0x6b 'k' 0x80,0x80,0xa0,0xc0,0xa0,0x00, 4, // 0x6c 'l' 0xc0,0x40,0x40,0x40,0xe0,0x00, 4, // 0x6d 'm' 0x00,0xa0,0xf0,0xf0,0x90,0x00, 4, // 0x6e 'n' 0x00,0xc0,0xa0,0xa0,0xa0,0x00, 4, // 0x6f 'o' 0x00,0x40,0xa0,0xa0,0x40,0x00, 4, // 0x70 'p' 0x00,0xc0,0xa0,0xc0,0x80,0x80, 4, // 0x71 'q' 0x00,0x60,0xa0,0x60,0x20,0x20, 4, // 0x72 'r' 0x00,0xa0,0x50,0x40,0x40,0x00, 4, // 0x73 's' 0x00,0x60,0xc0,0x20,0xc0,0x00, 4, // 0x74 't' 0x40,0x40,0xe0,0x40,0x60,0x00, 4, // 0x75 'u' 0x00,0xa0,0xa0,0xa0,0x60,0x00, 4, // 0x76 'v' 0x00,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x77 'w' 0x00,0xa0,0xa0,0xe0,0xa0,0x00, 4, // 0x78 'x' 0x00,0xa0,0x40,0xa0,0xa0,0x00, 4, // 0x79 'y' 0x00,0xa0,0xa0,0x60,0x20,0xc0, 4, // 0x7a 'z' 0x00,0xe0,0x40,0x80,0xe0,0x00, 4, // 0x7b '{' 0x30,0x20,0xc0,0x20,0x30,0x00, 4, // 0x7c '|' 0x40,0x40,0x00,0x40,0x40,0x40, 4, // 0x7d '}' 0xc0,0x40,0x30,0x40,0xc0,0x00, 4, // 0x7e '~' 0x50,0xa0,0x00,0x00,0x00,0x00, 4, // 0x7f '' 0x00,0x60,0x90,0xf0,0x00,0x00, 0 }; const int8u gse4x8[] = { 8, 0, 32, 128-32, 0x00,0x00,0x09,0x00,0x12,0x00,0x1b,0x00,0x24,0x00,0x2d,0x00,0x36,0x00,0x3f,0x00,0x48,0x00, 0x51,0x00,0x5a,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x7e,0x00,0x87,0x00,0x90,0x00,0x99,0x00, 0xa2,0x00,0xab,0x00,0xb4,0x00,0xbd,0x00,0xc6,0x00,0xcf,0x00,0xd8,0x00,0xe1,0x00,0xea,0x00, 0xf3,0x00,0xfc,0x00,0x05,0x01,0x0e,0x01,0x17,0x01,0x20,0x01,0x29,0x01,0x32,0x01,0x3b,0x01, 0x44,0x01,0x4d,0x01,0x56,0x01,0x5f,0x01,0x68,0x01,0x71,0x01,0x7a,0x01,0x83,0x01,0x8c,0x01, 0x95,0x01,0x9e,0x01,0xa7,0x01,0xb0,0x01,0xb9,0x01,0xc2,0x01,0xcb,0x01,0xd4,0x01,0xdd,0x01, 0xe6,0x01,0xef,0x01,0xf8,0x01,0x01,0x02,0x0a,0x02,0x13,0x02,0x1c,0x02,0x25,0x02,0x2e,0x02, 0x37,0x02,0x40,0x02,0x49,0x02,0x52,0x02,0x5b,0x02,0x64,0x02,0x6d,0x02,0x76,0x02,0x7f,0x02, 0x88,0x02,0x91,0x02,0x9a,0x02,0xa3,0x02,0xac,0x02,0xb5,0x02,0xbe,0x02,0xc7,0x02,0xd0,0x02, 0xd9,0x02,0xe2,0x02,0xeb,0x02,0xf4,0x02,0xfd,0x02,0x06,0x03,0x0f,0x03,0x18,0x03,0x21,0x03, 0x2a,0x03,0x33,0x03,0x3c,0x03,0x45,0x03,0x4e,0x03,0x57,0x03, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x00, 4, // 0x22 '"' 0x00,0xa0,0xa0,0x00,0x00,0x00,0x00,0x00, 4, // 0x23 '#' 0x60,0x60,0xf0,0x60,0x60,0xf0,0x60,0x60, 4, // 0x24 '$' 0x40,0x60,0xc0,0xc0,0x60,0x60,0xc0,0x40, 4, // 0x25 '%' 0x00,0xa0,0x20,0x40,0x40,0x80,0xa0,0x00, 4, // 0x26 '&' 0x00,0x40,0xa0,0xa0,0x40,0xb0,0xa0,0x70, 4, // 0x27 ''' 0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00, 4, // 0x28 '(' 0x20,0x40,0x80,0x80,0x80,0x80,0x40,0x20, 4, // 0x29 ')' 0x80,0x40,0x20,0x20,0x20,0x20,0x40,0x80, 4, // 0x2a '*' 0x00,0xa0,0x40,0xe0,0x40,0xa0,0x00,0x00, 4, // 0x2b '+' 0x00,0x40,0x40,0xe0,0x40,0x40,0x00,0x00, 4, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80, 4, // 0x2d '-' 0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00, 4, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, 4, // 0x2f '/' 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, 4, // 0x30 '0' 0x00,0xe0,0xa0,0xa0,0xa0,0xa0,0xe0,0x00, 4, // 0x31 '1' 0x00,0x40,0xc0,0x40,0x40,0x40,0xe0,0x00, 4, // 0x32 '2' 0x00,0xe0,0xa0,0x20,0x40,0x80,0xe0,0x00, 4, // 0x33 '3' 0x00,0xe0,0x20,0x40,0x20,0x20,0xe0,0x00, 4, // 0x34 '4' 0x00,0x60,0xa0,0xa0,0xf0,0x20,0x20,0x00, 4, // 0x35 '5' 0x00,0xe0,0x80,0xc0,0x20,0x20,0xc0,0x00, 4, // 0x36 '6' 0x00,0x40,0x80,0xe0,0xa0,0xa0,0xe0,0x00, 4, // 0x37 '7' 0x00,0xe0,0xa0,0x20,0x40,0x40,0x40,0x00, 4, // 0x38 '8' 0x00,0xe0,0xa0,0x40,0xa0,0xa0,0xe0,0x00, 4, // 0x39 '9' 0x00,0xe0,0xa0,0xe0,0x20,0x20,0x40,0x00, 4, // 0x3a ':' 0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00, 4, // 0x3b ';' 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x80, 4, // 0x3c '<' 0x00,0x20,0x40,0x80,0x40,0x20,0x00,0x00, 4, // 0x3d '=' 0x00,0x00,0xe0,0x00,0xe0,0x00,0x00,0x00, 4, // 0x3e '>' 0x00,0x80,0x40,0x20,0x40,0x80,0x00,0x00, 4, // 0x3f '?' 0x00,0x40,0xa0,0x20,0x40,0x00,0x40,0x00, 4, // 0x40 '@' 0x00,0x40,0xa0,0xe0,0xe0,0x80,0x60,0x00, 4, // 0x41 'A' 0x00,0x40,0xa0,0xa0,0xe0,0xa0,0xa0,0x00, 4, // 0x42 'B' 0x00,0xc0,0xa0,0xc0,0xa0,0xa0,0xc0,0x00, 4, // 0x43 'C' 0x00,0x40,0xa0,0x80,0x80,0xa0,0x40,0x00, 4, // 0x44 'D' 0x00,0xc0,0xa0,0xa0,0xa0,0xa0,0xc0,0x00, 4, // 0x45 'E' 0x00,0xe0,0x80,0xc0,0x80,0x80,0xe0,0x00, 4, // 0x46 'F' 0x00,0xe0,0x80,0xc0,0x80,0x80,0x80,0x00, 4, // 0x47 'G' 0x00,0x60,0x80,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x48 'H' 0x00,0xa0,0xa0,0xe0,0xa0,0xa0,0xa0,0x00, 4, // 0x49 'I' 0x00,0xe0,0x40,0x40,0x40,0x40,0xe0,0x00, 4, // 0x4a 'J' 0x00,0x20,0x20,0x20,0x20,0xa0,0x40,0x00, 4, // 0x4b 'K' 0x00,0xa0,0xa0,0xc0,0xc0,0xa0,0xa0,0x00, 4, // 0x4c 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0xe0,0x00, 4, // 0x4d 'M' 0x00,0xa0,0xe0,0xa0,0xa0,0xa0,0xa0,0x00, 4, // 0x4e 'N' 0x00,0x90,0x90,0xd0,0xb0,0x90,0x90,0x00, 4, // 0x4f 'O' 0x00,0x40,0xa0,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x50 'P' 0x00,0xc0,0xa0,0xa0,0xc0,0x80,0x80,0x00, 4, // 0x51 'Q' 0x00,0x40,0xa0,0xa0,0xa0,0xa0,0x60,0x00, 4, // 0x52 'R' 0x00,0xc0,0xa0,0xa0,0xc0,0xc0,0xa0,0x00, 4, // 0x53 'S' 0x00,0x60,0x80,0x40,0x20,0x20,0xc0,0x00, 4, // 0x54 'T' 0x00,0xe0,0x40,0x40,0x40,0x40,0x40,0x00, 4, // 0x55 'U' 0x00,0xa0,0xa0,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x56 'V' 0x00,0xa0,0xa0,0xa0,0xa0,0x40,0x40,0x00, 4, // 0x57 'W' 0x00,0xa0,0xa0,0xa0,0xa0,0xe0,0xa0,0x00, 4, // 0x58 'X' 0x00,0xa0,0xa0,0x40,0xa0,0xa0,0xa0,0x00, 4, // 0x59 'Y' 0x00,0xa0,0xa0,0x40,0x40,0x40,0x40,0x00, 4, // 0x5a 'Z' 0x00,0xe0,0x20,0x40,0x40,0x80,0xe0,0x00, 4, // 0x5b '[' 0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0xc0, 4, // 0x5c '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10, 4, // 0x5d ']' 0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0xc0, 4, // 0x5e '^' 0x00,0x40,0xa0,0x00,0x00,0x00,0x00,0x00, 4, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0, 4, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00, 4, // 0x61 'a' 0x00,0x00,0x60,0xa0,0xa0,0xa0,0x70,0x00, 4, // 0x62 'b' 0x00,0x80,0x80,0xc0,0xa0,0xa0,0xc0,0x00, 4, // 0x63 'c' 0x00,0x00,0x40,0xa0,0x80,0xa0,0x40,0x00, 4, // 0x64 'd' 0x00,0x20,0x20,0x60,0xa0,0xa0,0x60,0x00, 4, // 0x65 'e' 0x00,0x00,0x40,0xa0,0xe0,0x80,0x60,0x00, 4, // 0x66 'f' 0x00,0x20,0x40,0x40,0xe0,0x40,0x40,0x00, 4, // 0x67 'g' 0x00,0x00,0x60,0xa0,0xa0,0x60,0x20,0xc0, 4, // 0x68 'h' 0x00,0x80,0x80,0xc0,0xa0,0xa0,0xa0,0x00, 4, // 0x69 'i' 0x00,0x40,0x00,0xc0,0x40,0x40,0xe0,0x00, 4, // 0x6a 'j' 0x00,0x40,0x00,0xc0,0x40,0x40,0x40,0x80, 4, // 0x6b 'k' 0x00,0x80,0x80,0xa0,0xc0,0xc0,0xa0,0x00, 4, // 0x6c 'l' 0x00,0xc0,0x40,0x40,0x40,0x40,0xe0,0x00, 4, // 0x6d 'm' 0x00,0x00,0xa0,0xf0,0xf0,0xf0,0x90,0x00, 4, // 0x6e 'n' 0x00,0x00,0xc0,0xa0,0xa0,0xa0,0xa0,0x00, 4, // 0x6f 'o' 0x00,0x00,0x40,0xa0,0xa0,0xa0,0x40,0x00, 4, // 0x70 'p' 0x00,0x00,0xc0,0xa0,0xa0,0xc0,0x80,0x80, 4, // 0x71 'q' 0x00,0x00,0x60,0xa0,0xa0,0x60,0x20,0x20, 4, // 0x72 'r' 0x00,0x00,0xa0,0x50,0x40,0x40,0x40,0x00, 4, // 0x73 's' 0x00,0x00,0x60,0x80,0x40,0x20,0xc0,0x00, 4, // 0x74 't' 0x00,0x40,0x40,0xe0,0x40,0x40,0x20,0x00, 4, // 0x75 'u' 0x00,0x00,0xa0,0xa0,0xa0,0xa0,0x60,0x00, 4, // 0x76 'v' 0x00,0x00,0xa0,0xa0,0xa0,0x40,0x40,0x00, 4, // 0x77 'w' 0x00,0x00,0xa0,0xa0,0xa0,0xe0,0xa0,0x00, 4, // 0x78 'x' 0x00,0x00,0xa0,0xa0,0x40,0xa0,0xa0,0x00, 4, // 0x79 'y' 0x00,0x00,0xa0,0xa0,0xa0,0x60,0x20,0xc0, 4, // 0x7a 'z' 0x00,0x00,0xe0,0x20,0x40,0x80,0xe0,0x00, 4, // 0x7b '{' 0x10,0x20,0x20,0xc0,0x20,0x20,0x10,0x00, 4, // 0x7c '|' 0x00,0x40,0x40,0x40,0x00,0x40,0x40,0x40, 4, // 0x7d '}' 0x80,0x40,0x40,0x30,0x40,0x40,0x80,0x00, 4, // 0x7e '~' 0x00,0x50,0xa0,0x00,0x00,0x00,0x00,0x00, 4, // 0x7f '' 0x00,0x00,0x00,0x60,0x90,0xf0,0x00,0x00, 0 }; const int8u gse5x7[] = { 7, 0, 32, 128-32, 0x00,0x00,0x08,0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x38,0x00,0x40,0x00, 0x48,0x00,0x50,0x00,0x58,0x00,0x60,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00, 0x90,0x00,0x98,0x00,0xa0,0x00,0xa8,0x00,0xb0,0x00,0xb8,0x00,0xc0,0x00,0xc8,0x00,0xd0,0x00, 0xd8,0x00,0xe0,0x00,0xe8,0x00,0xf0,0x00,0xf8,0x00,0x00,0x01,0x08,0x01,0x10,0x01,0x18,0x01, 0x20,0x01,0x28,0x01,0x30,0x01,0x38,0x01,0x40,0x01,0x48,0x01,0x50,0x01,0x58,0x01,0x60,0x01, 0x68,0x01,0x70,0x01,0x78,0x01,0x80,0x01,0x88,0x01,0x90,0x01,0x98,0x01,0xa0,0x01,0xa8,0x01, 0xb0,0x01,0xb8,0x01,0xc0,0x01,0xc8,0x01,0xd0,0x01,0xd8,0x01,0xe0,0x01,0xe8,0x01,0xf0,0x01, 0xf8,0x01,0x00,0x02,0x08,0x02,0x10,0x02,0x18,0x02,0x20,0x02,0x28,0x02,0x30,0x02,0x38,0x02, 0x40,0x02,0x48,0x02,0x50,0x02,0x58,0x02,0x60,0x02,0x68,0x02,0x70,0x02,0x78,0x02,0x80,0x02, 0x88,0x02,0x90,0x02,0x98,0x02,0xa0,0x02,0xa8,0x02,0xb0,0x02,0xb8,0x02,0xc0,0x02,0xc8,0x02, 0xd0,0x02,0xd8,0x02,0xe0,0x02,0xe8,0x02,0xf0,0x02,0xf8,0x02, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x20,0x20,0x20,0x00,0x20,0x00, 5, // 0x22 '"' 0x00,0x50,0x50,0x00,0x00,0x00,0x00, 5, // 0x23 '#' 0x00,0x50,0xf8,0x50,0xf8,0x50,0x00, 5, // 0x24 '$' 0x20,0x78,0xa0,0x70,0x28,0xf0,0x20, 5, // 0x25 '%' 0x00,0x88,0x10,0x20,0x40,0x88,0x00, 5, // 0x26 '&' 0x00,0x40,0xa0,0x68,0x90,0x68,0x00, 5, // 0x27 ''' 0x00,0x20,0x20,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x10,0x20,0x40,0x40,0x40,0x20,0x10, 5, // 0x29 ')' 0x80,0x40,0x20,0x20,0x20,0x40,0x80, 5, // 0x2a '*' 0x00,0x20,0xa8,0x70,0xa8,0x20,0x00, 5, // 0x2b '+' 0x00,0x20,0x20,0xf8,0x20,0x20,0x00, 5, // 0x2c ',' 0x00,0x00,0x00,0x00,0x20,0x20,0x40, 5, // 0x2d '-' 0x00,0x00,0x00,0xf0,0x00,0x00,0x00, 5, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x40,0x00, 5, // 0x2f '/' 0x00,0x08,0x10,0x20,0x40,0x80,0x00, 5, // 0x30 '0' 0x00,0x60,0x90,0x90,0x90,0x60,0x00, 5, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x70,0x00, 5, // 0x32 '2' 0x00,0x60,0x90,0x20,0x40,0xf0,0x00, 5, // 0x33 '3' 0x00,0xf0,0x20,0x60,0x10,0xe0,0x00, 5, // 0x34 '4' 0x00,0x30,0x50,0x90,0xf0,0x10,0x00, 5, // 0x35 '5' 0x00,0xf0,0x80,0xe0,0x10,0xe0,0x00, 5, // 0x36 '6' 0x00,0x60,0x80,0xe0,0x90,0x60,0x00, 5, // 0x37 '7' 0x00,0xf0,0x90,0x20,0x40,0x40,0x00, 5, // 0x38 '8' 0x00,0x60,0x90,0x60,0x90,0x60,0x00, 5, // 0x39 '9' 0x00,0x60,0x90,0x70,0x10,0x60,0x00, 5, // 0x3a ':' 0x00,0x00,0x20,0x00,0x20,0x00,0x00, 5, // 0x3b ';' 0x00,0x00,0x20,0x00,0x20,0x20,0x40, 5, // 0x3c '<' 0x00,0x10,0x20,0x40,0x20,0x10,0x00, 5, // 0x3d '=' 0x00,0x00,0xf0,0x00,0xf0,0x00,0x00, 5, // 0x3e '>' 0x00,0x80,0x40,0x20,0x40,0x80,0x00, 5, // 0x3f '?' 0x00,0x60,0x90,0x20,0x00,0x20,0x00, 5, // 0x40 '@' 0x00,0x60,0x90,0xb0,0x80,0x70,0x00, 5, // 0x41 'A' 0x00,0x60,0x90,0xf0,0x90,0x90,0x00, 5, // 0x42 'B' 0x00,0xe0,0x90,0xe0,0x90,0xe0,0x00, 5, // 0x43 'C' 0x00,0x60,0x90,0x80,0x90,0x60,0x00, 5, // 0x44 'D' 0x00,0xe0,0x90,0x90,0x90,0xe0,0x00, 5, // 0x45 'E' 0x00,0xf0,0x80,0xe0,0x80,0xf0,0x00, 5, // 0x46 'F' 0x00,0xf0,0x80,0xe0,0x80,0x80,0x00, 5, // 0x47 'G' 0x00,0x70,0x80,0xb0,0x90,0x60,0x00, 5, // 0x48 'H' 0x00,0x90,0x90,0xf0,0x90,0x90,0x00, 5, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x70,0x00, 5, // 0x4a 'J' 0x00,0x70,0x20,0x20,0xa0,0x40,0x00, 5, // 0x4b 'K' 0x00,0x90,0xa0,0xc0,0xa0,0x90,0x00, 5, // 0x4c 'L' 0x00,0x80,0x80,0x80,0x80,0xf0,0x00, 5, // 0x4d 'M' 0x00,0x90,0xf0,0x90,0x90,0x90,0x00, 5, // 0x4e 'N' 0x00,0x90,0xd0,0xb0,0x90,0x90,0x00, 5, // 0x4f 'O' 0x00,0x60,0x90,0x90,0x90,0x60,0x00, 5, // 0x50 'P' 0x00,0xe0,0x90,0xe0,0x80,0x80,0x00, 5, // 0x51 'Q' 0x00,0x60,0x90,0x90,0xa0,0x50,0x00, 5, // 0x52 'R' 0x00,0xe0,0x90,0xe0,0xa0,0x90,0x00, 5, // 0x53 'S' 0x00,0x70,0x80,0x60,0x10,0xe0,0x00, 5, // 0x54 'T' 0x00,0x70,0x20,0x20,0x20,0x20,0x00, 5, // 0x55 'U' 0x00,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x56 'V' 0x00,0x50,0x50,0x50,0x20,0x20,0x00, 5, // 0x57 'W' 0x00,0x90,0x90,0x90,0xf0,0x90,0x00, 5, // 0x58 'X' 0x00,0x90,0x90,0x60,0x90,0x90,0x00, 5, // 0x59 'Y' 0x00,0x50,0x50,0x20,0x20,0x20,0x00, 5, // 0x5a 'Z' 0x00,0xf0,0x10,0x20,0x40,0xf0,0x00, 5, // 0x5b '[' 0x70,0x40,0x40,0x40,0x40,0x40,0x70, 5, // 0x5c '\' 0x00,0x80,0x40,0x20,0x10,0x08,0x00, 5, // 0x5d ']' 0xe0,0x20,0x20,0x20,0x20,0x20,0xe0, 5, // 0x5e '^' 0x00,0x20,0x50,0x00,0x00,0x00,0x00, 5, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0xf8,0x00, 5, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00, 5, // 0x61 'a' 0x00,0x00,0x60,0xa0,0xa0,0x50,0x00, 5, // 0x62 'b' 0x00,0x80,0x80,0xe0,0x90,0xe0,0x00, 5, // 0x63 'c' 0x00,0x00,0x70,0x80,0x80,0x70,0x00, 5, // 0x64 'd' 0x00,0x10,0x10,0x70,0x90,0x70,0x00, 5, // 0x65 'e' 0x00,0x00,0x60,0xf0,0x80,0x70,0x00, 5, // 0x66 'f' 0x00,0x30,0x40,0xe0,0x40,0x40,0x00, 5, // 0x67 'g' 0x00,0x00,0x70,0x90,0x70,0x10,0x60, 5, // 0x68 'h' 0x00,0x80,0x80,0xe0,0x90,0x90,0x00, 5, // 0x69 'i' 0x20,0x00,0x60,0x20,0x20,0x70,0x00, 5, // 0x6a 'j' 0x20,0x00,0x60,0x20,0x20,0xa0,0x40, 5, // 0x6b 'k' 0x80,0x80,0x90,0xa0,0xe0,0x90,0x00, 5, // 0x6c 'l' 0x00,0x60,0x20,0x20,0x20,0x70,0x00, 5, // 0x6d 'm' 0x00,0x00,0xa0,0xf0,0xf0,0x90,0x00, 5, // 0x6e 'n' 0x00,0x00,0xa0,0xd0,0x90,0x90,0x00, 5, // 0x6f 'o' 0x00,0x00,0x60,0x90,0x90,0x60,0x00, 5, // 0x70 'p' 0x00,0x00,0xe0,0x90,0xe0,0x80,0x80, 5, // 0x71 'q' 0x00,0x00,0x70,0x90,0x70,0x10,0x10, 5, // 0x72 'r' 0x00,0x00,0xe0,0x90,0x80,0x80,0x00, 5, // 0x73 's' 0x00,0x00,0x70,0xe0,0x10,0xe0,0x00, 5, // 0x74 't' 0x40,0x40,0xe0,0x40,0x40,0x70,0x00, 5, // 0x75 'u' 0x00,0x00,0x90,0x90,0x90,0x70,0x00, 5, // 0x76 'v' 0x00,0x00,0x50,0x50,0x50,0x20,0x00, 5, // 0x77 'w' 0x00,0x00,0x90,0x90,0xf0,0x90,0x00, 5, // 0x78 'x' 0x00,0x00,0x90,0x60,0x60,0x90,0x00, 5, // 0x79 'y' 0x00,0x00,0x90,0x90,0x70,0x10,0x60, 5, // 0x7a 'z' 0x00,0x00,0xf0,0x20,0x40,0xf0,0x00, 5, // 0x7b '{' 0x10,0x20,0x20,0xc0,0x20,0x20,0x10, 5, // 0x7c '|' 0x20,0x20,0x20,0x00,0x20,0x20,0x20, 5, // 0x7d '}' 0x40,0x20,0x20,0x18,0x20,0x20,0x40, 5, // 0x7e '~' 0x00,0x40,0xa8,0x10,0x00,0x00,0x00, 5, // 0x7f '' 0x00,0x00,0x20,0x50,0x88,0xf8,0x00, 0 }; const int8u gse5x9[] = { 9, 0, 32, 128-32, 0x00,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x28,0x00,0x32,0x00,0x3c,0x00,0x46,0x00,0x50,0x00, 0x5a,0x00,0x64,0x00,0x6e,0x00,0x78,0x00,0x82,0x00,0x8c,0x00,0x96,0x00,0xa0,0x00,0xaa,0x00, 0xb4,0x00,0xbe,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x00,0x04,0x01, 0x0e,0x01,0x18,0x01,0x22,0x01,0x2c,0x01,0x36,0x01,0x40,0x01,0x4a,0x01,0x54,0x01,0x5e,0x01, 0x68,0x01,0x72,0x01,0x7c,0x01,0x86,0x01,0x90,0x01,0x9a,0x01,0xa4,0x01,0xae,0x01,0xb8,0x01, 0xc2,0x01,0xcc,0x01,0xd6,0x01,0xe0,0x01,0xea,0x01,0xf4,0x01,0xfe,0x01,0x08,0x02,0x12,0x02, 0x1c,0x02,0x26,0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x4e,0x02,0x58,0x02,0x62,0x02,0x6c,0x02, 0x76,0x02,0x80,0x02,0x8a,0x02,0x94,0x02,0x9e,0x02,0xa8,0x02,0xb2,0x02,0xbc,0x02,0xc6,0x02, 0xd0,0x02,0xda,0x02,0xe4,0x02,0xee,0x02,0xf8,0x02,0x02,0x03,0x0c,0x03,0x16,0x03,0x20,0x03, 0x2a,0x03,0x34,0x03,0x3e,0x03,0x48,0x03,0x52,0x03,0x5c,0x03,0x66,0x03,0x70,0x03,0x7a,0x03, 0x84,0x03,0x8e,0x03,0x98,0x03,0xa2,0x03,0xac,0x03,0xb6,0x03, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, 5, // 0x22 '"' 0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x23 '#' 0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00, 5, // 0x24 '$' 0x00,0x20,0x78,0xa0,0x70,0x28,0xf0,0x20,0x00, 5, // 0x25 '%' 0x00,0xc8,0xc8,0x10,0x20,0x40,0x98,0x98,0x00, 5, // 0x26 '&' 0x00,0x40,0xa0,0xa0,0x40,0xa8,0x90,0x68,0x00, 5, // 0x27 ''' 0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10, 5, // 0x29 ')' 0x80,0x40,0x20,0x20,0x20,0x20,0x20,0x40,0x80, 5, // 0x2a '*' 0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00, 5, // 0x2b '+' 0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00, 5, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40, 5, // 0x2d '-' 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00, 5, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, 5, // 0x2f '/' 0x00,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, 5, // 0x30 '0' 0x00,0x60,0x90,0xb0,0xd0,0x90,0x90,0x60,0x00, 5, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x32 '2' 0x00,0x60,0x90,0x10,0x20,0x40,0x80,0xf0,0x00, 5, // 0x33 '3' 0x00,0xf0,0x10,0x20,0x60,0x10,0x90,0x60,0x00, 5, // 0x34 '4' 0x00,0x30,0x50,0x90,0x90,0xf8,0x10,0x10,0x00, 5, // 0x35 '5' 0x00,0xf0,0x80,0xe0,0x10,0x10,0x10,0xe0,0x00, 5, // 0x36 '6' 0x00,0x60,0x80,0xe0,0x90,0x90,0x90,0x60,0x00, 5, // 0x37 '7' 0x00,0xf0,0x90,0x10,0x20,0x40,0x40,0x40,0x00, 5, // 0x38 '8' 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x60,0x00, 5, // 0x39 '9' 0x00,0x60,0x90,0x90,0x70,0x10,0x90,0x60,0x00, 5, // 0x3a ':' 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00, 5, // 0x3b ';' 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40, 5, // 0x3c '<' 0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x00, 5, // 0x3d '=' 0x00,0x00,0x00,0xf0,0x00,0xf0,0x00,0x00,0x00, 5, // 0x3e '>' 0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00, 5, // 0x3f '?' 0x00,0x60,0x90,0x10,0x20,0x20,0x00,0x20,0x00, 5, // 0x40 '@' 0x00,0x60,0x90,0xb0,0xb0,0xb0,0x80,0x70,0x00, 5, // 0x41 'A' 0x00,0x60,0x90,0x90,0xf0,0x90,0x90,0x90,0x00, 5, // 0x42 'B' 0x00,0xe0,0x90,0x90,0xe0,0x90,0x90,0xe0,0x00, 5, // 0x43 'C' 0x00,0x60,0x90,0x80,0x80,0x80,0x90,0x60,0x00, 5, // 0x44 'D' 0x00,0xe0,0x90,0x90,0x90,0x90,0x90,0xe0,0x00, 5, // 0x45 'E' 0x00,0xf0,0x80,0x80,0xe0,0x80,0x80,0xf0,0x00, 5, // 0x46 'F' 0x00,0xf0,0x80,0x80,0xe0,0x80,0x80,0x80,0x00, 5, // 0x47 'G' 0x00,0x60,0x90,0x80,0xb0,0x90,0x90,0x60,0x00, 5, // 0x48 'H' 0x00,0x90,0x90,0x90,0xf0,0x90,0x90,0x90,0x00, 5, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x4a 'J' 0x00,0x70,0x20,0x20,0x20,0x20,0xa0,0x40,0x00, 5, // 0x4b 'K' 0x00,0x90,0x90,0xa0,0xc0,0xa0,0x90,0x90,0x00, 5, // 0x4c 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf0,0x00, 5, // 0x4d 'M' 0x00,0x90,0xf0,0x90,0x90,0x90,0x90,0x90,0x00, 5, // 0x4e 'N' 0x00,0x90,0x90,0xd0,0xb0,0x90,0x90,0x90,0x00, 5, // 0x4f 'O' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x50 'P' 0x00,0xe0,0x90,0x90,0xe0,0x80,0x80,0x80,0x00, 5, // 0x51 'Q' 0x00,0x60,0x90,0x90,0x90,0x90,0xa0,0x50,0x00, 5, // 0x52 'R' 0x00,0xe0,0x90,0x90,0xe0,0xa0,0x90,0x90,0x00, 5, // 0x53 'S' 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x00, 5, // 0x54 'T' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 5, // 0x55 'U' 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x56 'V' 0x00,0x50,0x50,0x50,0x50,0x50,0x20,0x20,0x00, 5, // 0x57 'W' 0x00,0x90,0x90,0x90,0x90,0x90,0xf0,0x90,0x00, 5, // 0x58 'X' 0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, 5, // 0x59 'Y' 0x00,0x50,0x50,0x50,0x20,0x20,0x20,0x20,0x00, 5, // 0x5a 'Z' 0x00,0xf0,0x10,0x10,0x20,0x40,0x80,0xf0,0x00, 5, // 0x5b '[' 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, 5, // 0x5c '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x00, 5, // 0x5d ']' 0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00, 5, // 0x5e '^' 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00, 5, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00, 5, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x61 'a' 0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00, 5, // 0x62 'b' 0x00,0x80,0x80,0xe0,0x90,0x90,0x90,0xe0,0x00, 5, // 0x63 'c' 0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00, 5, // 0x64 'd' 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x70,0x00, 5, // 0x65 'e' 0x00,0x00,0x60,0x90,0xf0,0x80,0x80,0x70,0x00, 5, // 0x66 'f' 0x00,0x30,0x40,0x40,0xe0,0x40,0x40,0x40,0x00, 5, // 0x67 'g' 0x00,0x00,0x70,0x90,0x90,0x70,0x10,0x90,0x60, 5, // 0x68 'h' 0x00,0x80,0x80,0xe0,0x90,0x90,0x90,0x90,0x00, 5, // 0x69 'i' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, 5, // 0x6a 'j' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0xa0,0x40, 5, // 0x6b 'k' 0x00,0x80,0x80,0x90,0xa0,0xc0,0xa0,0x90,0x00, 5, // 0x6c 'l' 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x6d 'm' 0x00,0x00,0xa0,0xf0,0xf0,0xf0,0x90,0x90,0x00, 5, // 0x6e 'n' 0x00,0x00,0xa0,0xd0,0x90,0x90,0x90,0x90,0x00, 5, // 0x6f 'o' 0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x70 'p' 0x00,0x00,0xe0,0x90,0x90,0x90,0xe0,0x80,0x80, 5, // 0x71 'q' 0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x10, 5, // 0x72 'r' 0x00,0x00,0xe0,0x90,0x80,0x80,0x80,0x80,0x00, 5, // 0x73 's' 0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00, 5, // 0x74 't' 0x00,0x40,0x40,0xe0,0x40,0x40,0x50,0x20,0x00, 5, // 0x75 'u' 0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00, 5, // 0x76 'v' 0x00,0x00,0x50,0x50,0x50,0x50,0x20,0x20,0x00, 5, // 0x77 'w' 0x00,0x00,0x90,0x90,0x90,0x90,0xf0,0x90,0x00, 5, // 0x78 'x' 0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00, 5, // 0x79 'y' 0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0xe0, 5, // 0x7a 'z' 0x00,0x00,0xf0,0x10,0x20,0x40,0x80,0xf0,0x00, 5, // 0x7b '{' 0x10,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x10, 5, // 0x7c '|' 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, 5, // 0x7d '}' 0x80,0x40,0x40,0x40,0x30,0x40,0x40,0x40,0x80, 5, // 0x7e '~' 0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00, 5, // 0x7f '' 0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00, 0 }; const int8u gse6x12[] = { 12, 0, 32, 128-32, 0x00,0x00,0x0d,0x00,0x1a,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4e,0x00,0x5b,0x00,0x68,0x00, 0x75,0x00,0x82,0x00,0x8f,0x00,0x9c,0x00,0xa9,0x00,0xb6,0x00,0xc3,0x00,0xd0,0x00,0xdd,0x00, 0xea,0x00,0xf7,0x00,0x04,0x01,0x11,0x01,0x1e,0x01,0x2b,0x01,0x38,0x01,0x45,0x01,0x52,0x01, 0x5f,0x01,0x6c,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xa0,0x01,0xad,0x01,0xba,0x01,0xc7,0x01, 0xd4,0x01,0xe1,0x01,0xee,0x01,0xfb,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2f,0x02,0x3c,0x02, 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7d,0x02,0x8a,0x02,0x97,0x02,0xa4,0x02,0xb1,0x02, 0xbe,0x02,0xcb,0x02,0xd8,0x02,0xe5,0x02,0xf2,0x02,0xff,0x02,0x0c,0x03,0x19,0x03,0x26,0x03, 0x33,0x03,0x40,0x03,0x4d,0x03,0x5a,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8e,0x03,0x9b,0x03, 0xa8,0x03,0xb5,0x03,0xc2,0x03,0xcf,0x03,0xdc,0x03,0xe9,0x03,0xf6,0x03,0x03,0x04,0x10,0x04, 0x1d,0x04,0x2a,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5e,0x04,0x6b,0x04,0x78,0x04,0x85,0x04, 0x92,0x04,0x9f,0x04,0xac,0x04,0xb9,0x04,0xc6,0x04,0xd3,0x04, 6, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 6, // 0x22 '"' 0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x00,0x50,0x50,0xf8,0x50,0x50,0x50,0xf8,0x50,0x50,0x00,0x00, 6, // 0x24 '$' 0x00,0x20,0x70,0xa8,0xa0,0x70,0x28,0xa8,0x70,0x20,0x00,0x00, 6, // 0x25 '%' 0x00,0xc8,0xd8,0x10,0x30,0x20,0x60,0x40,0xd8,0x98,0x00,0x00, 6, // 0x26 '&' 0x00,0x60,0x90,0x90,0x90,0x60,0xa8,0x90,0x90,0x68,0x00,0x00, 6, // 0x27 ''' 0x00,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x00,0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00, 6, // 0x29 ')' 0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00,0x00, 6, // 0x2a '*' 0x00,0x00,0x00,0x50,0x20,0xf8,0x20,0x50,0x00,0x00,0x00,0x00, 6, // 0x2b '+' 0x00,0x00,0x20,0x20,0x20,0xf8,0x20,0x20,0x20,0x00,0x00,0x00, 6, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, 6, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, 6, // 0x2f '/' 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00,0x00, 6, // 0x30 '0' 0x00,0x70,0x88,0x88,0x98,0xa8,0xc8,0x88,0x88,0x70,0x00,0x00, 6, // 0x31 '1' 0x00,0x20,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 6, // 0x32 '2' 0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00, 6, // 0x33 '3' 0x00,0xf8,0x10,0x20,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00, 6, // 0x34 '4' 0x00,0x10,0x20,0x40,0x90,0x90,0xf8,0x10,0x10,0x10,0x00,0x00, 6, // 0x35 '5' 0x00,0xf8,0x80,0x80,0xf0,0x08,0x08,0x08,0x88,0x70,0x00,0x00, 6, // 0x36 '6' 0x00,0x70,0x88,0x80,0x80,0xf0,0x88,0x88,0x88,0x70,0x00,0x00, 6, // 0x37 '7' 0x00,0xf8,0x88,0x08,0x08,0x10,0x20,0x20,0x20,0x20,0x00,0x00, 6, // 0x38 '8' 0x00,0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00, 6, // 0x39 '9' 0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x08,0x88,0x70,0x00,0x00, 6, // 0x3a ':' 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00, 6, // 0x3b ';' 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40, 6, // 0x3c '<' 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00,0x00, 6, // 0x3d '=' 0x00,0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0x00,0x00, 6, // 0x3e '>' 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00,0x00, 6, // 0x3f '?' 0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, 6, // 0x40 '@' 0x00,0x70,0x88,0x88,0xb8,0xb8,0xb0,0x80,0x88,0x70,0x00,0x00, 6, // 0x41 'A' 0x00,0x20,0x50,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x00, 6, // 0x42 'B' 0x00,0xf0,0x88,0x88,0x88,0xf0,0x88,0x88,0x88,0xf0,0x00,0x00, 6, // 0x43 'C' 0x00,0x70,0x88,0x88,0x80,0x80,0x80,0x88,0x88,0x70,0x00,0x00, 6, // 0x44 'D' 0x00,0xe0,0x90,0x88,0x88,0x88,0x88,0x88,0x90,0xe0,0x00,0x00, 6, // 0x45 'E' 0x00,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0x80,0xf8,0x00,0x00, 6, // 0x46 'F' 0x00,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0x80,0x80,0x00,0x00, 6, // 0x47 'G' 0x00,0x70,0x88,0x80,0x80,0xb8,0x88,0x88,0x88,0x70,0x00,0x00, 6, // 0x48 'H' 0x00,0x88,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x88,0x00,0x00, 6, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 6, // 0x4a 'J' 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x00, 6, // 0x4b 'K' 0x00,0x88,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x88,0x00,0x00, 6, // 0x4c 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x00, 6, // 0x4d 'M' 0x00,0x88,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x88,0x00,0x00, 6, // 0x4e 'N' 0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x88,0x88,0x00,0x00, 6, // 0x4f 'O' 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, 6, // 0x50 'P' 0x00,0xf0,0x88,0x88,0x88,0xf0,0x80,0x80,0x80,0x80,0x00,0x00, 6, // 0x51 'Q' 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0xa8,0x90,0x68,0x00,0x00, 6, // 0x52 'R' 0x00,0xf0,0x88,0x88,0x88,0x88,0xf0,0xa0,0x90,0x88,0x00,0x00, 6, // 0x53 'S' 0x00,0x70,0x88,0x80,0x80,0x70,0x08,0x08,0x88,0x70,0x00,0x00, 6, // 0x54 'T' 0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, 6, // 0x55 'U' 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, 6, // 0x56 'V' 0x00,0x88,0x88,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00, 6, // 0x57 'W' 0x00,0x88,0x88,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00, 6, // 0x58 'X' 0x00,0x88,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x88,0x00,0x00, 6, // 0x59 'Y' 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00,0x00, 6, // 0x5a 'Z' 0x00,0xf8,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0xf8,0x00,0x00, 6, // 0x5b '[' 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, 6, // 0x5c '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00,0x00, 6, // 0x5d ']' 0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, 6, // 0x5e '^' 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00, 6, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x70,0x88,0x08,0x78,0x88,0x88,0x78,0x00,0x00, 6, // 0x62 'b' 0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0xf0,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00,0x00, 6, // 0x64 'd' 0x00,0x08,0x08,0x08,0x78,0x88,0x88,0x88,0x88,0x78,0x00,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x70,0x88,0x88,0xf8,0x80,0x80,0x78,0x00,0x00, 6, // 0x66 'f' 0x00,0x18,0x20,0x20,0xf8,0x20,0x20,0x20,0x20,0x20,0x00,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0xf0, 6, // 0x68 'h' 0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x88,0x00,0x00, 6, // 0x69 'i' 0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 6, // 0x6a 'j' 0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x90,0x60, 6, // 0x6b 'k' 0x00,0x80,0x80,0x80,0x88,0x90,0xa0,0xd0,0x88,0x88,0x00,0x00, 6, // 0x6c 'l' 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 6, // 0x6d 'm' 0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x00,0x00, 6, // 0x6e 'n' 0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x88,0x88,0x00,0x00, 6, // 0x6f 'o' 0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0xf0,0x88,0x88,0x88,0x88,0xf0,0x80,0x80,0x80, 6, // 0x71 'q' 0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0x08, 6, // 0x72 'r' 0x00,0x00,0x00,0xb0,0xc8,0x88,0x80,0x80,0x80,0x80,0x00,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,0x00, 6, // 0x74 't' 0x00,0x40,0x40,0x40,0xe0,0x40,0x40,0x40,0x48,0x30,0x00,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x78,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00, 6, // 0x77 'w' 0x00,0x00,0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x78,0x08,0x10,0xe0, 6, // 0x7a 'z' 0x00,0x00,0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00, 6, // 0x7b '{' 0x18,0x20,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x20,0x18,0x00, 6, // 0x7c '|' 0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, 6, // 0x7d '}' 0xc0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xc0,0x00, 6, // 0x7e '~' 0x00,0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x7f '' 0x00,0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00,0x00,0x00, 0 }; const int8u gse6x9[] = { 9, 0, 32, 128-32, 0x00,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x28,0x00,0x32,0x00,0x3c,0x00,0x46,0x00,0x50,0x00, 0x5a,0x00,0x64,0x00,0x6e,0x00,0x78,0x00,0x82,0x00,0x8c,0x00,0x96,0x00,0xa0,0x00,0xaa,0x00, 0xb4,0x00,0xbe,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x00,0x04,0x01, 0x0e,0x01,0x18,0x01,0x22,0x01,0x2c,0x01,0x36,0x01,0x40,0x01,0x4a,0x01,0x54,0x01,0x5e,0x01, 0x68,0x01,0x72,0x01,0x7c,0x01,0x86,0x01,0x90,0x01,0x9a,0x01,0xa4,0x01,0xae,0x01,0xb8,0x01, 0xc2,0x01,0xcc,0x01,0xd6,0x01,0xe0,0x01,0xea,0x01,0xf4,0x01,0xfe,0x01,0x08,0x02,0x12,0x02, 0x1c,0x02,0x26,0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x4e,0x02,0x58,0x02,0x62,0x02,0x6c,0x02, 0x76,0x02,0x80,0x02,0x8a,0x02,0x94,0x02,0x9e,0x02,0xa8,0x02,0xb2,0x02,0xbc,0x02,0xc6,0x02, 0xd0,0x02,0xda,0x02,0xe4,0x02,0xee,0x02,0xf8,0x02,0x02,0x03,0x0c,0x03,0x16,0x03,0x20,0x03, 0x2a,0x03,0x34,0x03,0x3e,0x03,0x48,0x03,0x52,0x03,0x5c,0x03,0x66,0x03,0x70,0x03,0x7a,0x03, 0x84,0x03,0x8e,0x03,0x98,0x03,0xa2,0x03,0xac,0x03,0xb6,0x03, 6, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, 6, // 0x22 '"' 0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00, 6, // 0x24 '$' 0x00,0x70,0xa8,0xa0,0x70,0x28,0xa8,0x70,0x00, 6, // 0x25 '%' 0x00,0xc8,0xc8,0x10,0x20,0x40,0x98,0x98,0x00, 6, // 0x26 '&' 0x00,0x60,0x90,0x90,0x60,0xa8,0x90,0x68,0x00, 6, // 0x27 ''' 0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10, 6, // 0x29 ')' 0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x40, 6, // 0x2a '*' 0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00, 6, // 0x2b '+' 0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00, 6, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40, 6, // 0x2d '-' 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00, 6, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, 6, // 0x2f '/' 0x00,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0x00, 6, // 0x30 '0' 0x00,0x70,0x88,0x98,0xa8,0xc8,0x88,0x70,0x00, 6, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, 6, // 0x32 '2' 0x00,0x70,0x88,0x08,0x10,0x20,0x40,0xf8,0x00, 6, // 0x33 '3' 0x00,0xf8,0x10,0x20,0x70,0x08,0x88,0x70,0x00, 6, // 0x34 '4' 0x00,0x10,0x20,0x40,0x90,0xf8,0x10,0x10,0x00, 6, // 0x35 '5' 0x00,0xf8,0x80,0xf0,0x08,0x08,0x88,0x70,0x00, 6, // 0x36 '6' 0x00,0x70,0x88,0x80,0xf0,0x88,0x88,0x70,0x00, 6, // 0x37 '7' 0x00,0xf8,0x08,0x08,0x10,0x20,0x40,0x40,0x00, 6, // 0x38 '8' 0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00, 6, // 0x39 '9' 0x00,0x70,0x88,0x88,0x78,0x08,0x88,0x70,0x00, 6, // 0x3a ':' 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00, 6, // 0x3b ';' 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40, 6, // 0x3c '<' 0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00, 6, // 0x3d '=' 0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00, 6, // 0x3e '>' 0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00, 6, // 0x3f '?' 0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00, 6, // 0x40 '@' 0x00,0x70,0x88,0x88,0xb8,0xb8,0x80,0x70,0x00, 6, // 0x41 'A' 0x00,0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00, 6, // 0x42 'B' 0x00,0xf0,0x88,0x88,0xf0,0x88,0x88,0xf0,0x00, 6, // 0x43 'C' 0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00, 6, // 0x44 'D' 0x00,0xe0,0x90,0x88,0x88,0x88,0x90,0xe0,0x00, 6, // 0x45 'E' 0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00, 6, // 0x46 'F' 0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00, 6, // 0x47 'G' 0x00,0x70,0x88,0x80,0xb8,0x88,0x88,0x70,0x00, 6, // 0x48 'H' 0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00, 6, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 6, // 0x4a 'J' 0x00,0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00, 6, // 0x4b 'K' 0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00, 6, // 0x4c 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00, 6, // 0x4d 'M' 0x00,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x00, 6, // 0x4e 'N' 0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00, 6, // 0x4f 'O' 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, 6, // 0x50 'P' 0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00, 6, // 0x51 'Q' 0x00,0x70,0x88,0x88,0x88,0xa8,0x90,0x68,0x00, 6, // 0x52 'R' 0x00,0xf0,0x88,0x88,0x88,0xf0,0x90,0x88,0x00, 6, // 0x53 'S' 0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00, 6, // 0x54 'T' 0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 6, // 0x55 'U' 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00, 6, // 0x56 'V' 0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00, 6, // 0x57 'W' 0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00, 6, // 0x58 'X' 0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00, 6, // 0x59 'Y' 0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, 6, // 0x5a 'Z' 0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00, 6, // 0x5b '[' 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, 6, // 0x5c '\' 0x00,0x80,0x80,0x40,0x20,0x10,0x08,0x08,0x00, 6, // 0x5d ']' 0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, 6, // 0x5e '^' 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00, 6, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00, 6, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00, 6, // 0x62 'b' 0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00, 6, // 0x64 'd' 0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x78,0x00, 6, // 0x66 'f' 0x00,0x18,0x20,0x20,0xf8,0x20,0x20,0x20,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x70, 6, // 0x68 'h' 0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x00, 6, // 0x69 'i' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, 6, // 0x6a 'j' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x90,0x60, 6, // 0x6b 'k' 0x00,0x00,0x80,0x88,0x90,0xa0,0xd0,0x88,0x00, 6, // 0x6c 'l' 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 6, // 0x6d 'm' 0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0x00, 6, // 0x6e 'n' 0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x00, 6, // 0x6f 'o' 0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0xf0,0x88,0x88,0xf0,0x80,0x80, 6, // 0x71 'q' 0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x08, 6, // 0x72 'r' 0x00,0x00,0x00,0xb8,0xc0,0x80,0x80,0x80,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x78,0x80,0x70,0x08,0xf0,0x00, 6, // 0x74 't' 0x00,0x40,0x40,0xe0,0x40,0x40,0x48,0x30,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x78,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00, 6, // 0x77 'w' 0x00,0x00,0x00,0x88,0x88,0xa8,0xd8,0x88,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x88,0x88,0x88,0x78,0x08,0x70, 6, // 0x7a 'z' 0x00,0x00,0x00,0xf8,0x10,0x20,0x40,0xf8,0x00, 6, // 0x7b '{' 0x18,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x18, 6, // 0x7c '|' 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, 6, // 0x7d '}' 0xc0,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0xc0, 6, // 0x7e '~' 0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00, 6, // 0x7f '' 0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00, 0 }; const int8u gse7x11[] = { 11, 0, 32, 128-32, 0x00,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x48,0x00,0x54,0x00,0x60,0x00, 0x6c,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9c,0x00,0xa8,0x00,0xb4,0x00,0xc0,0x00,0xcc,0x00, 0xd8,0x00,0xe4,0x00,0xf0,0x00,0xfc,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2c,0x01,0x38,0x01, 0x44,0x01,0x50,0x01,0x5c,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8c,0x01,0x98,0x01,0xa4,0x01, 0xb0,0x01,0xbc,0x01,0xc8,0x01,0xd4,0x01,0xe0,0x01,0xec,0x01,0xf8,0x01,0x04,0x02,0x10,0x02, 0x1c,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4c,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7c,0x02, 0x88,0x02,0x94,0x02,0xa0,0x02,0xac,0x02,0xb8,0x02,0xc4,0x02,0xd0,0x02,0xdc,0x02,0xe8,0x02, 0xf4,0x02,0x00,0x03,0x0c,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3c,0x03,0x48,0x03,0x54,0x03, 0x60,0x03,0x6c,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9c,0x03,0xa8,0x03,0xb4,0x03,0xc0,0x03, 0xcc,0x03,0xd8,0x03,0xe4,0x03,0xf0,0x03,0xfc,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2c,0x04, 0x38,0x04,0x44,0x04,0x50,0x04,0x5c,0x04,0x68,0x04,0x74,0x04, 7, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x21 '!' 0x00,0x10,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x00,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x00,0x00, 7, // 0x24 '$' 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, 7, // 0x25 '%' 0x00,0x00,0x42,0xa4,0x48,0x10,0x24,0x4a,0x84,0x00,0x00, 7, // 0x26 '&' 0x00,0x30,0x48,0x48,0x30,0x60,0x94,0x98,0x6c,0x00,0x00, 7, // 0x27 ''' 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x08,0x04,0x00,0x00, 7, // 0x29 ')' 0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x20,0x40,0x00,0x00, 7, // 0x2a '*' 0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00, 7, // 0x2b '+' 0x00,0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00, 7, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60, 7, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00, 7, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, 7, // 0x2f '/' 0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, 7, // 0x30 '0' 0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x44,0x38,0x00,0x00, 7, // 0x31 '1' 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00, 7, // 0x32 '2' 0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x44,0x7c,0x00,0x00, 7, // 0x33 '3' 0x00,0x7c,0x48,0x10,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x34 '4' 0x00,0x08,0x10,0x20,0x48,0x48,0x7c,0x08,0x1c,0x00,0x00, 7, // 0x35 '5' 0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x36 '6' 0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x37 '7' 0x00,0x7c,0x44,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00, 7, // 0x38 '8' 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x39 '9' 0x00,0x38,0x44,0x44,0x44,0x3c,0x04,0x08,0x30,0x00,0x00, 7, // 0x3a ':' 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00, 7, // 0x3b ';' 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x30,0x60,0x00, 7, // 0x3c '<' 0x00,0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00, 7, // 0x3d '=' 0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00, 7, // 0x3e '>' 0x00,0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00, 7, // 0x3f '?' 0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00, 7, // 0x40 '@' 0x00,0x30,0x48,0x04,0x34,0x54,0x54,0x54,0x28,0x00,0x00, 7, // 0x41 'A' 0x00,0x10,0x28,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00, 7, // 0x42 'B' 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, 7, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, 7, // 0x45 'E' 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x7c,0x00,0x00, 7, // 0x46 'F' 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x00,0x00, 7, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x5c,0x44,0x44,0x38,0x00,0x00, 7, // 0x48 'H' 0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x49 'I' 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x4a 'J' 0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00, 7, // 0x4b 'K' 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x00,0x00, 7, // 0x4c 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00, 7, // 0x4d 'M' 0x00,0x44,0x6c,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x4e 'N' 0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x44,0x00,0x00, 7, // 0x4f 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, 7, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, 7, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, 7, // 0x53 'S' 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00, 7, // 0x54 'T' 0x00,0x7c,0x54,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 7, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x56 'V' 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, 7, // 0x57 'W' 0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00, 7, // 0x58 'X' 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, 7, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x5a 'Z' 0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x44,0x7c,0x00,0x00, 7, // 0x5b '[' 0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,0x00, 7, // 0x5c '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00,0x00, 7, // 0x5d ']' 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, 7, // 0x5e '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00, 7, // 0x60 '`' 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3c,0x44,0x44,0x3c,0x00,0x00, 7, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x64 'd' 0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x44,0x3c,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x44,0x38,0x00,0x00, 7, // 0x66 'f' 0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x70,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x44,0x38, 7, // 0x68 'h' 0x00,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00, 7, // 0x69 'i' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x6a 'j' 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30,0x00, 7, // 0x6b 'k' 0x00,0x40,0x40,0x44,0x48,0x50,0x68,0x44,0x44,0x00,0x00, 7, // 0x6c 'l' 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x6d 'm' 0x00,0x00,0x00,0xa8,0x54,0x54,0x54,0x54,0x54,0x00,0x00, 7, // 0x6e 'n' 0x00,0x00,0x00,0xb8,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x6f 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, 7, // 0x71 'q' 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x44,0x3c,0x04,0x04, 7, // 0x72 'r' 0x00,0x00,0x00,0x58,0x64,0x44,0x40,0x40,0x40,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x3c,0x40,0x38,0x04,0x04,0x78,0x00,0x00, 7, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x24,0x18,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x3c,0x04,0x08,0x30,0x00, 7, // 0x7a 'z' 0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x44,0x7c,0x00,0x00, 7, // 0x7b '{' 0x00,0x0c,0x10,0x10,0x10,0x60,0x10,0x10,0x0c,0x00,0x00, 7, // 0x7c '|' 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, 7, // 0x7d '}' 0x00,0x60,0x10,0x10,0x10,0x0c,0x10,0x10,0x60,0x00,0x00, 7, // 0x7e '~' 0x00,0x00,0x64,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7f '' 0x00,0x00,0x00,0x10,0x28,0x44,0x44,0x7c,0x00,0x00,0x00, 0 }; const int8u gse7x11_bold[] = { 11, 0, 32, 128-32, 0x00,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x48,0x00,0x54,0x00,0x60,0x00, 0x6c,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9c,0x00,0xa8,0x00,0xb4,0x00,0xc0,0x00,0xcc,0x00, 0xd8,0x00,0xe4,0x00,0xf0,0x00,0xfc,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2c,0x01,0x38,0x01, 0x44,0x01,0x50,0x01,0x5c,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8c,0x01,0x98,0x01,0xa4,0x01, 0xb0,0x01,0xbc,0x01,0xc8,0x01,0xd4,0x01,0xe0,0x01,0xec,0x01,0xf8,0x01,0x04,0x02,0x10,0x02, 0x1c,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4c,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7c,0x02, 0x88,0x02,0x94,0x02,0xa0,0x02,0xac,0x02,0xb8,0x02,0xc4,0x02,0xd0,0x02,0xdc,0x02,0xe8,0x02, 0xf4,0x02,0x00,0x03,0x0c,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3c,0x03,0x48,0x03,0x54,0x03, 0x60,0x03,0x6c,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9c,0x03,0xa8,0x03,0xb4,0x03,0xc0,0x03, 0xcc,0x03,0xd8,0x03,0xe4,0x03,0xf0,0x03,0xfc,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2c,0x04, 0x38,0x04,0x44,0x04,0x50,0x04,0x5c,0x04,0x68,0x04,0x74,0x04, 7, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x21 '!' 0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00, 7, // 0x22 '"' 0x00,0x6c,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x00,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x00,0x00, 7, // 0x24 '$' 0x30,0x30,0x78,0xcc,0xc0,0x78,0x0c,0xcc,0x78,0x30,0x30, 7, // 0x25 '%' 0x00,0x00,0xc4,0x0c,0x18,0x30,0x60,0xc0,0x8c,0x00,0x00, 7, // 0x26 '&' 0x00,0x30,0x58,0x58,0x30,0x74,0xdc,0xd8,0x6c,0x00,0x00, 7, // 0x27 ''' 0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00, 7, // 0x29 ')' 0x00,0xc0,0x60,0x30,0x30,0x30,0x30,0x60,0xc0,0x00,0x00, 7, // 0x2a '*' 0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00, 7, // 0x2b '+' 0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00, 7, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00, 7, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00, 7, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, 7, // 0x2f '/' 0x00,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0x00,0x00, 7, // 0x30 '0' 0x00,0x78,0xcc,0xcc,0xdc,0xec,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x31 '1' 0x00,0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0xfc,0x00,0x00, 7, // 0x32 '2' 0x00,0x78,0xcc,0xcc,0x18,0x30,0x60,0xcc,0xfc,0x00,0x00, 7, // 0x33 '3' 0x00,0xfc,0x98,0x30,0x78,0x0c,0x0c,0xcc,0x78,0x00,0x00, 7, // 0x34 '4' 0x00,0x18,0x30,0x68,0xd8,0xd8,0xfc,0x18,0x3c,0x00,0x00, 7, // 0x35 '5' 0x00,0xfc,0xc0,0xc0,0xf8,0x0c,0x0c,0xcc,0x78,0x00,0x00, 7, // 0x36 '6' 0x00,0x38,0x60,0xc0,0xf8,0xcc,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x37 '7' 0x00,0xfc,0x8c,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00, 7, // 0x38 '8' 0x00,0x78,0xcc,0xcc,0x78,0xcc,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x39 '9' 0x00,0x78,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0x70,0x00,0x00, 7, // 0x3a ':' 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x3b ';' 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x60,0x00, 7, // 0x3c '<' 0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x00, 7, // 0x3d '=' 0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00, 7, // 0x3e '>' 0x00,0x00,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,0x00, 7, // 0x3f '?' 0x00,0x78,0xcc,0xcc,0x18,0x30,0x30,0x00,0x30,0x00,0x00, 7, // 0x40 '@' 0x00,0x70,0x88,0x04,0x74,0xb4,0xb4,0xb4,0x68,0x00,0x00, 7, // 0x41 'A' 0x00,0x30,0x78,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x42 'B' 0x00,0xf8,0xcc,0xcc,0xf8,0xcc,0xcc,0xcc,0xf8,0x00,0x00, 7, // 0x43 'C' 0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xc0,0xcc,0x78,0x00,0x00, 7, // 0x44 'D' 0x00,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xd8,0xf0,0x00,0x00, 7, // 0x45 'E' 0x00,0xfc,0xc4,0xd0,0xf0,0xd0,0xc0,0xc4,0xfc,0x00,0x00, 7, // 0x46 'F' 0x00,0xfc,0xc4,0xd0,0xf0,0xd0,0xc0,0xc0,0xc0,0x00,0x00, 7, // 0x47 'G' 0x00,0x78,0xcc,0xc0,0xc0,0xdc,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x48 'H' 0x00,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x49 'I' 0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, 7, // 0x4a 'J' 0x00,0x3c,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00,0x00, 7, // 0x4b 'K' 0x00,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x4c 'L' 0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc4,0xfc,0x00,0x00, 7, // 0x4d 'M' 0x00,0x84,0xcc,0xfc,0xb4,0xcc,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x4e 'N' 0x00,0xcc,0xcc,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x4f 'O' 0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x50 'P' 0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0x00,0x00, 7, // 0x51 'Q' 0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xdc,0x78,0x18,0x0c,0x00, 7, // 0x52 'R' 0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xd8,0xcc,0xcc,0x00,0x00, 7, // 0x53 'S' 0x00,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x00,0x00, 7, // 0x54 'T' 0x00,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, 7, // 0x55 'U' 0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x56 'V' 0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00, 7, // 0x57 'W' 0x00,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00, 7, // 0x58 'X' 0x00,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x59 'Y' 0x00,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x78,0x00,0x00, 7, // 0x5a 'Z' 0x00,0xfc,0x8c,0x18,0x30,0x60,0xc0,0xc4,0xfc,0x00,0x00, 7, // 0x5b '[' 0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00, 7, // 0x5c '\' 0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x00,0x00, 7, // 0x5d ']' 0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00, 7, // 0x5e '^' 0x00,0x10,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00, 7, // 0x60 '`' 0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x70,0x18,0x78,0xd8,0xd8,0x6c,0x00,0x00, 7, // 0x62 'b' 0x00,0x60,0x60,0x60,0x78,0x6c,0x6c,0x6c,0x78,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x78,0xcc,0xc0,0xc0,0xcc,0x78,0x00,0x00, 7, // 0x64 'd' 0x00,0x18,0x18,0x18,0x78,0xd8,0xd8,0xd8,0x6c,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x78,0xcc,0xfc,0xc0,0xcc,0x78,0x00,0x00, 7, // 0x66 'f' 0x00,0x18,0x34,0x30,0x78,0x30,0x30,0x30,0x78,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x6c,0xd8,0xd8,0xd8,0x78,0x18,0xd8,0x70, 7, // 0x68 'h' 0x00,0xc0,0xc0,0xd8,0xec,0xcc,0xcc,0xcc,0xcc,0x00,0x00, 7, // 0x69 'i' 0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x78,0x00,0x00, 7, // 0x6a 'j' 0x00,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x6c,0x6c,0x38, 7, // 0x6b 'k' 0x00,0xc0,0xc0,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0x00,0x00, 7, // 0x6c 'l' 0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, 7, // 0x6d 'm' 0x00,0x00,0x00,0xe8,0xfc,0xd4,0xd4,0xc4,0xc4,0x00,0x00, 7, // 0x6e 'n' 0x00,0x00,0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00, 7, // 0x6f 'o' 0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0, 7, // 0x71 'q' 0x00,0x00,0x00,0x7c,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x0c, 7, // 0x72 'r' 0x00,0x00,0x00,0xd8,0xec,0xcc,0xc0,0xc0,0xc0,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x78,0xcc,0x60,0x18,0xcc,0x78,0x00,0x00, 7, // 0x74 't' 0x00,0x20,0x60,0x60,0xf0,0x60,0x60,0x68,0x30,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0xcc,0x78,0x30,0x78,0xcc,0xcc,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0xf0, 7, // 0x7a 'z' 0x00,0x00,0x00,0xfc,0x98,0x30,0x60,0xc4,0xfc,0x00,0x00, 7, // 0x7b '{' 0x1c,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x1c,0x00,0x00, 7, // 0x7c '|' 0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x30,0x30,0x00,0x00, 7, // 0x7d '}' 0xe0,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0xe0,0x00,0x00, 7, // 0x7e '~' 0x00,0x34,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7f '' 0x00,0x00,0x00,0x30,0x78,0xcc,0xcc,0xfc,0x00,0x00,0x00, 0 }; const int8u gse7x15[] = { 15, 0, 32, 128-32, 0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00, 0x90,0x00,0xa0,0x00,0xb0,0x00,0xc0,0x00,0xd0,0x00,0xe0,0x00,0xf0,0x00,0x00,0x01,0x10,0x01, 0x20,0x01,0x30,0x01,0x40,0x01,0x50,0x01,0x60,0x01,0x70,0x01,0x80,0x01,0x90,0x01,0xa0,0x01, 0xb0,0x01,0xc0,0x01,0xd0,0x01,0xe0,0x01,0xf0,0x01,0x00,0x02,0x10,0x02,0x20,0x02,0x30,0x02, 0x40,0x02,0x50,0x02,0x60,0x02,0x70,0x02,0x80,0x02,0x90,0x02,0xa0,0x02,0xb0,0x02,0xc0,0x02, 0xd0,0x02,0xe0,0x02,0xf0,0x02,0x00,0x03,0x10,0x03,0x20,0x03,0x30,0x03,0x40,0x03,0x50,0x03, 0x60,0x03,0x70,0x03,0x80,0x03,0x90,0x03,0xa0,0x03,0xb0,0x03,0xc0,0x03,0xd0,0x03,0xe0,0x03, 0xf0,0x03,0x00,0x04,0x10,0x04,0x20,0x04,0x30,0x04,0x40,0x04,0x50,0x04,0x60,0x04,0x70,0x04, 0x80,0x04,0x90,0x04,0xa0,0x04,0xb0,0x04,0xc0,0x04,0xd0,0x04,0xe0,0x04,0xf0,0x04,0x00,0x05, 0x10,0x05,0x20,0x05,0x30,0x05,0x40,0x05,0x50,0x05,0x60,0x05,0x70,0x05,0x80,0x05,0x90,0x05, 0xa0,0x05,0xb0,0x05,0xc0,0x05,0xd0,0x05,0xe0,0x05,0xf0,0x05, 7, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x21 '!' 0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x00,0x00,0x48,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x48,0x00,0x00,0x00, 7, // 0x24 '$' 0x00,0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x54,0x38,0x10,0x00,0x00,0x00, 7, // 0x25 '%' 0x00,0x00,0x44,0x44,0x08,0x08,0x10,0x10,0x20,0x20,0x44,0x44,0x00,0x00,0x00, 7, // 0x26 '&' 0x00,0x00,0x00,0x30,0x48,0x48,0x30,0x60,0x94,0x98,0x90,0x6c,0x00,0x00,0x00, 7, // 0x27 ''' 0x00,0x00,0x20,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x04,0x08,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x08,0x04,0x00,0x00,0x00, 7, // 0x29 ')' 0x00,0x40,0x20,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x20,0x40,0x00,0x00,0x00, 7, // 0x2a '*' 0x00,0x00,0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00,0x00,0x00, 7, // 0x2b '+' 0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x7c,0x10,0x10,0x10,0x00,0x00,0x00,0x00, 7, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, 7, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x2f '/' 0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00,0x00, 7, // 0x30 '0' 0x00,0x00,0x38,0x44,0x44,0x4c,0x54,0x64,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x31 '1' 0x00,0x00,0x10,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00,0x00, 7, // 0x32 '2' 0x00,0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x44,0x7c,0x00,0x00,0x00, 7, // 0x33 '3' 0x00,0x00,0x7c,0x44,0x08,0x10,0x38,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 7, // 0x34 '4' 0x00,0x00,0x08,0x10,0x20,0x40,0x48,0x48,0x7c,0x08,0x08,0x1c,0x00,0x00,0x00, 7, // 0x35 '5' 0x00,0x00,0x7c,0x40,0x40,0x40,0x78,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 7, // 0x36 '6' 0x00,0x00,0x18,0x20,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x37 '7' 0x00,0x00,0x7c,0x44,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 7, // 0x38 '8' 0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x39 '9' 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x08,0x30,0x00,0x00,0x00, 7, // 0x3a ':' 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, 7, // 0x3b ';' 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00, 7, // 0x3c '<' 0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00,0x00, 7, // 0x3d '=' 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x3e '>' 0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00,0x00, 7, // 0x3f '?' 0x00,0x00,0x78,0x84,0x84,0x84,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00,0x00, 7, // 0x40 '@' 0x00,0x00,0x00,0x30,0x48,0x04,0x34,0x54,0x54,0x54,0x54,0x28,0x00,0x00,0x00, 7, // 0x41 'A' 0x00,0x00,0x10,0x28,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x42 'B' 0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, 7, // 0x43 'C' 0x00,0x00,0x38,0x44,0x44,0x40,0x40,0x40,0x40,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x44 'D' 0x00,0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, 7, // 0x45 'E' 0x00,0x00,0x7c,0x40,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, 7, // 0x46 'F' 0x00,0x00,0x7c,0x40,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x47 'G' 0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x5c,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x48 'H' 0x00,0x00,0x44,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x49 'I' 0x00,0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x4a 'J' 0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, 7, // 0x4b 'K' 0x00,0x00,0x44,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x4c 'L' 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, 7, // 0x4d 'M' 0x00,0x00,0x44,0x6c,0x54,0x54,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x4e 'N' 0x00,0x00,0x44,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x4f 'O' 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x50 'P' 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x51 'Q' 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, 7, // 0x52 'R' 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x50,0x48,0x44,0x44,0x00,0x00,0x00, 7, // 0x53 'S' 0x00,0x00,0x38,0x44,0x44,0x40,0x38,0x04,0x04,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x54 'T' 0x00,0x00,0x7c,0x54,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 7, // 0x55 'U' 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x56 'V' 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, 7, // 0x57 'W' 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x59 'Y' 0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x5a 'Z' 0x00,0x00,0x7c,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, 7, // 0x5b '[' 0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,0x00, 7, // 0x5c '\' 0x00,0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00,0x00,0x00, 7, // 0x5d ']' 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, 7, // 0x5e '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, 7, // 0x60 '`' 0x00,0x20,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x3c,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, 7, // 0x62 'b' 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x64 'd' 0x00,0x00,0x04,0x04,0x04,0x3c,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x7c,0x40,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x66 'f' 0x00,0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x00,0x3a,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x44,0x38,0x00, 7, // 0x68 'h' 0x00,0x00,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x69 'i' 0x00,0x00,0x10,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x6a 'j' 0x00,0x00,0x08,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00, 7, // 0x6b 'k' 0x00,0x00,0x40,0x40,0x44,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, 7, // 0x6c 'l' 0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x6d 'm' 0x00,0x00,0x00,0x00,0xa8,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x00,0x00,0x00, 7, // 0x6e 'n' 0x00,0x00,0x00,0x00,0xb8,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x6f 'o' 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00, 7, // 0x71 'q' 0x00,0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x04,0x00, 7, // 0x72 'r' 0x00,0x00,0x00,0x00,0x58,0x64,0x44,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x74 't' 0x00,0x00,0x20,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x08,0x70,0x00, 7, // 0x7a 'z' 0x00,0x00,0x00,0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x40,0x7c,0x00,0x00,0x00, 7, // 0x7b '{' 0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x0c,0x00,0x00, 7, // 0x7c '|' 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x00, 7, // 0x7d '}' 0x00,0x60,0x10,0x10,0x10,0x10,0x10,0x0c,0x10,0x10,0x10,0x10,0x60,0x00,0x00, 7, // 0x7e '~' 0x00,0x00,0x64,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7f '' 0x00,0x00,0x00,0x00,0x00,0x10,0x28,0x44,0x44,0x7c,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u gse7x15_bold[] = { 15, 0, 32, 128-32, 0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00, 0x90,0x00,0xa0,0x00,0xb0,0x00,0xc0,0x00,0xd0,0x00,0xe0,0x00,0xf0,0x00,0x00,0x01,0x10,0x01, 0x20,0x01,0x30,0x01,0x40,0x01,0x50,0x01,0x60,0x01,0x70,0x01,0x80,0x01,0x90,0x01,0xa0,0x01, 0xb0,0x01,0xc0,0x01,0xd0,0x01,0xe0,0x01,0xf0,0x01,0x00,0x02,0x10,0x02,0x20,0x02,0x30,0x02, 0x40,0x02,0x50,0x02,0x60,0x02,0x70,0x02,0x80,0x02,0x90,0x02,0xa0,0x02,0xb0,0x02,0xc0,0x02, 0xd0,0x02,0xe0,0x02,0xf0,0x02,0x00,0x03,0x10,0x03,0x20,0x03,0x30,0x03,0x40,0x03,0x50,0x03, 0x60,0x03,0x70,0x03,0x80,0x03,0x90,0x03,0xa0,0x03,0xb0,0x03,0xc0,0x03,0xd0,0x03,0xe0,0x03, 0xf0,0x03,0x00,0x04,0x10,0x04,0x20,0x04,0x30,0x04,0x40,0x04,0x50,0x04,0x60,0x04,0x70,0x04, 0x80,0x04,0x90,0x04,0xa0,0x04,0xb0,0x04,0xc0,0x04,0xd0,0x04,0xe0,0x04,0xf0,0x04,0x00,0x05, 0x10,0x05,0x20,0x05,0x30,0x05,0x40,0x05,0x50,0x05,0x60,0x05,0x70,0x05,0x80,0x05,0x90,0x05, 0xa0,0x05,0xb0,0x05,0xc0,0x05,0xd0,0x05,0xe0,0x05,0xf0,0x05, 7, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x21 '!' 0x00,0x00,0x00,0x30,0x78,0x78,0x78,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x6c,0x6c,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x00,0x00,0x48,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x48,0x00,0x00,0x00, 7, // 0x24 '$' 0x00,0x30,0x30,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x30,0x30,0x00,0x00, 7, // 0x25 '%' 0x00,0x00,0x00,0x64,0x6c,0x08,0x18,0x10,0x30,0x20,0x6c,0x4c,0x00,0x00,0x00, 7, // 0x26 '&' 0x00,0x00,0x00,0x30,0x58,0x58,0x30,0x74,0xdc,0xd8,0xd8,0x6c,0x00,0x00,0x00, 7, // 0x27 ''' 0x00,0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x0c,0x18,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x18,0x0c,0x00,0x00,0x00, 7, // 0x29 ')' 0x00,0xc0,0x60,0x30,0x18,0x18,0x18,0x18,0x18,0x30,0x60,0xc0,0x00,0x00,0x00, 7, // 0x2a '*' 0x00,0x00,0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00,0x00,0x00, 7, // 0x2b '+' 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00,0x00,0x00, 7, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, 7, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x2f '/' 0x00,0x00,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0xc0,0xc0,0x00,0x00,0x00, 7, // 0x30 '0' 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xdc,0xec,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x31 '1' 0x00,0x00,0x30,0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0x30,0xfc,0x00,0x00,0x00, 7, // 0x32 '2' 0x00,0x00,0x78,0xcc,0xcc,0x0c,0x18,0x30,0x60,0xc0,0xcc,0xfc,0x00,0x00,0x00, 7, // 0x33 '3' 0x00,0x00,0xfc,0x8c,0x18,0x30,0x78,0x0c,0x0c,0x0c,0xcc,0x78,0x00,0x00,0x00, 7, // 0x34 '4' 0x00,0x00,0x18,0x30,0x60,0xc8,0xd8,0xd8,0xfc,0x18,0x18,0x3c,0x00,0x00,0x00, 7, // 0x35 '5' 0x00,0x00,0xfc,0xc0,0xc0,0xc0,0xf8,0x0c,0x0c,0x0c,0xcc,0x78,0x00,0x00,0x00, 7, // 0x36 '6' 0x00,0x00,0x38,0x60,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x37 '7' 0x00,0x00,0xfc,0x8c,0x0c,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00, 7, // 0x38 '8' 0x00,0x00,0x78,0xcc,0xcc,0xcc,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x39 '9' 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x18,0x70,0x00,0x00,0x00, 7, // 0x3a ':' 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00, 7, // 0x3b ';' 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, 7, // 0x3c '<' 0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x0c,0x00,0x00,0x00, 7, // 0x3d '=' 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x3e '>' 0x00,0x00,0x00,0xc0,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0xc0,0x00,0x00,0x00, 7, // 0x3f '?' 0x00,0x00,0x78,0xcc,0xcc,0x18,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x40 '@' 0x00,0x00,0x00,0x70,0x88,0x04,0x74,0xb4,0xb4,0xb4,0xb4,0x68,0x00,0x00,0x00, 7, // 0x41 'A' 0x00,0x00,0x30,0x78,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x42 'B' 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0x00,0x00,0x00, 7, // 0x43 'C' 0x00,0x00,0x78,0xcc,0xc4,0xc0,0xc0,0xc0,0xc0,0xc4,0xcc,0x78,0x00,0x00,0x00, 7, // 0x44 'D' 0x00,0x00,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xd8,0xf0,0x00,0x00,0x00, 7, // 0x45 'E' 0x00,0x00,0xfc,0xc4,0xc0,0xd0,0xf0,0xd0,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, 7, // 0x46 'F' 0x00,0x00,0xfc,0xc4,0xc0,0xd0,0xf0,0xd0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, 7, // 0x47 'G' 0x00,0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xdc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x48 'H' 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x49 'I' 0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, 7, // 0x4a 'J' 0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00,0x00,0x00, 7, // 0x4b 'K' 0x00,0x00,0xcc,0xcc,0xd8,0xd8,0xf0,0xd8,0xd8,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x4c 'L' 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, 7, // 0x4d 'M' 0x00,0x00,0x84,0xcc,0xfc,0xb4,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x4e 'N' 0x00,0x00,0xcc,0xcc,0xcc,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x4f 'O' 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x50 'P' 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, 7, // 0x51 'Q' 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xdc,0x78,0x18,0x0c,0x00,0x00, 7, // 0x52 'R' 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0xd8,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x53 'S' 0x00,0x00,0x78,0xcc,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x54 'T' 0x00,0x00,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, 7, // 0x55 'U' 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x56 'V' 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00, 7, // 0x57 'W' 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x59 'Y' 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, 7, // 0x5a 'Z' 0x00,0x00,0xfc,0x8c,0x0c,0x18,0x30,0x60,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, 7, // 0x5b '[' 0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00, 7, // 0x5c '\' 0x00,0x00,0xc0,0xc0,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x00,0x00,0x00, 7, // 0x5d ']' 0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00, 7, // 0x5e '^' 0x00,0x10,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, 7, // 0x60 '`' 0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x00,0x70,0xd8,0x18,0x78,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, 7, // 0x62 'b' 0x00,0x00,0x60,0x60,0x60,0x78,0x6c,0x6c,0x6c,0x6c,0x6c,0x78,0x00,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xc0,0xcc,0x78,0x00,0x00,0x00, 7, // 0x64 'd' 0x00,0x00,0x18,0x18,0x18,0x78,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x00,0x78,0xcc,0xcc,0xfc,0xc0,0xc0,0xcc,0x78,0x00,0x00,0x00, 7, // 0x66 'f' 0x00,0x00,0x30,0x68,0x60,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x00,0x6c,0xd8,0xd8,0xd8,0xd8,0xd8,0x78,0x18,0xd8,0x70,0x00, 7, // 0x68 'h' 0x00,0x00,0xc0,0xc0,0xc0,0xd8,0xec,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x69 'i' 0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, 7, // 0x6a 'j' 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00, 7, // 0x6b 'k' 0x00,0x00,0xc0,0xc0,0xcc,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x6c 'l' 0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, 7, // 0x6d 'm' 0x00,0x00,0x00,0x00,0xe8,0xfc,0xd4,0xd4,0xd4,0xc4,0xc4,0xc4,0x00,0x00,0x00, 7, // 0x6e 'n' 0x00,0x00,0x00,0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00, 7, // 0x6f 'o' 0x00,0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0x00, 7, // 0x71 'q' 0x00,0x00,0x00,0x00,0x7c,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x0c,0x00, 7, // 0x72 'r' 0x00,0x00,0x00,0x00,0xd8,0xec,0xcc,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x00,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x00,0x00,0x00, 7, // 0x74 't' 0x00,0x00,0x20,0x60,0x60,0xf0,0x60,0x60,0x60,0x60,0x6c,0x38,0x00,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x00,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x00,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0x00,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0xf0,0x00, 7, // 0x7a 'z' 0x00,0x00,0x00,0x00,0xfc,0x8c,0x18,0x30,0x60,0xc0,0xc4,0xfc,0x00,0x00,0x00, 7, // 0x7b '{' 0x00,0x1c,0x30,0x30,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x30,0x1c,0x00,0x00, 7, // 0x7c '|' 0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x00, 7, // 0x7d '}' 0x00,0xe0,0x30,0x30,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0x30,0xe0,0x00,0x00, 7, // 0x7e '~' 0x00,0x00,0x34,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7f '' 0x00,0x00,0x00,0x00,0x00,0x30,0x78,0xcc,0xcc,0xfc,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u gse8x16[] = { 16, 0, 32, 128-32, 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x44,0x00,0x55,0x00,0x66,0x00,0x77,0x00,0x88,0x00, 0x99,0x00,0xaa,0x00,0xbb,0x00,0xcc,0x00,0xdd,0x00,0xee,0x00,0xff,0x00,0x10,0x01,0x21,0x01, 0x32,0x01,0x43,0x01,0x54,0x01,0x65,0x01,0x76,0x01,0x87,0x01,0x98,0x01,0xa9,0x01,0xba,0x01, 0xcb,0x01,0xdc,0x01,0xed,0x01,0xfe,0x01,0x0f,0x02,0x20,0x02,0x31,0x02,0x42,0x02,0x53,0x02, 0x64,0x02,0x75,0x02,0x86,0x02,0x97,0x02,0xa8,0x02,0xb9,0x02,0xca,0x02,0xdb,0x02,0xec,0x02, 0xfd,0x02,0x0e,0x03,0x1f,0x03,0x30,0x03,0x41,0x03,0x52,0x03,0x63,0x03,0x74,0x03,0x85,0x03, 0x96,0x03,0xa7,0x03,0xb8,0x03,0xc9,0x03,0xda,0x03,0xeb,0x03,0xfc,0x03,0x0d,0x04,0x1e,0x04, 0x2f,0x04,0x40,0x04,0x51,0x04,0x62,0x04,0x73,0x04,0x84,0x04,0x95,0x04,0xa6,0x04,0xb7,0x04, 0xc8,0x04,0xd9,0x04,0xea,0x04,0xfb,0x04,0x0c,0x05,0x1d,0x05,0x2e,0x05,0x3f,0x05,0x50,0x05, 0x61,0x05,0x72,0x05,0x83,0x05,0x94,0x05,0xa5,0x05,0xb6,0x05,0xc7,0x05,0xd8,0x05,0xe9,0x05, 0xfa,0x05,0x0b,0x06,0x1c,0x06,0x2d,0x06,0x3e,0x06,0x4f,0x06, 8, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x21 '!' 0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00,0x00, 8, // 0x22 '"' 0x00,0x24,0x24,0x24,0x24,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x23 '#' 0x00,0x00,0x24,0x24,0x24,0x7e,0x24,0x24,0x7e,0x24,0x24,0x24,0x00,0x00,0x00,0x00, 8, // 0x24 '$' 0x00,0x14,0x14,0x3e,0x55,0x54,0x54,0x3e,0x15,0x15,0x55,0x3e,0x14,0x14,0x00,0x00, 8, // 0x25 '%' 0x00,0x00,0x32,0x56,0x6c,0x04,0x08,0x08,0x10,0x13,0x25,0x26,0x00,0x00,0x00,0x00, 8, // 0x26 '&' 0x00,0x00,0x18,0x24,0x24,0x24,0x18,0x28,0x45,0x46,0x44,0x3b,0x00,0x00,0x00,0x00, 8, // 0x27 ''' 0x00,0x00,0x08,0x08,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x28 '(' 0x00,0x04,0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x04,0x00,0x00,0x00, 8, // 0x29 ')' 0x00,0x10,0x08,0x04,0x04,0x02,0x02,0x02,0x02,0x04,0x04,0x08,0x10,0x00,0x00,0x00, 8, // 0x2a '*' 0x00,0x00,0x00,0x00,0x66,0x24,0x18,0xff,0x18,0x24,0x66,0x00,0x00,0x00,0x00,0x00, 8, // 0x2b '+' 0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, 8, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x20,0x00, 8, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, 8, // 0x2f '/' 0x00,0x02,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00,0x00, 8, // 0x30 '0' 0x00,0x00,0x3c,0x42,0x42,0x46,0x4a,0x52,0x62,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x31 '1' 0x00,0x00,0x08,0x08,0x18,0x38,0x08,0x08,0x08,0x08,0x08,0x3e,0x00,0x00,0x00,0x00, 8, // 0x32 '2' 0x00,0x00,0x3c,0x42,0x42,0x02,0x04,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,0x00,0x00, 8, // 0x33 '3' 0x00,0x00,0x7e,0x42,0x04,0x08,0x1c,0x02,0x02,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x34 '4' 0x00,0x00,0x04,0x08,0x10,0x24,0x44,0x44,0x7e,0x04,0x04,0x0e,0x00,0x00,0x00,0x00, 8, // 0x35 '5' 0x00,0x00,0x7e,0x42,0x40,0x40,0x7c,0x02,0x02,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x36 '6' 0x00,0x00,0x1c,0x20,0x40,0x40,0x7c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x37 '7' 0x00,0x00,0x7e,0x42,0x42,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00, 8, // 0x38 '8' 0x00,0x00,0x3c,0x42,0x42,0x42,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x39 '9' 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3e,0x02,0x02,0x04,0x38,0x00,0x00,0x00,0x00, 8, // 0x3a ':' 0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x3b ';' 0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x40,0x00, 8, // 0x3c '<' 0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x02,0x00,0x00,0x00,0x00, 8, // 0x3d '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x3e '>' 0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x00,0x00,0x00,0x00, 8, // 0x3f '?' 0x00,0x00,0x3c,0x42,0x42,0x42,0x04,0x08,0x08,0x00,0x08,0x08,0x00,0x00,0x00,0x00, 8, // 0x40 '@' 0x00,0x00,0x3c,0x42,0x01,0x39,0x49,0x49,0x49,0x49,0x49,0x36,0x00,0x00,0x00,0x00, 8, // 0x41 'A' 0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, 8, // 0x42 'B' 0x00,0x00,0x7c,0x22,0x22,0x22,0x3c,0x22,0x22,0x22,0x22,0x7c,0x00,0x00,0x00,0x00, 8, // 0x43 'C' 0x00,0x00,0x3c,0x42,0x42,0x40,0x40,0x40,0x40,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x44 'D' 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x7c,0x00,0x00,0x00,0x00, 8, // 0x45 'E' 0x00,0x00,0x7e,0x22,0x20,0x28,0x38,0x28,0x20,0x20,0x22,0x7e,0x00,0x00,0x00,0x00, 8, // 0x46 'F' 0x00,0x00,0x7e,0x22,0x20,0x28,0x38,0x28,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, 8, // 0x47 'G' 0x00,0x00,0x3c,0x42,0x42,0x40,0x40,0x4e,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x48 'H' 0x00,0x00,0x42,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, 8, // 0x49 'I' 0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, 8, // 0x4a 'J' 0x00,0x00,0x0e,0x04,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,0x00,0x00,0x00, 8, // 0x4b 'K' 0x00,0x00,0x62,0x22,0x24,0x28,0x30,0x28,0x24,0x22,0x22,0x62,0x00,0x00,0x00,0x00, 8, // 0x4c 'L' 0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x7e,0x00,0x00,0x00,0x00, 8, // 0x4d 'M' 0x00,0x00,0x41,0x63,0x55,0x49,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00, 8, // 0x4e 'N' 0x00,0x00,0x42,0x42,0x62,0x52,0x4a,0x46,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, 8, // 0x4f 'O' 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x50 'P' 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x3c,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, 8, // 0x51 'Q' 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x4a,0x44,0x3a,0x02,0x00,0x00,0x00, 8, // 0x52 'R' 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x3c,0x28,0x24,0x22,0x62,0x00,0x00,0x00,0x00, 8, // 0x53 'S' 0x00,0x00,0x3c,0x42,0x42,0x40,0x30,0x0c,0x02,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x54 'T' 0x00,0x00,0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, 8, // 0x55 'U' 0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x56 'V' 0x00,0x00,0x41,0x41,0x41,0x41,0x22,0x22,0x14,0x14,0x08,0x08,0x00,0x00,0x00,0x00, 8, // 0x57 'W' 0x00,0x00,0x41,0x41,0x41,0x41,0x41,0x49,0x49,0x55,0x63,0x41,0x00,0x00,0x00,0x00, 8, // 0x58 'X' 0x00,0x00,0x42,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x42,0x00,0x00,0x00,0x00, 8, // 0x59 'Y' 0x00,0x00,0x22,0x22,0x22,0x22,0x14,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, 8, // 0x5a 'Z' 0x00,0x00,0x7e,0x42,0x02,0x04,0x08,0x10,0x20,0x40,0x42,0x7e,0x00,0x00,0x00,0x00, 8, // 0x5b '[' 0x00,0x1e,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1e,0x00,0x00,0x00, 8, // 0x5c '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00,0x00,0x00, 8, // 0x5d ']' 0x00,0x3c,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x3c,0x00,0x00,0x00, 8, // 0x5e '^' 0x00,0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00, 8, // 0x60 '`' 0x00,0x00,0x08,0x08,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x3c,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, 8, // 0x62 'b' 0x00,0x00,0x60,0x20,0x20,0x38,0x24,0x22,0x22,0x22,0x22,0x3c,0x00,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x40,0x40,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x64 'd' 0x00,0x00,0x0c,0x04,0x04,0x1c,0x24,0x44,0x44,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x7e,0x40,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x66 'f' 0x00,0x00,0x0c,0x12,0x10,0x10,0x38,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00,0x00, 8, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x3e,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x44,0x38,0x00, 8, // 0x68 'h' 0x00,0x00,0x60,0x20,0x20,0x2c,0x32,0x22,0x22,0x22,0x22,0x62,0x00,0x00,0x00,0x00, 8, // 0x69 'i' 0x00,0x00,0x08,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, 8, // 0x6a 'j' 0x00,0x00,0x04,0x04,0x00,0x0c,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,0x00, 8, // 0x6b 'k' 0x00,0x00,0x60,0x20,0x20,0x22,0x24,0x28,0x38,0x24,0x22,0x62,0x00,0x00,0x00,0x00, 8, // 0x6c 'l' 0x00,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, 8, // 0x6d 'm' 0x00,0x00,0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x41,0x41,0x00,0x00,0x00,0x00, 8, // 0x6e 'n' 0x00,0x00,0x00,0x00,0x00,0x5c,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00, 8, // 0x6f 'o' 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x22,0x3c,0x20,0x20,0x70,0x00, 8, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x3e,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x0e,0x00, 8, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x7c,0x22,0x22,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, 8, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x3c,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, 8, // 0x74 't' 0x00,0x00,0x10,0x10,0x10,0x7c,0x10,0x10,0x10,0x10,0x12,0x0c,0x00,0x00,0x00,0x00, 8, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, 8, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x22,0x14,0x08,0x00,0x00,0x00,0x00, 8, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x49,0x49,0x55,0x22,0x00,0x00,0x00,0x00, 8, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x00,0x00,0x00,0x00, 8, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3e,0x02,0x04,0x78,0x00, 8, // 0x7a 'z' 0x00,0x00,0x00,0x00,0x00,0x7e,0x44,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,0x00,0x00, 8, // 0x7b '{' 0x00,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x08,0x08,0x08,0x08,0x08,0x06,0x00,0x00, 8, // 0x7c '|' 0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00, 8, // 0x7d '}' 0x00,0x30,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x00,0x00, 8, // 0x7e '~' 0x00,0x00,0x39,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x7f '' 0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x22,0x41,0x41,0x7f,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u gse8x16_bold[] = { 16, 0, 32, 128-32, 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x44,0x00,0x55,0x00,0x66,0x00,0x77,0x00,0x88,0x00, 0x99,0x00,0xaa,0x00,0xbb,0x00,0xcc,0x00,0xdd,0x00,0xee,0x00,0xff,0x00,0x10,0x01,0x21,0x01, 0x32,0x01,0x43,0x01,0x54,0x01,0x65,0x01,0x76,0x01,0x87,0x01,0x98,0x01,0xa9,0x01,0xba,0x01, 0xcb,0x01,0xdc,0x01,0xed,0x01,0xfe,0x01,0x0f,0x02,0x20,0x02,0x31,0x02,0x42,0x02,0x53,0x02, 0x64,0x02,0x75,0x02,0x86,0x02,0x97,0x02,0xa8,0x02,0xb9,0x02,0xca,0x02,0xdb,0x02,0xec,0x02, 0xfd,0x02,0x0e,0x03,0x1f,0x03,0x30,0x03,0x41,0x03,0x52,0x03,0x63,0x03,0x74,0x03,0x85,0x03, 0x96,0x03,0xa7,0x03,0xb8,0x03,0xc9,0x03,0xda,0x03,0xeb,0x03,0xfc,0x03,0x0d,0x04,0x1e,0x04, 0x2f,0x04,0x40,0x04,0x51,0x04,0x62,0x04,0x73,0x04,0x84,0x04,0x95,0x04,0xa6,0x04,0xb7,0x04, 0xc8,0x04,0xd9,0x04,0xea,0x04,0xfb,0x04,0x0c,0x05,0x1d,0x05,0x2e,0x05,0x3f,0x05,0x50,0x05, 0x61,0x05,0x72,0x05,0x83,0x05,0x94,0x05,0xa5,0x05,0xb6,0x05,0xc7,0x05,0xd8,0x05,0xe9,0x05, 0xfa,0x05,0x0b,0x06,0x1c,0x06,0x2d,0x06,0x3e,0x06,0x4f,0x06, 8, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x21 '!' 0x00,0x00,0x18,0x3c,0x3c,0x3c,0x3c,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, 8, // 0x22 '"' 0x00,0x66,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x23 '#' 0x00,0x00,0x66,0x66,0x66,0xff,0x66,0x66,0xff,0x66,0x66,0x66,0x00,0x00,0x00,0x00, 8, // 0x24 '$' 0x00,0x08,0x08,0x3e,0x6b,0x6b,0x68,0x3e,0x0b,0x6b,0x6b,0x3e,0x08,0x08,0x00,0x00, 8, // 0x25 '%' 0x00,0x00,0x66,0xbe,0xcc,0x0c,0x18,0x18,0x30,0x33,0x65,0x66,0x00,0x00,0x00,0x00, 8, // 0x26 '&' 0x00,0x00,0x1c,0x36,0x36,0x36,0x1c,0x3b,0x6e,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, 8, // 0x27 ''' 0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x28 '(' 0x00,0x06,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0c,0x06,0x00,0x00,0x00, 8, // 0x29 ')' 0x00,0x30,0x18,0x0c,0x0c,0x06,0x06,0x06,0x06,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00, 8, // 0x2a '*' 0x00,0x00,0x00,0x00,0x66,0x24,0x18,0xff,0x18,0x24,0x66,0x00,0x00,0x00,0x00,0x00, 8, // 0x2b '+' 0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00, 8, // 0x2c ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x20,0x00, 8, // 0x2d '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x2e '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, 8, // 0x2f '/' 0x00,0x03,0x03,0x06,0x06,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00, 8, // 0x30 '0' 0x00,0x00,0x3e,0x63,0x63,0x67,0x6b,0x73,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x31 '1' 0x00,0x00,0x0c,0x0c,0x1c,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x00,0x00,0x00, 8, // 0x32 '2' 0x00,0x00,0x3e,0x63,0x63,0x03,0x06,0x0c,0x18,0x30,0x61,0x7f,0x00,0x00,0x00,0x00, 8, // 0x33 '3' 0x00,0x00,0x7f,0x43,0x06,0x0c,0x1e,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x34 '4' 0x00,0x00,0x06,0x0c,0x18,0x32,0x66,0x66,0x7f,0x06,0x06,0x0f,0x00,0x00,0x00,0x00, 8, // 0x35 '5' 0x00,0x00,0x7f,0x61,0x60,0x60,0x7e,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x36 '6' 0x00,0x00,0x1e,0x30,0x60,0x60,0x7e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x37 '7' 0x00,0x00,0x7f,0x63,0x63,0x03,0x06,0x0c,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, 8, // 0x38 '8' 0x00,0x00,0x3e,0x63,0x63,0x63,0x3e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x39 '9' 0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x3f,0x03,0x03,0x06,0x3c,0x00,0x00,0x00,0x00, 8, // 0x3a ':' 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, 8, // 0x3b ';' 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x40,0x00, 8, // 0x3c '<' 0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, 8, // 0x3d '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x3e '>' 0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, 8, // 0x3f '?' 0x00,0x00,0x3e,0x63,0x63,0x63,0x06,0x0c,0x0c,0x00,0x0c,0x0c,0x00,0x00,0x00,0x00, 8, // 0x40 '@' 0x00,0x00,0x7c,0x86,0x03,0x73,0xdb,0xdb,0xdb,0xdb,0xdb,0x6e,0x00,0x00,0x00,0x00, 8, // 0x41 'A' 0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x42 'B' 0x00,0x00,0x7e,0x33,0x33,0x33,0x3e,0x33,0x33,0x33,0x33,0x7e,0x00,0x00,0x00,0x00, 8, // 0x43 'C' 0x00,0x00,0x1e,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1e,0x00,0x00,0x00,0x00, 8, // 0x44 'D' 0x00,0x00,0x7c,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7c,0x00,0x00,0x00,0x00, 8, // 0x45 'E' 0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x30,0x31,0x33,0x7f,0x00,0x00,0x00,0x00, 8, // 0x46 'F' 0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, 8, // 0x47 'G' 0x00,0x00,0x1f,0x33,0x61,0x60,0x60,0x6f,0x63,0x63,0x33,0x1e,0x00,0x00,0x00,0x00, 8, // 0x48 'H' 0x00,0x00,0x63,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x49 'I' 0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, 8, // 0x4a 'J' 0x00,0x00,0x0f,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, 8, // 0x4b 'K' 0x00,0x00,0x73,0x33,0x36,0x36,0x3c,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00, 8, // 0x4c 'L' 0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7f,0x00,0x00,0x00,0x00, 8, // 0x4d 'M' 0x00,0x00,0x63,0x63,0x77,0x77,0x7f,0x6b,0x6b,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x4e 'N' 0x00,0x00,0x63,0x63,0x73,0x7b,0x6f,0x67,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x4f 'O' 0x00,0x00,0x1c,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1c,0x00,0x00,0x00,0x00, 8, // 0x50 'P' 0x00,0x00,0x7e,0x33,0x33,0x33,0x33,0x3e,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, 8, // 0x51 'Q' 0x00,0x00,0x1c,0x36,0x63,0x63,0x63,0x63,0x63,0x6f,0x36,0x1e,0x03,0x00,0x00,0x00, 8, // 0x52 'R' 0x00,0x00,0x7e,0x33,0x33,0x33,0x33,0x3e,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00, 8, // 0x53 'S' 0x00,0x00,0x3e,0x63,0x63,0x30,0x18,0x0c,0x06,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x54 'T' 0x00,0x00,0x3f,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, 8, // 0x55 'U' 0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x56 'V' 0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x00, 8, // 0x57 'W' 0x00,0x00,0x63,0x63,0x63,0x6b,0x6b,0x7f,0x77,0x77,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x58 'X' 0x00,0x00,0x63,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x59 'Y' 0x00,0x00,0x33,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, 8, // 0x5a 'Z' 0x00,0x00,0x7f,0x63,0x43,0x06,0x0c,0x18,0x30,0x61,0x63,0x7f,0x00,0x00,0x00,0x00, 8, // 0x5b '[' 0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00, 8, // 0x5c '\' 0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x06,0x06,0x03,0x03,0x00,0x00,0x00, 8, // 0x5d ']' 0x00,0x7c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x7c,0x00,0x00,0x00, 8, // 0x5e '^' 0x00,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5f '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00, 8, // 0x60 '`' 0x00,0x00,0x18,0x18,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, 8, // 0x62 'b' 0x00,0x00,0x70,0x30,0x30,0x3c,0x36,0x33,0x33,0x33,0x33,0x3e,0x00,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x60,0x60,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x64 'd' 0x00,0x00,0x0e,0x06,0x06,0x1e,0x36,0x66,0x66,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x7f,0x60,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x66 'f' 0x00,0x00,0x0e,0x1b,0x1b,0x18,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, 8, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x3b,0x66,0x66,0x66,0x66,0x66,0x3e,0x06,0x66,0x3c,0x00, 8, // 0x68 'h' 0x00,0x00,0x70,0x30,0x30,0x36,0x3b,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00, 8, // 0x69 'i' 0x00,0x00,0x0c,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, 8, // 0x6a 'j' 0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,0x00, 8, // 0x6b 'k' 0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3c,0x36,0x33,0x73,0x00,0x00,0x00,0x00, 8, // 0x6c 'l' 0x00,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, 8, // 0x6d 'm' 0x00,0x00,0x00,0x00,0x00,0x76,0x7f,0x6b,0x6b,0x6b,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x6e 'n' 0x00,0x00,0x00,0x00,0x00,0x6e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00, 8, // 0x6f 'o' 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x6e,0x33,0x33,0x33,0x33,0x33,0x3e,0x30,0x30,0x78,0x00, 8, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x3b,0x66,0x66,0x66,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00, 8, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, 8, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x60,0x3e,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, 8, // 0x74 't' 0x00,0x00,0x08,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x1b,0x0e,0x00,0x00,0x00,0x00, 8, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, 8, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x00, 8, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x6b,0x6b,0x7f,0x36,0x36,0x00,0x00,0x00,0x00, 8, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x1c,0x36,0x63,0x63,0x00,0x00,0x00,0x00, 8, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x3f,0x03,0x06,0x7c,0x00, 8, // 0x7a 'z' 0x00,0x00,0x00,0x00,0x00,0x7f,0x63,0x06,0x0c,0x18,0x31,0x7f,0x00,0x00,0x00,0x00, 8, // 0x7b '{' 0x00,0x03,0x04,0x0c,0x0c,0x0c,0x08,0x30,0x08,0x0c,0x0c,0x0c,0x04,0x03,0x00,0x00, 8, // 0x7c '|' 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00, 8, // 0x7d '}' 0x00,0x60,0x10,0x18,0x18,0x18,0x08,0x06,0x08,0x18,0x18,0x18,0x10,0x60,0x00,0x00, 8, // 0x7e '~' 0x00,0x00,0x3b,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x7f '' 0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u mcs11_prop[] = { 11, 2, 32, 128-32, 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, 4, // 0x22 '"' 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00, 6, // 0x24 '$' 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10, 6, // 0x25 '%' 0x00,0x00,0x68,0xA8,0xD0,0x10,0x20,0x2C,0x54,0x58,0x00, 6, // 0x26 '&' 0x00,0x20,0x50,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00, 3, // 0x27 ''' 0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x28 '(' 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, 5, // 0x29 ')' 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, 6, // 0x2A '*' 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00,0x00, 6, // 0x2B '+' 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00, 7, // 0x2F '/' 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40, 6, // 0x30 '0' 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00, 4, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 6, // 0x32 '2' 0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00, 6, // 0x33 '3' 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00, 6, // 0x34 '4' 0x00,0x08,0x18,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00, 6, // 0x35 '5' 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00, 6, // 0x36 '6' 0x00,0x38,0x44,0x40,0x40,0x78,0x44,0x44,0x44,0x38,0x00, 6, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00, 6, // 0x38 '8' 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00, 6, // 0x39 '9' 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xC0, 6, // 0x3C '<' 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, 6, // 0x3D '=' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, 6, // 0x3E '>' 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, 6, // 0x3F '?' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00, 6, // 0x40 '@' 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00, 6, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00, 6, // 0x42 'B' 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00, 6, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00, 6, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00, 6, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00, 6, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00, 6, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00, 6, // 0x48 'H' 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00, 4, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 6, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x30,0x00, 6, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00, 6, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00, 8, // 0x4D 'M' 0x00,0x41,0x63,0x55,0x49,0x49,0x41,0x41,0x41,0x41,0x00, 7, // 0x4E 'N' 0x00,0x42,0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x42,0x00, 6, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00, 6, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00, 6, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00, 6, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x44,0x00, 6, // 0x53 'S' 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00, 6, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, 6, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00, 6, // 0x56 'V' 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00, 8, // 0x57 'W' 0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x49,0x55,0x22,0x00, 6, // 0x58 'X' 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00, 6, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00, 6, // 0x5A 'Z' 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00, 5, // 0x5B '[' 0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30, 7, // 0x5C '\' 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, 4, // 0x5D ']' 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, 6, // 0x5E '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00, 4, // 0x60 '`' 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00, 6, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00, 6, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00, 4, // 0x66 'f' 0x00,0x10,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, 6, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00, 2, // 0x69 'i' 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, 3, // 0x6A 'j' 0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, 5, // 0x6B 'k' 0x00,0x40,0x40,0x48,0x50,0x60,0x60,0x50,0x48,0x48,0x00, 2, // 0x6C 'l' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, 8, // 0x6D 'm' 0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x41,0x41,0x00, 6, // 0x6E 'n' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00, 6, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, 6, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, 6, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x20,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00, 5, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x28,0x10,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00, 8, // 0x77 'w' 0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x36,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, 6, // 0x7A 'z' 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00, 5, // 0x7B '{' 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18, 3, // 0x7C '|' 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x40,0x40,0x40,0x00, 5, // 0x7D '}' 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0, 6, // 0x7E '~' 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00, 0 }; const int8u mcs11_prop_condensed[] = { 11, 2, 32, 128-32, 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, 3, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 3, // 0x21 '!' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x40,0x00, 4, // 0x22 '"' 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x23 '#' 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50,0x00, 5, // 0x24 '$' 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20,0x00, 5, // 0x25 '%' 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90,0x00, 5, // 0x26 '&' 0x00,0x40,0xA0,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68,0x00, 5, // 0x27 ''' 0x00,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, 4, // 0x29 ')' 0x80,0x40,0x40,0x20,0x20,0x20,0x20,0x20,0x40,0x40,0x80, 5, // 0x2A '*' 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00,0x00, 5, // 0x2B '+' 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, 5, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00, 6, // 0x2F '/' 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, 5, // 0x30 '0' 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, 3, // 0x31 '1' 0x00,0x40,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, 5, // 0x32 '2' 0x00,0x60,0x90,0x90,0x10,0x10,0x20,0x40,0x80,0xF0,0x00, 5, // 0x33 '3' 0x00,0x60,0x90,0x10,0x10,0x60,0x10,0x10,0x90,0x60,0x00, 5, // 0x34 '4' 0x00,0x10,0x30,0x30,0x50,0x50,0x90,0xF0,0x10,0x10,0x00, 5, // 0x35 '5' 0x00,0xF0,0x80,0x80,0xE0,0x90,0x10,0x10,0x90,0x60,0x00, 5, // 0x36 '6' 0x00,0x60,0x90,0x80,0x80,0xE0,0x90,0x90,0x90,0x60,0x00, 5, // 0x37 '7' 0x00,0xF0,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00, 5, // 0x38 '8' 0x00,0x60,0x90,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00, 5, // 0x39 '9' 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x10,0x90,0x60,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xC0, 6, // 0x3C '<' 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00, 5, // 0x3D '=' 0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x00, 6, // 0x3E '>' 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00, 5, // 0x3F '?' 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00,0x00, 5, // 0x40 '@' 0x00,0x60,0x90,0x90,0xB0,0xB0,0xB0,0x80,0x80,0x70,0x00, 5, // 0x41 'A' 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, 5, // 0x42 'B' 0x00,0xE0,0x90,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00, 5, // 0x43 'C' 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x80,0x90,0x60,0x00, 5, // 0x44 'D' 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, 5, // 0x45 'E' 0x00,0xF0,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0xF0,0x00, 5, // 0x46 'F' 0x00,0xF0,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00, 5, // 0x47 'G' 0x00,0x70,0x80,0x80,0x80,0xB0,0x90,0x90,0x90,0x60,0x00, 5, // 0x48 'H' 0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, 4, // 0x49 'I' 0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xE0,0x00, 5, // 0x4A 'J' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0xA0,0xA0,0x40,0x00, 5, // 0x4B 'K' 0x00,0x90,0x90,0xA0,0xA0,0xC0,0xA0,0xA0,0x90,0x90,0x00, 5, // 0x4C 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00, 6, // 0x4D 'M' 0x00,0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x88,0x88,0x00, 5, // 0x4E 'N' 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x90,0x00, 5, // 0x4F 'O' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x50 'P' 0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00, 5, // 0x51 'Q' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30, 5, // 0x52 'R' 0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00, 5, // 0x53 'S' 0x00,0x60,0x90,0x80,0x80,0x60,0x10,0x10,0x90,0x60,0x00, 6, // 0x54 'T' 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 5, // 0x55 'U' 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 6, // 0x56 'V' 0x00,0x88,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x20,0x00, 6, // 0x57 'W' 0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0xA8,0xA8,0x50,0x00, 5, // 0x58 'X' 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x90,0x00, 6, // 0x59 'Y' 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00, 5, // 0x5A 'Z' 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0xF0,0x00, 4, // 0x5B '[' 0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60,0x00, 6, // 0x5C '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, 4, // 0x5D ']' 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60,0x00, 5, // 0x5E '^' 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00, 5, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x61 'a' 0x00,0x00,0x00,0x60,0x90,0x10,0x70,0x90,0x90,0x70,0x00, 5, // 0x62 'b' 0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00, 5, // 0x63 'c' 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x80,0x90,0x60,0x00, 5, // 0x64 'd' 0x00,0x10,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00, 5, // 0x65 'e' 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x90,0x60,0x00, 4, // 0x66 'f' 0x00,0x20,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00, 5, // 0x67 'g' 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x90,0x60, 5, // 0x68 'h' 0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, 2, // 0x69 'i' 0x00,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, 4, // 0x6A 'j' 0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, 5, // 0x6B 'k' 0x00,0x80,0x80,0x90,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00, 2, // 0x6C 'l' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, 6, // 0x6D 'm' 0x00,0x00,0x00,0xD0,0xA8,0xA8,0xA8,0x88,0x88,0x88,0x00, 5, // 0x6E 'n' 0x00,0x00,0x00,0xA0,0xD0,0x90,0x90,0x90,0x90,0x90,0x00, 5, // 0x6F 'o' 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x70 'p' 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80, 5, // 0x71 'q' 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0x10, 6, // 0x72 'r' 0x00,0x00,0x00,0xB8,0x48,0x40,0x40,0x40,0x40,0x40,0x00, 5, // 0x73 's' 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x10,0x90,0x60,0x00, 4, // 0x74 't' 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x20,0x00, 5, // 0x75 'u' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x70,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00, 6, // 0x77 'w' 0x00,0x00,0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00, 5, // 0x78 'x' 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, 5, // 0x79 'y' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0x20,0xC0, 5, // 0x7A 'z' 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0x80,0xF0,0x00, 5, // 0x7B '{' 0x30,0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, 3, // 0x7C '|' 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x40,0x40,0x40,0x00, 5, // 0x7D '}' 0xC0,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, 5, // 0x7E '~' 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x7F '' 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00,0x00, 0 }; const int8u mcs12_prop[] = { 12, 3, 32, 128-32, 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, 0x49,0x02,0x62,0x02,0x6F,0x02,0x7C,0x02,0x89,0x02,0x96,0x02,0xA3,0x02,0xB0,0x02,0xBD,0x02, 0xCA,0x02,0xD7,0x02,0xF0,0x02,0xFD,0x02,0x0A,0x03,0x17,0x03,0x24,0x03,0x31,0x03,0x3E,0x03, 0x4B,0x03,0x58,0x03,0x65,0x03,0x72,0x03,0x7F,0x03,0x8C,0x03,0x99,0x03,0xA6,0x03,0xB3,0x03, 0xC0,0x03,0xCD,0x03,0xDA,0x03,0xE7,0x03,0xF4,0x03,0x01,0x04,0x1A,0x04,0x27,0x04,0x34,0x04, 0x41,0x04,0x4E,0x04,0x5B,0x04,0x68,0x04,0x75,0x04,0x82,0x04,0x8F,0x04,0xA8,0x04,0xB5,0x04, 0xC2,0x04,0xCF,0x04,0xDC,0x04,0xE9,0x04,0xF6,0x04,0x03,0x05, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 4, // 0x22 '"' 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x00, 6, // 0x24 '$' 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, 7, // 0x25 '%' 0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, 7, // 0x26 '&' 0x00,0x30,0x48,0x48,0x48,0x30,0x4A,0x4A,0x44,0x3A,0x00,0x00, 3, // 0x27 ''' 0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00, 5, // 0x29 ')' 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00, 6, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, 6, // 0x2B '+' 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x40,0x80, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, 7, // 0x2F '/' 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, 7, // 0x30 '0' 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00, 4, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, 7, // 0x32 '2' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 7, // 0x33 '3' 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 6, // 0x34 '4' 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00, 7, // 0x35 '5' 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x36 '6' 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00, 7, // 0x38 '8' 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x39 '9' 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x40,0x80, 6, // 0x3C '<' 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, 6, // 0x3D '=' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, 6, // 0x3E '>' 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, 6, // 0x3F '?' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, 7, // 0x40 '@' 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, 7, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x42 'B' 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, 6, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, 6, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, 7, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00, 7, // 0x48 'H' 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, 5, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 6, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, 6, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00, 6, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, 9, // 0x4D 'M' 0x00,0x00,0x41,0x00,0x63,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 7, // 0x4E 'N' 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00, 7, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, 7, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, 7, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, 7, // 0x53 'S' 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 6, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 7, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x56 'V' 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, 9, // 0x57 'W' 0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x22,0x00,0x00,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, 7, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, 6, // 0x5A 'Z' 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, 4, // 0x5B '[' 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, 7, // 0x5C '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, 4, // 0x5D ']' 0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00, 6, // 0x5E '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, 4, // 0x60 '`' 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, 7, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, 4, // 0x66 'f' 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, 7, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 3, // 0x69 'i' 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 5, // 0x6A 'j' 0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60, 6, // 0x6B 'k' 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, 3, // 0x6C 'l' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 9, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 7, // 0x6E 'n' 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40, 7, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, 6, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, 5, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, 9, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x36,0x00,0x00,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, 6, // 0x7A 'z' 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 5, // 0x7B '{' 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, 3, // 0x7C '|' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, 5, // 0x7D '}' 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00, 7, // 0x7E '~' 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u mcs13_prop[] = { 13, 4, 32, 128-32, 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x38,0x00,0x46,0x00,0x54,0x00,0x62,0x00,0x70,0x00, 0x7E,0x00,0x8C,0x00,0x9A,0x00,0xA8,0x00,0xB6,0x00,0xC4,0x00,0xD2,0x00,0xE0,0x00,0xEE,0x00, 0xFC,0x00,0x0A,0x01,0x18,0x01,0x26,0x01,0x34,0x01,0x42,0x01,0x50,0x01,0x5E,0x01,0x6C,0x01, 0x7A,0x01,0x88,0x01,0x96,0x01,0xA4,0x01,0xB2,0x01,0xC0,0x01,0xCE,0x01,0xDC,0x01,0xEA,0x01, 0xF8,0x01,0x06,0x02,0x14,0x02,0x22,0x02,0x30,0x02,0x3E,0x02,0x4C,0x02,0x5A,0x02,0x68,0x02, 0x76,0x02,0x91,0x02,0x9F,0x02,0xAD,0x02,0xBB,0x02,0xC9,0x02,0xD7,0x02,0xE5,0x02,0xF3,0x02, 0x01,0x03,0x0F,0x03,0x2A,0x03,0x38,0x03,0x46,0x03,0x54,0x03,0x62,0x03,0x70,0x03,0x7E,0x03, 0x8C,0x03,0x9A,0x03,0xA8,0x03,0xB6,0x03,0xC4,0x03,0xD2,0x03,0xE0,0x03,0xEE,0x03,0xFC,0x03, 0x0A,0x04,0x18,0x04,0x26,0x04,0x34,0x04,0x42,0x04,0x50,0x04,0x6B,0x04,0x79,0x04,0x87,0x04, 0x95,0x04,0xA3,0x04,0xB1,0x04,0xBF,0x04,0xCD,0x04,0xDB,0x04,0xE9,0x04,0x04,0x05,0x12,0x05, 0x20,0x05,0x2E,0x05,0x3C,0x05,0x4A,0x05,0x58,0x05,0x66,0x05, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 4, // 0x22 '"' 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x00,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x00, 6, // 0x24 '$' 0x00,0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, 7, // 0x25 '%' 0x00,0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, 7, // 0x26 '&' 0x00,0x30,0x48,0x48,0x48,0x30,0x4A,0x4A,0x44,0x3A,0x00,0x00,0x00, 3, // 0x27 ''' 0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00,0x00, 5, // 0x29 ')' 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00,0x00, 6, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00,0x00, 6, // 0x2B '+' 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x20,0x40,0x80, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, 7, // 0x2F '/' 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, 7, // 0x30 '0' 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00,0x00, 4, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, 7, // 0x32 '2' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, 7, // 0x33 '3' 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 6, // 0x34 '4' 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00,0x00, 7, // 0x35 '5' 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 7, // 0x36 '6' 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 6, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00,0x00, 7, // 0x38 '8' 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x39 '9' 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x20,0x40,0x80, 6, // 0x3C '<' 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, 6, // 0x3D '=' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 6, // 0x3E '>' 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, 6, // 0x3F '?' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00,0x00, 7, // 0x40 '@' 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00,0x00, 7, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x42 'B' 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00,0x00, 6, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, 6, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, 6, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, 7, // 0x48 'H' 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 5, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 6, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, 6, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00,0x00, 6, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, 9, // 0x4D 'M' 0x00,0x00,0x41,0x00,0x63,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x4E 'N' 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00,0x00, 7, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, 7, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00,0x00, 7, // 0x53 'S' 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 6, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 7, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 6, // 0x56 'V' 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00,0x00, 9, // 0x57 'W' 0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 6, // 0x5A 'Z' 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00,0x00, 4, // 0x5B '[' 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00,0x00, 7, // 0x5C '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00,0x00, 4, // 0x5D ']' 0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00,0x00, 6, // 0x5E '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00, 4, // 0x60 '`' 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, 7, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00,0x00, 4, // 0x66 'f' 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, 7, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 3, // 0x69 'i' 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 5, // 0x6A 'j' 0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00, 6, // 0x6B 'k' 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, 3, // 0x6C 'l' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 9, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x6E 'n' 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40, 7, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,0x04, 6, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,0x00, 5, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, 9, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, 6, // 0x7A 'z' 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, 5, // 0x7B '{' 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00,0x00, 3, // 0x7C '|' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 5, // 0x7D '}' 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00,0x00, 7, // 0x7E '~' 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u mcs5x10_mono[] = { 10, 2, 32, 128-32, 0x00,0x00,0x0B,0x00,0x16,0x00,0x21,0x00,0x2C,0x00,0x37,0x00,0x42,0x00,0x4D,0x00,0x58,0x00, 0x63,0x00,0x6E,0x00,0x79,0x00,0x84,0x00,0x8F,0x00,0x9A,0x00,0xA5,0x00,0xB0,0x00,0xBB,0x00, 0xC6,0x00,0xD1,0x00,0xDC,0x00,0xE7,0x00,0xF2,0x00,0xFD,0x00,0x08,0x01,0x13,0x01,0x1E,0x01, 0x29,0x01,0x34,0x01,0x3F,0x01,0x4A,0x01,0x55,0x01,0x60,0x01,0x6B,0x01,0x76,0x01,0x81,0x01, 0x8C,0x01,0x97,0x01,0xA2,0x01,0xAD,0x01,0xB8,0x01,0xC3,0x01,0xCE,0x01,0xD9,0x01,0xE4,0x01, 0xEF,0x01,0xFA,0x01,0x05,0x02,0x10,0x02,0x1B,0x02,0x26,0x02,0x31,0x02,0x3C,0x02,0x47,0x02, 0x52,0x02,0x5D,0x02,0x68,0x02,0x73,0x02,0x7E,0x02,0x89,0x02,0x94,0x02,0x9F,0x02,0xAA,0x02, 0xB5,0x02,0xC0,0x02,0xCB,0x02,0xD6,0x02,0xE1,0x02,0xEC,0x02,0xF7,0x02,0x02,0x03,0x0D,0x03, 0x18,0x03,0x23,0x03,0x2E,0x03,0x39,0x03,0x44,0x03,0x4F,0x03,0x5A,0x03,0x65,0x03,0x70,0x03, 0x7B,0x03,0x86,0x03,0x91,0x03,0x9C,0x03,0xA7,0x03,0xB2,0x03,0xBD,0x03,0xC8,0x03,0xD3,0x03, 0xDE,0x03,0xE9,0x03,0xF4,0x03,0xFF,0x03,0x0A,0x04,0x15,0x04, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, 5, // 0x22 '"' 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x23 '#' 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50, 5, // 0x24 '$' 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20, 5, // 0x25 '%' 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90, 5, // 0x26 '&' 0x00,0x40,0xA0,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68, 5, // 0x27 ''' 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10, 5, // 0x29 ')' 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40, 5, // 0x2A '*' 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00, 5, // 0x2B '+' 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, 5, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00, 5, // 0x2F '/' 0x00,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x00, 5, // 0x30 '0' 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, 5, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x32 '2' 0x00,0x60,0x90,0x90,0x10,0x20,0x40,0x80,0xF0,0x00, 5, // 0x33 '3' 0x00,0x60,0x90,0x10,0x60,0x10,0x10,0x90,0x60,0x00, 5, // 0x34 '4' 0x00,0x10,0x30,0x50,0x50,0x90,0xF0,0x10,0x10,0x00, 5, // 0x35 '5' 0x00,0xF0,0x80,0x80,0xE0,0x10,0x10,0x90,0x60,0x00, 5, // 0x36 '6' 0x00,0x60,0x80,0x80,0xE0,0x90,0x90,0x90,0x60,0x00, 5, // 0x37 '7' 0x00,0xF0,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00, 5, // 0x38 '8' 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00, 5, // 0x39 '9' 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x10,0x60,0x00, 5, // 0x3A ':' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00, 5, // 0x3B ';' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xC0, 5, // 0x3C '<' 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08, 5, // 0x3D '=' 0x00,0x00,0x00,0x00,0xF0,0x00,0xF0,0x00,0x00,0x00, 5, // 0x3E '>' 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80, 5, // 0x3F '?' 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00, 5, // 0x40 '@' 0x00,0x60,0x90,0x90,0xB0,0xB0,0x80,0x80,0x70,0x00, 5, // 0x41 'A' 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, 5, // 0x42 'B' 0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00, 5, // 0x43 'C' 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x90,0x60,0x00, 5, // 0x44 'D' 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, 5, // 0x45 'E' 0x00,0xF0,0x80,0x80,0xF0,0x80,0x80,0x80,0xF0,0x00, 5, // 0x46 'F' 0x00,0xF0,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00, 5, // 0x47 'G' 0x00,0x60,0x90,0x80,0x80,0xB0,0x90,0x90,0x60,0x00, 5, // 0x48 'H' 0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, 5, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x4A 'J' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0xA0,0x40,0x00, 5, // 0x4B 'K' 0x00,0x90,0xA0,0xA0,0xC0,0xC0,0xA0,0xA0,0x90,0x00, 5, // 0x4C 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00, 5, // 0x4D 'M' 0x00,0x90,0x90,0xF0,0xF0,0x90,0x90,0x90,0x90,0x00, 5, // 0x4E 'N' 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x00, 5, // 0x4F 'O' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x50 'P' 0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00, 5, // 0x51 'Q' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30, 5, // 0x52 'R' 0x00,0xE0,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00, 5, // 0x53 'S' 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x90,0x60,0x00, 5, // 0x54 'T' 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 5, // 0x55 'U' 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x56 'V' 0x00,0x90,0x90,0x90,0x50,0x50,0x50,0x20,0x20,0x00, 5, // 0x57 'W' 0x00,0x90,0x90,0x90,0x90,0x90,0xF0,0xF0,0x90,0x00, 5, // 0x58 'X' 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, 5, // 0x59 'Y' 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, 5, // 0x5A 'Z' 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0xF0,0x00, 5, // 0x5B '[' 0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, 5, // 0x5C '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08, 5, // 0x5D ']' 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, 5, // 0x5E '^' 0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00, 5, // 0x60 '`' 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x61 'a' 0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00, 5, // 0x62 'b' 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00, 5, // 0x63 'c' 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00, 5, // 0x64 'd' 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00, 5, // 0x65 'e' 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x70,0x00, 5, // 0x66 'f' 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00, 5, // 0x67 'g' 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0xE0, 5, // 0x68 'h' 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, 5, // 0x69 'i' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x6A 'j' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xC0, 5, // 0x6B 'k' 0x00,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00, 5, // 0x6C 'l' 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 5, // 0x6D 'm' 0x00,0x00,0x00,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, 5, // 0x6E 'n' 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, 5, // 0x6F 'o' 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00, 5, // 0x70 'p' 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80, 5, // 0x71 'q' 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x10, 5, // 0x72 'r' 0x00,0x00,0x00,0xB0,0x50,0x40,0x40,0x40,0xE0,0x00, 5, // 0x73 's' 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00, 5, // 0x74 't' 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x50,0x20,0x00, 5, // 0x75 'u' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00, 5, // 0x76 'v' 0x00,0x00,0x00,0x90,0x90,0x50,0x50,0x20,0x20,0x00, 5, // 0x77 'w' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x00, 5, // 0x78 'x' 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00, 5, // 0x79 'y' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, 5, // 0x7A 'z' 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x00, 5, // 0x7B '{' 0x30,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, 5, // 0x7C '|' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 5, // 0x7D '}' 0xC0,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, 5, // 0x7E '~' 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x7F '' 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00, 0 }; const int8u mcs5x11_mono[] = { 11, 3, 32, 128-32, 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 5, // 0x22 '"' 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x23 '#' 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50,0x00, 5, // 0x24 '$' 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20,0x00, 5, // 0x25 '%' 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90,0x00, 5, // 0x26 '&' 0x00,0x40,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68,0x00,0x00, 5, // 0x27 ''' 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10, 5, // 0x29 ')' 0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40, 5, // 0x2A '*' 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00,0x00, 5, // 0x2B '+' 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x40,0x80, 5, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, 5, // 0x2F '/' 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, 5, // 0x30 '0' 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, 5, // 0x31 '1' 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x32 '2' 0x00,0x60,0x90,0x90,0x10,0x20,0x40,0x80,0xF0,0x00,0x00, 5, // 0x33 '3' 0x00,0x60,0x90,0x10,0x60,0x10,0x10,0x90,0x60,0x00,0x00, 5, // 0x34 '4' 0x00,0x10,0x30,0x50,0x50,0x90,0xF8,0x10,0x10,0x00,0x00, 5, // 0x35 '5' 0x00,0xF0,0x80,0xE0,0x90,0x10,0x10,0x90,0x60,0x00,0x00, 5, // 0x36 '6' 0x00,0x60,0x90,0x80,0xE0,0x90,0x90,0x90,0x60,0x00,0x00, 5, // 0x37 '7' 0x00,0xF0,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00,0x00, 5, // 0x38 '8' 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00,0x00, 5, // 0x39 '9' 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x90,0x60,0x00,0x00, 5, // 0x3A ':' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00, 5, // 0x3B ';' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x40,0x80, 5, // 0x3C '<' 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00, 5, // 0x3D '=' 0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x00, 5, // 0x3E '>' 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00, 5, // 0x3F '?' 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00,0x00, 5, // 0x40 '@' 0x00,0x60,0x90,0x90,0xB0,0xB0,0x80,0x80,0x70,0x00,0x00, 5, // 0x41 'A' 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00,0x00, 5, // 0x42 'B' 0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00,0x00, 5, // 0x43 'C' 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x90,0x60,0x00,0x00, 5, // 0x44 'D' 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, 5, // 0x45 'E' 0x00,0xF0,0x80,0x80,0xE0,0x80,0x80,0x80,0xF0,0x00,0x00, 5, // 0x46 'F' 0x00,0xF0,0x80,0x80,0xE0,0x80,0x80,0x80,0x80,0x00,0x00, 5, // 0x47 'G' 0x00,0x60,0x90,0x80,0x80,0xB0,0x90,0x90,0x60,0x00,0x00, 5, // 0x48 'H' 0x00,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00,0x00, 5, // 0x49 'I' 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x4A 'J' 0x00,0x70,0x20,0x20,0x20,0x20,0xA0,0xA0,0x40,0x00,0x00, 5, // 0x4B 'K' 0x00,0x90,0xA0,0xA0,0xC0,0xA0,0xA0,0x90,0x90,0x00,0x00, 5, // 0x4C 'L' 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00,0x00, 5, // 0x4D 'M' 0x00,0x90,0xF0,0xF0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, 5, // 0x4E 'N' 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x00,0x00, 5, // 0x4F 'O' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00,0x00, 5, // 0x50 'P' 0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00,0x00, 5, // 0x51 'Q' 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30,0x00, 5, // 0x52 'R' 0x00,0xE0,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00,0x00, 5, // 0x53 'S' 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x90,0x60,0x00,0x00, 5, // 0x54 'T' 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, 5, // 0x55 'U' 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00,0x00, 5, // 0x56 'V' 0x00,0x90,0x90,0x90,0x50,0x50,0x50,0x20,0x20,0x00,0x00, 5, // 0x57 'W' 0x00,0x90,0x90,0x90,0x90,0x90,0xF0,0xF0,0x90,0x00,0x00, 5, // 0x58 'X' 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00,0x00, 5, // 0x59 'Y' 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00,0x00, 5, // 0x5A 'Z' 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0xF0,0x00,0x00, 5, // 0x5B '[' 0x00,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, 5, // 0x5C '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, 5, // 0x5D ']' 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, 5, // 0x5E '^' 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00, 5, // 0x60 '`' 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x61 'a' 0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00,0x00, 5, // 0x62 'b' 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, 5, // 0x63 'c' 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00,0x00, 5, // 0x64 'd' 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00,0x00, 5, // 0x65 'e' 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x70,0x00,0x00, 5, // 0x66 'f' 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 5, // 0x67 'g' 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, 5, // 0x68 'h' 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, 5, // 0x69 'i' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x6A 'j' 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, 5, // 0x6B 'k' 0x00,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00,0x00, 5, // 0x6C 'l' 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x6D 'm' 0x00,0x00,0x00,0x90,0xF0,0x90,0x90,0x90,0x90,0x00,0x00, 5, // 0x6E 'n' 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, 5, // 0x6F 'o' 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00,0x00, 5, // 0x70 'p' 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80, 5, // 0x71 'q' 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0x10, 5, // 0x72 'r' 0x00,0x00,0x00,0xA0,0x50,0x40,0x40,0x40,0xE0,0x00,0x00, 5, // 0x73 's' 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00,0x00, 5, // 0x74 't' 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x30,0x00,0x00, 5, // 0x75 'u' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00,0x00, 5, // 0x76 'v' 0x00,0x00,0x00,0x90,0x90,0x50,0x50,0x20,0x20,0x00,0x00, 5, // 0x77 'w' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x00,0x00, 5, // 0x78 'x' 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00,0x00, 5, // 0x79 'y' 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, 5, // 0x7A 'z' 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x00,0x00, 5, // 0x7B '{' 0x30,0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, 5, // 0x7C '|' 0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00, 5, // 0x7D '}' 0xC0,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, 5, // 0x7E '~' 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x7F '' 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00,0x00, 0 }; const int8u mcs6x10_mono[] = { 10, 3, 32, 128-32, 0x00,0x00,0x0B,0x00,0x16,0x00,0x21,0x00,0x2C,0x00,0x37,0x00,0x42,0x00,0x4D,0x00,0x58,0x00, 0x63,0x00,0x6E,0x00,0x79,0x00,0x84,0x00,0x8F,0x00,0x9A,0x00,0xA5,0x00,0xB0,0x00,0xBB,0x00, 0xC6,0x00,0xD1,0x00,0xDC,0x00,0xE7,0x00,0xF2,0x00,0xFD,0x00,0x08,0x01,0x13,0x01,0x1E,0x01, 0x29,0x01,0x34,0x01,0x3F,0x01,0x4A,0x01,0x55,0x01,0x60,0x01,0x6B,0x01,0x76,0x01,0x81,0x01, 0x8C,0x01,0x97,0x01,0xA2,0x01,0xAD,0x01,0xB8,0x01,0xC3,0x01,0xCE,0x01,0xD9,0x01,0xE4,0x01, 0xEF,0x01,0xFA,0x01,0x05,0x02,0x10,0x02,0x1B,0x02,0x26,0x02,0x31,0x02,0x3C,0x02,0x47,0x02, 0x52,0x02,0x5D,0x02,0x68,0x02,0x73,0x02,0x7E,0x02,0x89,0x02,0x94,0x02,0x9F,0x02,0xAA,0x02, 0xB5,0x02,0xC0,0x02,0xCB,0x02,0xD6,0x02,0xE1,0x02,0xEC,0x02,0xF7,0x02,0x02,0x03,0x0D,0x03, 0x18,0x03,0x23,0x03,0x2E,0x03,0x39,0x03,0x44,0x03,0x4F,0x03,0x5A,0x03,0x65,0x03,0x70,0x03, 0x7B,0x03,0x86,0x03,0x91,0x03,0x9C,0x03,0xA7,0x03,0xB2,0x03,0xBD,0x03,0xC8,0x03,0xD3,0x03, 0xDE,0x03,0xE9,0x03,0xF4,0x03,0xFF,0x03,0x0A,0x04,0x15,0x04, 6, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, 6, // 0x22 '"' 0x00,0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x00,0x28,0x28,0x7C,0x28,0x28,0x7C,0x28,0x28,0x00, 6, // 0x24 '$' 0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, 6, // 0x25 '%' 0x00,0x08,0xC8,0xD0,0x10,0x20,0x2C,0x4C,0x40,0x00, 6, // 0x26 '&' 0x00,0x20,0x50,0x50,0x24,0x54,0x48,0x34,0x00,0x00, 6, // 0x27 ''' 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x08,0x10,0x10,0x20,0x20,0x20,0x10,0x10,0x08,0x00, 6, // 0x29 ')' 0x20,0x10,0x10,0x08,0x08,0x08,0x10,0x10,0x20,0x00, 6, // 0x2A '*' 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00, 6, // 0x2B '+' 0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 6, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 6, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, 6, // 0x2F '/' 0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, 6, // 0x30 '0' 0x00,0x38,0x44,0x4C,0x54,0x64,0x44,0x38,0x00,0x00, 6, // 0x31 '1' 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x32 '2' 0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7C,0x00,0x00, 6, // 0x33 '3' 0x00,0x38,0x44,0x04,0x38,0x04,0x44,0x38,0x00,0x00, 6, // 0x34 '4' 0x00,0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, 6, // 0x35 '5' 0x00,0x7C,0x40,0x40,0x78,0x04,0x44,0x38,0x00,0x00, 6, // 0x36 '6' 0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38,0x00,0x00, 6, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00, 6, // 0x38 '8' 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, 6, // 0x39 '9' 0x00,0x38,0x44,0x44,0x3C,0x04,0x04,0x38,0x00,0x00, 6, // 0x3A ':' 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00, 6, // 0x3B ';' 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40, 6, // 0x3C '<' 0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, 6, // 0x3D '=' 0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, 6, // 0x3E '>' 0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, 6, // 0x3F '?' 0x00,0x38,0x44,0x04,0x18,0x10,0x00,0x10,0x00,0x00, 6, // 0x40 '@' 0x00,0x38,0x44,0x5C,0x54,0x5C,0x40,0x38,0x00,0x00, 6, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x00,0x00, 6, // 0x42 'B' 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00, 6, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 6, // 0x44 'D' 0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x7C,0x00,0x00, 6, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00, 6, // 0x47 'G' 0x00,0x38,0x44,0x40,0x4C,0x44,0x44,0x3C,0x00,0x00, 6, // 0x48 'H' 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00, 6, // 0x49 'I' 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, 6, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, 6, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, 6, // 0x4D 'M' 0x00,0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x00,0x00, 6, // 0x4E 'N' 0x00,0x44,0x44,0x64,0x54,0x4C,0x44,0x44,0x00,0x00, 6, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x50 'P' 0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, 6, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, 6, // 0x52 'R' 0x00,0x78,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, 6, // 0x53 'S' 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, 6, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 6, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x56 'V' 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x00,0x00, 6, // 0x57 'W' 0x00,0x44,0x44,0x54,0x54,0x54,0x54,0x28,0x00,0x00, 6, // 0x58 'X' 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 6, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x00,0x00, 6, // 0x5A 'Z' 0x00,0x78,0x08,0x10,0x20,0x40,0x40,0x78,0x00,0x00, 6, // 0x5B '[' 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, 6, // 0x5C '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, 6, // 0x5D ']' 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, 6, // 0x5E '^' 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, 6, // 0x60 '`' 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00,0x00, 6, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x3C,0x00,0x00, 6, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x78,0x40,0x3C,0x00,0x00, 6, // 0x66 'f' 0x00,0x0C,0x10,0x10,0x38,0x10,0x10,0x10,0x00,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x38, 6, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x00,0x00, 6, // 0x69 'i' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x6A 'j' 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30, 6, // 0x6B 'k' 0x00,0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00,0x00, 6, // 0x6C 'l' 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x6D 'm' 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x00,0x00, 6, // 0x6E 'n' 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00, 6, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40, 6, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x04, 6, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x70,0x00,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00, 6, // 0x74 't' 0x00,0x10,0x10,0x38,0x10,0x10,0x14,0x08,0x00,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x00,0x00, 6, // 0x77 'w' 0x00,0x00,0x00,0x44,0x44,0x54,0x7C,0x28,0x00,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x48,0x48,0x30,0x48,0x48,0x00,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x3C,0x04,0x38, 6, // 0x7A 'z' 0x00,0x00,0x00,0x78,0x08,0x30,0x40,0x78,0x00,0x00, 6, // 0x7B '{' 0x18,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x18,0x00, 6, // 0x7C '|' 0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00, 6, // 0x7D '}' 0x60,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x60,0x00, 6, // 0x7E '~' 0x00,0x48,0xA8,0x90,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00, 0 }; const int8u mcs6x11_mono[] = { 11, 3, 32, 128-32, 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, 6, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 6, // 0x22 '"' 0x00,0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x23 '#' 0x00,0x28,0x28,0x7C,0x28,0x28,0x7C,0x28,0x28,0x00,0x00, 6, // 0x24 '$' 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, 6, // 0x25 '%' 0x00,0x68,0xA8,0xD0,0x10,0x20,0x2C,0x54,0x58,0x00,0x00, 6, // 0x26 '&' 0x00,0x20,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00, 6, // 0x27 ''' 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, 6, // 0x29 ')' 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, 6, // 0x2A '*' 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00,0x00, 6, // 0x2B '+' 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 6, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 6, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, 6, // 0x2F '/' 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, 6, // 0x30 '0' 0x00,0x38,0x44,0x44,0x54,0x54,0x44,0x44,0x38,0x00,0x00, 6, // 0x31 '1' 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x32 '2' 0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 6, // 0x33 '3' 0x00,0x38,0x44,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 6, // 0x34 '4' 0x00,0x08,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, 6, // 0x35 '5' 0x00,0x7C,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, 6, // 0x36 '6' 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00, 6, // 0x38 '8' 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x39 '9' 0x00,0x38,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, 6, // 0x3A ':' 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00, 6, // 0x3B ';' 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40, 6, // 0x3C '<' 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, 6, // 0x3D '=' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, 6, // 0x3E '>' 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, 6, // 0x3F '?' 0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, 6, // 0x40 '@' 0x00,0x38,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, 6, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00, 6, // 0x42 'B' 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 6, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, 6, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, 6, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, 6, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x4C,0x34,0x00,0x00, 6, // 0x48 'H' 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, 6, // 0x49 'I' 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, 6, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x00,0x00, 6, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, 6, // 0x4D 'M' 0x00,0x44,0x6C,0x54,0x54,0x54,0x44,0x44,0x44,0x00,0x00, 6, // 0x4E 'N' 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x00,0x00, 6, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, 6, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, 6, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, 6, // 0x53 'S' 0x00,0x38,0x44,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 6, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 6, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x56 'V' 0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, 6, // 0x57 'W' 0x00,0x44,0x44,0x54,0x54,0x54,0x54,0x54,0x28,0x00,0x00, 6, // 0x58 'X' 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, 6, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, 6, // 0x5A 'Z' 0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, 6, // 0x5B '[' 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, 6, // 0x5C '\' 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, 6, // 0x5D ']' 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, 6, // 0x5E '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, 6, // 0x60 '`' 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00, 6, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, 6, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, 6, // 0x66 'f' 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, 6, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 6, // 0x69 'i' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x6A 'j' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x50,0x20, 6, // 0x6B 'k' 0x00,0x40,0x40,0x4C,0x50,0x60,0x50,0x48,0x44,0x00,0x00, 6, // 0x6C 'l' 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 6, // 0x6D 'm' 0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x44,0x44,0x00,0x00, 6, // 0x6E 'n' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 6, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, 6, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, 6, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x70,0x00,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x38,0x44,0x30,0x08,0x44,0x38,0x00,0x00, 6, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x18,0x00,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, 6, // 0x77 'w' 0x00,0x00,0x00,0x44,0x44,0x44,0x54,0x7C,0x28,0x00,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, 6, // 0x7A 'z' 0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 6, // 0x7B '{' 0x18,0x20,0x20,0x20,0xC0,0xC0,0x20,0x20,0x20,0x18,0x00, 6, // 0x7C '|' 0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00, 6, // 0x7D '}' 0x60,0x10,0x10,0x10,0x0C,0x0C,0x10,0x10,0x10,0x60,0x00, 6, // 0x7E '~' 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00, 0 }; const int8u mcs7x12_mono_high[] = { 12, 3, 32, 128-32, 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7D,0x02,0x8A,0x02,0x97,0x02,0xA4,0x02,0xB1,0x02, 0xBE,0x02,0xCB,0x02,0xD8,0x02,0xE5,0x02,0xF2,0x02,0xFF,0x02,0x0C,0x03,0x19,0x03,0x26,0x03, 0x33,0x03,0x40,0x03,0x4D,0x03,0x5A,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8E,0x03,0x9B,0x03, 0xA8,0x03,0xB5,0x03,0xC2,0x03,0xCF,0x03,0xDC,0x03,0xE9,0x03,0xF6,0x03,0x03,0x04,0x10,0x04, 0x1D,0x04,0x2A,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5E,0x04,0x6B,0x04,0x78,0x04,0x85,0x04, 0x92,0x04,0x9F,0x04,0xAC,0x04,0xB9,0x04,0xC6,0x04,0xD3,0x04, 7, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x21 '!' 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, 7, // 0x22 '"' 0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x00, 7, // 0x24 '$' 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, 7, // 0x25 '%' 0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, 7, // 0x26 '&' 0x00,0x20,0x50,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00, 7, // 0x27 ''' 0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, 7, // 0x29 ')' 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, 7, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, 7, // 0x2B '+' 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 7, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 7, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, 7, // 0x2F '/' 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, 7, // 0x30 '0' 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00, 7, // 0x31 '1' 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x32 '2' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 7, // 0x33 '3' 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x34 '4' 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00, 7, // 0x35 '5' 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x36 '6' 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00, 7, // 0x38 '8' 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x39 '9' 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x3A ':' 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00, 7, // 0x3B ';' 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x20,0x40, 7, // 0x3C '<' 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, 7, // 0x3D '=' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, 7, // 0x3E '>' 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, 7, // 0x3F '?' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, 7, // 0x40 '@' 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, 7, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x42 'B' 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, 7, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, 7, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, 7, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, 7, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00, 7, // 0x48 'H' 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x49 'I' 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, 7, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00, 7, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, 7, // 0x4D 'M' 0x00,0x44,0x6C,0x6C,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x4E 'N' 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00, 7, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, 7, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, 7, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, 7, // 0x53 'S' 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 7, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x56 'V' 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, 7, // 0x57 'W' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00, 7, // 0x58 'X' 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, 7, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, 7, // 0x5A 'Z' 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, 7, // 0x5B '[' 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, 7, // 0x5C '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, 7, // 0x5D ']' 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, 7, // 0x5E '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, 7, // 0x60 '`' 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, 7, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, 7, // 0x66 'f' 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, 7, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x69 'i' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x6A 'j' 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x30, 7, // 0x6B 'k' 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, 7, // 0x6C 'l' 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x6D 'm' 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x6E 'n' 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40, 7, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, 7, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, 7, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, 7, // 0x7A 'z' 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 7, // 0x7B '{' 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, 7, // 0x7C '|' 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, 7, // 0x7D '}' 0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60,0x00, 7, // 0x7E '~' 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u mcs7x12_mono_low[] = { 12, 4, 32, 128-32, 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7D,0x02,0x8A,0x02,0x97,0x02,0xA4,0x02,0xB1,0x02, 0xBE,0x02,0xCB,0x02,0xD8,0x02,0xE5,0x02,0xF2,0x02,0xFF,0x02,0x0C,0x03,0x19,0x03,0x26,0x03, 0x33,0x03,0x40,0x03,0x4D,0x03,0x5A,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8E,0x03,0x9B,0x03, 0xA8,0x03,0xB5,0x03,0xC2,0x03,0xCF,0x03,0xDC,0x03,0xE9,0x03,0xF6,0x03,0x03,0x04,0x10,0x04, 0x1D,0x04,0x2A,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5E,0x04,0x6B,0x04,0x78,0x04,0x85,0x04, 0x92,0x04,0x9F,0x04,0xAC,0x04,0xB9,0x04,0xC6,0x04,0xD3,0x04, 7, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x21 '!' 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, 7, // 0x22 '"' 0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00,0x00, 7, // 0x24 '$' 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00,0x00, 7, // 0x25 '%' 0x34,0x54,0x68,0x08,0x10,0x10,0x20,0x2C,0x54,0x58,0x00,0x00, 7, // 0x26 '&' 0x00,0x20,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00,0x00, 7, // 0x27 ''' 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, 7, // 0x29 ')' 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, 7, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, 7, // 0x2B '+' 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00, 7, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40,0x00, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x2F '/' 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, 7, // 0x30 '0' 0x00,0x38,0x44,0x44,0x54,0x54,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x31 '1' 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x32 '2' 0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, 7, // 0x33 '3' 0x00,0x38,0x44,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 7, // 0x34 '4' 0x00,0x08,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,0x00,0x00, 7, // 0x35 '5' 0x00,0x7C,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00,0x00, 7, // 0x36 '6' 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x37 '7' 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00,0x00, 7, // 0x38 '8' 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x39 '9' 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x44,0x38,0x00,0x00,0x00, 7, // 0x3A ':' 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x3B ';' 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40,0x00, 7, // 0x3C '<' 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, 7, // 0x3D '=' 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, 7, // 0x3E '>' 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, 7, // 0x3F '?' 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, 7, // 0x40 '@' 0x00,0x38,0x44,0x44,0x5C,0x54,0x4C,0x40,0x38,0x00,0x00,0x00, 7, // 0x41 'A' 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x42 'B' 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00,0x00, 7, // 0x43 'C' 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x44 'D' 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, 7, // 0x45 'E' 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, 7, // 0x46 'F' 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x47 'G' 0x00,0x38,0x44,0x40,0x40,0x4C,0x44,0x4C,0x34,0x00,0x00,0x00, 7, // 0x48 'H' 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x49 'I' 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x4A 'J' 0x00,0x1C,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, 7, // 0x4B 'K' 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x00,0x00,0x00, 7, // 0x4C 'L' 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, 7, // 0x4D 'M' 0x00,0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x4E 'N' 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x00,0x00,0x00, 7, // 0x4F 'O' 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x50 'P' 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x51 'Q' 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, 7, // 0x52 'R' 0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00,0x00, 7, // 0x53 'S' 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x54 'T' 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 7, // 0x55 'U' 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x56 'V' 0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00,0x00, 7, // 0x57 'W' 0x00,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x59 'Y' 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 7, // 0x5A 'Z' 0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00,0x00, 7, // 0x5B '[' 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, 7, // 0x5C '\' 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, 7, // 0x5D ']' 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, 7, // 0x5E '^' 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00, 7, // 0x60 '`' 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00,0x00, 7, // 0x62 'b' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x64 'd' 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00,0x00, 7, // 0x66 'f' 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, 7, // 0x68 'h' 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x69 'i' 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x6A 'j' 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30, 7, // 0x6B 'k' 0x00,0x40,0x40,0x4C,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, 7, // 0x6C 'l' 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, 7, // 0x6D 'm' 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x6E 'n' 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x00,0x00,0x00, 7, // 0x6F 'o' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40, 7, // 0x71 'q' 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,0x04, 7, // 0x72 'r' 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x38,0x44,0x30,0x08,0x44,0x38,0x00,0x00,0x00, 7, // 0x74 't' 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x24,0x18,0x00,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, 7, // 0x7A 'z' 0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, 7, // 0x7B '{' 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, 7, // 0x7C '|' 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, 7, // 0x7D '}' 0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60,0x00, 7, // 0x7E '~' 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x7F '' 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana12[] = { 12, 3, 32, 128-32, 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x5A,0x00,0x67,0x00,0x74,0x00, 0x81,0x00,0x8E,0x00,0x9B,0x00,0xA8,0x00,0xB5,0x00,0xC2,0x00,0xCF,0x00,0xDC,0x00,0xE9,0x00, 0xF6,0x00,0x03,0x01,0x10,0x01,0x1D,0x01,0x2A,0x01,0x37,0x01,0x44,0x01,0x51,0x01,0x5E,0x01, 0x6B,0x01,0x78,0x01,0x85,0x01,0x92,0x01,0x9F,0x01,0xAC,0x01,0xC5,0x01,0xD2,0x01,0xDF,0x01, 0xEC,0x01,0xF9,0x01,0x06,0x02,0x13,0x02,0x20,0x02,0x2D,0x02,0x3A,0x02,0x47,0x02,0x54,0x02, 0x61,0x02,0x7A,0x02,0x87,0x02,0xA0,0x02,0xAD,0x02,0xC6,0x02,0xD3,0x02,0xE0,0x02,0xED,0x02, 0xFA,0x02,0x07,0x03,0x20,0x03,0x2D,0x03,0x3A,0x03,0x47,0x03,0x54,0x03,0x61,0x03,0x6E,0x03, 0x7B,0x03,0x88,0x03,0x95,0x03,0xA2,0x03,0xAF,0x03,0xBC,0x03,0xC9,0x03,0xD6,0x03,0xE3,0x03, 0xF0,0x03,0xFD,0x03,0x0A,0x04,0x17,0x04,0x24,0x04,0x31,0x04,0x4A,0x04,0x57,0x04,0x64,0x04, 0x71,0x04,0x7E,0x04,0x8B,0x04,0x98,0x04,0xA5,0x04,0xB2,0x04,0xBF,0x04,0xCC,0x04,0xD9,0x04, 0xE6,0x04,0xF3,0x04,0x00,0x05,0x0D,0x05,0x1A,0x05,0x27,0x05, 3, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 5, // 0x22 '"' 0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x23 '#' 0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00,0x00, 7, // 0x24 '$' 0x00,0x00,0x10,0x10,0x3C,0x50,0x30,0x18,0x14,0x78,0x10,0x10, 11, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x4A,0x00,0x4A,0x00,0x35,0x80,0x0A,0x40,0x0A,0x40,0x11,0x80,0x00,0x00,0x00,0x00, 7, // 0x26 '&' 0x00,0x00,0x00,0x30,0x48,0x48,0x32,0x4A,0x44,0x3A,0x00,0x00, 3, // 0x27 ''' 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x28 '(' 0x00,0x00,0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x10, 4, // 0x29 ')' 0x00,0x00,0x80,0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x40,0x80, 7, // 0x2A '*' 0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x2B '+' 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 3, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80,0x00, 5, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00, 3, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00, 4, // 0x2F '/' 0x00,0x00,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x80,0x00, 7, // 0x30 '0' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x31 '1' 0x00,0x00,0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, 7, // 0x32 '2' 0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x7C,0x00,0x00, 7, // 0x33 '3' 0x00,0x00,0x00,0x38,0x44,0x04,0x18,0x04,0x44,0x38,0x00,0x00, 7, // 0x34 '4' 0x00,0x00,0x00,0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, 7, // 0x35 '5' 0x00,0x00,0x00,0x7C,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x36 '6' 0x00,0x00,0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00, 7, // 0x37 '7' 0x00,0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x10,0x00,0x00, 7, // 0x38 '8' 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, 7, // 0x39 '9' 0x00,0x00,0x00,0x38,0x44,0x44,0x3C,0x04,0x08,0x30,0x00,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x80,0x00, 7, // 0x3C '<' 0x00,0x00,0x00,0x00,0x04,0x18,0x60,0x18,0x04,0x00,0x00,0x00, 7, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,0x00, 7, // 0x3E '>' 0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x30,0x40,0x00,0x00,0x00, 6, // 0x3F '?' 0x00,0x00,0x00,0x70,0x08,0x08,0x10,0x20,0x00,0x20,0x00,0x00, 10, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x4E,0x80,0x52,0x80,0x52,0x80,0x4D,0x00,0x20,0x00,0x1F,0x00,0x00,0x00, 8, // 0x41 'A' 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x7E,0x42,0x42,0x00,0x00, 7, // 0x42 'B' 0x00,0x00,0x00,0x70,0x48,0x48,0x78,0x44,0x44,0x78,0x00,0x00, 8, // 0x43 'C' 0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x22,0x1C,0x00,0x00, 8, // 0x44 'D' 0x00,0x00,0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x00,0x00, 7, // 0x45 'E' 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x7C,0x00,0x00, 6, // 0x46 'F' 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00, 8, // 0x47 'G' 0x00,0x00,0x00,0x1C,0x22,0x40,0x4E,0x42,0x22,0x1C,0x00,0x00, 8, // 0x48 'H' 0x00,0x00,0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x4A 'J' 0x00,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, 7, // 0x4B 'K' 0x00,0x00,0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, 6, // 0x4C 'L' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, 9, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 8, // 0x4E 'N' 0x00,0x00,0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x00,0x00, 9, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, 7, // 0x50 'P' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x00,0x00, 9, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x04,0x00,0x03,0x00, 7, // 0x52 'R' 0x00,0x00,0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, 7, // 0x53 'S' 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, 7, // 0x54 'T' 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 8, // 0x55 'U' 0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, 8, // 0x56 'V' 0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x00,0x00, 9, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x55,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 7, // 0x59 'Y' 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x00,0x00, 7, // 0x5A 'Z' 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 4, // 0x5B '[' 0x00,0x00,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, 4, // 0x5C '\' 0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x00, 4, // 0x5D ']' 0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, 7, // 0x5E '^' 0x00,0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, 6, // 0x60 '`' 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x30,0x08,0x38,0x48,0x38,0x00,0x00, 6, // 0x62 'b' 0x00,0x00,0x40,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00, 6, // 0x64 'd' 0x00,0x00,0x08,0x08,0x08,0x38,0x48,0x48,0x48,0x38,0x00,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00, 4, // 0x66 'f' 0x00,0x00,0x30,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x00,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x30, 6, // 0x68 'h' 0x00,0x00,0x40,0x40,0x40,0x70,0x48,0x48,0x48,0x48,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 3, // 0x6A 'j' 0x00,0x00,0x00,0x40,0x00,0xC0,0x40,0x40,0x40,0x40,0x40,0x80, 6, // 0x6B 'k' 0x00,0x00,0x40,0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 9, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00, 6, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x70,0x48,0x48,0x48,0x48,0x00,0x00, 6, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x70,0x48,0x48,0x48,0x70,0x40,0x40, 6, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x08, 4, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x50,0x60,0x40,0x40,0x40,0x00,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x30,0x08,0x70,0x00,0x00, 4, // 0x74 't' 0x00,0x00,0x00,0x00,0x40,0xF0,0x40,0x40,0x40,0x30,0x00,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x38,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x30,0x30,0x00,0x00, 7, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x44,0x54,0x54,0x28,0x28,0x00,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x30,0x48,0x48,0x00,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x30,0x10,0x20,0x20, 5, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x70,0x10,0x20,0x40,0x70,0x00,0x00, 6, // 0x7B '{' 0x00,0x00,0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x18, 5, // 0x7C '|' 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 6, // 0x7D '}' 0x00,0x00,0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x60, 7, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x58,0x00,0x00,0x00,0x00, 9, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana12_bold[] = { 12, 3, 32, 128-32, 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x5A,0x00,0x67,0x00,0x74,0x00, 0x81,0x00,0x8E,0x00,0x9B,0x00,0xA8,0x00,0xB5,0x00,0xC2,0x00,0xCF,0x00,0xDC,0x00,0xE9,0x00, 0xF6,0x00,0x03,0x01,0x10,0x01,0x1D,0x01,0x2A,0x01,0x37,0x01,0x44,0x01,0x51,0x01,0x5E,0x01, 0x6B,0x01,0x78,0x01,0x85,0x01,0x92,0x01,0x9F,0x01,0xAC,0x01,0xC5,0x01,0xD2,0x01,0xDF,0x01, 0xEC,0x01,0xF9,0x01,0x06,0x02,0x13,0x02,0x20,0x02,0x2D,0x02,0x3A,0x02,0x47,0x02,0x54,0x02, 0x61,0x02,0x6E,0x02,0x7B,0x02,0x88,0x02,0x95,0x02,0xA2,0x02,0xAF,0x02,0xBC,0x02,0xC9,0x02, 0xD6,0x02,0xE3,0x02,0xFC,0x02,0x09,0x03,0x16,0x03,0x23,0x03,0x30,0x03,0x3D,0x03,0x4A,0x03, 0x57,0x03,0x64,0x03,0x71,0x03,0x7E,0x03,0x8B,0x03,0x98,0x03,0xA5,0x03,0xB2,0x03,0xBF,0x03, 0xCC,0x03,0xD9,0x03,0xE6,0x03,0xF3,0x03,0x00,0x04,0x0D,0x04,0x26,0x04,0x33,0x04,0x40,0x04, 0x4D,0x04,0x5A,0x04,0x67,0x04,0x74,0x04,0x81,0x04,0x8E,0x04,0x9B,0x04,0xB4,0x04,0xC1,0x04, 0xCE,0x04,0xDB,0x04,0xE8,0x04,0xF5,0x04,0x02,0x05,0x0F,0x05, 3, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x00,0x00, 5, // 0x22 '"' 0x00,0x00,0xD8,0xD8,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x23 '#' 0x00,0x00,0x00,0x14,0x14,0x7E,0x28,0xFC,0x50,0x50,0x00,0x00, 6, // 0x24 '$' 0x00,0x00,0x20,0x20,0x70,0xE8,0xE0,0x38,0xB8,0x70,0x20,0x20, 11, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x00,0x94,0x00,0x94,0x00,0x69,0x80,0x0A,0x40,0x0A,0x40,0x11,0x80,0x00,0x00,0x00,0x00, 8, // 0x26 '&' 0x00,0x00,0x00,0x70,0xD8,0xD8,0x76,0xDC,0xCC,0x76,0x00,0x00, 3, // 0x27 ''' 0x00,0x00,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x00,0x00,0x30,0x60,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x60,0x30, 5, // 0x29 ')' 0x00,0x00,0xC0,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0xC0, 6, // 0x2A '*' 0x00,0x00,0x20,0xA8,0x70,0xA8,0x20,0x00,0x00,0x00,0x00,0x00, 8, // 0x2B '+' 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, 3, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x80,0x00, 4, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00, 3, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00, 6, // 0x2F '/' 0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0x80,0x00, 6, // 0x30 '0' 0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00, 6, // 0x31 '1' 0x00,0x00,0x00,0x30,0x70,0x30,0x30,0x30,0x30,0x78,0x00,0x00, 6, // 0x32 '2' 0x00,0x00,0x00,0x70,0x98,0x18,0x30,0x60,0xC0,0xF8,0x00,0x00, 6, // 0x33 '3' 0x00,0x00,0x00,0x70,0x98,0x18,0x70,0x18,0x98,0x70,0x00,0x00, 6, // 0x34 '4' 0x00,0x00,0x00,0x18,0x38,0x58,0x98,0xFC,0x18,0x18,0x00,0x00, 6, // 0x35 '5' 0x00,0x00,0x00,0xF8,0xC0,0xF0,0x18,0x18,0x98,0x70,0x00,0x00, 6, // 0x36 '6' 0x00,0x00,0x00,0x70,0xC0,0xF0,0xD8,0xD8,0xD8,0x70,0x00,0x00, 6, // 0x37 '7' 0x00,0x00,0x00,0xF8,0x18,0x30,0x30,0x60,0x60,0xC0,0x00,0x00, 6, // 0x38 '8' 0x00,0x00,0x00,0x70,0xD8,0xD8,0x70,0xD8,0xD8,0x70,0x00,0x00, 6, // 0x39 '9' 0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0x78,0x18,0x70,0x00,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x00,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x40,0x00, 8, // 0x3C '<' 0x00,0x00,0x00,0x00,0x04,0x18,0x60,0x60,0x18,0x04,0x00,0x00, 8, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,0x00, 8, // 0x3E '>' 0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x0C,0x30,0x40,0x00,0x00, 6, // 0x3F '?' 0x00,0x00,0x00,0xF0,0x18,0x18,0x30,0x60,0x00,0x60,0x00,0x00, 9, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x9D,0x00,0xA5,0x00,0xA5,0x00,0x9E,0x00,0x40,0x00,0x3C,0x00,0x00,0x00, 8, // 0x41 'A' 0x00,0x00,0x00,0x38,0x38,0x6C,0x6C,0x7C,0xC6,0xC6,0x00,0x00, 7, // 0x42 'B' 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xCC,0xCC,0xF8,0x00,0x00, 6, // 0x43 'C' 0x00,0x00,0x00,0x70,0xC8,0xC0,0xC0,0xC0,0xC8,0x70,0x00,0x00, 7, // 0x44 'D' 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0xCC,0xF8,0x00,0x00, 6, // 0x45 'E' 0x00,0x00,0x00,0xF8,0xC0,0xC0,0xF8,0xC0,0xC0,0xF8,0x00,0x00, 6, // 0x46 'F' 0x00,0x00,0x00,0xF8,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,0x00, 7, // 0x47 'G' 0x00,0x00,0x00,0x78,0xC4,0xC0,0xC0,0xDC,0xCC,0x7C,0x00,0x00, 7, // 0x48 'H' 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00, 5, // 0x4A 'J' 0x00,0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0xE0,0x00,0x00, 7, // 0x4B 'K' 0x00,0x00,0x00,0xCC,0xD8,0xF0,0xE0,0xF0,0xD8,0xCC,0x00,0x00, 6, // 0x4C 'L' 0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xF8,0x00,0x00, 8, // 0x4D 'M' 0x00,0x00,0x00,0x82,0xC6,0xEE,0xB6,0xB6,0x86,0x86,0x00,0x00, 7, // 0x4E 'N' 0x00,0x00,0x00,0x84,0xC4,0xE4,0xB4,0x9C,0x8C,0x84,0x00,0x00, 8, // 0x4F 'O' 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00, 7, // 0x50 'P' 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xF8,0xC0,0xC0,0x00,0x00, 8, // 0x51 'Q' 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x18,0x0E, 7, // 0x52 'R' 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xD8,0xCC,0xC6,0x00,0x00, 6, // 0x53 'S' 0x00,0x00,0x00,0x70,0xC8,0xC0,0x70,0x18,0x98,0x70,0x00,0x00, 6, // 0x54 'T' 0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, 7, // 0x55 'U' 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00, 7, // 0x56 'V' 0x00,0x00,0x00,0xCC,0xCC,0x78,0x78,0x78,0x30,0x30,0x00,0x00, 11, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xC0,0xCC,0xC0,0x6D,0x80,0x6D,0x80,0x73,0x80,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00, 7, // 0x58 'X' 0x00,0x00,0x00,0xCC,0xCC,0x78,0x30,0x78,0xCC,0xCC,0x00,0x00, 7, // 0x59 'Y' 0x00,0x00,0x00,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x00,0x00, 6, // 0x5A 'Z' 0x00,0x00,0x00,0xF8,0x18,0x30,0x60,0xC0,0xC0,0xF8,0x00,0x00, 5, // 0x5B '[' 0x00,0x00,0x70,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x70, 6, // 0x5C '\' 0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x10,0x08,0x08,0x00, 5, // 0x5D ']' 0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x70, 8, // 0x5E '^' 0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, 6, // 0x60 '`' 0x00,0x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x70,0x18,0x78,0xD8,0x78,0x00,0x00, 6, // 0x62 'b' 0x00,0x00,0xC0,0xC0,0xC0,0xF0,0xD8,0xD8,0xD8,0xF0,0x00,0x00, 5, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0xC0,0xC0,0x70,0x00,0x00, 6, // 0x64 'd' 0x00,0x00,0x18,0x18,0x18,0x78,0xD8,0xD8,0xD8,0x78,0x00,0x00, 6, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0xF8,0xC0,0x78,0x00,0x00, 5, // 0x66 'f' 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x00,0x00, 6, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x78,0xD8,0xD8,0xD8,0x78,0x18,0x70, 6, // 0x68 'h' 0x00,0x00,0xC0,0xC0,0xC0,0xF0,0xD8,0xD8,0xD8,0xD8,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x00,0xC0,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00, 4, // 0x6A 'j' 0x00,0x00,0x00,0x60,0x00,0xE0,0x60,0x60,0x60,0x60,0x60,0xC0, 6, // 0x6B 'k' 0x00,0x00,0xC0,0xC0,0xC0,0xD8,0xD8,0xF0,0xD8,0xD8,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00, 9, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF6,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00, 6, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0xF0,0xD8,0xD8,0xD8,0xD8,0x00,0x00, 6, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0x70,0x00,0x00, 6, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0xF0,0xD8,0xD8,0xD8,0xF0,0xC0,0xC0, 6, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x78,0xD8,0xD8,0xD8,0x78,0x18,0x18, 4, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0xD0,0xE0,0xC0,0xC0,0xC0,0x00,0x00, 5, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0xF0,0x30,0xE0,0x00,0x00, 5, // 0x74 't' 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x38,0x00,0x00, 6, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0xD8,0x78,0x00,0x00, 6, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0x70,0x70,0x00,0x00, 9, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0x66,0x00,0x66,0x00,0x00,0x00,0x00,0x00, 6, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x70,0xD8,0xD8,0x00,0x00, 6, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0x70,0x70,0x30,0x60, 5, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0xF0,0x30,0x60,0xC0,0xF0,0x00,0x00, 6, // 0x7B '{' 0x00,0x00,0x18,0x30,0x30,0x30,0xE0,0x30,0x30,0x30,0x30,0x18, 5, // 0x7C '|' 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 6, // 0x7D '}' 0x00,0x00,0xC0,0x60,0x60,0x60,0x38,0x60,0x60,0x60,0x60,0xC0, 8, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x92,0x8C,0x00,0x00,0x00, 9, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana13[] = { 13, 3, 32, 128-32, 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x45,0x00,0x53,0x00,0x6E,0x00,0x7C,0x00,0x8A,0x00, 0x98,0x00,0xA6,0x00,0xB4,0x00,0xCF,0x00,0xDD,0x00,0xEB,0x00,0xF9,0x00,0x07,0x01,0x15,0x01, 0x23,0x01,0x31,0x01,0x3F,0x01,0x4D,0x01,0x5B,0x01,0x69,0x01,0x77,0x01,0x85,0x01,0x93,0x01, 0xA1,0x01,0xAF,0x01,0xCA,0x01,0xE5,0x01,0x00,0x02,0x0E,0x02,0x29,0x02,0x37,0x02,0x45,0x02, 0x60,0x02,0x7B,0x02,0x89,0x02,0x97,0x02,0xB2,0x02,0xC0,0x02,0xCE,0x02,0xDC,0x02,0xEA,0x02, 0xF8,0x02,0x13,0x03,0x21,0x03,0x3C,0x03,0x4A,0x03,0x65,0x03,0x73,0x03,0x81,0x03,0x8F,0x03, 0x9D,0x03,0xAB,0x03,0xC6,0x03,0xD4,0x03,0xE2,0x03,0xF0,0x03,0xFE,0x03,0x0C,0x04,0x1A,0x04, 0x35,0x04,0x43,0x04,0x51,0x04,0x5F,0x04,0x6D,0x04,0x7B,0x04,0x89,0x04,0x97,0x04,0xA5,0x04, 0xB3,0x04,0xC1,0x04,0xCF,0x04,0xDD,0x04,0xEB,0x04,0xF9,0x04,0x14,0x05,0x22,0x05,0x30,0x05, 0x3E,0x05,0x4C,0x05,0x5A,0x05,0x68,0x05,0x76,0x05,0x84,0x05,0x92,0x05,0xAD,0x05,0xBB,0x05, 0xC9,0x05,0xD7,0x05,0xE5,0x05,0xF3,0x05,0x01,0x06,0x1C,0x06, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 5, // 0x22 '"' 0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x0A,0x00,0x3F,0x00,0x14,0x00,0x14,0x00,0x7E,0x00,0x28,0x00,0x28,0x00,0x00,0x00,0x00,0x00, 7, // 0x24 '$' 0x00,0x00,0x10,0x10,0x3C,0x50,0x50,0x38,0x14,0x14,0x78,0x10,0x10, 12, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x4A,0x00,0x32,0x00,0x04,0xC0,0x05,0x20,0x09,0x20,0x08,0xC0,0x00,0x00,0x00,0x00, 8, // 0x26 '&' 0x00,0x00,0x00,0x30,0x48,0x48,0x32,0x4A,0x44,0x46,0x39,0x00,0x00, 3, // 0x27 ''' 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x00,0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, 5, // 0x29 ')' 0x00,0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, 7, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, 5, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00, 5, // 0x2F '/' 0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, 7, // 0x30 '0' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x31 '1' 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, 7, // 0x32 '2' 0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 7, // 0x33 '3' 0x00,0x00,0x00,0x38,0x44,0x04,0x18,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x34 '4' 0x00,0x00,0x00,0x08,0x18,0x28,0x48,0x88,0xFC,0x08,0x08,0x00,0x00, 7, // 0x35 '5' 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, 7, // 0x36 '6' 0x00,0x00,0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x37 '7' 0x00,0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00, 7, // 0x38 '8' 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x39 '9' 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x08,0x30,0x00,0x00, 5, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x00,0x00, 5, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x40, 9, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x3F '?' 0x00,0x00,0x00,0x70,0x08,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, 10, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x4E,0x80,0x52,0x80,0x52,0x80,0x52,0x80,0x4D,0x00,0x20,0x00,0x1E,0x00,0x00,0x00, 8, // 0x41 'A' 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x24,0x7E,0x42,0x42,0x00,0x00, 8, // 0x42 'B' 0x00,0x00,0x00,0x78,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00, 9, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, 9, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 7, // 0x45 'E' 0x00,0x00,0x00,0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C,0x00,0x00, 6, // 0x46 'F' 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, 9, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, 8, // 0x48 'H' 0x00,0x00,0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x4A 'J' 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, 8, // 0x4B 'K' 0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x70,0x48,0x44,0x42,0x00,0x00, 6, // 0x4C 'L' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, 9, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 8, // 0x4E 'N' 0x00,0x00,0x00,0x62,0x62,0x52,0x52,0x4A,0x4A,0x46,0x46,0x00,0x00, 9, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, 7, // 0x50 'P' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, 9, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x04,0x00,0x03,0x00, 8, // 0x52 'R' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x42,0x00,0x00, 8, // 0x53 'S' 0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00, 7, // 0x54 'T' 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 8, // 0x55 'U' 0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, 8, // 0x56 'V' 0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00, 11, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00, 8, // 0x58 'X' 0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x00,0x00, 7, // 0x59 'Y' 0x00,0x00,0x00,0x82,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 8, // 0x5A 'Z' 0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x00, 5, // 0x5B '[' 0x00,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, 5, // 0x5C '\' 0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, 5, // 0x5D ']' 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, 9, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE, 7, // 0x60 '`' 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00, 7, // 0x62 'b' 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, 7, // 0x64 'd' 0x00,0x00,0x04,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, 7, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, 4, // 0x66 'f' 0x00,0x00,0x30,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 7, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x38, 7, // 0x68 'h' 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 4, // 0x6A 'j' 0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, 7, // 0x6B 'k' 0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x70,0x48,0x44,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 11, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0x80,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00, 7, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, 7, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, 7, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, 7, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, 5, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x00,0x00, 6, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x60,0x18,0x08,0x70,0x00,0x00, 4, // 0x74 't' 0x00,0x00,0x00,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x30,0x00,0x00, 7, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, 9, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x55,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x10,0x10,0x28,0x44,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x20, 6, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x78,0x08,0x10,0x20,0x40,0x78,0x00,0x00, 7, // 0x7B '{' 0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x0C, 5, // 0x7C '|' 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 7, // 0x7D '}' 0x00,0x00,0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60, 9, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x00,0x00,0x00,0x00, 0 }; const int8u verdana13_bold[] = { 13, 3, 32, 128-32, 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x45,0x00,0x53,0x00,0x6E,0x00,0x89,0x00,0x97,0x00, 0xA5,0x00,0xB3,0x00,0xC1,0x00,0xDC,0x00,0xEA,0x00,0xF8,0x00,0x06,0x01,0x14,0x01,0x22,0x01, 0x30,0x01,0x3E,0x01,0x4C,0x01,0x5A,0x01,0x68,0x01,0x76,0x01,0x84,0x01,0x92,0x01,0xA0,0x01, 0xAE,0x01,0xBC,0x01,0xD7,0x01,0xF2,0x01,0x0D,0x02,0x1B,0x02,0x36,0x02,0x51,0x02,0x5F,0x02, 0x6D,0x02,0x88,0x02,0x96,0x02,0xA4,0x02,0xBF,0x02,0xDA,0x02,0xE8,0x02,0xF6,0x02,0x04,0x03, 0x12,0x03,0x2D,0x03,0x48,0x03,0x63,0x03,0x71,0x03,0x8C,0x03,0x9A,0x03,0xA8,0x03,0xB6,0x03, 0xD1,0x03,0xDF,0x03,0xFA,0x03,0x08,0x04,0x16,0x04,0x24,0x04,0x32,0x04,0x40,0x04,0x4E,0x04, 0x69,0x04,0x77,0x04,0x85,0x04,0x93,0x04,0xA1,0x04,0xAF,0x04,0xBD,0x04,0xCB,0x04,0xD9,0x04, 0xE7,0x04,0xF5,0x04,0x03,0x05,0x11,0x05,0x1F,0x05,0x2D,0x05,0x48,0x05,0x56,0x05,0x64,0x05, 0x72,0x05,0x80,0x05,0x8E,0x05,0x9C,0x05,0xAA,0x05,0xB8,0x05,0xC6,0x05,0xE1,0x05,0xEF,0x05, 0xFD,0x05,0x0B,0x06,0x19,0x06,0x27,0x06,0x35,0x06,0x50,0x06, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x21 '!' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x0A,0x00,0x3F,0x00,0x14,0x00,0x14,0x00,0x7E,0x00,0x28,0x00,0x28,0x00,0x00,0x00,0x00,0x00, 8, // 0x24 '$' 0x00,0x00,0x08,0x08,0x3C,0x6A,0x68,0x3C,0x16,0x56,0x3C,0x10,0x10, 14, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x80,0x6C,0x80,0x6D,0x00,0x6D,0x70,0x3A,0xD8,0x02,0xD8,0x04,0xD8,0x04,0x70,0x00,0x00,0x00,0x00, 10, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x39,0x80,0x6D,0x00,0x66,0x00,0x63,0x00,0x3D,0x80,0x00,0x00,0x00,0x00, 4, // 0x27 ''' 0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x00,0x00,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18, 6, // 0x29 ')' 0x00,0x00,0x60,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x30,0x30,0x60, 8, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x40, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, 8, // 0x2F '/' 0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x30,0x30,0x60,0x60, 8, // 0x30 '0' 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, 8, // 0x31 '1' 0x00,0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00, 8, // 0x32 '2' 0x00,0x00,0x00,0x3C,0x66,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00, 8, // 0x33 '3' 0x00,0x00,0x00,0x3C,0x66,0x06,0x1C,0x06,0x06,0x66,0x3C,0x00,0x00, 8, // 0x34 '4' 0x00,0x00,0x00,0x04,0x0C,0x1C,0x2C,0x4C,0x7E,0x0C,0x0C,0x00,0x00, 8, // 0x35 '5' 0x00,0x00,0x00,0x3E,0x30,0x30,0x3C,0x06,0x06,0x66,0x3C,0x00,0x00, 8, // 0x36 '6' 0x00,0x00,0x00,0x1C,0x30,0x60,0x7C,0x66,0x66,0x66,0x3C,0x00,0x00, 8, // 0x37 '7' 0x00,0x00,0x00,0x7E,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x00,0x00, 8, // 0x38 '8' 0x00,0x00,0x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00, 8, // 0x39 '9' 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00,0x00, 4, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00, 4, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x60,0x40, 9, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00, 9, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00, 7, // 0x3F '?' 0x00,0x00,0x00,0x38,0x4C,0x0C,0x18,0x30,0x30,0x00,0x30,0x00,0x00, 11, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x4F,0x40,0x5B,0x40,0x5B,0x40,0x5B,0x40,0x4F,0x80,0x20,0x00,0x1F,0x00,0x00,0x00, 9, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, 8, // 0x42 'B' 0x00,0x00,0x00,0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x7C,0x00,0x00, 8, // 0x43 'C' 0x00,0x00,0x00,0x3C,0x62,0x60,0x60,0x60,0x60,0x62,0x3C,0x00,0x00, 9, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x66,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 8, // 0x45 'E' 0x00,0x00,0x00,0x7E,0x60,0x60,0x7E,0x60,0x60,0x60,0x7E,0x00,0x00, 8, // 0x46 'F' 0x00,0x00,0x00,0x7E,0x60,0x60,0x7E,0x60,0x60,0x60,0x60,0x00,0x00, 9, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x67,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, 9, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, 6, // 0x49 'I' 0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, 6, // 0x4A 'J' 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0xF0,0x00,0x00, 8, // 0x4B 'K' 0x00,0x00,0x00,0x66,0x6C,0x78,0x70,0x70,0x78,0x6C,0x66,0x00,0x00, 7, // 0x4C 'L' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0x00, 10, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x71,0x80,0x7B,0x80,0x5D,0x80,0x49,0x80,0x41,0x80,0x41,0x80,0x41,0x80,0x00,0x00,0x00,0x00, 9, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x61,0x00,0x71,0x00,0x59,0x00,0x4D,0x00,0x47,0x00,0x43,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 9, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 8, // 0x50 'P' 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00, 9, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x0C,0x00,0x07,0x00, 8, // 0x52 'R' 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x6C,0x66,0x63,0x00,0x00, 8, // 0x53 'S' 0x00,0x00,0x00,0x3C,0x62,0x60,0x7C,0x3E,0x06,0x46,0x3C,0x00,0x00, 8, // 0x54 'T' 0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00, 9, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 8, // 0x56 'V' 0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x18,0x00,0x00, 12, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x36,0xC0,0x3F,0xC0,0x39,0xC0,0x19,0x80,0x19,0x80,0x00,0x00,0x00,0x00, 8, // 0x58 'X' 0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x18,0x3C,0x66,0x66,0x00,0x00, 8, // 0x59 'Y' 0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x18,0x18,0x18,0x00,0x00, 8, // 0x5A 'Z' 0x00,0x00,0x00,0x7E,0x06,0x0E,0x1C,0x38,0x70,0x60,0x7E,0x00,0x00, 6, // 0x5B '[' 0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78, 8, // 0x5C '\' 0x00,0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x18,0x0C,0x0C,0x06,0x06, 6, // 0x5D ']' 0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78, 10, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, 8, // 0x60 '`' 0x00,0x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3E,0x00,0x00, 8, // 0x62 'b' 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x60,0x60,0x60,0x3C,0x00,0x00, 8, // 0x64 'd' 0x00,0x00,0x06,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x7E,0x60,0x62,0x3C,0x00,0x00, 5, // 0x66 'f' 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 8, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, 8, // 0x68 'h' 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00, 4, // 0x69 'i' 0x00,0x00,0x00,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 5, // 0x6A 'j' 0x00,0x00,0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, 8, // 0x6B 'k' 0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x00,0x00, 4, // 0x6C 'l' 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 12, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7D,0xC0,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x00,0x00,0x00,0x00, 8, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00, 8, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, 8, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0x60, 8, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06,0x06, 6, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x78,0x3C,0x0C,0x78,0x00,0x00, 5, // 0x74 't' 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x38,0x00,0x00, 8, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, 8, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x18,0x00,0x00, 10, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00, 8, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x66,0x66,0x00,0x00, 8, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x18,0x30,0x30, 7, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x7C,0x0C,0x18,0x30,0x60,0x7C,0x00,0x00, 8, // 0x7B '{' 0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E, 6, // 0x7C '|' 0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 8, // 0x7D '}' 0x00,0x00,0x70,0x18,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70, 9, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x49,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x00,0x00,0x00,0x00, 0 }; const int8u verdana14[] = { 14, 3, 32, 128-32, 0x00,0x00,0x0F,0x00,0x1E,0x00,0x2D,0x00,0x4A,0x00,0x59,0x00,0x76,0x00,0x93,0x00,0xA2,0x00, 0xB1,0x00,0xC0,0x00,0xCF,0x00,0xEC,0x00,0xFB,0x00,0x0A,0x01,0x19,0x01,0x28,0x01,0x37,0x01, 0x46,0x01,0x55,0x01,0x64,0x01,0x73,0x01,0x82,0x01,0x91,0x01,0xA0,0x01,0xAF,0x01,0xBE,0x01, 0xCD,0x01,0xDC,0x01,0xF9,0x01,0x16,0x02,0x33,0x02,0x42,0x02,0x5F,0x02,0x6E,0x02,0x7D,0x02, 0x9A,0x02,0xB7,0x02,0xC6,0x02,0xD5,0x02,0xF2,0x02,0x0F,0x03,0x1E,0x03,0x2D,0x03,0x3C,0x03, 0x4B,0x03,0x68,0x03,0x85,0x03,0xA2,0x03,0xB1,0x03,0xCE,0x03,0xDD,0x03,0xEC,0x03,0xFB,0x03, 0x18,0x04,0x27,0x04,0x44,0x04,0x53,0x04,0x62,0x04,0x71,0x04,0x80,0x04,0x8F,0x04,0x9E,0x04, 0xBB,0x04,0xCA,0x04,0xD9,0x04,0xE8,0x04,0xF7,0x04,0x06,0x05,0x15,0x05,0x24,0x05,0x33,0x05, 0x42,0x05,0x51,0x05,0x60,0x05,0x6F,0x05,0x7E,0x05,0x8D,0x05,0xAA,0x05,0xB9,0x05,0xC8,0x05, 0xD7,0x05,0xE6,0x05,0xF5,0x05,0x04,0x06,0x13,0x06,0x22,0x06,0x31,0x06,0x4E,0x06,0x5D,0x06, 0x6C,0x06,0x7B,0x06,0x8A,0x06,0x99,0x06,0xA8,0x06,0xC5,0x06, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, 6, // 0x22 '"' 0x00,0x00,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x12,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00, 8, // 0x24 '$' 0x00,0x00,0x10,0x10,0x3E,0x50,0x50,0x30,0x1C,0x12,0x12,0x7C,0x10,0x10, 13, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x49,0x00,0x49,0x00,0x4A,0x00,0x32,0x60,0x02,0x90,0x04,0x90,0x04,0x90,0x08,0x60,0x00,0x00,0x00,0x00, 10, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x39,0x00,0x45,0x00,0x42,0x00,0x43,0x00,0x3C,0x80,0x00,0x00,0x00,0x00, 3, // 0x27 ''' 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x28 '(' 0x00,0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, 5, // 0x29 ')' 0x00,0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, 8, // 0x2A '*' 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, 5, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00, 5, // 0x2F '/' 0x00,0x00,0x08,0x08,0x10,0x10,0x10,0x20,0x20,0x20,0x40,0x40,0x40,0x80, 8, // 0x30 '0' 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, 8, // 0x31 '1' 0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00, 8, // 0x32 '2' 0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x7E,0x00,0x00, 8, // 0x33 '3' 0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x1C,0x02,0x02,0x42,0x3C,0x00,0x00, 8, // 0x34 '4' 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x44,0x7F,0x04,0x04,0x04,0x00,0x00, 8, // 0x35 '5' 0x00,0x00,0x00,0x7E,0x40,0x40,0x7C,0x02,0x02,0x02,0x42,0x3C,0x00,0x00, 8, // 0x36 '6' 0x00,0x00,0x00,0x1C,0x20,0x40,0x7C,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, 8, // 0x37 '7' 0x00,0x00,0x00,0x7E,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x00,0x00, 8, // 0x38 '8' 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00, 8, // 0x39 '9' 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x3E,0x02,0x04,0x38,0x00,0x00, 5, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x00,0x00, 5, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40, 9, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00, 9, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00, 7, // 0x3F '?' 0x00,0x00,0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, 12, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x27,0x40,0x49,0x20,0x49,0x20,0x49,0x20,0x49,0x20,0x27,0xC0,0x30,0x00,0x0F,0x00,0x00,0x00, 8, // 0x41 'A' 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x42,0x42,0x7E,0x81,0x81,0x00,0x00, 8, // 0x42 'B' 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00, 9, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, 9, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, 8, // 0x45 'E' 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x7E,0x00,0x00, 7, // 0x46 'F' 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x40,0x00,0x00, 9, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, 9, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, 5, // 0x4A 'J' 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, 8, // 0x4B 'K' 0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00, 7, // 0x4C 'L' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x00, 10, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x52,0x80,0x52,0x80,0x52,0x80,0x4C,0x80,0x4C,0x80,0x40,0x80,0x40,0x80,0x00,0x00,0x00,0x00, 9, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x61,0x00,0x51,0x00,0x51,0x00,0x49,0x00,0x45,0x00,0x45,0x00,0x43,0x00,0x43,0x00,0x00,0x00,0x00,0x00, 10, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, 8, // 0x50 'P' 0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x00, 10, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x02,0x00,0x01,0x80, 8, // 0x52 'R' 0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x7C,0x48,0x44,0x42,0x41,0x00,0x00, 8, // 0x53 'S' 0x00,0x00,0x00,0x3C,0x42,0x40,0x40,0x3C,0x02,0x02,0x42,0x3C,0x00,0x00, 7, // 0x54 'T' 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 9, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, 8, // 0x56 'V' 0x00,0x00,0x00,0x81,0x81,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x00,0x00, 13, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x45,0x10,0x45,0x10,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00, 8, // 0x58 'X' 0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x18,0x24,0x42,0x42,0x00,0x00, 7, // 0x59 'Y' 0x00,0x00,0x00,0x82,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00,0x00, 8, // 0x5A 'Z' 0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x10,0x20,0x40,0x7E,0x00,0x00, 5, // 0x5B '[' 0x00,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, 5, // 0x5C '\' 0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x08, 5, // 0x5D ']' 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, 10, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, 8, // 0x60 '`' 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x3C,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,0x00, 8, // 0x62 'b' 0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x00,0x00, 6, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, 8, // 0x64 'd' 0x00,0x00,0x02,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00, 4, // 0x66 'f' 0x00,0x00,0x30,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 8, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x3C, 8, // 0x68 'h' 0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 4, // 0x6A 'j' 0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, 7, // 0x6B 'k' 0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 11, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0x80,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00, 8, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00, 8, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, 8, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x40,0x40, 8, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02, 5, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x3C,0x40,0x40,0x38,0x04,0x04,0x78,0x00,0x00, 5, // 0x74 't' 0x00,0x00,0x00,0x40,0x40,0xF8,0x40,0x40,0x40,0x40,0x40,0x38,0x00,0x00, 8, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, 7, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, 11, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, 7, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x20, 7, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, 8, // 0x7B '{' 0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x0C, 5, // 0x7C '|' 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 8, // 0x7D '}' 0x00,0x00,0x30,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30, 10, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x4C,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0xE0,0x00,0x00,0x00,0x00, 0 }; const int8u verdana14_bold[] = { 14, 3, 32, 128-32, 0x00,0x00,0x0F,0x00,0x1E,0x00,0x2D,0x00,0x4A,0x00,0x67,0x00,0x84,0x00,0xA1,0x00,0xB0,0x00, 0xBF,0x00,0xCE,0x00,0xEB,0x00,0x08,0x01,0x17,0x01,0x26,0x01,0x35,0x01,0x44,0x01,0x61,0x01, 0x7E,0x01,0x9B,0x01,0xB8,0x01,0xD5,0x01,0xF2,0x01,0x0F,0x02,0x2C,0x02,0x49,0x02,0x66,0x02, 0x75,0x02,0x84,0x02,0xA1,0x02,0xBE,0x02,0xDB,0x02,0xEA,0x02,0x07,0x03,0x24,0x03,0x41,0x03, 0x5E,0x03,0x7B,0x03,0x8A,0x03,0x99,0x03,0xB6,0x03,0xD3,0x03,0xE2,0x03,0xF1,0x03,0x0E,0x04, 0x1D,0x04,0x3A,0x04,0x57,0x04,0x74,0x04,0x91,0x04,0xAE,0x04,0xCB,0x04,0xE8,0x04,0xF7,0x04, 0x14,0x05,0x31,0x05,0x4E,0x05,0x6B,0x05,0x88,0x05,0x97,0x05,0xA6,0x05,0xB5,0x05,0xC4,0x05, 0xE1,0x05,0xFE,0x05,0x1B,0x06,0x2A,0x06,0x39,0x06,0x48,0x06,0x57,0x06,0x66,0x06,0x75,0x06, 0x84,0x06,0x93,0x06,0xA2,0x06,0xB1,0x06,0xC0,0x06,0xCF,0x06,0xEC,0x06,0xFB,0x06,0x0A,0x07, 0x19,0x07,0x28,0x07,0x37,0x07,0x46,0x07,0x55,0x07,0x64,0x07,0x73,0x07,0x90,0x07,0x9F,0x07, 0xAE,0x07,0xBD,0x07,0xDA,0x07,0xE9,0x07,0x06,0x08,0x23,0x08, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x60,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x3F,0x80,0x12,0x00,0x7F,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00, 9, // 0x24 '$' 0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x69,0x00,0x68,0x00,0x7E,0x00,0x3F,0x00,0x0B,0x00,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00, 15, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x6C,0x40,0x6C,0x80,0x6C,0xB8,0x6D,0x6C,0x3A,0x6C,0x02,0x6C,0x04,0x6C,0x04,0x38,0x00,0x00,0x00,0x00, 10, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x39,0x80,0x6D,0x00,0x66,0x00,0x63,0x00,0x3D,0x80,0x00,0x00,0x00,0x00, 4, // 0x27 ''' 0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x00,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18, 7, // 0x29 ')' 0x00,0x00,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x18,0x30, 9, // 0x2A '*' 0x00,0x00,0x00,0x00,0x08,0x00,0x2A,0x00,0x1C,0x00,0x1C,0x00,0x2A,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x40, 6, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, 8, // 0x2F '/' 0x00,0x00,0x06,0x06,0x0C,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x60,0x60, 9, // 0x30 '0' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 9, // 0x31 '1' 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, 9, // 0x32 '2' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, 9, // 0x33 '3' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x1E,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 9, // 0x34 '4' 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0E,0x00,0x16,0x00,0x16,0x00,0x26,0x00,0x46,0x00,0x7F,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00, 9, // 0x35 '5' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 9, // 0x36 '6' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x30,0x00,0x60,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 9, // 0x37 '7' 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00, 9, // 0x38 '8' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 9, // 0x39 '9' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x03,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00,0x00, 5, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00, 5, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x60,0x40, 10, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00, 10, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00,0x00,0x00,0x00, 7, // 0x3F '?' 0x00,0x00,0x00,0x38,0x4C,0x0C,0x18,0x30,0x30,0x00,0x30,0x30,0x00,0x00, 12, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x2F,0x40,0x5B,0x20,0x5B,0x20,0x5B,0x20,0x5B,0x20,0x2F,0xC0,0x30,0x00,0x0F,0x00,0x00,0x00, 9, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, 9, // 0x42 'B' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00, 9, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x31,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, 10, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00, 8, // 0x45 'E' 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7E,0x60,0x60,0x60,0x7E,0x00,0x00, 8, // 0x46 'F' 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7E,0x60,0x60,0x60,0x60,0x00,0x00, 10, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x30,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x67,0x80,0x61,0x80,0x31,0x80,0x1F,0x80,0x00,0x00,0x00,0x00, 10, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00, 6, // 0x49 'I' 0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, 7, // 0x4A 'J' 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xF8,0x00,0x00, 9, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x70,0x00,0x78,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x00,0x00,0x00,0x00, 8, // 0x4C 'L' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00, 11, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x71,0xC0,0x71,0xC0,0x5A,0xC0,0x5A,0xC0,0x4C,0xC0,0x4C,0xC0,0x40,0xC0,0x40,0xC0,0x00,0x00,0x00,0x00, 10, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x70,0x80,0x58,0x80,0x58,0x80,0x4C,0x80,0x46,0x80,0x46,0x80,0x43,0x80,0x41,0x80,0x00,0x00,0x00,0x00, 11, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00, 9, // 0x50 'P' 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00, 11, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x06,0x00,0x03,0xC0, 9, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00, 9, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x70,0x00,0x3E,0x00,0x07,0x00,0x03,0x00,0x43,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, 8, // 0x54 'T' 0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00, 10, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00, 9, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, 14, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00, 9, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, 10, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00, 8, // 0x5A 'Z' 0x00,0x00,0x00,0x7E,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x7E,0x00,0x00, 6, // 0x5B '[' 0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78, 8, // 0x5C '\' 0x00,0x00,0x60,0x60,0x30,0x30,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x06,0x06, 6, // 0x5D ']' 0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78, 10, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80, 9, // 0x60 '`' 0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x66,0x3E,0x00,0x00, 8, // 0x62 'b' 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x3C,0x62,0x60,0x60,0x60,0x62,0x3C,0x00,0x00, 8, // 0x64 'd' 0x00,0x00,0x06,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x62,0x3C,0x00,0x00, 5, // 0x66 'f' 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 8, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, 8, // 0x68 'h' 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00, 4, // 0x69 'i' 0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 5, // 0x6A 'j' 0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, 8, // 0x6B 'k' 0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x63,0x00,0x00, 4, // 0x6C 'l' 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 12, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xC0,0x77,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x00,0x00,0x00,0x00, 8, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00, 8, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, 8, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60, 8, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x06, 6, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x60,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x60,0x38,0x0C,0x0C,0x78,0x00,0x00, 5, // 0x74 't' 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x38,0x00,0x00, 8, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, 8, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x00,0x00, 12, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x69,0x60,0x39,0xC0,0x30,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00, 8, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00, 8, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x18,0x30, 7, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x7C,0x0C,0x18,0x38,0x30,0x60,0x7C,0x00,0x00, 9, // 0x7B '{' 0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0E,0x00, 6, // 0x7C '|' 0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 9, // 0x7D '}' 0x00,0x00,0x00,0x00,0x38,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x38,0x00, 10, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x48,0x80,0x44,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0xE0,0x00,0x00,0x00,0x00, 0 }; const int8u verdana16[] = { 16, 4, 32, 128-32, 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x54,0x00,0x65,0x00,0x86,0x00,0xA7,0x00,0xB8,0x00, 0xC9,0x00,0xDA,0x00,0xFB,0x00,0x1C,0x01,0x2D,0x01,0x3E,0x01,0x4F,0x01,0x60,0x01,0x71,0x01, 0x82,0x01,0x93,0x01,0xA4,0x01,0xB5,0x01,0xC6,0x01,0xD7,0x01,0xE8,0x01,0xF9,0x01,0x0A,0x02, 0x1B,0x02,0x2C,0x02,0x4D,0x02,0x6E,0x02,0x8F,0x02,0xA0,0x02,0xC1,0x02,0xE2,0x02,0xF3,0x02, 0x14,0x03,0x35,0x03,0x46,0x03,0x57,0x03,0x78,0x03,0x99,0x03,0xAA,0x03,0xBB,0x03,0xCC,0x03, 0xDD,0x03,0xFE,0x03,0x1F,0x04,0x40,0x04,0x51,0x04,0x72,0x04,0x93,0x04,0xB4,0x04,0xD5,0x04, 0xF6,0x04,0x17,0x05,0x38,0x05,0x59,0x05,0x7A,0x05,0x9B,0x05,0xAC,0x05,0xBD,0x05,0xCE,0x05, 0xEF,0x05,0x00,0x06,0x11,0x06,0x22,0x06,0x33,0x06,0x44,0x06,0x55,0x06,0x66,0x06,0x77,0x06, 0x88,0x06,0x99,0x06,0xAA,0x06,0xBB,0x06,0xCC,0x06,0xDD,0x06,0xFE,0x06,0x0F,0x07,0x20,0x07, 0x31,0x07,0x42,0x07,0x53,0x07,0x64,0x07,0x75,0x07,0x86,0x07,0x97,0x07,0xB8,0x07,0xC9,0x07, 0xDA,0x07,0xEB,0x07,0xFC,0x07,0x0D,0x08,0x1E,0x08,0x3F,0x08, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x21 '!' 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, 5, // 0x22 '"' 0x00,0x00,0x00,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x24 '$' 0x00,0x00,0x00,0x10,0x10,0x3E,0x50,0x50,0x30,0x1C,0x12,0x12,0x7C,0x10,0x10,0x00, 13, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x80,0x45,0x00,0x45,0x00,0x3A,0xE0,0x05,0x10,0x05,0x10,0x09,0x10,0x10,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x38,0x80,0x45,0x00,0x42,0x00,0x46,0x00,0x39,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 3, // 0x27 ''' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, 6, // 0x29 ')' 0x00,0x00,0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40, 9, // 0x2A '*' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, 6, // 0x2F '/' 0x00,0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, 8, // 0x30 '0' 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, 8, // 0x31 '1' 0x00,0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00,0x00, 8, // 0x32 '2' 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x7E,0x00,0x00,0x00, 8, // 0x33 '3' 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x1C,0x02,0x02,0x42,0x3C,0x00,0x00,0x00, 8, // 0x34 '4' 0x00,0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x44,0x7F,0x04,0x04,0x04,0x00,0x00,0x00, 8, // 0x35 '5' 0x00,0x00,0x00,0x00,0x3E,0x20,0x20,0x20,0x3C,0x02,0x02,0x42,0x3C,0x00,0x00,0x00, 8, // 0x36 '6' 0x00,0x00,0x00,0x00,0x1C,0x20,0x40,0x7C,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, 8, // 0x37 '7' 0x00,0x00,0x00,0x00,0x7E,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x00,0x00,0x00, 8, // 0x38 '8' 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, 8, // 0x39 '9' 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x3E,0x02,0x04,0x38,0x00,0x00,0x00, 6, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, 6, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, 9, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x3F '?' 0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, 13, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x10,0x40,0x27,0xA0,0x48,0x90,0x48,0x90,0x48,0x90,0x48,0x90,0x48,0x90,0x27,0xE0,0x10,0x00,0x0F,0x80,0x00,0x00, 9, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x14,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x42 'B' 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00,0x00, 9, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x45 'E' 0x00,0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x7E,0x00,0x00,0x00, 8, // 0x46 'F' 0x00,0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 9, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x21,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 6, // 0x4A 'J' 0x00,0x00,0x00,0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x00, 8, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00,0x00, 7, // 0x4C 'L' 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x00,0x00, 11, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x51,0x40,0x51,0x40,0x4A,0x40,0x4A,0x40,0x44,0x40,0x44,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x61,0x00,0x51,0x00,0x51,0x00,0x49,0x00,0x45,0x00,0x45,0x00,0x43,0x00,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x50 'P' 0x00,0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x00,0x00, 10, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x02,0x00,0x01,0x80,0x00,0x00, 9, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x40,0x00,0x40,0x00,0x3E,0x00,0x01,0x00,0x01,0x00,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x54 'T' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x45,0x10,0x45,0x10,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x5A 'Z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5B '[' 0x00,0x00,0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, 6, // 0x5C '\' 0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, 6, // 0x5D ']' 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, 11, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, 8, // 0x60 '`' 0x00,0x00,0x00,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,0x00,0x00, 8, // 0x62 'b' 0x00,0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x40,0x40,0x42,0x3C,0x00,0x00,0x00, 8, // 0x64 'd' 0x00,0x00,0x00,0x02,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00,0x00, 6, // 0x66 'f' 0x00,0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, 8, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x3C, 8, // 0x68 'h' 0x00,0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 4, // 0x6A 'j' 0x00,0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, 7, // 0x6B 'k' 0x00,0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 11, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x80,0x66,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, 8, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, 8, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40, 8, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x02, 5, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 7, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x40,0x40,0x38,0x04,0x04,0x78,0x00,0x00,0x00, 6, // 0x74 't' 0x00,0x00,0x00,0x00,0x20,0x20,0x78,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00,0x00, 8, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, 8, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00,0x00, 11, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, 8, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x10,0x10,0x20, 7, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, 8, // 0x7B '{' 0x00,0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x0C,0x00, 7, // 0x7C '|' 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, 8, // 0x7D '}' 0x00,0x00,0x00,0x30,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x00, 11, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x4C,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana16_bold[] = { 16, 4, 32, 128-32, 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x54,0x00,0x75,0x00,0xA6,0x00,0xC7,0x00,0xD8,0x00, 0xE9,0x00,0xFA,0x00,0x1B,0x01,0x3C,0x01,0x4D,0x01,0x5E,0x01,0x6F,0x01,0x90,0x01,0xB1,0x01, 0xD2,0x01,0xF3,0x01,0x14,0x02,0x35,0x02,0x56,0x02,0x77,0x02,0x98,0x02,0xB9,0x02,0xDA,0x02, 0xEB,0x02,0xFC,0x02,0x1D,0x03,0x3E,0x03,0x5F,0x03,0x70,0x03,0x91,0x03,0xB2,0x03,0xD3,0x03, 0xF4,0x03,0x15,0x04,0x36,0x04,0x57,0x04,0x78,0x04,0x99,0x04,0xAA,0x04,0xBB,0x04,0xDC,0x04, 0xED,0x04,0x0E,0x05,0x2F,0x05,0x50,0x05,0x71,0x05,0x92,0x05,0xB3,0x05,0xD4,0x05,0xE5,0x05, 0x06,0x06,0x27,0x06,0x48,0x06,0x69,0x06,0x8A,0x06,0xAB,0x06,0xBC,0x06,0xDD,0x06,0xEE,0x06, 0x0F,0x07,0x30,0x07,0x51,0x07,0x72,0x07,0x93,0x07,0xA4,0x07,0xC5,0x07,0xE6,0x07,0xF7,0x07, 0x18,0x08,0x39,0x08,0x4A,0x08,0x5B,0x08,0x6C,0x08,0x7D,0x08,0x9E,0x08,0xBF,0x08,0xE0,0x08, 0x01,0x09,0x22,0x09,0x33,0x09,0x44,0x09,0x55,0x09,0x76,0x09,0x97,0x09,0xB8,0x09,0xD9,0x09, 0xFA,0x09,0x0B,0x0A,0x2C,0x0A,0x3D,0x0A,0x5E,0x0A,0x7F,0x0A, 4, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x00,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x3F,0x80,0x12,0x00,0x7F,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x24 '$' 0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x69,0x00,0x68,0x00,0x78,0x00,0x3E,0x00,0x0F,0x00,0x0B,0x00,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, 17, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x20,0x00,0x66,0x20,0x00,0x66,0x40,0x00,0x66,0x5E,0x00,0x66,0xB3,0x00,0x3D,0x33,0x00,0x01,0x33,0x00,0x02,0x33,0x00,0x02,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x66,0x00,0x66,0x00,0x66,0xC0,0x3C,0xC0,0x66,0x80,0x63,0x00,0x63,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x27 ''' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C, 7, // 0x29 ')' 0x00,0x00,0x00,0x60,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x18,0x30,0x60, 9, // 0x2A '*' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0xC0,0xC0, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 9, // 0x2F '/' 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, 9, // 0x30 '0' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x31 '1' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x32 '2' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x33 '3' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x03,0x00,0x0E,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x34 '4' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0E,0x00,0x16,0x00,0x26,0x00,0x46,0x00,0x7F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x35 '5' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x36 '6' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x30,0x00,0x60,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x37 '7' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x38 '8' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x39 '9' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x03,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, 5, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x38,0x30,0x30,0x60,0x60, 11, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x40,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x3F '?' 0x00,0x00,0x00,0x00,0x3C,0x66,0x06,0x0C,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00, 13, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0x60,0x27,0xA0,0x4D,0x90,0x4D,0x90,0x4D,0x90,0x4D,0x90,0x27,0xE0,0x30,0x00,0x0F,0x80,0x00,0x00,0x00,0x00, 10, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x7F,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x42 'B' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x45 'E' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x46 'F' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x60,0x00,0x63,0x80,0x61,0x80,0x31,0x80,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x7F,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x49 'I' 0x00,0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, 7, // 0x4A 'J' 0x00,0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xF8,0x00,0x00,0x00, 9, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x78,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x4C 'L' 0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00,0x00, 12, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xE0,0x70,0xE0,0x59,0x60,0x59,0x60,0x4E,0x60,0x4E,0x60,0x44,0x60,0x44,0x60,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x80,0x70,0x80,0x58,0x80,0x58,0x80,0x4C,0x80,0x46,0x80,0x46,0x80,0x43,0x80,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x50 'P' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x03,0x00,0x01,0xC0,0x00,0x00, 9, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x70,0x00,0x3E,0x00,0x07,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x54 'T' 0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00, 10, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x5A 'Z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5B '[' 0x00,0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00, 9, // 0x5C '\' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x00,0x00, 6, // 0x5D ']' 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00, 10, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00, 9, // 0x60 '`' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x62 'b' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00, 9, // 0x64 'd' 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x60,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x66 'f' 0x00,0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 9, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x03,0x00,0x03,0x00,0x3E,0x00, 9, // 0x68 'h' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x69 'i' 0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 5, // 0x6A 'j' 0x00,0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, 8, // 0x6B 'k' 0x00,0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x63,0x00,0x00,0x00, 4, // 0x6C 'l' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 14, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x70,0x73,0x98,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, 9, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x03,0x00,0x03,0x00,0x03,0x00, 6, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 8, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x60,0x70,0x3C,0x0E,0x06,0x7C,0x00,0x00,0x00, 6, // 0x74 't' 0x00,0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x38,0x00,0x00,0x00, 9, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x69,0x60,0x39,0xC0,0x30,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, 8, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00,0x00, 9, // 0x7B '{' 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x00,0x00,0x00, 8, // 0x7C '|' 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00, 9, // 0x7D '}' 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x07,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x70,0x00,0x00,0x00, 11, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x40,0x44,0x40,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana17[] = { 17, 4, 32, 128-32, 0x00,0x00,0x12,0x00,0x24,0x00,0x36,0x00,0x59,0x00,0x7C,0x00,0x9F,0x00,0xC2,0x00,0xD4,0x00, 0xE6,0x00,0xF8,0x00,0x1B,0x01,0x3E,0x01,0x50,0x01,0x62,0x01,0x74,0x01,0x86,0x01,0xA9,0x01, 0xCC,0x01,0xEF,0x01,0x12,0x02,0x35,0x02,0x58,0x02,0x7B,0x02,0x9E,0x02,0xC1,0x02,0xE4,0x02, 0xF6,0x02,0x08,0x03,0x2B,0x03,0x4E,0x03,0x71,0x03,0x83,0x03,0xA6,0x03,0xC9,0x03,0xEC,0x03, 0x0F,0x04,0x32,0x04,0x55,0x04,0x67,0x04,0x8A,0x04,0xAD,0x04,0xBF,0x04,0xD1,0x04,0xF4,0x04, 0x06,0x05,0x29,0x05,0x4C,0x05,0x6F,0x05,0x81,0x05,0xA4,0x05,0xC7,0x05,0xEA,0x05,0x0D,0x06, 0x30,0x06,0x53,0x06,0x76,0x06,0x99,0x06,0xBC,0x06,0xDF,0x06,0xF1,0x06,0x03,0x07,0x15,0x07, 0x38,0x07,0x5B,0x07,0x7E,0x07,0x90,0x07,0xB3,0x07,0xC5,0x07,0xE8,0x07,0xFA,0x07,0x0C,0x08, 0x2F,0x08,0x52,0x08,0x64,0x08,0x76,0x08,0x88,0x08,0x9A,0x08,0xBD,0x08,0xE0,0x08,0x03,0x09, 0x26,0x09,0x49,0x09,0x5B,0x09,0x6D,0x09,0x7F,0x09,0xA2,0x09,0xB4,0x09,0xD7,0x09,0xFA,0x09, 0x0C,0x0A,0x1E,0x0A,0x41,0x0A,0x53,0x0A,0x76,0x0A,0x99,0x0A, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, 6, // 0x22 '"' 0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x04,0x80,0x09,0x00,0x3F,0xC0,0x09,0x00,0x12,0x00,0x7F,0x80,0x12,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x24 '$' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x49,0x00,0x48,0x00,0x48,0x00,0x3E,0x00,0x09,0x00,0x09,0x00,0x49,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, 15, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x44,0x40,0x44,0x80,0x44,0x80,0x45,0x38,0x39,0x44,0x02,0x44,0x04,0x44,0x04,0x44,0x08,0x38,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x38,0x80,0x44,0x80,0x42,0x80,0x41,0x00,0x22,0x80,0x1C,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x27 ''' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x28 '(' 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, 6, // 0x29 ')' 0x00,0x00,0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40, 9, // 0x2A '*' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, 6, // 0x2F '/' 0x00,0x00,0x00,0x04,0x08,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x40,0x40,0x80,0x80,0x00, 9, // 0x30 '0' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x31 '1' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x38,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x32 '2' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x0C,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x33 '3' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x01,0x00,0x02,0x00,0x1C,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x34 '4' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x00,0x0A,0x00,0x12,0x00,0x22,0x00,0x42,0x00,0x7F,0x80,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x35 '5' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7C,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x36 '6' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x30,0x00,0x20,0x00,0x40,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x37 '7' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x38 '8' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x39 '9' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x21,0x00,0x1F,0x00,0x01,0x00,0x02,0x00,0x06,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, 6, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, 11, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x06,0x00,0x18,0x00,0x60,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x3F '?' 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x0C,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, 14, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x18,0x20,0x20,0x10,0x27,0xC8,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, 10, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x7F,0x80,0x40,0x80,0x80,0x40,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x42 'B' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0x80,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x30,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x80,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x41,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x45 'E' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x46 'F' 0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 11, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x00,0x40,0x00,0x43,0xC0,0x40,0x40,0x20,0x40,0x30,0x40,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 6, // 0x4A 'J' 0x00,0x00,0x00,0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x00, 10, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x4C 'L' 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x00,0x00,0x00, 11, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x51,0x40,0x51,0x40,0x4A,0x40,0x4A,0x40,0x44,0x40,0x44,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x60,0x80,0x50,0x80,0x48,0x80,0x48,0x80,0x44,0x80,0x44,0x80,0x42,0x80,0x41,0x80,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x31,0x80,0x20,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x31,0x80,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x50 'P' 0x00,0x00,0x00,0x00,0x7C,0x42,0x41,0x41,0x42,0x7C,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 11, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x31,0x80,0x20,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x31,0x80,0x0E,0x00,0x02,0x00,0x02,0x00,0x01,0xC0, 10, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x40,0x00,0x40,0x00,0x38,0x00,0x07,0x00,0x00,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x54 'T' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x40,0x40,0x80,0x40,0x80,0x21,0x00,0x21,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x04,0x41,0x04,0x22,0x88,0x22,0x88,0x22,0x88,0x14,0x50,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x5A 'Z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x5B '[' 0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C, 6, // 0x5C '\' 0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x08,0x08,0x04,0x00, 6, // 0x5D ']' 0x00,0x00,0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78, 11, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00, 9, // 0x60 '`' 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x02,0x3E,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, 9, // 0x62 'b' 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x40,0x22,0x1C,0x00,0x00,0x00, 9, // 0x64 'd' 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x42,0x7E,0x40,0x40,0x22,0x1C,0x00,0x00,0x00, 6, // 0x66 'f' 0x00,0x00,0x00,0x1C,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, 9, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x22,0x00,0x1C,0x00, 9, // 0x68 'h' 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 5, // 0x6A 'j' 0x00,0x00,0x00,0x00,0x10,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0, 8, // 0x6B 'k' 0x00,0x00,0x00,0x40,0x40,0x40,0x42,0x44,0x48,0x50,0x70,0x48,0x44,0x42,0x00,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 13, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0xE0,0x63,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00, 9, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x01,0x00,0x01,0x00, 6, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 8, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00,0x00, 6, // 0x74 't' 0x00,0x00,0x00,0x00,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x1C,0x00,0x00,0x00, 9, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x18,0x00,0x00,0x00, 11, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x18,0x10,0x10,0x20, 8, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x00,0x00, 9, // 0x7B '{' 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x60,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0x00, 6, // 0x7C '|' 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, 9, // 0x7D '}' 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x03,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x70,0x00, 11, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x40,0x44,0x40,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana17_bold[] = { 17, 4, 32, 128-32, 0x00,0x00,0x12,0x00,0x24,0x00,0x36,0x00,0x59,0x00,0x7C,0x00,0xB0,0x00,0xD3,0x00,0xE5,0x00, 0xF7,0x00,0x09,0x01,0x2C,0x01,0x4F,0x01,0x61,0x01,0x73,0x01,0x85,0x01,0xA8,0x01,0xCB,0x01, 0xEE,0x01,0x11,0x02,0x34,0x02,0x57,0x02,0x7A,0x02,0x9D,0x02,0xC0,0x02,0xE3,0x02,0x06,0x03, 0x18,0x03,0x2A,0x03,0x4D,0x03,0x70,0x03,0x93,0x03,0xB6,0x03,0xD9,0x03,0xFC,0x03,0x1F,0x04, 0x42,0x04,0x65,0x04,0x88,0x04,0xAB,0x04,0xCE,0x04,0xF1,0x04,0x03,0x05,0x15,0x05,0x38,0x05, 0x5B,0x05,0x7E,0x05,0xA1,0x05,0xC4,0x05,0xE7,0x05,0x0A,0x06,0x2D,0x06,0x50,0x06,0x73,0x06, 0x96,0x06,0xB9,0x06,0xDC,0x06,0xFF,0x06,0x22,0x07,0x45,0x07,0x57,0x07,0x7A,0x07,0x8C,0x07, 0xAF,0x07,0xD2,0x07,0xF5,0x07,0x18,0x08,0x3B,0x08,0x4D,0x08,0x70,0x08,0x93,0x08,0xA5,0x08, 0xC8,0x08,0xEB,0x08,0xFD,0x08,0x0F,0x09,0x32,0x09,0x44,0x09,0x67,0x09,0x8A,0x09,0xAD,0x09, 0xD0,0x09,0xF3,0x09,0x05,0x0A,0x17,0x0A,0x29,0x0A,0x4C,0x0A,0x6F,0x0A,0x92,0x0A,0xB5,0x0A, 0xD8,0x0A,0xEA,0x0A,0x0D,0x0B,0x1F,0x0B,0x42,0x0B,0x65,0x0B, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, 8, // 0x22 '"' 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x40,0x04,0x40,0x3F,0xE0,0x3F,0xE0,0x08,0x80,0x11,0x00,0x7F,0xC0,0x7F,0xC0,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x24 '$' 0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x34,0x80,0x64,0x00,0x74,0x00,0x3C,0x00,0x0F,0x00,0x0B,0x80,0x09,0x80,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, 18, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x08,0x00,0x66,0x10,0x00,0x66,0x20,0x00,0x66,0x2F,0x00,0x66,0x59,0x80,0x66,0x99,0x80,0x3D,0x19,0x80,0x01,0x19,0x80,0x02,0x19,0x80,0x04,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x36,0x00,0x1C,0x60,0x36,0x60,0x63,0x60,0x61,0xC0,0x31,0xC0,0x1F,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x27 ''' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x28 '(' 0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C, 8, // 0x29 ')' 0x00,0x00,0x00,0x30,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x30, 10, // 0x2A '*' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0xC0,0xC0,0x00, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, 10, // 0x2F '/' 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, 10, // 0x30 '0' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x31 '1' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x32 '2' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x33 '3' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x0F,0x00,0x03,0x00,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x34 '4' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00,0x0B,0x00,0x13,0x00,0x23,0x00,0x43,0x00,0x7F,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x35 '5' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x36 '6' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x38,0x00,0x30,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x37 '7' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x38 '8' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x39 '9' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x03,0x00,0x07,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, 6, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x38,0x30,0x30,0x60,0x60,0x00, 12, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x40,0x01,0x80,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3F '?' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x18,0x20,0x20,0x10,0x27,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, 11, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x1B,0x00,0x31,0x80,0x3F,0x80,0x31,0x80,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x42 'B' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x61,0x80,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x61,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x45 'E' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x46 'F' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x63,0xC0,0x60,0xC0,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x7F,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x49 'I' 0x00,0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00, 8, // 0x4A 'J' 0x00,0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0xF8,0x00,0x00,0x00, 11, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7C,0x00,0x76,0x00,0x63,0x00,0x61,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x4C 'L' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x70,0x70,0x70,0x70,0xF0,0x58,0xB0,0x59,0xB0,0x4D,0x30,0x4F,0x30,0x46,0x30,0x46,0x30,0x40,0x30,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x40,0x70,0x40,0x58,0x40,0x4C,0x40,0x4C,0x40,0x46,0x40,0x43,0x40,0x43,0x40,0x41,0xC0,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x50 'P' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x03,0x00,0x03,0x00,0x01,0xE0, 11, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x63,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x3E,0x00,0x1F,0x00,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x54 'T' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x31,0x80,0x31,0x80,0x1B,0x00,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 16, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x86,0x61,0x86,0x63,0xC6,0x32,0x4C,0x36,0x6C,0x36,0x6C,0x34,0x2C,0x1C,0x38,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x31,0x80,0x31,0x80,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x5A 'Z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5B '[' 0x00,0x00,0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E, 10, // 0x5C '\' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00, 8, // 0x5D ']' 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C, 12, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00, 10, // 0x60 '`' 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x62 'b' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,0x60,0x60,0x60,0x60,0x33,0x1E,0x00,0x00,0x00, 10, // 0x64 'd' 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x63,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x66 'f' 0x00,0x00,0x00,0x1C,0x30,0x30,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, 10, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x03,0x00,0x3E,0x00, 10, // 0x68 'h' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x69 'i' 0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 6, // 0x6A 'j' 0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF0, 9, // 0x6B 'k' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x6C 'l' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 14, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x70,0x73,0x98,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, 10, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80, 7, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x7E,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 8, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x62,0x60,0x7C,0x3E,0x06,0x46,0x3C,0x00,0x00,0x00, 6, // 0x74 't' 0x00,0x00,0x00,0x00,0x60,0x60,0xFC,0x60,0x60,0x60,0x60,0x60,0x60,0x3C,0x00,0x00,0x00, 10, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x1C,0xE0,0x0C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, 8, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C,0x18,0x18,0x30,0x60,0x7E,0x00,0x00,0x00, 10, // 0x7B '{' 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80, 8, // 0x7C '|' 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 10, // 0x7D '}' 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x06,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00, 12, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x20,0x24,0x20,0x46,0x20,0x42,0x40,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana18[] = { 18, 4, 32, 128-32, 0x00,0x00,0x13,0x00,0x26,0x00,0x39,0x00,0x5E,0x00,0x83,0x00,0xA8,0x00,0xCD,0x00,0xE0,0x00, 0xF3,0x00,0x06,0x01,0x2B,0x01,0x50,0x01,0x63,0x01,0x76,0x01,0x89,0x01,0x9C,0x01,0xC1,0x01, 0xE6,0x01,0x0B,0x02,0x30,0x02,0x55,0x02,0x7A,0x02,0x9F,0x02,0xC4,0x02,0xE9,0x02,0x0E,0x03, 0x21,0x03,0x34,0x03,0x59,0x03,0x7E,0x03,0xA3,0x03,0xB6,0x03,0xDB,0x03,0x00,0x04,0x25,0x04, 0x4A,0x04,0x6F,0x04,0x94,0x04,0xB9,0x04,0xDE,0x04,0x03,0x05,0x16,0x05,0x29,0x05,0x4E,0x05, 0x61,0x05,0x86,0x05,0xAB,0x05,0xD0,0x05,0xF5,0x05,0x1A,0x06,0x3F,0x06,0x64,0x06,0x89,0x06, 0xAE,0x06,0xD3,0x06,0xF8,0x06,0x1D,0x07,0x42,0x07,0x67,0x07,0x7A,0x07,0x8D,0x07,0xA0,0x07, 0xC5,0x07,0xEA,0x07,0x0F,0x08,0x34,0x08,0x59,0x08,0x6C,0x08,0x91,0x08,0xB6,0x08,0xC9,0x08, 0xEE,0x08,0x13,0x09,0x26,0x09,0x39,0x09,0x5E,0x09,0x71,0x09,0x96,0x09,0xBB,0x09,0xE0,0x09, 0x05,0x0A,0x2A,0x0A,0x3D,0x0A,0x50,0x0A,0x63,0x0A,0x88,0x0A,0xAD,0x0A,0xD2,0x0A,0xF7,0x0A, 0x1C,0x0B,0x41,0x0B,0x66,0x0B,0x79,0x0B,0x9E,0x0B,0xC3,0x0B, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, 7, // 0x22 '"' 0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x04,0x80,0x09,0x00,0x3F,0xC0,0x09,0x00,0x11,0x00,0x12,0x00,0x7F,0x80,0x12,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x24 '$' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x49,0x00,0x48,0x00,0x48,0x00,0x38,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x49,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x08,0x00, 16, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x44,0x40,0x44,0x40,0x44,0x80,0x44,0x80,0x38,0x9C,0x01,0x22,0x01,0x22,0x02,0x22,0x02,0x22,0x04,0x1C,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x1E,0x40,0x24,0x40,0x42,0x40,0x41,0x40,0x40,0x80,0x21,0x40,0x1E,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x27 ''' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x28 '(' 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, 7, // 0x29 ')' 0x00,0x00,0x00,0x20,0x10,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x08,0x10,0x20, 10, // 0x2A '*' 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xE0,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x40, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, 7, // 0x2F '/' 0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00, 10, // 0x30 '0' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x31 '1' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1C,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x32 '2' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x33 '3' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x40,0x80,0x00,0x80,0x01,0x00,0x0E,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x34 '4' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x05,0x00,0x09,0x00,0x11,0x00,0x21,0x00,0x41,0x00,0x7F,0xC0,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x35 '5' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x20,0x00,0x20,0x00,0x20,0x00,0x3E,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x36 '6' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x37 '7' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x38 '8' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x39 '9' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x20,0x80,0x1F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, 7, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x20,0x20, 12, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x3F '?' 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, 15, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x18,0x60,0x20,0x10,0x23,0xD0,0x44,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x44,0x48,0x23,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, 10, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x40,0x80,0x7F,0x80,0x40,0x80,0x80,0x40,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x42 'B' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x40,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x80,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x41,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x45 'E' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x46 'F' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0x60,0x20,0x20,0x40,0x00,0x40,0x00,0x41,0xE0,0x40,0x20,0x40,0x20,0x20,0x20,0x30,0x20,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x49 'I' 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, 7, // 0x4A 'J' 0x00,0x00,0x00,0x00,0x3C,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0xF0,0x00,0x00,0x00, 10, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x41,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x4C 'L' 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x00,0x00,0x00, 13, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x50,0x50,0x50,0x50,0x48,0x90,0x48,0x90,0x45,0x10,0x45,0x10,0x42,0x10,0x42,0x10,0x40,0x10,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x60,0x40,0x50,0x40,0x48,0x40,0x48,0x40,0x44,0x40,0x42,0x40,0x42,0x40,0x41,0x40,0x40,0xC0,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x20,0x40,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x50 'P' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x20,0x40,0x30,0xC0,0x0F,0x00,0x01,0x00,0x01,0x00,0x00,0xE0, 10, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x40,0x00,0x40,0x00,0x20,0x00,0x1E,0x00,0x01,0x00,0x00,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x54 'T' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x40,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x04,0x41,0x04,0x22,0x88,0x22,0x88,0x22,0x88,0x12,0x90,0x14,0x50,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x21,0x00,0x21,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x5A 'Z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x5B '[' 0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C, 7, // 0x5C '\' 0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x04,0x02,0x00, 7, // 0x5D ']' 0x00,0x00,0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78, 12, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x10,0x80,0x20,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00, 10, // 0x60 '`' 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x01,0x00,0x3F,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x62 'b' 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x21,0x40,0x40,0x40,0x40,0x21,0x1E,0x00,0x00,0x00, 9, // 0x64 'd' 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x66 'f' 0x00,0x00,0x00,0x1C,0x20,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, 9, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x22,0x00,0x1C,0x00, 9, // 0x68 'h' 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 3, // 0x69 'i' 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 5, // 0x6A 'j' 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0, 9, // 0x6B 'k' 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 3, // 0x6C 'l' 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 15, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x70,0x31,0x88,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00, 9, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x01,0x00,0x01,0x00, 6, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 8, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00,0x00, 6, // 0x74 't' 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x1C,0x00,0x00,0x00, 9, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x25,0x20,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00, 9, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x7B '{' 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x60,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0x00, 7, // 0x7C '|' 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, 10, // 0x7D '}' 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x38,0x00, 12, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x20,0x24,0x20,0x42,0x40,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; const int8u verdana18_bold[] = { 18, 4, 32, 128-32, 0x00,0x00,0x13,0x00,0x26,0x00,0x4B,0x00,0x70,0x00,0x95,0x00,0xCC,0x00,0xF1,0x00,0x04,0x01, 0x17,0x01,0x2A,0x01,0x4F,0x01,0x74,0x01,0x87,0x01,0x9A,0x01,0xAD,0x01,0xD2,0x01,0xF7,0x01, 0x1C,0x02,0x41,0x02,0x66,0x02,0x8B,0x02,0xB0,0x02,0xD5,0x02,0xFA,0x02,0x1F,0x03,0x44,0x03, 0x57,0x03,0x6A,0x03,0x8F,0x03,0xB4,0x03,0xD9,0x03,0xFE,0x03,0x23,0x04,0x48,0x04,0x6D,0x04, 0x92,0x04,0xB7,0x04,0xDC,0x04,0x01,0x05,0x26,0x05,0x4B,0x05,0x5E,0x05,0x71,0x05,0x96,0x05, 0xBB,0x05,0xE0,0x05,0x05,0x06,0x2A,0x06,0x4F,0x06,0x74,0x06,0x99,0x06,0xBE,0x06,0xE3,0x06, 0x08,0x07,0x2D,0x07,0x52,0x07,0x77,0x07,0x9C,0x07,0xC1,0x07,0xD4,0x07,0xF9,0x07,0x0C,0x08, 0x31,0x08,0x56,0x08,0x7B,0x08,0xA0,0x08,0xC5,0x08,0xD8,0x08,0xFD,0x08,0x22,0x09,0x35,0x09, 0x5A,0x09,0x7F,0x09,0x92,0x09,0xA5,0x09,0xCA,0x09,0xDD,0x09,0x02,0x0A,0x27,0x0A,0x4C,0x0A, 0x71,0x0A,0x96,0x0A,0xA9,0x0A,0xCE,0x0A,0xE1,0x0A,0x06,0x0B,0x2B,0x0B,0x50,0x0B,0x75,0x0B, 0x9A,0x0B,0xBF,0x0B,0xE4,0x0B,0xF7,0x0B,0x1C,0x0C,0x41,0x0C, 5, // 0x20 ' ' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x21 '!' 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, 9, // 0x22 '"' 0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x23 '#' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x20,0x04,0x20,0x08,0x40,0x3F,0xF0,0x3F,0xF0,0x08,0x40,0x10,0x80,0x7F,0xE0,0x7F,0xE0,0x21,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x24 '$' 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x80,0x34,0xC0,0x64,0xC0,0x64,0x00,0x3C,0x00,0x07,0x80,0x04,0xC0,0x64,0xC0,0x65,0x80,0x3F,0x00,0x04,0x00,0x04,0x00,0x00,0x00, 19, // 0x25 '%' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x08,0x00,0x63,0x10,0x00,0x63,0x10,0x00,0x63,0x20,0x00,0x63,0x2F,0x80,0x63,0x58,0xC0,0x3E,0x98,0xC0,0x00,0x98,0xC0,0x01,0x18,0xC0,0x01,0x18,0xC0,0x02,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x26 '&' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x60,0x36,0x60,0x63,0x60,0x61,0xC0,0x60,0xC0,0x30,0xE0,0x1F,0x30,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x27 ''' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x28 '(' 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C,0x06, 8, // 0x29 ')' 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x30,0x60, 11, // 0x2A '*' 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x24,0x80,0x15,0x00,0x0E,0x00,0x15,0x00,0x24,0x80,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x2B '+' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xE0,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2C ',' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0x60,0xC0,0xC0, 7, // 0x2D '-' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5, // 0x2E '.' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, 10, // 0x2F '/' 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, 11, // 0x30 '0' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x31 '1' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x1E,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x32 '2' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0xC0,0x00,0xC0,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x33 '3' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0xC0,0x00,0xC0,0x01,0x80,0x0F,0x00,0x01,0x80,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x34 '4' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x80,0x05,0x80,0x09,0x80,0x11,0x80,0x21,0x80,0x41,0x80,0x7F,0xE0,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x35 '5' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x01,0x80,0x00,0xC0,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x36 '6' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x18,0x00,0x30,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x37 '7' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0xC0,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x38 '8' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x39 '9' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0xC0,0x1E,0xC0,0x00,0xC0,0x01,0x80,0x03,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x3A ':' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, 6, // 0x3B ';' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x38,0x30,0x30,0x30,0x60,0x60, 13, // 0x3C '<' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x3D '=' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x3E '>' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9, // 0x3F '?' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x40 '@' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x18,0x60,0x20,0x10,0x27,0xD0,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, 12, // 0x41 'A' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0F,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x30,0xC0,0x3F,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x42 'B' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x43 'C' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x30,0xC0,0x38,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x44 'D' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0xC0,0x60,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x61,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x45 'E' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x46 'F' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x47 'G' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x38,0x60,0x30,0x60,0x60,0x00,0x60,0x00,0x63,0xE0,0x60,0x60,0x60,0x60,0x30,0x60,0x38,0x60,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x48 'H' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0xE0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x49 'I' 0x00,0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00, 8, // 0x4A 'J' 0x00,0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0xF8,0x00,0x00,0x00, 12, // 0x4B 'K' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0xC0,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7E,0x00,0x73,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x4C 'L' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x4D 'M' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x38,0x70,0x38,0x70,0x78,0x58,0x58,0x58,0xD8,0x4C,0x98,0x4D,0x98,0x47,0x18,0x47,0x18,0x42,0x18,0x40,0x18,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x4E 'N' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x20,0x70,0x20,0x58,0x20,0x4C,0x20,0x4C,0x20,0x46,0x20,0x43,0x20,0x43,0x20,0x41,0xA0,0x40,0xE0,0x40,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x4F 'O' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xE0,0x30,0x60,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x30,0x60,0x38,0xE0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x50 'P' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13, // 0x51 'Q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xE0,0x30,0x60,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x30,0x60,0x38,0xE0,0x0F,0x80,0x03,0x00,0x03,0x80,0x01,0xF0, 12, // 0x52 'R' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x53 'S' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x30,0xC0,0x60,0xC0,0x60,0x00,0x7C,0x00,0x3F,0x80,0x03,0xC0,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x54 'T' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12, // 0x55 'U' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x56 'V' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x31,0x80,0x31,0x80,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 16, // 0x57 'W' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x86,0x61,0x86,0x63,0xC6,0x33,0xCC,0x32,0x4C,0x32,0x4C,0x1E,0x78,0x1C,0x38,0x1C,0x38,0x0C,0x30,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x58 'X' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x31,0x80,0x31,0x80,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x59 'Y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x5A 'Z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x5B '[' 0x00,0x00,0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E, 10, // 0x5C '\' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00, 8, // 0x5D ']' 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C, 13, // 0x5E '^' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0F,0x00,0x19,0x80,0x30,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x5F '_' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xE0,0x00,0x00, 11, // 0x60 '`' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x61 'a' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x01,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x62 'b' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8, // 0x63 'c' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,0x60,0x60,0x60,0x60,0x33,0x1E,0x00,0x00,0x00, 10, // 0x64 'd' 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x65 'e' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6, // 0x66 'f' 0x00,0x00,0x00,0x1C,0x30,0x30,0x30,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, 10, // 0x67 'g' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x03,0x00,0x3E,0x00, 10, // 0x68 'h' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x69 'i' 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 6, // 0x6A 'j' 0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF0, 10, // 0x6B 'k' 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7E,0x00,0x73,0x00,0x61,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, 4, // 0x6C 'l' 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 16, // 0x6D 'm' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x3C,0x71,0xC6,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x6E 'n' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x6F 'o' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x70 'p' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, 10, // 0x71 'q' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80, 7, // 0x72 'r' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x7E,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, 9, // 0x73 's' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x7E,0x00,0x3F,0x00,0x03,0x00,0x43,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7, // 0x74 't' 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x7E,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x00,0x00,0x00, 10, // 0x75 'u' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x76 'v' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14, // 0x77 'w' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x37,0xB0,0x34,0xB0,0x3C,0xF0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x78 'x' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 10, // 0x79 'y' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, 9, // 0x7A 'z' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11, // 0x7B '{' 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80, 8, // 0x7C '|' 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 11, // 0x7D '}' 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x01,0xC0,0x03,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3C,0x00, 13, // 0x7E '~' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x10,0x24,0x10,0x42,0x10,0x41,0x20,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15, // 0x7F '' 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, 0 }; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/��������������������������������������������������������������0000755�0024617�0000144�00000000000�12261257216�017467� 5����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_svg_exception.h�������������������������������������������0000644�0024617�0000144�00000003335�12261257215�023336� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG exception // //---------------------------------------------------------------------------- #ifndef AGG_SVG_EXCEPTION_INCLUDED #define AGG_SVG_EXCEPTION_INCLUDED #include <stdio.h> #include <string.h> #include <stdarg.h> namespace mapserver { namespace svg { class exception { public: ~exception() { delete [] m_msg; } exception() : m_msg(0) {} exception(const char* fmt, ...) : m_msg(0) { if(fmt) { m_msg = new char [4096]; va_list arg; va_start(arg, fmt); vsprintf(m_msg, fmt, arg); va_end(arg); } } exception(const exception& exc) : m_msg(exc.m_msg ? new char[strlen(exc.m_msg) + 1] : 0) { if(m_msg) strcpy(m_msg, exc.m_msg); } const char* msg() const { return m_msg; } private: char* m_msg; }; } } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vertex_sequence.h�����������������������������������������0000644�0024617�0000144�00000012106�12261257215�023662� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // vertex_sequence container and vertex_dist struct // //---------------------------------------------------------------------------- #ifndef AGG_VERTEX_SEQUENCE_INCLUDED #define AGG_VERTEX_SEQUENCE_INCLUDED #include "agg_basics.h" #include "agg_array.h" #include "agg_math.h" namespace mapserver { //----------------------------------------------------------vertex_sequence // Modified mapserver::pod_bvector. The data is interpreted as a sequence // of vertices. It means that the type T must expose: // // bool T::operator() (const T& val) // // that is called every time new vertex is being added. The main purpose // of this operator is the possibility to calculate some values during // adding and to return true if the vertex fits some criteria or false if // it doesn't. In the last case the new vertex is not added. // // The simple example is filtering coinciding vertices with calculation // of the distance between the current and previous ones: // // struct vertex_dist // { // double x; // double y; // double dist; // // vertex_dist() {} // vertex_dist(double x_, double y_) : // x(x_), // y(y_), // dist(0.0) // { // } // // bool operator () (const vertex_dist& val) // { // return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON; // } // }; // // Function close() calls this operator and removes the last vertex if // necessary. //------------------------------------------------------------------------ template<class T, unsigned S=6> class vertex_sequence : public pod_bvector<T, S> { public: typedef pod_bvector<T, S> base_type; void add(const T& val); void modify_last(const T& val); void close(bool remove_flag); }; //------------------------------------------------------------------------ template<class T, unsigned S> void vertex_sequence<T, S>::add(const T& val) { if(base_type::size() > 1) { if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) { base_type::remove_last(); } } base_type::add(val); } //------------------------------------------------------------------------ template<class T, unsigned S> void vertex_sequence<T, S>::modify_last(const T& val) { base_type::remove_last(); add(val); } //------------------------------------------------------------------------ template<class T, unsigned S> void vertex_sequence<T, S>::close(bool closed) { while(base_type::size() > 1) { if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break; T t = (*this)[base_type::size() - 1]; base_type::remove_last(); modify_last(t); } if(closed) { while(base_type::size() > 1) { if((*this)[base_type::size() - 1]((*this)[0])) break; base_type::remove_last(); } } } //-------------------------------------------------------------vertex_dist // Vertex (x, y) with the distance to the next one. The last vertex has // distance between the last and the first points if the polygon is closed // and 0.0 if it's a polyline. struct vertex_dist { double x; double y; double dist; vertex_dist() {} vertex_dist(double x_, double y_) : x(x_), y(y_), dist(0.0) { } bool operator () (const vertex_dist& val) { bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon; if(!ret) dist = 1.0 / vertex_dist_epsilon; return ret; } }; //--------------------------------------------------------vertex_dist_cmd // Save as the above but with additional "command" value struct vertex_dist_cmd : public vertex_dist { unsigned cmd; vertex_dist_cmd() {} vertex_dist_cmd(double x_, double y_, unsigned cmd_) : vertex_dist(x_, y_), cmd(cmd_) { } }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pixfmt_rgb.h����������������������������������������������0000644�0024617�0000144�00000075067�12261257215�022635� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_RGB_INCLUDED #define AGG_PIXFMT_RGB_INCLUDED #include <string.h> #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_rendering_buffer.h" namespace mapserver { //=====================================================apply_gamma_dir_rgb template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb { public: typedef typename ColorT::value_type value_type; apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { p[Order::R] = m_gamma.dir(p[Order::R]); p[Order::G] = m_gamma.dir(p[Order::G]); p[Order::B] = m_gamma.dir(p[Order::B]); } private: const GammaLut& m_gamma; }; //=====================================================apply_gamma_inv_rgb template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb { public: typedef typename ColorT::value_type value_type; apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { p[Order::R] = m_gamma.inv(p[Order::R]); p[Order::G] = m_gamma.inv(p[Order::G]); p[Order::B] = m_gamma.inv(p[Order::B]); } private: const GammaLut& m_gamma; }; //=========================================================blender_rgb template<class ColorT, class Order> struct blender_rgb { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover=0) { p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift); p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift); p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift); } }; //======================================================blender_rgb_pre template<class ColorT, class Order> struct blender_rgb_pre { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (base_shift - 8); p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); } //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha) { alpha = color_type::base_mask - alpha; p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); } }; //===================================================blender_rgb_gamma template<class ColorT, class Order, class Gamma> class blender_rgb_gamma { public: typedef ColorT color_type; typedef Order order_type; typedef Gamma gamma_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- blender_rgb_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } //-------------------------------------------------------------------- AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover=0) { calc_type r = m_gamma->dir(p[Order::R]); calc_type g = m_gamma->dir(p[Order::G]); calc_type b = m_gamma->dir(p[Order::B]); p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r); p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g); p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b); } private: const gamma_type* m_gamma; }; //==================================================pixfmt_alpha_blend_rgb template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb { public: typedef RenBuf rbuf_type; typedef Blender blender_type; typedef typename rbuf_type::row_data row_data; typedef typename blender_type::color_type color_type; typedef typename blender_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask, pix_width = sizeof(value_type) * 3 }; private: //-------------------------------------------------------------------- AGG_INLINE void copy_or_blend_pix(value_type* p, const color_type& c, unsigned cover) { if (c.a) { calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } else { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); } } } //-------------------------------------------------------------------- AGG_INLINE void copy_or_blend_pix(value_type* p, const color_type& c) { if (c.a) { if(c.a == base_mask) { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } else { m_blender.blend_pix(p, c.r, c.g, c.b, c.a); } } } public: //-------------------------------------------------------------------- explicit pixfmt_alpha_blend_rgb(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) { rect_i r(x1, y1, x2, y2); if(r.clip(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; } //-------------------------------------------------------------------- Blender& blender() { return m_blender; } //-------------------------------------------------------------------- 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_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } //-------------------------------------------------------------------- AGG_INLINE int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * pix_width; } AGG_INLINE const int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * pix_width; } //-------------------------------------------------------------------- AGG_INLINE static void make_pix(int8u* p, const color_type& c) { ((value_type*)p)[order_type::R] = c.r; ((value_type*)p)[order_type::G] = c.g; ((value_type*)p)[order_type::B] = c.b; } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x; return color_type(p[order_type::R], p[order_type::G], p[order_type::B]); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x; p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover); } //-------------------------------------------------------------------- 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 + x + x; do { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; p += 3; } 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 + x + x; p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } while(--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x + x + x; calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8; if(alpha == base_mask) { do { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; p += 3; } while(--len); } else { do { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); p += 3; } while(--len); } } } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { value_type* p; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } while(--len); } else { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); } while(--len); } } } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { if (c.a) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x + x + x; do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } else { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers); } p += 3; ++covers; } while(--len); } } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { if (c.a) { do { value_type* p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; } else { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers); } ++covers; } while(--len); } } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x + x + x; do { p[order_type::R] = colors->r; p[order_type::G] = colors->g; p[order_type::B] = colors->b; ++colors; p += 3; } while(--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { do { value_type* p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; p[order_type::R] = colors->r; p[order_type::G] = colors->g; p[order_type::B] = colors->b; ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x + x + x; if(covers) { do { copy_or_blend_pix(p, *colors++, *covers++); p += 3; } while(--len); } else { if(cover == 255) { do { copy_or_blend_pix(p, *colors++); p += 3; } while(--len); } else { do { copy_or_blend_pix(p, *colors++, cover); p += 3; } while(--len); } } } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p; if(covers) { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; copy_or_blend_pix(p, *colors++, *covers++); } while(--len); } else { if(cover == 255) { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; copy_or_blend_pix(p, *colors++); } while(--len); } else { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x + x + x; copy_or_blend_pix(p, *colors++, cover); } while(--len); } } } //-------------------------------------------------------------------- template<class Function> void for_each_pixel(Function f) { unsigned y; for(y = 0; y < height(); ++y) { row_data r = m_rbuf->row(y); if(r.ptr) { unsigned len = r.x2 - r.x1 + 1; value_type* p = (value_type*) m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3; do { f(p); p += 3; } while(--len); } } } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_dir(const GammaLut& g) { for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_inv(const GammaLut& g) { for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class RenBuf2> void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { const int8u* p = from.row_ptr(ysrc); if(p) { memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; const value_type* psrc = (const value_type*)from.row_ptr(ysrc); if(psrc) { psrc += xsrc * 4; value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; if(cover == 255) { do { value_type alpha = psrc[src_order::A]; if(alpha) { if(alpha == base_mask) { pdst[order_type::R] = psrc[src_order::R]; pdst[order_type::G] = psrc[src_order::G]; pdst[order_type::B] = psrc[src_order::B]; } else { m_blender.blend_pix(pdst, psrc[src_order::R], psrc[src_order::G], psrc[src_order::B], alpha); } } psrc += 4; pdst += 3; } while(--len); } else { color_type color; do { color.r = psrc[src_order::R]; color.g = psrc[src_order::G]; color.b = psrc[src_order::B]; color.a = psrc[src_order::A]; copy_or_blend_pix(pdst, color, cover); psrc += 4; pdst += 3; } while(--len); } } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; do { copy_or_blend_pix(pdst, color, (*psrc * cover + base_mask) >> base_shift); ++psrc; pdst += 3; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; if(cover == 255) { do { const color_type& color = color_lut[*psrc]; m_blender.blend_pix(pdst, color.r, color.g, color.b, color.a); ++psrc; pdst += 3; } while(--len); } else { do { copy_or_blend_pix(pdst, color_lut[*psrc], cover); ++psrc; pdst += 3; } while(--len); } } } private: rbuf_type* m_rbuf; Blender m_blender; }; typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24 typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24 typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48 typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48 typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre //-----------------------------------------------------pixfmt_rgb24_gamma template<class Gamma> class pixfmt_rgb24_gamma : public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer> { public: pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_bgr24_gamma template<class Gamma> class pixfmt_bgr24_gamma : public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer> { public: pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgb48_gamma template<class Gamma> class pixfmt_rgb48_gamma : public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer> { public: pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_bgr48_gamma template<class Gamma> class pixfmt_bgr48_gamma : public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer> { public: pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_svg_parser.h����������������������������������������������0000644�0024617�0000144�00000005367�12261257215�022643� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG parser. // //---------------------------------------------------------------------------- #ifndef AGG_SVG_PARSER_INCLUDED #define AGG_SVG_PARSER_INCLUDED #include "agg_svg_path_tokenizer.h" #include "agg_svg_path_renderer.h" namespace mapserver { namespace svg { class parser { enum buf_size_e { buf_size = BUFSIZ }; public: ~parser(); parser(path_renderer& path); void parse(const char* fname); const char* title() const { return m_title; } private: // XML event handlers static void start_element(void* data, const char* el, const char** attr); static void end_element(void* data, const char* el); static void content(void* data, const char* s, int len); void parse_attr(const char** attr); void parse_path(const char** attr); void parse_poly(const char** attr, bool close_flag); void parse_rect(const char** attr); void parse_line(const char** attr); void parse_style(const char* str); void parse_transform(const char* str); unsigned parse_matrix(const char* str); unsigned parse_translate(const char* str); unsigned parse_rotate(const char* str); unsigned parse_scale(const char* str); unsigned parse_skew_x(const char* str); unsigned parse_skew_y(const char* str); bool parse_attr(const char* name, const char* value); bool parse_name_value(const char* nv_start, const char* nv_end); void copy_name(const char* start, const char* end); void copy_value(const char* start, const char* end); private: path_renderer& m_path; path_tokenizer m_tokenizer; char* m_buf; char* m_title; unsigned m_title_len; bool m_title_flag; bool m_path_flag; char* m_attr_name; char* m_attr_value; unsigned m_attr_name_len; unsigned m_attr_value_len; }; } } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pixfmt_rgb_packed.h���������������������������������������0000644�0024617�0000144�00000140204�12261257215�024126� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_RGB_PACKED_INCLUDED #define AGG_PIXFMT_RGB_PACKED_INCLUDED #include <string.h> #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_rendering_buffer.h" namespace mapserver { //=========================================================blender_rgb555 struct blender_rgb555 { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 7) & 0xF8; calc_type g = (rgb >> 2) & 0xF8; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3) | 0x8000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 7) & 0xF8, (p >> 2) & 0xF8, (p << 3) & 0xF8); } }; //=====================================================blender_rgb555_pre struct blender_rgb555_pre { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; pixel_type rgb = *p; calc_type r = (rgb >> 7) & 0xF8; calc_type g = (rgb >> 2) & 0xF8; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) ((((r * alpha + cr * cover) >> 1) & 0x7C00) | (((g * alpha + cg * cover) >> 6) & 0x03E0) | ((b * alpha + cb * cover) >> 11) | 0x8000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3) | 0x8000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 7) & 0xF8, (p >> 2) & 0xF8, (p << 3) & 0xF8); } }; //=====================================================blender_rgb555_gamma template<class Gamma> class blender_rgb555_gamma { public: typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; typedef Gamma gamma_type; blender_rgb555_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); calc_type b = m_gamma->dir((rgb << 3) & 0xF8); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3) | 0x8000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 7) & 0xF8, (p >> 2) & 0xF8, (p << 3) & 0xF8); } private: const Gamma* m_gamma; }; //=========================================================blender_rgb565 struct blender_rgb565 { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 8) & 0xF8; calc_type g = (rgb >> 3) & 0xFC; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | (((cb - b) * alpha + (b << 8)) >> 11)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 8) & 0xF8, (p >> 3) & 0xFC, (p << 3) & 0xF8); } }; //=====================================================blender_rgb565_pre struct blender_rgb565_pre { typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; pixel_type rgb = *p; calc_type r = (rgb >> 8) & 0xF8; calc_type g = (rgb >> 3) & 0xFC; calc_type b = (rgb << 3) & 0xF8; *p = (pixel_type) ((((r * alpha + cr * cover) ) & 0xF800) | (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | ((b * alpha + cb * cover) >> 11)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 8) & 0xF8, (p >> 3) & 0xFC, (p << 3) & 0xF8); } }; //=====================================================blender_rgb565_gamma template<class Gamma> class blender_rgb565_gamma { public: typedef rgba8 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int16u pixel_type; typedef Gamma gamma_type; blender_rgb565_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); calc_type b = m_gamma->dir((rgb << 3) & 0xF8); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 8) & 0xF8, (p >> 3) & 0xFC, (p << 3) & 0xF8); } private: const Gamma* m_gamma; }; //=====================================================blender_rgbAAA struct blender_rgbAAA { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 14) & 0xFFC0; calc_type g = (rgb >> 4) & 0xFFC0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (b >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 14) & 0xFFC0, (p >> 4) & 0xFFC0, (p << 6) & 0xFFC0); } }; //==================================================blender_rgbAAA_pre struct blender_rgbAAA_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type rgb = *p; calc_type r = (rgb >> 14) & 0xFFC0; calc_type g = (rgb >> 4) & 0xFFC0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | ((b * alpha + cb * cover) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (b >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 14) & 0xFFC0, (p >> 4) & 0xFFC0, (p << 6) & 0xFFC0); } }; //=================================================blender_rgbAAA_gamma template<class Gamma> class blender_rgbAAA_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_rgbAAA_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (b >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 14) & 0xFFC0, (p >> 4) & 0xFFC0, (p << 6) & 0xFFC0); } private: const Gamma* m_gamma; }; //=====================================================blender_bgrAAA struct blender_bgrAAA { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = (bgr >> 14) & 0xFFC0; calc_type g = (bgr >> 4) & 0xFFC0; calc_type r = (bgr << 6) & 0xFFC0; *p = (pixel_type) (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (r >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 6) & 0xFFC0, (p >> 4) & 0xFFC0, (p >> 14) & 0xFFC0); } }; //=================================================blender_bgrAAA_pre struct blender_bgrAAA_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type bgr = *p; calc_type b = (bgr >> 14) & 0xFFC0; calc_type g = (bgr >> 4) & 0xFFC0; calc_type r = (bgr << 6) & 0xFFC0; *p = (pixel_type) ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | ((r * alpha + cr * cover) >> 22) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (r >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 6) & 0xFFC0, (p >> 4) & 0xFFC0, (p >> 14) & 0xFFC0); } }; //=================================================blender_bgrAAA_gamma template<class Gamma> class blender_bgrAAA_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_bgrAAA_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 14) | ((g & 0xFFC0) << 4) | (r >> 6) | 0xC0000000); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 6) & 0xFFC0, (p >> 4) & 0xFFC0, (p >> 14) & 0xFFC0); } private: const Gamma* m_gamma; }; //=====================================================blender_rgbBBA struct blender_rgbBBA { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = (rgb >> 16) & 0xFFE0; calc_type g = (rgb >> 5) & 0xFFE0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | (((cb - b) * alpha + (b << 16)) >> 22)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 16) & 0xFFE0, (p >> 5) & 0xFFE0, (p << 6) & 0xFFC0); } }; //=================================================blender_rgbBBA_pre struct blender_rgbBBA_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type rgb = *p; calc_type r = (rgb >> 16) & 0xFFE0; calc_type g = (rgb >> 5) & 0xFFE0; calc_type b = (rgb << 6) & 0xFFC0; *p = (pixel_type) ((((r * alpha + cr * cover) ) & 0xFFE00000) | (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | ((b * alpha + cb * cover) >> 22)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 16) & 0xFFE0, (p >> 5) & 0xFFE0, (p << 6) & 0xFFC0); } }; //=================================================blender_rgbBBA_gamma template<class Gamma> class blender_rgbBBA_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_rgbBBA_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type rgb = *p; calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p >> 16) & 0xFFE0, (p >> 5) & 0xFFE0, (p << 6) & 0xFFC0); } private: const Gamma* m_gamma; }; //=====================================================blender_bgrABB struct blender_bgrABB { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = (bgr >> 16) & 0xFFC0; calc_type g = (bgr >> 6) & 0xFFE0; calc_type r = (bgr << 5) & 0xFFE0; *p = (pixel_type) (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | (((cr - r) * alpha + (r << 16)) >> 21)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 5) & 0xFFE0, (p >> 6) & 0xFFE0, (p >> 16) & 0xFFC0); } }; //=================================================blender_bgrABB_pre struct blender_bgrABB_pre { typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; static AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (color_type::base_shift - 8); pixel_type bgr = *p; calc_type b = (bgr >> 16) & 0xFFC0; calc_type g = (bgr >> 6) & 0xFFE0; calc_type r = (bgr << 5) & 0xFFE0; *p = (pixel_type) ((((b * alpha + cb * cover) ) & 0xFFC00000) | (((g * alpha + cg * cover) >> 10) & 0x003FF800) | ((r * alpha + cr * cover) >> 21)); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 5) & 0xFFE0, (p >> 6) & 0xFFE0, (p >> 16) & 0xFFC0); } }; //=================================================blender_bgrABB_gamma template<class Gamma> class blender_bgrABB_gamma { public: typedef rgba16 color_type; typedef color_type::value_type value_type; typedef color_type::calc_type calc_type; typedef int32u pixel_type; typedef Gamma gamma_type; blender_bgrABB_gamma() : m_gamma(0) {} void gamma(const gamma_type& g) { m_gamma = &g; } AGG_INLINE void blend_pix(pixel_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned) { pixel_type bgr = *p; calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); *p = (pixel_type) (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); } static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) { return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); } static AGG_INLINE color_type make_color(pixel_type p) { return color_type((p << 5) & 0xFFE0, (p >> 6) & 0xFFE0, (p >> 16) & 0xFFC0); } private: const Gamma* m_gamma; }; //===========================================pixfmt_alpha_blend_rgb_packed template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed { public: typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef Blender blender_type; typedef typename blender_type::color_type color_type; typedef typename blender_type::pixel_type pixel_type; typedef int order_type; // A fake one typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask, pix_width = sizeof(pixel_type) }; private: //-------------------------------------------------------------------- AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) { if (c.a) { calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { *p = m_blender.make_pix(c.r, c.g, c.b); } else { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); } } } public: //-------------------------------------------------------------------- explicit pixfmt_alpha_blend_rgb_packed(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) { rect_i r(x1, y1, x2, y2); if(r.clip(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; } Blender& blender() { return m_blender; } //-------------------------------------------------------------------- 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_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } //-------------------------------------------------------------------- AGG_INLINE int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * pix_width; } AGG_INLINE const int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * pix_width; } //-------------------------------------------------------------------- AGG_INLINE void make_pix(int8u* p, const color_type& c) { *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { ((pixel_type*) m_rbuf->row_ptr(x, y, 1))[x] = m_blender.make_pix(c.r, c.g, c.b); } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); } //-------------------------------------------------------------------- AGG_INLINE void copy_hline(int x, int y, unsigned len, const color_type& c) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { *p++ = v; } while(--len); } //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; *p = v; } while(--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { *p++ = v; } while(--len); } else { do { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); ++p; } while(--len); } } } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; } while(--len); } else { do { m_blender.blend_pix( (pixel_type*)m_rbuf->row_ptr(x, y++, 1), c.r, c.g, c.b, alpha, cover); } while(--len); } } } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { copy_or_blend_pix(p, c, *covers++); ++p; } while(--len); } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { do { copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, c, *covers++); } while(--len); } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); ++colors; } while(--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { do { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; *p = m_blender.make_pix(colors->r, colors->g, colors->b); ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); } while(--len); } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { do { copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, *colors++, covers ? *covers++ : cover); } while(--len); } //-------------------------------------------------------------------- template<class RenBuf2> void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { const int8u* p = from.row_ptr(ysrc); if(p) { memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; const value_type* psrc = (const value_type*)from.row_ptr(ysrc); if(psrc) { psrc += xsrc * 4; pixel_type* pdst = (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { value_type alpha = psrc[src_order::A]; if(alpha) { if(alpha == base_mask && cover == 255) { *pdst = m_blender.make_pix(psrc[src_order::R], psrc[src_order::G], psrc[src_order::B]); } else { m_blender.blend_pix(pdst, psrc[src_order::R], psrc[src_order::G], psrc[src_order::B], alpha, cover); } } psrc += 4; ++pdst; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { pixel_type* pdst = (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { m_blender.blend_pix(pdst, color.r, color.g, color.b, color.a, cover); ++psrc; ++pdst; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { pixel_type* pdst = (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { const color_type& color = color_lut[*psrc]; m_blender.blend_pix(pdst, color.r, color.g, color.b, color.a, cover); ++psrc; ++pdst; } while(--len); } } private: rbuf_type* m_rbuf; Blender m_blender; }; typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565 typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre //-----------------------------------------------------pixfmt_rgb555_gamma template<class Gamma> class pixfmt_rgb555_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgb565_gamma template<class Gamma> class pixfmt_rgb565_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgbAAA_gamma template<class Gamma> class pixfmt_rgbAAA_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_bgrAAA_gamma template<class Gamma> class pixfmt_bgrAAA_gamma : public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, rendering_buffer> { public: pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_rgbBBA_gamma template<class Gamma> class pixfmt_rgbBBA_gamma : public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; //-----------------------------------------------------pixfmt_bgrABB_gamma template<class Gamma> class pixfmt_bgrABB_gamma : public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, rendering_buffer> { public: pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_solid.h����������������������������������������������0000644�0024617�0000144�00000003254�12261257215�022614� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // span_solid_rgba8 // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_SOLID_INCLUDED #define AGG_SPAN_SOLID_INCLUDED #include "agg_basics.h" namespace mapserver { //--------------------------------------------------------------span_solid template<class ColorT> class span_solid { public: typedef ColorT color_type; //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- void prepare() {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { do { *span++ = m_color; } while(--len); } private: color_type m_color; }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_subdiv_adaptor.h�������������������������������������0000644�0024617�0000144�00000011332�12261257215�024504� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED #define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED #include "agg_basics.h" namespace mapserver { //=================================================span_subdiv_adaptor template<class Interpolator, unsigned SubpixelShift = 8> class span_subdiv_adaptor { public: typedef Interpolator interpolator_type; typedef typename interpolator_type::trans_type trans_type; enum sublixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //---------------------------------------------------------------- span_subdiv_adaptor() : m_subdiv_shift(4), m_subdiv_size(1 << m_subdiv_shift), m_subdiv_mask(m_subdiv_size - 1) {} span_subdiv_adaptor(interpolator_type& interpolator, unsigned subdiv_shift = 4) : m_subdiv_shift(subdiv_shift), m_subdiv_size(1 << m_subdiv_shift), m_subdiv_mask(m_subdiv_size - 1), m_interpolator(&interpolator) {} span_subdiv_adaptor(interpolator_type& interpolator, double x, double y, unsigned len, unsigned subdiv_shift = 4) : m_subdiv_shift(subdiv_shift), m_subdiv_size(1 << m_subdiv_shift), m_subdiv_mask(m_subdiv_size - 1), m_interpolator(&interpolator) { begin(x, y, len); } //---------------------------------------------------------------- const interpolator_type& interpolator() const { return *m_interpolator; } void interpolator(interpolator_type& intr) { m_interpolator = &intr; } //---------------------------------------------------------------- const trans_type& transformer() const { return *m_interpolator->transformer(); } void transformer(const trans_type& trans) { m_interpolator->transformer(trans); } //---------------------------------------------------------------- unsigned subdiv_shift() const { return m_subdiv_shift; } void subdiv_shift(unsigned shift) { m_subdiv_shift = shift; m_subdiv_size = 1 << m_subdiv_shift; m_subdiv_mask = m_subdiv_size - 1; } //---------------------------------------------------------------- void begin(double x, double y, unsigned len) { m_pos = 1; m_src_x = iround(x * subpixel_scale) + subpixel_scale; m_src_y = y; m_len = len; if(len > m_subdiv_size) len = m_subdiv_size; m_interpolator->begin(x, y, len); } //---------------------------------------------------------------- void operator++() { ++(*m_interpolator); if(m_pos >= m_subdiv_size) { unsigned len = m_len; if(len > m_subdiv_size) len = m_subdiv_size; m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len, m_src_y, len); m_pos = 0; } m_src_x += subpixel_scale; ++m_pos; --m_len; } //---------------------------------------------------------------- void coordinates(int* x, int* y) const { m_interpolator->coordinates(x, y); } //---------------------------------------------------------------- void local_scale(int* x, int* y) const { m_interpolator->local_scale(x, y); } private: unsigned m_subdiv_shift; unsigned m_subdiv_size; unsigned m_subdiv_mask; interpolator_type* m_interpolator; int m_src_x; double m_src_y; unsigned m_pos; unsigned m_len; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_segmentator.h����������������������������������������0000644�0024617�0000144�00000003306�12261257215�024034� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_SEGMENTATOR_INCLUDED #define AGG_CONV_SEGMENTATOR_INCLUDED #include "agg_basics.h" #include "agg_conv_adaptor_vpgen.h" #include "agg_vpgen_segmentator.h" namespace mapserver { //========================================================conv_segmentator template<class VertexSource> struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator> { typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type; conv_segmentator(VertexSource& vs) : conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {} void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); } double approximation_scale() const { return base_type::vpgen().approximation_scale(); } private: conv_segmentator(const conv_segmentator<VertexSource>&); const conv_segmentator<VertexSource>& operator = (const conv_segmentator<VertexSource>&); }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_transform.h������������������������������������������0000644�0024617�0000144�00000004024�12261257215�023515� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class conv_transform // //---------------------------------------------------------------------------- #ifndef AGG_CONV_TRANSFORM_INCLUDED #define AGG_CONV_TRANSFORM_INCLUDED #include "agg_basics.h" #include "agg_trans_affine.h" namespace mapserver { //----------------------------------------------------------conv_transform template<class VertexSource, class Transformer=trans_affine> class conv_transform { public: conv_transform(VertexSource& source, const Transformer& tr) : m_source(&source), m_trans(&tr) {} void attach(VertexSource& source) { m_source = &source; } void rewind(unsigned path_id) { m_source->rewind(path_id); } unsigned vertex(double* x, double* y) { unsigned cmd = m_source->vertex(x, y); if(is_vertex(cmd)) { m_trans->transform(x, y); } return cmd; } void transformer(const Transformer& tr) { m_trans = &tr; } private: conv_transform(const conv_transform<VertexSource>&); const conv_transform<VertexSource>& operator = (const conv_transform<VertexSource>&); VertexSource* m_source; const Transformer* m_trans; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_markers.h����������������������������������������0000644�0024617�0000144�00000106275�12261257215�024022� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class renderer_markers // //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_MARKERS_INCLUDED #define AGG_RENDERER_MARKERS_INCLUDED #include "agg_basics.h" #include "agg_renderer_primitives.h" namespace mapserver { //---------------------------------------------------------------marker_e enum marker_e { marker_square, marker_diamond, marker_circle, marker_crossed_circle, marker_semiellipse_left, marker_semiellipse_right, marker_semiellipse_up, marker_semiellipse_down, marker_triangle_left, marker_triangle_right, marker_triangle_up, marker_triangle_down, marker_four_rays, marker_cross, marker_x, marker_dash, marker_dot, marker_pixel, end_of_markers }; //--------------------------------------------------------renderer_markers template<class BaseRenderer> class renderer_markers : public renderer_primitives<BaseRenderer> { public: typedef renderer_primitives<BaseRenderer> base_type; typedef BaseRenderer base_ren_type; typedef typename base_ren_type::color_type color_type; //-------------------------------------------------------------------- renderer_markers(base_ren_type& rbuf) : base_type(rbuf) {} //-------------------------------------------------------------------- bool visible(int x, int y, int r) const { rect_i rc(x-r, y-r, x+y, y+r); return rc.clip(base_type::ren().bounding_clip_box()); } //-------------------------------------------------------------------- void square(int x, int y, int r) { if(visible(x, y, r)) { if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r); else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } //-------------------------------------------------------------------- void diamond(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r; int dx = 0; do { base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); if(dx) { base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); } ++dy; ++dx; } while(dy <= 0); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void circle(int x, int y, int r) { if(visible(x, y, r)) { if(r) base_type::outlined_ellipse(x, y, r, r); else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } //-------------------------------------------------------------------- void crossed_circle(int x, int y, int r) { if(visible(x, y, r)) { if(r) { base_type::outlined_ellipse(x, y, r, r); int r6 = r + (r >> 1); if(r <= 2) r6++; r >>= 1; base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full); base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full); base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full); base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //------------------------------------------------------------------------ void semiellipse_left(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int r8 = r * 4 / 5; int dy = -r; int dx = 0; ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); do { dx += ei.dx(); dy += ei.dy(); base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); if(ei.dy() && dx) { base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); } ++ei; } while(dy < r8); base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void semiellipse_right(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int r8 = r * 4 / 5; int dy = -r; int dx = 0; ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); do { dx += ei.dx(); dy += ei.dy(); base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); if(ei.dy() && dx) { base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); } ++ei; } while(dy < r8); base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void semiellipse_up(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int r8 = r * 4 / 5; int dy = -r; int dx = 0; ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); do { dx += ei.dx(); dy += ei.dy(); base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); if(ei.dy() && dx) { base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); } ++ei; } while(dy < r8); base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void semiellipse_down(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int r8 = r * 4 / 5; int dy = -r; int dx = 0; ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); do { dx += ei.dx(); dy += ei.dy(); base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); if(ei.dy() && dx) { base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); } ++ei; } while(dy < r8); base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void triangle_left(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r; int dx = 0; int flip = 0; int r6 = r * 3 / 5; do { base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); if(dx) { base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); } ++dy; dx += flip; flip ^= 1; } while(dy < r6); base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void triangle_right(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r; int dx = 0; int flip = 0; int r6 = r * 3 / 5; do { base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); if(dx) { base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); } ++dy; dx += flip; flip ^= 1; } while(dy < r6); base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void triangle_up(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r; int dx = 0; int flip = 0; int r6 = r * 3 / 5; do { base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); if(dx) { base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); } ++dy; dx += flip; flip ^= 1; } while(dy < r6); base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void triangle_down(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r; int dx = 0; int flip = 0; int r6 = r * 3 / 5; do { base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); if(dx) { base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); } ++dy; dx += flip; flip ^= 1; } while(dy < r6); base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void four_rays(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r; int dx = 0; int flip = 0; int r3 = -(r / 3); do { base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); if(dx) { base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); } ++dy; dx += flip; flip ^= 1; } while(dy <= r3); base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void cross(int x, int y, int r) { if(visible(x, y, r)) { if(r) { base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full); base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); } else { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } } //-------------------------------------------------------------------- void xing(int x, int y, int r) { if(visible(x, y, r)) { if(r) { int dy = -r * 7 / 10; do { base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full); base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full); ++dy; } while(dy < 0); } base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } //-------------------------------------------------------------------- void dash(int x, int y, int r) { if(visible(x, y, r)) { if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } //-------------------------------------------------------------------- void dot(int x, int y, int r) { if(visible(x, y, r)) { if(r) base_type::solid_ellipse(x, y, r, r); else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } } //-------------------------------------------------------------------- void pixel(int x, int y, int) { base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); } //-------------------------------------------------------------------- void marker(int x, int y, int r, marker_e type) { switch(type) { case marker_square: square(x, y, r); break; case marker_diamond: diamond(x, y, r); break; case marker_circle: circle(x, y, r); break; case marker_crossed_circle: crossed_circle(x, y, r); break; case marker_semiellipse_left: semiellipse_left(x, y, r); break; case marker_semiellipse_right: semiellipse_right(x, y, r); break; case marker_semiellipse_up: semiellipse_up(x, y, r); break; case marker_semiellipse_down: semiellipse_down(x, y, r); break; case marker_triangle_left: triangle_left(x, y, r); break; case marker_triangle_right: triangle_right(x, y, r); break; case marker_triangle_up: triangle_up(x, y, r); break; case marker_triangle_down: triangle_down(x, y, r); break; case marker_four_rays: four_rays(x, y, r); break; case marker_cross: cross(x, y, r); break; case marker_x: xing(x, y, r); break; case marker_dash: dash(x, y, r); break; case marker_dot: dot(x, y, r); break; case marker_pixel: pixel(x, y, r); break; } } //-------------------------------------------------------------------- template<class T> void markers(int n, const T* x, const T* y, T r, marker_e type) { if(n <= 0) return; if(r == 0) { do { base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full); ++x; ++y; } while(--n); return; } switch(type) { case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; } } //-------------------------------------------------------------------- template<class T> void markers(int n, const T* x, const T* y, const T* r, marker_e type) { if(n <= 0) return; switch(type) { case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; } } //-------------------------------------------------------------------- template<class T> void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type) { if(n <= 0) return; switch(type) { case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; } } //-------------------------------------------------------------------- template<class T> void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type) { if(n <= 0) return; switch(type) { case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; } } }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pixfmt_amask_adaptor.h������������������������������������0000644�0024617�0000144�00000020526�12261257215�024657� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED #define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED #include <string.h> #include "agg_array.h" #include "agg_rendering_buffer.h" namespace mapserver { //==================================================pixfmt_amask_adaptor template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor { public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::row_data row_data; typedef AlphaMask amask_type; typedef typename amask_type::cover_type cover_type; private: enum span_extra_tail_e { span_extra_tail = 256 }; void realloc_span(unsigned len) { if(len > m_span.size()) { m_span.resize(len + span_extra_tail); } } void init_span(unsigned len) { realloc_span(len); memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type)); } void init_span(unsigned len, const cover_type* covers) { realloc_span(len); memcpy(&m_span[0], covers, len * sizeof(cover_type)); } public: pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : m_pixf(&pixf), m_mask(&mask), m_span() {} void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } //-------------------------------------------------------------------- template<class PixFmt2> bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2) { return m_pixf->attach(pixf, x1, y1, x2, y2); } //-------------------------------------------------------------------- unsigned width() const { return m_pixf->width(); } unsigned height() const { return m_pixf->height(); } //-------------------------------------------------------------------- color_type pixel(int x, int y) { return m_pixf->pixel(x, y); } //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); } //-------------------------------------------------------------------- void blend_pixel(int x, int y, const color_type& c, cover_type cover) { m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover)); } //-------------------------------------------------------------------- void copy_hline(int x, int y, unsigned len, const color_type& c) { realloc_span(len); m_mask->fill_hspan(x, y, &m_span[0], len); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, cover_type cover) { init_span(len); m_mask->combine_hspan(x, y, &m_span[0], len); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- void copy_vline(int x, int y, unsigned len, const color_type& c) { realloc_span(len); m_mask->fill_vspan(x, y, &m_span[0], len); m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, cover_type cover) { init_span(len); m_mask->combine_vspan(x, y, &m_span[0], len); m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- void copy_from(const rendering_buffer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len); } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const cover_type* covers) { init_span(len, covers); m_mask->combine_hspan(x, y, &m_span[0], len); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const cover_type* covers) { init_span(len, covers); m_mask->combine_vspan(x, y, &m_span[0], len); m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { realloc_span(len); m_mask->fill_hspan(x, y, &m_span[0], len); m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { realloc_span(len); m_mask->fill_vspan(x, y, &m_span[0], len); m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const cover_type* covers, cover_type cover = cover_full) { if(covers) { init_span(len, covers); m_mask->combine_hspan(x, y, &m_span[0], len); } else { realloc_span(len); m_mask->fill_hspan(x, y, &m_span[0], len); } m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover); } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const cover_type* covers, cover_type cover = cover_full) { if(covers) { init_span(len, covers); m_mask->combine_vspan(x, y, &m_span[0], len); } else { realloc_span(len); m_mask->fill_vspan(x, y, &m_span[0], len); } m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover); } private: pixfmt_type* m_pixf; const amask_type* m_mask; pod_array<cover_type> m_span; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_base.h�������������������������������������������0000644�0024617�0000144�00000060747�12261257215�023273� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class renderer_base // //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_BASE_INCLUDED #define AGG_RENDERER_BASE_INCLUDED #include "agg_basics.h" #include "agg_rendering_buffer.h" namespace mapserver { //-----------------------------------------------------------renderer_base template<class PixelFormat> class renderer_base { public: typedef PixelFormat pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::row_data row_data; //-------------------------------------------------------------------- renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {} explicit renderer_base(pixfmt_type& ren) : m_ren(&ren), m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) {} void attach(pixfmt_type& ren) { m_ren = &ren; m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1); } //-------------------------------------------------------------------- const pixfmt_type& ren() const { return *m_ren; } pixfmt_type& ren() { return *m_ren; } //-------------------------------------------------------------------- unsigned width() const { return m_ren->width(); } unsigned height() const { return m_ren->height(); } //-------------------------------------------------------------------- bool clip_box(int x1, int y1, int x2, int y2) { rect_i cb(x1, y1, x2, y2); cb.normalize(); if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) { m_clip_box = cb; return true; } m_clip_box.x1 = 1; m_clip_box.y1 = 1; m_clip_box.x2 = 0; m_clip_box.y2 = 0; return false; } //-------------------------------------------------------------------- void reset_clipping(bool visibility) { if(visibility) { m_clip_box.x1 = 0; m_clip_box.y1 = 0; m_clip_box.x2 = width() - 1; m_clip_box.y2 = height() - 1; } else { m_clip_box.x1 = 1; m_clip_box.y1 = 1; m_clip_box.x2 = 0; m_clip_box.y2 = 0; } } //-------------------------------------------------------------------- void clip_box_naked(int x1, int y1, int x2, int y2) { m_clip_box.x1 = x1; m_clip_box.y1 = y1; m_clip_box.x2 = x2; m_clip_box.y2 = y2; } //-------------------------------------------------------------------- bool inbox(int x, int y) const { return x >= m_clip_box.x1 && y >= m_clip_box.y1 && x <= m_clip_box.x2 && y <= m_clip_box.y2; } //-------------------------------------------------------------------- const rect_i& clip_box() const { return m_clip_box; } int xmin() const { return m_clip_box.x1; } int ymin() const { return m_clip_box.y1; } int xmax() const { return m_clip_box.x2; } int ymax() const { return m_clip_box.y2; } //-------------------------------------------------------------------- const rect_i& bounding_clip_box() const { return m_clip_box; } int bounding_xmin() const { return m_clip_box.x1; } int bounding_ymin() const { return m_clip_box.y1; } int bounding_xmax() const { return m_clip_box.x2; } int bounding_ymax() const { return m_clip_box.y2; } //-------------------------------------------------------------------- void clear(const color_type& c) { unsigned y; if(width()) { for(y = 0; y < height(); y++) { m_ren->copy_hline(0, y, width(), c); } } } //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { if(inbox(x, y)) { m_ren->copy_pixel(x, y, c); } } //-------------------------------------------------------------------- void blend_pixel(int x, int y, const color_type& c, cover_type cover) { if(inbox(x, y)) { m_ren->blend_pixel(x, y, c, cover); } } //-------------------------------------------------------------------- color_type pixel(int x, int y) const { return inbox(x, y) ? m_ren->pixel(x, y) : color_type::no_color(); } //-------------------------------------------------------------------- void copy_hline(int x1, int y, int x2, const color_type& c) { if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } if(y > ymax()) return; if(y < ymin()) return; if(x1 > xmax()) return; if(x2 < xmin()) return; if(x1 < xmin()) x1 = xmin(); if(x2 > xmax()) x2 = xmax(); m_ren->copy_hline(x1, y, x2 - x1 + 1, c); } //-------------------------------------------------------------------- void copy_vline(int x, int y1, int y2, const color_type& c) { if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } if(x > xmax()) return; if(x < xmin()) return; if(y1 > ymax()) return; if(y2 < ymin()) return; if(y1 < ymin()) y1 = ymin(); if(y2 > ymax()) y2 = ymax(); m_ren->copy_vline(x, y1, y2 - y1 + 1, c); } //-------------------------------------------------------------------- void blend_hline(int x1, int y, int x2, const color_type& c, cover_type cover) { if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } if(y > ymax()) return; if(y < ymin()) return; if(x1 > xmax()) return; if(x2 < xmin()) return; if(x1 < xmin()) x1 = xmin(); if(x2 > xmax()) x2 = xmax(); m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); } //-------------------------------------------------------------------- void blend_vline(int x, int y1, int y2, const color_type& c, cover_type cover) { if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } if(x > xmax()) return; if(x < xmin()) return; if(y1 > ymax()) return; if(y2 < ymin()) return; if(y1 < ymin()) y1 = ymin(); if(y2 > ymax()) y2 = ymax(); m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); } //-------------------------------------------------------------------- void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) { rect_i rc(x1, y1, x2, y2); rc.normalize(); if(rc.clip(clip_box())) { int y; for(y = rc.y1; y <= rc.y2; y++) { m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); } } } //-------------------------------------------------------------------- void blend_bar(int x1, int y1, int x2, int y2, const color_type& c, cover_type cover) { rect_i rc(x1, y1, x2, y2); rc.normalize(); if(rc.clip(clip_box())) { int y; for(y = rc.y1; y <= rc.y2; y++) { m_ren->blend_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c, cover); } } } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers) { if(y > ymax()) return; if(y < ymin()) return; if(x < xmin()) { len -= xmin() - x; if(len <= 0) return; covers += xmin() - x; x = xmin(); } if(x + len > xmax()) { len = xmax() - x + 1; if(len <= 0) return; } m_ren->blend_solid_hspan(x, y, len, c, covers); } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, int len, const color_type& c, const cover_type* covers) { if(x > xmax()) return; if(x < xmin()) return; if(y < ymin()) { len -= ymin() - y; if(len <= 0) return; covers += ymin() - y; y = ymin(); } if(y + len > ymax()) { len = ymax() - y + 1; if(len <= 0) return; } m_ren->blend_solid_vspan(x, y, len, c, covers); } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, int len, const color_type* colors) { if(y > ymax()) return; if(y < ymin()) return; if(x < xmin()) { int d = xmin() - x; len -= d; if(len <= 0) return; colors += d; x = xmin(); } if(x + len > xmax()) { len = xmax() - x + 1; if(len <= 0) return; } m_ren->copy_color_hspan(x, y, len, colors); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, int len, const color_type* colors) { if(x > xmax()) return; if(x < xmin()) return; if(y < ymin()) { int d = ymin() - y; len -= d; if(len <= 0) return; colors += d; y = ymin(); } if(y + len > ymax()) { len = ymax() - y + 1; if(len <= 0) return; } m_ren->copy_color_vspan(x, y, len, colors); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, int len, const color_type* colors, const cover_type* covers, cover_type cover = mapserver::cover_full) { if(y > ymax()) return; if(y < ymin()) return; if(x < xmin()) { int d = xmin() - x; len -= d; if(len <= 0) return; if(covers) covers += d; colors += d; x = xmin(); } if(x + len > xmax()) { len = xmax() - x + 1; if(len <= 0) return; } m_ren->blend_color_hspan(x, y, len, colors, covers, cover); } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, int len, const color_type* colors, const cover_type* covers, cover_type cover = mapserver::cover_full) { if(x > xmax()) return; if(x < xmin()) return; if(y < ymin()) { int d = ymin() - y; len -= d; if(len <= 0) return; if(covers) covers += d; colors += d; y = ymin(); } if(y + len > ymax()) { len = ymax() - y + 1; if(len <= 0) return; } m_ren->blend_color_vspan(x, y, len, colors, covers, cover); } //-------------------------------------------------------------------- rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const { rect_i rc(0,0,0,0); rect_i cb = clip_box(); ++cb.x2; ++cb.y2; if(src.x1 < 0) { dst.x1 -= src.x1; src.x1 = 0; } if(src.y1 < 0) { dst.y1 -= src.y1; src.y1 = 0; } if(src.x2 > wsrc) src.x2 = wsrc; if(src.y2 > hsrc) src.y2 = hsrc; if(dst.x1 < cb.x1) { src.x1 += cb.x1 - dst.x1; dst.x1 = cb.x1; } if(dst.y1 < cb.y1) { src.y1 += cb.y1 - dst.y1; dst.y1 = cb.y1; } if(dst.x2 > cb.x2) dst.x2 = cb.x2; if(dst.y2 > cb.y2) dst.y2 = cb.y2; rc.x2 = dst.x2 - dst.x1; rc.y2 = dst.y2 - dst.y1; if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; return rc; } //-------------------------------------------------------------------- template<class RenBuf> void copy_from(const RenBuf& src, const rect_i* rect_src_ptr = 0, int dx = 0, int dy = 0) { rect_i rsrc(0, 0, src.width(), src.height()); if(rect_src_ptr) { rsrc.x1 = rect_src_ptr->x1; rsrc.y1 = rect_src_ptr->y1; rsrc.x2 = rect_src_ptr->x2 + 1; rsrc.y2 = rect_src_ptr->y2 + 1; } // Version with xdst, ydst (absolute positioning) //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); // Version with dx, dy (relative positioning) rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); if(rc.x2 > 0) { int incy = 1; if(rdst.y1 > rsrc.y1) { rsrc.y1 += rc.y2 - 1; rdst.y1 += rc.y2 - 1; incy = -1; } while(rc.y2 > 0) { m_ren->copy_from(src, rdst.x1, rdst.y1, rsrc.x1, rsrc.y1, rc.x2); rdst.y1 += incy; rsrc.y1 += incy; --rc.y2; } } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& src, const rect_i* rect_src_ptr = 0, int dx = 0, int dy = 0, cover_type cover = mapserver::cover_full) { rect_i rsrc(0, 0, src.width(), src.height()); if(rect_src_ptr) { rsrc.x1 = rect_src_ptr->x1; rsrc.y1 = rect_src_ptr->y1; rsrc.x2 = rect_src_ptr->x2 + 1; rsrc.y2 = rect_src_ptr->y2 + 1; } // Version with xdst, ydst (absolute positioning) //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); // Version with dx, dy (relative positioning) rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); if(rc.x2 > 0) { int incy = 1; if(rdst.y1 > rsrc.y1) { rsrc.y1 += rc.y2 - 1; rdst.y1 += rc.y2 - 1; incy = -1; } while(rc.y2 > 0) { typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); if(rw.ptr) { int x1src = rsrc.x1; int x1dst = rdst.x1; int len = rc.x2; if(rw.x1 > x1src) { x1dst += rw.x1 - x1src; len -= rw.x1 - x1src; x1src = rw.x1; } if(len > 0) { if(x1src + len-1 > rw.x2) { len -= x1src + len - rw.x2 - 1; } if(len > 0) { m_ren->blend_from(src, x1dst, rdst.y1, x1src, rsrc.y1, len, cover); } } } rdst.y1 += incy; rsrc.y1 += incy; --rc.y2; } } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& src, const color_type& color, const rect_i* rect_src_ptr = 0, int dx = 0, int dy = 0, cover_type cover = mapserver::cover_full) { rect_i rsrc(0, 0, src.width(), src.height()); if(rect_src_ptr) { rsrc.x1 = rect_src_ptr->x1; rsrc.y1 = rect_src_ptr->y1; rsrc.x2 = rect_src_ptr->x2 + 1; rsrc.y2 = rect_src_ptr->y2 + 1; } // Version with xdst, ydst (absolute positioning) //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); // Version with dx, dy (relative positioning) rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); if(rc.x2 > 0) { int incy = 1; if(rdst.y1 > rsrc.y1) { rsrc.y1 += rc.y2 - 1; rdst.y1 += rc.y2 - 1; incy = -1; } while(rc.y2 > 0) { typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); if(rw.ptr) { int x1src = rsrc.x1; int x1dst = rdst.x1; int len = rc.x2; if(rw.x1 > x1src) { x1dst += rw.x1 - x1src; len -= rw.x1 - x1src; x1src = rw.x1; } if(len > 0) { if(x1src + len-1 > rw.x2) { len -= x1src + len - rw.x2 - 1; } if(len > 0) { m_ren->blend_from_color(src, color, x1dst, rdst.y1, x1src, rsrc.y1, len, cover); } } } rdst.y1 += incy; rsrc.y1 += incy; --rc.y2; } } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& src, const color_type* color_lut, const rect_i* rect_src_ptr = 0, int dx = 0, int dy = 0, cover_type cover = mapserver::cover_full) { rect_i rsrc(0, 0, src.width(), src.height()); if(rect_src_ptr) { rsrc.x1 = rect_src_ptr->x1; rsrc.y1 = rect_src_ptr->y1; rsrc.x2 = rect_src_ptr->x2 + 1; rsrc.y2 = rect_src_ptr->y2 + 1; } // Version with xdst, ydst (absolute positioning) //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); // Version with dx, dy (relative positioning) rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); if(rc.x2 > 0) { int incy = 1; if(rdst.y1 > rsrc.y1) { rsrc.y1 += rc.y2 - 1; rdst.y1 += rc.y2 - 1; incy = -1; } while(rc.y2 > 0) { typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); if(rw.ptr) { int x1src = rsrc.x1; int x1dst = rdst.x1; int len = rc.x2; if(rw.x1 > x1src) { x1dst += rw.x1 - x1src; len -= rw.x1 - x1src; x1src = rw.x1; } if(len > 0) { if(x1src + len-1 > rw.x2) { len -= x1src + len - rw.x2 - 1; } if(len > 0) { m_ren->blend_from_lut(src, color_lut, x1dst, rdst.y1, x1src, rsrc.y1, len, cover); } } } rdst.y1 += incy; rsrc.y1 += incy; --rc.y2; } } } private: pixfmt_type* m_ren; rect_i m_clip_box; }; } #endif �������������������������mapserver-6.4.1/renderers/agg/include/agg_span_image_filter_rgba.h����������������������������������0000644�0024617�0000144�00000111117�12261257215�025122� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED #define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_span_image_filter.h" namespace mapserver { //==============================================span_image_filter_rgba_nn template<class Source, class Interpolator> class span_image_filter_rgba_nn : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgba_nn() {} span_image_filter_rgba_nn(source_type& src, interpolator_type& inter) : base_type(src, inter, 0) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); do { base_type::interpolator().coordinates(&x, &y); const value_type* fg_ptr = (const value_type*) base_type::source().span(x >> image_subpixel_shift, y >> image_subpixel_shift, 1); span->r = fg_ptr[order_type::R]; span->g = fg_ptr[order_type::G]; span->b = fg_ptr[order_type::B]; span->a = fg_ptr[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); } }; //=========================================span_image_filter_rgba_bilinear template<class Source, class Interpolator> class span_image_filter_rgba_bilinear : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgba_bilinear() {} span_image_filter_rgba_bilinear(source_type& src, interpolator_type& inter) : base_type(src, inter, 0) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[4]; const value_type *fg_ptr; do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; fg[0] = fg[1] = fg[2] = fg[3] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = x_hr * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_y(); weight = (image_subpixel_scale - x_hr) * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = x_hr * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); span->a = value_type(fg[order_type::A] >> (image_subpixel_shift * 2)); ++span; ++base_type::interpolator(); } while(--len); } }; //====================================span_image_filter_rgba_bilinear_clip template<class Source, class Interpolator> class span_image_filter_rgba_bilinear_clip : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgba_bilinear_clip() {} span_image_filter_rgba_bilinear_clip(source_type& src, const color_type& back_color, interpolator_type& inter) : base_type(src, inter, 0), m_back_color(back_color) {} const color_type& background_color() const { return m_back_color; } void background_color(const color_type& v) { m_back_color = v; } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[4]; value_type back_r = m_back_color.r; value_type back_g = m_back_color.g; value_type back_b = m_back_color.b; value_type back_a = m_back_color.a; const value_type *fg_ptr; int maxx = base_type::source().width() - 1; int maxy = base_type::source().height() - 1; do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; if(x_lr >= 0 && y_lr >= 0 && x_lr < maxx && y_lr < maxy) { fg[0] = fg[1] = fg[2] = fg[3] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + (x_lr << 2); weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; weight = x_hr * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; ++y_lr; fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + (x_lr << 2); weight = (image_subpixel_scale - x_hr) * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; weight = x_hr * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; fg[0] >>= image_subpixel_shift * 2; fg[1] >>= image_subpixel_shift * 2; fg[2] >>= image_subpixel_shift * 2; fg[3] >>= image_subpixel_shift * 2; } else { if(x_lr < -1 || y_lr < -1 || x_lr > maxx || y_lr > maxy) { fg[order_type::R] = back_r; fg[order_type::G] = back_g; fg[order_type::B] = back_b; fg[order_type::A] = back_a; } else { fg[0] = fg[1] = fg[2] = fg[3] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + (x_lr << 2); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; fg[order_type::A] += back_a * weight; } x_lr++; weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + (x_lr << 2); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; fg[order_type::A] += back_a * weight; } x_lr--; y_lr++; weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + (x_lr << 2); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; fg[order_type::A] += back_a * weight; } x_lr++; weight = x_hr * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + (x_lr << 2); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; fg[order_type::A] += back_a * weight; } fg[0] >>= image_subpixel_shift * 2; fg[1] >>= image_subpixel_shift * 2; fg[2] >>= image_subpixel_shift * 2; fg[3] >>= image_subpixel_shift * 2; } } span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = (value_type)fg[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); } private: color_type m_back_color; }; //==============================================span_image_filter_rgba_2x2 template<class Source, class Interpolator> class span_image_filter_rgba_2x2 : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgba_2x2() {} span_image_filter_rgba_2x2(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[4]; const value_type *fg_ptr; const int16* weight_array = base_type::filter().weight_array() + ((base_type::filter().diameter()/2 - 1) << image_subpixel_shift); do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); weight = (weight_array[x_hr + image_subpixel_scale] * weight_array[y_hr + image_subpixel_scale] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = (weight_array[x_hr] * weight_array[y_hr + image_subpixel_scale] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_y(); weight = (weight_array[x_hr + image_subpixel_scale] * weight_array[y_hr] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = (weight_array[x_hr] * weight_array[y_hr] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; fg[0] >>= image_filter_shift; fg[1] >>= image_filter_shift; fg[2] >>= image_filter_shift; fg[3] >>= image_filter_shift; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = (value_type)fg[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); } }; //==================================================span_image_filter_rgba template<class Source, class Interpolator> class span_image_filter_rgba : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgba() {} span_image_filter_rgba(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); int fg[4]; const value_type *fg_ptr; unsigned diameter = base_type::filter().diameter(); int start = base_type::filter().start(); const int16* weight_array = base_type::filter().weight_array(); int x_count; int weight_y; do { base_type::interpolator().coordinates(&x, &y); x -= base_type::filter_dx_int(); y -= base_type::filter_dy_int(); int x_hr = x; int y_hr = y; int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; int x_fract = x_hr & image_subpixel_mask; unsigned y_count = diameter; y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); fg_ptr = (const value_type*)base_type::source().span(x_lr + start, y_lr + start, diameter); for(;;) { x_count = diameter; weight_y = weight_array[y_hr]; x_hr = image_subpixel_mask - x_fract; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr; if(--x_count == 0) break; x_hr += image_subpixel_scale; fg_ptr = (const value_type*)base_type::source().next_x(); } if(--y_count == 0) break; y_hr += image_subpixel_scale; fg_ptr = (const value_type*)base_type::source().next_y(); } fg[0] >>= image_filter_shift; fg[1] >>= image_filter_shift; fg[2] >>= image_filter_shift; fg[3] >>= image_filter_shift; if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[3] < 0) fg[3] = 0; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = (value_type)fg[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); } }; //========================================span_image_resample_rgba_affine template<class Source> class span_image_resample_rgba_affine : public span_image_resample_affine<Source> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef span_image_resample_affine<source_type> base_type; typedef typename base_type::interpolator_type interpolator_type; typedef typename color_type::value_type value_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask, downscale_shift = image_filter_shift }; //-------------------------------------------------------------------- span_image_resample_rgba_affine() {} span_image_resample_rgba_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg[4]; int diameter = base_type::filter().diameter(); int filter_scale = diameter << image_subpixel_shift; int radius_x = (diameter * base_type::m_rx) >> 1; int radius_y = (diameter * base_type::m_ry) >> 1; int len_x_lr = (diameter * base_type::m_rx + image_subpixel_mask) >> image_subpixel_shift; const int16* weight_array = base_type::filter().weight_array(); do { base_type::interpolator().coordinates(&x, &y); x += base_type::filter_dx_int() - radius_x; y += base_type::filter_dy_int() - radius_y; fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * base_type::m_ry_inv) >> image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * base_type::m_rx_inv) >> image_subpixel_shift; int x_hr2 = x_hr; const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { int weight_y = weight_array[y_hr]; x_hr = x_hr2; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; fg[0] += *fg_ptr++ * weight; fg[1] += *fg_ptr++ * weight; fg[2] += *fg_ptr++ * weight; fg[3] += *fg_ptr++ * weight; total_weight += weight; x_hr += base_type::m_rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); } y_hr += base_type::m_ry_inv; if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } fg[0] /= total_weight; fg[1] /= total_weight; fg[2] /= total_weight; fg[3] /= total_weight; if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[3] < 0) fg[3] = 0; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = (value_type)fg[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); } }; //==============================================span_image_resample_rgba template<class Source, class Interpolator> class span_image_resample_rgba : public span_image_resample<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_resample<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask, downscale_shift = image_filter_shift }; //-------------------------------------------------------------------- span_image_resample_rgba() {} span_image_resample_rgba(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg[4]; int diameter = base_type::filter().diameter(); int filter_scale = diameter << image_subpixel_shift; const int16* weight_array = base_type::filter().weight_array(); do { int rx; int ry; int rx_inv = image_subpixel_scale; int ry_inv = image_subpixel_scale; base_type::interpolator().coordinates(&x, &y); base_type::interpolator().local_scale(&rx, &ry); base_type::adjust_scale(&rx, &ry); rx_inv = image_subpixel_scale * image_subpixel_scale / rx; ry_inv = image_subpixel_scale * image_subpixel_scale / ry; int radius_x = (diameter * rx) >> 1; int radius_y = (diameter * ry) >> 1; int len_x_lr = (diameter * rx + image_subpixel_mask) >> image_subpixel_shift; x += base_type::filter_dx_int() - radius_x; y += base_type::filter_dy_int() - radius_y; fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * ry_inv) >> image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * rx_inv) >> image_subpixel_shift; int x_hr2 = x_hr; const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { int weight_y = weight_array[y_hr]; x_hr = x_hr2; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; fg[0] += *fg_ptr++ * weight; fg[1] += *fg_ptr++ * weight; fg[2] += *fg_ptr++ * weight; fg[3] += *fg_ptr++ * weight; total_weight += weight; x_hr += rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); } y_hr += ry_inv; if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } fg[0] /= total_weight; fg[1] /= total_weight; fg[2] /= total_weight; fg[3] /= total_weight; if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[3] < 0) fg[3] = 0; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = (value_type)fg[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); } }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_font_freetype.h�������������������������������������������0000644�0024617�0000144�00000020237�12261257215�023332� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // See implementation agg_font_freetype.cpp // //---------------------------------------------------------------------------- #ifndef AGG_FONT_FREETYPE_INCLUDED #define AGG_FONT_FREETYPE_INCLUDED #include <ft2build.h> #include FT_FREETYPE_H #include "agg_scanline_storage_aa.h" #include "agg_scanline_storage_bin.h" #include "agg_scanline_u.h" #include "agg_scanline_bin.h" #include "agg_path_storage_integer.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_conv_curve.h" #include "agg_font_cache_manager.h" #include "agg_trans_affine.h" namespace mapserver { //-----------------------------------------------font_engine_freetype_base class font_engine_freetype_base { public: //-------------------------------------------------------------------- typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type; typedef serialized_scanlines_adaptor_bin mono_adaptor_type; typedef scanline_storage_aa8 scanlines_aa_type; typedef scanline_storage_bin scanlines_bin_type; //-------------------------------------------------------------------- ~font_engine_freetype_base(); font_engine_freetype_base(bool flag32, unsigned max_faces = 32); // Set font parameters //-------------------------------------------------------------------- void resolution(unsigned dpi); bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type, const char* font_mem = 0, const long font_mem_size = 0); bool attach(const char* file_name); bool char_map(FT_Encoding map); bool height(double h); bool width(double w); void hinting(bool h); void flip_y(bool f); void transform(const trans_affine& affine); // Set Gamma //-------------------------------------------------------------------- template<class GammaF> void gamma(const GammaF& f) { m_rasterizer.gamma(f); } // Accessors //-------------------------------------------------------------------- int last_error() const { return m_last_error; } unsigned resolution() const { return m_resolution; } const char* name() const { return m_name; } unsigned num_faces() const; FT_Encoding char_map() const { return m_char_map; } double height() const { return double(m_height) / 64.0; } double width() const { return double(m_width) / 64.0; } double ascender() const; double descender() const; bool hinting() const { return m_hinting; } bool flip_y() const { return m_flip_y; } // Interface mandatory to implement for font_cache_manager //-------------------------------------------------------------------- const char* font_signature() const { return m_signature; } int change_stamp() const { return m_change_stamp; } bool prepare_glyph(unsigned glyph_code); unsigned glyph_index() const { return m_glyph_index; } unsigned data_size() const { return m_data_size; } glyph_data_type data_type() const { return m_data_type; } const rect_i& bounds() const { return m_bounds; } double advance_x() const { return m_advance_x; } double advance_y() const { return m_advance_y; } void write_glyph_to(int8u* data) const; bool add_kerning(unsigned first, unsigned second, double* x, double* y); private: font_engine_freetype_base(const font_engine_freetype_base&); const font_engine_freetype_base& operator = (const font_engine_freetype_base&); void update_char_size(); void update_signature(); int find_face(const char* face_name) const; bool m_flag32; int m_change_stamp; int m_last_error; char* m_name; unsigned m_name_len; unsigned m_face_index; FT_Encoding m_char_map; char* m_signature; unsigned m_height; unsigned m_width; bool m_hinting; bool m_flip_y; bool m_library_initialized; FT_Library m_library; // handle to library FT_Face* m_faces; // A pool of font faces char** m_face_names; unsigned m_num_faces; unsigned m_max_faces; FT_Face m_cur_face; // handle to the current face object int m_resolution; glyph_rendering m_glyph_rendering; unsigned m_glyph_index; unsigned m_data_size; glyph_data_type m_data_type; rect_i m_bounds; double m_advance_x; double m_advance_y; trans_affine m_affine; path_storage_integer<int16, 6> m_path16; path_storage_integer<int32, 6> m_path32; conv_curve<path_storage_integer<int16, 6> > m_curves16; conv_curve<path_storage_integer<int32, 6> > m_curves32; scanline_u8 m_scanline_aa; scanline_bin m_scanline_bin; scanlines_aa_type m_scanlines_aa; scanlines_bin_type m_scanlines_bin; rasterizer_scanline_aa<> m_rasterizer; }; //------------------------------------------------font_engine_freetype_int16 // This class uses values of type int16 (10.6 format) for the vector cache. // The vector cache is compact, but when rendering glyphs of height // more that 200 there integer overflow can occur. // class font_engine_freetype_int16 : public font_engine_freetype_base { public: typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type; typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; font_engine_freetype_int16(unsigned max_faces = 32) : font_engine_freetype_base(false, max_faces) {} }; //------------------------------------------------font_engine_freetype_int32 // This class uses values of type int32 (26.6 format) for the vector cache. // The vector cache is twice larger than in font_engine_freetype_int16, // but it allows you to render glyphs of very large sizes. // class font_engine_freetype_int32 : public font_engine_freetype_base { public: typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type; typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; font_engine_freetype_int32(unsigned max_faces = 32) : font_engine_freetype_base(true, max_faces) {} }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_outline_aa.h�������������������������������������0000644�0024617�0000144�00000174157�12261257215�024502� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED #define AGG_RENDERER_OUTLINE_AA_INCLUDED #include "agg_array.h" #include "agg_math.h" #include "agg_line_aa_basics.h" #include "agg_dda_line.h" #include "agg_ellipse_bresenham.h" #include "agg_renderer_base.h" #include "agg_gamma_functions.h" #include "agg_clip_liang_barsky.h" namespace mapserver { //===================================================distance_interpolator0 class distance_interpolator0 { public: //--------------------------------------------------------------------- distance_interpolator0() {} distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : m_dx(line_mr(x2) - line_mr(x1)), m_dy(line_mr(y2) - line_mr(y1)), m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) { m_dx <<= line_mr_subpixel_shift; m_dy <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; } int dist() const { return m_dist; } private: //--------------------------------------------------------------------- int m_dx; int m_dy; int m_dist; }; //==================================================distance_interpolator00 class distance_interpolator00 { public: //--------------------------------------------------------------------- distance_interpolator00() {} distance_interpolator00(int xc, int yc, int x1, int y1, int x2, int y2, int x, int y) : m_dx1(line_mr(x1) - line_mr(xc)), m_dy1(line_mr(y1) - line_mr(yc)), m_dx2(line_mr(x2) - line_mr(xc)), m_dy2(line_mr(y2) - line_mr(yc)), m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) { m_dx1 <<= line_mr_subpixel_shift; m_dy1 <<= line_mr_subpixel_shift; m_dx2 <<= line_mr_subpixel_shift; m_dy2 <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } int dist1() const { return m_dist1; } int dist2() const { return m_dist2; } private: //--------------------------------------------------------------------- int m_dx1; int m_dy1; int m_dx2; int m_dy2; int m_dist1; int m_dist2; }; //===================================================distance_interpolator1 class distance_interpolator1 { public: //--------------------------------------------------------------------- distance_interpolator1() {} distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : m_dx(x2 - x1), m_dy(y2 - y1), m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - double(y + line_subpixel_scale/2 - y2) * double(m_dx))) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; } //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; } void dec_x() { m_dist -= m_dy; } void inc_y() { m_dist -= m_dx; } void dec_y() { m_dist += m_dx; } //--------------------------------------------------------------------- void inc_x(int dy) { m_dist += m_dy; if(dy > 0) m_dist -= m_dx; if(dy < 0) m_dist += m_dx; } //--------------------------------------------------------------------- void dec_x(int dy) { m_dist -= m_dy; if(dy > 0) m_dist -= m_dx; if(dy < 0) m_dist += m_dx; } //--------------------------------------------------------------------- void inc_y(int dx) { m_dist -= m_dx; if(dx > 0) m_dist += m_dy; if(dx < 0) m_dist -= m_dy; } void dec_y(int dx) //--------------------------------------------------------------------- { m_dist += m_dx; if(dx > 0) m_dist += m_dy; if(dx < 0) m_dist -= m_dy; } //--------------------------------------------------------------------- int dist() const { return m_dist; } int dx() const { return m_dx; } int dy() const { return m_dy; } private: //--------------------------------------------------------------------- int m_dx; int m_dy; int m_dist; }; //===================================================distance_interpolator2 class distance_interpolator2 { public: //--------------------------------------------------------------------- distance_interpolator2() {} distance_interpolator2(int x1, int y1, int x2, int y2, int sx, int sy, int x, int y) : m_dx(x2 - x1), m_dy(y2 - y1), m_dx_start(line_mr(sx) - line_mr(x1)), m_dy_start(line_mr(sy) - line_mr(y1)), m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - double(y + line_subpixel_scale/2 - y2) * double(m_dx))), m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; m_dx_start <<= line_mr_subpixel_shift; m_dy_start <<= line_mr_subpixel_shift; } distance_interpolator2(int x1, int y1, int x2, int y2, int ex, int ey, int x, int y, int) : m_dx(x2 - x1), m_dy(y2 - y1), m_dx_start(line_mr(ex) - line_mr(x2)), m_dy_start(line_mr(ey) - line_mr(y2)), m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - double(y + line_subpixel_scale/2 - y2) * double(m_dx))), m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; m_dx_start <<= line_mr_subpixel_shift; m_dy_start <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; } void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; } void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; } void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } //--------------------------------------------------------------------- void inc_x(int dy) { m_dist += m_dy; m_dist_start += m_dy_start; if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; } if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; } } //--------------------------------------------------------------------- void dec_x(int dy) { m_dist -= m_dy; m_dist_start -= m_dy_start; if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; } if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; } } //--------------------------------------------------------------------- void inc_y(int dx) { m_dist -= m_dx; m_dist_start -= m_dx_start; if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; } if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; } } //--------------------------------------------------------------------- void dec_y(int dx) { m_dist += m_dx; m_dist_start += m_dx_start; if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; } if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; } } //--------------------------------------------------------------------- int dist() const { return m_dist; } int dist_start() const { return m_dist_start; } int dist_end() const { return m_dist_start; } //--------------------------------------------------------------------- int dx() const { return m_dx; } int dy() const { return m_dy; } int dx_start() const { return m_dx_start; } int dy_start() const { return m_dy_start; } int dx_end() const { return m_dx_start; } int dy_end() const { return m_dy_start; } private: //--------------------------------------------------------------------- int m_dx; int m_dy; int m_dx_start; int m_dy_start; int m_dist; int m_dist_start; }; //===================================================distance_interpolator3 class distance_interpolator3 { public: //--------------------------------------------------------------------- distance_interpolator3() {} distance_interpolator3(int x1, int y1, int x2, int y2, int sx, int sy, int ex, int ey, int x, int y) : m_dx(x2 - x1), m_dy(y2 - y1), m_dx_start(line_mr(sx) - line_mr(x1)), m_dy_start(line_mr(sy) - line_mr(y1)), m_dx_end(line_mr(ex) - line_mr(x2)), m_dy_end(line_mr(ey) - line_mr(y2)), m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - double(y + line_subpixel_scale/2 - y2) * double(m_dx))), m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; m_dx_start <<= line_mr_subpixel_shift; m_dy_start <<= line_mr_subpixel_shift; m_dx_end <<= line_mr_subpixel_shift; m_dy_end <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } //--------------------------------------------------------------------- void inc_x(int dy) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } } //--------------------------------------------------------------------- void dec_x(int dy) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } } //--------------------------------------------------------------------- void inc_y(int dx) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } } //--------------------------------------------------------------------- void dec_y(int dx) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } } //--------------------------------------------------------------------- int dist() const { return m_dist; } int dist_start() const { return m_dist_start; } int dist_end() const { return m_dist_end; } //--------------------------------------------------------------------- int dx() const { return m_dx; } int dy() const { return m_dy; } int dx_start() const { return m_dx_start; } int dy_start() const { return m_dy_start; } int dx_end() const { return m_dx_end; } int dy_end() const { return m_dy_end; } private: //--------------------------------------------------------------------- int m_dx; int m_dy; int m_dx_start; int m_dy_start; int m_dx_end; int m_dy_end; int m_dist; int m_dist_start; int m_dist_end; }; //================================================line_interpolator_aa_base template<class Renderer> class line_interpolator_aa_base { public: typedef Renderer renderer_type; typedef typename Renderer::color_type color_type; //--------------------------------------------------------------------- enum max_half_width_e { max_half_width = 64 }; //--------------------------------------------------------------------- line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) : m_lp(&lp), m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : line_dbl_hr(lp.y2 - lp.y1), lp.vertical ? abs(lp.y2 - lp.y1) : abs(lp.x2 - lp.x1) + 1), m_ren(ren), m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), m_x(lp.x1 >> line_subpixel_shift), m_y(lp.y1 >> line_subpixel_shift), m_old_x(m_x), m_old_y(m_y), m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : abs((lp.x2 >> line_subpixel_shift) - m_x))), m_width(ren.subpixel_width()), //m_max_extent(m_width >> (line_subpixel_shift - 2)), m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), m_step(0) { mapserver::dda2_line_interpolator li(0, lp.vertical ? (lp.dy << mapserver::line_subpixel_shift) : (lp.dx << mapserver::line_subpixel_shift), lp.len); unsigned i; int stop = m_width + line_subpixel_scale * 2; for(i = 0; i < max_half_width; ++i) { m_dist[i] = li.y(); if(m_dist[i] >= stop) break; ++li; } m_dist[i++] = 0x7FFF0000; } //--------------------------------------------------------------------- template<class DI> int step_hor_base(DI& di) { ++m_li; m_x += m_lp->inc; m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift; if(m_lp->inc > 0) di.inc_x(m_y - m_old_y); else di.dec_x(m_y - m_old_y); m_old_y = m_y; return di.dist() / m_len; } //--------------------------------------------------------------------- template<class DI> int step_ver_base(DI& di) { ++m_li; m_y += m_lp->inc; m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift; if(m_lp->inc > 0) di.inc_y(m_x - m_old_x); else di.dec_y(m_x - m_old_x); m_old_x = m_x; return di.dist() / m_len; } //--------------------------------------------------------------------- bool vertical() const { return m_lp->vertical; } int width() const { return m_width; } int count() const { return m_count; } private: line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&); const line_interpolator_aa_base<Renderer>& operator = (const line_interpolator_aa_base<Renderer>&); protected: const line_parameters* m_lp; dda2_line_interpolator m_li; renderer_type& m_ren; int m_len; int m_x; int m_y; int m_old_x; int m_old_y; int m_count; int m_width; int m_max_extent; int m_step; int m_dist[max_half_width + 1]; cover_type m_covers[max_half_width * 2 + 4]; }; //====================================================line_interpolator_aa0 template<class Renderer> class line_interpolator_aa0 : public line_interpolator_aa_base<Renderer> { public: typedef Renderer renderer_type; typedef typename Renderer::color_type color_type; typedef line_interpolator_aa_base<Renderer> base_type; //--------------------------------------------------------------------- line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) : line_interpolator_aa_base<Renderer>(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) { base_type::m_li.adjust_forward(); } //--------------------------------------------------------------------- bool step_hor() { int dist; int dy; int s1 = base_type::step_hor_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; *p1++ = (cover_type)base_type::m_ren.cover(s1); dy = 1; while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) { *p1++ = (cover_type)base_type::m_ren.cover(dist); ++dy; } dy = 1; while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) { *--p0 = (cover_type)base_type::m_ren.cover(dist); ++dy; } base_type::m_ren.blend_solid_vspan(base_type::m_x, base_type::m_y - dy + 1, unsigned(p1 - p0), p0); return ++base_type::m_step < base_type::m_count; } //--------------------------------------------------------------------- bool step_ver() { int dist; int dx; int s1 = base_type::step_ver_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; *p1++ = (cover_type)base_type::m_ren.cover(s1); dx = 1; while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) { *p1++ = (cover_type)base_type::m_ren.cover(dist); ++dx; } dx = 1; while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) { *--p0 = (cover_type)base_type::m_ren.cover(dist); ++dx; } base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, base_type::m_y, unsigned(p1 - p0), p0); return ++base_type::m_step < base_type::m_count; } private: line_interpolator_aa0(const line_interpolator_aa0<Renderer>&); const line_interpolator_aa0<Renderer>& operator = (const line_interpolator_aa0<Renderer>&); //--------------------------------------------------------------------- distance_interpolator1 m_di; }; //====================================================line_interpolator_aa1 template<class Renderer> class line_interpolator_aa1 : public line_interpolator_aa_base<Renderer> { public: typedef Renderer renderer_type; typedef typename Renderer::color_type color_type; typedef line_interpolator_aa_base<Renderer> base_type; //--------------------------------------------------------------------- line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, int sx, int sy) : line_interpolator_aa_base<Renderer>(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) { int dist1_start; int dist2_start; int npix = 1; if(lp.vertical) { do { --base_type::m_li; base_type::m_y -= lp.inc; base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); else m_di.inc_y(base_type::m_x - base_type::m_old_x); base_type::m_old_x = base_type::m_x; dist1_start = dist2_start = m_di.dist_start(); int dx = 0; if(dist1_start < 0) ++npix; do { dist1_start += m_di.dy_start(); dist2_start -= m_di.dy_start(); if(dist1_start < 0) ++npix; if(dist2_start < 0) ++npix; ++dx; } while(base_type::m_dist[dx] <= base_type::m_width); --base_type::m_step; if(npix == 0) break; npix = 0; } while(base_type::m_step >= -base_type::m_max_extent); } else { do { --base_type::m_li; base_type::m_x -= lp.inc; base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); else m_di.inc_x(base_type::m_y - base_type::m_old_y); base_type::m_old_y = base_type::m_y; dist1_start = dist2_start = m_di.dist_start(); int dy = 0; if(dist1_start < 0) ++npix; do { dist1_start -= m_di.dx_start(); dist2_start += m_di.dx_start(); if(dist1_start < 0) ++npix; if(dist2_start < 0) ++npix; ++dy; } while(base_type::m_dist[dy] <= base_type::m_width); --base_type::m_step; if(npix == 0) break; npix = 0; } while(base_type::m_step >= -base_type::m_max_extent); } base_type::m_li.adjust_forward(); } //--------------------------------------------------------------------- bool step_hor() { int dist_start; int dist; int dy; int s1 = base_type::step_hor_base(m_di); dist_start = m_di.dist_start(); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; *p1 = 0; if(dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(s1); } ++p1; dy = 1; while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) { dist_start -= m_di.dx_start(); *p1 = 0; if(dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(dist); } ++p1; ++dy; } dy = 1; dist_start = m_di.dist_start(); while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) { dist_start += m_di.dx_start(); *--p0 = 0; if(dist_start <= 0) { *p0 = (cover_type)base_type::m_ren.cover(dist); } ++dy; } base_type::m_ren.blend_solid_vspan(base_type::m_x, base_type::m_y - dy + 1, unsigned(p1 - p0), p0); return ++base_type::m_step < base_type::m_count; } //--------------------------------------------------------------------- bool step_ver() { int dist_start; int dist; int dx; int s1 = base_type::step_ver_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; dist_start = m_di.dist_start(); *p1 = 0; if(dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(s1); } ++p1; dx = 1; while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) { dist_start += m_di.dy_start(); *p1 = 0; if(dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(dist); } ++p1; ++dx; } dx = 1; dist_start = m_di.dist_start(); while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) { dist_start -= m_di.dy_start(); *--p0 = 0; if(dist_start <= 0) { *p0 = (cover_type)base_type::m_ren.cover(dist); } ++dx; } base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, base_type::m_y, unsigned(p1 - p0), p0); return ++base_type::m_step < base_type::m_count; } private: line_interpolator_aa1(const line_interpolator_aa1<Renderer>&); const line_interpolator_aa1<Renderer>& operator = (const line_interpolator_aa1<Renderer>&); //--------------------------------------------------------------------- distance_interpolator2 m_di; }; //====================================================line_interpolator_aa2 template<class Renderer> class line_interpolator_aa2 : public line_interpolator_aa_base<Renderer> { public: typedef Renderer renderer_type; typedef typename Renderer::color_type color_type; typedef line_interpolator_aa_base<Renderer> base_type; //--------------------------------------------------------------------- line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, int ex, int ey) : line_interpolator_aa_base<Renderer>(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask, 0) { base_type::m_li.adjust_forward(); base_type::m_step -= base_type::m_max_extent; } //--------------------------------------------------------------------- bool step_hor() { int dist_end; int dist; int dy; int s1 = base_type::step_hor_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; dist_end = m_di.dist_end(); int npix = 0; *p1 = 0; if(dist_end > 0) { *p1 = (cover_type)base_type::m_ren.cover(s1); ++npix; } ++p1; dy = 1; while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) { dist_end -= m_di.dx_end(); *p1 = 0; if(dist_end > 0) { *p1 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++p1; ++dy; } dy = 1; dist_end = m_di.dist_end(); while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) { dist_end += m_di.dx_end(); *--p0 = 0; if(dist_end > 0) { *p0 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++dy; } base_type::m_ren.blend_solid_vspan(base_type::m_x, base_type::m_y - dy + 1, unsigned(p1 - p0), p0); return npix && ++base_type::m_step < base_type::m_count; } //--------------------------------------------------------------------- bool step_ver() { int dist_end; int dist; int dx; int s1 = base_type::step_ver_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; dist_end = m_di.dist_end(); int npix = 0; *p1 = 0; if(dist_end > 0) { *p1 = (cover_type)base_type::m_ren.cover(s1); ++npix; } ++p1; dx = 1; while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) { dist_end += m_di.dy_end(); *p1 = 0; if(dist_end > 0) { *p1 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++p1; ++dx; } dx = 1; dist_end = m_di.dist_end(); while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) { dist_end -= m_di.dy_end(); *--p0 = 0; if(dist_end > 0) { *p0 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++dx; } base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, base_type::m_y, unsigned(p1 - p0), p0); return npix && ++base_type::m_step < base_type::m_count; } private: line_interpolator_aa2(const line_interpolator_aa2<Renderer>&); const line_interpolator_aa2<Renderer>& operator = (const line_interpolator_aa2<Renderer>&); //--------------------------------------------------------------------- distance_interpolator2 m_di; }; //====================================================line_interpolator_aa3 template<class Renderer> class line_interpolator_aa3 : public line_interpolator_aa_base<Renderer> { public: typedef Renderer renderer_type; typedef typename Renderer::color_type color_type; typedef line_interpolator_aa_base<Renderer> base_type; //--------------------------------------------------------------------- line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, int sx, int sy, int ex, int ey) : line_interpolator_aa_base<Renderer>(ren, lp), m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) { int dist1_start; int dist2_start; int npix = 1; if(lp.vertical) { do { --base_type::m_li; base_type::m_y -= lp.inc; base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); else m_di.inc_y(base_type::m_x - base_type::m_old_x); base_type::m_old_x = base_type::m_x; dist1_start = dist2_start = m_di.dist_start(); int dx = 0; if(dist1_start < 0) ++npix; do { dist1_start += m_di.dy_start(); dist2_start -= m_di.dy_start(); if(dist1_start < 0) ++npix; if(dist2_start < 0) ++npix; ++dx; } while(base_type::m_dist[dx] <= base_type::m_width); if(npix == 0) break; npix = 0; } while(--base_type::m_step >= -base_type::m_max_extent); } else { do { --base_type::m_li; base_type::m_x -= lp.inc; base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); else m_di.inc_x(base_type::m_y - base_type::m_old_y); base_type::m_old_y = base_type::m_y; dist1_start = dist2_start = m_di.dist_start(); int dy = 0; if(dist1_start < 0) ++npix; do { dist1_start -= m_di.dx_start(); dist2_start += m_di.dx_start(); if(dist1_start < 0) ++npix; if(dist2_start < 0) ++npix; ++dy; } while(base_type::m_dist[dy] <= base_type::m_width); if(npix == 0) break; npix = 0; } while(--base_type::m_step >= -base_type::m_max_extent); } base_type::m_li.adjust_forward(); base_type::m_step -= base_type::m_max_extent; } //--------------------------------------------------------------------- bool step_hor() { int dist_start; int dist_end; int dist; int dy; int s1 = base_type::step_hor_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; dist_start = m_di.dist_start(); dist_end = m_di.dist_end(); int npix = 0; *p1 = 0; if(dist_end > 0) { if(dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(s1); } ++npix; } ++p1; dy = 1; while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) { dist_start -= m_di.dx_start(); dist_end -= m_di.dx_end(); *p1 = 0; if(dist_end > 0 && dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++p1; ++dy; } dy = 1; dist_start = m_di.dist_start(); dist_end = m_di.dist_end(); while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) { dist_start += m_di.dx_start(); dist_end += m_di.dx_end(); *--p0 = 0; if(dist_end > 0 && dist_start <= 0) { *p0 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++dy; } base_type::m_ren.blend_solid_vspan(base_type::m_x, base_type::m_y - dy + 1, unsigned(p1 - p0), p0); return npix && ++base_type::m_step < base_type::m_count; } //--------------------------------------------------------------------- bool step_ver() { int dist_start; int dist_end; int dist; int dx; int s1 = base_type::step_ver_base(m_di); cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; cover_type* p1 = p0; dist_start = m_di.dist_start(); dist_end = m_di.dist_end(); int npix = 0; *p1 = 0; if(dist_end > 0) { if(dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(s1); } ++npix; } ++p1; dx = 1; while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) { dist_start += m_di.dy_start(); dist_end += m_di.dy_end(); *p1 = 0; if(dist_end > 0 && dist_start <= 0) { *p1 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++p1; ++dx; } dx = 1; dist_start = m_di.dist_start(); dist_end = m_di.dist_end(); while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) { dist_start -= m_di.dy_start(); dist_end -= m_di.dy_end(); *--p0 = 0; if(dist_end > 0 && dist_start <= 0) { *p0 = (cover_type)base_type::m_ren.cover(dist); ++npix; } ++dx; } base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, base_type::m_y, unsigned(p1 - p0), p0); return npix && ++base_type::m_step < base_type::m_count; } private: line_interpolator_aa3(const line_interpolator_aa3<Renderer>&); const line_interpolator_aa3<Renderer>& operator = (const line_interpolator_aa3<Renderer>&); //--------------------------------------------------------------------- distance_interpolator3 m_di; }; //==========================================================line_profile_aa // // See Implementation agg_line_profile_aa.cpp // class line_profile_aa { public: //--------------------------------------------------------------------- typedef int8u value_type; enum subpixel_scale_e { subpixel_shift = line_subpixel_shift, subpixel_scale = 1 << subpixel_shift, subpixel_mask = subpixel_scale - 1 }; enum aa_scale_e { aa_shift = 8, aa_scale = 1 << aa_shift, aa_mask = aa_scale - 1 }; //--------------------------------------------------------------------- line_profile_aa() : m_subpixel_width(0), m_min_width(1.0), m_smoother_width(1.0) { int i; for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; } //--------------------------------------------------------------------- template<class GammaF> line_profile_aa(double w, const GammaF& gamma_function) : m_subpixel_width(0), m_min_width(1.0), m_smoother_width(1.0) { gamma(gamma_function); width(w); } //--------------------------------------------------------------------- void min_width(double w) { m_min_width = w; } void smoother_width(double w) { m_smoother_width = w; } //--------------------------------------------------------------------- template<class GammaF> void gamma(const GammaF& gamma_function) { int i; for(i = 0; i < aa_scale; i++) { m_gamma[i] = value_type( uround(gamma_function(double(i) / aa_mask) * aa_mask)); } } void width(double w); unsigned profile_size() const { return m_profile.size(); } int subpixel_width() const { return m_subpixel_width; } //--------------------------------------------------------------------- double min_width() const { return m_min_width; } double smoother_width() const { return m_smoother_width; } //--------------------------------------------------------------------- value_type value(int dist) const { return m_profile[dist + subpixel_scale*2]; } private: line_profile_aa(const line_profile_aa&); const line_profile_aa& operator = (const line_profile_aa&); value_type* profile(double w); void set(double center_width, double smoother_width); //--------------------------------------------------------------------- pod_array<value_type> m_profile; value_type m_gamma[aa_scale]; int m_subpixel_width; double m_min_width; double m_smoother_width; }; //======================================================renderer_outline_aa template<class BaseRenderer> class renderer_outline_aa { public: //--------------------------------------------------------------------- typedef BaseRenderer base_ren_type; typedef renderer_outline_aa<base_ren_type> self_type; typedef typename base_ren_type::color_type color_type; //--------------------------------------------------------------------- renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) : m_ren(&ren), m_profile(&prof), m_clip_box(0,0,0,0), m_clipping(false) {} void attach(base_ren_type& ren) { m_ren = &ren; } //--------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //--------------------------------------------------------------------- void profile(const line_profile_aa& prof) { m_profile = &prof; } const line_profile_aa& profile() const { return *m_profile; } //--------------------------------------------------------------------- int subpixel_width() const { return m_profile->subpixel_width(); } //--------------------------------------------------------------------- void reset_clipping() { m_clipping = false; } void clip_box(double x1, double y1, double x2, double y2) { m_clip_box.x1 = line_coord_sat::conv(x1); m_clip_box.y1 = line_coord_sat::conv(y1); m_clip_box.x2 = line_coord_sat::conv(x2); m_clip_box.y2 = line_coord_sat::conv(y2); m_clipping = true; } //--------------------------------------------------------------------- int cover(int d) const { return m_profile->value(d); } //------------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers) { m_ren->blend_solid_hspan(x, y, len, m_color, covers); } //------------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers) { m_ren->blend_solid_vspan(x, y, len, m_color, covers); } //------------------------------------------------------------------------- static bool accurate_join_only() { return false; } //------------------------------------------------------------------------- template<class Cmp> void semidot_hline(Cmp cmp, int xc1, int yc1, int xc2, int yc2, int x1, int y1, int x2) { cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; cover_type* p0 = covers; cover_type* p1 = covers; int x = x1 << line_subpixel_shift; int y = y1 << line_subpixel_shift; int w = subpixel_width(); distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); x += line_subpixel_scale/2; y += line_subpixel_scale/2; int x0 = x1; int dx = x - xc1; int dy = y - yc1; do { int d = int(fast_sqrt(dx*dx + dy*dy)); *p1 = 0; if(cmp(di.dist()) && d <= w) { *p1 = (cover_type)cover(d); } ++p1; dx += line_subpixel_scale; di.inc_x(); } while(++x1 <= x2); m_ren->blend_solid_hspan(x0, y1, unsigned(p1 - p0), color(), p0); } //------------------------------------------------------------------------- template<class Cmp> void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) { if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); if(r < 1) r = 1; ellipse_bresenham_interpolator ei(r, r); int dx = 0; int dy = -r; int dy0 = dy; int dx0 = dx; int x = xc1 >> line_subpixel_shift; int y = yc1 >> line_subpixel_shift; do { dx += ei.dx(); dy += ei.dy(); if(dy != dy0) { semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0); } dx0 = dx; dy0 = dy; ++ei; } while(dy < 0); semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); } //------------------------------------------------------------------------- void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, int xh1, int yh1, int xh2) { if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; cover_type* p0 = covers; cover_type* p1 = covers; int x = xh1 << line_subpixel_shift; int y = yh1 << line_subpixel_shift; int w = subpixel_width(); distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); x += line_subpixel_scale/2; y += line_subpixel_scale/2; int xh0 = xh1; int dx = x - xc; int dy = y - yc; do { int d = int(fast_sqrt(dx*dx + dy*dy)); *p1 = 0; if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) { *p1 = (cover_type)cover(d); } ++p1; dx += line_subpixel_scale; di.inc_x(); } while(++xh1 <= xh2); m_ren->blend_solid_hspan(xh0, yh1, unsigned(p1 - p0), color(), p0); } //------------------------------------------------------------------------- void pie(int xc, int yc, int x1, int y1, int x2, int y2) { int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); if(r < 1) r = 1; ellipse_bresenham_interpolator ei(r, r); int dx = 0; int dy = -r; int dy0 = dy; int dx0 = dx; int x = xc >> line_subpixel_shift; int y = yc >> line_subpixel_shift; do { dx += ei.dx(); dy += ei.dy(); if(dy != dy0) { pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); } dx0 = dx; dy0 = dy; ++ei; } while(dy < 0); pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); } //------------------------------------------------------------------------- void line0_no_clip(const line_parameters& lp) { if(lp.len > line_max_length) { line_parameters lp1, lp2; lp.divide(lp1, lp2); line0_no_clip(lp1); line0_no_clip(lp2); return; } line_interpolator_aa0<self_type> li(*this, lp); if(li.count()) { if(li.vertical()) { while(li.step_ver()); } else { while(li.step_hor()); } } } //------------------------------------------------------------------------- void line0(const line_parameters& lp) { if(m_clipping) { int x1 = lp.x1; int y1 = lp.y1; int x2 = lp.x2; int y2 = lp.y2; unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); if((flags & 4) == 0) { if(flags) { line_parameters lp2(x1, y1, x2, y2, uround(calc_distance(x1, y1, x2, y2))); line0_no_clip(lp2); } else { line0_no_clip(lp); } } } else { line0_no_clip(lp); } } //------------------------------------------------------------------------- void line1_no_clip(const line_parameters& lp, int sx, int sy) { if(lp.len > line_max_length) { line_parameters lp1, lp2; lp.divide(lp1, lp2); line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); return; } fix_degenerate_bisectrix_start(lp, &sx, &sy); line_interpolator_aa1<self_type> li(*this, lp, sx, sy); if(li.vertical()) { while(li.step_ver()); } else { while(li.step_hor()); } } //------------------------------------------------------------------------- void line1(const line_parameters& lp, int sx, int sy) { if(m_clipping) { int x1 = lp.x1; int y1 = lp.y1; int x2 = lp.x2; int y2 = lp.y2; unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); if((flags & 4) == 0) { if(flags) { line_parameters lp2(x1, y1, x2, y2, uround(calc_distance(x1, y1, x2, y2))); if(flags & 1) { sx = x1 + (y2 - y1); sy = y1 - (x2 - x1); } else { while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) { sx = (lp.x1 + sx) >> 1; sy = (lp.y1 + sy) >> 1; } } line1_no_clip(lp2, sx, sy); } else { line1_no_clip(lp, sx, sy); } } } else { line1_no_clip(lp, sx, sy); } } //------------------------------------------------------------------------- void line2_no_clip(const line_parameters& lp, int ex, int ey) { if(lp.len > line_max_length) { line_parameters lp1, lp2; lp.divide(lp1, lp2); line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); return; } fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_aa2<self_type> li(*this, lp, ex, ey); if(li.vertical()) { while(li.step_ver()); } else { while(li.step_hor()); } } //------------------------------------------------------------------------- void line2(const line_parameters& lp, int ex, int ey) { if(m_clipping) { int x1 = lp.x1; int y1 = lp.y1; int x2 = lp.x2; int y2 = lp.y2; unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); if((flags & 4) == 0) { if(flags) { line_parameters lp2(x1, y1, x2, y2, uround(calc_distance(x1, y1, x2, y2))); if(flags & 2) { ex = x2 + (y2 - y1); ey = y2 - (x2 - x1); } else { while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) { ex = (lp.x2 + ex) >> 1; ey = (lp.y2 + ey) >> 1; } } line2_no_clip(lp2, ex, ey); } else { line2_no_clip(lp, ex, ey); } } } else { line2_no_clip(lp, ex, ey); } } //------------------------------------------------------------------------- void line3_no_clip(const line_parameters& lp, int sx, int sy, int ex, int ey) { if(lp.len > line_max_length) { line_parameters lp1, lp2; lp.divide(lp1, lp2); int mx = lp1.x2 + (lp1.y2 - lp1.y1); int my = lp1.y2 - (lp1.x2 - lp1.x1); line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); return; } fix_degenerate_bisectrix_start(lp, &sx, &sy); fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey); if(li.vertical()) { while(li.step_ver()); } else { while(li.step_hor()); } } //------------------------------------------------------------------------- void line3(const line_parameters& lp, int sx, int sy, int ex, int ey) { if(m_clipping) { int x1 = lp.x1; int y1 = lp.y1; int x2 = lp.x2; int y2 = lp.y2; unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); if((flags & 4) == 0) { if(flags) { line_parameters lp2(x1, y1, x2, y2, uround(calc_distance(x1, y1, x2, y2))); if(flags & 1) { sx = x1 + (y2 - y1); sy = y1 - (x2 - x1); } else { while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) { sx = (lp.x1 + sx) >> 1; sy = (lp.y1 + sy) >> 1; } } if(flags & 2) { ex = x2 + (y2 - y1); ey = y2 - (x2 - x1); } else { while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) { ex = (lp.x2 + ex) >> 1; ey = (lp.y2 + ey) >> 1; } } line3_no_clip(lp2, sx, sy, ex, ey); } else { line3_no_clip(lp, sx, sy, ex, ey); } } } else { line3_no_clip(lp, sx, sy, ex, ey); } } private: base_ren_type* m_ren; const line_profile_aa* m_profile; color_type m_color; rect_i m_clip_box; bool m_clipping; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_alpha_mask_u8.h�������������������������������������������0000644�0024617�0000144�00000044117�12261257215�023200� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // scanline_u8 class // //---------------------------------------------------------------------------- #ifndef AGG_ALPHA_MASK_U8_INCLUDED #define AGG_ALPHA_MASK_U8_INCLUDED #include <string.h> #include "agg_basics.h" #include "agg_rendering_buffer.h" namespace mapserver { //===================================================one_component_mask_u8 struct one_component_mask_u8 { static unsigned calculate(const int8u* p) { return *p; } }; //=====================================================rgb_to_gray_mask_u8 template<unsigned R, unsigned G, unsigned B> struct rgb_to_gray_mask_u8 { static unsigned calculate(const int8u* p) { return (p[R]*77 + p[G]*150 + p[B]*29) >> 8; } }; //==========================================================alpha_mask_u8 template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> class alpha_mask_u8 { public: typedef int8u cover_type; typedef alpha_mask_u8<Step, Offset, MaskF> self_type; enum cover_scale_e { cover_shift = 8, cover_none = 0, cover_full = 255 }; alpha_mask_u8() : m_rbuf(0) {} explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } MaskF& mask_function() { return m_mask_function; } const MaskF& mask_function() const { return m_mask_function; } //-------------------------------------------------------------------- cover_type pixel(int x, int y) const { if(x >= 0 && y >= 0 && x < (int)m_rbuf->width() && y < (int)m_rbuf->height()) { return (cover_type)m_mask_function.calculate( m_rbuf->row_ptr(y) + x * Step + Offset); } return 0; } //-------------------------------------------------------------------- cover_type combine_pixel(int x, int y, cover_type val) const { if(x >= 0 && y >= 0 && x < (int)m_rbuf->width() && y < (int)m_rbuf->height()) { return (cover_type)((cover_full + val * m_mask_function.calculate( m_rbuf->row_ptr(y) + x * Step + Offset)) >> cover_shift); } return 0; } //-------------------------------------------------------------------- void fill_hspan(int x, int y, cover_type* dst, int num_pix) const { int xmax = m_rbuf->width() - 1; int ymax = m_rbuf->height() - 1; int count = num_pix; cover_type* covers = dst; if(y < 0 || y > ymax) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } if(x < 0) { count += x; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers, 0, -x * sizeof(cover_type)); covers -= x; x = 0; } if(x + count > xmax) { int rest = x + count - xmax - 1; count -= rest; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers + count, 0, rest * sizeof(cover_type)); } const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers++ = (cover_type)m_mask_function.calculate(mask); mask += Step; } while(--count); } //-------------------------------------------------------------------- void combine_hspan(int x, int y, cover_type* dst, int num_pix) const { int xmax = m_rbuf->width() - 1; int ymax = m_rbuf->height() - 1; int count = num_pix; cover_type* covers = dst; if(y < 0 || y > ymax) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } if(x < 0) { count += x; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers, 0, -x * sizeof(cover_type)); covers -= x; x = 0; } if(x + count > xmax) { int rest = x + count - xmax - 1; count -= rest; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers + count, 0, rest * sizeof(cover_type)); } const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); ++covers; mask += Step; } while(--count); } //-------------------------------------------------------------------- void fill_vspan(int x, int y, cover_type* dst, int num_pix) const { int xmax = m_rbuf->width() - 1; int ymax = m_rbuf->height() - 1; int count = num_pix; cover_type* covers = dst; if(x < 0 || x > xmax) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } if(y < 0) { count += y; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers, 0, -y * sizeof(cover_type)); covers -= y; y = 0; } if(y + count > ymax) { int rest = y + count - ymax - 1; count -= rest; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers + count, 0, rest * sizeof(cover_type)); } const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers++ = (cover_type)m_mask_function.calculate(mask); mask += m_rbuf->stride(); } while(--count); } //-------------------------------------------------------------------- void combine_vspan(int x, int y, cover_type* dst, int num_pix) const { int xmax = m_rbuf->width() - 1; int ymax = m_rbuf->height() - 1; int count = num_pix; cover_type* covers = dst; if(x < 0 || x > xmax) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } if(y < 0) { count += y; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers, 0, -y * sizeof(cover_type)); covers -= y; y = 0; } if(y + count > ymax) { int rest = y + count - ymax - 1; count -= rest; if(count <= 0) { memset(dst, 0, num_pix * sizeof(cover_type)); return; } memset(covers + count, 0, rest * sizeof(cover_type)); } const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); ++covers; mask += m_rbuf->stride(); } while(--count); } private: alpha_mask_u8(const self_type&); const self_type& operator = (const self_type&); rendering_buffer* m_rbuf; MaskF m_mask_function; }; typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8 typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray //==========================================================amask_no_clip_u8 template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> class amask_no_clip_u8 { public: typedef int8u cover_type; typedef amask_no_clip_u8<Step, Offset, MaskF> self_type; enum cover_scale_e { cover_shift = 8, cover_none = 0, cover_full = 255 }; amask_no_clip_u8() : m_rbuf(0) {} explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } MaskF& mask_function() { return m_mask_function; } const MaskF& mask_function() const { return m_mask_function; } //-------------------------------------------------------------------- cover_type pixel(int x, int y) const { return (cover_type)m_mask_function.calculate( m_rbuf->row_ptr(y) + x * Step + Offset); } //-------------------------------------------------------------------- cover_type combine_pixel(int x, int y, cover_type val) const { return (cover_type)((cover_full + val * m_mask_function.calculate( m_rbuf->row_ptr(y) + x * Step + Offset)) >> cover_shift); } //-------------------------------------------------------------------- void fill_hspan(int x, int y, cover_type* dst, int num_pix) const { const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst++ = (cover_type)m_mask_function.calculate(mask); mask += Step; } while(--num_pix); } //-------------------------------------------------------------------- void combine_hspan(int x, int y, cover_type* dst, int num_pix) const { const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst = (cover_type)((cover_full + (*dst) * m_mask_function.calculate(mask)) >> cover_shift); ++dst; mask += Step; } while(--num_pix); } //-------------------------------------------------------------------- void fill_vspan(int x, int y, cover_type* dst, int num_pix) const { const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst++ = (cover_type)m_mask_function.calculate(mask); mask += m_rbuf->stride(); } while(--num_pix); } //-------------------------------------------------------------------- void combine_vspan(int x, int y, cover_type* dst, int num_pix) const { const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst = (cover_type)((cover_full + (*dst) * m_mask_function.calculate(mask)) >> cover_shift); ++dst; mask += m_rbuf->stride(); } while(--num_pix); } private: amask_no_clip_u8(const self_type&); const self_type& operator = (const self_type&); rendering_buffer* m_rbuf; MaskF m_mask_function; }; typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8 typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rasterizer_outline_aa.h�����������������������������������0000644�0024617�0000144�00000050376�12261257215�025062� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED #define AGG_RASTERIZER_OUTLINE_AA_INCLUDED #include "agg_basics.h" #include "agg_line_aa_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { //------------------------------------------------------------------------- inline bool cmp_dist_start(int d) { return d > 0; } inline bool cmp_dist_end(int d) { return d <= 0; } //-----------------------------------------------------------line_aa_vertex // Vertex (x, y) with the distance to the next one. The last vertex has // the distance between the last and the first points struct line_aa_vertex { int x; int y; int len; line_aa_vertex() {} line_aa_vertex(int x_, int y_) : x(x_), y(y_), len(0) { } bool operator () (const line_aa_vertex& val) { double dx = val.x - x; double dy = val.y - y; return (len = uround(sqrt(dx * dx + dy * dy))) > (line_subpixel_scale + line_subpixel_scale / 2); } }; //----------------------------------------------------------outline_aa_join_e enum outline_aa_join_e { outline_no_join, //-----outline_no_join outline_miter_join, //-----outline_miter_join outline_round_join, //-----outline_round_join outline_miter_accurate_join //-----outline_accurate_join }; //=======================================================rasterizer_outline_aa template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa { private: //------------------------------------------------------------------------ struct draw_vars { unsigned idx; int x1, y1, x2, y2; line_parameters curr, next; int lcurr, lnext; int xb1, yb1, xb2, yb2; unsigned flags; }; void draw(draw_vars& dv, unsigned start, unsigned end); public: typedef line_aa_vertex vertex_type; typedef vertex_sequence<vertex_type, 6> vertex_storage_type; explicit rasterizer_outline_aa(Renderer& ren) : m_ren(&ren), m_line_join(ren.accurate_join_only() ? outline_miter_accurate_join : outline_round_join), m_round_cap(false), m_start_x(0), m_start_y(0) {} void attach(Renderer& ren) { m_ren = &ren; } //------------------------------------------------------------------------ void line_join(outline_aa_join_e join) { m_line_join = m_ren->accurate_join_only() ? outline_miter_accurate_join : join; } bool line_join() const { return m_line_join; } //------------------------------------------------------------------------ void round_cap(bool v) { m_round_cap = v; } bool round_cap() const { return m_round_cap; } //------------------------------------------------------------------------ void move_to(int x, int y) { m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y)); } //------------------------------------------------------------------------ void line_to(int x, int y) { m_src_vertices.add(vertex_type(x, y)); } //------------------------------------------------------------------------ void move_to_d(double x, double y) { move_to(Coord::conv(x), Coord::conv(y)); } //------------------------------------------------------------------------ void line_to_d(double x, double y) { line_to(Coord::conv(x), Coord::conv(y)); } //------------------------------------------------------------------------ void render(bool close_polygon); //------------------------------------------------------------------------ void add_vertex(double x, double y, unsigned cmd) { if(is_move_to(cmd)) { render(false); move_to_d(x, y); } else { if(is_end_poly(cmd)) { render(is_closed(cmd)); if(is_closed(cmd)) { move_to(m_start_x, m_start_y); } } else { line_to_d(x, y); } } } //------------------------------------------------------------------------ template<class VertexSource> void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); } render(false); } //------------------------------------------------------------------------ template<class VertexSource, class ColorStorage, class PathId> void render_all_paths(VertexSource& vs, const ColorStorage& colors, const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { m_ren->color(colors[i]); add_path(vs, path_id[i]); } } //------------------------------------------------------------------------ template<class Ctrl> void render_ctrl(Ctrl& c) { unsigned i; for(i = 0; i < c.num_paths(); i++) { m_ren->color(c.color(i)); add_path(c, i); } } private: rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&); const rasterizer_outline_aa<Renderer, Coord>& operator = (const rasterizer_outline_aa<Renderer, Coord>&); Renderer* m_ren; vertex_storage_type m_src_vertices; outline_aa_join_e m_line_join; bool m_round_cap; int m_start_x; int m_start_y; }; //---------------------------------------------------------------------------- template<class Renderer, class Coord> void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, unsigned start, unsigned end) { unsigned i; const vertex_storage_type::value_type* v; for(i = start; i < end; i++) { if(m_line_join == outline_round_join) { dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1); dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1); } switch(dv.flags) { case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break; case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break; case 3: m_ren->line0(dv.curr); break; } if(m_line_join == outline_round_join && (dv.flags & 2) == 0) { m_ren->pie(dv.curr.x2, dv.curr.y2, dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), dv.curr.x2 + (dv.next.y2 - dv.next.y1), dv.curr.y2 - (dv.next.x2 - dv.next.x1)); } dv.x1 = dv.x2; dv.y1 = dv.y2; dv.lcurr = dv.lnext; dv.lnext = m_src_vertices[dv.idx].len; ++dv.idx; if(dv.idx >= m_src_vertices.size()) dv.idx = 0; v = &m_src_vertices[dv.idx]; dv.x2 = v->x; dv.y2 = v->y; dv.curr = dv.next; dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); dv.xb1 = dv.xb2; dv.yb1 = dv.yb2; switch(m_line_join) { case outline_no_join: dv.flags = 3; break; case outline_miter_join: dv.flags >>= 1; dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); if((dv.flags & 2) == 0) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } break; case outline_round_join: dv.flags >>= 1; dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); break; case outline_miter_accurate_join: dv.flags = 0; bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); break; } } } //---------------------------------------------------------------------------- template<class Renderer, class Coord> void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon) { m_src_vertices.close(close_polygon); draw_vars dv; const vertex_storage_type::value_type* v; int x1; int y1; int x2; int y2; int lprev; if(close_polygon) { if(m_src_vertices.size() >= 3) { dv.idx = 2; v = &m_src_vertices[m_src_vertices.size() - 1]; x1 = v->x; y1 = v->y; lprev = v->len; v = &m_src_vertices[0]; x2 = v->x; y2 = v->y; dv.lcurr = v->len; line_parameters prev(x1, y1, x2, y2, lprev); v = &m_src_vertices[1]; dv.x1 = v->x; dv.y1 = v->y; dv.lnext = v->len; dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); v = &m_src_vertices[dv.idx]; dv.x2 = v->x; dv.y2 = v->y; dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); dv.xb1 = 0; dv.yb1 = 0; dv.xb2 = 0; dv.yb2 = 0; switch(m_line_join) { case outline_no_join: dv.flags = 3; break; case outline_miter_join: case outline_round_join: dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); break; case outline_miter_accurate_join: dv.flags = 0; break; } if((dv.flags & 1) == 0 && m_line_join != outline_round_join) { bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); } if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } draw(dv, 0, m_src_vertices.size()); } } else { switch(m_src_vertices.size()) { case 0: case 1: break; case 2: { v = &m_src_vertices[0]; x1 = v->x; y1 = v->y; lprev = v->len; v = &m_src_vertices[1]; x2 = v->x; y2 = v->y; line_parameters lp(x1, y1, x2, y2, lprev); if(m_round_cap) { m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); } m_ren->line3(lp, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1)); if(m_round_cap) { m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); } } break; case 3: { int x3, y3; int lnext; v = &m_src_vertices[0]; x1 = v->x; y1 = v->y; lprev = v->len; v = &m_src_vertices[1]; x2 = v->x; y2 = v->y; lnext = v->len; v = &m_src_vertices[2]; x3 = v->x; y3 = v->y; line_parameters lp1(x1, y1, x2, y2, lprev); line_parameters lp2(x2, y2, x3, y3, lnext); if(m_round_cap) { m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); } if(m_line_join == outline_round_join) { m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1)); m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), x2 + (y3 - y2), y2 - (x3 - x2)); m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), x3 + (y3 - y2), y3 - (x3 - x2)); } else { bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), dv.xb1, dv.yb1); m_ren->line3(lp2, dv.xb1, dv.yb1, x3 + (y3 - y2), y3 - (x3 - x2)); } if(m_round_cap) { m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); } } break; default: { dv.idx = 3; v = &m_src_vertices[0]; x1 = v->x; y1 = v->y; lprev = v->len; v = &m_src_vertices[1]; x2 = v->x; y2 = v->y; dv.lcurr = v->len; line_parameters prev(x1, y1, x2, y2, lprev); v = &m_src_vertices[2]; dv.x1 = v->x; dv.y1 = v->y; dv.lnext = v->len; dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); v = &m_src_vertices[dv.idx]; dv.x2 = v->x; dv.y2 = v->y; dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); dv.xb1 = 0; dv.yb1 = 0; dv.xb2 = 0; dv.yb2 = 0; switch(m_line_join) { case outline_no_join: dv.flags = 3; break; case outline_miter_join: case outline_round_join: dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); break; case outline_miter_accurate_join: dv.flags = 0; break; } if(m_round_cap) { m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); } if((dv.flags & 1) == 0) { if(m_line_join == outline_round_join) { m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1)); m_ren->pie(prev.x2, prev.y2, x2 + (y2 - y1), y2 - (x2 - x1), dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); } else { bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), dv.xb1, dv.yb1); } } else { m_ren->line1(prev, x1 + (y2 - y1), y1 - (x2 - x1)); } if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } draw(dv, 1, m_src_vertices.size() - 2); if((dv.flags & 1) == 0) { if(m_line_join == outline_round_join) { m_ren->line3(dv.curr, dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } else { m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } } else { m_ren->line2(dv.curr, dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } if(m_round_cap) { m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); } } break; } } m_src_vertices.remove_all(); } } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_pattern_rgb.h����������������������������������������0000644�0024617�0000144�00000006567�12261257215�024023� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_PATTERN_RGB_INCLUDED #define AGG_SPAN_PATTERN_RGB_INCLUDED #include "agg_basics.h" namespace mapserver { //========================================================span_pattern_rgb template<class Source> class span_pattern_rgb { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; //-------------------------------------------------------------------- span_pattern_rgb() {} span_pattern_rgb(source_type& src, unsigned offset_x, unsigned offset_y) : m_src(&src), m_offset_x(offset_x), m_offset_y(offset_y), m_alpha(color_type::base_mask) {} //-------------------------------------------------------------------- void attach(source_type& v) { m_src = &v; } source_type& source() { return *m_src; } const source_type& source() const { return *m_src; } //-------------------------------------------------------------------- void offset_x(unsigned v) { m_offset_x = v; } void offset_y(unsigned v) { m_offset_y = v; } unsigned offset_x() const { return m_offset_x; } unsigned offset_y() const { return m_offset_y; } void alpha(value_type v) { m_alpha = v; } value_type alpha() const { return m_alpha; } //-------------------------------------------------------------------- void prepare() {} void generate(color_type* span, int x, int y, unsigned len) { x += m_offset_x; y += m_offset_y; const value_type* p = (const value_type*)m_src->span(x, y, len); do { span->r = p[order_type::R]; span->g = p[order_type::G]; span->b = p[order_type::B]; span->a = m_alpha; p = m_src->next_x(); ++span; } while(--len); } private: source_type* m_src; unsigned m_offset_x; unsigned m_offset_y; value_type m_alpha; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_bspline.h�������������������������������������������������0000644�0024617�0000144�00000005126�12261257215�022115� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class bspline // //---------------------------------------------------------------------------- #ifndef AGG_BSPLINE_INCLUDED #define AGG_BSPLINE_INCLUDED #include "agg_array.h" namespace mapserver { //----------------------------------------------------------------bspline // A very simple class of Bi-cubic Spline interpolation. // First call init(num, x[], y[]) where num - number of source points, // x, y - arrays of X and Y values respectively. Here Y must be a function // of X. It means that all the X-coordinates must be arranged in the ascending // order. // Then call get(x) that calculates a value Y for the respective X. // The class supports extrapolation, i.e. you can call get(x) where x is // outside the given with init() X-range. Extrapolation is a simple linear // function. // // See Implementation agg_bspline.cpp //------------------------------------------------------------------------ class bspline { public: bspline(); bspline(int num); bspline(int num, const double* x, const double* y); void init(int num); void add_point(double x, double y); void prepare(); void init(int num, const double* x, const double* y); double get(double x) const; double get_stateful(double x) const; private: bspline(const bspline&); const bspline& operator = (const bspline&); static void bsearch(int n, const double *x, double x0, int *i); double extrapolation_left(double x) const; double extrapolation_right(double x) const; double interpolation(double x, int i) const; int m_max; int m_num; double* m_x; double* m_y; pod_array<double> m_am; mutable int m_last_idx; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_math.h����������������������������������������������������0000644�0024617�0000144�00000034764�12261257215�021424� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // Bessel function (besj) was adapted for use in AGG library by Andy Wilk // Contact: castor.vulgaris@gmail.com //---------------------------------------------------------------------------- #ifndef AGG_MATH_INCLUDED #define AGG_MATH_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { //------------------------------------------------------vertex_dist_epsilon // Coinciding points maximal distance (Epsilon) const double vertex_dist_epsilon = 1e-14; //-----------------------------------------------------intersection_epsilon // See calc_intersection const double intersection_epsilon = 1.0e-30; //------------------------------------------------------------cross_product AGG_INLINE double cross_product(double x1, double y1, double x2, double y2, double x, double y) { return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); } //--------------------------------------------------------point_in_triangle AGG_INLINE bool point_in_triangle(double x1, double y1, double x2, double y2, double x3, double y3, double x, double y) { bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0; bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0; bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0; return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; } //-----------------------------------------------------------calc_distance AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) { double dx = x2-x1; double dy = y2-y1; return sqrt(dx * dx + dy * dy); } //--------------------------------------------------------calc_sq_distance AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) { double dx = x2-x1; double dy = y2-y1; return dx * dx + dy * dy; } //------------------------------------------------calc_line_point_distance AGG_INLINE double calc_line_point_distance(double x1, double y1, double x2, double y2, double x, double y) { double dx = x2-x1; double dy = y2-y1; double d = sqrt(dx * dx + dy * dy); if(d < vertex_dist_epsilon) { return calc_distance(x1, y1, x, y); } return ((x - x2) * dy - (y - y2) * dx) / d; } //-------------------------------------------------------calc_line_point_u AGG_INLINE double calc_segment_point_u(double x1, double y1, double x2, double y2, double x, double y) { double dx = x2 - x1; double dy = y2 - y1; if(dx == 0 && dy == 0) { return 0; } double pdx = x - x1; double pdy = y - y1; return (pdx * dx + pdy * dy) / (dx * dx + dy * dy); } //---------------------------------------------calc_line_point_sq_distance AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, double x2, double y2, double x, double y, double u) { if(u <= 0) { return calc_sq_distance(x, y, x1, y1); } else if(u >= 1) { return calc_sq_distance(x, y, x2, y2); } return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1)); } //---------------------------------------------calc_line_point_sq_distance AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, double x2, double y2, double x, double y) { return calc_segment_point_sq_distance( x1, y1, x2, y2, x, y, calc_segment_point_u(x1, y1, x2, y2, x, y)); } //-------------------------------------------------------calc_intersection AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, double cx, double cy, double dx, double dy, double* x, double* y) { double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy); double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx); if(fabs(den) < intersection_epsilon) return false; double r = num / den; *x = ax + r * (bx-ax); *y = ay + r * (by-ay); return true; } //-----------------------------------------------------intersection_exists AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { // It's less expensive but you can't control the // boundary conditions: Less or LessEqual double dx1 = x2 - x1; double dy1 = y2 - y1; double dx2 = x4 - x3; double dy2 = y4 - y3; return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) && ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) != ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0); // It's is more expensive but more flexible // in terms of boundary conditions. //-------------------- //double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3); //if(fabs(den) < intersection_epsilon) return false; //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3); //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3); //double ua = nom1 / den; //double ub = nom2 / den; //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0; } //--------------------------------------------------------calc_orthogonal AGG_INLINE void calc_orthogonal(double thickness, double x1, double y1, double x2, double y2, double* x, double* y) { double dx = x2 - x1; double dy = y2 - y1; double d = sqrt(dx*dx + dy*dy); *x = thickness * dy / d; *y = -thickness * dx / d; } //--------------------------------------------------------dilate_triangle AGG_INLINE void dilate_triangle(double x1, double y1, double x2, double y2, double x3, double y3, double *x, double* y, double d) { double dx1=0.0; double dy1=0.0; double dx2=0.0; double dy2=0.0; double dx3=0.0; double dy3=0.0; double loc = cross_product(x1, y1, x2, y2, x3, y3); if(fabs(loc) > intersection_epsilon) { if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) { d = -d; } calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1); calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2); calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3); } *x++ = x1 + dx1; *y++ = y1 + dy1; *x++ = x2 + dx1; *y++ = y2 + dy1; *x++ = x2 + dx2; *y++ = y2 + dy2; *x++ = x3 + dx2; *y++ = y3 + dy2; *x++ = x3 + dx3; *y++ = y3 + dy3; *x++ = x1 + dx3; *y++ = y1 + dy3; } //------------------------------------------------------calc_triangle_area AGG_INLINE double calc_triangle_area(double x1, double y1, double x2, double y2, double x3, double y3) { return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5; } //-------------------------------------------------------calc_polygon_area template<class Storage> double calc_polygon_area(const Storage& st) { unsigned i; double sum = 0.0; double x = st[0].x; double y = st[0].y; double xs = x; double ys = y; for(i = 1; i < st.size(); i++) { const typename Storage::value_type& v = st[i]; sum += x * v.y - y * v.x; x = v.x; y = v.y; } return (sum + x * ys - y * xs) * 0.5; } //------------------------------------------------------------------------ // Tables for fast sqrt extern int16u g_sqrt_table[1024]; extern int8 g_elder_bit_table[256]; //---------------------------------------------------------------fast_sqrt //Fast integer Sqrt - really fast: no cycles, divisions or multiplications #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4035) //Disable warning "no return value" #endif AGG_INLINE unsigned fast_sqrt(unsigned val) { #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) //For Ix86 family processors this assembler code is used. //The key command here is bsr - determination the number of the most //significant bit of the value. For other processors //(and maybe compilers) the pure C "#else" section is used. __asm { mov ebx, val mov edx, 11 bsr ecx, ebx sub ecx, 9 jle less_than_9_bits shr ecx, 1 adc ecx, 0 sub edx, ecx shl ecx, 1 shr ebx, cl less_than_9_bits: xor eax, eax mov ax, g_sqrt_table[ebx*2] mov ecx, edx shr eax, cl } #else //This code is actually pure C and portable to most //arcitectures including 64bit ones. unsigned t = val; int bit=0; unsigned shift = 11; //The following piece of code is just an emulation of the //Ix86 assembler command "bsr" (see above). However on old //Intels (like Intel MMX 233MHz) this code is about twice //faster (sic!) then just one "bsr". On PIII and PIV the //bsr is optimized quite well. bit = t >> 24; if(bit) { bit = g_elder_bit_table[bit] + 24; } else { bit = (t >> 16) & 0xFF; if(bit) { bit = g_elder_bit_table[bit] + 16; } else { bit = (t >> 8) & 0xFF; if(bit) { bit = g_elder_bit_table[bit] + 8; } else { bit = g_elder_bit_table[t]; } } } //This code calculates the sqrt. bit -= 9; if(bit > 0) { bit = (bit >> 1) + (bit & 1); shift -= bit; val >>= (bit << 1); } return g_sqrt_table[val] >> shift; #endif } #if defined(_MSC_VER) #pragma warning(pop) #endif //--------------------------------------------------------------------besj // Function BESJ calculates Bessel function of first kind of order n // Arguments: // n - an integer (>=0), the order // x - value at which the Bessel function is required //-------------------- // C++ Mathematical Library // Convereted from equivalent FORTRAN library // Converetd by Gareth Walker for use by course 392 computational project // All functions tested and yield the same results as the corresponding // FORTRAN versions. // // If you have any problems using these functions please report them to // M.Muldoon@UMIST.ac.uk // // Documentation available on the web // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html // Version 1.0 8/98 // 29 October, 1999 //-------------------- // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com) //------------------------------------------------------------------------ inline double besj(double x, int n) { if(n < 0) { return 0; } double d = 1E-6; double b = 0; if(fabs(x) <= d) { if(n != 0) return 0; return 1; } double b1 = 0; // b1 is the value from the previous iteration // Set up a starting order for recurrence int m1 = (int)fabs(x) + 6; if(fabs(x) > 5) { m1 = (int)(fabs(1.4 * x + 60 / x)); } int m2 = (int)(n + 2 + fabs(x) / 4); if (m1 > m2) { m2 = m1; } // Apply recurrence down from curent max order for(;;) { double c3 = 0; double c2 = 1E-30; double c4 = 0; int m8 = 1; if (m2 / 2 * 2 == m2) { m8 = -1; } int imax = m2 - 2; for (int i = 1; i <= imax; i++) { double c6 = 2 * (m2 - i) * c2 / x - c3; c3 = c2; c2 = c6; if(m2 - i - 1 == n) { b = c6; } m8 = -1 * m8; if (m8 > 0) { c4 = c4 + 2 * c6; } } double c6 = 2 * c2 / x - c3; if(n == 0) { b = c6; } c4 += c6; b /= c4; if(fabs(b - b1) < d) { return b; } b1 = b; m2 += 3; } } } #endif ������������mapserver-6.4.1/renderers/agg/include/agg_bezier_arc.h����������������������������������������������0000644�0024617�0000144�00000013225�12261257215�022565� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., // 4, 7, 10, or 13 vertices. // //---------------------------------------------------------------------------- #ifndef AGG_BEZIER_ARC_INCLUDED #define AGG_BEZIER_ARC_INCLUDED #include "agg_conv_transform.h" namespace mapserver { //----------------------------------------------------------------------- void arc_to_bezier(double cx, double cy, double rx, double ry, double start_angle, double sweep_angle, double* curve); //==============================================================bezier_arc // // See implemantaion agg_bezier_arc.cpp // class bezier_arc { public: //-------------------------------------------------------------------- bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {} bezier_arc(double x, double y, double rx, double ry, double start_angle, double sweep_angle) { init(x, y, rx, ry, start_angle, sweep_angle); } //-------------------------------------------------------------------- void init(double x, double y, double rx, double ry, double start_angle, double sweep_angle); //-------------------------------------------------------------------- void rewind(unsigned) { m_vertex = 0; } //-------------------------------------------------------------------- unsigned vertex(double* x, double* y) { if(m_vertex >= m_num_vertices) return path_cmd_stop; *x = m_vertices[m_vertex]; *y = m_vertices[m_vertex + 1]; m_vertex += 2; return (m_vertex == 2) ? path_cmd_move_to : m_cmd; } // Supplemantary functions. num_vertices() actually returns doubled // number of vertices. That is, for 1 vertex it returns 2. //-------------------------------------------------------------------- unsigned num_vertices() const { return m_num_vertices; } const double* vertices() const { return m_vertices; } double* vertices() { return m_vertices; } private: unsigned m_vertex; unsigned m_num_vertices; double m_vertices[26]; unsigned m_cmd; }; //==========================================================bezier_arc_svg // Compute an SVG-style bezier arc. // // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and // orientation of the ellipse are defined by two radii (rx, ry) // and an x-axis-rotation, which indicates how the ellipse as a whole // is rotated relative to the current coordinate system. The center // (cx, cy) of the ellipse is calculated automatically to satisfy the // constraints imposed by the other parameters. // large-arc-flag and sweep-flag contribute to the automatic calculations // and help determine how the arc is drawn. class bezier_arc_svg { public: //-------------------------------------------------------------------- bezier_arc_svg() : m_arc(), m_radii_ok(false) {} bezier_arc_svg(double x1, double y1, double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x2, double y2) : m_arc(), m_radii_ok(false) { init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2); } //-------------------------------------------------------------------- void init(double x1, double y1, double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x2, double y2); //-------------------------------------------------------------------- bool radii_ok() const { return m_radii_ok; } //-------------------------------------------------------------------- void rewind(unsigned) { m_arc.rewind(0); } //-------------------------------------------------------------------- unsigned vertex(double* x, double* y) { return m_arc.vertex(x, y); } // Supplemantary functions. num_vertices() actually returns doubled // number of vertices. That is, for 1 vertex it returns 2. //-------------------------------------------------------------------- unsigned num_vertices() const { return m_arc.num_vertices(); } const double* vertices() const { return m_arc.vertices(); } double* vertices() { return m_arc.vertices(); } private: bezier_arc m_arc; bool m_radii_ok; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_gouraud_gray.h���������������������������������������0000644�0024617�0000144�00000020132�12261257215�024164� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED #define AGG_SPAN_GOURAUD_GRAY_INCLUDED #include "agg_basics.h" #include "agg_color_gray.h" #include "agg_dda_line.h" #include "agg_span_gouraud.h" namespace mapserver { //=======================================================span_gouraud_gray template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT> { public: typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef span_gouraud<color_type> base_type; typedef typename base_type::coord_type coord_type; enum subpixel_scale_e { subpixel_shift = 4, subpixel_scale = 1 << subpixel_shift }; private: //-------------------------------------------------------------------- struct gray_calc { void init(const coord_type& c1, const coord_type& c2) { m_x1 = c1.x - 0.5; m_y1 = c1.y - 0.5; m_dx = c2.x - c1.x; double dy = c2.y - c1.y; m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy; m_v1 = c1.color.v; m_a1 = c1.color.a; m_dv = c2.color.v - m_v1; m_da = c2.color.a - m_a1; } void calc(double y) { double k = (y - m_y1) * m_1dy; if(k < 0.0) k = 0.0; if(k > 1.0) k = 1.0; m_v = m_v1 + iround(m_dv * k); m_a = m_a1 + iround(m_da * k); m_x = iround((m_x1 + m_dx * k) * subpixel_scale); } double m_x1; double m_y1; double m_dx; double m_1dy; int m_v1; int m_a1; int m_dv; int m_da; int m_v; int m_a; int m_x; }; public: //-------------------------------------------------------------------- span_gouraud_gray() {} span_gouraud_gray(const color_type& c1, const color_type& c2, const color_type& c3, double x1, double y1, double x2, double y2, double x3, double y3, double d = 0) : base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) {} //-------------------------------------------------------------------- void prepare() { coord_type coord[3]; base_type::arrange_vertices(coord); m_y2 = int(coord[1].y); m_swap = cross_product(coord[0].x, coord[0].y, coord[2].x, coord[2].y, coord[1].x, coord[1].y) < 0.0; m_c1.init(coord[0], coord[2]); m_c2.init(coord[0], coord[1]); m_c3.init(coord[1], coord[2]); } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { m_c1.calc(y); const gray_calc* pc1 = &m_c1; const gray_calc* pc2 = &m_c2; if(y < m_y2) { // Bottom part of the triangle (first subtriangle) //------------------------- m_c2.calc(y + m_c2.m_1dy); } else { // Upper part (second subtriangle) //------------------------- m_c3.calc(y - m_c3.m_1dy); pc2 = &m_c3; } if(m_swap) { // It means that the triangle is oriented clockwise, // so that we need to swap the controlling structures //------------------------- const gray_calc* t = pc2; pc2 = pc1; pc1 = t; } // Get the horizontal length with subpixel accuracy // and protect it from division by zero //------------------------- int nlen = abs(pc2->m_x - pc1->m_x); if(nlen <= 0) nlen = 1; dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen); dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); // Calculate the starting point of the gradient with subpixel // accuracy and correct (roll back) the interpolators. // This operation will also clip the beginning of the span // if necessary. //------------------------- int start = pc1->m_x - (x << subpixel_shift); v -= start; a -= start; nlen += start; int vv, va; enum lim_e { lim = color_type::base_mask }; // Beginning part of the span. Since we rolled back the // interpolators, the color values may have overflow. // So that, we render the beginning part with checking // for overflow. It lasts until "start" is positive; // typically it's 1-2 pixels, but may be more in some cases. //------------------------- while(len && start > 0) { vv = v.y(); va = a.y(); if(vv < 0) vv = 0; if(vv > lim) vv = lim; if(va < 0) va = 0; if(va > lim) va = lim; span->v = (value_type)vv; span->a = (value_type)va; v += subpixel_scale; a += subpixel_scale; nlen -= subpixel_scale; start -= subpixel_scale; ++span; --len; } // Middle part, no checking for overflow. // Actual spans can be longer than the calculated length // because of anti-aliasing, thus, the interpolators can // overflow. But while "nlen" is positive we are safe. //------------------------- while(len && nlen > 0) { span->v = (value_type)v.y(); span->a = (value_type)a.y(); v += subpixel_scale; a += subpixel_scale; nlen -= subpixel_scale; ++span; --len; } // Ending part; checking for overflow. // Typically it's 1-2 pixels, but may be more in some cases. //------------------------- while(len) { vv = v.y(); va = a.y(); if(vv < 0) vv = 0; if(vv > lim) vv = lim; if(va < 0) va = 0; if(va > lim) va = lim; span->v = (value_type)vv; span->a = (value_type)va; v += subpixel_scale; a += subpixel_scale; ++span; --len; } } private: bool m_swap; int m_y2; gray_calc m_c1; gray_calc m_c2; gray_calc m_c3; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_gamma_functions.h�����������������������������������������0000644�0024617�0000144�00000006272�12261257215�023636� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_GAMMA_FUNCTIONS_INCLUDED #define AGG_GAMMA_FUNCTIONS_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { //===============================================================gamma_none struct gamma_none { double operator()(double x) const { return x; } }; //==============================================================gamma_power class gamma_power { public: gamma_power() : m_gamma(1.0) {} gamma_power(double g) : m_gamma(g) {} void gamma(double g) { m_gamma = g; } double gamma() const { return m_gamma; } double operator() (double x) const { return pow(x, m_gamma); } private: double m_gamma; }; //==========================================================gamma_threshold class gamma_threshold { public: gamma_threshold() : m_threshold(0.5) {} gamma_threshold(double t) : m_threshold(t) {} void threshold(double t) { m_threshold = t; } double threshold() const { return m_threshold; } double operator() (double x) const { return (x < m_threshold) ? 0.0 : 1.0; } private: double m_threshold; }; //============================================================gamma_linear class gamma_linear { public: gamma_linear() : m_start(0.0), m_end(1.0) {} gamma_linear(double s, double e) : m_start(s), m_end(e) {} void set(double s, double e) { m_start = s; m_end = e; } void start(double s) { m_start = s; } void end(double e) { m_end = e; } double start() const { return m_start; } double end() const { return m_end; } double operator() (double x) const { if(x < m_start) return 0.0; if(x > m_end) return 1.0; return (x - m_start) / (m_end - m_start); } private: double m_start; double m_end; }; //==========================================================gamma_multiply class gamma_multiply { public: gamma_multiply() : m_mul(1.0) {} gamma_multiply(double v) : m_mul(v) {} void value(double v) { m_mul = v; } double value() const { return m_mul; } double operator() (double x) const { double y = x * m_mul; if(y > 1.0) y = 1.0; return y; } private: double m_mul; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_line_aa_basics.h������������������������������������������0000644�0024617�0000144�00000015125�12261257215�023375� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_LINE_AA_BASICS_INCLUDED #define AGG_LINE_AA_BASICS_INCLUDED #include <stdlib.h> #include "agg_basics.h" namespace mapserver { // See Implementation agg_line_aa_basics.cpp //------------------------------------------------------------------------- enum line_subpixel_scale_e { line_subpixel_shift = 8, //----line_subpixel_shift line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask line_max_coord = (1 << 28) - 1, //----line_max_coord line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length }; //------------------------------------------------------------------------- enum line_mr_subpixel_scale_e { line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask }; //------------------------------------------------------------------line_mr AGG_INLINE int line_mr(int x) { return x >> (line_subpixel_shift - line_mr_subpixel_shift); } //-------------------------------------------------------------------line_hr AGG_INLINE int line_hr(int x) { return x << (line_subpixel_shift - line_mr_subpixel_shift); } //---------------------------------------------------------------line_dbl_hr AGG_INLINE int line_dbl_hr(int x) { return x << line_subpixel_shift; } //---------------------------------------------------------------line_coord struct line_coord { AGG_INLINE static int conv(double x) { return iround(x * line_subpixel_scale); } }; //-----------------------------------------------------------line_coord_sat struct line_coord_sat { AGG_INLINE static int conv(double x) { return saturation<line_max_coord>::iround(x * line_subpixel_scale); } }; //==========================================================line_parameters struct line_parameters { //--------------------------------------------------------------------- line_parameters() {} line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) : x1(x1_), y1(y1_), x2(x2_), y2(y2_), dx(abs(x2_ - x1_)), dy(abs(y2_ - y1_)), sx((x2_ > x1_) ? 1 : -1), sy((y2_ > y1_) ? 1 : -1), vertical(dy >= dx), inc(vertical ? sy : sx), len(len_), octant((sy & 4) | (sx & 2) | int(vertical)) { } //--------------------------------------------------------------------- unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; } unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; } //--------------------------------------------------------------------- bool same_orthogonal_quadrant(const line_parameters& lp) const { return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant]; } //--------------------------------------------------------------------- bool same_diagonal_quadrant(const line_parameters& lp) const { return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant]; } //--------------------------------------------------------------------- void divide(line_parameters& lp1, line_parameters& lp2) const { int xmid = (x1 + x2) >> 1; int ymid = (y1 + y2) >> 1; int len2 = len >> 1; lp1 = *this; lp2 = *this; lp1.x2 = xmid; lp1.y2 = ymid; lp1.len = len2; lp1.dx = abs(lp1.x2 - lp1.x1); lp1.dy = abs(lp1.y2 - lp1.y1); lp2.x1 = xmid; lp2.y1 = ymid; lp2.len = len2; lp2.dx = abs(lp2.x2 - lp2.x1); lp2.dy = abs(lp2.y2 - lp2.y1); } //--------------------------------------------------------------------- int x1, y1, x2, y2, dx, dy, sx, sy; bool vertical; int inc; int len; int octant; //--------------------------------------------------------------------- static const int8u s_orthogonal_quadrant[8]; static const int8u s_diagonal_quadrant[8]; }; // See Implementation agg_line_aa_basics.cpp //----------------------------------------------------------------bisectrix void bisectrix(const line_parameters& l1, const line_parameters& l2, int* x, int* y); //-------------------------------------------fix_degenerate_bisectrix_start void inline fix_degenerate_bisectrix_start(const line_parameters& lp, int* x, int* y) { int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); if(d < line_subpixel_scale/2) { *x = lp.x1 + (lp.y2 - lp.y1); *y = lp.y1 - (lp.x2 - lp.x1); } } //---------------------------------------------fix_degenerate_bisectrix_end void inline fix_degenerate_bisectrix_end(const line_parameters& lp, int* x, int* y) { int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); if(d < line_subpixel_scale/2) { *x = lp.x2 + (lp.y2 - lp.y1); *y = lp.y2 - (lp.x2 - lp.x1); } } } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_double_path.h���������������������������������������0000644�0024617�0000144�00000010141�12261257215�024147� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_TRANS_DOUBLE_PATH_INCLUDED #define AGG_TRANS_DOUBLE_PATH_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { // See also: agg_trans_double_path.cpp // //-------------------------------------------------------trans_double_path class trans_double_path { enum status_e { initial, making_path, ready }; public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; trans_double_path(); //-------------------------------------------------------------------- void base_length(double v) { m_base_length = v; } double base_length() const { return m_base_length; } //-------------------------------------------------------------------- void base_height(double v) { m_base_height = v; } double base_height() const { return m_base_height; } //-------------------------------------------------------------------- void preserve_x_scale(bool f) { m_preserve_x_scale = f; } bool preserve_x_scale() const { return m_preserve_x_scale; } //-------------------------------------------------------------------- void reset(); void move_to1(double x, double y); void line_to1(double x, double y); void move_to2(double x, double y); void line_to2(double x, double y); void finalize_paths(); //-------------------------------------------------------------------- template<class VertexSource1, class VertexSource2> void add_paths(VertexSource1& vs1, VertexSource2& vs2, unsigned path1_id=0, unsigned path2_id=0) { double x; double y; unsigned cmd; vs1.rewind(path1_id); while(!is_stop(cmd = vs1.vertex(&x, &y))) { if(is_move_to(cmd)) { move_to1(x, y); } else { if(is_vertex(cmd)) { line_to1(x, y); } } } vs2.rewind(path2_id); while(!is_stop(cmd = vs2.vertex(&x, &y))) { if(is_move_to(cmd)) { move_to2(x, y); } else { if(is_vertex(cmd)) { line_to2(x, y); } } } finalize_paths(); } //-------------------------------------------------------------------- double total_length1() const; double total_length2() const; void transform(double *x, double *y) const; private: double finalize_path(vertex_storage& vertices); void transform1(const vertex_storage& vertices, double kindex, double kx, double *x, double* y) const; vertex_storage m_src_vertices1; vertex_storage m_src_vertices2; double m_base_length; double m_base_height; double m_kindex1; double m_kindex2; status_e m_status1; status_e m_status2; bool m_preserve_x_scale; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_markers_term.h��������������������������������������0000644�0024617�0000144�00000003737�12261257215�024344� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_MARKERS_TERM_INCLUDED #define AGG_VCGEN_MARKERS_TERM_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { //======================================================vcgen_markers_term // // See Implemantation agg_vcgen_markers_term.cpp // Terminal markers generator (arrowhead/arrowtail) // //------------------------------------------------------------------------ class vcgen_markers_term { public: vcgen_markers_term() : m_curr_id(0), m_curr_idx(0) {} // Vertex Generator Interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: vcgen_markers_term(const vcgen_markers_term&); const vcgen_markers_term& operator = (const vcgen_markers_term&); struct coord_type { double x, y; coord_type() {} coord_type(double x_, double y_) : x(x_), y(y_) {} }; typedef pod_bvector<coord_type, 6> coord_storage; coord_storage m_markers; unsigned m_curr_id; unsigned m_curr_idx; }; } #endif ���������������������������������mapserver-6.4.1/renderers/agg/include/agg_vpgen_clip_polygon.h��������������������������������������0000644�0024617�0000144�00000004564�12261257215�024363� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VPGEN_CLIP_POLYGON_INCLUDED #define AGG_VPGEN_CLIP_POLYGON_INCLUDED #include "agg_basics.h" namespace mapserver { //======================================================vpgen_clip_polygon // // See Implementation agg_vpgen_clip_polygon.cpp // class vpgen_clip_polygon { public: vpgen_clip_polygon() : m_clip_box(0, 0, 1, 1), m_x1(0), m_y1(0), m_clip_flags(0), m_num_vertices(0), m_vertex(0), m_cmd(path_cmd_move_to) { } void clip_box(double x1, double y1, double x2, double y2) { m_clip_box.x1 = x1; m_clip_box.y1 = y1; m_clip_box.x2 = x2; m_clip_box.y2 = y2; m_clip_box.normalize(); } double x1() const { return m_clip_box.x1; } double y1() const { return m_clip_box.y1; } double x2() const { return m_clip_box.x2; } double y2() const { return m_clip_box.y2; } static bool auto_close() { return true; } static bool auto_unclose() { return false; } void reset(); void move_to(double x, double y); void line_to(double x, double y); unsigned vertex(double* x, double* y); private: unsigned clipping_flags(double x, double y); private: rect_d m_clip_box; double m_x1; double m_y1; unsigned m_clip_flags; double m_x[4]; double m_y[4]; unsigned m_num_vertices; unsigned m_vertex; unsigned m_cmd; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_arrowhead.h�����������������������������������������������0000644�0024617�0000144�00000004427�12261257215�022440� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Simple arrowhead/arrowtail generator // //---------------------------------------------------------------------------- #ifndef AGG_ARROWHEAD_INCLUDED #define AGG_ARROWHEAD_INCLUDED #include "agg_basics.h" namespace mapserver { //===============================================================arrowhead // // See implementation agg_arrowhead.cpp // class arrowhead { public: arrowhead(); void head(double d1, double d2, double d3, double d4) { m_head_d1 = d1; m_head_d2 = d2; m_head_d3 = d3; m_head_d4 = d4; m_head_flag = true; } void head() { m_head_flag = true; } void no_head() { m_head_flag = false; } void tail(double d1, double d2, double d3, double d4) { m_tail_d1 = d1; m_tail_d2 = d2; m_tail_d3 = d3; m_tail_d4 = d4; m_tail_flag = true; } void tail() { m_tail_flag = true; } void no_tail() { m_tail_flag = false; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: double m_head_d1; double m_head_d2; double m_head_d3; double m_head_d4; double m_tail_d1; double m_tail_d2; double m_tail_d3; double m_tail_d4; bool m_head_flag; bool m_tail_flag; double m_coord[16]; unsigned m_cmd[8]; unsigned m_curr_id; unsigned m_curr_coord; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_array.h���������������������������������������������������0000644�0024617�0000144�00000102765�12261257215�021606� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_ARRAY_INCLUDED #define AGG_ARRAY_INCLUDED #include <stddef.h> #include <string.h> #include "agg_basics.h" namespace mapserver { //-------------------------------------------------------pod_array_adaptor template<class T> class pod_array_adaptor { public: typedef T value_type; pod_array_adaptor(T* array, unsigned size) : m_array(array), m_size(size) {} unsigned size() const { return m_size; } const T& operator [] (unsigned i) const { return m_array[i]; } T& operator [] (unsigned i) { return m_array[i]; } const T& at(unsigned i) const { return m_array[i]; } T& at(unsigned i) { return m_array[i]; } T value_at(unsigned i) const { return m_array[i]; } private: T* m_array; unsigned m_size; }; //---------------------------------------------------------pod_auto_array template<class T, unsigned Size> class pod_auto_array { public: typedef T value_type; typedef pod_auto_array<T, Size> self_type; pod_auto_array() {} explicit pod_auto_array(const T* c) { memcpy(m_array, c, sizeof(T) * Size); } const self_type& operator = (const T* c) { memcpy(m_array, c, sizeof(T) * Size); return *this; } static unsigned size() { return Size; } const T& operator [] (unsigned i) const { return m_array[i]; } T& operator [] (unsigned i) { return m_array[i]; } const T& at(unsigned i) const { return m_array[i]; } T& at(unsigned i) { return m_array[i]; } T value_at(unsigned i) const { return m_array[i]; } private: T m_array[Size]; }; //--------------------------------------------------------pod_auto_vector template<class T, unsigned Size> class pod_auto_vector { public: typedef T value_type; typedef pod_auto_vector<T, Size> self_type; pod_auto_vector() : m_size(0) {} void remove_all() { m_size = 0; } void clear() { m_size = 0; } void add(const T& v) { m_array[m_size++] = v; } void push_back(const T& v) { m_array[m_size++] = v; } void inc_size(unsigned size) { m_size += size; } unsigned size() const { return m_size; } const T& operator [] (unsigned i) const { return m_array[i]; } T& operator [] (unsigned i) { return m_array[i]; } const T& at(unsigned i) const { return m_array[i]; } T& at(unsigned i) { return m_array[i]; } T value_at(unsigned i) const { return m_array[i]; } private: T m_array[Size]; unsigned m_size; }; //---------------------------------------------------------------pod_array template<class T> class pod_array { public: typedef T value_type; typedef pod_array<T> self_type; ~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); } pod_array() : m_array(0), m_size(0) {} pod_array(unsigned size) : m_array(pod_allocator<T>::allocate(size)), m_size(size) {} pod_array(const self_type& v) : m_array(pod_allocator<T>::allocate(v.m_size)), m_size(v.m_size) { memcpy(m_array, v.m_array, sizeof(T) * m_size); } void resize(unsigned size) { if(size != m_size) { pod_allocator<T>::deallocate(m_array, m_size); m_array = pod_allocator<T>::allocate(m_size = size); } } const self_type& operator = (const self_type& v) { resize(v.size()); memcpy(m_array, v.m_array, sizeof(T) * m_size); return *this; } unsigned size() const { return m_size; } const T& operator [] (unsigned i) const { return m_array[i]; } T& operator [] (unsigned i) { return m_array[i]; } const T& at(unsigned i) const { return m_array[i]; } T& at(unsigned i) { return m_array[i]; } T value_at(unsigned i) const { return m_array[i]; } const T* data() const { return m_array; } T* data() { return m_array; } private: T* m_array; unsigned m_size; }; //--------------------------------------------------------------pod_vector // A simple class template to store Plain Old Data, a vector // of a fixed size. The data is continous in memory //------------------------------------------------------------------------ template<class T> class pod_vector { public: typedef T value_type; ~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); } pod_vector() : m_size(0), m_capacity(0), m_array(0) {} pod_vector(unsigned cap, unsigned extra_tail=0); // Copying pod_vector(const pod_vector<T>&); const pod_vector<T>& operator = (const pod_vector<T>&); // Set new capacity. All data is lost, size is set to zero. void capacity(unsigned cap, unsigned extra_tail=0); unsigned capacity() const { return m_capacity; } // Allocate n elements. All data is lost, // but elements can be accessed in range 0...size-1. void allocate(unsigned size, unsigned extra_tail=0); // Resize keeping the content. void resize(unsigned new_size); void zero() { memset(m_array, 0, sizeof(T) * m_size); } void add(const T& v) { m_array[m_size++] = v; } void push_back(const T& v) { m_array[m_size++] = v; } void insert_at(unsigned pos, const T& val); void inc_size(unsigned size) { m_size += size; } unsigned size() const { return m_size; } unsigned byte_size() const { return m_size * sizeof(T); } void serialize(int8u* ptr) const; void deserialize(const int8u* data, unsigned byte_size); const T& operator [] (unsigned i) const { return m_array[i]; } T& operator [] (unsigned i) { return m_array[i]; } const T& at(unsigned i) const { return m_array[i]; } T& at(unsigned i) { return m_array[i]; } T value_at(unsigned i) const { return m_array[i]; } const T* data() const { return m_array; } T* data() { return m_array; } void remove_all() { m_size = 0; } void clear() { m_size = 0; } void cut_at(unsigned num) { if(num < m_size) m_size = num; } private: unsigned m_size; unsigned m_capacity; T* m_array; }; //------------------------------------------------------------------------ template<class T> void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail) { m_size = 0; if(cap > m_capacity) { pod_allocator<T>::deallocate(m_array, m_capacity); m_capacity = cap + extra_tail; m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0; } } //------------------------------------------------------------------------ template<class T> void pod_vector<T>::allocate(unsigned size, unsigned extra_tail) { capacity(size, extra_tail); m_size = size; } //------------------------------------------------------------------------ template<class T> void pod_vector<T>::resize(unsigned new_size) { if(new_size > m_size) { if(new_size > m_capacity) { T* data = pod_allocator<T>::allocate(new_size); memcpy(data, m_array, m_size * sizeof(T)); pod_allocator<T>::deallocate(m_array, m_capacity); m_array = data; } } else { m_size = new_size; } } //------------------------------------------------------------------------ template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) : m_size(0), m_capacity(cap + extra_tail), m_array(pod_allocator<T>::allocate(m_capacity)) {} //------------------------------------------------------------------------ template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) : m_size(v.m_size), m_capacity(v.m_capacity), m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0) { memcpy(m_array, v.m_array, sizeof(T) * v.m_size); } //------------------------------------------------------------------------ template<class T> const pod_vector<T>& pod_vector<T>::operator = (const pod_vector<T>&v) { allocate(v.m_size); if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size); return *this; } //------------------------------------------------------------------------ template<class T> void pod_vector<T>::serialize(int8u* ptr) const { if(m_size) memcpy(ptr, m_array, m_size * sizeof(T)); } //------------------------------------------------------------------------ template<class T> void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size) { byte_size /= sizeof(T); allocate(byte_size); if(byte_size) memcpy(m_array, data, byte_size * sizeof(T)); } //------------------------------------------------------------------------ template<class T> void pod_vector<T>::insert_at(unsigned pos, const T& val) { if(pos >= m_size) { m_array[m_size] = val; } else { memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T)); m_array[pos] = val; } ++m_size; } //---------------------------------------------------------------pod_bvector // A simple class template to store Plain Old Data, similar to std::deque // It doesn't reallocate memory but instead, uses blocks of data of size // of (1 << S), that is, power of two. The data is NOT contiguous in memory, // so the only valid access method is operator [] or curr(), prev(), next() // // There reallocs occure only when the pool of pointers to blocks needs // to be extended (it happens very rarely). You can control the value // of increment to reallocate the pointer buffer. See the second constructor. // By default, the incremeent value equals (1 << S), i.e., the block size. //------------------------------------------------------------------------ template<class T, unsigned S=6> class pod_bvector { public: enum block_scale_e { block_shift = S, block_size = 1 << block_shift, block_mask = block_size - 1 }; typedef T value_type; ~pod_bvector(); pod_bvector(); pod_bvector(unsigned block_ptr_inc); // Copying pod_bvector(const pod_bvector<T, S>& v); const pod_bvector<T, S>& operator = (const pod_bvector<T, S>& v); void remove_all() { m_size = 0; } void clear() { m_size = 0; } void free_all() { free_tail(0); } void free_tail(unsigned size); void add(const T& val); void push_back(const T& val) { add(val); } void modify_last(const T& val); void remove_last(); int allocate_continuous_block(unsigned num_elements); void add_array(const T* ptr, unsigned num_elem) { while(num_elem--) { add(*ptr++); } } template<class DataAccessor> void add_data(DataAccessor& data) { while(data.size()) { add(*data); ++data; } } void cut_at(unsigned size) { if(size < m_size) m_size = size; } unsigned size() const { return m_size; } const T& operator [] (unsigned i) const { return m_blocks[i >> block_shift][i & block_mask]; } T& operator [] (unsigned i) { return m_blocks[i >> block_shift][i & block_mask]; } const T& at(unsigned i) const { return m_blocks[i >> block_shift][i & block_mask]; } T& at(unsigned i) { return m_blocks[i >> block_shift][i & block_mask]; } T value_at(unsigned i) const { return m_blocks[i >> block_shift][i & block_mask]; } const T& curr(unsigned idx) const { return (*this)[idx]; } T& curr(unsigned idx) { return (*this)[idx]; } const T& prev(unsigned idx) const { return (*this)[(idx + m_size - 1) % m_size]; } T& prev(unsigned idx) { return (*this)[(idx + m_size - 1) % m_size]; } const T& next(unsigned idx) const { return (*this)[(idx + 1) % m_size]; } T& next(unsigned idx) { return (*this)[(idx + 1) % m_size]; } const T& last() const { return (*this)[m_size - 1]; } T& last() { return (*this)[m_size - 1]; } unsigned byte_size() const; void serialize(int8u* ptr) const; void deserialize(const int8u* data, unsigned byte_size); void deserialize(unsigned start, const T& empty_val, const int8u* data, unsigned byte_size); template<class ByteAccessor> void deserialize(ByteAccessor data) { remove_all(); unsigned elem_size = data.size() / sizeof(T); for(unsigned i = 0; i < elem_size; ++i) { int8u* ptr = (int8u*)data_ptr(); for(unsigned j = 0; j < sizeof(T); ++j) { *ptr++ = *data; ++data; } ++m_size; } } template<class ByteAccessor> void deserialize(unsigned start, const T& empty_val, ByteAccessor data) { while(m_size < start) { add(empty_val); } unsigned elem_size = data.size() / sizeof(T); for(unsigned i = 0; i < elem_size; ++i) { int8u* ptr; if(start + i < m_size) { ptr = (int8u*)(&((*this)[start + i])); } else { ptr = (int8u*)data_ptr(); ++m_size; } for(unsigned j = 0; j < sizeof(T); ++j) { *ptr++ = *data; ++data; } } } const T* block(unsigned nb) const { return m_blocks[nb]; } private: void allocate_block(unsigned nb); T* data_ptr(); unsigned m_size; unsigned m_num_blocks; unsigned m_max_blocks; T** m_blocks; unsigned m_block_ptr_inc; }; //------------------------------------------------------------------------ template<class T, unsigned S> pod_bvector<T, S>::~pod_bvector() { if(m_num_blocks) { T** blk = m_blocks + m_num_blocks - 1; while(m_num_blocks--) { pod_allocator<T>::deallocate(*blk, block_size); --blk; } } pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); } //------------------------------------------------------------------------ template<class T, unsigned S> void pod_bvector<T, S>::free_tail(unsigned size) { if(size < m_size) { unsigned nb = (size + block_mask) >> block_shift; while(m_num_blocks > nb) { pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size); } if(m_num_blocks == 0) { pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); m_blocks = 0; m_max_blocks = 0; } m_size = size; } } //------------------------------------------------------------------------ template<class T, unsigned S> pod_bvector<T, S>::pod_bvector() : m_size(0), m_num_blocks(0), m_max_blocks(0), m_blocks(0), m_block_ptr_inc(block_size) { } //------------------------------------------------------------------------ template<class T, unsigned S> pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc) : m_size(0), m_num_blocks(0), m_max_blocks(0), m_blocks(0), m_block_ptr_inc(block_ptr_inc) { } //------------------------------------------------------------------------ template<class T, unsigned S> pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v) : m_size(v.m_size), m_num_blocks(v.m_num_blocks), m_max_blocks(v.m_max_blocks), m_blocks(v.m_max_blocks ? pod_allocator<T*>::allocate(v.m_max_blocks) : 0), m_block_ptr_inc(v.m_block_ptr_inc) { unsigned i; for(i = 0; i < v.m_num_blocks; ++i) { m_blocks[i] = pod_allocator<T>::allocate(block_size); memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); } } //------------------------------------------------------------------------ template<class T, unsigned S> const pod_bvector<T, S>& pod_bvector<T, S>::operator = (const pod_bvector<T, S>& v) { unsigned i; for(i = m_num_blocks; i < v.m_num_blocks; ++i) { allocate_block(i); } for(i = 0; i < v.m_num_blocks; ++i) { memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); } m_size = v.m_size; return *this; } //------------------------------------------------------------------------ template<class T, unsigned S> void pod_bvector<T, S>::allocate_block(unsigned nb) { if(nb >= m_max_blocks) { T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc); if(m_blocks) { memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(T*)); pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); } m_blocks = new_blocks; m_max_blocks += m_block_ptr_inc; } m_blocks[nb] = pod_allocator<T>::allocate(block_size); m_num_blocks++; } //------------------------------------------------------------------------ template<class T, unsigned S> inline T* pod_bvector<T, S>::data_ptr() { unsigned nb = m_size >> block_shift; if(nb >= m_num_blocks) { allocate_block(nb); } return m_blocks[nb] + (m_size & block_mask); } //------------------------------------------------------------------------ template<class T, unsigned S> inline void pod_bvector<T, S>::add(const T& val) { *data_ptr() = val; ++m_size; } //------------------------------------------------------------------------ template<class T, unsigned S> inline void pod_bvector<T, S>::remove_last() { if(m_size) --m_size; } //------------------------------------------------------------------------ template<class T, unsigned S> void pod_bvector<T, S>::modify_last(const T& val) { remove_last(); add(val); } //------------------------------------------------------------------------ template<class T, unsigned S> int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements) { if(num_elements < block_size) { data_ptr(); // Allocate initial block if necessary unsigned rest = block_size - (m_size & block_mask); unsigned index; if(num_elements <= rest) { // The rest of the block is good, we can use it //----------------- index = m_size; m_size += num_elements; return index; } // New block //--------------- m_size += rest; data_ptr(); index = m_size; m_size += num_elements; return index; } return -1; // Impossible to allocate } //------------------------------------------------------------------------ template<class T, unsigned S> unsigned pod_bvector<T, S>::byte_size() const { return m_size * sizeof(T); } //------------------------------------------------------------------------ template<class T, unsigned S> void pod_bvector<T, S>::serialize(int8u* ptr) const { unsigned i; for(i = 0; i < m_size; i++) { memcpy(ptr, &(*this)[i], sizeof(T)); ptr += sizeof(T); } } //------------------------------------------------------------------------ template<class T, unsigned S> void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size) { remove_all(); byte_size /= sizeof(T); for(unsigned i = 0; i < byte_size; ++i) { T* ptr = data_ptr(); memcpy(ptr, data, sizeof(T)); ++m_size; data += sizeof(T); } } // Replace or add a number of elements starting from "start" position //------------------------------------------------------------------------ template<class T, unsigned S> void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val, const int8u* data, unsigned byte_size) { while(m_size < start) { add(empty_val); } byte_size /= sizeof(T); for(unsigned i = 0; i < byte_size; ++i) { if(start + i < m_size) { memcpy(&((*this)[start + i]), data, sizeof(T)); } else { T* ptr = data_ptr(); memcpy(ptr, data, sizeof(T)); ++m_size; } data += sizeof(T); } } //---------------------------------------------------------block_allocator // Allocator for arbitrary POD data. Most usable in different cache // systems for efficient memory allocations. // Memory is allocated with blocks of fixed size ("block_size" in // the constructor). If required size exceeds the block size the allocator // creates a new block of the required size. However, the most efficient // use is when the average reqired size is much less than the block size. //------------------------------------------------------------------------ class block_allocator { struct block_type { int8u* data; unsigned size; }; public: void remove_all() { if(m_num_blocks) { block_type* blk = m_blocks + m_num_blocks - 1; while(m_num_blocks--) { pod_allocator<int8u>::deallocate(blk->data, blk->size); --blk; } pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks); } m_num_blocks = 0; m_max_blocks = 0; m_blocks = 0; m_buf_ptr = 0; m_rest = 0; } ~block_allocator() { remove_all(); } block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : m_block_size(block_size), m_block_ptr_inc(block_ptr_inc), m_num_blocks(0), m_max_blocks(0), m_blocks(0), m_buf_ptr(0), m_rest(0) { } int8u* allocate(unsigned size, unsigned alignment=1) { if(size == 0) return 0; if(size <= m_rest) { int8u* ptr = m_buf_ptr; if(alignment > 1) { unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment; size += align; ptr += align; if(size <= m_rest) { m_rest -= size; m_buf_ptr += size; return ptr; } allocate_block(size); return allocate(size - align, alignment); } m_rest -= size; m_buf_ptr += size; return ptr; } allocate_block(size + alignment - 1); return allocate(size, alignment); } private: void allocate_block(unsigned size) { if(size < m_block_size) size = m_block_size; if(m_num_blocks >= m_max_blocks) { block_type* new_blocks = pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc); if(m_blocks) { memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(block_type)); pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks); } m_blocks = new_blocks; m_max_blocks += m_block_ptr_inc; } m_blocks[m_num_blocks].size = size; m_blocks[m_num_blocks].data = m_buf_ptr = pod_allocator<int8u>::allocate(size); m_num_blocks++; m_rest = size; } unsigned m_block_size; unsigned m_block_ptr_inc; unsigned m_num_blocks; unsigned m_max_blocks; block_type* m_blocks; int8u* m_buf_ptr; unsigned m_rest; }; //------------------------------------------------------------------------ enum quick_sort_threshold_e { quick_sort_threshold = 9 }; //-----------------------------------------------------------swap_elements template<class T> inline void swap_elements(T& a, T& b) { T temp = a; a = b; b = temp; } //--------------------------------------------------------------quick_sort template<class Array, class Less> void quick_sort(Array& arr, Less less) { if(arr.size() < 2) return; typename Array::value_type* e1; typename Array::value_type* e2; int stack[80]; int* top = stack; int limit = arr.size(); int base = 0; for(;;) { int len = limit - base; int i; int j; int pivot; if(len > quick_sort_threshold) { // we use base + len/2 as the pivot pivot = base + len / 2; swap_elements(arr[base], arr[pivot]); i = base + 1; j = limit - 1; // now ensure that *i <= *base <= *j e1 = &(arr[j]); e2 = &(arr[i]); if(less(*e1, *e2)) swap_elements(*e1, *e2); e1 = &(arr[base]); e2 = &(arr[i]); if(less(*e1, *e2)) swap_elements(*e1, *e2); e1 = &(arr[j]); e2 = &(arr[base]); if(less(*e1, *e2)) swap_elements(*e1, *e2); for(;;) { do i++; while( less(arr[i], arr[base]) ); do j--; while( less(arr[base], arr[j]) ); if( i > j ) { break; } swap_elements(arr[i], arr[j]); } swap_elements(arr[base], arr[j]); // now, push the largest sub-array if(j - base > limit - i) { top[0] = base; top[1] = j; base = i; } else { top[0] = i; top[1] = limit; limit = j; } top += 2; } else { // the sub-array is small, perform insertion sort j = base; i = j + 1; for(; i < limit; j = i, i++) { for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) { swap_elements(*e1, *e2); if(j == base) { break; } } } if(top > stack) { top -= 2; base = top[0]; limit = top[1]; } else { break; } } } } //------------------------------------------------------remove_duplicates // Remove duplicates from a sorted array. It doesn't cut the // tail of the array, it just returns the number of remaining elements. //----------------------------------------------------------------------- template<class Array, class Equal> unsigned remove_duplicates(Array& arr, Equal equal) { if(arr.size() < 2) return arr.size(); unsigned i, j; for(i = 1, j = 1; i < arr.size(); i++) { typename Array::value_type& e = arr[i]; if(!equal(e, arr[i - 1])) { arr[j++] = e; } } return j; } //--------------------------------------------------------invert_container template<class Array> void invert_container(Array& arr) { int i = 0; int j = arr.size() - 1; while(i < j) { swap_elements(arr[i++], arr[j--]); } } //------------------------------------------------------binary_search_pos template<class Array, class Value, class Less> unsigned binary_search_pos(const Array& arr, const Value& val, Less less) { if(arr.size() == 0) return 0; unsigned beg = 0; unsigned end = arr.size() - 1; if(less(val, arr[0])) return 0; if(less(arr[end], val)) return end + 1; while(end - beg > 1) { unsigned mid = (end + beg) >> 1; if(less(val, arr[mid])) end = mid; else beg = mid; } //if(beg <= 0 && less(val, arr[0])) return 0; //if(end >= arr.size() - 1 && less(arr[end], val)) ++end; return end; } //----------------------------------------------------------range_adaptor template<class Array> class range_adaptor { public: typedef typename Array::value_type value_type; range_adaptor(Array& array, unsigned start, unsigned size) : m_array(array), m_start(start), m_size(size) {} unsigned size() const { return m_size; } const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; } value_type& operator [] (unsigned i) { return m_array[m_start + i]; } const value_type& at(unsigned i) const { return m_array[m_start + i]; } value_type& at(unsigned i) { return m_array[m_start + i]; } value_type value_at(unsigned i) const { return m_array[m_start + i]; } private: Array& m_array; unsigned m_start; unsigned m_size; }; //---------------------------------------------------------------int_less inline bool int_less(int a, int b) { return a < b; } //------------------------------------------------------------int_greater inline bool int_greater(int a, int b) { return a > b; } //----------------------------------------------------------unsigned_less inline bool unsigned_less(unsigned a, unsigned b) { return a < b; } //-------------------------------------------------------unsigned_greater inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; } } #endif �����������mapserver-6.4.1/renderers/agg/include/agg_scanline_boolean_algebra.h��������������������������������0000644�0024617�0000144�00000152211�12261257215�025427� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED #define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED #include <stdlib.h> #include <math.h> #include "agg_basics.h" namespace mapserver { //-----------------------------------------------sbool_combine_spans_bin // Functor. // Combine two binary encoded spans, i.e., when we don't have any // anti-aliasing information, but only X and Length. The function // is compatible with any type of scanlines. //---------------- template<class Scanline1, class Scanline2, class Scanline> struct sbool_combine_spans_bin { void operator () (const typename Scanline1::const_iterator&, const typename Scanline2::const_iterator&, int x, unsigned len, Scanline& sl) const { sl.add_span(x, len, cover_full); } }; //---------------------------------------------sbool_combine_spans_empty // Functor. // Combine two spans as empty ones. The functor does nothing // and is used to XOR binary spans. //---------------- template<class Scanline1, class Scanline2, class Scanline> struct sbool_combine_spans_empty { void operator () (const typename Scanline1::const_iterator&, const typename Scanline2::const_iterator&, int, unsigned, Scanline&) const {} }; //--------------------------------------------------sbool_add_span_empty // Functor. // Add nothing. Used in conbine_shapes_sub //---------------- template<class Scanline1, class Scanline> struct sbool_add_span_empty { void operator () (const typename Scanline1::const_iterator&, int, unsigned, Scanline&) const {} }; //----------------------------------------------------sbool_add_span_bin // Functor. // Add a binary span //---------------- template<class Scanline1, class Scanline> struct sbool_add_span_bin { void operator () (const typename Scanline1::const_iterator&, int x, unsigned len, Scanline& sl) const { sl.add_span(x, len, cover_full); } }; //-----------------------------------------------------sbool_add_span_aa // Functor. // Add an anti-aliased span // anti-aliasing information, but only X and Length. The function // is compatible with any type of scanlines. //---------------- template<class Scanline1, class Scanline> struct sbool_add_span_aa { void operator () (const typename Scanline1::const_iterator& span, int x, unsigned len, Scanline& sl) const { if(span->len < 0) { sl.add_span(x, len, *span->covers); } else if(span->len > 0) { const typename Scanline1::cover_type* covers = span->covers; if(span->x < x) covers += x - span->x; sl.add_cells(x, len, covers); } } }; //----------------------------------------------sbool_intersect_spans_aa // Functor. // Intersect two spans preserving the anti-aliasing information. // The result is added to the "sl" scanline. //------------------ template<class Scanline1, class Scanline2, class Scanline, unsigned CoverShift = cover_shift> struct sbool_intersect_spans_aa { enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1, cover_full = cover_mask }; void operator () (const typename Scanline1::const_iterator& span1, const typename Scanline2::const_iterator& span2, int x, unsigned len, Scanline& sl) const { unsigned cover; const typename Scanline1::cover_type* covers1; const typename Scanline2::cover_type* covers2; // Calculate the operation code and choose the // proper combination algorithm. // 0 = Both spans are of AA type // 1 = span1 is solid, span2 is AA // 2 = span1 is AA, span2 is solid // 3 = Both spans are of solid type //----------------- switch((span1->len < 0) | ((span2->len < 0) << 1)) { case 0: // Both are AA spans covers1 = span1->covers; covers2 = span2->covers; if(span1->x < x) covers1 += x - span1->x; if(span2->x < x) covers2 += x - span2->x; do { cover = *covers1++ * *covers2++; sl.add_cell(x++, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } while(--len); break; case 1: // span1 is solid, span2 is AA covers2 = span2->covers; if(span2->x < x) covers2 += x - span2->x; if(*(span1->covers) == cover_full) { sl.add_cells(x, len, covers2); } else { do { cover = *(span1->covers) * *covers2++; sl.add_cell(x++, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } while(--len); } break; case 2: // span1 is AA, span2 is solid covers1 = span1->covers; if(span1->x < x) covers1 += x - span1->x; if(*(span2->covers) == cover_full) { sl.add_cells(x, len, covers1); } else { do { cover = *covers1++ * *(span2->covers); sl.add_cell(x++, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } while(--len); } break; case 3: // Both are solid spans cover = *(span1->covers) * *(span2->covers); sl.add_span(x, len, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); break; } } }; //--------------------------------------------------sbool_unite_spans_aa // Functor. // Unite two spans preserving the anti-aliasing information. // The result is added to the "sl" scanline. //------------------ template<class Scanline1, class Scanline2, class Scanline, unsigned CoverShift = cover_shift> struct sbool_unite_spans_aa { enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1, cover_full = cover_mask }; void operator () (const typename Scanline1::const_iterator& span1, const typename Scanline2::const_iterator& span2, int x, unsigned len, Scanline& sl) const { unsigned cover; const typename Scanline1::cover_type* covers1; const typename Scanline2::cover_type* covers2; // Calculate the operation code and choose the // proper combination algorithm. // 0 = Both spans are of AA type // 1 = span1 is solid, span2 is AA // 2 = span1 is AA, span2 is solid // 3 = Both spans are of solid type //----------------- switch((span1->len < 0) | ((span2->len < 0) << 1)) { case 0: // Both are AA spans covers1 = span1->covers; covers2 = span2->covers; if(span1->x < x) covers1 += x - span1->x; if(span2->x < x) covers2 += x - span2->x; do { cover = cover_mask * cover_mask - (cover_mask - *covers1++) * (cover_mask - *covers2++); sl.add_cell(x++, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } while(--len); break; case 1: // span1 is solid, span2 is AA covers2 = span2->covers; if(span2->x < x) covers2 += x - span2->x; if(*(span1->covers) == cover_full) { sl.add_span(x, len, cover_full); } else { do { cover = cover_mask * cover_mask - (cover_mask - *(span1->covers)) * (cover_mask - *covers2++); sl.add_cell(x++, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } while(--len); } break; case 2: // span1 is AA, span2 is solid covers1 = span1->covers; if(span1->x < x) covers1 += x - span1->x; if(*(span2->covers) == cover_full) { sl.add_span(x, len, cover_full); } else { do { cover = cover_mask * cover_mask - (cover_mask - *covers1++) * (cover_mask - *(span2->covers)); sl.add_cell(x++, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } while(--len); } break; case 3: // Both are solid spans cover = cover_mask * cover_mask - (cover_mask - *(span1->covers)) * (cover_mask - *(span2->covers)); sl.add_span(x, len, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); break; } } }; //---------------------------------------------sbool_xor_formula_linear template<unsigned CoverShift = cover_shift> struct sbool_xor_formula_linear { enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1 }; static AGG_INLINE unsigned calculate(unsigned a, unsigned b) { unsigned cover = a + b; if(cover > cover_mask) cover = cover_mask + cover_mask - cover; return cover; } }; //---------------------------------------------sbool_xor_formula_saddle template<unsigned CoverShift = cover_shift> struct sbool_xor_formula_saddle { enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1 }; static AGG_INLINE unsigned calculate(unsigned a, unsigned b) { unsigned k = a * b; if(k == cover_mask * cover_mask) return 0; a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift; b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift; return cover_mask - ((a * b) >> cover_shift); } }; //-------------------------------------------sbool_xor_formula_abs_diff struct sbool_xor_formula_abs_diff { static AGG_INLINE unsigned calculate(unsigned a, unsigned b) { return unsigned(abs(int(a) - int(b))); } }; //----------------------------------------------------sbool_xor_spans_aa // Functor. // XOR two spans preserving the anti-aliasing information. // The result is added to the "sl" scanline. //------------------ template<class Scanline1, class Scanline2, class Scanline, class XorFormula, unsigned CoverShift = cover_shift> struct sbool_xor_spans_aa { enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1, cover_full = cover_mask }; void operator () (const typename Scanline1::const_iterator& span1, const typename Scanline2::const_iterator& span2, int x, unsigned len, Scanline& sl) const { unsigned cover; const typename Scanline1::cover_type* covers1; const typename Scanline2::cover_type* covers2; // Calculate the operation code and choose the // proper combination algorithm. // 0 = Both spans are of AA type // 1 = span1 is solid, span2 is AA // 2 = span1 is AA, span2 is solid // 3 = Both spans are of solid type //----------------- switch((span1->len < 0) | ((span2->len < 0) << 1)) { case 0: // Both are AA spans covers1 = span1->covers; covers2 = span2->covers; if(span1->x < x) covers1 += x - span1->x; if(span2->x < x) covers2 += x - span2->x; do { cover = XorFormula::calculate(*covers1++, *covers2++); if(cover) sl.add_cell(x, cover); ++x; } while(--len); break; case 1: // span1 is solid, span2 is AA covers2 = span2->covers; if(span2->x < x) covers2 += x - span2->x; do { cover = XorFormula::calculate(*(span1->covers), *covers2++); if(cover) sl.add_cell(x, cover); ++x; } while(--len); break; case 2: // span1 is AA, span2 is solid covers1 = span1->covers; if(span1->x < x) covers1 += x - span1->x; do { cover = XorFormula::calculate(*covers1++, *(span2->covers)); if(cover) sl.add_cell(x, cover); ++x; } while(--len); break; case 3: // Both are solid spans cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); if(cover) sl.add_span(x, len, cover); break; } } }; //-----------------------------------------------sbool_subtract_spans_aa // Functor. // Unite two spans preserving the anti-aliasing information. // The result is added to the "sl" scanline. //------------------ template<class Scanline1, class Scanline2, class Scanline, unsigned CoverShift = cover_shift> struct sbool_subtract_spans_aa { enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, cover_mask = cover_size - 1, cover_full = cover_mask }; void operator () (const typename Scanline1::const_iterator& span1, const typename Scanline2::const_iterator& span2, int x, unsigned len, Scanline& sl) const { unsigned cover; const typename Scanline1::cover_type* covers1; const typename Scanline2::cover_type* covers2; // Calculate the operation code and choose the // proper combination algorithm. // 0 = Both spans are of AA type // 1 = span1 is solid, span2 is AA // 2 = span1 is AA, span2 is solid // 3 = Both spans are of solid type //----------------- switch((span1->len < 0) | ((span2->len < 0) << 1)) { case 0: // Both are AA spans covers1 = span1->covers; covers2 = span2->covers; if(span1->x < x) covers1 += x - span1->x; if(span2->x < x) covers2 += x - span2->x; do { cover = *covers1++ * (cover_mask - *covers2++); if(cover) { sl.add_cell(x, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } ++x; } while(--len); break; case 1: // span1 is solid, span2 is AA covers2 = span2->covers; if(span2->x < x) covers2 += x - span2->x; do { cover = *(span1->covers) * (cover_mask - *covers2++); if(cover) { sl.add_cell(x, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } ++x; } while(--len); break; case 2: // span1 is AA, span2 is solid covers1 = span1->covers; if(span1->x < x) covers1 += x - span1->x; if(*(span2->covers) != cover_full) { do { cover = *covers1++ * (cover_mask - *(span2->covers)); if(cover) { sl.add_cell(x, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } ++x; } while(--len); } break; case 3: // Both are solid spans cover = *(span1->covers) * (cover_mask - *(span2->covers)); if(cover) { sl.add_span(x, len, (cover == cover_full * cover_full) ? cover_full : (cover >> cover_shift)); } break; } } }; //--------------------------------------------sbool_add_spans_and_render template<class Scanline1, class Scanline, class Renderer, class AddSpanFunctor> void sbool_add_spans_and_render(const Scanline1& sl1, Scanline& sl, Renderer& ren, AddSpanFunctor add_span) { sl.reset_spans(); typename Scanline1::const_iterator span = sl1.begin(); unsigned num_spans = sl1.num_spans(); for(;;) { add_span(span, span->x, abs((int)span->len), sl); if(--num_spans == 0) break; ++span; } sl.finalize(sl1.y()); ren.render(sl); } //---------------------------------------------sbool_intersect_scanlines // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. // The combine_spans functor can be of type sbool_combine_spans_bin or // sbool_intersect_spans_aa. First is a general functor to combine // two spans without Anti-Aliasing, the second preserves the AA // information, but works slower // template<class Scanline1, class Scanline2, class Scanline, class CombineSpansFunctor> void sbool_intersect_scanlines(const Scanline1& sl1, const Scanline2& sl2, Scanline& sl, CombineSpansFunctor combine_spans) { sl.reset_spans(); unsigned num1 = sl1.num_spans(); if(num1 == 0) return; unsigned num2 = sl2.num_spans(); if(num2 == 0) return; typename Scanline1::const_iterator span1 = sl1.begin(); typename Scanline2::const_iterator span2 = sl2.begin(); while(num1 && num2) { int xb1 = span1->x; int xb2 = span2->x; int xe1 = xb1 + abs((int)span1->len) - 1; int xe2 = xb2 + abs((int)span2->len) - 1; // Determine what spans we should advance in the next step // The span with the least ending X should be advanced // advance_both is just an optimization when we ending // coordinates are the same and we can advance both //-------------- bool advance_span1 = xe1 < xe2; bool advance_both = xe1 == xe2; // Find the intersection of the spans // and check if they intersect //-------------- if(xb1 < xb2) xb1 = xb2; if(xe1 > xe2) xe1 = xe2; if(xb1 <= xe1) { combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); } // Advance the spans //-------------- if(advance_both) { --num1; --num2; if(num1) ++span1; if(num2) ++span2; } else { if(advance_span1) { --num1; if(num1) ++span1; } else { --num2; if(num2) ++span2; } } } } //------------------------------------------------sbool_intersect_shapes // Intersect the scanline shapes. Here the "Scanline Generator" // abstraction is used. ScanlineGen1 and ScanlineGen2 are // the generators, and can be of type rasterizer_scanline_aa<>. // There function requires three scanline containers that can be of // different types. // "sl1" and "sl2" are used to retrieve scanlines from the generators, // "sl" is ised as the resulting scanline to render it. // The external "sl1" and "sl2" are used only for the sake of // optimization and reusing of the scanline objects. // the function calls sbool_intersect_scanlines with CombineSpansFunctor // as the last argument. See sbool_intersect_scanlines for details. //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer, class CombineSpansFunctor> void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren, CombineSpansFunctor combine_spans) { // Prepare the scanline generators. // If anyone of them doesn't contain // any scanlines, then return. //----------------- if(!sg1.rewind_scanlines()) return; if(!sg2.rewind_scanlines()) return; // Get the bounding boxes //---------------- rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); // Calculate the intersection of the bounding // boxes and return if they don't intersect. //----------------- rect_i ir = intersect_rectangles(r1, r2); if(!ir.is_valid()) return; // Reset the scanlines and get two first ones //----------------- sl.reset(ir.x1, ir.x2); sl1.reset(sg1.min_x(), sg1.max_x()); sl2.reset(sg2.min_x(), sg2.max_x()); if(!sg1.sweep_scanline(sl1)) return; if(!sg2.sweep_scanline(sl2)) return; ren.prepare(); // The main loop // Here we synchronize the scanlines with // the same Y coordinate, ignoring all other ones. // Only scanlines having the same Y-coordinate // are to be combined. //----------------- for(;;) { while(sl1.y() < sl2.y()) { if(!sg1.sweep_scanline(sl1)) return; } while(sl2.y() < sl1.y()) { if(!sg2.sweep_scanline(sl2)) return; } if(sl1.y() == sl2.y()) { // The Y coordinates are the same. // Combine the scanlines, render if they contain any spans, // and advance both generators to the next scanlines //---------------------- sbool_intersect_scanlines(sl1, sl2, sl, combine_spans); if(sl.num_spans()) { sl.finalize(sl1.y()); ren.render(sl); } if(!sg1.sweep_scanline(sl1)) return; if(!sg2.sweep_scanline(sl2)) return; } } } //-------------------------------------------------sbool_unite_scanlines // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one. // The combine_spans functor can be of type sbool_combine_spans_bin or // sbool_intersect_spans_aa. First is a general functor to combine // two spans without Anti-Aliasing, the second preserves the AA // information, but works slower // template<class Scanline1, class Scanline2, class Scanline, class AddSpanFunctor1, class AddSpanFunctor2, class CombineSpansFunctor> void sbool_unite_scanlines(const Scanline1& sl1, const Scanline2& sl2, Scanline& sl, AddSpanFunctor1 add_span1, AddSpanFunctor2 add_span2, CombineSpansFunctor combine_spans) { sl.reset_spans(); unsigned num1 = sl1.num_spans(); unsigned num2 = sl2.num_spans(); typename Scanline1::const_iterator span1 = NULL;// = sl1.begin(); typename Scanline2::const_iterator span2 = NULL;// = sl2.begin(); enum invalidation_e { invalid_b = 0xFFFFFFF, invalid_e = invalid_b - 1 }; // Initialize the spans as invalid //--------------- int xb1 = invalid_b; int xb2 = invalid_b; int xe1 = invalid_e; int xe2 = invalid_e; // Initialize span1 if there are spans //--------------- if(num1) { span1 = sl1.begin(); xb1 = span1->x; xe1 = xb1 + abs((int)span1->len) - 1; --num1; } // Initialize span2 if there are spans //--------------- if(num2) { span2 = sl2.begin(); xb2 = span2->x; xe2 = xb2 + abs((int)span2->len) - 1; --num2; } for(;;) { // Retrieve a new span1 if it's invalid //---------------- if(num1 && xb1 > xe1) { --num1; ++span1; xb1 = span1->x; xe1 = xb1 + abs((int)span1->len) - 1; } // Retrieve a new span2 if it's invalid //---------------- if(num2 && xb2 > xe2) { --num2; ++span2; xb2 = span2->x; xe2 = xb2 + abs((int)span2->len) - 1; } if(xb1 > xe1 && xb2 > xe2) break; // Calculate the intersection //---------------- int xb = xb1; int xe = xe1; if(xb < xb2) xb = xb2; if(xe > xe2) xe = xe2; int len = xe - xb + 1; // The length of the intersection if(len > 0) { // The spans intersect, // add the beginning of the span //---------------- if(xb1 < xb2) { add_span1(span1, xb1, xb2 - xb1, sl); xb1 = xb2; } else if(xb2 < xb1) { add_span2(span2, xb2, xb1 - xb2, sl); xb2 = xb1; } // Add the combination part of the spans //---------------- combine_spans(span1, span2, xb, len, sl); // Invalidate the fully processed span or both //---------------- if(xe1 < xe2) { // Invalidate span1 and eat // the processed part of span2 //-------------- xb1 = invalid_b; xe1 = invalid_e; xb2 += len; } else if(xe2 < xe1) { // Invalidate span2 and eat // the processed part of span1 //-------------- xb2 = invalid_b; xe2 = invalid_e; xb1 += len; } else { xb1 = invalid_b; // Invalidate both xb2 = invalid_b; xe1 = invalid_e; xe2 = invalid_e; } } else { // The spans do not intersect //-------------- if(xb1 < xb2) { // Advance span1 //--------------- if(xb1 <= xe1) { add_span1(span1, xb1, xe1 - xb1 + 1, sl); } xb1 = invalid_b; // Invalidate xe1 = invalid_e; } else { // Advance span2 //--------------- if(xb2 <= xe2) { add_span2(span2, xb2, xe2 - xb2 + 1, sl); } xb2 = invalid_b; // Invalidate xe2 = invalid_e; } } } } //----------------------------------------------------sbool_unite_shapes // Unite the scanline shapes. Here the "Scanline Generator" // abstraction is used. ScanlineGen1 and ScanlineGen2 are // the generators, and can be of type rasterizer_scanline_aa<>. // There function requires three scanline containers that can be // of different type. // "sl1" and "sl2" are used to retrieve scanlines from the generators, // "sl" is ised as the resulting scanline to render it. // The external "sl1" and "sl2" are used only for the sake of // optimization and reusing of the scanline objects. // the function calls sbool_unite_scanlines with CombineSpansFunctor // as the last argument. See sbool_unite_scanlines for details. //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer, class AddSpanFunctor1, class AddSpanFunctor2, class CombineSpansFunctor> void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren, AddSpanFunctor1 add_span1, AddSpanFunctor2 add_span2, CombineSpansFunctor combine_spans) { // Prepare the scanline generators. // If anyone of them doesn't contain // any scanlines, then return. //----------------- bool flag1 = sg1.rewind_scanlines(); bool flag2 = sg2.rewind_scanlines(); if(!flag1 && !flag2) return; // Get the bounding boxes //---------------- rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); // Calculate the union of the bounding boxes //----------------- rect_i ur(1,1,0,0); if(flag1 && flag2) ur = unite_rectangles(r1, r2); else if(flag1) ur = r1; else if(flag2) ur = r2; if(!ur.is_valid()) return; ren.prepare(); // Reset the scanlines and get two first ones //----------------- sl.reset(ur.x1, ur.x2); if(flag1) { sl1.reset(sg1.min_x(), sg1.max_x()); flag1 = sg1.sweep_scanline(sl1); } if(flag2) { sl2.reset(sg2.min_x(), sg2.max_x()); flag2 = sg2.sweep_scanline(sl2); } // The main loop // Here we synchronize the scanlines with // the same Y coordinate. //----------------- while(flag1 || flag2) { if(flag1 && flag2) { if(sl1.y() == sl2.y()) { // The Y coordinates are the same. // Combine the scanlines, render if they contain any spans, // and advance both generators to the next scanlines //---------------------- sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); if(sl.num_spans()) { sl.finalize(sl1.y()); ren.render(sl); } flag1 = sg1.sweep_scanline(sl1); flag2 = sg2.sweep_scanline(sl2); } else { if(sl1.y() < sl2.y()) { sbool_add_spans_and_render(sl1, sl, ren, add_span1); flag1 = sg1.sweep_scanline(sl1); } else { sbool_add_spans_and_render(sl2, sl, ren, add_span2); flag2 = sg2.sweep_scanline(sl2); } } } else { if(flag1) { sbool_add_spans_and_render(sl1, sl, ren, add_span1); flag1 = sg1.sweep_scanline(sl1); } if(flag2) { sbool_add_spans_and_render(sl2, sl, ren, add_span2); flag2 = sg2.sweep_scanline(sl2); } } } } //-------------------------------------------------sbool_subtract_shapes // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator" // abstraction is used. ScanlineGen1 and ScanlineGen2 are // the generators, and can be of type rasterizer_scanline_aa<>. // There function requires three scanline containers that can be of // different types. // "sl1" and "sl2" are used to retrieve scanlines from the generators, // "sl" is ised as the resulting scanline to render it. // The external "sl1" and "sl2" are used only for the sake of // optimization and reusing of the scanline objects. // the function calls sbool_intersect_scanlines with CombineSpansFunctor // as the last argument. See combine_scanlines_sub for details. //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer, class AddSpanFunctor1, class CombineSpansFunctor> void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren, AddSpanFunctor1 add_span1, CombineSpansFunctor combine_spans) { // Prepare the scanline generators. // Here "sg1" is master, "sg2" is slave. //----------------- if(!sg1.rewind_scanlines()) return; bool flag2 = sg2.rewind_scanlines(); // Get the bounding box //---------------- rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); // Reset the scanlines and get two first ones //----------------- sl.reset(sg1.min_x(), sg1.max_x()); sl1.reset(sg1.min_x(), sg1.max_x()); sl2.reset(sg2.min_x(), sg2.max_x()); if(!sg1.sweep_scanline(sl1)) return; if(flag2) flag2 = sg2.sweep_scanline(sl2); ren.prepare(); // A fake span2 processor sbool_add_span_empty<Scanline2, Scanline> add_span2; // The main loop // Here we synchronize the scanlines with // the same Y coordinate, ignoring all other ones. // Only scanlines having the same Y-coordinate // are to be combined. //----------------- bool flag1 = true; do { // Synchronize "slave" with "master" //----------------- while(flag2 && sl2.y() < sl1.y()) { flag2 = sg2.sweep_scanline(sl2); } if(flag2 && sl2.y() == sl1.y()) { // The Y coordinates are the same. // Combine the scanlines and render if they contain any spans. //---------------------- sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); if(sl.num_spans()) { sl.finalize(sl1.y()); ren.render(sl); } } else { sbool_add_spans_and_render(sl1, sl, ren, add_span1); } // Advance the "master" flag1 = sg1.sweep_scanline(sl1); } while(flag1); } //---------------------------------------------sbool_intersect_shapes_aa // Intersect two anti-aliased scanline shapes. // Here the "Scanline Generator" abstraction is used. // ScanlineGen1 and ScanlineGen2 are the generators, and can be of // type rasterizer_scanline_aa<>. There function requires three // scanline containers that can be of different types. // "sl1" and "sl2" are used to retrieve scanlines from the generators, // "sl" is ised as the resulting scanline to render it. // The external "sl1" and "sl2" are used only for the sake of // optimization and reusing of the scanline objects. //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); } //--------------------------------------------sbool_intersect_shapes_bin // Intersect two binary scanline shapes (without anti-aliasing). // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); } //-------------------------------------------------sbool_unite_shapes_aa // Unite two anti-aliased scanline shapes // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_aa<Scanline1, Scanline> add_functor1; sbool_add_span_aa<Scanline2, Scanline> add_functor2; sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor1, add_functor2, combine_functor); } //------------------------------------------------sbool_unite_shapes_bin // Unite two binary scanline shapes (without anti-aliasing). // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_bin<Scanline1, Scanline> add_functor1; sbool_add_span_bin<Scanline2, Scanline> add_functor2; sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor1, add_functor2, combine_functor); } //---------------------------------------------------sbool_xor_shapes_aa // Apply eXclusive OR to two anti-aliased scanline shapes. There's // a modified "Linear" XOR used instead of classical "Saddle" one. // The reason is to have the result absolutely conststent with what // the scanline rasterizer produces. // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_aa<Scanline1, Scanline> add_functor1; sbool_add_span_aa<Scanline2, Scanline> add_functor2; sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, sbool_xor_formula_linear<> > combine_functor; sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor1, add_functor2, combine_functor); } //------------------------------------------sbool_xor_shapes_saddle_aa // Apply eXclusive OR to two anti-aliased scanline shapes. // There's the classical "Saddle" used to calculate the // Anti-Aliasing values, that is: // a XOR b : 1-((1-a+a*b)*(1-b+a*b)) // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_aa<Scanline1, Scanline> add_functor1; sbool_add_span_aa<Scanline2, Scanline> add_functor2; sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, sbool_xor_formula_saddle<> > combine_functor; sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor1, add_functor2, combine_functor); } //--------------------------------------sbool_xor_shapes_abs_diff_aa // Apply eXclusive OR to two anti-aliased scanline shapes. // There's the absolute difference used to calculate // Anti-Aliasing values, that is: // a XOR b : abs(a-b) // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_aa<Scanline1, Scanline> add_functor1; sbool_add_span_aa<Scanline2, Scanline> add_functor2; sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, sbool_xor_formula_abs_diff> combine_functor; sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor1, add_functor2, combine_functor); } //--------------------------------------------------sbool_xor_shapes_bin // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_bin<Scanline1, Scanline> add_functor1; sbool_add_span_bin<Scanline2, Scanline> add_functor2; sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor1, add_functor2, combine_functor); } //----------------------------------------------sbool_subtract_shapes_aa // Subtract shapes "sg1-sg2" with anti-aliasing // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_aa<Scanline1, Scanline> add_functor; sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor, combine_functor); } //---------------------------------------------sbool_subtract_shapes_bin // Subtract binary shapes "sg1-sg2" without anti-aliasing // See intersect_shapes_aa for more comments //---------- template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { sbool_add_span_bin<Scanline1, Scanline> add_functor; sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, add_functor, combine_functor); } //------------------------------------------------------------sbool_op_e enum sbool_op_e { sbool_or, //----sbool_or sbool_and, //----sbool_and sbool_xor, //----sbool_xor sbool_xor_saddle, //----sbool_xor_saddle sbool_xor_abs_diff, //----sbool_xor_abs_diff sbool_a_minus_b, //----sbool_a_minus_b sbool_b_minus_a //----sbool_b_minus_a }; //----------------------------------------------sbool_combine_shapes_bin template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_combine_shapes_bin(sbool_op_e op, ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { switch(op) { case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; case sbool_xor : case sbool_xor_saddle : case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; } } //-----------------------------------------------sbool_combine_shapes_aa template<class ScanlineGen1, class ScanlineGen2, class Scanline1, class Scanline2, class Scanline, class Renderer> void sbool_combine_shapes_aa(sbool_op_e op, ScanlineGen1& sg1, ScanlineGen2& sg2, Scanline1& sl1, Scanline2& sl2, Scanline& sl, Renderer& ren) { switch(op) { case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; } } } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rendering_buffer.h����������������������������������������0000644�0024617�0000144�00000023301�12261257215�023762� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class rendering_buffer // //---------------------------------------------------------------------------- #ifndef AGG_RENDERING_BUFFER_INCLUDED #define AGG_RENDERING_BUFFER_INCLUDED #include "agg_array.h" namespace mapserver { //===========================================================row_accessor template<class T> class row_accessor { public: typedef const_row_info<T> row_data; //------------------------------------------------------------------- row_accessor() : m_buf(0), m_start(0), m_width(0), m_height(0), m_stride(0) { } //-------------------------------------------------------------------- row_accessor(T* buf, unsigned width, unsigned height, int stride) : m_buf(0), m_start(0), m_width(0), m_height(0), m_stride(0) { attach(buf, width, height, stride); } //-------------------------------------------------------------------- void attach(T* buf, unsigned width, unsigned height, int stride) { m_buf = m_start = buf; m_width = width; m_height = height; m_stride = stride; if(stride < 0) { m_start = m_buf - int(height - 1) * stride; } } //-------------------------------------------------------------------- AGG_INLINE T* buf() { return m_buf; } AGG_INLINE const T* buf() const { return m_buf; } AGG_INLINE unsigned width() const { return m_width; } AGG_INLINE unsigned height() const { return m_height; } AGG_INLINE int stride() const { return m_stride; } AGG_INLINE unsigned stride_abs() const { return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); } //-------------------------------------------------------------------- AGG_INLINE T* row_ptr(int, int y, unsigned) { return m_start + y * m_stride; } AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; } AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; } AGG_INLINE row_data row (int y) const { return row_data(0, m_width-1, row_ptr(y)); } //-------------------------------------------------------------------- template<class RenBuf> void copy_from(const RenBuf& src) { unsigned h = height(); if(src.height() < h) h = src.height(); unsigned l = stride_abs(); if(src.stride_abs() < l) l = src.stride_abs(); l *= sizeof(T); unsigned y; unsigned w = width(); for (y = 0; y < h; y++) { memcpy(row_ptr(0, y, w), src.row_ptr(y), l); } } //-------------------------------------------------------------------- void clear(T value) { unsigned y; unsigned w = width(); unsigned stride = stride_abs(); for(y = 0; y < height(); y++) { T* p = row_ptr(0, y, w); unsigned x; for(x = 0; x < stride; x++) { *p++ = value; } } } private: //-------------------------------------------------------------------- T* m_buf; // Pointer to renrdering buffer T* m_start; // Pointer to first pixel depending on stride unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels int m_stride; // Number of bytes per row. Can be < 0 }; //==========================================================row_ptr_cache template<class T> class row_ptr_cache { public: typedef const_row_info<T> row_data; //------------------------------------------------------------------- row_ptr_cache() : m_buf(0), m_rows(), m_width(0), m_height(0), m_stride(0) { } //-------------------------------------------------------------------- row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : m_buf(0), m_rows(), m_width(0), m_height(0), m_stride(0) { attach(buf, width, height, stride); } //-------------------------------------------------------------------- void attach(T* buf, unsigned width, unsigned height, int stride) { m_buf = buf; m_width = width; m_height = height; m_stride = stride; if(height > m_rows.size()) { m_rows.resize(height); } T* row_ptr = m_buf; if(stride < 0) { row_ptr = m_buf - int(height - 1) * stride; } T** rows = &m_rows[0]; while(height--) { *rows++ = row_ptr; row_ptr += stride; } } //-------------------------------------------------------------------- AGG_INLINE T* buf() { return m_buf; } AGG_INLINE const T* buf() const { return m_buf; } AGG_INLINE unsigned width() const { return m_width; } AGG_INLINE unsigned height() const { return m_height; } AGG_INLINE int stride() const { return m_stride; } AGG_INLINE unsigned stride_abs() const { return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); } //-------------------------------------------------------------------- AGG_INLINE T* row_ptr(int, int y, unsigned) { return m_rows[y]; } AGG_INLINE T* row_ptr(int y) { return m_rows[y]; } AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; } AGG_INLINE row_data row (int y) const { return row_data(0, m_width-1, m_rows[y]); } //-------------------------------------------------------------------- T const* const* rows() const { return &m_rows[0]; } //-------------------------------------------------------------------- template<class RenBuf> void copy_from(const RenBuf& src) { unsigned h = height(); if(src.height() < h) h = src.height(); unsigned l = stride_abs(); if(src.stride_abs() < l) l = src.stride_abs(); l *= sizeof(T); unsigned y; unsigned w = width(); for (y = 0; y < h; y++) { memcpy(row_ptr(0, y, w), src.row_ptr(y), l); } } //-------------------------------------------------------------------- void clear(T value) { unsigned y; unsigned w = width(); unsigned stride = stride_abs(); for(y = 0; y < height(); y++) { T* p = row_ptr(0, y, w); unsigned x; for(x = 0; x < stride; x++) { *p++ = value; } } } private: //-------------------------------------------------------------------- T* m_buf; // Pointer to renrdering buffer pod_array<T*> m_rows; // Pointers to each row of the buffer unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels int m_stride; // Number of bytes per row. Can be < 0 }; //========================================================rendering_buffer // // The definition of the main type for accessing the rows in the frame // buffer. It provides functionality to navigate to the rows in a // rectangular matrix, from top to bottom or from bottom to top depending // on stride. // // row_accessor is cheap to create/destroy, but performs one multiplication // when calling row_ptr(). // // row_ptr_cache creates an array of pointers to rows, so, the access // via row_ptr() may be faster. But it requires memory allocation // when creating. For example, on typical Intel Pentium hardware // row_ptr_cache speeds span_image_filter_rgb_nn up to 10% // // It's used only in short hand typedefs like pixfmt_rgba32 and can be // redefined in agg_config.h // In real applications you can use both, depending on your needs //------------------------------------------------------------------------ #ifdef AGG_RENDERING_BUFFER typedef AGG_RENDERING_BUFFER rendering_buffer; #else // typedef row_ptr_cache<int8u> rendering_buffer; typedef row_accessor<int8u> rendering_buffer; #endif } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_ellipse_bresenham.h���������������������������������������0000644�0024617�0000144�00000005431�12261257215�024141� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Simple Bresenham interpolator for ellipsees // //---------------------------------------------------------------------------- #ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED #define AGG_ELLIPSE_BRESENHAM_INCLUDED #include "agg_basics.h" namespace mapserver { //------------------------------------------ellipse_bresenham_interpolator class ellipse_bresenham_interpolator { public: ellipse_bresenham_interpolator(int rx, int ry) : m_rx2(rx * rx), m_ry2(ry * ry), m_two_rx2(m_rx2 << 1), m_two_ry2(m_ry2 << 1), m_dx(0), m_dy(0), m_inc_x(0), m_inc_y(-ry * m_two_rx2), m_cur_f(0) {} int dx() const { return m_dx; } int dy() const { return m_dy; } void operator++ () { int mx, my, mxy, min_m; int fx, fy, fxy; mx = fx = m_cur_f + m_inc_x + m_ry2; if(mx < 0) mx = -mx; my = fy = m_cur_f + m_inc_y + m_rx2; if(my < 0) my = -my; mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2; if(mxy < 0) mxy = -mxy; min_m = mx; bool flag = true; if(min_m > my) { min_m = my; flag = false; } m_dx = m_dy = 0; if(min_m > mxy) { m_inc_x += m_two_ry2; m_inc_y += m_two_rx2; m_cur_f = fxy; m_dx = 1; m_dy = 1; return; } if(flag) { m_inc_x += m_two_ry2; m_cur_f = fx; m_dx = 1; return; } m_inc_y += m_two_rx2; m_cur_f = fy; m_dy = 1; } private: int m_rx2; int m_ry2; int m_two_rx2; int m_two_ry2; int m_dx; int m_dy; int m_inc_x; int m_inc_y; int m_cur_f; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pattern_filters_rgba.h������������������������������������0000644�0024617�0000144�00000010041�12261257215�024651� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED #define AGG_PATTERN_FILTERS_RGBA8_INCLUDED #include "agg_basics.h" #include "agg_line_aa_basics.h" #include "agg_color_rgba.h" namespace mapserver { //=======================================================pattern_filter_nn template<class ColorT> struct pattern_filter_nn { typedef ColorT color_type; static unsigned dilation() { return 0; } static void AGG_INLINE pixel_low_res(color_type const* const* buf, color_type* p, int x, int y) { *p = buf[y][x]; } static void AGG_INLINE pixel_high_res(color_type const* const* buf, color_type* p, int x, int y) { *p = buf[y >> line_subpixel_shift] [x >> line_subpixel_shift]; } }; typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8; typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16; //===========================================pattern_filter_bilinear_rgba template<class ColorT> struct pattern_filter_bilinear_rgba { typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; static unsigned dilation() { return 1; } static AGG_INLINE void pixel_low_res(color_type const* const* buf, color_type* p, int x, int y) { *p = buf[y][x]; } static AGG_INLINE void pixel_high_res(color_type const* const* buf, color_type* p, int x, int y) { calc_type r, g, b, a; r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2; calc_type weight; int x_lr = x >> line_subpixel_shift; int y_lr = y >> line_subpixel_shift; x &= line_subpixel_mask; y &= line_subpixel_mask; const color_type* ptr = buf[y_lr] + x_lr; weight = (line_subpixel_scale - x) * (line_subpixel_scale - y); r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; a += weight * ptr->a; ++ptr; weight = x * (line_subpixel_scale - y); r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; a += weight * ptr->a; ptr = buf[y_lr + 1] + x_lr; weight = (line_subpixel_scale - x) * y; r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; a += weight * ptr->a; ++ptr; weight = x * y; r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; a += weight * ptr->a; p->r = (value_type)(r >> line_subpixel_shift * 2); p->g = (value_type)(g >> line_subpixel_shift * 2); p->b = (value_type)(b >> line_subpixel_shift * 2); p->a = (value_type)(a >> line_subpixel_shift * 2); } }; typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8; typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/util/���������������������������������������������������������0000755�0024617�0000144�00000000000�12261257215�020443� 5����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/util/agg_color_conv.h�����������������������������������������0000644�0024617�0000144�00000004571�12261257215�023604� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Conversion from one colorspace/pixel format to another // //---------------------------------------------------------------------------- #ifndef AGG_COLOR_CONV_INCLUDED #define AGG_COLOR_CONV_INCLUDED #include <string.h> #include "agg_basics.h" #include "agg_rendering_buffer.h" namespace mapserver { //--------------------------------------------------------------color_conv template<class RenBuf, class CopyRow> void color_conv(RenBuf* dst, const RenBuf* src, CopyRow copy_row_functor) { unsigned width = src->width(); unsigned height = src->height(); if(dst->width() < width) width = dst->width(); if(dst->height() < height) height = dst->height(); if(width) { unsigned y; for(y = 0; y < height; y++) { copy_row_functor(dst->row_ptr(0, y, width), src->row_ptr(y), width); } } } //---------------------------------------------------------color_conv_row template<class CopyRow> void color_conv_row(int8u* dst, const int8u* src, unsigned width, CopyRow copy_row_functor) { copy_row_functor(dst, src, width); } //---------------------------------------------------------color_conv_same template<int BPP> class color_conv_same { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { memmove(dst, src, width*BPP); } }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/util/agg_color_conv_rgb8.h������������������������������������0000644�0024617�0000144�00000042651�12261257215�024527� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // A set of functors used with color_conv(). See file agg_color_conv.h // These functors can convert images with up to 8 bits per component. // Use convertors in the following way: // // mapserver::color_conv(dst, src, mapserver::color_conv_XXXX_to_YYYY()); // whare XXXX and YYYY can be any of: // rgb24 // bgr24 // rgba32 // abgr32 // argb32 // bgra32 // rgb555 // rgb565 //---------------------------------------------------------------------------- #ifndef AGG_COLOR_CONV_RGB8_INCLUDED #define AGG_COLOR_CONV_RGB8_INCLUDED #include "agg_basics.h" #include "agg_color_conv.h" namespace mapserver { //-----------------------------------------------------color_conv_rgb24 class color_conv_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *dst++ = src[2]; *dst++ = src[1]; *dst++ = src[0]; src += 3; } while(--width); } }; typedef color_conv_rgb24 color_conv_rgb24_to_bgr24; typedef color_conv_rgb24 color_conv_bgr24_to_rgb24; typedef color_conv_same<3> color_conv_bgr24_to_bgr24; typedef color_conv_same<3> color_conv_rgb24_to_rgb24; //------------------------------------------------------color_conv_rgba32 template<int I1, int I2, int I3, int I4> class color_conv_rgba32 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *dst++ = src[I1]; *dst++ = src[I2]; *dst++ = src[I3]; *dst++ = src[I4]; src += 4; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgba32<0,3,2,1> color_conv_argb32_to_abgr32; //----color_conv_argb32_to_abgr32 typedef color_conv_rgba32<3,2,1,0> color_conv_argb32_to_bgra32; //----color_conv_argb32_to_bgra32 typedef color_conv_rgba32<1,2,3,0> color_conv_argb32_to_rgba32; //----color_conv_argb32_to_rgba32 typedef color_conv_rgba32<3,0,1,2> color_conv_bgra32_to_abgr32; //----color_conv_bgra32_to_abgr32 typedef color_conv_rgba32<3,2,1,0> color_conv_bgra32_to_argb32; //----color_conv_bgra32_to_argb32 typedef color_conv_rgba32<2,1,0,3> color_conv_bgra32_to_rgba32; //----color_conv_bgra32_to_rgba32 typedef color_conv_rgba32<3,2,1,0> color_conv_rgba32_to_abgr32; //----color_conv_rgba32_to_abgr32 typedef color_conv_rgba32<3,0,1,2> color_conv_rgba32_to_argb32; //----color_conv_rgba32_to_argb32 typedef color_conv_rgba32<2,1,0,3> color_conv_rgba32_to_bgra32; //----color_conv_rgba32_to_bgra32 typedef color_conv_rgba32<0,3,2,1> color_conv_abgr32_to_argb32; //----color_conv_abgr32_to_argb32 typedef color_conv_rgba32<1,2,3,0> color_conv_abgr32_to_bgra32; //----color_conv_abgr32_to_bgra32 typedef color_conv_rgba32<3,2,1,0> color_conv_abgr32_to_rgba32; //----color_conv_abgr32_to_rgba32 //------------------------------------------------------------------------ typedef color_conv_same<4> color_conv_rgba32_to_rgba32; //----color_conv_rgba32_to_rgba32 typedef color_conv_same<4> color_conv_argb32_to_argb32; //----color_conv_argb32_to_argb32 typedef color_conv_same<4> color_conv_bgra32_to_bgra32; //----color_conv_bgra32_to_bgra32 typedef color_conv_same<4> color_conv_abgr32_to_abgr32; //----color_conv_abgr32_to_abgr32 //--------------------------------------------color_conv_rgb24_rgba32 template<int I1, int I2, int I3, int A> class color_conv_rgb24_rgba32 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { dst[I1] = *src++; dst[I2] = *src++; dst[I3] = *src++; dst[A] = 255; dst += 4; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_rgb24_to_argb32; //----color_conv_rgb24_to_argb32 typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_rgb24_to_abgr32; //----color_conv_rgb24_to_abgr32 typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_rgb24_to_bgra32; //----color_conv_rgb24_to_bgra32 typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_rgb24_to_rgba32; //----color_conv_rgb24_to_rgba32 typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_bgr24_to_argb32; //----color_conv_bgr24_to_argb32 typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_bgr24_to_abgr32; //----color_conv_bgr24_to_abgr32 typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_bgr24_to_bgra32; //----color_conv_bgr24_to_bgra32 typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_bgr24_to_rgba32; //----color_conv_bgr24_to_rgba32 //-------------------------------------------------color_conv_rgba32_rgb24 template<int I1, int I2, int I3> class color_conv_rgba32_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *dst++ = src[I1]; *dst++ = src[I2]; *dst++ = src[I3]; src += 4; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgba32_rgb24<1,2,3> color_conv_argb32_to_rgb24; //----color_conv_argb32_to_rgb24 typedef color_conv_rgba32_rgb24<3,2,1> color_conv_abgr32_to_rgb24; //----color_conv_abgr32_to_rgb24 typedef color_conv_rgba32_rgb24<2,1,0> color_conv_bgra32_to_rgb24; //----color_conv_bgra32_to_rgb24 typedef color_conv_rgba32_rgb24<0,1,2> color_conv_rgba32_to_rgb24; //----color_conv_rgba32_to_rgb24 typedef color_conv_rgba32_rgb24<3,2,1> color_conv_argb32_to_bgr24; //----color_conv_argb32_to_bgr24 typedef color_conv_rgba32_rgb24<1,2,3> color_conv_abgr32_to_bgr24; //----color_conv_abgr32_to_bgr24 typedef color_conv_rgba32_rgb24<0,1,2> color_conv_bgra32_to_bgr24; //----color_conv_bgra32_to_bgr24 typedef color_conv_rgba32_rgb24<2,1,0> color_conv_rgba32_to_bgr24; //----color_conv_rgba32_to_bgr24 //------------------------------------------------color_conv_rgb555_rgb24 template<int R, int B> class color_conv_rgb555_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { unsigned rgb = *(int16u*)src; dst[R] = (int8u)((rgb >> 7) & 0xF8); dst[1] = (int8u)((rgb >> 2) & 0xF8); dst[B] = (int8u)((rgb << 3) & 0xF8); src += 2; dst += 3; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb555_rgb24<2,0> color_conv_rgb555_to_bgr24; //----color_conv_rgb555_to_bgr24 typedef color_conv_rgb555_rgb24<0,2> color_conv_rgb555_to_rgb24; //----color_conv_rgb555_to_rgb24 //-------------------------------------------------color_conv_rgb24_rgb555 template<int R, int B> class color_conv_rgb24_rgb555 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) | ((unsigned(src[1]) << 2) & 0x3E0) | ((unsigned(src[B]) >> 3))); src += 3; dst += 2; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb24_rgb555<2,0> color_conv_bgr24_to_rgb555; //----color_conv_bgr24_to_rgb555 typedef color_conv_rgb24_rgb555<0,2> color_conv_rgb24_to_rgb555; //----color_conv_rgb24_to_rgb555 //-------------------------------------------------color_conv_rgb565_rgb24 template<int R, int B> class color_conv_rgb565_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { unsigned rgb = *(int16u*)src; dst[R] = (rgb >> 8) & 0xF8; dst[1] = (rgb >> 3) & 0xFC; dst[B] = (rgb << 3) & 0xF8; src += 2; dst += 3; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb565_rgb24<2,0> color_conv_rgb565_to_bgr24; //----color_conv_rgb565_to_bgr24 typedef color_conv_rgb565_rgb24<0,2> color_conv_rgb565_to_rgb24; //----color_conv_rgb565_to_rgb24 //-------------------------------------------------color_conv_rgb24_rgb565 template<int R, int B> class color_conv_rgb24_rgb565 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) | ((unsigned(src[1]) << 3) & 0x7E0) | ((unsigned(src[B]) >> 3))); src += 3; dst += 2; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb24_rgb565<2,0> color_conv_bgr24_to_rgb565; //----color_conv_bgr24_to_rgb565 typedef color_conv_rgb24_rgb565<0,2> color_conv_rgb24_to_rgb565; //----color_conv_rgb24_to_rgb565 //-------------------------------------------------color_conv_rgb555_rgba32 template<int R, int G, int B, int A> class color_conv_rgb555_rgba32 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { int rgb = *(int16*)src; dst[R] = (int8u)((rgb >> 7) & 0xF8); dst[G] = (int8u)((rgb >> 2) & 0xF8); dst[B] = (int8u)((rgb << 3) & 0xF8); dst[A] = (int8u)(rgb >> 15); src += 2; dst += 4; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb555_rgba32<1,2,3,0> color_conv_rgb555_to_argb32; //----color_conv_rgb555_to_argb32 typedef color_conv_rgb555_rgba32<3,2,1,0> color_conv_rgb555_to_abgr32; //----color_conv_rgb555_to_abgr32 typedef color_conv_rgb555_rgba32<2,1,0,3> color_conv_rgb555_to_bgra32; //----color_conv_rgb555_to_bgra32 typedef color_conv_rgb555_rgba32<0,1,2,3> color_conv_rgb555_to_rgba32; //----color_conv_rgb555_to_rgba32 //------------------------------------------------color_conv_rgba32_rgb555 template<int R, int G, int B, int A> class color_conv_rgba32_rgb555 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) | ((unsigned(src[G]) << 2) & 0x3E0) | ((unsigned(src[B]) >> 3)) | ((unsigned(src[A]) << 8) & 0x8000)); src += 4; dst += 2; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgba32_rgb555<1,2,3,0> color_conv_argb32_to_rgb555; //----color_conv_argb32_to_rgb555 typedef color_conv_rgba32_rgb555<3,2,1,0> color_conv_abgr32_to_rgb555; //----color_conv_abgr32_to_rgb555 typedef color_conv_rgba32_rgb555<2,1,0,3> color_conv_bgra32_to_rgb555; //----color_conv_bgra32_to_rgb555 typedef color_conv_rgba32_rgb555<0,1,2,3> color_conv_rgba32_to_rgb555; //----color_conv_rgba32_to_rgb555 //------------------------------------------------color_conv_rgb565_rgba32 template<int R, int G, int B, int A> class color_conv_rgb565_rgba32 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { int rgb = *(int16*)src; dst[R] = (rgb >> 8) & 0xF8; dst[G] = (rgb >> 3) & 0xFC; dst[B] = (rgb << 3) & 0xF8; dst[A] = 255; src += 2; dst += 4; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb565_rgba32<1,2,3,0> color_conv_rgb565_to_argb32; //----color_conv_rgb565_to_argb32 typedef color_conv_rgb565_rgba32<3,2,1,0> color_conv_rgb565_to_abgr32; //----color_conv_rgb565_to_abgr32 typedef color_conv_rgb565_rgba32<2,1,0,3> color_conv_rgb565_to_bgra32; //----color_conv_rgb565_to_bgra32 typedef color_conv_rgb565_rgba32<0,1,2,3> color_conv_rgb565_to_rgba32; //----color_conv_rgb565_to_rgba32 //------------------------------------------------color_conv_rgba32_rgb565 template<int R, int G, int B> class color_conv_rgba32_rgb565 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) | ((unsigned(src[G]) << 3) & 0x7E0) | ((unsigned(src[B]) >> 3))); src += 4; dst += 2; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgba32_rgb565<1,2,3> color_conv_argb32_to_rgb565; //----color_conv_argb32_to_rgb565 typedef color_conv_rgba32_rgb565<3,2,1> color_conv_abgr32_to_rgb565; //----color_conv_abgr32_to_rgb565 typedef color_conv_rgba32_rgb565<2,1,0> color_conv_bgra32_to_rgb565; //----color_conv_bgra32_to_rgb565 typedef color_conv_rgba32_rgb565<0,1,2> color_conv_rgba32_to_rgb565; //----color_conv_rgba32_to_rgb565 //---------------------------------------------color_conv_rgb555_to_rgb565 class color_conv_rgb555_to_rgb565 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { unsigned rgb = *(int16u*)src; *(int16u*)dst = (int16u)(((rgb << 1) & 0xFFC0) | (rgb & 0x1F)); src += 2; dst += 2; } while(--width); } }; //----------------------------------------------color_conv_rgb565_to_rgb555 class color_conv_rgb565_to_rgb555 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { unsigned rgb = *(int16u*)src; *(int16u*)dst = (int16u)(((rgb >> 1) & 0x7FE0) | (rgb & 0x1F)); src += 2; dst += 2; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_same<2> color_conv_rgb555_to_rgb555; //----color_conv_rgb555_to_rgb555 typedef color_conv_same<2> color_conv_rgb565_to_rgb565; //----color_conv_rgb565_to_rgb565 template<int R, int B> class color_conv_rgb24_gray8 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *dst++ = (src[R]*77 + src[1]*150 + src[B]*29) >> 8; src += 3; } while(--width); } }; typedef color_conv_rgb24_gray8<0,2> color_conv_rgb24_to_gray8; //----color_conv_rgb24_to_gray8 typedef color_conv_rgb24_gray8<2,0> color_conv_bgr24_to_gray8; //----color_conv_bgr24_to_gray8 } #endif ���������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/util/agg_color_conv_rgb16.h�����������������������������������0000644�0024617�0000144�00000024737�12261257215�024613� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // This part of the library has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- // // A set of functors used with color_conv(). See file agg_color_conv.h // These functors can convert images with up to 8 bits per component. // Use convertors in the following way: // // mapserver::color_conv(dst, src, mapserver::color_conv_XXXX_to_YYYY()); //---------------------------------------------------------------------------- #ifndef AGG_COLOR_CONV_RGB16_INCLUDED #define AGG_COLOR_CONV_RGB16_INCLUDED #include "agg_basics.h" #include "agg_color_conv.h" namespace mapserver { //-------------------------------------------------color_conv_gray16_to_gray8 class color_conv_gray16_to_gray8 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { int16u* s = (int16u*)src; do { *dst++ = *s++ >> 8; } while(--width); } }; //-----------------------------------------------------color_conv_rgb24_rgb48 template<int I1, int I3> class color_conv_rgb24_rgb48 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { int16u* d = (int16u*)dst; do { *d++ = (src[I1] << 8) | src[I1]; *d++ = (src[1] << 8) | src[1] ; *d++ = (src[I3] << 8) | src[I3]; src += 3; } while(--width); } }; typedef color_conv_rgb24_rgb48<0,2> color_conv_rgb24_to_rgb48; typedef color_conv_rgb24_rgb48<0,2> color_conv_bgr24_to_bgr48; typedef color_conv_rgb24_rgb48<2,0> color_conv_rgb24_to_bgr48; typedef color_conv_rgb24_rgb48<2,0> color_conv_bgr24_to_rgb48; //-----------------------------------------------------color_conv_rgb24_rgb48 template<int I1, int I3> class color_conv_rgb48_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { const int16u* s = (const int16u*)src; do { *dst++ = s[I1] >> 8; *dst++ = s[1] >> 8; *dst++ = s[I3] >> 8; s += 3; } while(--width); } }; typedef color_conv_rgb48_rgb24<0,2> color_conv_rgb48_to_rgb24; typedef color_conv_rgb48_rgb24<0,2> color_conv_bgr48_to_bgr24; typedef color_conv_rgb48_rgb24<2,0> color_conv_rgb48_to_bgr24; typedef color_conv_rgb48_rgb24<2,0> color_conv_bgr48_to_rgb24; //----------------------------------------------color_conv_rgbAAA_rgb24 template<int R, int B> class color_conv_rgbAAA_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { int32u rgb = *(int32u*)src; dst[R] = int8u(rgb >> 22); dst[1] = int8u(rgb >> 12); dst[B] = int8u(rgb >> 2); src += 4; dst += 3; } while(--width); } }; typedef color_conv_rgbAAA_rgb24<0,2> color_conv_rgbAAA_to_rgb24; typedef color_conv_rgbAAA_rgb24<2,0> color_conv_rgbAAA_to_bgr24; typedef color_conv_rgbAAA_rgb24<2,0> color_conv_bgrAAA_to_rgb24; typedef color_conv_rgbAAA_rgb24<0,2> color_conv_bgrAAA_to_bgr24; //----------------------------------------------color_conv_rgbBBA_rgb24 template<int R, int B> class color_conv_rgbBBA_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { int32u rgb = *(int32u*)src; dst[R] = int8u(rgb >> 24); dst[1] = int8u(rgb >> 13); dst[B] = int8u(rgb >> 2); src += 4; dst += 3; } while(--width); } }; typedef color_conv_rgbBBA_rgb24<0,2> color_conv_rgbBBA_to_rgb24; typedef color_conv_rgbBBA_rgb24<2,0> color_conv_rgbBBA_to_bgr24; //----------------------------------------------color_conv_bgrABB_rgb24 template<int B, int R> class color_conv_bgrABB_rgb24 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { int32u bgr = *(int32u*)src; dst[R] = int8u(bgr >> 3); dst[1] = int8u(bgr >> 14); dst[B] = int8u(bgr >> 24); src += 4; dst += 3; } while(--width); } }; typedef color_conv_bgrABB_rgb24<2,0> color_conv_bgrABB_to_rgb24; typedef color_conv_bgrABB_rgb24<0,2> color_conv_bgrABB_to_bgr24; //-------------------------------------------------color_conv_rgba64_rgba32 template<int I1, int I2, int I3, int I4> class color_conv_rgba64_rgba32 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { do { *dst++ = int8u(((int16u*)src)[I1] >> 8); *dst++ = int8u(((int16u*)src)[I2] >> 8); *dst++ = int8u(((int16u*)src)[I3] >> 8); *dst++ = int8u(((int16u*)src)[I4] >> 8); src += 8; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_rgba64_to_rgba32; //----color_conv_rgba64_to_rgba32 typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_argb64_to_argb32; //----color_conv_argb64_to_argb32 typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_bgra64_to_bgra32; //----color_conv_bgra64_to_bgra32 typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_abgr64_to_abgr32; //----color_conv_abgr64_to_abgr32 typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_argb64_to_abgr32; //----color_conv_argb64_to_abgr32 typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_argb64_to_bgra32; //----color_conv_argb64_to_bgra32 typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_argb64_to_rgba32; //----color_conv_argb64_to_rgba32 typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_bgra64_to_abgr32; //----color_conv_bgra64_to_abgr32 typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_bgra64_to_argb32; //----color_conv_bgra64_to_argb32 typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_bgra64_to_rgba32; //----color_conv_bgra64_to_rgba32 typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_rgba64_to_abgr32; //----color_conv_rgba64_to_abgr32 typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_rgba64_to_argb32; //----color_conv_rgba64_to_argb32 typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_rgba64_to_bgra32; //----color_conv_rgba64_to_bgra32 typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_abgr64_to_argb32; //----color_conv_abgr64_to_argb32 typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_abgr64_to_bgra32; //----color_conv_abgr64_to_bgra32 typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_abgr64_to_rgba32; //----color_conv_abgr64_to_rgba32 //--------------------------------------------color_conv_rgb24_rgba64 template<int I1, int I2, int I3, int A> class color_conv_rgb24_rgba64 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { int16u* d = (int16u*)dst; do { d[I1] = (src[0] << 8) | src[0]; d[I2] = (src[1] << 8) | src[1]; d[I3] = (src[2] << 8) | src[2]; d[A] = 65535; d += 4; src += 3; } while(--width); } }; //------------------------------------------------------------------------ typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_rgb24_to_argb64; //----color_conv_rgb24_to_argb64 typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_rgb24_to_abgr64; //----color_conv_rgb24_to_abgr64 typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_rgb24_to_bgra64; //----color_conv_rgb24_to_bgra64 typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_rgb24_to_rgba64; //----color_conv_rgb24_to_rgba64 typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_bgr24_to_argb64; //----color_conv_bgr24_to_argb64 typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_bgr24_to_abgr64; //----color_conv_bgr24_to_abgr64 typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_bgr24_to_bgra64; //----color_conv_bgr24_to_bgra64 typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_bgr24_to_rgba64; //----color_conv_bgr24_to_rgba64 template<int R, int B> class color_conv_rgb24_gray16 { public: void operator () (int8u* dst, const int8u* src, unsigned width) const { int16u* d = (int16u*)dst; do { *d++ = src[R]*77 + src[1]*150 + src[B]*29; src += 3; } while(--width); } }; typedef color_conv_rgb24_gray16<0,2> color_conv_rgb24_to_gray16; typedef color_conv_rgb24_gray16<2,0> color_conv_bgr24_to_gray16; } #endif ���������������������������������mapserver-6.4.1/renderers/agg/include/util/Makefile.am����������������������������������������������0000644�0024617�0000144�00000000171�12261257215�022476� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������myincludedir = $(includedir)/agg2/util myinclude_HEADERS = agg_color_conv.h agg_color_conv_rgb8.h agg_color_conv_rgb16.h �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rasterizer_cells_aa.h�������������������������������������0000644�0024617�0000144�00000051635�12261257215�024504� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // // The author gratefully acknowleges the support of David Turner, // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED #define AGG_RASTERIZER_CELLS_AA_INCLUDED #include <string.h> #include <math.h> #include "agg_math.h" #include "agg_array.h" namespace mapserver { //-----------------------------------------------------rasterizer_cells_aa // An internal class that implements the main rasterization algorithm. // Used in the rasterizer. Should not be used direcly. template<class Cell> class rasterizer_cells_aa { enum cell_block_scale_e { cell_block_shift = 12, cell_block_size = 1 << cell_block_shift, cell_block_mask = cell_block_size - 1, cell_block_pool = 256, cell_block_limit = 1024 }; struct sorted_y { unsigned start; unsigned num; }; public: typedef Cell cell_type; typedef rasterizer_cells_aa<Cell> self_type; ~rasterizer_cells_aa(); rasterizer_cells_aa(); void reset(); void style(const cell_type& style_cell); void line(int x1, int y1, int x2, int y2); int min_x() const { return m_min_x; } int min_y() const { return m_min_y; } int max_x() const { return m_max_x; } int max_y() const { return m_max_y; } void sort_cells(); unsigned total_cells() const { return m_num_cells; } unsigned scanline_num_cells(unsigned y) const { return m_sorted_y[y - m_min_y].num; } const cell_type* const* scanline_cells(unsigned y) const { return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start; } bool sorted() const { return m_sorted; } private: rasterizer_cells_aa(const self_type&); const self_type& operator = (const self_type&); void set_curr_cell(int x, int y); void add_curr_cell(); void render_hline(int ey, int x1, int y1, int x2, int y2); void allocate_block(); private: unsigned m_num_blocks; unsigned m_max_blocks; unsigned m_curr_block; unsigned m_num_cells; cell_type** m_cells; cell_type* m_curr_cell_ptr; pod_vector<cell_type*> m_sorted_cells; pod_vector<sorted_y> m_sorted_y; cell_type m_curr_cell; cell_type m_style_cell; int m_min_x; int m_min_y; int m_max_x; int m_max_y; bool m_sorted; }; //------------------------------------------------------------------------ template<class Cell> rasterizer_cells_aa<Cell>::~rasterizer_cells_aa() { if(m_num_blocks) { cell_type** ptr = m_cells + m_num_blocks - 1; while(m_num_blocks--) { pod_allocator<cell_type>::deallocate(*ptr, cell_block_size); ptr--; } pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks); } } //------------------------------------------------------------------------ template<class Cell> rasterizer_cells_aa<Cell>::rasterizer_cells_aa() : m_num_blocks(0), m_max_blocks(0), m_curr_block(0), m_num_cells(0), m_cells(0), m_curr_cell_ptr(0), m_sorted_cells(), m_sorted_y(), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF), m_sorted(false) { m_style_cell.initial(); m_curr_cell.initial(); } //------------------------------------------------------------------------ template<class Cell> void rasterizer_cells_aa<Cell>::reset() { m_num_cells = 0; m_curr_block = 0; m_curr_cell.initial(); m_style_cell.initial(); m_sorted = false; m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; m_max_y = -0x7FFFFFFF; } //------------------------------------------------------------------------ template<class Cell> AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell() { if(m_curr_cell.area | m_curr_cell.cover) { if((m_num_cells & cell_block_mask) == 0) { if(m_num_blocks >= cell_block_limit) return; allocate_block(); } *m_curr_cell_ptr++ = m_curr_cell; ++m_num_cells; } } //------------------------------------------------------------------------ template<class Cell> AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y) { if(m_curr_cell.not_equal(x, y, m_style_cell)) { add_curr_cell(); m_curr_cell.style(m_style_cell); m_curr_cell.x = x; m_curr_cell.y = y; m_curr_cell.cover = 0; m_curr_cell.area = 0; } } //------------------------------------------------------------------------ template<class Cell> AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey, int x1, int y1, int x2, int y2) { int ex1 = x1 >> poly_subpixel_shift; int ex2 = x2 >> poly_subpixel_shift; int fx1 = x1 & poly_subpixel_mask; int fx2 = x2 & poly_subpixel_mask; int delta, p, first, dx; int incr, lift, mod, rem; //trivial case. Happens often if(y1 == y2) { set_curr_cell(ex2, ey); return; } //everything is located in a single cell. That is easy! if(ex1 == ex2) { delta = y2 - y1; m_curr_cell.cover += delta; m_curr_cell.area += (fx1 + fx2) * delta; return; } //ok, we'll have to render a run of adjacent cells on the same //hline... p = (poly_subpixel_scale - fx1) * (y2 - y1); first = poly_subpixel_scale; incr = 1; dx = x2 - x1; if(dx < 0) { p = fx1 * (y2 - y1); first = 0; incr = -1; dx = -dx; } delta = p / dx; mod = p % dx; if(mod < 0) { delta--; mod += dx; } m_curr_cell.cover += delta; m_curr_cell.area += (fx1 + first) * delta; ex1 += incr; set_curr_cell(ex1, ey); y1 += delta; if(ex1 != ex2) { p = poly_subpixel_scale * (y2 - y1 + delta); lift = p / dx; rem = p % dx; if (rem < 0) { lift--; rem += dx; } mod -= dx; while (ex1 != ex2) { delta = lift; mod += rem; if(mod >= 0) { mod -= dx; delta++; } m_curr_cell.cover += delta; m_curr_cell.area += poly_subpixel_scale * delta; y1 += delta; ex1 += incr; set_curr_cell(ex1, ey); } } delta = y2 - y1; m_curr_cell.cover += delta; m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta; } //------------------------------------------------------------------------ template<class Cell> AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell) { m_style_cell.style(style_cell); } //------------------------------------------------------------------------ template<class Cell> void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2) { enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift }; int dx = x2 - x1; if(dx >= dx_limit || dx <= -dx_limit) { int cx = (x1 + x2) >> 1; int cy = (y1 + y2) >> 1; line(x1, y1, cx, cy); line(cx, cy, x2, y2); } int dy = y2 - y1; int ex1 = x1 >> poly_subpixel_shift; int ex2 = x2 >> poly_subpixel_shift; int ey1 = y1 >> poly_subpixel_shift; int ey2 = y2 >> poly_subpixel_shift; int fy1 = y1 & poly_subpixel_mask; int fy2 = y2 & poly_subpixel_mask; int x_from, x_to; int p, rem, mod, lift, delta, first, incr; if(ex1 < m_min_x) m_min_x = ex1; if(ex1 > m_max_x) m_max_x = ex1; if(ey1 < m_min_y) m_min_y = ey1; if(ey1 > m_max_y) m_max_y = ey1; if(ex2 < m_min_x) m_min_x = ex2; if(ex2 > m_max_x) m_max_x = ex2; if(ey2 < m_min_y) m_min_y = ey2; if(ey2 > m_max_y) m_max_y = ey2; set_curr_cell(ex1, ey1); //everything is on a single hline if(ey1 == ey2) { render_hline(ey1, x1, fy1, x2, fy2); return; } //Vertical line - we have to calculate start and end cells, //and then - the common values of the area and coverage for //all cells of the line. We know exactly there's only one //cell, so, we don't have to call render_hline(). incr = 1; if(dx == 0) { int ex = x1 >> poly_subpixel_shift; int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1; int area; first = poly_subpixel_scale; if(dy < 0) { first = 0; incr = -1; } x_from = x1; //render_hline(ey1, x_from, fy1, x_from, first); delta = first - fy1; m_curr_cell.cover += delta; m_curr_cell.area += two_fx * delta; ey1 += incr; set_curr_cell(ex, ey1); delta = first + first - poly_subpixel_scale; area = two_fx * delta; while(ey1 != ey2) { //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first); m_curr_cell.cover = delta; m_curr_cell.area = area; ey1 += incr; set_curr_cell(ex, ey1); } //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2); delta = fy2 - poly_subpixel_scale + first; m_curr_cell.cover += delta; m_curr_cell.area += two_fx * delta; return; } //ok, we have to render several hlines p = (poly_subpixel_scale - fy1) * dx; first = poly_subpixel_scale; if(dy < 0) { p = fy1 * dx; first = 0; incr = -1; dy = -dy; } delta = p / dy; mod = p % dy; if(mod < 0) { delta--; mod += dy; } x_from = x1 + delta; render_hline(ey1, x1, fy1, x_from, first); ey1 += incr; set_curr_cell(x_from >> poly_subpixel_shift, ey1); if(ey1 != ey2) { p = poly_subpixel_scale * dx; lift = p / dy; rem = p % dy; if(rem < 0) { lift--; rem += dy; } mod -= dy; while(ey1 != ey2) { delta = lift; mod += rem; if (mod >= 0) { mod -= dy; delta++; } x_to = x_from + delta; render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first); x_from = x_to; ey1 += incr; set_curr_cell(x_from >> poly_subpixel_shift, ey1); } } render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2); } //------------------------------------------------------------------------ template<class Cell> void rasterizer_cells_aa<Cell>::allocate_block() { if(m_curr_block >= m_num_blocks) { if(m_num_blocks >= m_max_blocks) { cell_type** new_cells = pod_allocator<cell_type*>::allocate(m_max_blocks + cell_block_pool); if(m_cells) { memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks); } m_cells = new_cells; m_max_blocks += cell_block_pool; } m_cells[m_num_blocks++] = pod_allocator<cell_type>::allocate(cell_block_size); } m_curr_cell_ptr = m_cells[m_curr_block++]; } //------------------------------------------------------------------------ template <class T> static AGG_INLINE void swap_cells(T* a, T* b) { T temp = *a; *a = *b; *b = temp; } //------------------------------------------------------------------------ enum { qsort_threshold = 9 }; //------------------------------------------------------------------------ template<class Cell> void qsort_cells(Cell** start, unsigned num) { Cell** stack[80]; Cell*** top; Cell** limit; Cell** base; limit = start + num; base = start; top = stack; for (;;) { int len = int(limit - base); Cell** i; Cell** j; Cell** pivot; if(len > qsort_threshold) { // we use base + len/2 as the pivot pivot = base + len / 2; swap_cells(base, pivot); i = base + 1; j = limit - 1; // now ensure that *i <= *base <= *j if((*j)->x < (*i)->x) { swap_cells(i, j); } if((*base)->x < (*i)->x) { swap_cells(base, i); } if((*j)->x < (*base)->x) { swap_cells(base, j); } for(;;) { int x = (*base)->x; do i++; while( (*i)->x < x ); do j--; while( x < (*j)->x ); if(i > j) { break; } swap_cells(i, j); } swap_cells(base, j); // now, push the largest sub-array if(j - base > limit - i) { top[0] = base; top[1] = j; base = i; } else { top[0] = i; top[1] = limit; limit = j; } top += 2; } else { // the sub-array is small, perform insertion sort j = base; i = j + 1; for(; i < limit; j = i, i++) { for(; j[1]->x < (*j)->x; j--) { swap_cells(j + 1, j); if (j == base) { break; } } } if(top > stack) { top -= 2; base = top[0]; limit = top[1]; } else { break; } } } } //------------------------------------------------------------------------ template<class Cell> void rasterizer_cells_aa<Cell>::sort_cells() { if(m_sorted) return; //Perform sort only the first time. add_curr_cell(); m_curr_cell.x = 0x7FFFFFFF; m_curr_cell.y = 0x7FFFFFFF; m_curr_cell.cover = 0; m_curr_cell.area = 0; if(m_num_cells == 0) return; // DBG: Check to see if min/max works well. //for(unsigned nc = 0; nc < m_num_cells; nc++) //{ // cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask); // if(cell->x < m_min_x || // cell->y < m_min_y || // cell->x > m_max_x || // cell->y > m_max_y) // { // cell = cell; // Breakpoint here // } //} // Allocate the array of cell pointers m_sorted_cells.allocate(m_num_cells, 16); // Allocate and zero the Y array m_sorted_y.allocate(m_max_y - m_min_y + 1, 16); m_sorted_y.zero(); // Create the Y-histogram (count the numbers of cells for each Y) cell_type** block_ptr = m_cells; cell_type* cell_ptr; unsigned nb = m_num_cells >> cell_block_shift; unsigned i; while(nb--) { cell_ptr = *block_ptr++; i = cell_block_size; while(i--) { m_sorted_y[cell_ptr->y - m_min_y].start++; ++cell_ptr; } } cell_ptr = *block_ptr++; i = m_num_cells & cell_block_mask; while(i--) { m_sorted_y[cell_ptr->y - m_min_y].start++; ++cell_ptr; } // Convert the Y-histogram into the array of starting indexes unsigned start = 0; for(i = 0; i < m_sorted_y.size(); i++) { unsigned v = m_sorted_y[i].start; m_sorted_y[i].start = start; start += v; } // Fill the cell pointer array sorted by Y block_ptr = m_cells; nb = m_num_cells >> cell_block_shift; while(nb--) { cell_ptr = *block_ptr++; i = cell_block_size; while(i--) { sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; ++curr_y.num; ++cell_ptr; } } cell_ptr = *block_ptr++; i = m_num_cells & cell_block_mask; while(i--) { sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; ++curr_y.num; ++cell_ptr; } // Finally arrange the X-arrays for(i = 0; i < m_sorted_y.size(); i++) { const sorted_y& curr_y = m_sorted_y[i]; if(curr_y.num) { qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num); } } m_sorted = true; } //------------------------------------------------------scanline_hit_test class scanline_hit_test { public: scanline_hit_test(int x) : m_x(x), m_hit(false) {} void reset_spans() {} void finalize(int) {} void add_cell(int x, int) { if(m_x == x) m_hit = true; } void add_span(int x, int len, int) { if(m_x >= x && m_x < x+len) m_hit = true; } unsigned num_spans() const { return 1; } bool hit() const { return m_hit; } private: int m_x; bool m_hit; }; } #endif ���������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_arc.h�����������������������������������������������������0000644�0024617�0000144�00000003770�12261257215�021231� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Arc vertex generator // //---------------------------------------------------------------------------- #ifndef AGG_ARC_INCLUDED #define AGG_ARC_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { //=====================================================================arc // // See Implementation agg_arc.cpp // class arc { public: arc() : m_scale(1.0), m_initialized(false) {} arc(double x, double y, double rx, double ry, double a1, double a2, bool ccw=true); void init(double x, double y, double rx, double ry, double a1, double a2, bool ccw=true); void approximation_scale(double s); double approximation_scale() const { return m_scale; } void rewind(unsigned); unsigned vertex(double* x, double* y); private: void normalize(double a1, double a2, bool ccw); double m_x; double m_y; double m_rx; double m_ry; double m_angle; double m_start; double m_end; double m_scale; double m_da; bool m_ccw; bool m_initialized; unsigned m_path_cmd; }; } #endif ��������mapserver-6.4.1/renderers/agg/include/agg_span_gradient_alpha.h�������������������������������������0000644�0024617�0000144�00000011520�12261257215�024437� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_GRADIENT_ALPHA_INCLUDED #define AGG_SPAN_GRADIENT_ALPHA_INCLUDED #include "agg_span_gradient.h" namespace mapserver { //======================================================span_gradient_alpha template<class ColorT, class Interpolator, class GradientF, class AlphaF> class span_gradient_alpha { public: typedef Interpolator interpolator_type; typedef ColorT color_type; typedef typename color_type::value_type alpha_type; enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift }; //-------------------------------------------------------------------- span_gradient_alpha() {} //-------------------------------------------------------------------- span_gradient_alpha(interpolator_type& inter, const GradientF& gradient_function, const AlphaF& alpha_function, double d1, double d2) : m_interpolator(&inter), m_gradient_function(&gradient_function), m_alpha_function(&alpha_function), m_d1(iround(d1 * gradient_subpixel_scale)), m_d2(iround(d2 * gradient_subpixel_scale)) {} //-------------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } const GradientF& gradient_function() const { return *m_gradient_function; } const AlphaF& alpha_function() const { return *m_alpha_function; } double d1() const { return double(m_d1) / gradient_subpixel_scale; } double d2() const { return double(m_d2) / gradient_subpixel_scale; } //-------------------------------------------------------------------- void interpolator(interpolator_type& i) { m_interpolator = &i; } void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ } void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } //-------------------------------------------------------------------- void prepare() {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { int dd = m_d2 - m_d1; if(dd < 1) dd = 1; m_interpolator->begin(x+0.5, y+0.5, len); do { m_interpolator->coordinates(&x, &y); int d = m_gradient_function->calculate(x >> downscale_shift, y >> downscale_shift, m_d2); d = ((d - m_d1) * (int)m_alpha_function->size()) / dd; if(d < 0) d = 0; if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1; span->a = (*m_alpha_function)[d]; ++span; ++(*m_interpolator); } while(--len); } private: interpolator_type* m_interpolator; const GradientF* m_gradient_function; const AlphaF* m_alpha_function; int m_d1; int m_d2; }; //=======================================================gradient_alpha_x template<class ColorT> struct gradient_alpha_x { typedef typename ColorT::value_type alpha_type; alpha_type operator [] (alpha_type x) const { return x; } }; //====================================================gradient_alpha_x_u8 struct gradient_alpha_x_u8 { typedef int8u alpha_type; alpha_type operator [] (alpha_type x) const { return x; } }; //==========================================gradient_alpha_one_munus_x_u8 struct gradient_alpha_one_munus_x_u8 { typedef int8u alpha_type; alpha_type operator [] (alpha_type x) const { return 255-x; } }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_clip_polyline.h��������������������������������������0000644�0024617�0000144�00000004752�12261257215�024354� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // polyline clipping converter // There an optimized Liang-Basky algorithm is used. // The algorithm doesn't optimize the degenerate edges, i.e. it will never // break a closed polyline into two or more ones, instead, there will be // degenerate edges coinciding with the respective clipping boundaries. // This is a sub-optimal solution, because that optimization would require // extra, rather expensive math while the rasterizer tolerates it quite well, // without any considerable overhead. // //---------------------------------------------------------------------------- #ifndef AGG_CONV_CLIP_polyline_INCLUDED #define AGG_CONV_CLIP_polyline_INCLUDED #include "agg_basics.h" #include "agg_conv_adaptor_vpgen.h" #include "agg_vpgen_clip_polyline.h" namespace mapserver { //=======================================================conv_clip_polyline template<class VertexSource> struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> { typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type; conv_clip_polyline(VertexSource& vs) : conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {} void clip_box(double x1, double y1, double x2, double y2) { base_type::vpgen().clip_box(x1, y1, x2, y2); } double x1() const { return base_type::vpgen().x1(); } double y1() const { return base_type::vpgen().y1(); } double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } private: conv_clip_polyline(const conv_clip_polyline<VertexSource>&); const conv_clip_polyline<VertexSource>& operator = (const conv_clip_polyline<VertexSource>&); }; } #endif ����������������������mapserver-6.4.1/renderers/agg/include/agg_image_accessors.h�����������������������������������������0000644�0024617�0000144�00000031601�12261257215�023605� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_IMAGE_ACCESSORS_INCLUDED #define AGG_IMAGE_ACCESSORS_INCLUDED #include "agg_basics.h" namespace mapserver { //-----------------------------------------------------image_accessor_clip template<class PixFmt> class image_accessor_clip { public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::order_type order_type; typedef typename pixfmt_type::value_type value_type; enum pix_width_e { pix_width = pixfmt_type::pix_width }; image_accessor_clip() {} explicit image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) : m_pixf(&pixf) { pixfmt_type::make_pix(m_bk_buf, bk); } void attach(const pixfmt_type& pixf) { m_pixf = &pixf; } void background_color(const color_type& bk) { pixfmt_type::make_pix(m_bk_buf, bk); } private: AGG_INLINE const int8u* pixel() const { if(m_y >= 0 && m_y < (int)m_pixf->height() && m_x >= 0 && m_x < (int)m_pixf->width()) { return m_pixf->pix_ptr(m_x, m_y); } return m_bk_buf; } public: AGG_INLINE const int8u* span(int x, int y, unsigned len) { m_x = m_x0 = x; m_y = y; if(y >= 0 && y < (int)m_pixf->height() && x >= 0 && x+(int)len <= (int)m_pixf->width()) { return m_pix_ptr = m_pixf->pix_ptr(x, y); } m_pix_ptr = 0; return pixel(); } AGG_INLINE const int8u* next_x() { if(m_pix_ptr) return m_pix_ptr += pix_width; ++m_x; return pixel(); } AGG_INLINE const int8u* next_y() { ++m_y; m_x = m_x0; if(m_pix_ptr && m_y >= 0 && m_y < (int)m_pixf->height()) { return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); } m_pix_ptr = 0; return pixel(); } private: const pixfmt_type* m_pixf; int8u m_bk_buf[4]; int m_x, m_x0, m_y; const int8u* m_pix_ptr; }; //--------------------------------------------------image_accessor_no_clip template<class PixFmt> class image_accessor_no_clip { public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::order_type order_type; typedef typename pixfmt_type::value_type value_type; enum pix_width_e { pix_width = pixfmt_type::pix_width }; image_accessor_no_clip() {} explicit image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {} void attach(const pixfmt_type& pixf) { m_pixf = &pixf; } AGG_INLINE const int8u* span(int x, int y, unsigned) { m_x = x; m_y = y; return m_pix_ptr = m_pixf->pix_ptr(x, y); } AGG_INLINE const int8u* next_x() { return m_pix_ptr += pix_width; } AGG_INLINE const int8u* next_y() { ++m_y; return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); } private: const pixfmt_type* m_pixf; int m_x, m_y; const int8u* m_pix_ptr; }; //----------------------------------------------------image_accessor_clone template<class PixFmt> class image_accessor_clone { public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::order_type order_type; typedef typename pixfmt_type::value_type value_type; enum pix_width_e { pix_width = pixfmt_type::pix_width }; image_accessor_clone() {} explicit image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {} void attach(const pixfmt_type& pixf) { m_pixf = &pixf; } private: AGG_INLINE const int8u* pixel() const { register int x = m_x; register int y = m_y; if(x < 0) x = 0; if(y < 0) y = 0; if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1; if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1; return m_pixf->pix_ptr(x, y); } public: AGG_INLINE const int8u* span(int x, int y, unsigned len) { m_x = m_x0 = x; m_y = y; if(y >= 0 && y < (int)m_pixf->height() && x >= 0 && x+len <= (int)m_pixf->width()) { return m_pix_ptr = m_pixf->pix_ptr(x, y); } m_pix_ptr = 0; return pixel(); } AGG_INLINE const int8u* next_x() { if(m_pix_ptr) return m_pix_ptr += pix_width; ++m_x; return pixel(); } AGG_INLINE const int8u* next_y() { ++m_y; m_x = m_x0; if(m_pix_ptr && m_y >= 0 && m_y < (int)m_pixf->height()) { return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); } m_pix_ptr = 0; return pixel(); } private: const pixfmt_type* m_pixf; int m_x, m_x0, m_y; const int8u* m_pix_ptr; }; //-----------------------------------------------------image_accessor_wrap template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap { public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::order_type order_type; typedef typename pixfmt_type::value_type value_type; enum pix_width_e { pix_width = pixfmt_type::pix_width }; image_accessor_wrap() {} explicit image_accessor_wrap(const pixfmt_type& pixf) : m_pixf(&pixf), m_wrap_x(pixf.width()), m_wrap_y(pixf.height()) {} void attach(const pixfmt_type& pixf) { m_pixf = &pixf; } AGG_INLINE const int8u* span(int x, int y, unsigned) { m_x = x; m_row_ptr = m_pixf->row_ptr(m_wrap_y(y)); return m_row_ptr + m_wrap_x(x) * pix_width; } AGG_INLINE const int8u* next_x() { int x = ++m_wrap_x; return m_row_ptr + x * pix_width; } AGG_INLINE const int8u* next_y() { m_row_ptr = m_pixf->row_ptr(++m_wrap_y); return m_row_ptr + m_wrap_x(m_x) * pix_width; } private: const pixfmt_type* m_pixf; const int8u* m_row_ptr; int m_x; WrapX m_wrap_x; WrapY m_wrap_y; }; //--------------------------------------------------------wrap_mode_repeat class wrap_mode_repeat { public: wrap_mode_repeat() {} wrap_mode_repeat(unsigned size) : m_size(size), m_add(size * (0x3FFFFFFF / size)), m_value(0) {} AGG_INLINE unsigned operator() (int v) { return m_value = (unsigned(v) + m_add) % m_size; } AGG_INLINE unsigned operator++ () { ++m_value; if(m_value >= m_size) m_value = 0; return m_value; } private: unsigned m_size; unsigned m_add; unsigned m_value; }; //---------------------------------------------------wrap_mode_repeat_pow2 class wrap_mode_repeat_pow2 { public: wrap_mode_repeat_pow2() {} wrap_mode_repeat_pow2(unsigned size) : m_value(0) { m_mask = 1; while(m_mask < size) m_mask = (m_mask << 1) | 1; m_mask >>= 1; } AGG_INLINE unsigned operator() (int v) { return m_value = unsigned(v) & m_mask; } AGG_INLINE unsigned operator++ () { ++m_value; if(m_value > m_mask) m_value = 0; return m_value; } private: unsigned m_mask; unsigned m_value; }; //----------------------------------------------wrap_mode_repeat_auto_pow2 class wrap_mode_repeat_auto_pow2 { public: wrap_mode_repeat_auto_pow2() {} wrap_mode_repeat_auto_pow2(unsigned size) : m_size(size), m_add(size * (0x3FFFFFFF / size)), m_mask((m_size & (m_size-1)) ? 0 : m_size-1), m_value(0) {} AGG_INLINE unsigned operator() (int v) { if(m_mask) return m_value = unsigned(v) & m_mask; return m_value = (unsigned(v) + m_add) % m_size; } AGG_INLINE unsigned operator++ () { ++m_value; if(m_value >= m_size) m_value = 0; return m_value; } private: unsigned m_size; unsigned m_add; unsigned m_mask; unsigned m_value; }; //-------------------------------------------------------wrap_mode_reflect class wrap_mode_reflect { public: wrap_mode_reflect() {} wrap_mode_reflect(unsigned size) : m_size(size), m_size2(size * 2), m_add(m_size2 * (0x3FFFFFFF / m_size2)), m_value(0) {} AGG_INLINE unsigned operator() (int v) { m_value = (unsigned(v) + m_add) % m_size2; if(m_value >= m_size) return m_size2 - m_value - 1; return m_value; } AGG_INLINE unsigned operator++ () { ++m_value; if(m_value >= m_size2) m_value = 0; if(m_value >= m_size) return m_size2 - m_value - 1; return m_value; } private: unsigned m_size; unsigned m_size2; unsigned m_add; unsigned m_value; }; //--------------------------------------------------wrap_mode_reflect_pow2 class wrap_mode_reflect_pow2 { public: wrap_mode_reflect_pow2() {} wrap_mode_reflect_pow2(unsigned size) : m_value(0) { m_mask = 1; m_size = 1; while(m_mask < size) { m_mask = (m_mask << 1) | 1; m_size <<= 1; } } AGG_INLINE unsigned operator() (int v) { m_value = unsigned(v) & m_mask; if(m_value >= m_size) return m_mask - m_value; return m_value; } AGG_INLINE unsigned operator++ () { ++m_value; m_value &= m_mask; if(m_value >= m_size) return m_mask - m_value; return m_value; } private: unsigned m_size; unsigned m_mask; unsigned m_value; }; //---------------------------------------------wrap_mode_reflect_auto_pow2 class wrap_mode_reflect_auto_pow2 { public: wrap_mode_reflect_auto_pow2() {} wrap_mode_reflect_auto_pow2(unsigned size) : m_size(size), m_size2(size * 2), m_add(m_size2 * (0x3FFFFFFF / m_size2)), m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), m_value(0) {} AGG_INLINE unsigned operator() (int v) { m_value = m_mask ? unsigned(v) & m_mask : (unsigned(v) + m_add) % m_size2; if(m_value >= m_size) return m_size2 - m_value - 1; return m_value; } AGG_INLINE unsigned operator++ () { ++m_value; if(m_value >= m_size2) m_value = 0; if(m_value >= m_size) return m_size2 - m_value - 1; return m_value; } private: unsigned m_size; unsigned m_size2; unsigned m_add; unsigned m_mask; unsigned m_value; }; } #endif �������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_vertex_sequence.h�����������������������������������0000644�0024617�0000144�00000007376�12261257215�025061� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED #define AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" #include "agg_shorten_path.h" namespace mapserver { //===================================================vcgen_vertex_sequence class vcgen_vertex_sequence { public: typedef vertex_dist_cmd vertex_type; typedef vertex_sequence<vertex_type, 6> vertex_storage; vcgen_vertex_sequence() : m_flags(0), m_cur_vertex(0), m_shorten(0.0), m_ready(false) { } // Vertex Generator Interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); void shorten(double s) { m_shorten = s; } double shorten() const { return m_shorten; } private: vcgen_vertex_sequence(const vcgen_vertex_sequence&); const vcgen_vertex_sequence& operator = (const vcgen_vertex_sequence&); vertex_storage m_src_vertices; unsigned m_flags; unsigned m_cur_vertex; double m_shorten; bool m_ready; }; //------------------------------------------------------------------------ inline void vcgen_vertex_sequence::remove_all() { m_ready = false; m_src_vertices.remove_all(); m_cur_vertex = 0; m_flags = 0; } //------------------------------------------------------------------------ inline void vcgen_vertex_sequence::add_vertex(double x, double y, unsigned cmd) { m_ready = false; if(is_move_to(cmd)) { m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd)); } else { if(is_vertex(cmd)) { m_src_vertices.add(vertex_dist_cmd(x, y, cmd)); } else { m_flags = cmd & path_flags_mask; } } } //------------------------------------------------------------------------ inline void vcgen_vertex_sequence::rewind(unsigned) { if(!m_ready) { m_src_vertices.close(is_closed(m_flags)); shorten_path(m_src_vertices, m_shorten, get_close_flag(m_flags)); } m_ready = true; m_cur_vertex = 0; } //------------------------------------------------------------------------ inline unsigned vcgen_vertex_sequence::vertex(double* x, double* y) { if(!m_ready) { rewind(0); } if(m_cur_vertex == m_src_vertices.size()) { ++m_cur_vertex; return path_cmd_end_poly | m_flags; } if(m_cur_vertex > m_src_vertices.size()) { return path_cmd_stop; } vertex_type& v = m_src_vertices[m_cur_vertex++]; *x = v.x; *y = v.y; return v.cmd; } } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_bitset_iterator.h�����������������������������������������0000644�0024617�0000144�00000002622�12261257215�023662� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_BITSET_ITERATOR_INCLUDED #define AGG_BITSET_ITERATOR_INCLUDED #include "agg_basics.h" namespace mapserver { class bitset_iterator { public: bitset_iterator(const int8u* bits, unsigned offset = 0) : m_bits(bits + (offset >> 3)), m_mask(0x80 >> (offset & 7)) {} void operator ++ () { m_mask >>= 1; if(m_mask == 0) { ++m_bits; m_mask = 0x80; } } unsigned bit() const { return (*m_bits) & m_mask; } private: const int8u* m_bits; int8u m_mask; }; } #endif ��������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_concat.h���������������������������������������������0000644�0024617�0000144�00000004303�12261257215�022751� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_CONCAT_INCLUDED #define AGG_CONV_CONCAT_INCLUDED #include "agg_basics.h" namespace mapserver { //=============================================================conv_concat // Concatenation of two paths. Usually used to combine lines or curves // with markers such as arrowheads template<class VS1, class VS2> class conv_concat { public: conv_concat(VS1& source1, VS2& source2) : m_source1(&source1), m_source2(&source2), m_status(2) {} void attach1(VS1& source) { m_source1 = &source; } void attach2(VS2& source) { m_source2 = &source; } void rewind(unsigned path_id) { m_source1->rewind(path_id); m_source2->rewind(0); m_status = 0; } unsigned vertex(double* x, double* y) { unsigned cmd; if(m_status == 0) { cmd = m_source1->vertex(x, y); if(!is_stop(cmd)) return cmd; m_status = 1; } if(m_status == 1) { cmd = m_source2->vertex(x, y); if(!is_stop(cmd)) return cmd; m_status = 2; } return path_cmd_stop; } private: conv_concat(const conv_concat<VS1, VS2>&); const conv_concat<VS1, VS2>& operator = (const conv_concat<VS1, VS2>&); VS1* m_source1; VS2* m_source2; int m_status; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_image_filter_gray.h����������������������������������0000644�0024617�0000144�00000070471�12261257215�025160� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED #define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED #include "agg_basics.h" #include "agg_color_gray.h" #include "agg_span_image_filter.h" namespace mapserver { //==============================================span_image_filter_gray_nn template<class Source, class Interpolator> class span_image_filter_gray_nn : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_gray_nn() {} span_image_filter_gray_nn(source_type& src, interpolator_type& inter) : base_type(src, inter, 0) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); do { base_type::interpolator().coordinates(&x, &y); span->v = *(const value_type*) base_type::source().span(x >> image_subpixel_shift, y >> image_subpixel_shift, 1); span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //=========================================span_image_filter_gray_bilinear template<class Source, class Interpolator> class span_image_filter_gray_bilinear : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_gray_bilinear() {} span_image_filter_gray_bilinear(source_type& src, interpolator_type& inter) : base_type(src, inter, 0) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg; const value_type *fg_ptr; do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; fg = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); fg_ptr = (const value_type*)base_type::source().next_x(); fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); fg_ptr = (const value_type*)base_type::source().next_y(); fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; fg_ptr = (const value_type*)base_type::source().next_x(); fg += *fg_ptr * x_hr * y_hr; span->v = value_type(fg >> (image_subpixel_shift * 2)); span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //====================================span_image_filter_gray_bilinear_clip template<class Source, class Interpolator> class span_image_filter_gray_bilinear_clip : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_gray_bilinear_clip() {} span_image_filter_gray_bilinear_clip(source_type& src, const color_type& back_color, interpolator_type& inter) : base_type(src, inter, 0), m_back_color(back_color) {} const color_type& background_color() const { return m_back_color; } void background_color(const color_type& v) { m_back_color = v; } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg; calc_type src_alpha; value_type back_v = m_back_color.v; value_type back_a = m_back_color.a; const value_type *fg_ptr; int maxx = base_type::source().width() - 1; int maxy = base_type::source().height() - 1; do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; if(x_lr >= 0 && y_lr >= 0 && x_lr < maxx && y_lr < maxy) { fg = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; ++y_lr; fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; fg += *fg_ptr++ * x_hr * y_hr; fg >>= image_subpixel_shift * 2; src_alpha = base_mask; } else { unsigned weight; if(x_lr < -1 || y_lr < -1 || x_lr > maxx || y_lr > maxy) { fg = back_v; src_alpha = back_a; } else { fg = src_alpha = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg += weight * *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else { fg += back_v * weight; src_alpha += back_a * weight; } x_lr++; weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg += weight * *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else { fg += back_v * weight; src_alpha += back_a * weight; } x_lr--; y_lr++; weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg += weight * *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else { fg += back_v * weight; src_alpha += back_a * weight; } x_lr++; weight = x_hr * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg += weight * *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else { fg += back_v * weight; src_alpha += back_a * weight; } fg >>= image_subpixel_shift * 2; src_alpha >>= image_subpixel_shift * 2; } } span->v = (value_type)fg; span->a = (value_type)src_alpha; ++span; ++base_type::interpolator(); } while(--len); } private: color_type m_back_color; }; //==============================================span_image_filter_gray_2x2 template<class Source, class Interpolator> class span_image_filter_gray_2x2 : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_gray_2x2() {} span_image_filter_gray_2x2(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg; const value_type *fg_ptr; const int16* weight_array = base_type::filter().weight_array() + ((base_type::filter().diameter()/2 - 1) << image_subpixel_shift); do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; fg = image_filter_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); weight = (weight_array[x_hr + image_subpixel_scale] * weight_array[y_hr + image_subpixel_scale] + image_filter_scale / 2) >> image_filter_shift; fg += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = (weight_array[x_hr] * weight_array[y_hr + image_subpixel_scale] + image_filter_scale / 2) >> image_filter_shift; fg += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_y(); weight = (weight_array[x_hr + image_subpixel_scale] * weight_array[y_hr] + image_filter_scale / 2) >> image_filter_shift; fg += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = (weight_array[x_hr] * weight_array[y_hr] + image_filter_scale / 2) >> image_filter_shift; fg += weight * *fg_ptr; fg >>= image_filter_shift; if(fg > base_mask) fg = base_mask; span->v = (value_type)fg; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //==================================================span_image_filter_gray template<class Source, class Interpolator> class span_image_filter_gray : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_gray() {} span_image_filter_gray(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); int fg; const value_type *fg_ptr; unsigned diameter = base_type::filter().diameter(); int start = base_type::filter().start(); const int16* weight_array = base_type::filter().weight_array(); int x_count; int weight_y; do { base_type::interpolator().coordinates(&x, &y); x -= base_type::filter_dx_int(); y -= base_type::filter_dy_int(); int x_hr = x; int y_hr = y; int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; fg = image_filter_scale / 2; int x_fract = x_hr & image_subpixel_mask; unsigned y_count = diameter; y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); fg_ptr = (const value_type*)base_type::source().span(x_lr + start, y_lr + start, diameter); for(;;) { x_count = diameter; weight_y = weight_array[y_hr]; x_hr = image_subpixel_mask - x_fract; for(;;) { fg += *fg_ptr * ((weight_y * weight_array[x_hr] + image_filter_scale / 2) >> image_filter_shift); if(--x_count == 0) break; x_hr += image_subpixel_scale; fg_ptr = (const value_type*)base_type::source().next_x(); } if(--y_count == 0) break; y_hr += image_subpixel_scale; fg_ptr = (const value_type*)base_type::source().next_y(); } fg >>= image_filter_shift; if(fg < 0) fg = 0; if(fg > base_mask) fg = base_mask; span->v = (value_type)fg; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //=========================================span_image_resample_gray_affine template<class Source> class span_image_resample_gray_affine : public span_image_resample_affine<Source> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef span_image_resample_affine<source_type> base_type; typedef typename base_type::interpolator_type interpolator_type; typedef typename color_type::value_type value_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask, downscale_shift = image_filter_shift }; //-------------------------------------------------------------------- span_image_resample_gray_affine() {} span_image_resample_gray_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg; int diameter = base_type::filter().diameter(); int filter_scale = diameter << image_subpixel_shift; int radius_x = (diameter * base_type::m_rx) >> 1; int radius_y = (diameter * base_type::m_ry) >> 1; int len_x_lr = (diameter * base_type::m_rx + image_subpixel_mask) >> image_subpixel_shift; const int16* weight_array = base_type::filter().weight_array(); do { base_type::interpolator().coordinates(&x, &y); x += base_type::filter_dx_int() - radius_x; y += base_type::filter_dy_int() - radius_y; fg = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * base_type::m_ry_inv) >> image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * base_type::m_rx_inv) >> image_subpixel_shift; int x_hr2 = x_hr; const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { int weight_y = weight_array[y_hr]; x_hr = x_hr2; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; fg += *fg_ptr * weight; total_weight += weight; x_hr += base_type::m_rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); } y_hr += base_type::m_ry_inv; if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } fg /= total_weight; if(fg < 0) fg = 0; if(fg > base_mask) fg = base_mask; span->v = (value_type)fg; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //================================================span_image_resample_gray template<class Source, class Interpolator> class span_image_resample_gray : public span_image_resample<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; typedef span_image_resample<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask, downscale_shift = image_filter_shift }; //-------------------------------------------------------------------- span_image_resample_gray() {} span_image_resample_gray(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg; int diameter = base_type::filter().diameter(); int filter_scale = diameter << image_subpixel_shift; const int16* weight_array = base_type::filter().weight_array(); do { int rx; int ry; int rx_inv = image_subpixel_scale; int ry_inv = image_subpixel_scale; base_type::interpolator().coordinates(&x, &y); base_type::interpolator().local_scale(&rx, &ry); base_type::adjust_scale(&rx, &ry); rx_inv = image_subpixel_scale * image_subpixel_scale / rx; ry_inv = image_subpixel_scale * image_subpixel_scale / ry; int radius_x = (diameter * rx) >> 1; int radius_y = (diameter * ry) >> 1; int len_x_lr = (diameter * rx + image_subpixel_mask) >> image_subpixel_shift; x += base_type::filter_dx_int() - radius_x; y += base_type::filter_dy_int() - radius_y; fg = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * ry_inv) >> image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * rx_inv) >> image_subpixel_shift; int x_hr2 = x_hr; const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { int weight_y = weight_array[y_hr]; x_hr = x_hr2; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; fg += *fg_ptr * weight; total_weight += weight; x_hr += rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); } y_hr += ry_inv; if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } fg /= total_weight; if(fg < 0) fg = 0; if(fg > base_mask) fg = base_mask; span->v = (value_type)fg; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_gradient.h�������������������������������������������0000644�0024617�0000144�00000027237�12261257215�023306� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_GRADIENT_INCLUDED #define AGG_SPAN_GRADIENT_INCLUDED #include <math.h> #include <stdlib.h> #include <string.h> #include "agg_basics.h" #include "agg_math.h" #include "agg_array.h" namespace mapserver { enum gradient_subpixel_scale_e { gradient_subpixel_shift = 4, //-----gradient_subpixel_shift gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask }; //==========================================================span_gradient template<class ColorT, class Interpolator, class GradientF, class ColorF> class span_gradient { public: typedef Interpolator interpolator_type; typedef ColorT color_type; enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift }; //-------------------------------------------------------------------- span_gradient() {} //-------------------------------------------------------------------- span_gradient(interpolator_type& inter, const GradientF& gradient_function, const ColorF& color_function, double d1, double d2) : m_interpolator(&inter), m_gradient_function(&gradient_function), m_color_function(&color_function), m_d1(iround(d1 * gradient_subpixel_scale)), m_d2(iround(d2 * gradient_subpixel_scale)) {} //-------------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } const GradientF& gradient_function() const { return *m_gradient_function; } const ColorF& color_function() const { return *m_color_function; } double d1() const { return double(m_d1) / gradient_subpixel_scale; } double d2() const { return double(m_d2) / gradient_subpixel_scale; } //-------------------------------------------------------------------- void interpolator(interpolator_type& i) { m_interpolator = &i; } void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } void color_function(const ColorF& cf) { m_color_function = &cf; } void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } //-------------------------------------------------------------------- void prepare() {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { int dd = m_d2 - m_d1; if(dd < 1) dd = 1; m_interpolator->begin(x+0.5, y+0.5, len); do { m_interpolator->coordinates(&x, &y); int d = m_gradient_function->calculate(x >> downscale_shift, y >> downscale_shift, m_d2); d = ((d - m_d1) * (int)m_color_function->size()) / dd; if(d < 0) d = 0; if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1; *span++ = (*m_color_function)[d]; ++(*m_interpolator); } while(--len); } private: interpolator_type* m_interpolator; const GradientF* m_gradient_function; const ColorF* m_color_function; int m_d1; int m_d2; }; //=====================================================gradient_linear_color template<class ColorT> struct gradient_linear_color { typedef ColorT color_type; gradient_linear_color() {} gradient_linear_color(const color_type& c1, const color_type& c2, unsigned size = 256) : m_c1(c1), m_c2(c2), m_size(size) {} unsigned size() const { return m_size; } color_type operator [] (unsigned v) const { return m_c1.gradient(m_c2, double(v) / double(m_size - 1)); } void colors(const color_type& c1, const color_type& c2, unsigned size = 256) { m_c1 = c1; m_c2 = c2; m_size = size; } color_type m_c1; color_type m_c2; unsigned m_size; }; //==========================================================gradient_circle class gradient_circle { // Actually the same as radial. Just for compatibility public: static AGG_INLINE int calculate(int x, int y, int) { return int(fast_sqrt(x*x + y*y)); } }; //==========================================================gradient_radial class gradient_radial { public: static AGG_INLINE int calculate(int x, int y, int) { return int(fast_sqrt(x*x + y*y)); } }; //========================================================gradient_radial_d class gradient_radial_d { public: static AGG_INLINE int calculate(int x, int y, int) { return uround(sqrt(double(x)*double(x) + double(y)*double(y))); } }; //====================================================gradient_radial_focus class gradient_radial_focus { public: //--------------------------------------------------------------------- gradient_radial_focus() : m_r(100 * gradient_subpixel_scale), m_fx(0), m_fy(0) { update_values(); } //--------------------------------------------------------------------- gradient_radial_focus(double r, double fx, double fy) : m_r (iround(r * gradient_subpixel_scale)), m_fx(iround(fx * gradient_subpixel_scale)), m_fy(iround(fy * gradient_subpixel_scale)) { update_values(); } //--------------------------------------------------------------------- void init(double r, double fx, double fy) { m_r = iround(r * gradient_subpixel_scale); m_fx = iround(fx * gradient_subpixel_scale); m_fy = iround(fy * gradient_subpixel_scale); update_values(); } //--------------------------------------------------------------------- double radius() const { return double(m_r) / gradient_subpixel_scale; } double focus_x() const { return double(m_fx) / gradient_subpixel_scale; } double focus_y() const { return double(m_fy) / gradient_subpixel_scale; } //--------------------------------------------------------------------- int calculate(int x, int y, int) const { double dx = x - m_fx; double dy = y - m_fy; double d2 = dx * m_fy - dy * m_fx; double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2; return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul); } private: //--------------------------------------------------------------------- void update_values() { // Calculate the invariant values. In case the focal center // lies exactly on the gradient circle the divisor degenerates // into zero. In this case we just move the focal center by // one subpixel unit possibly in the direction to the origin (0,0) // and calculate the values again. //------------------------- m_r2 = double(m_r) * double(m_r); m_fx2 = double(m_fx) * double(m_fx); m_fy2 = double(m_fy) * double(m_fy); double d = (m_r2 - (m_fx2 + m_fy2)); if(d == 0) { if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; } if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; } m_fx2 = double(m_fx) * double(m_fx); m_fy2 = double(m_fy) * double(m_fy); d = (m_r2 - (m_fx2 + m_fy2)); } m_mul = m_r / d; } int m_r; int m_fx; int m_fy; double m_r2; double m_fx2; double m_fy2; double m_mul; }; //==============================================================gradient_x class gradient_x { public: static int calculate(int x, int, int) { return x; } }; //==============================================================gradient_y class gradient_y { public: static int calculate(int, int y, int) { return y; } }; //========================================================gradient_diamond class gradient_diamond { public: static AGG_INLINE int calculate(int x, int y, int) { int ax = abs(x); int ay = abs(y); return ax > ay ? ax : ay; } }; //=============================================================gradient_xy class gradient_xy { public: static AGG_INLINE int calculate(int x, int y, int d) { return abs(x) * abs(y) / d; } }; //========================================================gradient_sqrt_xy class gradient_sqrt_xy { public: static AGG_INLINE int calculate(int x, int y, int) { return fast_sqrt(abs(x) * abs(y)); } }; //==========================================================gradient_conic class gradient_conic { public: static AGG_INLINE int calculate(int x, int y, int d) { return uround(fabs(atan2(double(y), double(x))) * double(d) / pi); } }; //=================================================gradient_repeat_adaptor template<class GradientF> class gradient_repeat_adaptor { public: gradient_repeat_adaptor(const GradientF& gradient) : m_gradient(&gradient) {} AGG_INLINE int calculate(int x, int y, int d) const { int ret = m_gradient->calculate(x, y, d) % d; if(ret < 0) ret += d; return ret; } private: const GradientF* m_gradient; }; //================================================gradient_reflect_adaptor template<class GradientF> class gradient_reflect_adaptor { public: gradient_reflect_adaptor(const GradientF& gradient) : m_gradient(&gradient) {} AGG_INLINE int calculate(int x, int y, int d) const { int d2 = d << 1; int ret = m_gradient->calculate(x, y, d) % d2; if(ret < 0) ret += d2; if(ret >= d) ret = d2 - ret; return ret; } private: const GradientF* m_gradient; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_clip_liang_barsky.h���������������������������������������0000644�0024617�0000144�00000022640�12261257215�024135� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Liang-Barsky clipping // //---------------------------------------------------------------------------- #ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED #define AGG_CLIP_LIANG_BARSKY_INCLUDED #include "agg_basics.h" namespace mapserver { //------------------------------------------------------------------------ enum clipping_flags_e { clipping_flags_x1_clipped = 4, clipping_flags_x2_clipped = 1, clipping_flags_y1_clipped = 8, clipping_flags_y2_clipped = 2, clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped, clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped }; //----------------------------------------------------------clipping_flags // Determine the clipping code of the vertex according to the // Cyrus-Beck line clipping algorithm // // | | // 0110 | 0010 | 0011 // | | // -------+--------+-------- clip_box.y2 // | | // 0100 | 0000 | 0001 // | | // -------+--------+-------- clip_box.y1 // | | // 1100 | 1000 | 1001 // | | // clip_box.x1 clip_box.x2 // // template<class T> inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box) { return (x > clip_box.x2) | ((y > clip_box.y2) << 1) | ((x < clip_box.x1) << 2) | ((y < clip_box.y1) << 3); } //--------------------------------------------------------clipping_flags_x template<class T> inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box) { return (x > clip_box.x2) | ((x < clip_box.x1) << 2); } //--------------------------------------------------------clipping_flags_y template<class T> inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box) { return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3); } //-------------------------------------------------------clip_liang_barsky template<class T> inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, const rect_base<T>& clip_box, T* x, T* y) { const double nearzero = 1e-30; double deltax = x2 - x1; double deltay = y2 - y1; double xin; double xout; double yin; double yout; double tinx; double tiny; double toutx; double touty; double tin1; double tin2; double tout1; unsigned np = 0; if(deltax == 0.0) { // bump off of the vertical deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; } if(deltay == 0.0) { // bump off of the horizontal deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; } if(deltax > 0.0) { // points to right xin = clip_box.x1; xout = clip_box.x2; } else { xin = clip_box.x2; xout = clip_box.x1; } if(deltay > 0.0) { // points up yin = clip_box.y1; yout = clip_box.y2; } else { yin = clip_box.y2; yout = clip_box.y1; } tinx = (xin - x1) / deltax; tiny = (yin - y1) / deltay; if (tinx < tiny) { // hits x first tin1 = tinx; tin2 = tiny; } else { // hits y first tin1 = tiny; tin2 = tinx; } if(tin1 <= 1.0) { if(0.0 < tin1) { *x++ = (T)xin; *y++ = (T)yin; ++np; } if(tin2 <= 1.0) { toutx = (xout - x1) / deltax; touty = (yout - y1) / deltay; tout1 = (toutx < touty) ? toutx : touty; if(tin2 > 0.0 || tout1 > 0.0) { if(tin2 <= tout1) { if(tin2 > 0.0) { if(tinx > tiny) { *x++ = (T)xin; *y++ = (T)(y1 + tinx * deltay); } else { *x++ = (T)(x1 + tiny * deltax); *y++ = (T)yin; } ++np; } if(tout1 < 1.0) { if(toutx < touty) { *x++ = (T)xout; *y++ = (T)(y1 + toutx * deltay); } else { *x++ = (T)(x1 + touty * deltax); *y++ = (T)yout; } } else { *x++ = x2; *y++ = y2; } ++np; } else { if(tinx > tiny) { *x++ = (T)xin; *y++ = (T)yout; } else { *x++ = (T)xout; *y++ = (T)yin; } ++np; } } } } return np; } //---------------------------------------------------------------------------- template<class T> bool clip_move_point(T x1, T y1, T x2, T y2, const rect_base<T>& clip_box, T* x, T* y, unsigned flags) { T bound; if(flags & clipping_flags_x_clipped) { if(x1 == x2) { return false; } bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2; *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1); *x = bound; } flags = clipping_flags_y(*y, clip_box); if(flags & clipping_flags_y_clipped) { if(y1 == y2) { return false; } bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2; *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1); *y = bound; } return true; } //-------------------------------------------------------clip_line_segment // Returns: ret >= 4 - Fully clipped // (ret & 1) != 0 - First point has been moved // (ret & 2) != 0 - Second point has been moved // template<class T> unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2, const rect_base<T>& clip_box) { unsigned f1 = clipping_flags(*x1, *y1, clip_box); unsigned f2 = clipping_flags(*x2, *y2, clip_box); unsigned ret = 0; if((f2 | f1) == 0) { // Fully visible return 0; } if((f1 & clipping_flags_x_clipped) != 0 && (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped)) { // Fully clipped return 4; } if((f1 & clipping_flags_y_clipped) != 0 && (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped)) { // Fully clipped return 4; } T tx1 = *x1; T ty1 = *y1; T tx2 = *x2; T ty2 = *y2; if(f1) { if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1)) { return 4; } if(*x1 == *x2 && *y1 == *y2) { return 4; } ret |= 1; } if(f2) { if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2)) { return 4; } if(*x1 == *x2 && *y1 == *y2) { return 4; } ret |= 2; } return ret; } } #endif ������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_gouraud_rgba.h���������������������������������������0000644�0024617�0000144�00000023124�12261257215�024141� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED #define AGG_SPAN_GOURAUD_RGBA_INCLUDED #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_dda_line.h" #include "agg_span_gouraud.h" namespace mapserver { //=======================================================span_gouraud_rgba template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT> { public: typedef ColorT color_type; typedef typename ColorT::value_type value_type; typedef span_gouraud<color_type> base_type; typedef typename base_type::coord_type coord_type; enum subpixel_scale_e { subpixel_shift = 4, subpixel_scale = 1 << subpixel_shift }; private: //-------------------------------------------------------------------- struct rgba_calc { void init(const coord_type& c1, const coord_type& c2) { m_x1 = c1.x - 0.5; m_y1 = c1.y - 0.5; m_dx = c2.x - c1.x; double dy = c2.y - c1.y; m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy; m_r1 = c1.color.r; m_g1 = c1.color.g; m_b1 = c1.color.b; m_a1 = c1.color.a; m_dr = c2.color.r - m_r1; m_dg = c2.color.g - m_g1; m_db = c2.color.b - m_b1; m_da = c2.color.a - m_a1; } void calc(double y) { double k = (y - m_y1) * m_1dy; if(k < 0.0) k = 0.0; if(k > 1.0) k = 1.0; m_r = m_r1 + iround(m_dr * k); m_g = m_g1 + iround(m_dg * k); m_b = m_b1 + iround(m_db * k); m_a = m_a1 + iround(m_da * k); m_x = iround((m_x1 + m_dx * k) * subpixel_scale); } double m_x1; double m_y1; double m_dx; double m_1dy; int m_r1; int m_g1; int m_b1; int m_a1; int m_dr; int m_dg; int m_db; int m_da; int m_r; int m_g; int m_b; int m_a; int m_x; }; public: //-------------------------------------------------------------------- span_gouraud_rgba() {} span_gouraud_rgba(const color_type& c1, const color_type& c2, const color_type& c3, double x1, double y1, double x2, double y2, double x3, double y3, double d = 0) : base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) {} //-------------------------------------------------------------------- void prepare() { coord_type coord[3]; base_type::arrange_vertices(coord); m_y2 = int(coord[1].y); m_swap = cross_product(coord[0].x, coord[0].y, coord[2].x, coord[2].y, coord[1].x, coord[1].y) < 0.0; m_rgba1.init(coord[0], coord[2]); m_rgba2.init(coord[0], coord[1]); m_rgba3.init(coord[1], coord[2]); } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); const rgba_calc* pc1 = &m_rgba1; const rgba_calc* pc2 = &m_rgba2; if(y <= m_y2) { // Bottom part of the triangle (first subtriangle) //------------------------- m_rgba2.calc(y + m_rgba2.m_1dy); } else { // Upper part (second subtriangle) m_rgba3.calc(y - m_rgba3.m_1dy); //------------------------- pc2 = &m_rgba3; } if(m_swap) { // It means that the triangle is oriented clockwise, // so that we need to swap the controlling structures //------------------------- const rgba_calc* t = pc2; pc2 = pc1; pc1 = t; } // Get the horizontal length with subpixel accuracy // and protect it from division by zero //------------------------- int nlen = abs(pc2->m_x - pc1->m_x); if(nlen <= 0) nlen = 1; dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen); dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen); dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen); dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); // Calculate the starting point of the gradient with subpixel // accuracy and correct (roll back) the interpolators. // This operation will also clip the beginning of the span // if necessary. //------------------------- int start = pc1->m_x - (x << subpixel_shift); r -= start; g -= start; b -= start; a -= start; nlen += start; int vr, vg, vb, va; enum lim_e { lim = color_type::base_mask }; // Beginning part of the span. Since we rolled back the // interpolators, the color values may have overflow. // So that, we render the beginning part with checking // for overflow. It lasts until "start" is positive; // typically it's 1-2 pixels, but may be more in some cases. //------------------------- while(len && start > 0) { vr = r.y(); vg = g.y(); vb = b.y(); va = a.y(); if(vr < 0) vr = 0; if(vr > lim) vr = lim; if(vg < 0) vg = 0; if(vg > lim) vg = lim; if(vb < 0) vb = 0; if(vb > lim) vb = lim; if(va < 0) va = 0; if(va > lim) va = lim; span->r = (value_type)vr; span->g = (value_type)vg; span->b = (value_type)vb; span->a = (value_type)va; r += subpixel_scale; g += subpixel_scale; b += subpixel_scale; a += subpixel_scale; nlen -= subpixel_scale; start -= subpixel_scale; ++span; --len; } // Middle part, no checking for overflow. // Actual spans can be longer than the calculated length // because of anti-aliasing, thus, the interpolators can // overflow. But while "nlen" is positive we are safe. //------------------------- while(len && nlen > 0) { span->r = (value_type)r.y(); span->g = (value_type)g.y(); span->b = (value_type)b.y(); span->a = (value_type)a.y(); r += subpixel_scale; g += subpixel_scale; b += subpixel_scale; a += subpixel_scale; nlen -= subpixel_scale; ++span; --len; } // Ending part; checking for overflow. // Typically it's 1-2 pixels, but may be more in some cases. //------------------------- while(len) { vr = r.y(); vg = g.y(); vb = b.y(); va = a.y(); if(vr < 0) vr = 0; if(vr > lim) vr = lim; if(vg < 0) vg = 0; if(vg > lim) vg = lim; if(vb < 0) vb = 0; if(vb > lim) vb = lim; if(va < 0) va = 0; if(va > lim) va = lim; span->r = (value_type)vr; span->g = (value_type)vg; span->b = (value_type)vb; span->a = (value_type)va; r += subpixel_scale; g += subpixel_scale; b += subpixel_scale; a += subpixel_scale; ++span; --len; } } private: bool m_swap; int m_y2; rgba_calc m_rgba1; rgba_calc m_rgba2; rgba_calc m_rgba3; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_bspline.h�������������������������������������������0000644�0024617�0000144�00000004110�12261257215�023267� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_BSPLINE_INCLUDED #define AGG_VCGEN_BSPLINE_INCLUDED #include "agg_basics.h" #include "agg_array.h" #include "agg_bspline.h" namespace mapserver { //==========================================================vcgen_bspline class vcgen_bspline { enum status_e { initial, ready, polygon, end_poly, stop }; public: typedef pod_bvector<point_d, 6> vertex_storage; vcgen_bspline(); void interpolation_step(double v) { m_interpolation_step = v; } double interpolation_step() const { return m_interpolation_step; } // Vertex Generator Interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: vcgen_bspline(const vcgen_bspline&); const vcgen_bspline& operator = (const vcgen_bspline&); vertex_storage m_src_vertices; bspline m_spline_x; bspline m_spline_y; double m_interpolation_step; unsigned m_closed; status_e m_status; unsigned m_src_vertex; double m_cur_abscissa; double m_max_abscissa; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_bounding_rect.h�������������������������������������������0000644�0024617�0000144�00000007010�12261257215�023275� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // bounding_rect function template // //---------------------------------------------------------------------------- #ifndef AGG_BOUNDING_RECT_INCLUDED #define AGG_BOUNDING_RECT_INCLUDED #include "agg_basics.h" namespace mapserver { //-----------------------------------------------------------bounding_rect template<class VertexSource, class GetId, class CoordT> bool bounding_rect(VertexSource& vs, GetId& gi, unsigned start, unsigned num, CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) { unsigned i; double x; double y; bool first = true; *x1 = CoordT(1); *y1 = CoordT(1); *x2 = CoordT(0); *y2 = CoordT(0); for(i = 0; i < num; i++) { vs.rewind(gi[start + i]); unsigned cmd; while(!is_stop(cmd = vs.vertex(&x, &y))) { if(is_vertex(cmd)) { if(first) { *x1 = CoordT(x); *y1 = CoordT(y); *x2 = CoordT(x); *y2 = CoordT(y); first = false; } else { if(CoordT(x) < *x1) *x1 = CoordT(x); if(CoordT(y) < *y1) *y1 = CoordT(y); if(CoordT(x) > *x2) *x2 = CoordT(x); if(CoordT(y) > *y2) *y2 = CoordT(y); } } } } return *x1 <= *x2 && *y1 <= *y2; } //-----------------------------------------------------bounding_rect_single template<class VertexSource, class CoordT> bool bounding_rect_single(VertexSource& vs, unsigned path_id, CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) { double x; double y; bool first = true; *x1 = CoordT(1); *y1 = CoordT(1); *x2 = CoordT(0); *y2 = CoordT(0); vs.rewind(path_id); unsigned cmd; while(!is_stop(cmd = vs.vertex(&x, &y))) { if(is_vertex(cmd)) { if(first) { *x1 = CoordT(x); *y1 = CoordT(y); *x2 = CoordT(x); *y2 = CoordT(y); first = false; } else { if(CoordT(x) < *x1) *x1 = CoordT(x); if(CoordT(y) < *y1) *y1 = CoordT(y); if(CoordT(x) > *x2) *x2 = CoordT(x); if(CoordT(y) > *y2) *y2 = CoordT(y); } } } return *x1 <= *x2 && *y1 <= *y2; } } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_pattern_rgba.h���������������������������������������0000644�0024617�0000144�00000006470�12261257215�024155� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_PATTERN_RGBA_INCLUDED #define AGG_SPAN_PATTERN_RGBA_INCLUDED #include "agg_basics.h" namespace mapserver { //======================================================span_pattern_rgba template<class Source> class span_pattern_rgba { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; //-------------------------------------------------------------------- span_pattern_rgba() {} span_pattern_rgba(source_type& src, unsigned offset_x, unsigned offset_y) : m_src(&src), m_offset_x(offset_x), m_offset_y(offset_y) {} //-------------------------------------------------------------------- void attach(source_type& v) { m_src = &v; } source_type& source() { return *m_src; } const source_type& source() const { return *m_src; } //-------------------------------------------------------------------- void offset_x(unsigned v) { m_offset_x = v; } void offset_y(unsigned v) { m_offset_y = v; } unsigned offset_x() const { return m_offset_x; } unsigned offset_y() const { return m_offset_y; } void alpha(value_type) {} value_type alpha() const { return 0; } //-------------------------------------------------------------------- void prepare() {} void generate(color_type* span, int x, int y, unsigned len) { x += m_offset_x; y += m_offset_y; const value_type* p = (const value_type*)m_src->span(x, y, len); do { span->r = p[order_type::R]; span->g = p[order_type::G]; span->b = p[order_type::B]; span->a = p[order_type::A]; p = (const value_type*)m_src->next_x(); ++span; } while(--len); } private: source_type* m_src; unsigned m_offset_x; unsigned m_offset_y; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_simul_eq.h������������������������������������������������0000644�0024617�0000144�00000007647�12261257215�022311� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Solving simultaneous equations // //---------------------------------------------------------------------------- #ifndef AGG_SIMUL_EQ_INCLUDED #define AGG_SIMUL_EQ_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { //=============================================================swap_arrays template<class T> void swap_arrays(T* a1, T* a2, unsigned n) { unsigned i; for(i = 0; i < n; i++) { T tmp = *a1; *a1++ = *a2; *a2++ = tmp; } } //============================================================matrix_pivot template<unsigned Rows, unsigned Cols> struct matrix_pivot { static int pivot(double m[Rows][Cols], unsigned row) { int k = int(row); double max_val, tmp; max_val = -1.0; unsigned i; for(i = row; i < Rows; i++) { if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0) { max_val = tmp; k = i; } } if(m[k][row] == 0.0) { return -1; } if(k != int(row)) { swap_arrays(m[k], m[row], Cols); return k; } return 0; } }; //===============================================================simul_eq template<unsigned Size, unsigned RightCols> struct simul_eq { static bool solve(const double left[Size][Size], const double right[Size][RightCols], double result[Size][RightCols]) { unsigned i, j, k; double a1; double tmp[Size][Size + RightCols]; for(i = 0; i < Size; i++) { for(j = 0; j < Size; j++) { tmp[i][j] = left[i][j]; } for(j = 0; j < RightCols; j++) { tmp[i][Size + j] = right[i][j]; } } for(k = 0; k < Size; k++) { if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0) { return false; // Singularity.... } a1 = tmp[k][k]; for(j = k; j < Size + RightCols; j++) { tmp[k][j] /= a1; } for(i = k + 1; i < Size; i++) { a1 = tmp[i][k]; for (j = k; j < Size + RightCols; j++) { tmp[i][j] -= a1 * tmp[k][j]; } } } for(k = 0; k < RightCols; k++) { int m; for(m = int(Size - 1); m >= 0; m--) { result[m][k] = tmp[m][Size + k]; for(j = m + 1; j < Size; j++) { result[m][k] -= tmp[m][j] * result[j][k]; } } } return true; } }; } #endif �����������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_image_filter_rgb.h�����������������������������������0000644�0024617�0000144�00000105640�12261257215�024765� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED #define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_span_image_filter.h" namespace mapserver { //===============================================span_image_filter_rgb_nn template<class Source, class Interpolator> class span_image_filter_rgb_nn : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgb_nn() {} span_image_filter_rgb_nn(source_type& src, interpolator_type& inter) : base_type(src, inter, 0) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); do { base_type::interpolator().coordinates(&x, &y); const value_type* fg_ptr = (const value_type*) base_type::source().span(x >> image_subpixel_shift, y >> image_subpixel_shift, 1); span->r = fg_ptr[order_type::R]; span->g = fg_ptr[order_type::G]; span->b = fg_ptr[order_type::B]; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //==========================================span_image_filter_rgb_bilinear template<class Source, class Interpolator> class span_image_filter_rgb_bilinear : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgb_bilinear() {} span_image_filter_rgb_bilinear(source_type& src, interpolator_type& inter) : base_type(src, inter, 0) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[3]; const value_type *fg_ptr; do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; fg[0] = fg[1] = fg[2] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = x_hr * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_y(); weight = (image_subpixel_scale - x_hr) * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = x_hr * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //=====================================span_image_filter_rgb_bilinear_clip template<class Source, class Interpolator> class span_image_filter_rgb_bilinear_clip : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgb_bilinear_clip() {} span_image_filter_rgb_bilinear_clip(source_type& src, const color_type& back_color, interpolator_type& inter) : base_type(src, inter, 0), m_back_color(back_color) {} const color_type& background_color() const { return m_back_color; } void background_color(const color_type& v) { m_back_color = v; } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[3]; calc_type src_alpha; value_type back_r = m_back_color.r; value_type back_g = m_back_color.g; value_type back_b = m_back_color.b; value_type back_a = m_back_color.a; const value_type *fg_ptr; int maxx = base_type::source().width() - 1; int maxy = base_type::source().height() - 1; do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; if(x_lr >= 0 && y_lr >= 0 && x_lr < maxx && y_lr < maxy) { fg[0] = fg[1] = fg[2] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; weight = x_hr * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; ++y_lr; fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; weight = (image_subpixel_scale - x_hr) * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; weight = x_hr * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[0] >>= image_subpixel_shift * 2; fg[1] >>= image_subpixel_shift * 2; fg[2] >>= image_subpixel_shift * 2; src_alpha = base_mask; } else { if(x_lr < -1 || y_lr < -1 || x_lr > maxx || y_lr > maxy) { fg[order_type::R] = back_r; fg[order_type::G] = back_g; fg[order_type::B] = back_b; src_alpha = back_a; } else { fg[0] = fg[1] = fg[2] = src_alpha = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; weight = (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; src_alpha += weight * base_mask; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; src_alpha += back_a * weight; } x_lr++; weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; src_alpha += weight * base_mask; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; src_alpha += back_a * weight; } x_lr--; y_lr++; weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; src_alpha += weight * base_mask; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; src_alpha += back_a * weight; } x_lr++; weight = x_hr * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { fg_ptr = (const value_type*) base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; src_alpha += weight * base_mask; } else { fg[order_type::R] += back_r * weight; fg[order_type::G] += back_g * weight; fg[order_type::B] += back_b * weight; src_alpha += back_a * weight; } fg[0] >>= image_subpixel_shift * 2; fg[1] >>= image_subpixel_shift * 2; fg[2] >>= image_subpixel_shift * 2; src_alpha >>= image_subpixel_shift * 2; } } span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = (value_type)src_alpha; ++span; ++base_type::interpolator(); } while(--len); } private: color_type m_back_color; }; //===============================================span_image_filter_rgb_2x2 template<class Source, class Interpolator> class span_image_filter_rgb_2x2 : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgb_2x2() {} span_image_filter_rgb_2x2(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[3]; const value_type *fg_ptr; const int16* weight_array = base_type::filter().weight_array() + ((base_type::filter().diameter()/2 - 1) << image_subpixel_shift); do { int x_hr; int y_hr; base_type::interpolator().coordinates(&x_hr, &y_hr); x_hr -= base_type::filter_dx_int(); y_hr -= base_type::filter_dy_int(); int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; unsigned weight; fg[0] = fg[1] = fg[2] = image_filter_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); weight = (weight_array[x_hr + image_subpixel_scale] * weight_array[y_hr + image_subpixel_scale] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = (weight_array[x_hr] * weight_array[y_hr + image_subpixel_scale] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_y(); weight = (weight_array[x_hr + image_subpixel_scale] * weight_array[y_hr] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg_ptr = (const value_type*)base_type::source().next_x(); weight = (weight_array[x_hr] * weight_array[y_hr] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; fg[0] >>= image_filter_shift; fg[1] >>= image_filter_shift; fg[2] >>= image_filter_shift; if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //===================================================span_image_filter_rgb template<class Source, class Interpolator> class span_image_filter_rgb : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- span_image_filter_rgb() {} span_image_filter_rgb(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); int fg[3]; const value_type *fg_ptr; unsigned diameter = base_type::filter().diameter(); int start = base_type::filter().start(); const int16* weight_array = base_type::filter().weight_array(); int x_count; int weight_y; do { base_type::interpolator().coordinates(&x, &y); x -= base_type::filter_dx_int(); y -= base_type::filter_dy_int(); int x_hr = x; int y_hr = y; int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; fg[0] = fg[1] = fg[2] = image_filter_scale / 2; int x_fract = x_hr & image_subpixel_mask; unsigned y_count = diameter; y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); fg_ptr = (const value_type*)base_type::source().span(x_lr + start, y_lr + start, diameter); for(;;) { x_count = diameter; weight_y = weight_array[y_hr]; x_hr = image_subpixel_mask - x_fract; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> image_filter_shift; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr; if(--x_count == 0) break; x_hr += image_subpixel_scale; fg_ptr = (const value_type*)base_type::source().next_x(); } if(--y_count == 0) break; y_hr += image_subpixel_scale; fg_ptr = (const value_type*)base_type::source().next_y(); } fg[0] >>= image_filter_shift; fg[1] >>= image_filter_shift; fg[2] >>= image_filter_shift; if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //==========================================span_image_resample_rgb_affine template<class Source> class span_image_resample_rgb_affine : public span_image_resample_affine<Source> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef span_image_resample_affine<source_type> base_type; typedef typename base_type::interpolator_type interpolator_type; typedef typename color_type::value_type value_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask, downscale_shift = image_filter_shift }; //-------------------------------------------------------------------- span_image_resample_rgb_affine() {} span_image_resample_rgb_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg[3]; int diameter = base_type::filter().diameter(); int filter_scale = diameter << image_subpixel_shift; int radius_x = (diameter * base_type::m_rx) >> 1; int radius_y = (diameter * base_type::m_ry) >> 1; int len_x_lr = (diameter * base_type::m_rx + image_subpixel_mask) >> image_subpixel_shift; const int16* weight_array = base_type::filter().weight_array(); do { base_type::interpolator().coordinates(&x, &y); x += base_type::filter_dx_int() - radius_x; y += base_type::filter_dy_int() - radius_y; fg[0] = fg[1] = fg[2] = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * base_type::m_ry_inv) >> image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * base_type::m_rx_inv) >> image_subpixel_shift; int x_hr2 = x_hr; const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { int weight_y = weight_array[y_hr]; x_hr = x_hr2; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; fg[0] += *fg_ptr++ * weight; fg[1] += *fg_ptr++ * weight; fg[2] += *fg_ptr * weight; total_weight += weight; x_hr += base_type::m_rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); } y_hr += base_type::m_ry_inv; if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } fg[0] /= total_weight; fg[1] /= total_weight; fg[2] /= total_weight; if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; //=================================================span_image_resample_rgb template<class Source, class Interpolator> class span_image_resample_rgb : public span_image_resample<Source, Interpolator> { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; typedef span_image_resample<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask, downscale_shift = image_filter_shift }; //-------------------------------------------------------------------- span_image_resample_rgb() {} span_image_resample_rgb(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, filter) {} //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); long_type fg[3]; int diameter = base_type::filter().diameter(); int filter_scale = diameter << image_subpixel_shift; const int16* weight_array = base_type::filter().weight_array(); do { int rx; int ry; int rx_inv = image_subpixel_scale; int ry_inv = image_subpixel_scale; base_type::interpolator().coordinates(&x, &y); base_type::interpolator().local_scale(&rx, &ry); base_type::adjust_scale(&rx, &ry); rx_inv = image_subpixel_scale * image_subpixel_scale / rx; ry_inv = image_subpixel_scale * image_subpixel_scale / ry; int radius_x = (diameter * rx) >> 1; int radius_y = (diameter * ry) >> 1; int len_x_lr = (diameter * rx + image_subpixel_mask) >> image_subpixel_shift; x += base_type::filter_dx_int() - radius_x; y += base_type::filter_dy_int() - radius_y; fg[0] = fg[1] = fg[2] = image_filter_scale / 2; int y_lr = y >> image_subpixel_shift; int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * ry_inv) >> image_subpixel_shift; int total_weight = 0; int x_lr = x >> image_subpixel_shift; int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * rx_inv) >> image_subpixel_shift; int x_hr2 = x_hr; const value_type* fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); for(;;) { int weight_y = weight_array[y_hr]; x_hr = x_hr2; for(;;) { int weight = (weight_y * weight_array[x_hr] + image_filter_scale / 2) >> downscale_shift; fg[0] += *fg_ptr++ * weight; fg[1] += *fg_ptr++ * weight; fg[2] += *fg_ptr * weight; total_weight += weight; x_hr += rx_inv; if(x_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_x(); } y_hr += ry_inv; if(y_hr >= filter_scale) break; fg_ptr = (const value_type*)base_type::source().next_y(); } fg[0] /= total_weight; fg[1] /= total_weight; fg[2] /= total_weight; if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); } }; } #endif ������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_curves.h��������������������������������������������������0000644�0024617�0000144�00000046673�12261257215�022004� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CURVES_INCLUDED #define AGG_CURVES_INCLUDED #include "agg_array.h" namespace mapserver { // See Implementation agg_curves.cpp //--------------------------------------------curve_approximation_method_e enum curve_approximation_method_e { curve_inc, curve_div }; //--------------------------------------------------------------curve3_inc class curve3_inc { public: curve3_inc() : m_num_steps(0), m_step(0), m_scale(1.0) { } curve3_inc(double x1, double y1, double x2, double y2, double x3, double y3) : m_num_steps(0), m_step(0), m_scale(1.0) { init(x1, y1, x2, y2, x3, y3); } void reset() { m_num_steps = 0; m_step = -1; } void init(double x1, double y1, double x2, double y2, double x3, double y3); void approximation_method(curve_approximation_method_e) {} curve_approximation_method_e approximation_method() const { return curve_inc; } void approximation_scale(double s); double approximation_scale() const; void angle_tolerance(double) {} double angle_tolerance() const { return 0.0; } void cusp_limit(double) {} double cusp_limit() const { return 0.0; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: int m_num_steps; int m_step; double m_scale; double m_start_x; double m_start_y; double m_end_x; double m_end_y; double m_fx; double m_fy; double m_dfx; double m_dfy; double m_ddfx; double m_ddfy; double m_saved_fx; double m_saved_fy; double m_saved_dfx; double m_saved_dfy; }; //-------------------------------------------------------------curve3_div class curve3_div { public: curve3_div() : m_approximation_scale(1.0), m_angle_tolerance(0.0), m_count(0) {} curve3_div(double x1, double y1, double x2, double y2, double x3, double y3) : m_approximation_scale(1.0), m_angle_tolerance(0.0), m_count(0) { init(x1, y1, x2, y2, x3, y3); } void reset() { m_points.remove_all(); m_count = 0; } void init(double x1, double y1, double x2, double y2, double x3, double y3); void approximation_method(curve_approximation_method_e) {} curve_approximation_method_e approximation_method() const { return curve_div; } void approximation_scale(double s) { m_approximation_scale = s; } double approximation_scale() const { return m_approximation_scale; } void angle_tolerance(double a) { m_angle_tolerance = a; } double angle_tolerance() const { return m_angle_tolerance; } void cusp_limit(double) {} double cusp_limit() const { return 0.0; } void rewind(unsigned) { m_count = 0; } unsigned vertex(double* x, double* y) { if(m_count >= m_points.size()) return path_cmd_stop; const point_d& p = m_points[m_count++]; *x = p.x; *y = p.y; return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; } private: void bezier(double x1, double y1, double x2, double y2, double x3, double y3); void recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, unsigned level); double m_approximation_scale; double m_distance_tolerance_square; double m_angle_tolerance; unsigned m_count; pod_bvector<point_d> m_points; }; //-------------------------------------------------------------curve4_points struct curve4_points { double cp[8]; curve4_points() {} curve4_points(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; } void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; } double operator [] (unsigned i) const { return cp[i]; } double& operator [] (unsigned i) { return cp[i]; } }; //-------------------------------------------------------------curve4_inc class curve4_inc { public: curve4_inc() : m_num_steps(0), m_step(0), m_scale(1.0) { } curve4_inc(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) : m_num_steps(0), m_step(0), m_scale(1.0) { init(x1, y1, x2, y2, x3, y3, x4, y4); } curve4_inc(const curve4_points& cp) : m_num_steps(0), m_step(0), m_scale(1.0) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } void reset() { m_num_steps = 0; m_step = -1; } void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); void init(const curve4_points& cp) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } void approximation_method(curve_approximation_method_e) {} curve_approximation_method_e approximation_method() const { return curve_inc; } void approximation_scale(double s); double approximation_scale() const; void angle_tolerance(double) {} double angle_tolerance() const { return 0.0; } void cusp_limit(double) {} double cusp_limit() const { return 0.0; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: int m_num_steps; int m_step; double m_scale; double m_start_x; double m_start_y; double m_end_x; double m_end_y; double m_fx; double m_fy; double m_dfx; double m_dfy; double m_ddfx; double m_ddfy; double m_dddfx; double m_dddfy; double m_saved_fx; double m_saved_fy; double m_saved_dfx; double m_saved_dfy; double m_saved_ddfx; double m_saved_ddfy; }; //-------------------------------------------------------catrom_to_bezier inline curve4_points catrom_to_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { // Trans. matrix Catmull-Rom to Bezier // // 0 1 0 0 // -1/6 1 1/6 0 // 0 1/6 1 -1/6 // 0 0 1 0 // return curve4_points( x2, y2, (-x1 + 6*x2 + x3) / 6, (-y1 + 6*y2 + y3) / 6, ( x2 + 6*x3 - x4) / 6, ( y2 + 6*y3 - y4) / 6, x3, y3); } //----------------------------------------------------------------------- inline curve4_points catrom_to_bezier(const curve4_points& cp) { return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } //-----------------------------------------------------ubspline_to_bezier inline curve4_points ubspline_to_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { // Trans. matrix Uniform BSpline to Bezier // // 1/6 4/6 1/6 0 // 0 4/6 2/6 0 // 0 2/6 4/6 0 // 0 1/6 4/6 1/6 // return curve4_points( (x1 + 4*x2 + x3) / 6, (y1 + 4*y2 + y3) / 6, (4*x2 + 2*x3) / 6, (4*y2 + 2*y3) / 6, (2*x2 + 4*x3) / 6, (2*y2 + 4*y3) / 6, (x2 + 4*x3 + x4) / 6, (y2 + 4*y3 + y4) / 6); } //----------------------------------------------------------------------- inline curve4_points ubspline_to_bezier(const curve4_points& cp) { return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } //------------------------------------------------------hermite_to_bezier inline curve4_points hermite_to_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { // Trans. matrix Hermite to Bezier // // 1 0 0 0 // 1 0 1/3 0 // 0 1 0 -1/3 // 0 1 0 0 // return curve4_points( x1, y1, (3*x1 + x3) / 3, (3*y1 + y3) / 3, (3*x2 - x4) / 3, (3*y2 - y4) / 3, x2, y2); } //----------------------------------------------------------------------- inline curve4_points hermite_to_bezier(const curve4_points& cp) { return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } //-------------------------------------------------------------curve4_div class curve4_div { public: curve4_div() : m_approximation_scale(1.0), m_angle_tolerance(0.0), m_cusp_limit(0.0), m_count(0) {} curve4_div(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) : m_approximation_scale(1.0), m_angle_tolerance(0.0), m_cusp_limit(0.0), m_count(0) { init(x1, y1, x2, y2, x3, y3, x4, y4); } curve4_div(const curve4_points& cp) : m_approximation_scale(1.0), m_angle_tolerance(0.0), m_count(0) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } void reset() { m_points.remove_all(); m_count = 0; } void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); void init(const curve4_points& cp) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } void approximation_method(curve_approximation_method_e) {} curve_approximation_method_e approximation_method() const { return curve_div; } void approximation_scale(double s) { m_approximation_scale = s; } double approximation_scale() const { return m_approximation_scale; } void angle_tolerance(double a) { m_angle_tolerance = a; } double angle_tolerance() const { return m_angle_tolerance; } void cusp_limit(double v) { m_cusp_limit = (v == 0.0) ? 0.0 : pi - v; } double cusp_limit() const { return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit; } void rewind(unsigned) { m_count = 0; } unsigned vertex(double* x, double* y) { if(m_count >= m_points.size()) return path_cmd_stop; const point_d& p = m_points[m_count++]; *x = p.x; *y = p.y; return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; } private: void bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); void recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, unsigned level); double m_approximation_scale; double m_distance_tolerance_square; double m_angle_tolerance; double m_cusp_limit; unsigned m_count; pod_bvector<point_d> m_points; }; //-----------------------------------------------------------------curve3 class curve3 { public: curve3() : m_approximation_method(curve_div) {} curve3(double x1, double y1, double x2, double y2, double x3, double y3) : m_approximation_method(curve_div) { init(x1, y1, x2, y2, x3, y3); } void reset() { m_curve_inc.reset(); m_curve_div.reset(); } void init(double x1, double y1, double x2, double y2, double x3, double y3) { if(m_approximation_method == curve_inc) { m_curve_inc.init(x1, y1, x2, y2, x3, y3); } else { m_curve_div.init(x1, y1, x2, y2, x3, y3); } } void approximation_method(curve_approximation_method_e v) { m_approximation_method = v; } curve_approximation_method_e approximation_method() const { return m_approximation_method; } void approximation_scale(double s) { m_curve_inc.approximation_scale(s); m_curve_div.approximation_scale(s); } double approximation_scale() const { return m_curve_inc.approximation_scale(); } void angle_tolerance(double a) { m_curve_div.angle_tolerance(a); } double angle_tolerance() const { return m_curve_div.angle_tolerance(); } void cusp_limit(double v) { m_curve_div.cusp_limit(v); } double cusp_limit() const { return m_curve_div.cusp_limit(); } void rewind(unsigned path_id) { if(m_approximation_method == curve_inc) { m_curve_inc.rewind(path_id); } else { m_curve_div.rewind(path_id); } } unsigned vertex(double* x, double* y) { if(m_approximation_method == curve_inc) { return m_curve_inc.vertex(x, y); } return m_curve_div.vertex(x, y); } private: curve3_inc m_curve_inc; curve3_div m_curve_div; curve_approximation_method_e m_approximation_method; }; //-----------------------------------------------------------------curve4 class curve4 { public: curve4() : m_approximation_method(curve_div) {} curve4(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) : m_approximation_method(curve_div) { init(x1, y1, x2, y2, x3, y3, x4, y4); } curve4(const curve4_points& cp) : m_approximation_method(curve_div) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } void reset() { m_curve_inc.reset(); m_curve_div.reset(); } void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { if(m_approximation_method == curve_inc) { m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4); } else { m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); } } void init(const curve4_points& cp) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } void approximation_method(curve_approximation_method_e v) { m_approximation_method = v; } curve_approximation_method_e approximation_method() const { return m_approximation_method; } void approximation_scale(double s) { m_curve_inc.approximation_scale(s); m_curve_div.approximation_scale(s); } double approximation_scale() const { return m_curve_inc.approximation_scale(); } void angle_tolerance(double v) { m_curve_div.angle_tolerance(v); } double angle_tolerance() const { return m_curve_div.angle_tolerance(); } void cusp_limit(double v) { m_curve_div.cusp_limit(v); } double cusp_limit() const { return m_curve_div.cusp_limit(); } void rewind(unsigned path_id) { if(m_approximation_method == curve_inc) { m_curve_inc.rewind(path_id); } else { m_curve_div.rewind(path_id); } } unsigned vertex(double* x, double* y) { if(m_approximation_method == curve_inc) { return m_curve_inc.vertex(x, y); } return m_curve_div.vertex(x, y); } private: curve4_inc m_curve_inc; curve4_div m_curve_div; curve_approximation_method_e m_approximation_method; }; } #endif ���������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/clipper.hpp���������������������������������������������������0000644�0024617�0000144�00000024727�12261257215�021651� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************************* * * * Author : Angus Johnson * * Version : 4.6.3 * * Date : 11 November 2011 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2011 * * * * License: * * Use, modification & distribution is subject to Boost Software License Ver 1. * * http://www.boost.org/LICENSE_1_0.txt * * * * Attributions: * * The code in this library is an extension of Bala Vatti's clipping algorithm: * * "A generic solution to polygon clipping" * * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * * http://portal.acm.org/citation.cfm?id=129906 * * * * Computer graphics and geometric modeling: implementation and algorithms * * By Max K. Agoston * * Springer; 1 edition (January 4, 2005) * * http://books.google.com/books?q=vatti+clipping+agoston * * * * See also: * * "Polygon Offsetting by Computing Winding Numbers" * * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * * September 24-28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ #ifndef clipper_hpp #define clipper_hpp #include <vector> #include <stdexcept> #include <cstring> #include <cstdlib> #include <ostream> namespace ClipperLib { enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; enum PolyType { ptSubject, ptClip }; //By far the most widely used winding rules for polygon filling are //EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) //Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) //see http://glprogramming.com/red/chapter11.html enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; typedef signed long long long64; typedef unsigned long long ulong64; struct IntPoint { public: long64 X; long64 Y; IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; friend std::ostream& operator <<(std::ostream &s, IntPoint &p); }; typedef std::vector< IntPoint > Polygon; typedef std::vector< Polygon > Polygons; std::ostream& operator <<(std::ostream &s, Polygon &p); std::ostream& operator <<(std::ostream &s, Polygons &p); struct ExPolygon { Polygon outer; Polygons holes; }; typedef std::vector< ExPolygon > ExPolygons; enum JoinType { jtSquare, jtMiter, jtRound }; bool Orientation(const Polygon &poly); double Area(const Polygon &poly); void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, double delta, JoinType jointype = jtSquare, double MiterLimit = 2); void ReversePoints(Polygon& p); void ReversePoints(Polygons& p); //used internally ... enum EdgeSide { esLeft, esRight }; enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; struct TEdge { long64 xbot; long64 ybot; long64 xcurr; long64 ycurr; long64 xtop; long64 ytop; double dx; long64 tmpX; PolyType polyType; EdgeSide side; int windDelta; //1 or -1 depending on winding direction int windCnt; int windCnt2; //winding count of the opposite polytype int outIdx; TEdge *next; TEdge *prev; TEdge *nextInLML; TEdge *nextInAEL; TEdge *prevInAEL; TEdge *nextInSEL; TEdge *prevInSEL; }; struct IntersectNode { TEdge *edge1; TEdge *edge2; IntPoint pt; IntersectNode *next; }; struct LocalMinima { long64 Y; TEdge *leftBound; TEdge *rightBound; LocalMinima *next; }; struct Scanbeam { long64 Y; Scanbeam *next; }; struct OutPt; //forward declaration struct OutRec { int idx; bool isHole; OutRec *FirstLeft; OutRec *AppendLink; OutPt *pts; OutPt *bottomPt; TEdge *bottomE1; TEdge *bottomE2; }; struct OutPt { int idx; IntPoint pt; OutPt *next; OutPt *prev; }; struct JoinRec { IntPoint pt1a; IntPoint pt1b; int poly1Idx; IntPoint pt2a; IntPoint pt2b; int poly2Idx; }; struct HorzJoinRec { TEdge *edge; int savedIdx; }; struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; typedef std::vector < OutRec* > PolyOutList; typedef std::vector < TEdge* > EdgeList; typedef std::vector < JoinRec* > JoinList; typedef std::vector < HorzJoinRec* > HorzJoinList; //ClipperBase is the ancestor to the Clipper class. It should not be //instantiated directly. This class simply abstracts the conversion of sets of //polygon coordinates into edge objects that are stored in a LocalMinima list. class ClipperBase { public: ClipperBase(); virtual ~ClipperBase(); bool AddPolygon(const Polygon &pg, PolyType polyType); bool AddPolygons( const Polygons &ppg, PolyType polyType); virtual void Clear(); IntRect GetBounds(); protected: void DisposeLocalMinimaList(); TEdge* AddBoundsToLML(TEdge *e); void PopLocalMinima(); virtual void Reset(); void InsertLocalMinima(LocalMinima *newLm); LocalMinima *m_CurrentLM; LocalMinima *m_MinimaList; bool m_UseFullRange; EdgeList m_edges; }; class Clipper : public virtual ClipperBase { public: Clipper(); ~Clipper(); bool Execute(ClipType clipType, Polygons &solution, PolyFillType subjFillType = pftEvenOdd, PolyFillType clipFillType = pftEvenOdd); bool Execute(ClipType clipType, ExPolygons &solution, PolyFillType subjFillType = pftEvenOdd, PolyFillType clipFillType = pftEvenOdd); void Clear(); bool ReverseSolution() {return m_ReverseOutput;}; void ReverseSolution(bool value) {m_ReverseOutput = value;}; protected: void Reset(); virtual bool ExecuteInternal(bool fixHoleLinkages); private: PolyOutList m_PolyOuts; JoinList m_Joins; HorzJoinList m_HorizJoins; ClipType m_ClipType; Scanbeam *m_Scanbeam; TEdge *m_ActiveEdges; TEdge *m_SortedEdges; IntersectNode *m_IntersectNodes; bool m_ExecuteLocked; PolyFillType m_ClipFillType; PolyFillType m_SubjFillType; bool m_ReverseOutput; void DisposeScanbeamList(); void SetWindingCount(TEdge& edge); bool IsEvenOddFillType(const TEdge& edge) const; bool IsEvenOddAltFillType(const TEdge& edge) const; void InsertScanbeam(const long64 Y); long64 PopScanbeam(); void InsertLocalMinimaIntoAEL(const long64 botY); void InsertEdgeIntoAEL(TEdge *edge); void AddEdgeToSEL(TEdge *edge); void CopyAELToSEL(); void DeleteFromSEL(TEdge *e); void DeleteFromAEL(TEdge *e); void UpdateEdgeIntoAEL(TEdge *&e); void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); bool IsContributing(const TEdge& edge) const; bool IsTopHorz(const long64 XPos); void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); void DoMaxima(TEdge *e, long64 topY); void ProcessHorizontals(); void ProcessHorizontal(TEdge *horzEdge); void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); void AppendPolygon(TEdge *e1, TEdge *e2); void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); void IntersectEdges(TEdge *e1, TEdge *e2, const IntPoint &pt, IntersectProtects protects); OutRec* CreateOutRec(); void AddOutPt(TEdge *e, TEdge *altE, const IntPoint &pt); void DisposeAllPolyPts(); void DisposeOutRec(PolyOutList::size_type index, bool ignorePts = false); bool ProcessIntersections(const long64 botY, const long64 topY); void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); void BuildIntersectList(const long64 botY, const long64 topY); void ProcessIntersectList(); void ProcessEdgesAtTopOfScanbeam(const long64 topY); void BuildResult(Polygons& polys); void BuildResultEx(ExPolygons& polys); void SetHoleState(TEdge *e, OutRec *OutRec); void DisposeIntersectNodes(); bool FixupIntersections(); void FixupOutPolygon(OutRec &outRec); bool IsHole(TEdge *e); void FixHoleLinkage(OutRec *outRec); void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); void ClearJoins(); void AddHorzJoin(TEdge *e, int idx); void ClearHorzJoins(); void JoinCommonEdges(bool fixHoleLinkages); }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ class clipperException : public std::exception { public: clipperException(const char* description): m_descr(description) {} virtual ~clipperException() throw() {} virtual const char* what() const throw() {return m_descr.c_str();} private: std::string m_descr; }; //------------------------------------------------------------------------------ } //ClipperLib namespace #endif //clipper_hpp �����������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rasterizer_outline.h��������������������������������������0000644�0024617�0000144�00000010252�12261257215�024406� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_OUTLINE_INCLUDED #define AGG_RASTERIZER_OUTLINE_INCLUDED #include "agg_basics.h" namespace mapserver { //======================================================rasterizer_outline template<class Renderer> class rasterizer_outline { public: explicit rasterizer_outline(Renderer& ren) : m_ren(&ren), m_start_x(0), m_start_y(0), m_vertices(0) {} void attach(Renderer& ren) { m_ren = &ren; } //-------------------------------------------------------------------- void move_to(int x, int y) { m_vertices = 1; m_ren->move_to(m_start_x = x, m_start_y = y); } //-------------------------------------------------------------------- void line_to(int x, int y) { ++m_vertices; m_ren->line_to(x, y); } //-------------------------------------------------------------------- void move_to_d(double x, double y) { move_to(m_ren->coord(x), m_ren->coord(y)); } //-------------------------------------------------------------------- void line_to_d(double x, double y) { line_to(m_ren->coord(x), m_ren->coord(y)); } //-------------------------------------------------------------------- void close() { if(m_vertices > 2) { line_to(m_start_x, m_start_y); } m_vertices = 0; } //-------------------------------------------------------------------- void add_vertex(double x, double y, unsigned cmd) { if(is_move_to(cmd)) { move_to_d(x, y); } else { if(is_end_poly(cmd)) { if(is_closed(cmd)) close(); } else { line_to_d(x, y); } } } //-------------------------------------------------------------------- template<class VertexSource> void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); } } //-------------------------------------------------------------------- template<class VertexSource, class ColorStorage, class PathId> void render_all_paths(VertexSource& vs, const ColorStorage& colors, const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { m_ren->line_color(colors[i]); add_path(vs, path_id[i]); } } //-------------------------------------------------------------------- template<class Ctrl> void render_ctrl(Ctrl& c) { unsigned i; for(i = 0; i < c.num_paths(); i++) { m_ren->line_color(c.color(i)); add_path(c, i); } } private: Renderer* m_ren; int m_start_x; int m_start_y; unsigned m_vertices; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_scanline_storage_aa.h�������������������������������������0000644�0024617�0000144�00000063440�12261257215�024445� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED #define AGG_SCANLINE_STORAGE_AA_INCLUDED #include <string.h> #include <stdlib.h> #include <math.h> #include "agg_array.h" namespace mapserver { //----------------------------------------------scanline_cell_storage template<class T> class scanline_cell_storage { struct extra_span { unsigned len; T* ptr; }; public: typedef T value_type; //--------------------------------------------------------------- ~scanline_cell_storage() { remove_all(); } //--------------------------------------------------------------- scanline_cell_storage() : m_cells(128-2), m_extra_storage() {} // Copying //--------------------------------------------------------------- scanline_cell_storage(const scanline_cell_storage<T>& v) : m_cells(v.m_cells), m_extra_storage() { copy_extra_storage(v); } //--------------------------------------------------------------- const scanline_cell_storage<T>& operator = (const scanline_cell_storage<T>& v) { remove_all(); m_cells = v.m_cells; copy_extra_storage(v); return *this; } //--------------------------------------------------------------- void remove_all() { int i; for(i = m_extra_storage.size()-1; i >= 0; --i) { pod_allocator<T>::deallocate(m_extra_storage[i].ptr, m_extra_storage[i].len); } m_extra_storage.remove_all(); m_cells.remove_all(); } //--------------------------------------------------------------- int add_cells(const T* cells, unsigned num_cells) { int idx = m_cells.allocate_continuous_block(num_cells); if(idx >= 0) { T* ptr = &m_cells[idx]; memcpy(ptr, cells, sizeof(T) * num_cells); return idx; } extra_span s; s.len = num_cells; s.ptr = pod_allocator<T>::allocate(num_cells); memcpy(s.ptr, cells, sizeof(T) * num_cells); m_extra_storage.add(s); return -int(m_extra_storage.size()); } //--------------------------------------------------------------- const T* operator [] (int idx) const { if(idx >= 0) { if((unsigned)idx >= m_cells.size()) return 0; return &m_cells[(unsigned)idx]; } unsigned i = unsigned(-idx - 1); if(i >= m_extra_storage.size()) return 0; return m_extra_storage[i].ptr; } //--------------------------------------------------------------- T* operator [] (int idx) { if(idx >= 0) { if((unsigned)idx >= m_cells.size()) return 0; return &m_cells[(unsigned)idx]; } unsigned i = unsigned(-idx - 1); if(i >= m_extra_storage.size()) return 0; return m_extra_storage[i].ptr; } private: void copy_extra_storage(const scanline_cell_storage<T>& v) { unsigned i; for(i = 0; i < v.m_extra_storage.size(); ++i) { const extra_span& src = v.m_extra_storage[i]; extra_span dst; dst.len = src.len; dst.ptr = pod_allocator<T>::allocate(dst.len); memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); m_extra_storage.add(dst); } } pod_bvector<T, 12> m_cells; pod_bvector<extra_span, 6> m_extra_storage; }; //-----------------------------------------------scanline_storage_aa template<class T> class scanline_storage_aa { public: typedef T cover_type; //--------------------------------------------------------------- struct span_data { int32 x; int32 len; // If negative, it's a solid span, covers is valid int covers_id; // The index of the cells in the scanline_cell_storage }; //--------------------------------------------------------------- struct scanline_data { int y; unsigned num_spans; unsigned start_span; }; //--------------------------------------------------------------- class embedded_scanline { public: //----------------------------------------------------------- class const_iterator { public: struct span { int32 x; int32 len; // If negative, it's a solid span, covers is valid const T* covers; }; const_iterator() : m_storage(0) {} const_iterator(const embedded_scanline& sl) : m_storage(sl.m_storage), m_span_idx(sl.m_scanline.start_span) { init_span(); } const span& operator*() const { return m_span; } const span* operator->() const { return &m_span; } void operator ++ () { ++m_span_idx; init_span(); } private: void init_span() { const span_data& s = m_storage->span_by_index(m_span_idx); m_span.x = s.x; m_span.len = s.len; m_span.covers = m_storage->covers_by_index(s.covers_id); } const scanline_storage_aa* m_storage; unsigned m_span_idx; span m_span; }; friend class const_iterator; //----------------------------------------------------------- embedded_scanline(const scanline_storage_aa& storage) : m_storage(&storage) { init(0); } //----------------------------------------------------------- void reset(int, int) {} unsigned num_spans() const { return m_scanline.num_spans; } int y() const { return m_scanline.y; } const_iterator begin() const { return const_iterator(*this); } //----------------------------------------------------------- void init(unsigned scanline_idx) { m_scanline_idx = scanline_idx; m_scanline = m_storage->scanline_by_index(m_scanline_idx); } private: const scanline_storage_aa* m_storage; scanline_data m_scanline; unsigned m_scanline_idx; }; //--------------------------------------------------------------- scanline_storage_aa() : m_covers(), m_spans(256-2), // Block increment size m_scanlines(), m_min_x( 0x7FFFFFFF), m_min_y( 0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF), m_cur_scanline(0) { m_fake_scanline.y = 0; m_fake_scanline.num_spans = 0; m_fake_scanline.start_span = 0; m_fake_span.x = 0; m_fake_span.len = 0; m_fake_span.covers_id = 0; } // Renderer Interface //--------------------------------------------------------------- void prepare() { m_covers.remove_all(); m_scanlines.remove_all(); m_spans.remove_all(); m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; m_max_y = -0x7FFFFFFF; m_cur_scanline = 0; } //--------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { scanline_data sl_this; int y = sl.y(); if(y < m_min_y) m_min_y = y; if(y > m_max_y) m_max_y = y; sl_this.y = y; sl_this.num_spans = sl.num_spans(); sl_this.start_span = m_spans.size(); typename Scanline::const_iterator span_iterator = sl.begin(); unsigned num_spans = sl_this.num_spans; for(;;) { span_data sp; sp.x = span_iterator->x; sp.len = span_iterator->len; int len = abs(int(sp.len)); sp.covers_id = m_covers.add_cells(span_iterator->covers, unsigned(len)); m_spans.add(sp); int x1 = sp.x; int x2 = sp.x + len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; if(--num_spans == 0) break; ++span_iterator; } m_scanlines.add(sl_this); } //--------------------------------------------------------------- // Iterate scanlines interface int min_x() const { return m_min_x; } int min_y() const { return m_min_y; } int max_x() const { return m_max_x; } int max_y() const { return m_max_y; } //--------------------------------------------------------------- bool rewind_scanlines() { m_cur_scanline = 0; return m_scanlines.size() > 0; } //--------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { sl.reset_spans(); for(;;) { if(m_cur_scanline >= m_scanlines.size()) return false; const scanline_data& sl_this = m_scanlines[m_cur_scanline]; unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; do { const span_data& sp = m_spans[span_idx++]; const T* covers = covers_by_index(sp.covers_id); if(sp.len < 0) { sl.add_span(sp.x, unsigned(-sp.len), *covers); } else { sl.add_cells(sp.x, sp.len, covers); } } while(--num_spans); ++m_cur_scanline; if(sl.num_spans()) { sl.finalize(sl_this.y); break; } } return true; } //--------------------------------------------------------------- // Specialization for embedded_scanline bool sweep_scanline(embedded_scanline& sl) { do { if(m_cur_scanline >= m_scanlines.size()) return false; sl.init(m_cur_scanline); ++m_cur_scanline; } while(sl.num_spans() == 0); return true; } //--------------------------------------------------------------- unsigned byte_size() const { unsigned i; unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y for(i = 0; i < m_scanlines.size(); ++i) { size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans const scanline_data& sl_this = m_scanlines[i]; unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; do { const span_data& sp = m_spans[span_idx++]; size += sizeof(int32) * 2; // X, span_len if(sp.len < 0) { size += sizeof(T); // cover } else { size += sizeof(T) * unsigned(sp.len); // covers } } while(--num_spans); } return size; } //--------------------------------------------------------------- static void write_int32(int8u* dst, int32 val) { dst[0] = ((const int8u*)&val)[0]; dst[1] = ((const int8u*)&val)[1]; dst[2] = ((const int8u*)&val)[2]; dst[3] = ((const int8u*)&val)[3]; } //--------------------------------------------------------------- void serialize(int8u* data) const { unsigned i; write_int32(data, min_x()); // min_x data += sizeof(int32); write_int32(data, min_y()); // min_y data += sizeof(int32); write_int32(data, max_x()); // max_x data += sizeof(int32); write_int32(data, max_y()); // max_y data += sizeof(int32); for(i = 0; i < m_scanlines.size(); ++i) { const scanline_data& sl_this = m_scanlines[i]; int8u* size_ptr = data; data += sizeof(int32); // Reserve space for scanline size in bytes write_int32(data, sl_this.y); // Y data += sizeof(int32); write_int32(data, sl_this.num_spans); // num_spans data += sizeof(int32); unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; do { const span_data& sp = m_spans[span_idx++]; const T* covers = covers_by_index(sp.covers_id); write_int32(data, sp.x); // X data += sizeof(int32); write_int32(data, sp.len); // span_len data += sizeof(int32); if(sp.len < 0) { memcpy(data, covers, sizeof(T)); data += sizeof(T); } else { memcpy(data, covers, unsigned(sp.len) * sizeof(T)); data += sizeof(T) * unsigned(sp.len); } } while(--num_spans); write_int32(size_ptr, int32(unsigned(data - size_ptr))); } } //--------------------------------------------------------------- const scanline_data& scanline_by_index(unsigned i) const { return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; } //--------------------------------------------------------------- const span_data& span_by_index(unsigned i) const { return (i < m_spans.size()) ? m_spans[i] : m_fake_span; } //--------------------------------------------------------------- const T* covers_by_index(int i) const { return m_covers[i]; } private: scanline_cell_storage<T> m_covers; pod_bvector<span_data, 10> m_spans; pod_bvector<scanline_data, 8> m_scanlines; span_data m_fake_span; scanline_data m_fake_scanline; int m_min_x; int m_min_y; int m_max_x; int m_max_y; unsigned m_cur_scanline; }; typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8 typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16 typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32 //------------------------------------------serialized_scanlines_adaptor_aa template<class T> class serialized_scanlines_adaptor_aa { public: typedef T cover_type; //--------------------------------------------------------------------- class embedded_scanline { public: typedef T cover_type; //----------------------------------------------------------------- class const_iterator { public: struct span { int32 x; int32 len; // If negative, it's a solid span, "covers" is valid const T* covers; }; const_iterator() : m_ptr(0) {} const_iterator(const embedded_scanline& sl) : m_ptr(sl.m_ptr), m_dx(sl.m_dx) { init_span(); } const span& operator*() const { return m_span; } const span* operator->() const { return &m_span; } void operator ++ () { if(m_span.len < 0) { m_ptr += sizeof(T); } else { m_ptr += m_span.len * sizeof(T); } init_span(); } private: int read_int32() { int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } void init_span() { m_span.x = read_int32() + m_dx; m_span.len = read_int32(); m_span.covers = m_ptr; } const int8u* m_ptr; span m_span; int m_dx; }; friend class const_iterator; //----------------------------------------------------------------- embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} //----------------------------------------------------------------- void reset(int, int) {} unsigned num_spans() const { return m_num_spans; } int y() const { return m_y; } const_iterator begin() const { return const_iterator(*this); } private: //----------------------------------------------------------------- int read_int32() { int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } public: //----------------------------------------------------------------- void init(const int8u* ptr, int dx, int dy) { m_ptr = ptr; m_y = read_int32() + dy; m_num_spans = unsigned(read_int32()); m_dx = dx; } private: const int8u* m_ptr; int m_y; unsigned m_num_spans; int m_dx; }; public: //-------------------------------------------------------------------- serialized_scanlines_adaptor_aa() : m_data(0), m_end(0), m_ptr(0), m_dx(0), m_dy(0), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF) {} //-------------------------------------------------------------------- serialized_scanlines_adaptor_aa(const int8u* data, unsigned size, double dx, double dy) : m_data(data), m_end(data + size), m_ptr(data), m_dx(iround(dx)), m_dy(iround(dy)), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF) {} //-------------------------------------------------------------------- void init(const int8u* data, unsigned size, double dx, double dy) { m_data = data; m_end = data + size; m_ptr = data; m_dx = iround(dx); m_dy = iround(dy); m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; m_max_y = -0x7FFFFFFF; } private: //-------------------------------------------------------------------- int read_int32() { int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } //-------------------------------------------------------------------- unsigned read_int32u() { int32u val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } public: // Iterate scanlines interface //-------------------------------------------------------------------- bool rewind_scanlines() { m_ptr = m_data; if(m_ptr < m_end) { m_min_x = read_int32() + m_dx; m_min_y = read_int32() + m_dy; m_max_x = read_int32() + m_dx; m_max_y = read_int32() + m_dy; } return m_ptr < m_end; } //-------------------------------------------------------------------- int min_x() const { return m_min_x; } int min_y() const { return m_min_y; } int max_x() const { return m_max_x; } int max_y() const { return m_max_y; } //-------------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { sl.reset_spans(); for(;;) { if(m_ptr >= m_end) return false; read_int32(); // Skip scanline size in bytes int y = read_int32() + m_dy; unsigned num_spans = read_int32(); do { int x = read_int32() + m_dx; int len = read_int32(); if(len < 0) { sl.add_span(x, unsigned(-len), *m_ptr); m_ptr += sizeof(T); } else { sl.add_cells(x, len, m_ptr); m_ptr += len * sizeof(T); } } while(--num_spans); if(sl.num_spans()) { sl.finalize(y); break; } } return true; } //-------------------------------------------------------------------- // Specialization for embedded_scanline bool sweep_scanline(embedded_scanline& sl) { do { if(m_ptr >= m_end) return false; unsigned byte_size = read_int32u(); sl.init(m_ptr, m_dx, m_dy); m_ptr += byte_size - sizeof(int32); } while(sl.num_spans() == 0); return true; } private: const int8u* m_data; const int8u* m_end; const int8u* m_ptr; int m_dx; int m_dy; int m_min_x; int m_min_y; int m_max_x; int m_max_y; }; typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8 typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16 typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32 } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_interpolator_trans.h���������������������������������0000644�0024617�0000144�00000006056�12261257215�025436� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Horizontal span interpolator for use with an arbitrary transformer // The efficiency highly depends on the operations done in the transformer // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED #define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED #include "agg_basics.h" namespace mapserver { //=================================================span_interpolator_trans template<class Transformer, unsigned SubpixelShift = 8> class span_interpolator_trans { public: typedef Transformer trans_type; enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- span_interpolator_trans() {} span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {} span_interpolator_trans(const trans_type& trans, double x, double y, unsigned) : m_trans(&trans) { begin(x, y, 0); } //---------------------------------------------------------------- const trans_type& transformer() const { return *m_trans; } void transformer(const trans_type& trans) { m_trans = &trans; } //---------------------------------------------------------------- void begin(double x, double y, unsigned) { m_x = x; m_y = y; m_trans->transform(&x, &y); m_ix = iround(x * subpixel_scale); m_iy = iround(y * subpixel_scale); } //---------------------------------------------------------------- void operator++() { m_x += 1.0; double x = m_x; double y = m_y; m_trans->transform(&x, &y); m_ix = iround(x * subpixel_scale); m_iy = iround(y * subpixel_scale); } //---------------------------------------------------------------- void coordinates(int* x, int* y) const { *x = m_ix; *y = m_iy; } private: const trans_type* m_trans; double m_x; double m_y; int m_ix; int m_iy; }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_raster_text.h������������������������������������0000644�0024617�0000144�00000021037�12261257216�024713� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED #define AGG_RENDERER_RASTER_TEXT_INCLUDED #include "agg_basics.h" namespace mapserver { //==============================================renderer_raster_htext_solid template<class BaseRenderer, class GlyphGenerator> class renderer_raster_htext_solid { public: typedef BaseRenderer ren_type; typedef GlyphGenerator glyph_gen_type; typedef typename glyph_gen_type::glyph_rect glyph_rect; typedef typename ren_type::color_type color_type; renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) : m_ren(&ren), m_glyph(&glyph) {} void attach(ren_type& ren) { m_ren = &ren; } //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- template<class CharT> void render_text(double x, double y, const CharT* str, bool flip=false) { glyph_rect r; while(*str) { m_glyph->prepare(&r, x, y, *str, flip); if(r.x2 >= r.x1) { int i; if(flip) { for(i = r.y1; i <= r.y2; i++) { m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), m_color, m_glyph->span(r.y2 - i)); } } else { for(i = r.y1; i <= r.y2; i++) { m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), m_color, m_glyph->span(i - r.y1)); } } } x += r.dx; y += r.dy; ++str; } } private: ren_type* m_ren; glyph_gen_type* m_glyph; color_type m_color; }; //=============================================renderer_raster_vtext_solid template<class BaseRenderer, class GlyphGenerator> class renderer_raster_vtext_solid { public: typedef BaseRenderer ren_type; typedef GlyphGenerator glyph_gen_type; typedef typename glyph_gen_type::glyph_rect glyph_rect; typedef typename ren_type::color_type color_type; renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) : m_ren(&ren), m_glyph(&glyph) { } //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- template<class CharT> void render_text(double x, double y, const CharT* str, bool flip=false) { glyph_rect r; while(*str) { m_glyph->prepare(&r, x, y, *str, !flip); if(r.x2 >= r.x1) { int i; if(flip) { for(i = r.y1; i <= r.y2; i++) { m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), m_color, m_glyph->span(i - r.y1)); } } else { for(i = r.y1; i <= r.y2; i++) { m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), m_color, m_glyph->span(r.y2 - i)); } } } x += r.dx; y += r.dy; ++str; } } private: ren_type* m_ren; glyph_gen_type* m_glyph; color_type m_color; }; //===================================================renderer_raster_htext template<class ScanlineRenderer, class GlyphGenerator> class renderer_raster_htext { public: typedef ScanlineRenderer ren_type; typedef GlyphGenerator glyph_gen_type; typedef typename glyph_gen_type::glyph_rect glyph_rect; class scanline_single_span { public: typedef mapserver::cover_type cover_type; //---------------------------------------------------------------- struct const_span { int x; unsigned len; const cover_type* covers; const_span() {} const_span(int x_, unsigned len_, const cover_type* covers_) : x(x_), len(len_), covers(covers_) {} }; typedef const const_span* const_iterator; //---------------------------------------------------------------- scanline_single_span(int x, int y, unsigned len, const cover_type* covers) : m_y(y), m_span(x, len, covers) {} //---------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return 1; } const_iterator begin() const { return &m_span; } private: //---------------------------------------------------------------- int m_y; const_span m_span; }; //-------------------------------------------------------------------- renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) : m_ren(&ren), m_glyph(&glyph) { } //-------------------------------------------------------------------- template<class CharT> void render_text(double x, double y, const CharT* str, bool flip=false) { glyph_rect r; while(*str) { m_glyph->prepare(&r, x, y, *str, flip); if(r.x2 >= r.x1) { m_ren->prepare(); int i; if(flip) { for(i = r.y1; i <= r.y2; i++) { m_ren->render( scanline_single_span(r.x1, i, (r.x2 - r.x1 + 1), m_glyph->span(r.y2 - i))); } } else { for(i = r.y1; i <= r.y2; i++) { m_ren->render( scanline_single_span(r.x1, i, (r.x2 - r.x1 + 1), m_glyph->span(i - r.y1))); } } } x += r.dx; y += r.dy; ++str; } } private: ren_type* m_ren; glyph_gen_type* m_glyph; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_marker.h���������������������������������������������0000644�0024617�0000144�00000010644�12261257215�022770� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // conv_marker // //---------------------------------------------------------------------------- #ifndef AGG_CONV_MARKER_INCLUDED #define AGG_CONV_MARKER_INCLUDED #include "agg_basics.h" #include "agg_trans_affine.h" namespace mapserver { //-------------------------------------------------------------conv_marker template<class MarkerLocator, class MarkerShapes> class conv_marker { public: conv_marker(MarkerLocator& ml, MarkerShapes& ms); trans_affine& transform() { return m_transform; } const trans_affine& transform() const { return m_transform; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&); const conv_marker<MarkerLocator, MarkerShapes>& operator = (const conv_marker<MarkerLocator, MarkerShapes>&); enum status_e { initial, markers, polygon, stop }; MarkerLocator* m_marker_locator; MarkerShapes* m_marker_shapes; trans_affine m_transform; trans_affine m_mtx; status_e m_status; unsigned m_marker; unsigned m_num_markers; }; //------------------------------------------------------------------------ template<class MarkerLocator, class MarkerShapes> conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) : m_marker_locator(&ml), m_marker_shapes(&ms), m_status(initial), m_marker(0), m_num_markers(1) { } //------------------------------------------------------------------------ template<class MarkerLocator, class MarkerShapes> void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned) { m_status = initial; m_marker = 0; m_num_markers = 1; } //------------------------------------------------------------------------ template<class MarkerLocator, class MarkerShapes> unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y) { unsigned cmd = path_cmd_move_to; double x1, y1, x2, y2; while(!is_stop(cmd)) { switch(m_status) { case initial: if(m_num_markers == 0) { cmd = path_cmd_stop; break; } m_marker_locator->rewind(m_marker); ++m_marker; m_num_markers = 0; m_status = markers; case markers: if(is_stop(m_marker_locator->vertex(&x1, &y1))) { m_status = initial; break; } if(is_stop(m_marker_locator->vertex(&x2, &y2))) { m_status = initial; break; } ++m_num_markers; m_mtx = m_transform; m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1)); m_mtx *= trans_affine_translation(x1, y1); m_marker_shapes->rewind(m_marker - 1); m_status = polygon; case polygon: cmd = m_marker_shapes->vertex(x, y); if(is_stop(cmd)) { cmd = path_cmd_move_to; m_status = markers; break; } m_mtx.transform(x, y); return cmd; case stop: cmd = path_cmd_stop; break; } } return cmd; } } #endif ��������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rounded_rect.h��������������������������������������������0000644�0024617�0000144�00000004313�12261257215�023133� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Rounded rectangle vertex generator // //---------------------------------------------------------------------------- #ifndef AGG_ROUNDED_RECT_INCLUDED #define AGG_ROUNDED_RECT_INCLUDED #include "agg_basics.h" #include "agg_arc.h" namespace mapserver { //------------------------------------------------------------rounded_rect // // See Implemantation agg_rounded_rect.cpp // class rounded_rect { public: rounded_rect() {} rounded_rect(double x1, double y1, double x2, double y2, double r); void rect(double x1, double y1, double x2, double y2); void radius(double r); void radius(double rx, double ry); void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top); void radius(double rx1, double ry1, double rx2, double ry2, double rx3, double ry3, double rx4, double ry4); void normalize_radius(); void approximation_scale(double s) { m_arc.approximation_scale(s); } double approximation_scale() const { return m_arc.approximation_scale(); } void rewind(unsigned); unsigned vertex(double* x, double* y); private: double m_x1; double m_y1; double m_x2; double m_y2; double m_rx1; double m_ry1; double m_rx2; double m_ry2; double m_rx3; double m_ry3; double m_rx4; double m_ry4; unsigned m_status; arc m_arc; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_warp_magnifier.h������������������������������������0000644�0024617�0000144�00000003345�12261257215�024663� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_WARP_MAGNIFIER_INCLUDED #define AGG_WARP_MAGNIFIER_INCLUDED namespace mapserver { //----------------------------------------------------trans_warp_magnifier // // See Inmplementation agg_trans_warp_magnifier.cpp // class trans_warp_magnifier { public: trans_warp_magnifier() : m_xc(0.0), m_yc(0.0), m_magn(1.0), m_radius(1.0) {} void center(double x, double y) { m_xc = x; m_yc = y; } void magnification(double m) { m_magn = m; } void radius(double r) { m_radius = r; } double xc() const { return m_xc; } double yc() const { return m_yc; } double magnification() const { return m_magn; } double radius() const { return m_radius; } void transform(double* x, double* y) const; void inverse_transform(double* x, double* y) const; private: double m_xc; double m_yc; double m_magn; double m_radius; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_shorten_path.h���������������������������������������0000644�0024617�0000144�00000003312�12261257215�024177� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_SHORTEN_PATH_INCLUDED #define AGG_CONV_SHORTEN_PATH_INCLUDED #include "agg_basics.h" #include "agg_conv_adaptor_vcgen.h" #include "agg_vcgen_vertex_sequence.h" namespace mapserver { //=======================================================conv_shorten_path template<class VertexSource> class conv_shorten_path : public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> { public: typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type; conv_shorten_path(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs) { } void shorten(double s) { base_type::generator().shorten(s); } double shorten() const { return base_type::generator().shorten(); } private: conv_shorten_path(const conv_shorten_path<VertexSource>&); const conv_shorten_path<VertexSource>& operator = (const conv_shorten_path<VertexSource>&); }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_path_storage_integer.h������������������������������������0000644�0024617�0000144�00000023114�12261257215�024653� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED #define AGG_PATH_STORAGE_INTEGER_INCLUDED #include <string.h> #include "agg_array.h" namespace mapserver { //---------------------------------------------------------vertex_integer template<class T, unsigned CoordShift=6> struct vertex_integer { enum path_cmd { cmd_move_to = 0, cmd_line_to = 1, cmd_curve3 = 2, cmd_curve4 = 3 }; enum coord_scale_e { coord_shift = CoordShift, coord_scale = 1 << coord_shift }; T x,y; vertex_integer() {} vertex_integer(T x_, T y_, unsigned flag) : x(((x_ << 1) & ~1) | (flag & 1)), y(((y_ << 1) & ~1) | (flag >> 1)) {} unsigned vertex(double* x_, double* y_, double dx=0, double dy=0, double scale=1.0) const { *x_ = dx + (double(x >> 1) / coord_scale) * scale; *y_ = dy + (double(y >> 1) / coord_scale) * scale; switch(((y & 1) << 1) | (x & 1)) { case cmd_move_to: return path_cmd_move_to; case cmd_line_to: return path_cmd_line_to; case cmd_curve3: return path_cmd_curve3; case cmd_curve4: return path_cmd_curve4; } return path_cmd_stop; } }; //---------------------------------------------------path_storage_integer template<class T, unsigned CoordShift=6> class path_storage_integer { public: typedef T value_type; typedef vertex_integer<T, CoordShift> vertex_integer_type; //-------------------------------------------------------------------- path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {} //-------------------------------------------------------------------- void remove_all() { m_storage.remove_all(); } //-------------------------------------------------------------------- void move_to(T x, T y) { m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to)); } //-------------------------------------------------------------------- void line_to(T x, T y) { m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to)); } //-------------------------------------------------------------------- void curve3(T x_ctrl, T y_ctrl, T x_to, T y_to) { m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3)); m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3)); } //-------------------------------------------------------------------- void curve4(T x_ctrl1, T y_ctrl1, T x_ctrl2, T y_ctrl2, T x_to, T y_to) { m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4)); m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4)); m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4)); } //-------------------------------------------------------------------- void close_polygon() {} //-------------------------------------------------------------------- unsigned size() const { return m_storage.size(); } unsigned vertex(unsigned idx, double* x, double* y) const { return m_storage[idx].vertex(x, y); } //-------------------------------------------------------------------- unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); } void serialize(int8u* ptr) const { unsigned i; for(i = 0; i < m_storage.size(); i++) { memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); ptr += sizeof(vertex_integer_type); } } //-------------------------------------------------------------------- void rewind(unsigned) { m_vertex_idx = 0; m_closed = true; } //-------------------------------------------------------------------- unsigned vertex(double* x, double* y) { if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) { *x = 0; *y = 0; return path_cmd_stop; } if(m_vertex_idx == m_storage.size()) { *x = 0; *y = 0; ++m_vertex_idx; return path_cmd_end_poly | path_flags_close; } unsigned cmd = m_storage[m_vertex_idx].vertex(x, y); if(is_move_to(cmd) && !m_closed) { *x = 0; *y = 0; m_closed = true; return path_cmd_end_poly | path_flags_close; } m_closed = false; ++m_vertex_idx; return cmd; } //-------------------------------------------------------------------- rect_d bounding_rect() const { rect_d bounds(1e100, 1e100, -1e100, -1e100); if(m_storage.size() == 0) { bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; } else { unsigned i; for(i = 0; i < m_storage.size(); i++) { double x, y; m_storage[i].vertex(&x, &y); if(x < bounds.x1) bounds.x1 = x; if(y < bounds.y1) bounds.y1 = y; if(x > bounds.x2) bounds.x2 = x; if(y > bounds.y2) bounds.y2 = y; } } return bounds; } private: pod_bvector<vertex_integer_type, 6> m_storage; unsigned m_vertex_idx; bool m_closed; }; //-----------------------------------------serialized_integer_path_adaptor template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor { public: typedef vertex_integer<T, CoordShift> vertex_integer_type; //-------------------------------------------------------------------- serialized_integer_path_adaptor() : m_data(0), m_end(0), m_ptr(0), m_dx(0.0), m_dy(0.0), m_scale(1.0), m_vertices(0) {} //-------------------------------------------------------------------- serialized_integer_path_adaptor(const int8u* data, unsigned size, double dx, double dy) : m_data(data), m_end(data + size), m_ptr(data), m_dx(dx), m_dy(dy), m_vertices(0) {} //-------------------------------------------------------------------- void init(const int8u* data, unsigned size, double dx, double dy, double scale=1.0) { m_data = data; m_end = data + size; m_ptr = data; m_dx = dx; m_dy = dy; m_scale = scale; m_vertices = 0; } //-------------------------------------------------------------------- void rewind(unsigned) { m_ptr = m_data; m_vertices = 0; } //-------------------------------------------------------------------- unsigned vertex(double* x, double* y) { if(m_data == 0 || m_ptr > m_end) { *x = 0; *y = 0; return path_cmd_stop; } if(m_ptr == m_end) { *x = 0; *y = 0; m_ptr += sizeof(vertex_integer_type); return path_cmd_end_poly | path_flags_close; } vertex_integer_type v; memcpy(&v, m_ptr, sizeof(vertex_integer_type)); unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); if(is_move_to(cmd) && m_vertices > 2) { *x = 0; *y = 0; m_vertices = 0; return path_cmd_end_poly | path_flags_close; } ++m_vertices; m_ptr += sizeof(vertex_integer_type); return cmd; } private: const int8u* m_data; const int8u* m_end; const int8u* m_ptr; double m_dx; double m_dy; double m_scale; unsigned m_vertices; }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_scanline_p.h����������������������������������������������0000644�0024617�0000144�00000024361�12261257215�022576� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Class scanline_p - a general purpose scanline container with packed spans. // //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_P_INCLUDED #define AGG_SCANLINE_P_INCLUDED #include "agg_array.h" namespace mapserver { //=============================================================scanline_p8 // // This is a general purpose scaline container which supports the interface // used in the rasterizer::render(). See description of scanline_u8 // for details. // //------------------------------------------------------------------------ class scanline_p8 { public: typedef scanline_p8 self_type; typedef int8u cover_type; typedef int16 coord_type; //-------------------------------------------------------------------- struct span { coord_type x; coord_type len; // If negative, it's a solid span, covers is valid const cover_type* covers; }; typedef span* iterator; typedef const span* const_iterator; scanline_p8() : m_last_x(0x7FFFFFF0), m_covers(), m_cover_ptr(0), m_spans(), m_cur_span(0) { } //-------------------------------------------------------------------- void reset(int min_x, int max_x) { unsigned max_len = max_x - min_x + 3; if(max_len > m_spans.size()) { m_spans.resize(max_len); m_covers.resize(max_len); } m_last_x = 0x7FFFFFF0; m_cover_ptr = &m_covers[0]; m_cur_span = &m_spans[0]; m_cur_span->len = 0; } //-------------------------------------------------------------------- void add_cell(int x, unsigned cover) { *m_cover_ptr = (cover_type)cover; if(x == m_last_x+1 && m_cur_span->len > 0) { m_cur_span->len++; } else { m_cur_span++; m_cur_span->covers = m_cover_ptr; m_cur_span->x = (int16)x; m_cur_span->len = 1; } m_last_x = x; m_cover_ptr++; } //-------------------------------------------------------------------- void add_cells(int x, unsigned len, const cover_type* covers) { memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); if(x == m_last_x+1 && m_cur_span->len > 0) { m_cur_span->len += (int16)len; } else { m_cur_span++; m_cur_span->covers = m_cover_ptr; m_cur_span->x = (int16)x; m_cur_span->len = (int16)len; } m_cover_ptr += len; m_last_x = x + len - 1; } //-------------------------------------------------------------------- void add_span(int x, unsigned len, unsigned cover) { if(x == m_last_x+1 && m_cur_span->len < 0 && cover == *m_cur_span->covers) { m_cur_span->len -= (int16)len; } else { *m_cover_ptr = (cover_type)cover; m_cur_span++; m_cur_span->covers = m_cover_ptr++; m_cur_span->x = (int16)x; m_cur_span->len = (int16)(-int(len)); } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void finalize(int y) { m_y = y; } //-------------------------------------------------------------------- void reset_spans() { m_last_x = 0x7FFFFFF0; m_cover_ptr = &m_covers[0]; m_cur_span = &m_spans[0]; m_cur_span->len = 0; } //-------------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } const_iterator begin() const { return &m_spans[1]; } private: scanline_p8(const self_type&); const self_type& operator = (const self_type&); int m_last_x; int m_y; pod_array<cover_type> m_covers; cover_type* m_cover_ptr; pod_array<span> m_spans; span* m_cur_span; }; //==========================================================scanline32_p8 class scanline32_p8 { public: typedef scanline32_p8 self_type; typedef int8u cover_type; typedef int32 coord_type; struct span { span() {} span(coord_type x_, coord_type len_, const cover_type* covers_) : x(x_), len(len_), covers(covers_) {} coord_type x; coord_type len; // If negative, it's a solid span, covers is valid const cover_type* covers; }; typedef pod_bvector<span, 4> span_array_type; //-------------------------------------------------------------------- class const_iterator { public: const_iterator(const span_array_type& spans) : m_spans(spans), m_span_idx(0) {} const span& operator*() const { return m_spans[m_span_idx]; } const span* operator->() const { return &m_spans[m_span_idx]; } void operator ++ () { ++m_span_idx; } private: const span_array_type& m_spans; unsigned m_span_idx; }; //-------------------------------------------------------------------- scanline32_p8() : m_max_len(0), m_last_x(0x7FFFFFF0), m_covers(), m_cover_ptr(0) { } //-------------------------------------------------------------------- void reset(int min_x, int max_x) { unsigned max_len = max_x - min_x + 3; if(max_len > m_covers.size()) { m_covers.resize(max_len); } m_last_x = 0x7FFFFFF0; m_cover_ptr = &m_covers[0]; m_spans.remove_all(); } //-------------------------------------------------------------------- void add_cell(int x, unsigned cover) { *m_cover_ptr = cover_type(cover); if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) { m_spans.last().len++; } else { m_spans.add(span(coord_type(x), 1, m_cover_ptr)); } m_last_x = x; m_cover_ptr++; } //-------------------------------------------------------------------- void add_cells(int x, unsigned len, const cover_type* covers) { memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) { m_spans.last().len += coord_type(len); } else { m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr)); } m_cover_ptr += len; m_last_x = x + len - 1; } //-------------------------------------------------------------------- void add_span(int x, unsigned len, unsigned cover) { if(x == m_last_x+1 && m_spans.size() && m_spans.last().len < 0 && cover == *m_spans.last().covers) { m_spans.last().len -= coord_type(len); } else { *m_cover_ptr = cover_type(cover); m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++)); } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void finalize(int y) { m_y = y; } //-------------------------------------------------------------------- void reset_spans() { m_last_x = 0x7FFFFFF0; m_cover_ptr = &m_covers[0]; m_spans.remove_all(); } //-------------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return m_spans.size(); } const_iterator begin() const { return const_iterator(m_spans); } private: scanline32_p8(const self_type&); const self_type& operator = (const self_type&); unsigned m_max_len; int m_last_x; int m_y; pod_array<cover_type> m_covers; cover_type* m_cover_ptr; span_array_type m_spans; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_curve.h����������������������������������������������0000644�0024617�0000144�00000015020�12261257215�022624� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // classes conv_curve // //---------------------------------------------------------------------------- #ifndef AGG_CONV_CURVE_INCLUDED #define AGG_CONV_CURVE_INCLUDED #include "agg_basics.h" #include "agg_curves.h" namespace mapserver { //---------------------------------------------------------------conv_curve // Curve converter class. Any path storage can have Bezier curves defined // by their control points. There're two types of curves supported: curve3 // and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control // point. Curve4 has 2 control points (4 points in total) and can be used // to interpolate more complicated curves. Curve4, unlike curve3 can be used // to approximate arcs, both circular and elliptical. Curves are approximated // with straight lines and one of the approaches is just to store the whole // sequence of vertices that approximate our curve. It takes additional // memory, and at the same time the consecutive vertices can be calculated // on demand. // // Initially, path storages are not suppose to keep all the vertices of the // curves (although, nothing prevents us from doing so). Instead, path_storage // keeps only vertices, needed to calculate a curve on demand. Those vertices // are marked with special commands. So, if the path_storage contains curves // (which are not real curves yet), and we render this storage directly, // all we will see is only 2 or 3 straight line segments (for curve3 and // curve4 respectively). If we need to see real curves drawn we need to // include this class into the conversion pipeline. // // Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4 // and converts these vertices into a move_to/line_to sequence. //----------------------------------------------------------------------- template<class VertexSource, class Curve3=curve3, class Curve4=curve4> class conv_curve { public: typedef Curve3 curve3_type; typedef Curve4 curve4_type; typedef conv_curve<VertexSource, Curve3, Curve4> self_type; explicit conv_curve(VertexSource& source) : m_source(&source), m_last_x(0.0), m_last_y(0.0) {} void attach(VertexSource& source) { m_source = &source; } void approximation_method(curve_approximation_method_e v) { m_curve3.approximation_method(v); m_curve4.approximation_method(v); } curve_approximation_method_e approximation_method() const { return m_curve4.approximation_method(); } void approximation_scale(double s) { m_curve3.approximation_scale(s); m_curve4.approximation_scale(s); } double approximation_scale() const { return m_curve4.approximation_scale(); } void angle_tolerance(double v) { m_curve3.angle_tolerance(v); m_curve4.angle_tolerance(v); } double angle_tolerance() const { return m_curve4.angle_tolerance(); } void cusp_limit(double v) { m_curve3.cusp_limit(v); m_curve4.cusp_limit(v); } double cusp_limit() const { return m_curve4.cusp_limit(); } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: conv_curve(const self_type&); const self_type& operator = (const self_type&); VertexSource* m_source; double m_last_x; double m_last_y; curve3_type m_curve3; curve4_type m_curve4; }; //------------------------------------------------------------------------ template<class VertexSource, class Curve3, class Curve4> void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id) { m_source->rewind(path_id); m_last_x = 0.0; m_last_y = 0.0; m_curve3.reset(); m_curve4.reset(); } //------------------------------------------------------------------------ template<class VertexSource, class Curve3, class Curve4> unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y) { if(!is_stop(m_curve3.vertex(x, y))) { m_last_x = *x; m_last_y = *y; return path_cmd_line_to; } if(!is_stop(m_curve4.vertex(x, y))) { m_last_x = *x; m_last_y = *y; return path_cmd_line_to; } double ct2_x; double ct2_y; double end_x; double end_y; unsigned cmd = m_source->vertex(x, y); switch(cmd) { case path_cmd_curve3: m_source->vertex(&end_x, &end_y); m_curve3.init(m_last_x, m_last_y, *x, *y, end_x, end_y); m_curve3.vertex(x, y); // First call returns path_cmd_move_to m_curve3.vertex(x, y); // This is the first vertex of the curve cmd = path_cmd_line_to; break; case path_cmd_curve4: m_source->vertex(&ct2_x, &ct2_y); m_source->vertex(&end_x, &end_y); m_curve4.init(m_last_x, m_last_y, *x, *y, ct2_x, ct2_y, end_x, end_y); m_curve4.vertex(x, y); // First call returns path_cmd_move_to m_curve4.vertex(x, y); // This is the first vertex of the curve cmd = path_cmd_line_to; break; } m_last_x = *x; m_last_y = *y; return cmd; } } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_interpolator_linear.h��������������������������������0000644�0024617�0000144�00000016670�12261257215�025564� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED #define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED #include "agg_basics.h" #include "agg_dda_line.h" #include "agg_trans_affine.h" namespace mapserver { //================================================span_interpolator_linear template<class Transformer = trans_affine, unsigned SubpixelShift = 8> class span_interpolator_linear { public: typedef Transformer trans_type; enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- span_interpolator_linear() {} span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {} span_interpolator_linear(const trans_type& trans, double x, double y, unsigned len) : m_trans(&trans) { begin(x, y, len); } //---------------------------------------------------------------- const trans_type& transformer() const { return *m_trans; } void transformer(const trans_type& trans) { m_trans = &trans; } //---------------------------------------------------------------- void begin(double x, double y, unsigned len) { double tx; double ty; tx = x; ty = y; m_trans->transform(&tx, &ty); int x1 = iround(tx * subpixel_scale); int y1 = iround(ty * subpixel_scale); tx = x + len; ty = y; m_trans->transform(&tx, &ty); int x2 = iround(tx * subpixel_scale); int y2 = iround(ty * subpixel_scale); m_li_x = dda2_line_interpolator(x1, x2, len); m_li_y = dda2_line_interpolator(y1, y2, len); } //---------------------------------------------------------------- void resynchronize(double xe, double ye, unsigned len) { m_trans->transform(&xe, &ye); m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len); m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len); } //---------------------------------------------------------------- void operator++() { ++m_li_x; ++m_li_y; } //---------------------------------------------------------------- void coordinates(int* x, int* y) const { *x = m_li_x.y(); *y = m_li_y.y(); } private: const trans_type* m_trans; dda2_line_interpolator m_li_x; dda2_line_interpolator m_li_y; }; //=====================================span_interpolator_linear_subdiv template<class Transformer = trans_affine, unsigned SubpixelShift = 8> class span_interpolator_linear_subdiv { public: typedef Transformer trans_type; enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //---------------------------------------------------------------- span_interpolator_linear_subdiv() : m_subdiv_shift(4), m_subdiv_size(1 << m_subdiv_shift), m_subdiv_mask(m_subdiv_size - 1) {} span_interpolator_linear_subdiv(const trans_type& trans, unsigned subdiv_shift = 4) : m_subdiv_shift(subdiv_shift), m_subdiv_size(1 << m_subdiv_shift), m_subdiv_mask(m_subdiv_size - 1), m_trans(&trans) {} span_interpolator_linear_subdiv(const trans_type& trans, double x, double y, unsigned len, unsigned subdiv_shift = 4) : m_subdiv_shift(subdiv_shift), m_subdiv_size(1 << m_subdiv_shift), m_subdiv_mask(m_subdiv_size - 1), m_trans(&trans) { begin(x, y, len); } //---------------------------------------------------------------- const trans_type& transformer() const { return *m_trans; } void transformer(const trans_type& trans) { m_trans = &trans; } //---------------------------------------------------------------- unsigned subdiv_shift() const { return m_subdiv_shift; } void subdiv_shift(unsigned shift) { m_subdiv_shift = shift; m_subdiv_size = 1 << m_subdiv_shift; m_subdiv_mask = m_subdiv_size - 1; } //---------------------------------------------------------------- void begin(double x, double y, unsigned len) { double tx; double ty; m_pos = 1; m_src_x = iround(x * subpixel_scale) + subpixel_scale; m_src_y = y; m_len = len; if(len > m_subdiv_size) len = m_subdiv_size; tx = x; ty = y; m_trans->transform(&tx, &ty); int x1 = iround(tx * subpixel_scale); int y1 = iround(ty * subpixel_scale); tx = x + len; ty = y; m_trans->transform(&tx, &ty); m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len); m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len); } //---------------------------------------------------------------- void operator++() { ++m_li_x; ++m_li_y; if(m_pos >= m_subdiv_size) { unsigned len = m_len; if(len > m_subdiv_size) len = m_subdiv_size; double tx = double(m_src_x) / double(subpixel_scale) + len; double ty = m_src_y; m_trans->transform(&tx, &ty); m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len); m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len); m_pos = 0; } m_src_x += subpixel_scale; ++m_pos; --m_len; } //---------------------------------------------------------------- void coordinates(int* x, int* y) const { *x = m_li_x.y(); *y = m_li_y.y(); } private: unsigned m_subdiv_shift; unsigned m_subdiv_size; unsigned m_subdiv_mask; const trans_type* m_trans; dda2_line_interpolator m_li_x; dda2_line_interpolator m_li_y; int m_src_x; double m_src_y; unsigned m_pos; unsigned m_len; }; } #endif ������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pixfmt_gray.h���������������������������������������������0000644�0024617�0000144�00000053374�12261257215�023022� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_GRAY_INCLUDED #define AGG_PIXFMT_GRAY_INCLUDED #include <string.h> #include "agg_basics.h" #include "agg_color_gray.h" #include "agg_rendering_buffer.h" namespace mapserver { //============================================================blender_gray template<class ColorT> struct blender_gray { typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; static AGG_INLINE void blend_pix(value_type* p, unsigned cv, unsigned alpha, unsigned cover=0) { *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); } }; //======================================================blender_gray_pre template<class ColorT> struct blender_gray_pre { typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; static AGG_INLINE void blend_pix(value_type* p, unsigned cv, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (base_shift - 8); *p = (value_type)((*p * alpha + cv * cover) >> base_shift); } static AGG_INLINE void blend_pix(value_type* p, unsigned cv, unsigned alpha) { *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv); } }; //=====================================================apply_gamma_dir_gray template<class ColorT, class GammaLut> class apply_gamma_dir_gray { public: typedef typename ColorT::value_type value_type; apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { *p = m_gamma.dir(*p); } private: const GammaLut& m_gamma; }; //=====================================================apply_gamma_inv_gray template<class ColorT, class GammaLut> class apply_gamma_inv_gray { public: typedef typename ColorT::value_type value_type; apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { *p = m_gamma.inv(*p); } private: const GammaLut& m_gamma; }; //=================================================pixfmt_alpha_blend_gray template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0> class pixfmt_alpha_blend_gray { public: typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef Blender blender_type; typedef typename blender_type::color_type color_type; typedef int order_type; // A fake one typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask, 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) { if (c.a) { calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { *p = c.v; } else { Blender::blend_pix(p, c.v, alpha, cover); } } } static AGG_INLINE void copy_or_blend_pix(value_type* p, const color_type& c) { if (c.a) { if(c.a == base_mask) { *p = c.v; } else { Blender::blend_pix(p, c.v, c.a); } } } public: //-------------------------------------------------------------------- explicit pixfmt_alpha_blend_gray(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) { rect_i r(x1, y1, x2, y2); if(r.clip(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(); } //-------------------------------------------------------------------- int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row_data row(int y) const { return m_rbuf->row(y); } const int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * Step + Offset; } int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * Step + Offset; } //-------------------------------------------------------------------- AGG_INLINE static void make_pix(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, int8u cover) { copy_or_blend_pix((value_type*) m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, c, cover); } //-------------------------------------------------------------------- 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, int8u cover) { if (c.a) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x * Step + Offset; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { do { *p = c.v; p += Step; } while(--len); } else { do { Blender::blend_pix(p, c.v, alpha, cover); p += Step; } while(--len); } } } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { value_type* p; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; *p = c.v; } while(--len); } else { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; Blender::blend_pix(p, c.v, alpha, cover); } while(--len); } } } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { if (c.a) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x * Step + Offset; do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { *p = c.v; } else { Blender::blend_pix(p, c.v, alpha, *covers); } p += Step; ++covers; } while(--len); } } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { if (c.a) { do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; value_type* p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; if(alpha == base_mask) { *p = c.v; } else { Blender::blend_pix(p, c.v, alpha, *covers); } ++covers; } while(--len); } } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x * Step + Offset; do { *p = colors->v; p += Step; ++colors; } while(--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { do { value_type* p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; *p = colors->v; ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x * Step + Offset; if(covers) { do { copy_or_blend_pix(p, *colors++, *covers++); p += Step; } while(--len); } else { if(cover == 255) { do { if(colors->a == base_mask) { *p = colors->v; } else { copy_or_blend_pix(p, *colors); } p += Step; ++colors; } while(--len); } else { do { copy_or_blend_pix(p, *colors++, cover); p += Step; } while(--len); } } } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p; if(covers) { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; copy_or_blend_pix(p, *colors++, *covers++); } while(--len); } else { if(cover == 255) { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; if(colors->a == base_mask) { *p = colors->v; } else { copy_or_blend_pix(p, *colors); } ++colors; } while(--len); } else { do { p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; copy_or_blend_pix(p, *colors++, cover); } while(--len); } } } //-------------------------------------------------------------------- template<class Function> void for_each_pixel(Function f) { unsigned y; for(y = 0; y < height(); ++y) { row_data r = m_rbuf->row(y); if(r.ptr) { unsigned len = r.x2 - r.x1 + 1; value_type* p = (value_type*) m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset; do { f(p); p += Step; } while(--len); } } } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_dir(const GammaLut& g) { for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_inv(const GammaLut& g) { for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class RenBuf2> void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { const int8u* p = from.row_ptr(ysrc); if(p) { memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { copy_or_blend_pix(pdst, color, (*psrc * cover + base_mask) >> base_shift); ++psrc; ++pdst; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { copy_or_blend_pix(pdst, color_lut[*psrc], cover); ++psrc; ++pdst; } while(--len); } } private: rbuf_type* m_rbuf; }; typedef blender_gray<gray8> blender_gray8; typedef blender_gray_pre<gray8> blender_gray8_pre; typedef blender_gray<gray16> blender_gray16; typedef blender_gray_pre<gray16> blender_gray16_pre; typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8 typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16 typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_close_polygon.h��������������������������������������0000644�0024617�0000144�00000007026�12261257215�024363� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED #define AGG_CONV_CLOSE_POLYGON_INCLUDED #include "agg_basics.h" namespace mapserver { //======================================================conv_close_polygon template<class VertexSource> class conv_close_polygon { public: explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {} void attach(VertexSource& source) { m_source = &source; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: conv_close_polygon(const conv_close_polygon<VertexSource>&); const conv_close_polygon<VertexSource>& operator = (const conv_close_polygon<VertexSource>&); VertexSource* m_source; unsigned m_cmd[2]; double m_x[2]; double m_y[2]; unsigned m_vertex; bool m_line_to; }; //------------------------------------------------------------------------ template<class VertexSource> void conv_close_polygon<VertexSource>::rewind(unsigned path_id) { m_source->rewind(path_id); m_vertex = 2; m_line_to = false; } //------------------------------------------------------------------------ template<class VertexSource> unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y) { unsigned cmd = path_cmd_stop; for(;;) { if(m_vertex < 2) { *x = m_x[m_vertex]; *y = m_y[m_vertex]; cmd = m_cmd[m_vertex]; ++m_vertex; break; } cmd = m_source->vertex(x, y); if(is_end_poly(cmd)) { cmd |= path_flags_close; break; } if(is_stop(cmd)) { if(m_line_to) { m_cmd[0] = path_cmd_end_poly | path_flags_close; m_cmd[1] = path_cmd_stop; m_vertex = 0; m_line_to = false; continue; } break; } if(is_move_to(cmd)) { if(m_line_to) { m_x[0] = 0.0; m_y[0] = 0.0; m_cmd[0] = path_cmd_end_poly | path_flags_close; m_x[1] = *x; m_y[1] = *y; m_cmd[1] = cmd; m_vertex = 0; m_line_to = false; continue; } break; } if(is_vertex(cmd)) { m_line_to = true; break; } } return cmd; } } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_shorten_path.h��������������������������������������������0000644�0024617�0000144�00000003766�12261257215�023167� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SHORTEN_PATH_INCLUDED #define AGG_SHORTEN_PATH_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { //===========================================================shorten_path template<class VertexSequence> void shorten_path(VertexSequence& vs, double s, unsigned closed = 0) { typedef typename VertexSequence::value_type vertex_type; if(s > 0.0 && vs.size() > 1) { double d; int n = int(vs.size() - 2); while(n) { d = vs[n].dist; if(d > s) break; vs.remove_last(); s -= d; --n; } if(vs.size() < 2) { vs.remove_all(); } else { n = vs.size() - 1; vertex_type& prev = vs[n-1]; vertex_type& last = vs[n]; d = (prev.dist - s) / prev.dist; double x = prev.x + (last.x - prev.x) * d; double y = prev.y + (last.y - prev.y) * d; last.x = x; last.y = y; if(!prev(last)) vs.remove_last(); vs.close(closed != 0); } } } } #endif ����������mapserver-6.4.1/renderers/agg/include/agg_conv_bspline.h��������������������������������������������0000644�0024617�0000144�00000003221�12261257215�023134� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_BSPLINE_INCLUDED #define AGG_CONV_BSPLINE_INCLUDED #include "agg_basics.h" #include "agg_vcgen_bspline.h" #include "agg_conv_adaptor_vcgen.h" namespace mapserver { //---------------------------------------------------------conv_bspline template<class VertexSource> struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline> { typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type; conv_bspline(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {} void interpolation_step(double v) { base_type::generator().interpolation_step(v); } double interpolation_step() const { return base_type::generator().interpolation_step(); } private: conv_bspline(const conv_bspline<VertexSource>&); const conv_bspline<VertexSource>& operator = (const conv_bspline<VertexSource>&); }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_perspective.h���������������������������������������0000644�0024617�0000144�00000061615�12261257215�024226� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Perspective 2D transformations // //---------------------------------------------------------------------------- #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED #define AGG_TRANS_PERSPECTIVE_INCLUDED #include "agg_trans_affine.h" namespace mapserver { //=======================================================trans_perspective struct trans_perspective { double sx, shy, w0, shx, sy, w1, tx, ty, w2; //------------------------------------------------------- Construction // Identity matrix trans_perspective() : sx (1), shy(0), w0(0), shx(0), sy (1), w1(0), tx (0), ty (0), w2(1) {} // Custom matrix trans_perspective(double v0, double v1, double v2, double v3, double v4, double v5, double v6, double v7, double v8) : sx (v0), shy(v1), w0(v2), shx(v3), sy (v4), w1(v5), tx (v6), ty (v7), w2(v8) {} // Custom matrix from m[9] explicit trans_perspective(const double* m) : sx (m[0]), shy(m[1]), w0(m[2]), shx(m[3]), sy (m[4]), w1(m[5]), tx (m[6]), ty (m[7]), w2(m[8]) {} // From affine explicit trans_perspective(const trans_affine& a) : sx (a.sx ), shy(a.shy), w0(0), shx(a.shx), sy (a.sy ), w1(0), tx (a.tx ), ty (a.ty ), w2(1) {} // Rectangle to quadrilateral trans_perspective(double x1, double y1, double x2, double y2, const double* quad); // Quadrilateral to rectangle trans_perspective(const double* quad, double x1, double y1, double x2, double y2); // Arbitrary quadrilateral transformations trans_perspective(const double* src, const double* dst); //-------------------------------------- Quadrilateral transformations // The arguments are double[8] that are mapped to quadrilaterals: // x1,y1, x2,y2, x3,y3, x4,y4 bool quad_to_quad(const double* qs, const double* qd); bool rect_to_quad(double x1, double y1, double x2, double y2, const double* q); bool quad_to_rect(const double* q, double x1, double y1, double x2, double y2); // Map square (0,0,1,1) to the quadrilateral and vice versa bool square_to_quad(const double* q); bool quad_to_square(const double* q); //--------------------------------------------------------- Operations // Reset - load an identity matrix const trans_perspective& reset(); // Invert matrix. Returns false in degenerate case bool invert(); // Direct transformations operations const trans_perspective& translate(double x, double y); const trans_perspective& rotate(double a); const trans_perspective& scale(double s); const trans_perspective& scale(double x, double y); // Multiply the matrix by another one const trans_perspective& multiply(const trans_perspective& m); // Multiply "m" by "this" and assign the result to "this" const trans_perspective& premultiply(const trans_perspective& m); // Multiply matrix to inverse of another one const trans_perspective& multiply_inv(const trans_perspective& m); // Multiply inverse of "m" by "this" and assign the result to "this" const trans_perspective& premultiply_inv(const trans_perspective& m); // Multiply the matrix by another one const trans_perspective& multiply(const trans_affine& m); // Multiply "m" by "this" and assign the result to "this" const trans_perspective& premultiply(const trans_affine& m); // Multiply the matrix by inverse of another one const trans_perspective& multiply_inv(const trans_affine& m); // Multiply inverse of "m" by "this" and assign the result to "this" const trans_perspective& premultiply_inv(const trans_affine& m); //--------------------------------------------------------- Load/Store void store_to(double* m) const; const trans_perspective& load_from(const double* m); //---------------------------------------------------------- Operators // Multiply the matrix by another one const trans_perspective& operator *= (const trans_perspective& m) { return multiply(m); } const trans_perspective& operator *= (const trans_affine& m) { return multiply(m); } // Multiply the matrix by inverse of another one const trans_perspective& operator /= (const trans_perspective& m) { return multiply_inv(m); } const trans_perspective& operator /= (const trans_affine& m) { return multiply_inv(m); } // Multiply the matrix by another one and return // the result in a separete matrix. trans_perspective operator * (const trans_perspective& m) { return trans_perspective(*this).multiply(m); } trans_perspective operator * (const trans_affine& m) { return trans_perspective(*this).multiply(m); } // Multiply the matrix by inverse of another one // and return the result in a separete matrix. trans_perspective operator / (const trans_perspective& m) { return trans_perspective(*this).multiply_inv(m); } trans_perspective operator / (const trans_affine& m) { return trans_perspective(*this).multiply_inv(m); } // Calculate and return the inverse matrix trans_perspective operator ~ () const { trans_perspective ret = *this; ret.invert(); return ret; } // Equal operator with default epsilon bool operator == (const trans_perspective& m) const { return is_equal(m, affine_epsilon); } // Not Equal operator with default epsilon bool operator != (const trans_perspective& m) const { return !is_equal(m, affine_epsilon); } //---------------------------------------------------- Transformations // Direct transformation of x and y void transform(double* x, double* y) const; // Direct transformation of x and y, affine part only void transform_affine(double* x, double* y) const; // Direct transformation of x and y, 2x2 matrix only, no translation void transform_2x2(double* x, double* y) const; // Inverse transformation of x and y. It works slow because // it explicitly inverts the matrix on every call. For massive // operations it's better to invert() the matrix and then use // direct transformations. void inverse_transform(double* x, double* y) const; //---------------------------------------------------------- Auxiliary const trans_perspective& from_affine(const trans_affine& a); double determinant() const; double determinant_reciprocal() const; bool is_valid(double epsilon = affine_epsilon) const; bool is_identity(double epsilon = affine_epsilon) const; bool is_equal(const trans_perspective& m, double epsilon = affine_epsilon) const; // Determine the major affine parameters. Use with caution // considering possible degenerate cases. double scale() const; double rotation() const; void translation(double* dx, double* dy) const; void scaling(double* x, double* y) const; void scaling_abs(double* x, double* y) const; //-------------------------------------------------------------------- class iterator_x { double den; double den_step; double nom_x; double nom_x_step; double nom_y; double nom_y_step; public: double x; double y; iterator_x() {} iterator_x(double px, double py, double step, const trans_perspective& m) : den(px * m.w0 + py * m.w1 + m.w2), den_step(m.w0 * step), nom_x(px * m.sx + py * m.shx + m.tx), nom_x_step(step * m.sx), nom_y(px * m.shy + py * m.sy + m.ty), nom_y_step(step * m.shy), x(nom_x / den), y(nom_y / den) {} void operator ++ () { den += den_step; nom_x += nom_x_step; nom_y += nom_y_step; double d = 1.0 / den; x = nom_x * d; y = nom_y * d; } }; //-------------------------------------------------------------------- iterator_x begin(double x, double y, double step) const { return iterator_x(x, y, step, *this); } }; //------------------------------------------------------------------------ inline bool trans_perspective::square_to_quad(const double* q) { double dx = q[0] - q[2] + q[4] - q[6]; double dy = q[1] - q[3] + q[5] - q[7]; if(dx == 0.0 && dy == 0.0) { // Affine case (parallelogram) //--------------- sx = q[2] - q[0]; shy = q[3] - q[1]; w0 = 0.0; shx = q[4] - q[2]; sy = q[5] - q[3]; w1 = 0.0; tx = q[0]; ty = q[1]; w2 = 1.0; } else { double dx1 = q[2] - q[4]; double dy1 = q[3] - q[5]; double dx2 = q[6] - q[4]; double dy2 = q[7] - q[5]; double den = dx1 * dy2 - dx2 * dy1; if(den == 0.0) { // Singular case //--------------- sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; return false; } // General case //--------------- double u = (dx * dy2 - dy * dx2) / den; double v = (dy * dx1 - dx * dy1) / den; sx = q[2] - q[0] + u * q[2]; shy = q[3] - q[1] + u * q[3]; w0 = u; shx = q[6] - q[0] + v * q[6]; sy = q[7] - q[1] + v * q[7]; w1 = v; tx = q[0]; ty = q[1]; w2 = 1.0; } return true; } //------------------------------------------------------------------------ inline bool trans_perspective::invert() { double d0 = sy * w2 - w1 * ty; double d1 = w0 * ty - shy * w2; double d2 = shy * w1 - w0 * sy; double d = sx * d0 + shx * d1 + tx * d2; if(d == 0.0) { sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; return false; } d = 1.0 / d; trans_perspective a = *this; sx = d * d0; shy = d * d1; w0 = d * d2; shx = d * (a.w1 *a.tx - a.shx*a.w2); sy = d * (a.sx *a.w2 - a.w0 *a.tx); w1 = d * (a.w0 *a.shx - a.sx *a.w1); tx = d * (a.shx*a.ty - a.sy *a.tx); ty = d * (a.shy*a.tx - a.sx *a.ty); w2 = d * (a.sx *a.sy - a.shy*a.shx); return true; } //------------------------------------------------------------------------ inline bool trans_perspective::quad_to_square(const double* q) { if(!square_to_quad(q)) return false; invert(); return true; } //------------------------------------------------------------------------ inline bool trans_perspective::quad_to_quad(const double* qs, const double* qd) { trans_perspective p; if(! quad_to_square(qs)) return false; if(!p.square_to_quad(qd)) return false; multiply(p); return true; } //------------------------------------------------------------------------ inline bool trans_perspective::rect_to_quad(double x1, double y1, double x2, double y2, const double* q) { double r[8]; r[0] = r[6] = x1; r[2] = r[4] = x2; r[1] = r[3] = y1; r[5] = r[7] = y2; return quad_to_quad(r, q); } //------------------------------------------------------------------------ inline bool trans_perspective::quad_to_rect(const double* q, double x1, double y1, double x2, double y2) { double r[8]; r[0] = r[6] = x1; r[2] = r[4] = x2; r[1] = r[3] = y1; r[5] = r[7] = y2; return quad_to_quad(q, r); } //------------------------------------------------------------------------ inline trans_perspective::trans_perspective(double x1, double y1, double x2, double y2, const double* quad) { rect_to_quad(x1, y1, x2, y2, quad); } //------------------------------------------------------------------------ inline trans_perspective::trans_perspective(const double* quad, double x1, double y1, double x2, double y2) { quad_to_rect(quad, x1, y1, x2, y2); } //------------------------------------------------------------------------ inline trans_perspective::trans_perspective(const double* src, const double* dst) { quad_to_quad(src, dst); } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::reset() { sx = 1; shy = 0; w0 = 0; shx = 0; sy = 1; w1 = 0; tx = 0; ty = 0; w2 = 1; return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::multiply(const trans_perspective& a) { trans_perspective b = *this; sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::multiply(const trans_affine& a) { trans_perspective b = *this; sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::premultiply(const trans_perspective& b) { trans_perspective a = *this; sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::premultiply(const trans_affine& b) { trans_perspective a = *this; sx = a.sx *b.sx + a.shx*b.shy; shx = a.sx *b.shx + a.shx*b.sy; tx = a.sx *b.tx + a.shx*b.ty + a.tx; shy = a.shy*b.sx + a.sy *b.shy; sy = a.shy*b.shx + a.sy *b.sy; ty = a.shy*b.tx + a.sy *b.ty + a.ty; w0 = a.w0 *b.sx + a.w1 *b.shy; w1 = a.w0 *b.shx + a.w1 *b.sy; w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2; return *this; } //------------------------------------------------------------------------ const trans_perspective& trans_perspective::multiply_inv(const trans_perspective& m) { trans_perspective t = m; t.invert(); return multiply(t); } //------------------------------------------------------------------------ const trans_perspective& trans_perspective::multiply_inv(const trans_affine& m) { trans_affine t = m; t.invert(); return multiply(t); } //------------------------------------------------------------------------ const trans_perspective& trans_perspective::premultiply_inv(const trans_perspective& m) { trans_perspective t = m; t.invert(); return *this = t.multiply(*this); } //------------------------------------------------------------------------ const trans_perspective& trans_perspective::premultiply_inv(const trans_affine& m) { trans_perspective t(m); t.invert(); return *this = t.multiply(*this); } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::translate(double x, double y) { tx += x; ty += y; return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::rotate(double a) { multiply(trans_affine_rotation(a)); return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::scale(double s) { multiply(trans_affine_scaling(s)); return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::scale(double x, double y) { multiply(trans_affine_scaling(x, y)); return *this; } //------------------------------------------------------------------------ inline void trans_perspective::transform(double* px, double* py) const { double x = *px; double y = *py; double m = 1.0 / (x*w0 + y*w1 + w2); *px = m * (x*sx + y*shx + tx); *py = m * (x*shy + y*sy + ty); } //------------------------------------------------------------------------ inline void trans_perspective::transform_affine(double* x, double* y) const { double tmp = *x; *x = tmp * sx + *y * shx + tx; *y = tmp * shy + *y * sy + ty; } //------------------------------------------------------------------------ inline void trans_perspective::transform_2x2(double* x, double* y) const { double tmp = *x; *x = tmp * sx + *y * shx; *y = tmp * shy + *y * sy; } //------------------------------------------------------------------------ inline void trans_perspective::inverse_transform(double* x, double* y) const { trans_perspective t(*this); if(t.invert()) t.transform(x, y); } //------------------------------------------------------------------------ inline void trans_perspective::store_to(double* m) const { *m++ = sx; *m++ = shy; *m++ = w0; *m++ = shx; *m++ = sy; *m++ = w1; *m++ = tx; *m++ = ty; *m++ = w2; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::load_from(const double* m) { sx = *m++; shy = *m++; w0 = *m++; shx = *m++; sy = *m++; w1 = *m++; tx = *m++; ty = *m++; w2 = *m++; return *this; } //------------------------------------------------------------------------ inline const trans_perspective& trans_perspective::from_affine(const trans_affine& a) { sx = a.sx; shy = a.shy; w0 = 0; shx = a.shx; sy = a.sy; w1 = 0; tx = a.tx; ty = a.ty; w2 = 1; return *this; } //------------------------------------------------------------------------ inline double trans_perspective::determinant() const { return sx * (sy * w2 - ty * w1) + shx * (ty * w0 - shy * w2) + tx * (shy * w1 - sy * w0); } //------------------------------------------------------------------------ inline double trans_perspective::determinant_reciprocal() const { return 1.0 / determinant(); } //------------------------------------------------------------------------ inline bool trans_perspective::is_valid(double epsilon) const { return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon; } //------------------------------------------------------------------------ inline bool trans_perspective::is_identity(double epsilon) const { return is_equal_eps(sx, 1.0, epsilon) && is_equal_eps(shy, 0.0, epsilon) && is_equal_eps(w0, 0.0, epsilon) && is_equal_eps(shx, 0.0, epsilon) && is_equal_eps(sy, 1.0, epsilon) && is_equal_eps(w1, 0.0, epsilon) && is_equal_eps(tx, 0.0, epsilon) && is_equal_eps(ty, 0.0, epsilon) && is_equal_eps(w2, 1.0, epsilon); } //------------------------------------------------------------------------ inline bool trans_perspective::is_equal(const trans_perspective& m, double epsilon) const { return is_equal_eps(sx, m.sx, epsilon) && is_equal_eps(shy, m.shy, epsilon) && is_equal_eps(w0, m.w0, epsilon) && is_equal_eps(shx, m.shx, epsilon) && is_equal_eps(sy, m.sy, epsilon) && is_equal_eps(w1, m.w1, epsilon) && is_equal_eps(tx, m.tx, epsilon) && is_equal_eps(ty, m.ty, epsilon) && is_equal_eps(w2, m.w2, epsilon); } //------------------------------------------------------------------------ inline double trans_perspective::scale() const { double x = 0.707106781 * sx + 0.707106781 * shx; double y = 0.707106781 * shy + 0.707106781 * sy; return sqrt(x*x + y*y); } //------------------------------------------------------------------------ inline double trans_perspective::rotation() const { double x1 = 0.0; double y1 = 0.0; double x2 = 1.0; double y2 = 0.0; transform(&x1, &y1); transform(&x2, &y2); return atan2(y2-y1, x2-x1); } //------------------------------------------------------------------------ void trans_perspective::translation(double* dx, double* dy) const { *dx = tx; *dy = ty; } //------------------------------------------------------------------------ void trans_perspective::scaling(double* x, double* y) const { double x1 = 0.0; double y1 = 0.0; double x2 = 1.0; double y2 = 1.0; trans_perspective t(*this); t *= trans_affine_rotation(-rotation()); t.transform(&x1, &y1); t.transform(&x2, &y2); *x = x2 - x1; *y = y2 - y1; } //------------------------------------------------------------------------ void trans_perspective::scaling_abs(double* x, double* y) const { *x = sqrt(sx * sx + shx * shx); *y = sqrt(shy * shy + sy * sy); } } #endif �������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_smooth_poly1.h��������������������������������������0000644�0024617�0000144�00000005013�12261257215�024273� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_SMOOTH_POLY1_INCLUDED #define AGG_VCGEN_SMOOTH_POLY1_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { //======================================================vcgen_smooth_poly1 // // See Implementation agg_vcgen_smooth_poly1.cpp // Smooth polygon generator // //------------------------------------------------------------------------ class vcgen_smooth_poly1 { enum status_e { initial, ready, polygon, ctrl_b, ctrl_e, ctrl1, ctrl2, end_poly, stop }; public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; vcgen_smooth_poly1(); void smooth_value(double v) { m_smooth_value = v * 0.5; } double smooth_value() const { return m_smooth_value * 2.0; } // Vertex Generator Interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: vcgen_smooth_poly1(const vcgen_smooth_poly1&); const vcgen_smooth_poly1& operator = (const vcgen_smooth_poly1&); void calculate(const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, const vertex_dist& v3); vertex_storage m_src_vertices; double m_smooth_value; unsigned m_closed; status_e m_status; unsigned m_src_vertex; double m_ctrl1_x; double m_ctrl1_y; double m_ctrl2_x; double m_ctrl2_y; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vpgen_clip_polyline.h�������������������������������������0000644�0024617�0000144�00000004421�12261257215�024517� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VPGEN_CLIP_POLYLINE_INCLUDED #define AGG_VPGEN_CLIP_POLYLINE_INCLUDED #include "agg_basics.h" namespace mapserver { //======================================================vpgen_clip_polyline // // See Implementation agg_vpgen_clip_polyline.cpp // class vpgen_clip_polyline { public: vpgen_clip_polyline() : m_clip_box(0, 0, 1, 1), m_x1(0), m_y1(0), m_num_vertices(0), m_vertex(0), m_move_to(false) { } void clip_box(double x1, double y1, double x2, double y2) { m_clip_box.x1 = x1; m_clip_box.y1 = y1; m_clip_box.x2 = x2; m_clip_box.y2 = y2; m_clip_box.normalize(); } double x1() const { return m_clip_box.x1; } double y1() const { return m_clip_box.y1; } double x2() const { return m_clip_box.x2; } double y2() const { return m_clip_box.y2; } static bool auto_close() { return false; } static bool auto_unclose() { return true; } void reset(); void move_to(double x, double y); void line_to(double x, double y); unsigned vertex(double* x, double* y); private: rect_d m_clip_box; double m_x1; double m_y1; double m_x[2]; double m_y[2]; unsigned m_cmd[2]; unsigned m_num_vertices; unsigned m_vertex; bool m_move_to; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_smooth_poly1.h���������������������������������������0000644�0024617�0000144�00000005221�12261257215�024137� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Smooth polygon generator // //---------------------------------------------------------------------------- #ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED #define AGG_CONV_SMOOTH_POLY1_INCLUDED #include "agg_basics.h" #include "agg_vcgen_smooth_poly1.h" #include "agg_conv_adaptor_vcgen.h" #include "agg_conv_curve.h" namespace mapserver { //-------------------------------------------------------conv_smooth_poly1 template<class VertexSource> struct conv_smooth_poly1 : public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> { typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type; conv_smooth_poly1(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs) { } void smooth_value(double v) { base_type::generator().smooth_value(v); } double smooth_value() const { return base_type::generator().smooth_value(); } private: conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&); const conv_smooth_poly1<VertexSource>& operator = (const conv_smooth_poly1<VertexSource>&); }; //-------------------------------------------------conv_smooth_poly1_curve template<class VertexSource> struct conv_smooth_poly1_curve : public conv_curve<conv_smooth_poly1<VertexSource> > { conv_smooth_poly1_curve(VertexSource& vs) : conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth), m_smooth(vs) { } void smooth_value(double v) { m_smooth.generator().smooth_value(v); } double smooth_value() const { return m_smooth.generator().smooth_value(); } private: conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&); const conv_smooth_poly1_curve<VertexSource>& operator = (const conv_smooth_poly1_curve<VertexSource>&); conv_smooth_poly1<VertexSource> m_smooth; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_clip_polygon.h���������������������������������������0000644�0024617�0000144�00000004733�12261257215�024207� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Polygon clipping converter // There an optimized Liang-Basky algorithm is used. // The algorithm doesn't optimize the degenerate edges, i.e. it will never // break a closed polygon into two or more ones, instead, there will be // degenerate edges coinciding with the respective clipping boundaries. // This is a sub-optimal solution, because that optimization would require // extra, rather expensive math while the rasterizer tolerates it quite well, // without any considerable overhead. // //---------------------------------------------------------------------------- #ifndef AGG_CONV_CLIP_POLYGON_INCLUDED #define AGG_CONV_CLIP_POLYGON_INCLUDED #include "agg_basics.h" #include "agg_conv_adaptor_vpgen.h" #include "agg_vpgen_clip_polygon.h" namespace mapserver { //=======================================================conv_clip_polygon template<class VertexSource> struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> { typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type; conv_clip_polygon(VertexSource& vs) : conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {} void clip_box(double x1, double y1, double x2, double y2) { base_type::vpgen().clip_box(x1, y1, x2, y2); } double x1() const { return base_type::vpgen().x1(); } double y1() const { return base_type::vpgen().y1(); } double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } private: conv_clip_polygon(const conv_clip_polygon<VertexSource>&); const conv_clip_polygon<VertexSource>& operator = (const conv_clip_polygon<VertexSource>&); }; } #endif �������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pixfmt_rgba.h���������������������������������������������0000644�0024617�0000144�00000350177�12261257215�022774� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_RGBA_INCLUDED #define AGG_PIXFMT_RGBA_INCLUDED #include <string.h> #include <math.h> #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_rendering_buffer.h" namespace mapserver { //=========================================================multiplier_rgba template<class ColorT, class Order> struct multiplier_rgba { typedef typename ColorT::value_type value_type; typedef typename ColorT::calc_type calc_type; //-------------------------------------------------------------------- static AGG_INLINE void premultiply(value_type* p) { calc_type a = p[Order::A]; if(a < ColorT::base_mask) { if(a == 0) { p[Order::R] = p[Order::G] = p[Order::B] = 0; return; } p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); } } //-------------------------------------------------------------------- static AGG_INLINE void demultiply(value_type* p) { calc_type a = p[Order::A]; if(a < ColorT::base_mask) { if(a == 0) { p[Order::R] = p[Order::G] = p[Order::B] = 0; return; } calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); } } }; //=====================================================apply_gamma_dir_rgba template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba { public: typedef typename ColorT::value_type value_type; apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { p[Order::R] = m_gamma.dir(p[Order::R]); p[Order::G] = m_gamma.dir(p[Order::G]); p[Order::B] = m_gamma.dir(p[Order::B]); } private: const GammaLut& m_gamma; }; //=====================================================apply_gamma_inv_rgba template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba { public: typedef typename ColorT::value_type value_type; apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} AGG_INLINE void operator () (value_type* p) { p[Order::R] = m_gamma.inv(p[Order::R]); p[Order::G] = m_gamma.inv(p[Order::G]); p[Order::B] = m_gamma.inv(p[Order::B]); } private: const GammaLut& m_gamma; }; //=============================================================blender_rgba template<class ColorT, class Order> struct blender_rgba { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover=0) { calc_type r = p[Order::R]; calc_type g = p[Order::G]; calc_type b = p[Order::B]; calc_type a = p[Order::A]; p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); } }; //=========================================================blender_rgba_pre template<class ColorT, class Order> struct blender_rgba_pre { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { alpha = color_type::base_mask - alpha; cover = (cover + 1) << (base_shift - 8); p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); } //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha) { alpha = color_type::base_mask - alpha; p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); } }; //======================================================blender_rgba_plain template<class ColorT, class Order> struct blender_rgba_plain { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover=0) { if(alpha == 0) return; calc_type a = p[Order::A]; calc_type r = p[Order::R] * a; calc_type g = p[Order::G] * a; calc_type b = p[Order::B] * a; a = ((alpha + a) << base_shift) - alpha * a; p[Order::A] = (value_type)(a >> base_shift); p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); } }; //=========================================================comp_op_rgba_clear template<class ColorT, class Order> struct comp_op_rgba_clear { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(value_type* p, unsigned, unsigned, unsigned, unsigned, unsigned cover) { if(cover < 255) { cover = 255 - cover; p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); } else { p[0] = p[1] = p[2] = p[3] = 0; } } }; //===========================================================comp_op_rgba_src template<class ColorT, class Order> struct comp_op_rgba_src { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { unsigned alpha = 255 - cover; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); } else { p[Order::R] = sr; p[Order::G] = sg; p[Order::B] = sb; p[Order::A] = sa; } } }; //===========================================================comp_op_rgba_dst template<class ColorT, class Order> struct comp_op_rgba_dst { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; static AGG_INLINE void blend_pix(value_type*, unsigned, unsigned, unsigned, unsigned, unsigned) { } }; //======================================================comp_op_rgba_src_over template<class ColorT, class Order> struct comp_op_rgba_src_over { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } calc_type s1a = base_mask - sa; p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); } }; //======================================================comp_op_rgba_dst_over template<class ColorT, class Order> struct comp_op_rgba_dst_over { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca + Sca.(1 - Da) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } calc_type d1a = base_mask - p[Order::A]; p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); } }; //======================================================comp_op_rgba_src_in template<class ColorT, class Order> struct comp_op_rgba_src_in { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.Da // Da' = Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { calc_type da = p[Order::A]; if(cover < 255) { unsigned alpha = 255 - cover; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); } else { p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); } } }; //======================================================comp_op_rgba_dst_in template<class ColorT, class Order> struct comp_op_rgba_dst_in { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca.Sa // Da' = Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned, unsigned, unsigned, unsigned sa, unsigned cover) { if(cover < 255) { sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); } p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); } }; //======================================================comp_op_rgba_src_out template<class ColorT, class Order> struct comp_op_rgba_src_out { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.(1 - Da) // Da' = Sa.(1 - Da) static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { calc_type da = base_mask - p[Order::A]; if(cover < 255) { unsigned alpha = 255 - cover; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); } else { p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); } } }; //======================================================comp_op_rgba_dst_out template<class ColorT, class Order> struct comp_op_rgba_dst_out { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca.(1 - Sa) // Da' = Da.(1 - Sa) static AGG_INLINE void blend_pix(value_type* p, unsigned, unsigned, unsigned, unsigned sa, unsigned cover) { if(cover < 255) { sa = (sa * cover + 255) >> 8; } sa = base_mask - sa; p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); } }; //=====================================================comp_op_rgba_src_atop template<class ColorT, class Order> struct comp_op_rgba_src_atop { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.Da + Dca.(1 - Sa) // Da' = Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } calc_type da = p[Order::A]; sa = base_mask - sa; p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); } }; //=====================================================comp_op_rgba_dst_atop template<class ColorT, class Order> struct comp_op_rgba_dst_atop { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca.Sa + Sca.(1 - Da) // Da' = Sa static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { calc_type da = base_mask - p[Order::A]; if(cover < 255) { unsigned alpha = 255 - cover; sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); } else { p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); p[Order::A] = (value_type)sa; } } }; //=========================================================comp_op_rgba_xor template<class ColorT, class Order> struct comp_op_rgba_xor { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - 2.Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type s1a = base_mask - sa; calc_type d1a = base_mask - p[Order::A]; p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); } } }; //=========================================================comp_op_rgba_plus template<class ColorT, class Order> struct comp_op_rgba_plus { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca + Dca // Da' = Sa + Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R] + sr; calc_type dg = p[Order::G] + sg; calc_type db = p[Order::B] + sb; calc_type da = p[Order::A] + sa; p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; } } }; //========================================================comp_op_rgba_minus template<class ColorT, class Order> struct comp_op_rgba_minus { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Dca - Sca // Da' = 1 - (1 - Sa).(1 - Da) static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R] - sr; calc_type dg = p[Order::G] - sg; calc_type db = p[Order::B] - sb; p[Order::R] = (dr > base_mask) ? 0 : dr; p[Order::G] = (dg > base_mask) ? 0 : dg; p[Order::B] = (db > base_mask) ? 0 : db; p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_multiply template<class ColorT, class Order> struct comp_op_rgba_multiply { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type s1a = base_mask - sa; calc_type d1a = base_mask - p[Order::A]; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_screen template<class ColorT, class Order> struct comp_op_rgba_screen { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = Sca + Dca - Sca.Dca // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_overlay template<class ColorT, class Order> struct comp_op_rgba_overlay { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // if 2.Dca < Da // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) // otherwise // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) // // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; calc_type sada = sa * p[Order::A]; p[Order::R] = (value_type)(((2*dr < da) ? 2*sr*dr + sr*d1a + dr*s1a : sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); p[Order::G] = (value_type)(((2*dg < da) ? 2*sg*dg + sg*d1a + dg*s1a : sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); p[Order::B] = (value_type)(((2*db < da) ? 2*sb*db + sb*d1a + db*s1a : sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; } template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; } //=====================================================comp_op_rgba_darken template<class ColorT, class Order> struct comp_op_rgba_darken { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_lighten template<class ColorT, class Order> struct comp_op_rgba_lighten { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_color_dodge template<class ColorT, class Order> struct comp_op_rgba_color_dodge { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // if Sca.Da + Dca.Sa >= Sa.Da // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) // otherwise // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) // // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; long_type drsa = dr * sa; long_type dgsa = dg * sa; long_type dbsa = db * sa; long_type srda = sr * da; long_type sgda = sg * da; long_type sbda = sb * da; long_type sada = sa * da; p[Order::R] = (value_type)((srda + drsa >= sada) ? (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); p[Order::G] = (value_type)((sgda + dgsa >= sada) ? (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); p[Order::B] = (value_type)((sbda + dbsa >= sada) ? (sada + sb * d1a + db * s1a + base_mask) >> base_shift : dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_color_burn template<class ColorT, class Order> struct comp_op_rgba_color_burn { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // if Sca.Da + Dca.Sa <= Sa.Da // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) // otherwise // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) // // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; long_type drsa = dr * sa; long_type dgsa = dg * sa; long_type dbsa = db * sa; long_type srda = sr * da; long_type sgda = sg * da; long_type sbda = sb * da; long_type sada = sa * da; p[Order::R] = (value_type)(((srda + drsa <= sada) ? sr * d1a + dr * s1a : sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? sg * d1a + dg * s1a : sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? sb * d1a + db * s1a : sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_hard_light template<class ColorT, class Order> struct comp_op_rgba_hard_light { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // if 2.Sca < Sa // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) // otherwise // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) // // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; calc_type sada = sa * da; p[Order::R] = (value_type)(((2*sr < sa) ? 2*sr*dr + sr*d1a + dr*s1a : sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); p[Order::G] = (value_type)(((2*sg < sa) ? 2*sg*dg + sg*d1a + dg*s1a : sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); p[Order::B] = (value_type)(((2*sb < sa) ? 2*sb*db + sb*d1a + db*s1a : sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_soft_light template<class ColorT, class Order> struct comp_op_rgba_soft_light { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // if 2.Sca < Sa // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) // otherwise if 8.Dca <= Da // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) // otherwise // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) // // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned r, unsigned g, unsigned b, unsigned a, unsigned cover) { double sr = double(r * cover) / (base_mask * 255); double sg = double(g * cover) / (base_mask * 255); double sb = double(b * cover) / (base_mask * 255); double sa = double(a * cover) / (base_mask * 255); if(sa > 0) { double dr = double(p[Order::R]) / base_mask; double dg = double(p[Order::G]) / base_mask; double db = double(p[Order::B]) / base_mask; double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; if(cover < 255) { a = (a * cover + 255) >> 8; } if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); p[Order::R] = (value_type)uround(dr * base_mask); p[Order::G] = (value_type)uround(dg * base_mask); p[Order::B] = (value_type)uround(db * base_mask); p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_difference template<class ColorT, class Order> struct comp_op_rgba_difference { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask }; // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_exclusion template<class ColorT, class Order> struct comp_op_rgba_exclusion { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type d1a = base_mask - p[Order::A]; calc_type s1a = base_mask - sa; calc_type dr = p[Order::R]; calc_type dg = p[Order::G]; calc_type db = p[Order::B]; calc_type da = p[Order::A]; p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=====================================================comp_op_rgba_contrast template<class ColorT, class Order> struct comp_op_rgba_contrast { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } long_type dr = p[Order::R]; long_type dg = p[Order::G]; long_type db = p[Order::B]; int da = p[Order::A]; long_type d2a = da >> 1; unsigned s2a = sa >> 1; int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); r = (r < 0) ? 0 : r; g = (g < 0) ? 0 : g; b = (b < 0) ? 0 : b; p[Order::R] = (value_type)((r > da) ? da : r); p[Order::G] = (value_type)((g > da) ? da : g); p[Order::B] = (value_type)((b > da) ? da : b); } }; //=====================================================comp_op_rgba_invert template<class ColorT, class Order> struct comp_op_rgba_invert { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { sa = (sa * cover + 255) >> 8; if(sa) { calc_type da = p[Order::A]; calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; calc_type s1a = base_mask - sa; p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //=================================================comp_op_rgba_invert_rgb template<class ColorT, class Order> struct comp_op_rgba_invert_rgb { typedef ColorT color_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef typename color_type::long_type long_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover) { if(cover < 255) { sr = (sr * cover + 255) >> 8; sg = (sg * cover + 255) >> 8; sb = (sb * cover + 255) >> 8; sa = (sa * cover + 255) >> 8; } if(sa) { calc_type da = p[Order::A]; calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; calc_type s1a = base_mask - sa; p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); } } }; //======================================================comp_op_table_rgba template<class ColorT, class Order> struct comp_op_table_rgba { typedef typename ColorT::value_type value_type; typedef void (*comp_op_func_type)(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover); static comp_op_func_type g_comp_op_func[]; }; //==========================================================g_comp_op_func template<class ColorT, class Order> typename comp_op_table_rgba<ColorT, Order>::comp_op_func_type comp_op_table_rgba<ColorT, Order>::g_comp_op_func[] = { comp_op_rgba_clear <ColorT,Order>::blend_pix, comp_op_rgba_src <ColorT,Order>::blend_pix, comp_op_rgba_dst <ColorT,Order>::blend_pix, comp_op_rgba_src_over <ColorT,Order>::blend_pix, comp_op_rgba_dst_over <ColorT,Order>::blend_pix, comp_op_rgba_src_in <ColorT,Order>::blend_pix, comp_op_rgba_dst_in <ColorT,Order>::blend_pix, comp_op_rgba_src_out <ColorT,Order>::blend_pix, comp_op_rgba_dst_out <ColorT,Order>::blend_pix, comp_op_rgba_src_atop <ColorT,Order>::blend_pix, comp_op_rgba_dst_atop <ColorT,Order>::blend_pix, comp_op_rgba_xor <ColorT,Order>::blend_pix, comp_op_rgba_plus <ColorT,Order>::blend_pix, comp_op_rgba_minus <ColorT,Order>::blend_pix, comp_op_rgba_multiply <ColorT,Order>::blend_pix, comp_op_rgba_screen <ColorT,Order>::blend_pix, comp_op_rgba_overlay <ColorT,Order>::blend_pix, comp_op_rgba_darken <ColorT,Order>::blend_pix, comp_op_rgba_lighten <ColorT,Order>::blend_pix, comp_op_rgba_color_dodge<ColorT,Order>::blend_pix, comp_op_rgba_color_burn <ColorT,Order>::blend_pix, comp_op_rgba_hard_light <ColorT,Order>::blend_pix, comp_op_rgba_soft_light <ColorT,Order>::blend_pix, comp_op_rgba_difference <ColorT,Order>::blend_pix, comp_op_rgba_exclusion <ColorT,Order>::blend_pix, comp_op_rgba_contrast <ColorT,Order>::blend_pix, comp_op_rgba_invert <ColorT,Order>::blend_pix, comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix, 0 }; //==============================================================comp_op_e enum comp_op_e { comp_op_clear, //----comp_op_clear comp_op_src, //----comp_op_src comp_op_dst, //----comp_op_dst comp_op_src_over, //----comp_op_src_over comp_op_dst_over, //----comp_op_dst_over comp_op_src_in, //----comp_op_src_in comp_op_dst_in, //----comp_op_dst_in comp_op_src_out, //----comp_op_src_out comp_op_dst_out, //----comp_op_dst_out comp_op_src_atop, //----comp_op_src_atop comp_op_dst_atop, //----comp_op_dst_atop comp_op_xor, //----comp_op_xor comp_op_plus, //----comp_op_plus comp_op_minus, //----comp_op_minus comp_op_multiply, //----comp_op_multiply comp_op_screen, //----comp_op_screen comp_op_overlay, //----comp_op_overlay comp_op_darken, //----comp_op_darken comp_op_lighten, //----comp_op_lighten comp_op_color_dodge, //----comp_op_color_dodge comp_op_color_burn, //----comp_op_color_burn comp_op_hard_light, //----comp_op_hard_light comp_op_soft_light, //----comp_op_soft_light comp_op_difference, //----comp_op_difference comp_op_exclusion, //----comp_op_exclusion comp_op_contrast, //----comp_op_contrast comp_op_invert, //----comp_op_invert comp_op_invert_rgb, //----comp_op_invert_rgb end_of_comp_op_e }; //====================================================comp_op_adaptor_rgba template<class ColorT, class Order> struct comp_op_adaptor_rgba { typedef Order order_type; typedef ColorT color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] (p, (cr * ca + base_mask) >> base_shift, (cg * ca + base_mask) >> base_shift, (cb * ca + base_mask) >> base_shift, ca, cover); } }; //=========================================comp_op_adaptor_clip_to_dst_rgba template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba { typedef Order order_type; typedef ColorT color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { cr = (cr * ca + base_mask) >> base_shift; cg = (cg * ca + base_mask) >> base_shift; cb = (cb * ca + base_mask) >> base_shift; unsigned da = p[Order::A]; comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] (p, (cr * da + base_mask) >> base_shift, (cg * da + base_mask) >> base_shift, (cb * da + base_mask) >> base_shift, (ca * da + base_mask) >> base_shift, cover); } }; //================================================comp_op_adaptor_rgba_pre template<class ColorT, class Order> struct comp_op_adaptor_rgba_pre { typedef Order order_type; typedef ColorT color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, cr, cg, cb, ca, cover); } }; //=====================================comp_op_adaptor_clip_to_dst_rgba_pre template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba_pre { typedef Order order_type; typedef ColorT color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { unsigned da = p[Order::A]; comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] (p, (cr * da + base_mask) >> base_shift, (cg * da + base_mask) >> base_shift, (cb * da + base_mask) >> base_shift, (ca * da + base_mask) >> base_shift, cover); } }; //=======================================================comp_adaptor_rgba template<class BlenderPre> struct comp_adaptor_rgba { typedef typename BlenderPre::order_type order_type; typedef typename BlenderPre::color_type color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { BlenderPre::blend_pix(p, (cr * ca + base_mask) >> base_shift, (cg * ca + base_mask) >> base_shift, (cb * ca + base_mask) >> base_shift, ca, cover); } }; //==========================================comp_adaptor_clip_to_dst_rgba template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba { typedef typename BlenderPre::order_type order_type; typedef typename BlenderPre::color_type color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { cr = (cr * ca + base_mask) >> base_shift; cg = (cg * ca + base_mask) >> base_shift; cb = (cb * ca + base_mask) >> base_shift; unsigned da = p[order_type::A]; BlenderPre::blend_pix(p, (cr * da + base_mask) >> base_shift, (cg * da + base_mask) >> base_shift, (cb * da + base_mask) >> base_shift, (ca * da + base_mask) >> base_shift, cover); } }; //======================================comp_adaptor_clip_to_dst_rgba_pre template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba_pre { typedef typename BlenderPre::order_type order_type; typedef typename BlenderPre::color_type color_type; typedef typename color_type::value_type value_type; enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned ca, unsigned cover) { unsigned da = p[order_type::A]; BlenderPre::blend_pix(p, (cr * da + base_mask) >> base_shift, (cg * da + base_mask) >> base_shift, (cb * da + base_mask) >> base_shift, (ca * da + base_mask) >> base_shift, cover); } }; //===============================================copy_or_blend_rgba_wrapper template<class Blender> struct copy_or_blend_rgba_wrapper { typedef typename Blender::color_type color_type; typedef typename Blender::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- static AGG_INLINE void copy_or_blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha) { if(alpha) { if(alpha == base_mask) { p[order_type::R] = cr; p[order_type::G] = cg; p[order_type::B] = cb; p[order_type::A] = base_mask; } else { Blender::blend_pix(p, cr, cg, cb, alpha); } } } //-------------------------------------------------------------------- static AGG_INLINE void copy_or_blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, unsigned cover) { if(cover == 255) { copy_or_blend_pix(p, cr, cg, cb, alpha); } else { if(alpha) { alpha = (alpha * (cover + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = cr; p[order_type::G] = cg; p[order_type::B] = cb; p[order_type::A] = base_mask; } else { Blender::blend_pix(p, cr, cg, cb, alpha, cover); } } } } }; //=================================================pixfmt_alpha_blend_rgba template<class Blender, class RenBuf, class PixelT = int32u> class pixfmt_alpha_blend_rgba { public: typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef PixelT pixel_type; typedef Blender blender_type; typedef typename blender_type::color_type color_type; typedef typename blender_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; typedef copy_or_blend_rgba_wrapper<blender_type> cob_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask, pix_width = sizeof(pixel_type) }; //-------------------------------------------------------------------- pixfmt_alpha_blend_rgba() : m_rbuf(0) {} explicit pixfmt_alpha_blend_rgba(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) { rect_i r(x1, y1, x2, y2); if(r.clip(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_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } //-------------------------------------------------------------------- AGG_INLINE int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * pix_width; } AGG_INLINE const int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * pix_width; } //-------------------------------------------------------------------- AGG_INLINE static void make_pix(int8u* p, const color_type& c) { ((value_type*)p)[order_type::R] = c.r; ((value_type*)p)[order_type::G] = c.g; ((value_type*)p)[order_type::B] = c.b; ((value_type*)p)[order_type::A] = c.a; } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { const value_type* p = (const value_type*)m_rbuf->row_ptr(y); if(p) { p += x << 2; return color_type(p[order_type::R], p[order_type::G], p[order_type::B], p[order_type::A]); } return color_type::no_color(); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; p[order_type::A] = c.a; } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { cob_type::copy_or_blend_pix( (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), c.r, c.g, c.b, c.a, cover); } //-------------------------------------------------------------------- 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 << 2); pixel_type v; ((value_type*)&v)[order_type::R] = c.r; ((value_type*)&v)[order_type::G] = c.g; ((value_type*)&v)[order_type::B] = c.b; ((value_type*)&v)[order_type::A] = c.a; do { *(pixel_type*)p = v; p += 4; } while(--len); } //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { pixel_type v; ((value_type*)&v)[order_type::R] = c.r; ((value_type*)&v)[order_type::G] = c.g; ((value_type*)&v)[order_type::B] = c.b; ((value_type*)&v)[order_type::A] = c.a; do { value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); *(pixel_type*)p = v; } while(--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v; ((value_type*)&v)[order_type::R] = c.r; ((value_type*)&v)[order_type::G] = c.g; ((value_type*)&v)[order_type::B] = c.b; ((value_type*)&v)[order_type::A] = c.a; do { *(pixel_type*)p = v; p += 4; } while(--len); } else { if(cover == 255) { do { blender_type::blend_pix(p, c.r, c.g, c.b, alpha); p += 4; } while(--len); } else { do { blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); p += 4; } while(--len); } } } } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { if (c.a) { value_type* p; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v; ((value_type*)&v)[order_type::R] = c.r; ((value_type*)&v)[order_type::G] = c.g; ((value_type*)&v)[order_type::B] = c.b; ((value_type*)&v)[order_type::A] = c.a; do { p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); *(pixel_type*)p = v; } while(--len); } else { if(cover == 255) { do { p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); blender_type::blend_pix(p, c.r, c.g, c.b, alpha); } while(--len); } else { do { p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); } while(--len); } } } } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { if (c.a) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; p[order_type::A] = base_mask; } else { blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); } p += 4; ++covers; } while(--len); } } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { if (c.a) { do { value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; p[order_type::A] = base_mask; } else { blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); } ++covers; } while(--len); } } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { p[order_type::R] = colors->r; p[order_type::G] = colors->g; p[order_type::B] = colors->b; p[order_type::A] = colors->a; ++colors; p += 4; } while(--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { do { value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); p[order_type::R] = colors->r; p[order_type::G] = colors->g; p[order_type::B] = colors->b; p[order_type::A] = colors->a; ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); if(covers) { do { cob_type::copy_or_blend_pix(p, colors->r, colors->g, colors->b, colors->a, *covers++); p += 4; ++colors; } while(--len); } else { if(cover == 255) { do { cob_type::copy_or_blend_pix(p, colors->r, colors->g, colors->b, colors->a); p += 4; ++colors; } while(--len); } else { do { cob_type::copy_or_blend_pix(p, colors->r, colors->g, colors->b, colors->a, cover); p += 4; ++colors; } while(--len); } } } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p; if(covers) { do { p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); cob_type::copy_or_blend_pix(p, colors->r, colors->g, colors->b, colors->a, *covers++); ++colors; } while(--len); } else { if(cover == 255) { do { p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); cob_type::copy_or_blend_pix(p, colors->r, colors->g, colors->b, colors->a); ++colors; } while(--len); } else { do { p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); cob_type::copy_or_blend_pix(p, colors->r, colors->g, colors->b, colors->a, cover); ++colors; } while(--len); } } } //-------------------------------------------------------------------- template<class Function> void for_each_pixel(Function f) { unsigned y; for(y = 0; y < height(); ++y) { row_data r = m_rbuf->row(y); if(r.ptr) { unsigned len = r.x2 - r.x1 + 1; value_type* p = (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); do { f(p); p += 4; } while(--len); } } } //-------------------------------------------------------------------- void premultiply() { for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); } //-------------------------------------------------------------------- void demultiply() { for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_dir(const GammaLut& g) { for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_inv(const GammaLut& g) { for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class RenBuf2> void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { const int8u* p = from.row_ptr(ysrc); if(p) { memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; const value_type* psrc = (value_type*)from.row_ptr(ysrc); if(psrc) { psrc += xsrc << 2; value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); int incp = 4; if(xdst > xsrc) { psrc += (len-1) << 2; pdst += (len-1) << 2; incp = -4; } if(cover == 255) { do { cob_type::copy_or_blend_pix(pdst, psrc[src_order::R], psrc[src_order::G], psrc[src_order::B], psrc[src_order::A]); psrc += incp; pdst += incp; } while(--len); } else { do { cob_type::copy_or_blend_pix(pdst, psrc[src_order::R], psrc[src_order::G], psrc[src_order::B], psrc[src_order::A], cover); psrc += incp; pdst += incp; } while(--len); } } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); do { cob_type::copy_or_blend_pix(pdst, color.r, color.g, color.b, color.a, (*psrc * cover + base_mask) >> base_shift); ++psrc; pdst += 4; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); if(cover == 255) { do { const color_type& color = color_lut[*psrc]; cob_type::copy_or_blend_pix(pdst, color.r, color.g, color.b, color.a); ++psrc; pdst += 4; } while(--len); } else { do { const color_type& color = color_lut[*psrc]; cob_type::copy_or_blend_pix(pdst, color.r, color.g, color.b, color.a, cover); ++psrc; pdst += 4; } while(--len); } } } private: rbuf_type* m_rbuf; }; //================================================pixfmt_custom_blend_rgba template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba { public: typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef Blender blender_type; typedef typename blender_type::color_type color_type; typedef typename blender_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { base_shift = color_type::base_shift, base_scale = color_type::base_scale, base_mask = color_type::base_mask, pix_width = sizeof(value_type) * 4 }; //-------------------------------------------------------------------- pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : m_rbuf(&rb), m_comp_op(comp_op) {} void attach(rbuf_type& rb) { m_rbuf = &rb; } //-------------------------------------------------------------------- template<class PixFmt> bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) { rect_i r(x1, y1, x2, y2); if(r.clip(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_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } //-------------------------------------------------------------------- AGG_INLINE int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * pix_width; } AGG_INLINE const int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * pix_width; } //-------------------------------------------------------------------- void comp_op(unsigned op) { m_comp_op = op; } unsigned comp_op() const { return m_comp_op; } //-------------------------------------------------------------------- AGG_INLINE static void make_pix(int8u* p, const color_type& c) { ((value_type*)p)[order_type::R] = c.r; ((value_type*)p)[order_type::G] = c.g; ((value_type*)p)[order_type::B] = c.b; ((value_type*)p)[order_type::A] = c.a; } //-------------------------------------------------------------------- color_type pixel(int x, int y) const { const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); return color_type(p[order_type::R], p[order_type::G], p[order_type::B], p[order_type::A]); } //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { blender_type::blend_pix( m_comp_op, (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), c.r, c.g, c.b, c.a, 255); } //-------------------------------------------------------------------- void blend_pixel(int x, int y, const color_type& c, int8u cover) { blender_type::blend_pix( m_comp_op, (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), c.r, c.g, c.b, c.a, cover); } //-------------------------------------------------------------------- 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 << 2);; do { blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); p += 4; } while(--len); } //-------------------------------------------------------------------- void copy_vline(int x, int y, unsigned len, const color_type& c) { do { blender_type::blend_pix( m_comp_op, (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), c.r, c.g, c.b, c.a, 255); } while(--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); p += 4; } while(--len); } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { do { blender_type::blend_pix( m_comp_op, (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), c.r, c.g, c.b, c.a, cover); } while(--len); } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, *covers++); p += 4; } while(--len); } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { do { blender_type::blend_pix( m_comp_op, (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), c.r, c.g, c.b, c.a, *covers++); } while(--len); } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { p[order_type::R] = colors->r; p[order_type::G] = colors->g; p[order_type::B] = colors->b; p[order_type::A] = colors->a; ++colors; p += 4; } while(--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { do { value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); p[order_type::R] = colors->r; p[order_type::G] = colors->g; p[order_type::B] = colors->b; p[order_type::A] = colors->a; ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { blender_type::blend_pix(m_comp_op, p, colors->r, colors->g, colors->b, colors->a, covers ? *covers++ : cover); p += 4; ++colors; } while(--len); } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { do { blender_type::blend_pix( m_comp_op, (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), colors->r, colors->g, colors->b, colors->a, covers ? *covers++ : cover); ++colors; } while(--len); } //-------------------------------------------------------------------- template<class Function> void for_each_pixel(Function f) { unsigned y; for(y = 0; y < height(); ++y) { row_data r = m_rbuf->row(y); if(r.ptr) { unsigned len = r.x2 - r.x1 + 1; value_type* p = (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); do { f(p); p += 4; } while(--len); } } } //-------------------------------------------------------------------- void premultiply() { for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); } //-------------------------------------------------------------------- void demultiply() { for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_dir(const GammaLut& g) { for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class GammaLut> void apply_gamma_inv(const GammaLut& g) { for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g)); } //-------------------------------------------------------------------- template<class RenBuf2> void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { const int8u* p = from.row_ptr(ysrc); if(p) { memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; const value_type* psrc = (const value_type*)from.row_ptr(ysrc); if(psrc) { psrc += xsrc << 2; value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); int incp = 4; if(xdst > xsrc) { psrc += (len-1) << 2; pdst += (len-1) << 2; incp = -4; } do { blender_type::blend_pix(m_comp_op, pdst, psrc[src_order::R], psrc[src_order::G], psrc[src_order::B], psrc[src_order::A], cover); psrc += incp; pdst += incp; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); do { blender_type::blend_pix(m_comp_op, pdst, color.r, color.g, color.b, color.a, (*psrc * cover + base_mask) >> base_shift); ++psrc; pdst += 4; } while(--len); } } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { typedef typename SrcPixelFormatRenderer::value_type src_value_type; const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); if(psrc) { value_type* pdst = (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); do { const color_type& color = color_lut[*psrc]; blender_type::blend_pix(m_comp_op, pdst, color.r, color.g, color.b, color.a, cover); ++psrc; pdst += 4; } while(--len); } } private: rbuf_type* m_rbuf; unsigned m_comp_op; }; //----------------------------------------------------------------------- typedef blender_rgba<rgba8, order_rgba> blender_rgba32; //----blender_rgba32 typedef blender_rgba<rgba8, order_argb> blender_argb32; //----blender_argb32 typedef blender_rgba<rgba8, order_abgr> blender_abgr32; //----blender_abgr32 typedef blender_rgba<rgba8, order_bgra> blender_bgra32; //----blender_bgra32 typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; //----blender_rgba32_pre typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; //----blender_argb32_pre typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; //----blender_abgr32_pre typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; //----blender_bgra32_pre typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; //----blender_rgba32_plain typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; //----blender_argb32_plain typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; //----blender_abgr32_plain typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; //----blender_bgra32_plain typedef blender_rgba<rgba16, order_rgba> blender_rgba64; //----blender_rgba64 typedef blender_rgba<rgba16, order_argb> blender_argb64; //----blender_argb64 typedef blender_rgba<rgba16, order_abgr> blender_abgr64; //----blender_abgr64 typedef blender_rgba<rgba16, order_bgra> blender_bgra64; //----blender_bgra64 typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; //----blender_rgba64_pre typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; //----blender_argb64_pre typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; //----blender_abgr64_pre typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; //----blender_bgra64_pre //----------------------------------------------------------------------- typedef int32u pixel32_type; typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer, pixel32_type> pixfmt_rgba32; //----pixfmt_rgba32 typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer, pixel32_type> pixfmt_argb32; //----pixfmt_argb32 typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer, pixel32_type> pixfmt_abgr32; //----pixfmt_abgr32 typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer, pixel32_type> pixfmt_bgra32; //----pixfmt_bgra32 typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer, pixel32_type> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer, pixel32_type> pixfmt_argb32_pre; //----pixfmt_argb32_pre typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer, pixel32_type> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer, pixel32_type> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer, pixel32_type> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer, pixel32_type> pixfmt_argb32_plain; //----pixfmt_argb32_plain typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer, pixel32_type> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer, pixel32_type> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain struct pixel64_type { int16u c[4]; }; typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer, pixel64_type> pixfmt_rgba64; //----pixfmt_rgba64 typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer, pixel64_type> pixfmt_argb64; //----pixfmt_argb64 typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer, pixel64_type> pixfmt_abgr64; //----pixfmt_abgr64 typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer, pixel64_type> pixfmt_bgra64; //----pixfmt_bgra64 typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer, pixel64_type> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer, pixel64_type> pixfmt_argb64_pre; //----pixfmt_argb64_pre typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer, pixel64_type> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer, pixel64_type> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_image_filters.h�������������������������������������������0000644�0024617�0000144�00000035046�12261257215�023277� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Image transformation filters, // Filtering classes (image_filter_lut, image_filter), // Basic filter shape classes //---------------------------------------------------------------------------- #ifndef AGG_IMAGE_FILTERS_INCLUDED #define AGG_IMAGE_FILTERS_INCLUDED #include "agg_array.h" #include "agg_math.h" namespace mapserver { // See Implementation agg_image_filters.cpp enum image_filter_scale_e { image_filter_shift = 14, //----image_filter_shift image_filter_scale = 1 << image_filter_shift, //----image_filter_scale image_filter_mask = image_filter_scale - 1 //----image_filter_mask }; enum image_subpixel_scale_e { image_subpixel_shift = 8, //----image_subpixel_shift image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask }; //-----------------------------------------------------image_filter_lut class image_filter_lut { public: template<class FilterF> void calculate(const FilterF& filter, bool normalization=true) { double r = filter.radius(); realloc_lut(r); unsigned i; unsigned pivot = diameter() << (image_subpixel_shift - 1); for(i = 0; i < pivot; i++) { double x = double(i) / double(image_subpixel_scale); double y = filter.calc_weight(x); m_weight_array[pivot + i] = m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale); } unsigned end = (diameter() << image_subpixel_shift) - 1; m_weight_array[0] = m_weight_array[end]; if(normalization) { normalize(); } } image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} template<class FilterF> image_filter_lut(const FilterF& filter, bool normalization=true) { calculate(filter, normalization); } double radius() const { return m_radius; } unsigned diameter() const { return m_diameter; } int start() const { return m_start; } const int16* weight_array() const { return &m_weight_array[0]; } void normalize(); private: void realloc_lut(double radius); image_filter_lut(const image_filter_lut&); const image_filter_lut& operator = (const image_filter_lut&); double m_radius; unsigned m_diameter; int m_start; pod_array<int16> m_weight_array; }; //--------------------------------------------------------image_filter template<class FilterF> class image_filter : public image_filter_lut { public: image_filter() { calculate(m_filter_function); } private: FilterF m_filter_function; }; //-----------------------------------------------image_filter_bilinear struct image_filter_bilinear { static double radius() { return 1.0; } static double calc_weight(double x) { return 1.0 - x; } }; //-----------------------------------------------image_filter_hanning struct image_filter_hanning { static double radius() { return 1.0; } static double calc_weight(double x) { return 0.5 + 0.5 * cos(pi * x); } }; //-----------------------------------------------image_filter_hamming struct image_filter_hamming { static double radius() { return 1.0; } static double calc_weight(double x) { return 0.54 + 0.46 * cos(pi * x); } }; //-----------------------------------------------image_filter_hermite struct image_filter_hermite { static double radius() { return 1.0; } static double calc_weight(double x) { return (2.0 * x - 3.0) * x * x + 1.0; } }; //------------------------------------------------image_filter_quadric struct image_filter_quadric { static double radius() { return 1.5; } static double calc_weight(double x) { double t; if(x < 0.5) return 0.75 - x * x; if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;} return 0.0; } }; //------------------------------------------------image_filter_bicubic class image_filter_bicubic { static double pow3(double x) { return (x <= 0.0) ? 0.0 : x * x * x; } public: static double radius() { return 2.0; } static double calc_weight(double x) { return (1.0/6.0) * (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1)); } }; //-------------------------------------------------image_filter_kaiser class image_filter_kaiser { double a; double i0a; double epsilon; public: image_filter_kaiser(double b = 6.33) : a(b), epsilon(1e-12) { i0a = 1.0 / bessel_i0(b); } static double radius() { return 1.0; } double calc_weight(double x) const { return bessel_i0(a * sqrt(1. - x * x)) * i0a; } private: double bessel_i0(double x) const { int i; double sum, y, t; sum = 1.; y = x * x / 4.; t = y; for(i = 2; t > epsilon; i++) { sum += t; t *= (double)y / (i * i); } return sum; } }; //----------------------------------------------image_filter_catrom struct image_filter_catrom { static double radius() { return 2.0; } static double calc_weight(double x) { if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0)); if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x))); return 0.; } }; //---------------------------------------------image_filter_mitchell class image_filter_mitchell { double p0, p2, p3; double q0, q1, q2, q3; public: image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) : p0((6.0 - 2.0 * b) / 6.0), p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0), p3((12.0 - 9.0 * b - 6.0 * c) / 6.0), q0((8.0 * b + 24.0 * c) / 6.0), q1((-12.0 * b - 48.0 * c) / 6.0), q2((6.0 * b + 30.0 * c) / 6.0), q3((-b - 6.0 * c) / 6.0) {} static double radius() { return 2.0; } double calc_weight(double x) const { if(x < 1.0) return p0 + x * x * (p2 + x * p3); if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3)); return 0.0; } }; //----------------------------------------------image_filter_spline16 struct image_filter_spline16 { static double radius() { return 2.0; } static double calc_weight(double x) { if(x < 1.0) { return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0; } return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1); } }; //---------------------------------------------image_filter_spline36 struct image_filter_spline36 { static double radius() { return 3.0; } static double calc_weight(double x) { if(x < 1.0) { return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0; } if(x < 2.0) { return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1); } return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2); } }; //----------------------------------------------image_filter_gaussian struct image_filter_gaussian { static double radius() { return 2.0; } static double calc_weight(double x) { return exp(-2.0 * x * x) * sqrt(2.0 / pi); } }; //------------------------------------------------image_filter_bessel struct image_filter_bessel { static double radius() { return 3.2383; } static double calc_weight(double x) { return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); } }; //-------------------------------------------------image_filter_sinc class image_filter_sinc { public: image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {} double radius() const { return m_radius; } double calc_weight(double x) const { if(x == 0.0) return 1.0; x *= pi; return sin(x) / x; } private: double m_radius; }; //-----------------------------------------------image_filter_lanczos class image_filter_lanczos { public: image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {} double radius() const { return m_radius; } double calc_weight(double x) const { if(x == 0.0) return 1.0; if(x > m_radius) return 0.0; x *= pi; double xr = x / m_radius; return (sin(x) / x) * (sin(xr) / xr); } private: double m_radius; }; //----------------------------------------------image_filter_blackman class image_filter_blackman { public: image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {} double radius() const { return m_radius; } double calc_weight(double x) const { if(x == 0.0) return 1.0; if(x > m_radius) return 0.0; x *= pi; double xr = x / m_radius; return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr)); } private: double m_radius; }; //------------------------------------------------image_filter_sinc36 class image_filter_sinc36 : public image_filter_sinc { public: image_filter_sinc36() : image_filter_sinc(3.0){} }; //------------------------------------------------image_filter_sinc64 class image_filter_sinc64 : public image_filter_sinc { public: image_filter_sinc64() : image_filter_sinc(4.0){} }; //-----------------------------------------------image_filter_sinc100 class image_filter_sinc100 : public image_filter_sinc { public: image_filter_sinc100() : image_filter_sinc(5.0){} }; //-----------------------------------------------image_filter_sinc144 class image_filter_sinc144 : public image_filter_sinc { public: image_filter_sinc144() : image_filter_sinc(6.0){} }; //-----------------------------------------------image_filter_sinc196 class image_filter_sinc196 : public image_filter_sinc { public: image_filter_sinc196() : image_filter_sinc(7.0){} }; //-----------------------------------------------image_filter_sinc256 class image_filter_sinc256 : public image_filter_sinc { public: image_filter_sinc256() : image_filter_sinc(8.0){} }; //---------------------------------------------image_filter_lanczos36 class image_filter_lanczos36 : public image_filter_lanczos { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} }; //---------------------------------------------image_filter_lanczos64 class image_filter_lanczos64 : public image_filter_lanczos { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} }; //--------------------------------------------image_filter_lanczos100 class image_filter_lanczos100 : public image_filter_lanczos { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} }; //--------------------------------------------image_filter_lanczos144 class image_filter_lanczos144 : public image_filter_lanczos { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} }; //--------------------------------------------image_filter_lanczos196 class image_filter_lanczos196 : public image_filter_lanczos { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} }; //--------------------------------------------image_filter_lanczos256 class image_filter_lanczos256 : public image_filter_lanczos { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} }; //--------------------------------------------image_filter_blackman36 class image_filter_blackman36 : public image_filter_blackman { public: image_filter_blackman36() : image_filter_blackman(3.0){} }; //--------------------------------------------image_filter_blackman64 class image_filter_blackman64 : public image_filter_blackman { public: image_filter_blackman64() : image_filter_blackman(4.0){} }; //-------------------------------------------image_filter_blackman100 class image_filter_blackman100 : public image_filter_blackman { public: image_filter_blackman100() : image_filter_blackman(5.0){} }; //-------------------------------------------image_filter_blackman144 class image_filter_blackman144 : public image_filter_blackman { public: image_filter_blackman144() : image_filter_blackman(6.0){} }; //-------------------------------------------image_filter_blackman196 class image_filter_blackman196 : public image_filter_blackman { public: image_filter_blackman196() : image_filter_blackman(7.0){} }; //-------------------------------------------image_filter_blackman256 class image_filter_blackman256 : public image_filter_blackman { public: image_filter_blackman256() : image_filter_blackman(8.0){} }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_font_cache_manager.h��������������������������������������0000644�0024617�0000144�00000034522�12261257215�024246� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_FONT_CACHE_MANAGER_INCLUDED #define AGG_FONT_CACHE_MANAGER_INCLUDED #include <string.h> #include "agg_array.h" namespace mapserver { //---------------------------------------------------------glyph_data_type enum glyph_data_type { glyph_data_invalid = 0, glyph_data_mono = 1, glyph_data_gray8 = 2, glyph_data_outline = 3 }; //-------------------------------------------------------------glyph_cache struct glyph_cache { unsigned glyph_index; int8u* data; unsigned data_size; glyph_data_type data_type; rect_i bounds; double advance_x; double advance_y; }; //--------------------------------------------------------------font_cache class font_cache { public: enum block_size_e { block_size = 16384-16 }; //-------------------------------------------------------------------- font_cache() : m_allocator(block_size), m_font_signature(0) {} //-------------------------------------------------------------------- void signature(const char* font_signature) { m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); strcpy(m_font_signature, font_signature); memset(m_glyphs, 0, sizeof(m_glyphs)); } //-------------------------------------------------------------------- bool font_is(const char* font_signature) const { return strcmp(font_signature, m_font_signature) == 0; } //-------------------------------------------------------------------- const glyph_cache* find_glyph(unsigned glyph_code) const { unsigned msb = (glyph_code >> 8) & 0xFF; if(m_glyphs[msb]) { return m_glyphs[msb][glyph_code & 0xFF]; } return 0; } //-------------------------------------------------------------------- glyph_cache* cache_glyph(unsigned glyph_code, unsigned glyph_index, unsigned data_size, glyph_data_type data_type, const rect_i& bounds, double advance_x, double advance_y) { unsigned msb = (glyph_code >> 8) & 0xFF; if(m_glyphs[msb] == 0) { m_glyphs[msb] = (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, sizeof(glyph_cache*)); memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); } unsigned lsb = glyph_code & 0xFF; if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite glyph_cache* glyph = (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), sizeof(double)); glyph->glyph_index = glyph_index; glyph->data = m_allocator.allocate(data_size); glyph->data_size = data_size; glyph->data_type = data_type; glyph->bounds = bounds; glyph->advance_x = advance_x; glyph->advance_y = advance_y; return m_glyphs[msb][lsb] = glyph; } private: block_allocator m_allocator; glyph_cache** m_glyphs[256]; char* m_font_signature; }; //---------------------------------------------------------font_cache_pool class font_cache_pool { public: //-------------------------------------------------------------------- ~font_cache_pool() { unsigned i; for(i = 0; i < m_num_fonts; ++i) { obj_allocator<font_cache>::deallocate(m_fonts[i]); } pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts); } //-------------------------------------------------------------------- font_cache_pool(unsigned max_fonts=32) : m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)), m_max_fonts(max_fonts), m_num_fonts(0), m_cur_font(0) {} //-------------------------------------------------------------------- void font(const char* font_signature, bool reset_cache = false) { int idx = find_font(font_signature); if(idx >= 0) { if(reset_cache) { obj_allocator<font_cache>::deallocate(m_fonts[idx]); m_fonts[idx] = obj_allocator<font_cache>::allocate(); m_fonts[idx]->signature(font_signature); } m_cur_font = m_fonts[idx]; } else { if(m_num_fonts >= m_max_fonts) { obj_allocator<font_cache>::deallocate(m_fonts[0]); memcpy(m_fonts, m_fonts + 1, (m_max_fonts - 1) * sizeof(font_cache*)); m_num_fonts = m_max_fonts - 1; } m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate(); m_fonts[m_num_fonts]->signature(font_signature); m_cur_font = m_fonts[m_num_fonts]; ++m_num_fonts; } } //-------------------------------------------------------------------- const font_cache* font() const { return m_cur_font; } //-------------------------------------------------------------------- const glyph_cache* find_glyph(unsigned glyph_code) const { if(m_cur_font) return m_cur_font->find_glyph(glyph_code); return 0; } //-------------------------------------------------------------------- glyph_cache* cache_glyph(unsigned glyph_code, unsigned glyph_index, unsigned data_size, glyph_data_type data_type, const rect_i& bounds, double advance_x, double advance_y) { if(m_cur_font) { return m_cur_font->cache_glyph(glyph_code, glyph_index, data_size, data_type, bounds, advance_x, advance_y); } return 0; } //-------------------------------------------------------------------- int find_font(const char* font_signature) { unsigned i; for(i = 0; i < m_num_fonts; i++) { if(m_fonts[i]->font_is(font_signature)) return int(i); } return -1; } private: font_cache** m_fonts; unsigned m_max_fonts; unsigned m_num_fonts; font_cache* m_cur_font; }; //------------------------------------------------------------------------ enum glyph_rendering { glyph_ren_native_mono, glyph_ren_native_gray8, glyph_ren_outline, glyph_ren_agg_mono, glyph_ren_agg_gray8 }; //------------------------------------------------------font_cache_manager template<class FontEngine> class font_cache_manager { public: typedef FontEngine font_engine_type; typedef font_cache_manager<FontEngine> self_type; typedef typename font_engine_type::path_adaptor_type path_adaptor_type; typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; //-------------------------------------------------------------------- font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) : m_fonts(max_fonts), m_engine(engine), m_change_stamp(-1), m_prev_glyph(0), m_last_glyph(0) {} //-------------------------------------------------------------------- void reset_last_glyph() { m_prev_glyph = m_last_glyph = 0; } //-------------------------------------------------------------------- const glyph_cache* glyph(unsigned glyph_code) { synchronize(); const glyph_cache* gl = m_fonts.find_glyph(glyph_code); if(gl) { m_prev_glyph = m_last_glyph; return m_last_glyph = gl; } else { if(m_engine.prepare_glyph(glyph_code)) { m_prev_glyph = m_last_glyph; m_last_glyph = m_fonts.cache_glyph(glyph_code, m_engine.glyph_index(), m_engine.data_size(), m_engine.data_type(), m_engine.bounds(), m_engine.advance_x(), m_engine.advance_y()); m_engine.write_glyph_to(m_last_glyph->data); return m_last_glyph; } } return 0; } //-------------------------------------------------------------------- void init_embedded_adaptors(const glyph_cache* gl, double x, double y, double scale=1.0) { if(gl) { switch(gl->data_type) { default: return; case glyph_data_mono: m_mono_adaptor.init(gl->data, gl->data_size, x, y); break; case glyph_data_gray8: m_gray8_adaptor.init(gl->data, gl->data_size, x, y); break; case glyph_data_outline: m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); break; } } } //-------------------------------------------------------------------- path_adaptor_type& path_adaptor() { return m_path_adaptor; } gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } mono_scanline_type& mono_scanline() { return m_mono_scanline; } //-------------------------------------------------------------------- const glyph_cache* perv_glyph() const { return m_prev_glyph; } const glyph_cache* last_glyph() const { return m_last_glyph; } //-------------------------------------------------------------------- bool add_kerning(double* x, double* y) { if(m_prev_glyph && m_last_glyph) { return m_engine.add_kerning(m_prev_glyph->glyph_index, m_last_glyph->glyph_index, x, y); } return false; } //-------------------------------------------------------------------- void precache(unsigned from, unsigned to) { for(; from <= to; ++from) glyph(from); } //-------------------------------------------------------------------- void reset_cache() { m_fonts.font(m_engine.font_signature(), true); m_change_stamp = m_engine.change_stamp(); m_prev_glyph = m_last_glyph = 0; } private: //-------------------------------------------------------------------- font_cache_manager(const self_type&); const self_type& operator = (const self_type&); //-------------------------------------------------------------------- void synchronize() { if(m_change_stamp != m_engine.change_stamp()) { m_fonts.font(m_engine.font_signature()); m_change_stamp = m_engine.change_stamp(); m_prev_glyph = m_last_glyph = 0; } } font_cache_pool m_fonts; font_engine_type& m_engine; int m_change_stamp; double m_dx; double m_dy; const glyph_cache* m_prev_glyph; const glyph_cache* m_last_glyph; path_adaptor_type m_path_adaptor; gray8_adaptor_type m_gray8_adaptor; gray8_scanline_type m_gray8_scanline; mono_adaptor_type m_mono_adaptor; mono_scanline_type m_mono_scanline; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_dash.h����������������������������������������������0000644�0024617�0000144�00000005131�12261257215�022556� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Line dash generator // //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_DASH_INCLUDED #define AGG_VCGEN_DASH_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { //---------------------------------------------------------------vcgen_dash // // See Implementation agg_vcgen_dash.cpp // class vcgen_dash { enum max_dashes_e { max_dashes = 32 }; enum status_e { initial, ready, polyline, stop }; public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; vcgen_dash(); void remove_all_dashes(); void add_dash(double dash_len, double gap_len); void dash_start(double ds); void shorten(double s) { m_shorten = s; } double shorten() const { return m_shorten; } // Vertex Generator Interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: vcgen_dash(const vcgen_dash&); const vcgen_dash& operator = (const vcgen_dash&); void calc_dash_start(double ds); double m_dashes[max_dashes]; double m_total_dash_len; unsigned m_num_dashes; double m_dash_start; double m_shorten; double m_curr_dash_start; unsigned m_curr_dash; double m_curr_rest; const vertex_dist* m_v1; const vertex_dist* m_v2; vertex_storage m_src_vertices; unsigned m_closed; status_e m_status; unsigned m_src_vertex; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_viewport.h������������������������������������������0000644�0024617�0000144�00000022610�12261257215�023544� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Viewport transformer - simple orthogonal conversions from world coordinates // to screen (device) ones. // //---------------------------------------------------------------------------- #ifndef AGG_TRANS_VIEWPORT_INCLUDED #define AGG_TRANS_VIEWPORT_INCLUDED #include <string.h> #include "agg_trans_affine.h" namespace mapserver { enum aspect_ratio_e { aspect_ratio_stretch, aspect_ratio_meet, aspect_ratio_slice }; //----------------------------------------------------------trans_viewport class trans_viewport { public: //------------------------------------------------------------------- trans_viewport() : m_world_x1(0.0), m_world_y1(0.0), m_world_x2(1.0), m_world_y2(1.0), m_device_x1(0.0), m_device_y1(0.0), m_device_x2(1.0), m_device_y2(1.0), m_aspect(aspect_ratio_stretch), m_is_valid(true), m_align_x(0.5), m_align_y(0.5), m_wx1(0.0), m_wy1(0.0), m_wx2(1.0), m_wy2(1.0), m_dx1(0.0), m_dy1(0.0), m_kx(1.0), m_ky(1.0) {} //------------------------------------------------------------------- void preserve_aspect_ratio(double alignx, double aligny, aspect_ratio_e aspect) { m_align_x = alignx; m_align_y = aligny; m_aspect = aspect; update(); } //------------------------------------------------------------------- void device_viewport(double x1, double y1, double x2, double y2) { m_device_x1 = x1; m_device_y1 = y1; m_device_x2 = x2; m_device_y2 = y2; update(); } //------------------------------------------------------------------- void world_viewport(double x1, double y1, double x2, double y2) { m_world_x1 = x1; m_world_y1 = y1; m_world_x2 = x2; m_world_y2 = y2; update(); } //------------------------------------------------------------------- void device_viewport(double* x1, double* y1, double* x2, double* y2) const { *x1 = m_device_x1; *y1 = m_device_y1; *x2 = m_device_x2; *y2 = m_device_y2; } //------------------------------------------------------------------- void world_viewport(double* x1, double* y1, double* x2, double* y2) const { *x1 = m_world_x1; *y1 = m_world_y1; *x2 = m_world_x2; *y2 = m_world_y2; } //------------------------------------------------------------------- void world_viewport_actual(double* x1, double* y1, double* x2, double* y2) const { *x1 = m_wx1; *y1 = m_wy1; *x2 = m_wx2; *y2 = m_wy2; } //------------------------------------------------------------------- bool is_valid() const { return m_is_valid; } double align_x() const { return m_align_x; } double align_y() const { return m_align_y; } aspect_ratio_e aspect_ratio() const { return m_aspect; } //------------------------------------------------------------------- void transform(double* x, double* y) const { *x = (*x - m_wx1) * m_kx + m_dx1; *y = (*y - m_wy1) * m_ky + m_dy1; } //------------------------------------------------------------------- void transform_scale_only(double* x, double* y) const { *x *= m_kx; *y *= m_ky; } //------------------------------------------------------------------- void inverse_transform(double* x, double* y) const { *x = (*x - m_dx1) / m_kx + m_wx1; *y = (*y - m_dy1) / m_ky + m_wy1; } //------------------------------------------------------------------- void inverse_transform_scale_only(double* x, double* y) const { *x /= m_kx; *y /= m_ky; } //------------------------------------------------------------------- double device_dx() const { return m_dx1 - m_wx1 * m_kx; } double device_dy() const { return m_dy1 - m_wy1 * m_ky; } //------------------------------------------------------------------- double scale_x() const { return m_kx; } //------------------------------------------------------------------- double scale_y() const { return m_ky; } //------------------------------------------------------------------- double scale() const { return (m_kx + m_ky) * 0.5; } //------------------------------------------------------------------- trans_affine to_affine() const { trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1); mtx *= trans_affine_scaling(m_kx, m_ky); mtx *= trans_affine_translation(m_dx1, m_dy1); return mtx; } //------------------------------------------------------------------- trans_affine to_affine_scale_only() const { return trans_affine_scaling(m_kx, m_ky); } //------------------------------------------------------------------- unsigned byte_size() const { return sizeof(*this); } void serialize(int8u* ptr) const { memcpy(ptr, this, sizeof(*this)); } void deserialize(const int8u* ptr) { memcpy(this, ptr, sizeof(*this)); } private: void update(); double m_world_x1; double m_world_y1; double m_world_x2; double m_world_y2; double m_device_x1; double m_device_y1; double m_device_x2; double m_device_y2; aspect_ratio_e m_aspect; bool m_is_valid; double m_align_x; double m_align_y; double m_wx1; double m_wy1; double m_wx2; double m_wy2; double m_dx1; double m_dy1; double m_kx; double m_ky; }; //----------------------------------------------------------------------- inline void trans_viewport::update() { const double epsilon = 1e-30; if(fabs(m_world_x1 - m_world_x2) < epsilon || fabs(m_world_y1 - m_world_y2) < epsilon || fabs(m_device_x1 - m_device_x2) < epsilon || fabs(m_device_y1 - m_device_y2) < epsilon) { m_wx1 = m_world_x1; m_wy1 = m_world_y1; m_wx2 = m_world_x1 + 1.0; m_wy2 = m_world_y2 + 1.0; m_dx1 = m_device_x1; m_dy1 = m_device_y1; m_kx = 1.0; m_ky = 1.0; m_is_valid = false; return; } double world_x1 = m_world_x1; double world_y1 = m_world_y1; double world_x2 = m_world_x2; double world_y2 = m_world_y2; double device_x1 = m_device_x1; double device_y1 = m_device_y1; double device_x2 = m_device_x2; double device_y2 = m_device_y2; if(m_aspect != aspect_ratio_stretch) { double d; m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky)) { d = (world_y2 - world_y1) * m_ky / m_kx; world_y1 += (world_y2 - world_y1 - d) * m_align_y; world_y2 = world_y1 + d; } else { d = (world_x2 - world_x1) * m_kx / m_ky; world_x1 += (world_x2 - world_x1 - d) * m_align_x; world_x2 = world_x1 + d; } } m_wx1 = world_x1; m_wy1 = world_y1; m_wx2 = world_x2; m_wy2 = world_y2; m_dx1 = device_x1; m_dy1 = device_y1; m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); m_is_valid = true; } } #endif ������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_glyph_raster_bin.h����������������������������������������0000644�0024617�0000144�00000011425�12261257215�024013� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_GLYPH_RASTER_BIN_INCLUDED #define AGG_GLYPH_RASTER_BIN_INCLUDED #include <string.h> #include "agg_basics.h" namespace mapserver { //========================================================glyph_raster_bin template<class ColorT> class glyph_raster_bin { public: typedef ColorT color_type; //-------------------------------------------------------------------- struct glyph_rect { int x1,y1,x2,y2; double dx, dy; }; //-------------------------------------------------------------------- glyph_raster_bin(const int8u* font) : m_font(font), m_big_endian(false) { int t = 1; if(*(char*)&t == 0) m_big_endian = true; memset(m_span, 0, sizeof(m_span)); } //-------------------------------------------------------------------- const int8u* font() const { return m_font; } void font(const int8u* f) { m_font = f; } //-------------------------------------------------------------------- double height() const { return m_font[0]; } double base_line() const { return m_font[1]; } //-------------------------------------------------------------------- template<class CharT> double width(const CharT* str) const { unsigned start_char = m_font[2]; unsigned num_chars = m_font[3]; unsigned w = 0; while(*str) { unsigned glyph = *str; const int8u* bits = m_font + 4 + num_chars * 2 + value(m_font + 4 + (glyph - start_char) * 2); w += *bits; ++str; } return w; } //-------------------------------------------------------------------- void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip) { unsigned start_char = m_font[2]; unsigned num_chars = m_font[3]; m_bits = m_font + 4 + num_chars * 2 + value(m_font + 4 + (glyph - start_char) * 2); m_glyph_width = *m_bits++; m_glyph_byte_width = (m_glyph_width + 7) >> 3; r->x1 = int(x); r->x2 = r->x1 + m_glyph_width - 1; if(flip) { r->y1 = int(y) - m_font[0] + m_font[1]; r->y2 = r->y1 + m_font[0] - 1; } else { r->y1 = int(y) - m_font[1] + 1; r->y2 = r->y1 + m_font[0] - 1; } r->dx = m_glyph_width; r->dy = 0; } //-------------------------------------------------------------------- const cover_type* span(unsigned i) { i = m_font[0] - i - 1; const int8u* bits = m_bits + i * m_glyph_byte_width; unsigned j; unsigned val = *bits; unsigned nb = 0; for(j = 0; j < m_glyph_width; ++j) { m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none); val <<= 1; if(++nb >= 8) { val = *++bits; nb = 0; } } return m_span; } private: //-------------------------------------------------------------------- int16u value(const int8u* p) const { int16u v; if(m_big_endian) { *(int8u*)&v = p[1]; *((int8u*)&v + 1) = p[0]; } else { *(int8u*)&v = p[0]; *((int8u*)&v + 1) = p[1]; } return v; } //-------------------------------------------------------------------- const int8u* m_font; bool m_big_endian; cover_type m_span[32]; const int8u* m_bits; unsigned m_glyph_width; unsigned m_glyph_byte_width; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_blur.h����������������������������������������������������0000644�0024617�0000144�00000127775�12261257215�021444� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // The Stack Blur Algorithm was invented by Mario Klingemann, // mario@quasimondo.com and described here: // http://incubator.quasimondo.com/processing/fast_blur_deluxe.php // (search phrase "Stackblur: Fast But Goodlooking"). // The major improvement is that there's no more division table // that was very expensive to create for large blur radii. Insted, // for 8-bit per channel and radius not exceeding 254 the division is // replaced by multiplication and shift. // //---------------------------------------------------------------------------- #ifndef AGG_BLUR_INCLUDED #define AGG_BLUR_INCLUDED #include "agg_array.h" #include "agg_pixfmt_transposer.h" namespace mapserver { template<class T> struct stack_blur_tables { static int16u const g_stack_blur8_mul[255]; static int8u const g_stack_blur8_shr[255]; }; //------------------------------------------------------------------------ template<class T> int16u const stack_blur_tables<T>::g_stack_blur8_mul[255] = { 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 }; //------------------------------------------------------------------------ template<class T> int8u const stack_blur_tables<T>::g_stack_blur8_shr[255] = { 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 }; //==============================================================stack_blur template<class ColorT, class CalculatorT> class stack_blur { public: typedef ColorT color_type; typedef CalculatorT calculator_type; //-------------------------------------------------------------------- template<class Img> void blur_x(Img& img, unsigned radius) { if(radius < 1) return; unsigned x, y, xp, i; unsigned stack_ptr; unsigned stack_start; color_type pix; color_type* stack_pix; calculator_type sum; calculator_type sum_in; calculator_type sum_out; unsigned w = img.width(); unsigned h = img.height(); unsigned wm = w - 1; unsigned div = radius * 2 + 1; unsigned div_sum = (radius + 1) * (radius + 1); unsigned mul_sum = 0; unsigned shr_sum = 0; unsigned max_val = color_type::base_mask; if(max_val <= 255 && radius < 255) { mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[radius]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[radius]; } m_buf.allocate(w, 128); m_stack.allocate(div, 32); for(y = 0; y < h; y++) { sum.clear(); sum_in.clear(); sum_out.clear(); pix = img.pixel(0, y); for(i = 0; i <= radius; i++) { m_stack[i] = pix; sum.add(pix, i + 1); sum_out.add(pix); } for(i = 1; i <= radius; i++) { pix = img.pixel((i > wm) ? wm : i, y); m_stack[i + radius] = pix; sum.add(pix, radius + 1 - i); sum_in.add(pix); } stack_ptr = radius; for(x = 0; x < w; x++) { if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum); else sum.calc_pix(m_buf[x], div_sum); sum.sub(sum_out); stack_start = stack_ptr + div - radius; if(stack_start >= div) stack_start -= div; stack_pix = &m_stack[stack_start]; sum_out.sub(*stack_pix); xp = x + radius + 1; if(xp > wm) xp = wm; pix = img.pixel(xp, y); *stack_pix = pix; sum_in.add(pix); sum.add(sum_in); ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix = &m_stack[stack_ptr]; sum_out.add(*stack_pix); sum_in.sub(*stack_pix); } img.copy_color_hspan(0, y, w, &m_buf[0]); } } //-------------------------------------------------------------------- template<class Img> void blur_y(Img& img, unsigned radius) { pixfmt_transposer<Img> img2(img); blur_x(img2, radius); } //-------------------------------------------------------------------- template<class Img> void blur(Img& img, unsigned radius) { blur_x(img, radius); pixfmt_transposer<Img> img2(img); blur_x(img2, radius); } private: pod_vector<color_type> m_buf; pod_vector<color_type> m_stack; }; //====================================================stack_blur_calc_rgba template<class T=unsigned> struct stack_blur_calc_rgba { typedef T value_type; value_type r,g,b,a; AGG_INLINE void clear() { r = g = b = a = 0; } template<class ArgT> AGG_INLINE void add(const ArgT& v) { r += v.r; g += v.g; b += v.b; a += v.a; } template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k) { r += v.r * k; g += v.g * k; b += v.b * k; a += v.a * k; } template<class ArgT> AGG_INLINE void sub(const ArgT& v) { r -= v.r; g -= v.g; b -= v.b; a -= v.a; } template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div) { typedef typename ArgT::value_type value_type; v.r = value_type(r / div); v.g = value_type(g / div); v.b = value_type(b / div); v.a = value_type(a / div); } template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) { typedef typename ArgT::value_type value_type; v.r = value_type((r * mul) >> shr); v.g = value_type((g * mul) >> shr); v.b = value_type((b * mul) >> shr); v.a = value_type((a * mul) >> shr); } }; //=====================================================stack_blur_calc_rgb template<class T=unsigned> struct stack_blur_calc_rgb { typedef T value_type; value_type r,g,b; AGG_INLINE void clear() { r = g = b = 0; } template<class ArgT> AGG_INLINE void add(const ArgT& v) { r += v.r; g += v.g; b += v.b; } template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k) { r += v.r * k; g += v.g * k; b += v.b * k; } template<class ArgT> AGG_INLINE void sub(const ArgT& v) { r -= v.r; g -= v.g; b -= v.b; } template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div) { typedef typename ArgT::value_type value_type; v.r = value_type(r / div); v.g = value_type(g / div); v.b = value_type(b / div); } template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) { typedef typename ArgT::value_type value_type; v.r = value_type((r * mul) >> shr); v.g = value_type((g * mul) >> shr); v.b = value_type((b * mul) >> shr); } }; //====================================================stack_blur_calc_gray template<class T=unsigned> struct stack_blur_calc_gray { typedef T value_type; value_type v; AGG_INLINE void clear() { v = 0; } template<class ArgT> AGG_INLINE void add(const ArgT& a) { v += a.v; } template<class ArgT> AGG_INLINE void add(const ArgT& a, unsigned k) { v += a.v * k; } template<class ArgT> AGG_INLINE void sub(const ArgT& a) { v -= a.v; } template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned div) { typedef typename ArgT::value_type value_type; a.v = value_type(v / div); } template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr) { typedef typename ArgT::value_type value_type; a.v = value_type((v * mul) >> shr); } }; //========================================================stack_blur_gray8 template<class Img> void stack_blur_gray8(Img& img, unsigned rx, unsigned ry) { unsigned x, y, xp, yp, i; unsigned stack_ptr; unsigned stack_start; const int8u* src_pix_ptr; int8u* dst_pix_ptr; unsigned pix; unsigned stack_pix; unsigned sum; unsigned sum_in; unsigned sum_out; unsigned w = img.width(); unsigned h = img.height(); unsigned wm = w - 1; unsigned hm = h - 1; unsigned div; unsigned mul_sum; unsigned shr_sum; pod_vector<int8u> stack; if(rx > 0) { if(rx > 254) rx = 254; div = rx * 2 + 1; mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; stack.allocate(div); for(y = 0; y < h; y++) { sum = sum_in = sum_out = 0; src_pix_ptr = img.pix_ptr(0, y); pix = *src_pix_ptr; for(i = 0; i <= rx; i++) { stack[i] = pix; sum += pix * (i + 1); sum_out += pix; } for(i = 1; i <= rx; i++) { if(i <= wm) src_pix_ptr += Img::pix_step; pix = *src_pix_ptr; stack[i + rx] = pix; sum += pix * (rx + 1 - i); sum_in += pix; } stack_ptr = rx; xp = rx; if(xp > wm) xp = wm; src_pix_ptr = img.pix_ptr(xp, y); dst_pix_ptr = img.pix_ptr(0, y); for(x = 0; x < w; x++) { *dst_pix_ptr = (sum * mul_sum) >> shr_sum; dst_pix_ptr += Img::pix_step; sum -= sum_out; stack_start = stack_ptr + div - rx; if(stack_start >= div) stack_start -= div; sum_out -= stack[stack_start]; if(xp < wm) { src_pix_ptr += Img::pix_step; pix = *src_pix_ptr; ++xp; } stack[stack_start] = pix; sum_in += pix; sum += sum_in; ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix = stack[stack_ptr]; sum_out += stack_pix; sum_in -= stack_pix; } } } if(ry > 0) { if(ry > 254) ry = 254; div = ry * 2 + 1; mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; stack.allocate(div); int stride = img.stride(); for(x = 0; x < w; x++) { sum = sum_in = sum_out = 0; src_pix_ptr = img.pix_ptr(x, 0); pix = *src_pix_ptr; for(i = 0; i <= ry; i++) { stack[i] = pix; sum += pix * (i + 1); sum_out += pix; } for(i = 1; i <= ry; i++) { if(i <= hm) src_pix_ptr += stride; pix = *src_pix_ptr; stack[i + ry] = pix; sum += pix * (ry + 1 - i); sum_in += pix; } stack_ptr = ry; yp = ry; if(yp > hm) yp = hm; src_pix_ptr = img.pix_ptr(x, yp); dst_pix_ptr = img.pix_ptr(x, 0); for(y = 0; y < h; y++) { *dst_pix_ptr = (sum * mul_sum) >> shr_sum; dst_pix_ptr += stride; sum -= sum_out; stack_start = stack_ptr + div - ry; if(stack_start >= div) stack_start -= div; sum_out -= stack[stack_start]; if(yp < hm) { src_pix_ptr += stride; pix = *src_pix_ptr; ++yp; } stack[stack_start] = pix; sum_in += pix; sum += sum_in; ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix = stack[stack_ptr]; sum_out += stack_pix; sum_in -= stack_pix; } } } } //========================================================stack_blur_rgb24 template<class Img> void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry) { typedef typename Img::color_type color_type; typedef typename Img::order_type order_type; enum order_e { R = order_type::R, G = order_type::G, B = order_type::B }; unsigned x, y, xp, yp, i; unsigned stack_ptr; unsigned stack_start; const int8u* src_pix_ptr; int8u* dst_pix_ptr; color_type* stack_pix_ptr; unsigned sum_r; unsigned sum_g; unsigned sum_b; unsigned sum_in_r; unsigned sum_in_g; unsigned sum_in_b; unsigned sum_out_r; unsigned sum_out_g; unsigned sum_out_b; unsigned w = img.width(); unsigned h = img.height(); unsigned wm = w - 1; unsigned hm = h - 1; unsigned div; unsigned mul_sum; unsigned shr_sum; pod_vector<color_type> stack; if(rx > 0) { if(rx > 254) rx = 254; div = rx * 2 + 1; mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; stack.allocate(div); for(y = 0; y < h; y++) { sum_r = sum_g = sum_b = sum_in_r = sum_in_g = sum_in_b = sum_out_r = sum_out_g = sum_out_b = 0; src_pix_ptr = img.pix_ptr(0, y); for(i = 0; i <= rx; i++) { stack_pix_ptr = &stack[i]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; sum_r += src_pix_ptr[R] * (i + 1); sum_g += src_pix_ptr[G] * (i + 1); sum_b += src_pix_ptr[B] * (i + 1); sum_out_r += src_pix_ptr[R]; sum_out_g += src_pix_ptr[G]; sum_out_b += src_pix_ptr[B]; } for(i = 1; i <= rx; i++) { if(i <= wm) src_pix_ptr += Img::pix_width; stack_pix_ptr = &stack[i + rx]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; sum_r += src_pix_ptr[R] * (rx + 1 - i); sum_g += src_pix_ptr[G] * (rx + 1 - i); sum_b += src_pix_ptr[B] * (rx + 1 - i); sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; } stack_ptr = rx; xp = rx; if(xp > wm) xp = wm; src_pix_ptr = img.pix_ptr(xp, y); dst_pix_ptr = img.pix_ptr(0, y); for(x = 0; x < w; x++) { dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; dst_pix_ptr += Img::pix_width; sum_r -= sum_out_r; sum_g -= sum_out_g; sum_b -= sum_out_b; stack_start = stack_ptr + div - rx; if(stack_start >= div) stack_start -= div; stack_pix_ptr = &stack[stack_start]; sum_out_r -= stack_pix_ptr->r; sum_out_g -= stack_pix_ptr->g; sum_out_b -= stack_pix_ptr->b; if(xp < wm) { src_pix_ptr += Img::pix_width; ++xp; } stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; sum_r += sum_in_r; sum_g += sum_in_g; sum_b += sum_in_b; ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix_ptr = &stack[stack_ptr]; sum_out_r += stack_pix_ptr->r; sum_out_g += stack_pix_ptr->g; sum_out_b += stack_pix_ptr->b; sum_in_r -= stack_pix_ptr->r; sum_in_g -= stack_pix_ptr->g; sum_in_b -= stack_pix_ptr->b; } } } if(ry > 0) { if(ry > 254) ry = 254; div = ry * 2 + 1; mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; stack.allocate(div); int stride = img.stride(); for(x = 0; x < w; x++) { sum_r = sum_g = sum_b = sum_in_r = sum_in_g = sum_in_b = sum_out_r = sum_out_g = sum_out_b = 0; src_pix_ptr = img.pix_ptr(x, 0); for(i = 0; i <= ry; i++) { stack_pix_ptr = &stack[i]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; sum_r += src_pix_ptr[R] * (i + 1); sum_g += src_pix_ptr[G] * (i + 1); sum_b += src_pix_ptr[B] * (i + 1); sum_out_r += src_pix_ptr[R]; sum_out_g += src_pix_ptr[G]; sum_out_b += src_pix_ptr[B]; } for(i = 1; i <= ry; i++) { if(i <= hm) src_pix_ptr += stride; stack_pix_ptr = &stack[i + ry]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; sum_r += src_pix_ptr[R] * (ry + 1 - i); sum_g += src_pix_ptr[G] * (ry + 1 - i); sum_b += src_pix_ptr[B] * (ry + 1 - i); sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; } stack_ptr = ry; yp = ry; if(yp > hm) yp = hm; src_pix_ptr = img.pix_ptr(x, yp); dst_pix_ptr = img.pix_ptr(x, 0); for(y = 0; y < h; y++) { dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; dst_pix_ptr += stride; sum_r -= sum_out_r; sum_g -= sum_out_g; sum_b -= sum_out_b; stack_start = stack_ptr + div - ry; if(stack_start >= div) stack_start -= div; stack_pix_ptr = &stack[stack_start]; sum_out_r -= stack_pix_ptr->r; sum_out_g -= stack_pix_ptr->g; sum_out_b -= stack_pix_ptr->b; if(yp < hm) { src_pix_ptr += stride; ++yp; } stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; sum_r += sum_in_r; sum_g += sum_in_g; sum_b += sum_in_b; ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix_ptr = &stack[stack_ptr]; sum_out_r += stack_pix_ptr->r; sum_out_g += stack_pix_ptr->g; sum_out_b += stack_pix_ptr->b; sum_in_r -= stack_pix_ptr->r; sum_in_g -= stack_pix_ptr->g; sum_in_b -= stack_pix_ptr->b; } } } } //=======================================================stack_blur_rgba32 template<class Img> void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry) { typedef typename Img::color_type color_type; typedef typename Img::order_type order_type; enum order_e { R = order_type::R, G = order_type::G, B = order_type::B, A = order_type::A }; unsigned x, y, xp, yp, i; unsigned stack_ptr; unsigned stack_start; const int8u* src_pix_ptr; int8u* dst_pix_ptr; color_type* stack_pix_ptr; unsigned sum_r; unsigned sum_g; unsigned sum_b; unsigned sum_a; unsigned sum_in_r; unsigned sum_in_g; unsigned sum_in_b; unsigned sum_in_a; unsigned sum_out_r; unsigned sum_out_g; unsigned sum_out_b; unsigned sum_out_a; unsigned w = img.width(); unsigned h = img.height(); unsigned wm = w - 1; unsigned hm = h - 1; unsigned div; unsigned mul_sum; unsigned shr_sum; pod_vector<color_type> stack; if(rx > 0) { if(rx > 254) rx = 254; div = rx * 2 + 1; mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; stack.allocate(div); for(y = 0; y < h; y++) { sum_r = sum_g = sum_b = sum_a = sum_in_r = sum_in_g = sum_in_b = sum_in_a = sum_out_r = sum_out_g = sum_out_b = sum_out_a = 0; src_pix_ptr = img.pix_ptr(0, y); for(i = 0; i <= rx; i++) { stack_pix_ptr = &stack[i]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; stack_pix_ptr->a = src_pix_ptr[A]; sum_r += src_pix_ptr[R] * (i + 1); sum_g += src_pix_ptr[G] * (i + 1); sum_b += src_pix_ptr[B] * (i + 1); sum_a += src_pix_ptr[A] * (i + 1); sum_out_r += src_pix_ptr[R]; sum_out_g += src_pix_ptr[G]; sum_out_b += src_pix_ptr[B]; sum_out_a += src_pix_ptr[A]; } for(i = 1; i <= rx; i++) { if(i <= wm) src_pix_ptr += Img::pix_width; stack_pix_ptr = &stack[i + rx]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; stack_pix_ptr->a = src_pix_ptr[A]; sum_r += src_pix_ptr[R] * (rx + 1 - i); sum_g += src_pix_ptr[G] * (rx + 1 - i); sum_b += src_pix_ptr[B] * (rx + 1 - i); sum_a += src_pix_ptr[A] * (rx + 1 - i); sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; sum_in_a += src_pix_ptr[A]; } stack_ptr = rx; xp = rx; if(xp > wm) xp = wm; src_pix_ptr = img.pix_ptr(xp, y); dst_pix_ptr = img.pix_ptr(0, y); for(x = 0; x < w; x++) { dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; dst_pix_ptr += Img::pix_width; sum_r -= sum_out_r; sum_g -= sum_out_g; sum_b -= sum_out_b; sum_a -= sum_out_a; stack_start = stack_ptr + div - rx; if(stack_start >= div) stack_start -= div; stack_pix_ptr = &stack[stack_start]; sum_out_r -= stack_pix_ptr->r; sum_out_g -= stack_pix_ptr->g; sum_out_b -= stack_pix_ptr->b; sum_out_a -= stack_pix_ptr->a; if(xp < wm) { src_pix_ptr += Img::pix_width; ++xp; } stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; stack_pix_ptr->a = src_pix_ptr[A]; sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; sum_in_a += src_pix_ptr[A]; sum_r += sum_in_r; sum_g += sum_in_g; sum_b += sum_in_b; sum_a += sum_in_a; ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix_ptr = &stack[stack_ptr]; sum_out_r += stack_pix_ptr->r; sum_out_g += stack_pix_ptr->g; sum_out_b += stack_pix_ptr->b; sum_out_a += stack_pix_ptr->a; sum_in_r -= stack_pix_ptr->r; sum_in_g -= stack_pix_ptr->g; sum_in_b -= stack_pix_ptr->b; sum_in_a -= stack_pix_ptr->a; } } } if(ry > 0) { if(ry > 254) ry = 254; div = ry * 2 + 1; mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; stack.allocate(div); int stride = img.stride(); for(x = 0; x < w; x++) { sum_r = sum_g = sum_b = sum_a = sum_in_r = sum_in_g = sum_in_b = sum_in_a = sum_out_r = sum_out_g = sum_out_b = sum_out_a = 0; src_pix_ptr = img.pix_ptr(x, 0); for(i = 0; i <= ry; i++) { stack_pix_ptr = &stack[i]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; stack_pix_ptr->a = src_pix_ptr[A]; sum_r += src_pix_ptr[R] * (i + 1); sum_g += src_pix_ptr[G] * (i + 1); sum_b += src_pix_ptr[B] * (i + 1); sum_a += src_pix_ptr[A] * (i + 1); sum_out_r += src_pix_ptr[R]; sum_out_g += src_pix_ptr[G]; sum_out_b += src_pix_ptr[B]; sum_out_a += src_pix_ptr[A]; } for(i = 1; i <= ry; i++) { if(i <= hm) src_pix_ptr += stride; stack_pix_ptr = &stack[i + ry]; stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; stack_pix_ptr->a = src_pix_ptr[A]; sum_r += src_pix_ptr[R] * (ry + 1 - i); sum_g += src_pix_ptr[G] * (ry + 1 - i); sum_b += src_pix_ptr[B] * (ry + 1 - i); sum_a += src_pix_ptr[A] * (ry + 1 - i); sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; sum_in_a += src_pix_ptr[A]; } stack_ptr = ry; yp = ry; if(yp > hm) yp = hm; src_pix_ptr = img.pix_ptr(x, yp); dst_pix_ptr = img.pix_ptr(x, 0); for(y = 0; y < h; y++) { dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; dst_pix_ptr += stride; sum_r -= sum_out_r; sum_g -= sum_out_g; sum_b -= sum_out_b; sum_a -= sum_out_a; stack_start = stack_ptr + div - ry; if(stack_start >= div) stack_start -= div; stack_pix_ptr = &stack[stack_start]; sum_out_r -= stack_pix_ptr->r; sum_out_g -= stack_pix_ptr->g; sum_out_b -= stack_pix_ptr->b; sum_out_a -= stack_pix_ptr->a; if(yp < hm) { src_pix_ptr += stride; ++yp; } stack_pix_ptr->r = src_pix_ptr[R]; stack_pix_ptr->g = src_pix_ptr[G]; stack_pix_ptr->b = src_pix_ptr[B]; stack_pix_ptr->a = src_pix_ptr[A]; sum_in_r += src_pix_ptr[R]; sum_in_g += src_pix_ptr[G]; sum_in_b += src_pix_ptr[B]; sum_in_a += src_pix_ptr[A]; sum_r += sum_in_r; sum_g += sum_in_g; sum_b += sum_in_b; sum_a += sum_in_a; ++stack_ptr; if(stack_ptr >= div) stack_ptr = 0; stack_pix_ptr = &stack[stack_ptr]; sum_out_r += stack_pix_ptr->r; sum_out_g += stack_pix_ptr->g; sum_out_b += stack_pix_ptr->b; sum_out_a += stack_pix_ptr->a; sum_in_r -= stack_pix_ptr->r; sum_in_g -= stack_pix_ptr->g; sum_in_b -= stack_pix_ptr->b; sum_in_a -= stack_pix_ptr->a; } } } } //===========================================================recursive_blur template<class ColorT, class CalculatorT> class recursive_blur { public: typedef ColorT color_type; typedef CalculatorT calculator_type; typedef typename color_type::value_type value_type; typedef typename calculator_type::value_type calc_type; //-------------------------------------------------------------------- template<class Img> void blur_x(Img& img, double radius) { if(radius < 0.62) return; if(img.width() < 3) return; calc_type s = calc_type(radius * 0.5); calc_type q = calc_type((s < 2.5) ? 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) : 0.98711 * s - 0.96330); calc_type q2 = calc_type(q * q); calc_type q3 = calc_type(q2 * q); calc_type b0 = calc_type(1.0 / (1.578250 + 2.444130 * q + 1.428100 * q2 + 0.422205 * q3)); calc_type b1 = calc_type( 2.44413 * q + 2.85619 * q2 + 1.26661 * q3); calc_type b2 = calc_type(-1.42810 * q2 + -1.26661 * q3); calc_type b3 = calc_type(0.422205 * q3); calc_type b = calc_type(1 - (b1 + b2 + b3) * b0); b1 *= b0; b2 *= b0; b3 *= b0; int w = img.width(); int h = img.height(); int wm = w-1; int x, y; m_sum1.allocate(w); m_sum2.allocate(w); m_buf.allocate(w); for(y = 0; y < h; y++) { calculator_type c; c.from_pix(img.pixel(0, y)); m_sum1[0].calc(b, b1, b2, b3, c, c, c, c); c.from_pix(img.pixel(1, y)); m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]); c.from_pix(img.pixel(2, y)); m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]); for(x = 3; x < w; ++x) { c.from_pix(img.pixel(x, y)); m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]); } m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]); m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]); m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]); m_sum2[wm ].to_pix(m_buf[wm ]); m_sum2[wm-1].to_pix(m_buf[wm-1]); m_sum2[wm-2].to_pix(m_buf[wm-2]); for(x = wm-3; x >= 0; --x) { m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]); m_sum2[x].to_pix(m_buf[x]); } img.copy_color_hspan(0, y, w, &m_buf[0]); } } //-------------------------------------------------------------------- template<class Img> void blur_y(Img& img, double radius) { pixfmt_transposer<Img> img2(img); blur_x(img2, radius); } //-------------------------------------------------------------------- template<class Img> void blur(Img& img, double radius) { blur_x(img, radius); pixfmt_transposer<Img> img2(img); blur_x(img2, radius); } private: mapserver::pod_vector<calculator_type> m_sum1; mapserver::pod_vector<calculator_type> m_sum2; mapserver::pod_vector<color_type> m_buf; }; //=================================================recursive_blur_calc_rgba template<class T=double> struct recursive_blur_calc_rgba { typedef T value_type; typedef recursive_blur_calc_rgba<T> self_type; value_type r,g,b,a; template<class ColorT> AGG_INLINE void from_pix(const ColorT& c) { r = c.r; g = c.g; b = c.b; a = c.a; } AGG_INLINE void calc(value_type b1, value_type b2, value_type b3, value_type b4, const self_type& c1, const self_type& c2, const self_type& c3, const self_type& c4) { r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a; } template<class ColorT> AGG_INLINE void to_pix(ColorT& c) const { typedef typename ColorT::value_type cv_type; c.r = (cv_type)uround(r); c.g = (cv_type)uround(g); c.b = (cv_type)uround(b); c.a = (cv_type)uround(a); } }; //=================================================recursive_blur_calc_rgb template<class T=double> struct recursive_blur_calc_rgb { typedef T value_type; typedef recursive_blur_calc_rgb<T> self_type; value_type r,g,b; template<class ColorT> AGG_INLINE void from_pix(const ColorT& c) { r = c.r; g = c.g; b = c.b; } AGG_INLINE void calc(value_type b1, value_type b2, value_type b3, value_type b4, const self_type& c1, const self_type& c2, const self_type& c3, const self_type& c4) { r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; } template<class ColorT> AGG_INLINE void to_pix(ColorT& c) const { typedef typename ColorT::value_type cv_type; c.r = (cv_type)uround(r); c.g = (cv_type)uround(g); c.b = (cv_type)uround(b); } }; //================================================recursive_blur_calc_gray template<class T=double> struct recursive_blur_calc_gray { typedef T value_type; typedef recursive_blur_calc_gray<T> self_type; value_type v; template<class ColorT> AGG_INLINE void from_pix(const ColorT& c) { v = c.v; } AGG_INLINE void calc(value_type b1, value_type b2, value_type b3, value_type b4, const self_type& c1, const self_type& c2, const self_type& c3, const self_type& c4) { v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v; } template<class ColorT> AGG_INLINE void to_pix(ColorT& c) const { typedef typename ColorT::value_type cv_type; c.v = (cv_type)uround(v); } }; } #endif ���mapserver-6.4.1/renderers/agg/include/agg_svg_path_tokenizer.h��������������������������������������0000644�0024617�0000144�00000007235�12261257215�024371� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG path tokenizer. // //---------------------------------------------------------------------------- #ifndef AGG_SVG_PATH_TOKENIZER_INCLUDED #define AGG_SVG_PATH_TOKENIZER_INCLUDED #include "agg_svg_exception.h" namespace mapserver { namespace svg { // SVG path tokenizer. // Example: // // agg::svg::path_tokenizer tok; // // tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 "); // while(tok.next()) // { // printf("command='%c' number=%f\n", // tok.last_command(), // tok.last_number()); // } // // The tokenizer does all the routine job of parsing the SVG paths. // It doesn't recognize any graphical primitives, it even doesn't know // anything about pairs of coordinates (X,Y). The purpose of this class // is to tokenize the numeric values and commands. SVG paths can // have single numeric values for Horizontal or Vertical line_to commands // as well as more than two coordinates (4 or 6) for Bezier curves // depending on the semantics of the command. // The behaviour is as follows: // // Each call to next() returns true if there's new command or new numeric // value or false when the path ends. How to interpret the result // depends on the sematics of the command. For example, command "C" // (cubic Bezier curve) implies 6 floating point numbers preceded by this // command. If the command assumes no arguments (like z or Z) the // the last_number() values won't change, that is, last_number() always // returns the last recognized numeric value, so does last_command(). //=============================================================== class path_tokenizer { public: path_tokenizer(); void set_path_str(const char* str); bool next(); double next(char cmd); char last_command() const { return m_last_command; } double last_number() const { return m_last_number; } private: static void init_char_mask(char* mask, const char* char_set); bool contains(const char* mask, unsigned c) const { return (mask[(c >> 3) & (256/8-1)] & (1 << (c & 7))) != 0; } bool is_command(unsigned c) const { return contains(m_commands_mask, c); } bool is_numeric(unsigned c) const { return contains(m_numeric_mask, c); } bool is_separator(unsigned c) const { return contains(m_separators_mask, c); } bool parse_number(); char m_separators_mask[256/8]; char m_commands_mask[256/8]; char m_numeric_mask[256/8]; const char* m_path; double m_last_number; char m_last_command; static const char s_commands[]; static const char s_numeric[]; static const char s_separators[]; }; } //namespace svg } //namespace mapserver #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_dda_line.h������������������������������������������������0000644�0024617�0000144�00000020410�12261257215�022211� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // classes dda_line_interpolator, dda2_line_interpolator // //---------------------------------------------------------------------------- #ifndef AGG_DDA_LINE_INCLUDED #define AGG_DDA_LINE_INCLUDED #include <stdlib.h> #include "agg_basics.h" namespace mapserver { //===================================================dda_line_interpolator template<int FractionShift, int YShift=0> class dda_line_interpolator { public: //-------------------------------------------------------------------- dda_line_interpolator() {} //-------------------------------------------------------------------- dda_line_interpolator(int y1, int y2, unsigned count) : m_y(y1), m_inc(((y2 - y1) << FractionShift) / int(count)), m_dy(0) { } //-------------------------------------------------------------------- void operator ++ () { m_dy += m_inc; } //-------------------------------------------------------------------- void operator -- () { m_dy -= m_inc; } //-------------------------------------------------------------------- void operator += (unsigned n) { m_dy += m_inc * n; } //-------------------------------------------------------------------- void operator -= (unsigned n) { m_dy -= m_inc * n; } //-------------------------------------------------------------------- int y() const { return m_y + (m_dy >> (FractionShift-YShift)); } int dy() const { return m_dy; } private: int m_y; int m_inc; int m_dy; }; //=================================================dda2_line_interpolator class dda2_line_interpolator { public: typedef int save_data_type; enum save_size_e { save_size = 2 }; //-------------------------------------------------------------------- dda2_line_interpolator() {} //-------------------------------------------- Forward-adjusted line dda2_line_interpolator(int y1, int y2, int count) : m_cnt(count <= 0 ? 1 : count), m_lft((y2 - y1) / m_cnt), m_rem((y2 - y1) % m_cnt), m_mod(m_rem), m_y(y1) { if(m_mod <= 0) { m_mod += count; m_rem += count; m_lft--; } m_mod -= count; } //-------------------------------------------- Backward-adjusted line dda2_line_interpolator(int y1, int y2, int count, int) : m_cnt(count <= 0 ? 1 : count), m_lft((y2 - y1) / m_cnt), m_rem((y2 - y1) % m_cnt), m_mod(m_rem), m_y(y1) { if(m_mod <= 0) { m_mod += count; m_rem += count; m_lft--; } } //-------------------------------------------- Backward-adjusted line dda2_line_interpolator(int y, int count) : m_cnt(count <= 0 ? 1 : count), m_lft(y / m_cnt), m_rem(y % m_cnt), m_mod(m_rem), m_y(0) { if(m_mod <= 0) { m_mod += count; m_rem += count; m_lft--; } } //-------------------------------------------------------------------- void save(save_data_type* data) const { data[0] = m_mod; data[1] = m_y; } //-------------------------------------------------------------------- void load(const save_data_type* data) { m_mod = data[0]; m_y = data[1]; } //-------------------------------------------------------------------- void operator++() { m_mod += m_rem; m_y += m_lft; if(m_mod > 0) { m_mod -= m_cnt; m_y++; } } //-------------------------------------------------------------------- void operator--() { if(m_mod <= m_rem) { m_mod += m_cnt; m_y--; } m_mod -= m_rem; m_y -= m_lft; } //-------------------------------------------------------------------- void adjust_forward() { m_mod -= m_cnt; } //-------------------------------------------------------------------- void adjust_backward() { m_mod += m_cnt; } //-------------------------------------------------------------------- int mod() const { return m_mod; } int rem() const { return m_rem; } int lft() const { return m_lft; } //-------------------------------------------------------------------- int y() const { return m_y; } private: int m_cnt; int m_lft; int m_rem; int m_mod; int m_y; }; //---------------------------------------------line_bresenham_interpolator class line_bresenham_interpolator { public: enum subpixel_scale_e { subpixel_shift = 8, subpixel_scale = 1 << subpixel_shift, subpixel_mask = subpixel_scale - 1 }; //-------------------------------------------------------------------- static int line_lr(int v) { return v >> subpixel_shift; } //-------------------------------------------------------------------- line_bresenham_interpolator(int x1, int y1, int x2, int y2) : m_x1_lr(line_lr(x1)), m_y1_lr(line_lr(y1)), m_x2_lr(line_lr(x2)), m_y2_lr(line_lr(y2)), m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)), m_len(m_ver ? abs(m_y2_lr - m_y1_lr) : abs(m_x2_lr - m_x1_lr)), m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)), m_interpolator(m_ver ? x1 : y1, m_ver ? x2 : y2, m_len) { } //-------------------------------------------------------------------- bool is_ver() const { return m_ver; } unsigned len() const { return m_len; } int inc() const { return m_inc; } //-------------------------------------------------------------------- void hstep() { ++m_interpolator; m_x1_lr += m_inc; } //-------------------------------------------------------------------- void vstep() { ++m_interpolator; m_y1_lr += m_inc; } //-------------------------------------------------------------------- int x1() const { return m_x1_lr; } int y1() const { return m_y1_lr; } int x2() const { return line_lr(m_interpolator.y()); } int y2() const { return line_lr(m_interpolator.y()); } int x2_hr() const { return m_interpolator.y(); } int y2_hr() const { return m_interpolator.y(); } private: int m_x1_lr; int m_y1_lr; int m_x2_lr; int m_y2_lr; bool m_ver; unsigned m_len; int m_inc; dda2_line_interpolator m_interpolator; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_scanline_u.h����������������������������������������������0000644�0024617�0000144�00000041253�12261257215�022602� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_U_INCLUDED #define AGG_SCANLINE_U_INCLUDED #include "agg_array.h" namespace mapserver { //=============================================================scanline_u8 // // Unpacked scanline container class // // This class is used to transfer data from a scanline rasterizer // to the rendering buffer. It's organized very simple. The class stores // information of horizontal spans to render it into a pixel-map buffer. // Each span has staring X, length, and an array of bytes that determine the // cover-values for each pixel. // Before using this class you should know the minimal and maximal pixel // coordinates of your scanline. The protocol of using is: // 1. reset(min_x, max_x) // 2. add_cell() / add_span() - accumulate scanline. // When forming one scanline the next X coordinate must be always greater // than the last stored one, i.e. it works only with ordered coordinates. // 3. Call finalize(y) and render the scanline. // 3. Call reset_spans() to prepare for the new scanline. // // 4. Rendering: // // Scanline provides an iterator class that allows you to extract // the spans and the cover values for each pixel. Be aware that clipping // has not been done yet, so you should perform it yourself. // Use scanline_u8::iterator to render spans: //------------------------------------------------------------------------- // // int y = sl.y(); // Y-coordinate of the scanline // // ************************************ // ...Perform vertical clipping here... // ************************************ // // scanline_u8::const_iterator span = sl.begin(); // // unsigned char* row = m_rbuf->row(y); // The the address of the beginning // // of the current row // // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that // // num_spans is always greater than 0. // // do // { // const scanline_u8::cover_type* covers = // span->covers; // The array of the cover values // // int num_pix = span->len; // Number of pixels of the span. // // Always greater than 0, still it's // // better to use "int" instead of // // "unsigned" because it's more // // convenient for clipping // int x = span->x; // // ************************************** // ...Perform horizontal clipping here... // ...you have x, covers, and pix_count.. // ************************************** // // unsigned char* dst = row + x; // Calculate the start address of the row. // // In this case we assume a simple // // grayscale image 1-byte per pixel. // do // { // *dst++ = *covers++; // Hypotetical rendering. // } // while(--num_pix); // // ++span; // } // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe //------------------------------------------------------------------------ // // The question is: why should we accumulate the whole scanline when we // could render just separate spans when they're ready? // That's because using the scanline is generally faster. When is consists // of more than one span the conditions for the processor cash system // are better, because switching between two different areas of memory // (that can be very large) occurs less frequently. //------------------------------------------------------------------------ class scanline_u8 { public: typedef scanline_u8 self_type; typedef int8u cover_type; typedef int16 coord_type; //-------------------------------------------------------------------- struct span { coord_type x; coord_type len; cover_type* covers; }; typedef span* iterator; typedef const span* const_iterator; //-------------------------------------------------------------------- scanline_u8() : m_min_x(0), m_last_x(0x7FFFFFF0), m_cur_span(0) {} //-------------------------------------------------------------------- void reset(int min_x, int max_x) { unsigned max_len = max_x - min_x + 2; if(max_len > m_spans.size()) { m_spans.resize(max_len); m_covers.resize(max_len); } m_last_x = 0x7FFFFFF0; m_min_x = min_x; m_cur_span = &m_spans[0]; } //-------------------------------------------------------------------- void add_cell(int x, unsigned cover) { x -= m_min_x; m_covers[x] = (cover_type)cover; if(x == m_last_x+1) { m_cur_span->len++; } else { m_cur_span++; m_cur_span->x = (coord_type)(x + m_min_x); m_cur_span->len = 1; m_cur_span->covers = &m_covers[x]; } m_last_x = x; } //-------------------------------------------------------------------- void add_cells(int x, unsigned len, const cover_type* covers) { x -= m_min_x; memcpy(&m_covers[x], covers, len * sizeof(cover_type)); if(x == m_last_x+1) { m_cur_span->len += (coord_type)len; } else { m_cur_span++; m_cur_span->x = (coord_type)(x + m_min_x); m_cur_span->len = (coord_type)len; m_cur_span->covers = &m_covers[x]; } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void add_span(int x, unsigned len, unsigned cover) { x -= m_min_x; memset(&m_covers[x], cover, len); if(x == m_last_x+1) { m_cur_span->len += (coord_type)len; } else { m_cur_span++; m_cur_span->x = (coord_type)(x + m_min_x); m_cur_span->len = (coord_type)len; m_cur_span->covers = &m_covers[x]; } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void finalize(int y) { m_y = y; } //-------------------------------------------------------------------- void reset_spans() { m_last_x = 0x7FFFFFF0; m_cur_span = &m_spans[0]; } //-------------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } const_iterator begin() const { return &m_spans[1]; } iterator begin() { return &m_spans[1]; } private: scanline_u8(const self_type&); const self_type& operator = (const self_type&); private: int m_min_x; int m_last_x; int m_y; pod_array<cover_type> m_covers; pod_array<span> m_spans; span* m_cur_span; }; //==========================================================scanline_u8_am // // The scanline container with alpha-masking // //------------------------------------------------------------------------ template<class AlphaMask> class scanline_u8_am : public scanline_u8 { public: typedef scanline_u8 base_type; typedef AlphaMask alpha_mask_type; typedef base_type::cover_type cover_type; typedef base_type::coord_type coord_type; scanline_u8_am() : base_type(), m_alpha_mask(0) {} scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} //-------------------------------------------------------------------- void finalize(int span_y) { base_type::finalize(span_y); if(m_alpha_mask) { typename base_type::iterator span = base_type::begin(); unsigned count = base_type::num_spans(); do { m_alpha_mask->combine_hspan(span->x, base_type::y(), span->covers, span->len); ++span; } while(--count); } } private: const AlphaMask* m_alpha_mask; }; //===========================================================scanline32_u8 class scanline32_u8 { public: typedef scanline32_u8 self_type; typedef int8u cover_type; typedef int32 coord_type; //-------------------------------------------------------------------- struct span { span() {} span(coord_type x_, coord_type len_, cover_type* covers_) : x(x_), len(len_), covers(covers_) {} coord_type x; coord_type len; cover_type* covers; }; typedef pod_bvector<span, 4> span_array_type; //-------------------------------------------------------------------- class const_iterator { public: const_iterator(const span_array_type& spans) : m_spans(spans), m_span_idx(0) {} const span& operator*() const { return m_spans[m_span_idx]; } const span* operator->() const { return &m_spans[m_span_idx]; } void operator ++ () { ++m_span_idx; } private: const span_array_type& m_spans; unsigned m_span_idx; }; //-------------------------------------------------------------------- class iterator { public: iterator(span_array_type& spans) : m_spans(spans), m_span_idx(0) {} span& operator*() { return m_spans[m_span_idx]; } span* operator->() { return &m_spans[m_span_idx]; } void operator ++ () { ++m_span_idx; } private: span_array_type& m_spans; unsigned m_span_idx; }; //-------------------------------------------------------------------- scanline32_u8() : m_min_x(0), m_last_x(0x7FFFFFF0), m_covers() {} //-------------------------------------------------------------------- void reset(int min_x, int max_x) { unsigned max_len = max_x - min_x + 2; if(max_len > m_covers.size()) { m_covers.resize(max_len); } m_last_x = 0x7FFFFFF0; m_min_x = min_x; m_spans.remove_all(); } //-------------------------------------------------------------------- void add_cell(int x, unsigned cover) { x -= m_min_x; m_covers[x] = cover_type(cover); if(x == m_last_x+1) { m_spans.last().len++; } else { m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x])); } m_last_x = x; } //-------------------------------------------------------------------- void add_cells(int x, unsigned len, const cover_type* covers) { x -= m_min_x; memcpy(&m_covers[x], covers, len * sizeof(cover_type)); if(x == m_last_x+1) { m_spans.last().len += coord_type(len); } else { m_spans.add(span(coord_type(x + m_min_x), coord_type(len), &m_covers[x])); } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void add_span(int x, unsigned len, unsigned cover) { x -= m_min_x; memset(&m_covers[x], cover, len); if(x == m_last_x+1) { m_spans.last().len += coord_type(len); } else { m_spans.add(span(coord_type(x + m_min_x), coord_type(len), &m_covers[x])); } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void finalize(int y) { m_y = y; } //-------------------------------------------------------------------- void reset_spans() { m_last_x = 0x7FFFFFF0; m_spans.remove_all(); } //-------------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return m_spans.size(); } const_iterator begin() const { return const_iterator(m_spans); } iterator begin() { return iterator(m_spans); } private: scanline32_u8(const self_type&); const self_type& operator = (const self_type&); private: int m_min_x; int m_last_x; int m_y; pod_array<cover_type> m_covers; span_array_type m_spans; }; //========================================================scanline32_u8_am // // The scanline container with alpha-masking // //------------------------------------------------------------------------ template<class AlphaMask> class scanline32_u8_am : public scanline32_u8 { public: typedef scanline32_u8 base_type; typedef AlphaMask alpha_mask_type; typedef base_type::cover_type cover_type; typedef base_type::coord_type coord_type; scanline32_u8_am() : base_type(), m_alpha_mask(0) {} scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} //-------------------------------------------------------------------- void finalize(int span_y) { base_type::finalize(span_y); if(m_alpha_mask) { typename base_type::iterator span = base_type::begin(); unsigned count = base_type::num_spans(); do { m_alpha_mask->combine_hspan(span->x, base_type::y(), span->covers, span->len); ++span; } while(--count); } } private: const AlphaMask* m_alpha_mask; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_clipper.h��������������������������������������������0000644�0024617�0000144�00000022606�12261257215�023146� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************************* * * * Author : Angus Johnson * * Version : 1.1 * * Date : 4 April 2011 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2011 * * * * License: * * Use, modification & distribution is subject to Boost Software License Ver 1. * * http://www.boost.org/LICENSE_1_0.txt * * * *******************************************************************************/ #ifndef AGG_CONV_CLIPPER_INCLUDED #define AGG_CONV_CLIPPER_INCLUDED #include <cmath> #include "agg_basics.h" #include "agg_array.h" #include "clipper.hpp" namespace mapserver { enum clipper_op_e { clipper_or, clipper_and, clipper_xor, clipper_a_minus_b, clipper_b_minus_a }; enum clipper_PolyFillType {clipper_even_odd, clipper_non_zero, clipper_positive, clipper_negative}; template<class VSA, class VSB> class conv_clipper { enum status { status_move_to, status_line_to, status_stop }; typedef VSA source_a_type; typedef VSB source_b_type; typedef conv_clipper<source_a_type, source_b_type> self_type; private: source_a_type* m_src_a; source_b_type* m_src_b; status m_status; int m_vertex; int m_contour; int m_scaling_factor; clipper_op_e m_operation; pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator; ClipperLib::Polygons m_poly_a; ClipperLib::Polygons m_poly_b; ClipperLib::Polygons m_result; ClipperLib::Clipper m_clipper; clipper_PolyFillType m_subjFillType; clipper_PolyFillType m_clipFillType; int Round(double val) { if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5); } public: conv_clipper(source_a_type &a, source_b_type &b, clipper_op_e op = clipper_or, clipper_PolyFillType subjFillType = clipper_even_odd, clipper_PolyFillType clipFillType = clipper_even_odd, int scaling_factor = 2) : m_src_a(&a), m_src_b(&b), m_status(status_move_to), m_vertex(-1), m_contour(-1), m_operation(op), m_subjFillType(subjFillType), m_clipFillType(clipFillType) { m_scaling_factor = std::max(std::min(scaling_factor, 6),0); m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); } ~conv_clipper() { } void attach1(VSA &source, clipper_PolyFillType subjFillType = clipper_even_odd) { m_src_a = &source; m_subjFillType = subjFillType; } void attach2(VSB &source, clipper_PolyFillType clipFillType = clipper_even_odd) { m_src_b = &source; m_clipFillType = clipFillType; } void operation(clipper_op_e v) { m_operation = v; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); bool next_contour(); bool next_vertex(double* x, double* y); void start_extracting(); void add_vertex_(double &x, double &y); void end_contour(ClipperLib::Polygons &p); template<class VS> void add(VS &src, ClipperLib::Polygons &p){ unsigned cmd; double x; double y; double start_x; double start_y; bool starting_first_line; start_x = 0.0; start_y = 0.0; starting_first_line = true; p.resize(0); cmd = src->vertex( &x , &y ); while(!is_stop(cmd)) { if(is_vertex(cmd)) { if(is_move_to(cmd)) { if(!starting_first_line ) end_contour(p); start_x = x; start_y = y; } add_vertex_( x, y ); starting_first_line = false; } else if(is_end_poly(cmd)) { if(!starting_first_line && is_closed(cmd)) add_vertex_( start_x, start_y ); } cmd = src->vertex( &x, &y ); } end_contour(p); } }; //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_clipper<VSA, VSB>::start_extracting() { m_status = status_move_to; m_contour = -1; m_vertex = -1; } //------------------------------------------------------------------------------ template<class VSA, class VSB> void conv_clipper<VSA, VSB>::rewind(unsigned path_id) { m_src_a->rewind( path_id ); m_src_b->rewind( path_id ); add( m_src_a , m_poly_a ); add( m_src_b , m_poly_b ); m_result.resize(0); ClipperLib::PolyFillType pftSubj, pftClip; switch (m_subjFillType) { case clipper_even_odd: pftSubj = ClipperLib::pftEvenOdd; break; case clipper_non_zero: pftSubj = ClipperLib::pftNonZero; break; case clipper_positive: pftSubj = ClipperLib::pftPositive; break; default: pftSubj = ClipperLib::pftNegative; } switch (m_clipFillType) { case clipper_even_odd: pftClip = ClipperLib::pftEvenOdd; break; case clipper_non_zero: pftClip = ClipperLib::pftNonZero; break; case clipper_positive: pftClip = ClipperLib::pftPositive; break; default: pftClip = ClipperLib::pftNegative; } m_clipper.Clear(); switch( m_operation ) { case clipper_or: { m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.Execute( ClipperLib::ctUnion , m_result , pftSubj, pftClip); break; } case clipper_and: { m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.Execute( ClipperLib::ctIntersection , m_result, pftSubj, pftClip ); break; } case clipper_xor: { m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.Execute( ClipperLib::ctXor , m_result, pftSubj, pftClip ); break; } case clipper_a_minus_b: { m_clipper.AddPolygons( m_poly_a , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_b , ClipperLib::ptClip ); m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); break; } case clipper_b_minus_a: { m_clipper.AddPolygons( m_poly_b , ClipperLib::ptSubject ); m_clipper.AddPolygons( m_poly_a , ClipperLib::ptClip ); m_clipper.Execute( ClipperLib::ctDifference , m_result, pftSubj, pftClip ); break; } } start_extracting(); } //------------------------------------------------------------------------------ template<class VSA, class VSB> void conv_clipper<VSA, VSB>::end_contour( ClipperLib::Polygons &p) { unsigned i, len; if( m_vertex_accumulator.size() < 3 ) return; len = p.size(); p.resize(len+1); p[len].resize(m_vertex_accumulator.size()); for( i = 0 ; i < m_vertex_accumulator.size() ; i++ ) p[len][i] = m_vertex_accumulator[i]; m_vertex_accumulator.remove_all(); } //------------------------------------------------------------------------------ template<class VSA, class VSB> void conv_clipper<VSA, VSB>::add_vertex_(double &x, double &y) { ClipperLib::IntPoint v; v.X = Round(x * m_scaling_factor); v.Y = Round(y * m_scaling_factor); m_vertex_accumulator.add( v ); } //------------------------------------------------------------------------------ template<class VSA, class VSB> bool conv_clipper<VSA, VSB>::next_contour() { m_contour++; if(m_contour >= (int)m_result.size()) return false; m_vertex =-1; return true; } //------------------------------------------------------------------------------ template<class VSA, class VSB> bool conv_clipper<VSA, VSB>::next_vertex(double *x, double *y) { m_vertex++; if(m_vertex >= (int)m_result[m_contour].size()) return false; *x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor; *y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor; return true; } //------------------------------------------------------------------------------ template<class VSA, class VSB> unsigned conv_clipper<VSA, VSB>::vertex(double *x, double *y) { if( m_status == status_move_to ) { if( next_contour() ) { if( next_vertex( x, y ) ) { m_status =status_line_to; return path_cmd_move_to; } else { m_status = status_stop; return path_cmd_end_poly | path_flags_close; } } else return path_cmd_stop; } else { if( next_vertex( x, y ) ) { return path_cmd_line_to; } else { m_status = status_move_to; return path_cmd_end_poly | path_flags_close; } } } //------------------------------------------------------------------------------ } //namespace agg #endif //AGG_CONV_CLIPPER_INCLUDED ��������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_allocator.h������������������������������������������0000644�0024617�0000144�00000003417�12261257215�023463� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_ALLOCATOR_INCLUDED #define AGG_SPAN_ALLOCATOR_INCLUDED #include "agg_array.h" namespace mapserver { //----------------------------------------------------------span_allocator template<class ColorT> class span_allocator { public: typedef ColorT color_type; //-------------------------------------------------------------------- AGG_INLINE color_type* allocate(unsigned span_len) { if(span_len > m_span.size()) { // To reduce the number of reallocs we align the // span_len to 256 color elements. // Well, I just like this number and it looks reasonable. //----------------------- m_span.resize(((span_len + 255) >> 8) << 8); } return &m_span[0]; } AGG_INLINE color_type* span() { return &m_span[0]; } AGG_INLINE unsigned max_span_len() const { return m_span.size(); } private: pod_array<color_type> m_span; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_gamma_lut.h�����������������������������������������������0000644�0024617�0000144�00000006573�12261257215�022436� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_GAMMA_LUT_INCLUDED #define AGG_GAMMA_LUT_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { template<class LoResT=int8u, class HiResT=int8u, unsigned GammaShift=8, unsigned HiResShift=8> class gamma_lut { public: typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type; enum gamma_scale_e { gamma_shift = GammaShift, gamma_size = 1 << gamma_shift, gamma_mask = gamma_size - 1 }; enum hi_res_scale_e { hi_res_shift = HiResShift, hi_res_size = 1 << hi_res_shift, hi_res_mask = hi_res_size - 1 }; ~gamma_lut() { pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size); pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size); } gamma_lut() : m_gamma(1.0), m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)), m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size)) { unsigned i; for(i = 0; i < gamma_size; i++) { m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift)); } for(i = 0; i < hi_res_size; i++) { m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift)); } } gamma_lut(double g) : m_gamma(1.0), m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)), m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size)) { gamma(g); } void gamma(double g) { m_gamma = g; unsigned i; for(i = 0; i < gamma_size; i++) { m_dir_gamma[i] = (HiResT) uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask)); } double inv_g = 1.0 / g; for(i = 0; i < hi_res_size; i++) { m_inv_gamma[i] = (LoResT) uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask)); } } double gamma() const { return m_gamma; } HiResT dir(LoResT v) const { return m_dir_gamma[unsigned(v)]; } LoResT inv(HiResT v) const { return m_inv_gamma[unsigned(v)]; } private: gamma_lut(const self_type&); const self_type& operator = (const self_type&); double m_gamma; HiResT* m_dir_gamma; LoResT* m_inv_gamma; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rasterizer_sl_clip.h��������������������������������������0000644�0024617�0000144�00000031157�12261257215�024363� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED #define AGG_RASTERIZER_SL_CLIP_INCLUDED #include "agg_clip_liang_barsky.h" namespace mapserver { //--------------------------------------------------------poly_max_coord_e enum poly_max_coord_e { poly_max_coord = (1 << 30) - 1 //----poly_max_coord }; //------------------------------------------------------------ras_conv_int struct ras_conv_int { typedef int coord_type; static AGG_INLINE int mul_div(double a, double b, double c) { return iround(a * b / c); } static int xi(int v) { return v; } static int yi(int v) { return v; } static int upscale(double v) { return iround(v * poly_subpixel_scale); } static int downscale(int v) { return v; } }; //--------------------------------------------------------ras_conv_int_sat struct ras_conv_int_sat { typedef int coord_type; static AGG_INLINE int mul_div(double a, double b, double c) { return saturation<poly_max_coord>::iround(a * b / c); } static int xi(int v) { return v; } static int yi(int v) { return v; } static int upscale(double v) { return saturation<poly_max_coord>::iround(v * poly_subpixel_scale); } static int downscale(int v) { return v; } }; //---------------------------------------------------------ras_conv_int_3x struct ras_conv_int_3x { typedef int coord_type; static AGG_INLINE int mul_div(double a, double b, double c) { return iround(a * b / c); } static int xi(int v) { return v * 3; } static int yi(int v) { return v; } static int upscale(double v) { return iround(v * poly_subpixel_scale); } static int downscale(int v) { return v; } }; //-----------------------------------------------------------ras_conv_dbl struct ras_conv_dbl { typedef double coord_type; static AGG_INLINE double mul_div(double a, double b, double c) { return a * b / c; } static int xi(double v) { return iround(v * poly_subpixel_scale); } static int yi(double v) { return iround(v * poly_subpixel_scale); } static double upscale(double v) { return v; } static double downscale(int v) { return v / double(poly_subpixel_scale); } }; //--------------------------------------------------------ras_conv_dbl_3x struct ras_conv_dbl_3x { typedef double coord_type; static AGG_INLINE double mul_div(double a, double b, double c) { return a * b / c; } static int xi(double v) { return iround(v * poly_subpixel_scale * 3); } static int yi(double v) { return iround(v * poly_subpixel_scale); } static double upscale(double v) { return v; } static double downscale(int v) { return v / double(poly_subpixel_scale); } }; //------------------------------------------------------rasterizer_sl_clip template<class Conv> class rasterizer_sl_clip { public: typedef Conv conv_type; typedef typename Conv::coord_type coord_type; typedef rect_base<coord_type> rect_type; //-------------------------------------------------------------------- rasterizer_sl_clip() : m_clip_box(0,0,0,0), m_x1(0), m_y1(0), m_f1(0), m_clipping(false) {} //-------------------------------------------------------------------- void reset_clipping() { m_clipping = false; } //-------------------------------------------------------------------- void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) { m_clip_box = rect_type(x1, y1, x2, y2); m_clip_box.normalize(); m_clipping = true; } //-------------------------------------------------------------------- void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box); } private: //------------------------------------------------------------------------ template<class Rasterizer> AGG_INLINE void line_clip_y(Rasterizer& ras, coord_type x1, coord_type y1, coord_type x2, coord_type y2, unsigned f1, unsigned f2) const { f1 &= 10; f2 &= 10; if((f1 | f2) == 0) { // Fully visible ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); } else { if(f1 == f2) { // Invisible by Y return; } coord_type tx1 = x1; coord_type ty1 = y1; coord_type tx2 = x2; coord_type ty2 = y2; if(f1 & 8) // y1 < clip.y1 { tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); ty1 = m_clip_box.y1; } if(f1 & 2) // y1 > clip.y2 { tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); ty1 = m_clip_box.y2; } if(f2 & 8) // y2 < clip.y1 { tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); ty2 = m_clip_box.y1; } if(f2 & 2) // y2 > clip.y2 { tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); ty2 = m_clip_box.y2; } ras.line(Conv::xi(tx1), Conv::yi(ty1), Conv::xi(tx2), Conv::yi(ty2)); } } public: //-------------------------------------------------------------------- template<class Rasterizer> void line_to(Rasterizer& ras, coord_type x2, coord_type y2) { if(m_clipping) { unsigned f2 = clipping_flags(x2, y2, m_clip_box); if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) { // Invisible by Y m_x1 = x2; m_y1 = y2; m_f1 = f2; return; } coord_type x1 = m_x1; coord_type y1 = m_y1; unsigned f1 = m_f1; coord_type y3, y4; unsigned f3, f4; switch(((f1 & 5) << 1) | (f2 & 5)) { case 0: // Visible by X line_clip_y(ras, x1, y1, x2, y2, f1, f2); break; case 1: // x2 > clip.x2 y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); f3 = clipping_flags_y(y3, m_clip_box); line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3); line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2); break; case 2: // x1 > clip.x2 y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); f3 = clipping_flags_y(y3, m_clip_box); line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2); break; case 3: // x1 > clip.x2 && x2 > clip.x2 line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2); break; case 4: // x2 < clip.x1 y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); f3 = clipping_flags_y(y3, m_clip_box); line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3); line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2); break; case 6: // x1 > clip.x2 && x2 < clip.x1 y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); f3 = clipping_flags_y(y3, m_clip_box); f4 = clipping_flags_y(y4, m_clip_box); line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4); line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2); break; case 8: // x1 < clip.x1 y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); f3 = clipping_flags_y(y3, m_clip_box); line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2); break; case 9: // x1 < clip.x1 && x2 > clip.x2 y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); f3 = clipping_flags_y(y3, m_clip_box); f4 = clipping_flags_y(y4, m_clip_box); line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4); line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2); break; case 12: // x1 < clip.x1 && x2 < clip.x1 line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2); break; } m_f1 = f2; } else { ras.line(Conv::xi(m_x1), Conv::yi(m_y1), Conv::xi(x2), Conv::yi(y2)); } m_x1 = x2; m_y1 = y2; } private: rect_type m_clip_box; coord_type m_x1; coord_type m_y1; unsigned m_f1; bool m_clipping; }; //---------------------------------------------------rasterizer_sl_no_clip class rasterizer_sl_no_clip { public: typedef ras_conv_int conv_type; typedef int coord_type; rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {} void reset_clipping() {} void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {} void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; } template<class Rasterizer> void line_to(Rasterizer& ras, coord_type x2, coord_type y2) { ras.line(m_x1, m_y1, x2, y2); m_x1 = x2; m_y1 = y2; } private: int m_x1, m_y1; }; // -----rasterizer_sl_clip_int // -----rasterizer_sl_clip_int_sat // -----rasterizer_sl_clip_int_3x // -----rasterizer_sl_clip_dbl // -----rasterizer_sl_clip_dbl_3x //------------------------------------------------------------------------ typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int; typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat; typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x; typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl; typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_gpc.h������������������������������������������������0000644�0024617�0000144�00000030707�12261257215�022262� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // General Polygon Clipper based on the GPC library by Alan Murta // Union, Intersection, XOR, A-B, B-A // Contact the author if you intend to use it in commercial applications! // http://www.cs.man.ac.uk/aig/staff/alan/software/ // Alan Murta (email: gpc@cs.man.ac.uk) // //---------------------------------------------------------------------------- #ifndef AGG_CONV_GPC_INCLUDED #define AGG_CONV_GPC_INCLUDED #include <math.h> #include "agg_basics.h" #include "agg_array.h" extern "C" { #include "gpc.h" } namespace mapserver { enum gpc_op_e { gpc_or, gpc_and, gpc_xor, gpc_a_minus_b, gpc_b_minus_a }; //================================================================conv_gpc template<class VSA, class VSB> class conv_gpc { enum status { status_move_to, status_line_to, status_stop }; struct contour_header_type { int num_vertices; int hole_flag; gpc_vertex* vertices; }; typedef pod_bvector<gpc_vertex, 8> vertex_array_type; typedef pod_bvector<contour_header_type, 6> contour_header_array_type; public: typedef VSA source_a_type; typedef VSB source_b_type; typedef conv_gpc<source_a_type, source_b_type> self_type; ~conv_gpc() { free_gpc_data(); } conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) : m_src_a(&a), m_src_b(&b), m_status(status_move_to), m_vertex(-1), m_contour(-1), m_operation(op) { memset(&m_poly_a, 0, sizeof(m_poly_a)); memset(&m_poly_b, 0, sizeof(m_poly_b)); memset(&m_result, 0, sizeof(m_result)); } void attach1(VSA& source) { m_src_a = &source; } void attach2(VSB& source) { m_src_b = &source; } void operation(gpc_op_e v) { m_operation = v; } // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: conv_gpc(const conv_gpc<VSA, VSB>&); const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&); //-------------------------------------------------------------------- void free_polygon(gpc_polygon& p); void free_result(); void free_gpc_data(); void start_contour(); void add_vertex(double x, double y); void end_contour(unsigned orientation); void make_polygon(gpc_polygon& p); void start_extracting(); bool next_contour(); bool next_vertex(double* x, double* y); //-------------------------------------------------------------------- template<class VS> void add(VS& src, gpc_polygon& p) { unsigned cmd; double x, y; double start_x = 0.0; double start_y = 0.0; bool line_to = false; unsigned orientation = 0; m_contour_accumulator.remove_all(); while(!is_stop(cmd = src.vertex(&x, &y))) { if(is_vertex(cmd)) { if(is_move_to(cmd)) { if(line_to) { end_contour(orientation); orientation = 0; } start_contour(); start_x = x; start_y = y; } add_vertex(x, y); line_to = true; } else { if(is_end_poly(cmd)) { orientation = get_orientation(cmd); if(line_to && is_closed(cmd)) { add_vertex(start_x, start_y); } } } } if(line_to) { end_contour(orientation); } make_polygon(p); } private: //-------------------------------------------------------------------- source_a_type* m_src_a; source_b_type* m_src_b; status m_status; int m_vertex; int m_contour; gpc_op_e m_operation; vertex_array_type m_vertex_accumulator; contour_header_array_type m_contour_accumulator; gpc_polygon m_poly_a; gpc_polygon m_poly_b; gpc_polygon m_result; }; //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p) { int i; for(i = 0; i < p.num_contours; i++) { pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex, p.contour[i].num_vertices); } pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours); memset(&p, 0, sizeof(gpc_polygon)); } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::free_result() { if(m_result.contour) { gpc_free_polygon(&m_result); } memset(&m_result, 0, sizeof(m_result)); } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::free_gpc_data() { free_polygon(m_poly_a); free_polygon(m_poly_b); free_result(); } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::start_contour() { contour_header_type h; memset(&h, 0, sizeof(h)); m_contour_accumulator.add(h); m_vertex_accumulator.remove_all(); } //------------------------------------------------------------------------ template<class VSA, class VSB> inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y) { gpc_vertex v; v.x = x; v.y = y; m_vertex_accumulator.add(v); } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::end_contour(unsigned orientation) { if(m_contour_accumulator.size()) { if(m_vertex_accumulator.size() > 2) { contour_header_type& h = m_contour_accumulator[m_contour_accumulator.size() - 1]; h.num_vertices = m_vertex_accumulator.size(); h.hole_flag = 0; // TO DO: Clarify the "holes" //if(is_cw(orientation)) h.hole_flag = 1; h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices); gpc_vertex* d = h.vertices; int i; for(i = 0; i < h.num_vertices; i++) { const gpc_vertex& s = m_vertex_accumulator[i]; d->x = s.x; d->y = s.y; ++d; } } else { m_vertex_accumulator.remove_last(); } } } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p) { free_polygon(p); if(m_contour_accumulator.size()) { p.num_contours = m_contour_accumulator.size(); p.hole = 0; p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours); int i; gpc_vertex_list* pv = p.contour; for(i = 0; i < p.num_contours; i++) { const contour_header_type& h = m_contour_accumulator[i]; pv->num_vertices = h.num_vertices; pv->vertex = h.vertices; ++pv; } } } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::start_extracting() { m_status = status_move_to; m_contour = -1; m_vertex = -1; } //------------------------------------------------------------------------ template<class VSA, class VSB> bool conv_gpc<VSA, VSB>::next_contour() { if(++m_contour < m_result.num_contours) { m_vertex = -1; return true; } return false; } //------------------------------------------------------------------------ template<class VSA, class VSB> inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y) { const gpc_vertex_list& vlist = m_result.contour[m_contour]; if(++m_vertex < vlist.num_vertices) { const gpc_vertex& v = vlist.vertex[m_vertex]; *x = v.x; *y = v.y; return true; } return false; } //------------------------------------------------------------------------ template<class VSA, class VSB> void conv_gpc<VSA, VSB>::rewind(unsigned path_id) { free_result(); m_src_a->rewind(path_id); m_src_b->rewind(path_id); add(*m_src_a, m_poly_a); add(*m_src_b, m_poly_b); switch(m_operation) { case gpc_or: gpc_polygon_clip(GPC_UNION, &m_poly_a, &m_poly_b, &m_result); break; case gpc_and: gpc_polygon_clip(GPC_INT, &m_poly_a, &m_poly_b, &m_result); break; case gpc_xor: gpc_polygon_clip(GPC_XOR, &m_poly_a, &m_poly_b, &m_result); break; case gpc_a_minus_b: gpc_polygon_clip(GPC_DIFF, &m_poly_a, &m_poly_b, &m_result); break; case gpc_b_minus_a: gpc_polygon_clip(GPC_DIFF, &m_poly_b, &m_poly_a, &m_result); break; } start_extracting(); } //------------------------------------------------------------------------ template<class VSA, class VSB> unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y) { if(m_status == status_move_to) { if(next_contour()) { if(next_vertex(x, y)) { m_status = status_line_to; return path_cmd_move_to; } m_status = status_stop; return path_cmd_end_poly | path_flags_close; } } else { if(next_vertex(x, y)) { return path_cmd_line_to; } else { m_status = status_move_to; } return path_cmd_end_poly | path_flags_close; } return path_cmd_stop; } } #endif ���������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_scanline_storage_bin.h������������������������������������0000644�0024617�0000144�00000043472�12261257215�024637� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED #define AGG_SCANLINE_STORAGE_BIN_INCLUDED #include <string.h> #include <stdlib.h> #include <math.h> #include "agg_array.h" namespace mapserver { //-----------------------------------------------scanline_storage_bin class scanline_storage_bin { public: //--------------------------------------------------------------- struct span_data { int32 x; int32 len; }; //--------------------------------------------------------------- struct scanline_data { int y; unsigned num_spans; unsigned start_span; }; //--------------------------------------------------------------- class embedded_scanline { public: //----------------------------------------------------------- class const_iterator { public: const_iterator() : m_storage(0) {} const_iterator(const embedded_scanline& sl) : m_storage(sl.m_storage), m_span_idx(sl.m_scanline.start_span) { m_span = m_storage->span_by_index(m_span_idx); } const span_data& operator*() const { return m_span; } const span_data* operator->() const { return &m_span; } void operator ++ () { ++m_span_idx; m_span = m_storage->span_by_index(m_span_idx); } private: const scanline_storage_bin* m_storage; unsigned m_span_idx; span_data m_span; }; friend class const_iterator; //----------------------------------------------------------- embedded_scanline(const scanline_storage_bin& storage) : m_storage(&storage) { setup(0); } //----------------------------------------------------------- void reset(int, int) {} unsigned num_spans() const { return m_scanline.num_spans; } int y() const { return m_scanline.y; } const_iterator begin() const { return const_iterator(*this); } //----------------------------------------------------------- void setup(unsigned scanline_idx) { m_scanline_idx = scanline_idx; m_scanline = m_storage->scanline_by_index(m_scanline_idx); } private: const scanline_storage_bin* m_storage; scanline_data m_scanline; unsigned m_scanline_idx; }; //--------------------------------------------------------------- scanline_storage_bin() : m_spans(256-2), // Block increment size m_scanlines(), m_min_x( 0x7FFFFFFF), m_min_y( 0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF), m_cur_scanline(0) { m_fake_scanline.y = 0; m_fake_scanline.num_spans = 0; m_fake_scanline.start_span = 0; m_fake_span.x = 0; m_fake_span.len = 0; } // Renderer Interface //--------------------------------------------------------------- void prepare() { m_scanlines.remove_all(); m_spans.remove_all(); m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; m_max_y = -0x7FFFFFFF; m_cur_scanline = 0; } //--------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { scanline_data sl_this; int y = sl.y(); if(y < m_min_y) m_min_y = y; if(y > m_max_y) m_max_y = y; sl_this.y = y; sl_this.num_spans = sl.num_spans(); sl_this.start_span = m_spans.size(); typename Scanline::const_iterator span_iterator = sl.begin(); unsigned num_spans = sl_this.num_spans; for(;;) { span_data sp; sp.x = span_iterator->x; sp.len = (int32)abs((int)(span_iterator->len)); m_spans.add(sp); int x1 = sp.x; int x2 = sp.x + sp.len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; if(--num_spans == 0) break; ++span_iterator; } m_scanlines.add(sl_this); } //--------------------------------------------------------------- // Iterate scanlines interface int min_x() const { return m_min_x; } int min_y() const { return m_min_y; } int max_x() const { return m_max_x; } int max_y() const { return m_max_y; } //--------------------------------------------------------------- bool rewind_scanlines() { m_cur_scanline = 0; return m_scanlines.size() > 0; } //--------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { sl.reset_spans(); for(;;) { if(m_cur_scanline >= m_scanlines.size()) return false; const scanline_data& sl_this = m_scanlines[m_cur_scanline]; unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; do { const span_data& sp = m_spans[span_idx++]; sl.add_span(sp.x, sp.len, cover_full); } while(--num_spans); ++m_cur_scanline; if(sl.num_spans()) { sl.finalize(sl_this.y); break; } } return true; } //--------------------------------------------------------------- // Specialization for embedded_scanline bool sweep_scanline(embedded_scanline& sl) { do { if(m_cur_scanline >= m_scanlines.size()) return false; sl.setup(m_cur_scanline); ++m_cur_scanline; } while(sl.num_spans() == 0); return true; } //--------------------------------------------------------------- unsigned byte_size() const { unsigned i; unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y for(i = 0; i < m_scanlines.size(); ++i) { size += sizeof(int32) * 2 + // Y, num_spans unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len } return size; } //--------------------------------------------------------------- static void write_int32(int8u* dst, int32 val) { dst[0] = ((const int8u*)&val)[0]; dst[1] = ((const int8u*)&val)[1]; dst[2] = ((const int8u*)&val)[2]; dst[3] = ((const int8u*)&val)[3]; } //--------------------------------------------------------------- void serialize(int8u* data) const { unsigned i; write_int32(data, min_x()); // min_x data += sizeof(int32); write_int32(data, min_y()); // min_y data += sizeof(int32); write_int32(data, max_x()); // max_x data += sizeof(int32); write_int32(data, max_y()); // max_y data += sizeof(int32); for(i = 0; i < m_scanlines.size(); ++i) { const scanline_data& sl_this = m_scanlines[i]; write_int32(data, sl_this.y); // Y data += sizeof(int32); write_int32(data, sl_this.num_spans); // num_spans data += sizeof(int32); unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; do { const span_data& sp = m_spans[span_idx++]; write_int32(data, sp.x); // X data += sizeof(int32); write_int32(data, sp.len); // len data += sizeof(int32); } while(--num_spans); } } //--------------------------------------------------------------- const scanline_data& scanline_by_index(unsigned i) const { return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; } //--------------------------------------------------------------- const span_data& span_by_index(unsigned i) const { return (i < m_spans.size()) ? m_spans[i] : m_fake_span; } private: pod_bvector<span_data, 10> m_spans; pod_bvector<scanline_data, 8> m_scanlines; span_data m_fake_span; scanline_data m_fake_scanline; int m_min_x; int m_min_y; int m_max_x; int m_max_y; unsigned m_cur_scanline; }; //---------------------------------------serialized_scanlines_adaptor_bin class serialized_scanlines_adaptor_bin { public: typedef bool cover_type; //-------------------------------------------------------------------- class embedded_scanline { public: //---------------------------------------------------------------- class const_iterator { public: struct span { int32 x; int32 len; }; const_iterator() : m_ptr(0) {} const_iterator(const embedded_scanline& sl) : m_ptr(sl.m_ptr), m_dx(sl.m_dx) { m_span.x = read_int32() + m_dx; m_span.len = read_int32(); } const span& operator*() const { return m_span; } const span* operator->() const { return &m_span; } void operator ++ () { m_span.x = read_int32() + m_dx; m_span.len = read_int32(); } private: int read_int32() { int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } const int8u* m_ptr; span m_span; int m_dx; }; friend class const_iterator; //---------------------------------------------------------------- embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} //---------------------------------------------------------------- void reset(int, int) {} unsigned num_spans() const { return m_num_spans; } int y() const { return m_y; } const_iterator begin() const { return const_iterator(*this); } private: //---------------------------------------------------------------- int read_int32() { int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } public: //---------------------------------------------------------------- void init(const int8u* ptr, int dx, int dy) { m_ptr = ptr; m_y = read_int32() + dy; m_num_spans = unsigned(read_int32()); m_dx = dx; } private: const int8u* m_ptr; int m_y; unsigned m_num_spans; int m_dx; }; public: //-------------------------------------------------------------------- serialized_scanlines_adaptor_bin() : m_data(0), m_end(0), m_ptr(0), m_dx(0), m_dy(0), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF) {} //-------------------------------------------------------------------- serialized_scanlines_adaptor_bin(const int8u* data, unsigned size, double dx, double dy) : m_data(data), m_end(data + size), m_ptr(data), m_dx(iround(dx)), m_dy(iround(dy)), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), m_max_y(-0x7FFFFFFF) {} //-------------------------------------------------------------------- void init(const int8u* data, unsigned size, double dx, double dy) { m_data = data; m_end = data + size; m_ptr = data; m_dx = iround(dx); m_dy = iround(dy); m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; m_max_y = -0x7FFFFFFF; } private: //-------------------------------------------------------------------- int read_int32() { int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; ((int8u*)&val)[2] = *m_ptr++; ((int8u*)&val)[3] = *m_ptr++; return val; } public: // Iterate scanlines interface //-------------------------------------------------------------------- bool rewind_scanlines() { m_ptr = m_data; if(m_ptr < m_end) { m_min_x = read_int32() + m_dx; m_min_y = read_int32() + m_dy; m_max_x = read_int32() + m_dx; m_max_y = read_int32() + m_dy; } return m_ptr < m_end; } //-------------------------------------------------------------------- int min_x() const { return m_min_x; } int min_y() const { return m_min_y; } int max_x() const { return m_max_x; } int max_y() const { return m_max_y; } //-------------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { sl.reset_spans(); for(;;) { if(m_ptr >= m_end) return false; int y = read_int32() + m_dy; unsigned num_spans = read_int32(); do { int x = read_int32() + m_dx; int len = read_int32(); if(len < 0) len = -len; sl.add_span(x, unsigned(len), cover_full); } while(--num_spans); if(sl.num_spans()) { sl.finalize(y); break; } } return true; } //-------------------------------------------------------------------- // Specialization for embedded_scanline bool sweep_scanline(embedded_scanline& sl) { do { if(m_ptr >= m_end) return false; sl.init(m_ptr, m_dx, m_dy); // Jump to the next scanline //-------------------------- read_int32(); // Y int num_spans = read_int32(); // num_spans m_ptr += num_spans * sizeof(int32) * 2; } while(sl.num_spans() == 0); return true; } private: const int8u* m_data; const int8u* m_end; const int8u* m_ptr; int m_dx; int m_dy; int m_min_x; int m_min_y; int m_max_x; int m_max_y; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_path_length.h���������������������������������������������0000644�0024617�0000144�00000003566�12261257215�022764� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_PATH_LENGTH_INCLUDED #define AGG_PATH_LENGTH_INCLUDED #include "agg_math.h" namespace mapserver { template<class VertexSource> double path_length(VertexSource& vs, unsigned path_id = 0) { double len = 0.0; double start_x = 0.0; double start_y = 0.0; double x1 = 0.0; double y1 = 0.0; double x2 = 0.0; double y2 = 0.0; bool first = true; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x2, &y2))) { if(is_vertex(cmd)) { if(first || is_move_to(cmd)) { start_x = x2; start_y = y2; } else { len += calc_distance(x1, y1, x2, y2); } x1 = x2; y1 = y2; first = false; } else { if(is_close(cmd) && !first) { len += calc_distance(x1, y1, start_x, start_y); } } } return len; } } #endif ������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_ellipse.h�������������������������������������������������0000644�0024617�0000144�00000007106�12261257215�022116� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class ellipse // //---------------------------------------------------------------------------- #ifndef AGG_ELLIPSE_INCLUDED #define AGG_ELLIPSE_INCLUDED #include "agg_basics.h" #include <math.h> namespace mapserver { //----------------------------------------------------------------ellipse class ellipse { public: ellipse() : m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0), m_num(4), m_step(0), m_cw(false) {} ellipse(double x, double y, double rx, double ry, unsigned num_steps=0, bool cw=false) : m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0), m_num(num_steps), m_step(0), m_cw(cw) { if(m_num == 0) calc_num_steps(); } void init(double x, double y, double rx, double ry, unsigned num_steps=0, bool cw=false); void approximation_scale(double scale); void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: void calc_num_steps(); double m_x; double m_y; double m_rx; double m_ry; double m_scale; unsigned m_num; unsigned m_step; bool m_cw; }; //------------------------------------------------------------------------ inline void ellipse::init(double x, double y, double rx, double ry, unsigned num_steps, bool cw) { m_x = x; m_y = y; m_rx = rx; m_ry = ry; m_num = num_steps; m_step = 0; m_cw = cw; if(m_num == 0) calc_num_steps(); } //------------------------------------------------------------------------ inline void ellipse::approximation_scale(double scale) { m_scale = scale; calc_num_steps(); } //------------------------------------------------------------------------ inline void ellipse::calc_num_steps() { double ra = (fabs(m_rx) + fabs(m_ry)) / 2; double da = acos(ra / (ra + 0.125 / m_scale)) * 2; m_num = uround(2*pi / da); } //------------------------------------------------------------------------ inline void ellipse::rewind(unsigned) { m_step = 0; } //------------------------------------------------------------------------ inline unsigned ellipse::vertex(double* x, double* y) { if(m_step == m_num) { ++m_step; return path_cmd_end_poly | path_flags_close | path_flags_ccw; } if(m_step > m_num) return path_cmd_stop; double angle = double(m_step) / double(m_num) * 2.0 * pi; if(m_cw) angle = 2.0 * pi - angle; *x = m_x + cos(angle) * m_rx; *y = m_y + sin(angle) * m_ry; m_step++; return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to); } } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_color_rgba.h����������������������������������������������0000644�0024617�0000144�00000062536�12261257215�022602� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_COLOR_RGBA_INCLUDED #define AGG_COLOR_RGBA_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { // Supported byte orders for RGB and RGBA pixel formats //======================================================================= struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra //====================================================================rgba struct rgba { typedef double value_type; double r; double g; double b; double a; //-------------------------------------------------------------------- rgba() {} //-------------------------------------------------------------------- rgba(double r_, double g_, double b_, double a_=1.0) : r(r_), g(g_), b(b_), a(a_) {} //-------------------------------------------------------------------- rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} //-------------------------------------------------------------------- void clear() { r = g = b = a = 0; } //-------------------------------------------------------------------- const rgba& transparent() { a = 0.0; return *this; } //-------------------------------------------------------------------- const rgba& opacity(double a_) { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; a = a_; return *this; } //-------------------------------------------------------------------- double opacity() const { return a; } //-------------------------------------------------------------------- const rgba& premultiply() { r *= a; g *= a; b *= a; return *this; } //-------------------------------------------------------------------- const rgba& premultiply(double a_) { if(a <= 0.0 || a_ <= 0.0) { r = g = b = a = 0.0; return *this; } a_ /= a; r *= a_; g *= a_; b *= a_; a = a_; return *this; } //-------------------------------------------------------------------- const rgba& demultiply() { if(a == 0) { r = g = b = 0; return *this; } double a_ = 1.0 / a; r *= a_; g *= a_; b *= a_; return *this; } //-------------------------------------------------------------------- rgba gradient(rgba c, double k) const { rgba ret; ret.r = r + (c.r - r) * k; ret.g = g + (c.g - g) * k; ret.b = b + (c.b - b) * k; ret.a = a + (c.a - a) * k; return ret; } //-------------------------------------------------------------------- static rgba no_color() { return rgba(0,0,0,0); } //-------------------------------------------------------------------- static rgba from_wavelength(double wl, double gamma = 1.0); //-------------------------------------------------------------------- explicit rgba(double wavelen, double gamma=1.0) { *this = from_wavelength(wavelen, gamma); } }; //----------------------------------------------------------------rgba_pre inline rgba rgba_pre(double r, double g, double b, double a=1.0) { return rgba(r, g, b, a).premultiply(); } inline rgba rgba_pre(const rgba& c) { return rgba(c).premultiply(); } inline rgba rgba_pre(const rgba& c, double a) { return rgba(c, a).premultiply(); } //------------------------------------------------------------------------ inline rgba rgba::from_wavelength(double wl, double gamma) { rgba t(0.0, 0.0, 0.0); if(wl >= 380.0 && wl <= 440.0) { t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); t.b = 1.0; } else if(wl >= 440.0 && wl <= 490.0) { t.g = (wl - 440.0) / (490.0 - 440.0); t.b = 1.0; } else if(wl >= 490.0 && wl <= 510.0) { t.g = 1.0; t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); } else if(wl >= 510.0 && wl <= 580.0) { t.r = (wl - 510.0) / (580.0 - 510.0); t.g = 1.0; } else if(wl >= 580.0 && wl <= 645.0) { t.r = 1.0; t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); } else if(wl >= 645.0 && wl <= 780.0) { t.r = 1.0; } double s = 1.0; if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); t.r = pow(t.r * s, gamma); t.g = pow(t.g * s, gamma); t.b = pow(t.b * s, gamma); return t; } //===================================================================rgba8 struct rgba8 { typedef int8u value_type; typedef int32u calc_type; typedef int32 long_type; enum base_scale_e { base_shift = 8, base_scale = 1 << base_shift, base_mask = base_scale - 1 }; typedef rgba8 self_type; value_type r; value_type g; value_type b; value_type a; //-------------------------------------------------------------------- rgba8() {} //-------------------------------------------------------------------- rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : r(value_type(r_)), g(value_type(g_)), b(value_type(b_)), a(value_type(a_)) {} //-------------------------------------------------------------------- rgba8(const rgba& c, double a_) : r((value_type)uround(c.r * double(base_mask))), g((value_type)uround(c.g * double(base_mask))), b((value_type)uround(c.b * double(base_mask))), a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- rgba8(const self_type& c, unsigned a_) : r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} //-------------------------------------------------------------------- rgba8(const rgba& c) : r((value_type)uround(c.r * double(base_mask))), g((value_type)uround(c.g * double(base_mask))), b((value_type)uround(c.b * double(base_mask))), a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- void clear() { r = g = b = a = 0; } //-------------------------------------------------------------------- const self_type& transparent() { a = 0; return *this; } //-------------------------------------------------------------------- const self_type& opacity(double a_) { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; a = (value_type)uround(a_ * double(base_mask)); return *this; } //-------------------------------------------------------------------- double opacity() const { return double(a) / double(base_mask); } //-------------------------------------------------------------------- AGG_INLINE const self_type& premultiply() { if(a == base_mask) return *this; if(a == 0) { r = g = b = 0; return *this; } r = value_type((calc_type(r) * a) >> base_shift); g = value_type((calc_type(g) * a) >> base_shift); b = value_type((calc_type(b) * a) >> base_shift); return *this; } //-------------------------------------------------------------------- AGG_INLINE const self_type& premultiply(unsigned a_) { if(a == base_mask && a_ >= base_mask) return *this; if(a == 0 || a_ == 0) { r = g = b = a = 0; return *this; } calc_type r_ = (calc_type(r) * a_) / a; calc_type g_ = (calc_type(g) * a_) / a; calc_type b_ = (calc_type(b) * a_) / a; r = value_type((r_ > a_) ? a_ : r_); g = value_type((g_ > a_) ? a_ : g_); b = value_type((b_ > a_) ? a_ : b_); a = value_type(a_); return *this; } //-------------------------------------------------------------------- AGG_INLINE const self_type& demultiply() { if(a == base_mask) return *this; if(a == 0) { r = g = b = 0; return *this; } calc_type r_ = (calc_type(r) * base_mask) / a; calc_type g_ = (calc_type(g) * base_mask) / a; calc_type b_ = (calc_type(b) * base_mask) / a; r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); return *this; } //-------------------------------------------------------------------- AGG_INLINE self_type gradient(const self_type& c, double k) const { self_type ret; calc_type ik = uround(k * base_scale); ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); return ret; } //-------------------------------------------------------------------- AGG_INLINE void add(const self_type& c, unsigned cover) { calc_type cr, cg, cb, ca; if(cover == cover_mask) { if(c.a == base_mask) { *this = c; } else { cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } else { cr = r + ((c.r * cover + cover_mask/2) >> cover_shift); cg = g + ((c.g * cover + cover_mask/2) >> cover_shift); cb = b + ((c.b * cover + cover_mask/2) >> cover_shift); ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } //-------------------------------------------------------------------- template<class GammaLUT> AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) { r = gamma.dir(r); g = gamma.dir(g); b = gamma.dir(b); } //-------------------------------------------------------------------- template<class GammaLUT> AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) { r = gamma.inv(r); g = gamma.inv(g); b = gamma.inv(b); } //-------------------------------------------------------------------- static self_type no_color() { return self_type(0,0,0,0); } //-------------------------------------------------------------------- static self_type from_wavelength(double wl, double gamma = 1.0) { return self_type(rgba::from_wavelength(wl, gamma)); } }; //-------------------------------------------------------------rgba8_pre inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a = rgba8::base_mask) { return rgba8(r,g,b,a).premultiply(); } inline rgba8 rgba8_pre(const rgba8& c) { return rgba8(c).premultiply(); } inline rgba8 rgba8_pre(const rgba8& c, unsigned a) { return rgba8(c,a).premultiply(); } inline rgba8 rgba8_pre(const rgba& c) { return rgba8(c).premultiply(); } inline rgba8 rgba8_pre(const rgba& c, double a) { return rgba8(c,a).premultiply(); } //-------------------------------------------------------------rgb8_packed inline rgba8 rgb8_packed(unsigned v) { return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); } //-------------------------------------------------------------bgr8_packed inline rgba8 bgr8_packed(unsigned v) { return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); } //------------------------------------------------------------argb8_packed inline rgba8 argb8_packed(unsigned v) { return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); } //---------------------------------------------------------rgba8_gamma_dir template<class GammaLUT> rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) { return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); } //---------------------------------------------------------rgba8_gamma_inv template<class GammaLUT> rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) { return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); } //==================================================================rgba16 struct rgba16 { typedef int16u value_type; typedef int32u calc_type; typedef int64 long_type; enum base_scale_e { base_shift = 16, base_scale = 1 << base_shift, base_mask = base_scale - 1 }; typedef rgba16 self_type; value_type r; value_type g; value_type b; value_type a; //-------------------------------------------------------------------- rgba16() {} //-------------------------------------------------------------------- rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : r(value_type(r_)), g(value_type(g_)), b(value_type(b_)), a(value_type(a_)) {} //-------------------------------------------------------------------- rgba16(const self_type& c, unsigned a_) : r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} //-------------------------------------------------------------------- rgba16(const rgba& c) : r((value_type)uround(c.r * double(base_mask))), g((value_type)uround(c.g * double(base_mask))), b((value_type)uround(c.b * double(base_mask))), a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- rgba16(const rgba& c, double a_) : r((value_type)uround(c.r * double(base_mask))), g((value_type)uround(c.g * double(base_mask))), b((value_type)uround(c.b * double(base_mask))), a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- rgba16(const rgba8& c) : r(value_type((value_type(c.r) << 8) | c.r)), g(value_type((value_type(c.g) << 8) | c.g)), b(value_type((value_type(c.b) << 8) | c.b)), a(value_type((value_type(c.a) << 8) | c.a)) {} //-------------------------------------------------------------------- rgba16(const rgba8& c, unsigned a_) : r(value_type((value_type(c.r) << 8) | c.r)), g(value_type((value_type(c.g) << 8) | c.g)), b(value_type((value_type(c.b) << 8) | c.b)), a(value_type(( a_ << 8) | c.a)) {} //-------------------------------------------------------------------- void clear() { r = g = b = a = 0; } //-------------------------------------------------------------------- const self_type& transparent() { a = 0; return *this; } //-------------------------------------------------------------------- AGG_INLINE const self_type& opacity(double a_) { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; a = (value_type)uround(a_ * double(base_mask)); return *this; } //-------------------------------------------------------------------- double opacity() const { return double(a) / double(base_mask); } //-------------------------------------------------------------------- AGG_INLINE const self_type& premultiply() { if(a == base_mask) return *this; if(a == 0) { r = g = b = 0; return *this; } r = value_type((calc_type(r) * a) >> base_shift); g = value_type((calc_type(g) * a) >> base_shift); b = value_type((calc_type(b) * a) >> base_shift); return *this; } //-------------------------------------------------------------------- AGG_INLINE const self_type& premultiply(unsigned a_) { if(a == base_mask && a_ >= base_mask) return *this; if(a == 0 || a_ == 0) { r = g = b = a = 0; return *this; } calc_type r_ = (calc_type(r) * a_) / a; calc_type g_ = (calc_type(g) * a_) / a; calc_type b_ = (calc_type(b) * a_) / a; r = value_type((r_ > a_) ? a_ : r_); g = value_type((g_ > a_) ? a_ : g_); b = value_type((b_ > a_) ? a_ : b_); a = value_type(a_); return *this; } //-------------------------------------------------------------------- AGG_INLINE const self_type& demultiply() { if(a == base_mask) return *this; if(a == 0) { r = g = b = 0; return *this; } calc_type r_ = (calc_type(r) * base_mask) / a; calc_type g_ = (calc_type(g) * base_mask) / a; calc_type b_ = (calc_type(b) * base_mask) / a; r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); return *this; } //-------------------------------------------------------------------- AGG_INLINE self_type gradient(const self_type& c, double k) const { self_type ret; calc_type ik = uround(k * base_scale); ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); return ret; } //-------------------------------------------------------------------- AGG_INLINE void add(const self_type& c, unsigned cover) { calc_type cr, cg, cb, ca; if(cover == cover_mask) { if(c.a == base_mask) { *this = c; } else { cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } else { cr = r + ((c.r * cover + cover_mask) >> cover_shift); cg = g + ((c.g * cover + cover_mask) >> cover_shift); cb = b + ((c.b * cover + cover_mask) >> cover_shift); ca = a + ((c.a * cover + cover_mask) >> cover_shift); r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } //-------------------------------------------------------------------- template<class GammaLUT> AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) { r = gamma.dir(r); g = gamma.dir(g); b = gamma.dir(b); } //-------------------------------------------------------------------- template<class GammaLUT> AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) { r = gamma.inv(r); g = gamma.inv(g); b = gamma.inv(b); } //-------------------------------------------------------------------- static self_type no_color() { return self_type(0,0,0,0); } //-------------------------------------------------------------------- static self_type from_wavelength(double wl, double gamma = 1.0) { return self_type(rgba::from_wavelength(wl, gamma)); } }; //--------------------------------------------------------------rgba16_pre inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b, unsigned a = rgba16::base_mask) { return rgba16(r,g,b,a).premultiply(); } inline rgba16 rgba16_pre(const rgba16& c, unsigned a) { return rgba16(c,a).premultiply(); } inline rgba16 rgba16_pre(const rgba& c) { return rgba16(c).premultiply(); } inline rgba16 rgba16_pre(const rgba& c, double a) { return rgba16(c,a).premultiply(); } inline rgba16 rgba16_pre(const rgba8& c) { return rgba16(c).premultiply(); } inline rgba16 rgba16_pre(const rgba8& c, unsigned a) { return rgba16(c,a).premultiply(); } //------------------------------------------------------rgba16_gamma_dir template<class GammaLUT> rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) { return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); } //------------------------------------------------------rgba16_gamma_inv template<class GammaLUT> rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) { return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); } } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_gradient_lut.h��������������������������������������������0000644�0024617�0000144�00000016667�12261257215�023156� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_GRADIENT_LUT_INCLUDED #define AGG_GRADIENT_LUT_INCLUDED #include "agg_array.h" #include "agg_dda_line.h" #include "agg_color_rgba.h" #include "agg_color_gray.h" namespace mapserver { //======================================================color_interpolator template<class ColorT> struct color_interpolator { public: typedef ColorT color_type; color_interpolator(const color_type& c1, const color_type& c2, unsigned len) : m_c1(c1), m_c2(c2), m_len(len), m_count(0) {} void operator ++ () { ++m_count; } color_type color() const { return m_c1.gradient(m_c2, double(m_count) / m_len); } private: color_type m_c1; color_type m_c2; unsigned m_len; unsigned m_count; }; //======================================================================== // Fast specialization for rgba8 template<> struct color_interpolator<rgba8> { public: typedef rgba8 color_type; color_interpolator(const color_type& c1, const color_type& c2, unsigned len) : r(c1.r, c2.r, len), g(c1.g, c2.g, len), b(c1.b, c2.b, len), a(c1.a, c2.a, len) {} void operator ++ () { ++r; ++g; ++b; ++a; } color_type color() const { return color_type(r.y(), g.y(), b.y(), a.y()); } private: mapserver::dda_line_interpolator<14> r, g, b, a; }; //======================================================================== // Fast specialization for gray8 template<> struct color_interpolator<gray8> { public: typedef gray8 color_type; color_interpolator(const color_type& c1, const color_type& c2, unsigned len) : v(c1.v, c2.v, len), a(c1.a, c2.a, len) {} void operator ++ () { ++v; ++a; } color_type color() const { return color_type(v.y(), a.y()); } private: mapserver::dda_line_interpolator<14> v,a; }; //============================================================gradient_lut template<class ColorInterpolator, unsigned ColorLutSize=256> class gradient_lut { public: typedef ColorInterpolator interpolator_type; typedef typename interpolator_type::color_type color_type; enum { color_lut_size = ColorLutSize }; //-------------------------------------------------------------------- gradient_lut() : m_color_lut(color_lut_size) {} // Build Gradient Lut // First, call remove_all(), then add_color() at least twice, // then build_lut(). Argument "offset" in add_color must be // in range [0...1] and defines a color stop as it is described // in SVG specification, section Gradients and Patterns. // The simplest linear gradient is: // gradient_lut.add_color(0.0, start_color); // gradient_lut.add_color(1.0, end_color); //-------------------------------------------------------------------- void remove_all(); void add_color(double offset, const color_type& color); void build_lut(); // Size-index Interface. This class can be used directly as the // ColorF in span_gradient. All it needs is two access methods // size() and operator []. //-------------------------------------------------------------------- static unsigned size() { return color_lut_size; } const color_type& operator [] (unsigned i) const { return m_color_lut[i]; } private: //-------------------------------------------------------------------- struct color_point { double offset; color_type color; color_point() {} color_point(double off, const color_type& c) : offset(off), color(c) { if(offset < 0.0) offset = 0.0; if(offset > 1.0) offset = 1.0; } }; typedef mapserver::pod_bvector<color_point, 4> color_profile_type; typedef mapserver::pod_array<color_type> color_lut_type; static bool offset_less(const color_point& a, const color_point& b) { return a.offset < b.offset; } static bool offset_equal(const color_point& a, const color_point& b) { return a.offset == b.offset; } //-------------------------------------------------------------------- color_profile_type m_color_profile; color_lut_type m_color_lut; }; //------------------------------------------------------------------------ template<class T, unsigned S> void gradient_lut<T,S>::remove_all() { m_color_profile.remove_all(); } //------------------------------------------------------------------------ template<class T, unsigned S> void gradient_lut<T,S>::add_color(double offset, const color_type& color) { m_color_profile.add(color_point(offset, color)); } //------------------------------------------------------------------------ template<class T, unsigned S> void gradient_lut<T,S>::build_lut() { quick_sort(m_color_profile, offset_less); m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal)); if(m_color_profile.size() >= 2) { unsigned i; unsigned start = uround(m_color_profile[0].offset * color_lut_size); unsigned end; color_type c = m_color_profile[0].color; for(i = 0; i < start; i++) { m_color_lut[i] = c; } for(i = 1; i < m_color_profile.size(); i++) { end = uround(m_color_profile[i].offset * color_lut_size); interpolator_type ci(m_color_profile[i-1].color, m_color_profile[i ].color, end - start + 1); while(start < end) { m_color_lut[start] = ci.color(); ++ci; ++start; } } c = m_color_profile.last().color; for(; end < m_color_lut.size(); end++) { m_color_lut[end] = c; } } } } #endif �������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_math_stroke.h���������������������������������������������0000644�0024617�0000144�00000044177�12261257215�023012� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Stroke math // //---------------------------------------------------------------------------- #ifndef AGG_STROKE_MATH_INCLUDED #define AGG_STROKE_MATH_INCLUDED #include "agg_math.h" #include "agg_vertex_sequence.h" namespace mapserver { //-------------------------------------------------------------line_cap_e enum line_cap_e { butt_cap, square_cap, round_cap }; //------------------------------------------------------------line_join_e enum line_join_e { miter_join = 0, miter_join_revert = 1, round_join = 2, bevel_join = 3, miter_join_round = 4 }; //-----------------------------------------------------------inner_join_e enum inner_join_e { inner_bevel, inner_miter, inner_jag, inner_round }; //------------------------------------------------------------math_stroke template<class VertexConsumer> class math_stroke { public: typedef typename VertexConsumer::value_type coord_type; math_stroke(); void line_cap(line_cap_e lc) { m_line_cap = lc; } void line_join(line_join_e lj) { m_line_join = lj; } void inner_join(inner_join_e ij) { m_inner_join = ij; } line_cap_e line_cap() const { return m_line_cap; } line_join_e line_join() const { return m_line_join; } inner_join_e inner_join() const { return m_inner_join; } void width(double w); void miter_limit(double ml) { m_miter_limit = ml; } void miter_limit_theta(double t); void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } void approximation_scale(double as) { m_approx_scale = as; } double width() const { return m_width * 2.0; } double miter_limit() const { return m_miter_limit; } double inner_miter_limit() const { return m_inner_miter_limit; } double approximation_scale() const { return m_approx_scale; } void calc_cap(VertexConsumer& vc, const vertex_dist& v0, const vertex_dist& v1, double len); void calc_join(VertexConsumer& vc, const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, double len1, double len2); private: AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y) { vc.add(coord_type(x, y)); } void calc_arc(VertexConsumer& vc, double x, double y, double dx1, double dy1, double dx2, double dy2); void calc_miter(VertexConsumer& vc, const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, double dx1, double dy1, double dx2, double dy2, line_join_e lj, double mlimit, double dbevel); double m_width; double m_width_abs; double m_width_eps; int m_width_sign; double m_miter_limit; double m_inner_miter_limit; double m_approx_scale; line_cap_e m_line_cap; line_join_e m_line_join; inner_join_e m_inner_join; }; //----------------------------------------------------------------------- template<class VC> math_stroke<VC>::math_stroke() : m_width(0.5), m_width_abs(0.5), m_width_eps(0.5/1024.0), m_width_sign(1), m_miter_limit(4.0), m_inner_miter_limit(1.01), m_approx_scale(1.0), m_line_cap(butt_cap), m_line_join(miter_join), m_inner_join(inner_miter) { } //----------------------------------------------------------------------- template<class VC> void math_stroke<VC>::width(double w) { m_width = w * 0.5; if(m_width < 0) { m_width_abs = -m_width; m_width_sign = -1; } else { m_width_abs = m_width; m_width_sign = 1; } m_width_eps = m_width / 1024.0; } //----------------------------------------------------------------------- template<class VC> void math_stroke<VC>::miter_limit_theta(double t) { m_miter_limit = 1.0 / sin(t * 0.5) ; } //----------------------------------------------------------------------- template<class VC> void math_stroke<VC>::calc_arc(VC& vc, double x, double y, double dx1, double dy1, double dx2, double dy2) { double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign); double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign); double da = a1 - a2; int i, n; da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; add_vertex(vc, x + dx1, y + dy1); if(m_width_sign > 0) { if(a1 > a2) a2 += 2 * pi; n = int((a2 - a1) / da); da = (a2 - a1) / (n + 1); a1 += da; for(i = 0; i < n; i++) { add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); a1 += da; } } else { if(a1 < a2) a2 -= 2 * pi; n = int((a1 - a2) / da); da = (a1 - a2) / (n + 1); a1 -= da; for(i = 0; i < n; i++) { add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); a1 -= da; } } add_vertex(vc, x + dx2, y + dy2); } //----------------------------------------------------------------------- template<class VC> void math_stroke<VC>::calc_miter(VC& vc, const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, double dx1, double dy1, double dx2, double dy2, line_join_e lj, double mlimit, double dbevel) { double xi = v1.x; double yi = v1.y; double di = 1; double lim = m_width_abs * mlimit; bool miter_limit_exceeded = true; // Assume the worst bool intersection_failed = true; // Assume the worst if(calc_intersection(v0.x + dx1, v0.y - dy1, v1.x + dx1, v1.y - dy1, v1.x + dx2, v1.y - dy2, v2.x + dx2, v2.y - dy2, &xi, &yi)) { // Calculation of the intersection succeeded //--------------------- di = calc_distance(v1.x, v1.y, xi, yi); if(di <= lim) { // Inside the miter limit //--------------------- add_vertex(vc, xi, yi); miter_limit_exceeded = false; } intersection_failed = false; } else { // Calculation of the intersection failed, most probably // the three points lie one straight line. // First check if v0 and v2 lie on the opposite sides of vector: // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular // to the line determined by vertices v0 and v1. // This condition determines whether the next line segments continues // the previous one or goes back. //---------------- double x2 = v1.x + dx1; double y2 = v1.y - dy1; if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) == (cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0)) { // This case means that the next segment continues // the previous one (straight line) //----------------- add_vertex(vc, v1.x + dx1, v1.y - dy1); miter_limit_exceeded = false; } } if(miter_limit_exceeded) { // Miter limit exceeded //------------------------ switch(lj) { case miter_join_revert: // For the compatibility with SVG, PDF, etc, // we use a simple bevel join instead of // "smart" bevel //------------------- add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx2, v1.y - dy2); break; case miter_join_round: calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); break; default: // If no miter-revert, calculate new dx1, dy1, dx2, dy2 //---------------- if(intersection_failed) { mlimit *= m_width_sign; add_vertex(vc, v1.x + dx1 + dy1 * mlimit, v1.y - dy1 + dx1 * mlimit); add_vertex(vc, v1.x + dx2 - dy2 * mlimit, v1.y - dy2 - dx2 * mlimit); } else { double x1 = v1.x + dx1; double y1 = v1.y - dy1; double x2 = v1.x + dx2; double y2 = v1.y - dy2; di = (lim - dbevel) / (di - dbevel); add_vertex(vc, x1 + (xi - x1) * di, y1 + (yi - y1) * di); add_vertex(vc, x2 + (xi - x2) * di, y2 + (yi - y2) * di); } break; } } } //--------------------------------------------------------stroke_calc_cap template<class VC> void math_stroke<VC>::calc_cap(VC& vc, const vertex_dist& v0, const vertex_dist& v1, double len) { vc.remove_all(); double dx1 = (v1.y - v0.y) / len; double dy1 = (v1.x - v0.x) / len; double dx2 = 0; double dy2 = 0; dx1 *= m_width; dy1 *= m_width; if(m_line_cap != round_cap) { if(m_line_cap == square_cap) { dx2 = dy1 * m_width_sign; dy2 = dx1 * m_width_sign; } add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2); add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2); } else { double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; double a1; int i; int n = int(pi / da); da = pi / (n + 1); add_vertex(vc, v0.x - dx1, v0.y + dy1); if(m_width_sign > 0) { a1 = atan2(dy1, -dx1); a1 += da; for(i = 0; i < n; i++) { add_vertex(vc, v0.x + cos(a1) * m_width, v0.y + sin(a1) * m_width); a1 += da; } } else { a1 = atan2(-dy1, dx1); a1 -= da; for(i = 0; i < n; i++) { add_vertex(vc, v0.x + cos(a1) * m_width, v0.y + sin(a1) * m_width); a1 -= da; } } add_vertex(vc, v0.x + dx1, v0.y - dy1); } } //----------------------------------------------------------------------- template<class VC> void math_stroke<VC>::calc_join(VC& vc, const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, double len1, double len2) { double dx1 = m_width * (v1.y - v0.y) / len1; double dy1 = m_width * (v1.x - v0.x) / len1; double dx2 = m_width * (v2.y - v1.y) / len2; double dy2 = m_width * (v2.x - v1.x) / len2; vc.remove_all(); double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); if(cp != 0 && (cp > 0) == (m_width > 0)) { // Inner join //--------------- double limit = ((len1 < len2) ? len1 : len2) / m_width_abs; if(limit < m_inner_miter_limit) { limit = m_inner_miter_limit; } switch(m_inner_join) { default: // inner_bevel add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx2, v1.y - dy2); break; case inner_miter: calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0); break; case inner_jag: case inner_round: cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); if(cp < len1 * len1 && cp < len2 * len2) { calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0); } else { if(m_inner_join == inner_jag) { add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x, v1.y ); add_vertex(vc, v1.x + dx2, v1.y - dy2); } else { add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x, v1.y ); calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1); add_vertex(vc, v1.x, v1.y ); add_vertex(vc, v1.x + dx2, v1.y - dy2); } } break; } } else { // Outer join //--------------- // Calculate the distance between v1 and // the central point of the bevel line segment //--------------- double dx = (dx1 + dx2) / 2; double dy = (dy1 + dy2) / 2; double dbevel = sqrt(dx * dx + dy * dy); if(m_line_join == round_join || m_line_join == bevel_join) { // This is an optimization that reduces the number of points // in cases of almost collinear segments. If there's no // visible difference between bevel and miter joins we'd rather // use miter join because it adds only one point instead of two. // // Here we calculate the middle point between the bevel points // and then, the distance between v1 and this middle point. // At outer joins this distance always less than stroke width, // because it's actually the height of an isosceles triangle of // v1 and its two bevel points. If the difference between this // width and this value is small (no visible bevel) we can // add just one point. // // The constant in the expression makes the result approximately // the same as in round joins and caps. You can safely comment // out this entire "if". //------------------- if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps) { if(calc_intersection(v0.x + dx1, v0.y - dy1, v1.x + dx1, v1.y - dy1, v1.x + dx2, v1.y - dy2, v2.x + dx2, v2.y - dy2, &dx, &dy)) { add_vertex(vc, dx, dy); } else { add_vertex(vc, v1.x + dx1, v1.y - dy1); } return; } } switch(m_line_join) { case miter_join: case miter_join_revert: case miter_join_round: calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, m_line_join, m_miter_limit, dbevel); break; case round_join: calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); break; default: // Bevel join add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx2, v1.y - dy2); break; } } } } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rasterizer_compound_aa.h����������������������������������0000644�0024617�0000144�00000055517�12261257215�025231� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // // The author gratefully acknowleges the support of David Turner, // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED #define AGG_RASTERIZER_COMPOUND_AA_INCLUDED #include "agg_rasterizer_cells_aa.h" #include "agg_rasterizer_sl_clip.h" namespace mapserver { //-----------------------------------------------------------cell_style_aa // A pixel cell. There're no constructors defined and it was done // intentionally in order to avoid extra overhead when allocating an // array of cells. struct cell_style_aa { int x; int y; int cover; int area; int16 left, right; void initial() { x = 0x7FFFFFFF; y = 0x7FFFFFFF; cover = 0; area = 0; left = -1; right = -1; } void style(const cell_style_aa& c) { left = c.left; right = c.right; } int not_equal(int ex, int ey, const cell_style_aa& c) const { return (ex - x) | (ey - y) | (left - c.left) | (right - c.right); } }; //===========================================================layer_order_e enum layer_order_e { layer_unsorted, //------layer_unsorted layer_direct, //------layer_direct layer_inverse //------layer_inverse }; //==================================================rasterizer_compound_aa template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa { struct style_info { unsigned start_cell; unsigned num_cells; int last_x; }; struct cell_info { int x, area, cover; }; public: typedef Clip clip_type; typedef typename Clip::conv_type conv_type; typedef typename Clip::coord_type coord_type; enum aa_scale_e { aa_shift = 8, aa_scale = 1 << aa_shift, aa_mask = aa_scale - 1, aa_scale2 = aa_scale * 2, aa_mask2 = aa_scale2 - 1 }; //-------------------------------------------------------------------- rasterizer_compound_aa() : m_outline(), m_clipper(), m_filling_rule(fill_non_zero), m_layer_order(layer_direct), m_styles(), // Active Styles m_ast(), // Active Style Table (unique values) m_asm(), // Active Style Mask m_cells(), m_cover_buf(), m_master_alpha(), m_min_style(0x7FFFFFFF), m_max_style(-0x7FFFFFFF), m_start_x(0), m_start_y(0), m_scan_y(0x7FFFFFFF), m_sl_start(0), m_sl_len(0) {} //-------------------------------------------------------------------- void reset(); void reset_clipping(); void clip_box(double x1, double y1, double x2, double y2); void filling_rule(filling_rule_e filling_rule); void layer_order(layer_order_e order); void master_alpha(int style, double alpha); //-------------------------------------------------------------------- void styles(int left, int right); void move_to(int x, int y); void line_to(int x, int y); void move_to_d(double x, double y); void line_to_d(double x, double y); void add_vertex(double x, double y, unsigned cmd); void edge(int x1, int y1, int x2, int y2); void edge_d(double x1, double y1, double x2, double y2); //------------------------------------------------------------------- template<class VertexSource> void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; vs.rewind(path_id); if(m_outline.sorted()) reset(); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); } } //-------------------------------------------------------------------- int min_x() const { return m_outline.min_x(); } int min_y() const { return m_outline.min_y(); } int max_x() const { return m_outline.max_x(); } int max_y() const { return m_outline.max_y(); } int min_style() const { return m_min_style; } int max_style() const { return m_max_style; } //-------------------------------------------------------------------- void sort(); bool rewind_scanlines(); unsigned sweep_styles(); int scanline_start() const { return m_sl_start; } unsigned scanline_length() const { return m_sl_len; } unsigned style(unsigned style_idx) const; cover_type* allocate_cover_buffer(unsigned len); //-------------------------------------------------------------------- bool navigate_scanline(int y); bool hit_test(int tx, int ty); //-------------------------------------------------------------------- AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const { int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); if(cover < 0) cover = -cover; if(m_filling_rule == fill_even_odd) { cover &= aa_mask2; if(cover > aa_scale) { cover = aa_scale2 - cover; } } if(cover > aa_mask) cover = aa_mask; return (cover * master_alpha + aa_mask) >> aa_shift; } //-------------------------------------------------------------------- // Sweeps one scanline with one style index. The style ID can be // determined by calling style(). template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx) { int scan_y = m_scan_y - 1; if(scan_y > m_outline.max_y()) return false; sl.reset_spans(); unsigned master_alpha = aa_mask; if(style_idx < 0) { style_idx = 0; } else { style_idx++; master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1]; } const style_info& st = m_styles[m_ast[style_idx]]; unsigned num_cells = st.num_cells; cell_info* cell = &m_cells[st.start_cell]; int cover = 0; while(num_cells--) { unsigned alpha; int x = cell->x; int area = cell->area; cover += cell->cover; ++cell; if(area) { alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area, master_alpha); sl.add_cell(x, alpha); x++; } if(num_cells && cell->x > x) { alpha = calculate_alpha(cover << (poly_subpixel_shift + 1), master_alpha); if(alpha) { sl.add_span(x, cell->x - x, alpha); } } } if(sl.num_spans() == 0) return false; sl.finalize(scan_y); return true; } private: void add_style(int style_id); void allocate_master_alpha(); //-------------------------------------------------------------------- // Disable copying rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&); const rasterizer_compound_aa<Clip>& operator = (const rasterizer_compound_aa<Clip>&); private: rasterizer_cells_aa<cell_style_aa> m_outline; clip_type m_clipper; filling_rule_e m_filling_rule; layer_order_e m_layer_order; pod_vector<style_info> m_styles; // Active Styles pod_vector<unsigned> m_ast; // Active Style Table (unique values) pod_vector<int8u> m_asm; // Active Style Mask pod_vector<cell_info> m_cells; pod_vector<cover_type> m_cover_buf; pod_bvector<unsigned> m_master_alpha; int m_min_style; int m_max_style; coord_type m_start_x; coord_type m_start_y; int m_scan_y; int m_sl_start; unsigned m_sl_len; }; //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::reset() { m_outline.reset(); m_min_style = 0x7FFFFFFF; m_max_style = -0x7FFFFFFF; m_scan_y = 0x7FFFFFFF; m_sl_start = 0; m_sl_len = 0; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::filling_rule(filling_rule_e filling_rule) { m_filling_rule = filling_rule; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order) { m_layer_order = order; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1, double x2, double y2) { reset(); m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), conv_type::upscale(x2), conv_type::upscale(y2)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::reset_clipping() { reset(); m_clipper.reset_clipping(); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::styles(int left, int right) { cell_style_aa cell; cell.initial(); cell.left = (int16)left; cell.right = (int16)right; m_outline.style(cell); if(left >= 0 && left < m_min_style) m_min_style = left; if(left >= 0 && left > m_max_style) m_max_style = left; if(right >= 0 && right < m_min_style) m_min_style = right; if(right >= 0 && right > m_max_style) m_max_style = right; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::move_to(int x, int y) { if(m_outline.sorted()) reset(); m_clipper.move_to(m_start_x = conv_type::downscale(x), m_start_y = conv_type::downscale(y)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::line_to(int x, int y) { m_clipper.line_to(m_outline, conv_type::downscale(x), conv_type::downscale(y)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::move_to_d(double x, double y) { if(m_outline.sorted()) reset(); m_clipper.move_to(m_start_x = conv_type::upscale(x), m_start_y = conv_type::upscale(y)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::line_to_d(double x, double y) { m_clipper.line_to(m_outline, conv_type::upscale(x), conv_type::upscale(y)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd) { if(is_move_to(cmd)) { move_to_d(x, y); } else if(is_vertex(cmd)) { line_to_d(x, y); } else if(is_close(cmd)) { m_clipper.line_to(m_outline, m_start_x, m_start_y); } } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2) { if(m_outline.sorted()) reset(); m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); m_clipper.line_to(m_outline, conv_type::downscale(x2), conv_type::downscale(y2)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1, double x2, double y2) { if(m_outline.sorted()) reset(); m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); m_clipper.line_to(m_outline, conv_type::upscale(x2), conv_type::upscale(y2)); } //------------------------------------------------------------------------ template<class Clip> AGG_INLINE void rasterizer_compound_aa<Clip>::sort() { m_outline.sort_cells(); } //------------------------------------------------------------------------ template<class Clip> AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines() { m_outline.sort_cells(); if(m_outline.total_cells() == 0) { return false; } if(m_max_style < m_min_style) { return false; } m_scan_y = m_outline.min_y(); m_styles.allocate(m_max_style - m_min_style + 2, 128); allocate_master_alpha(); return true; } //------------------------------------------------------------------------ template<class Clip> AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id) { if(style_id < 0) style_id = 0; else style_id -= m_min_style - 1; unsigned nbyte = style_id >> 3; unsigned mask = 1 << (style_id & 7); style_info* style = &m_styles[style_id]; if((m_asm[nbyte] & mask) == 0) { m_ast.add(style_id); m_asm[nbyte] |= mask; style->start_cell = 0; style->num_cells = 0; style->last_x = -0x7FFFFFFF; } ++style->start_cell; } //------------------------------------------------------------------------ // Returns the number of styles template<class Clip> unsigned rasterizer_compound_aa<Clip>::sweep_styles() { for(;;) { if(m_scan_y > m_outline.max_y()) return 0; unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y); unsigned num_styles = m_max_style - m_min_style + 2; const cell_style_aa* curr_cell; unsigned style_id; style_info* style; cell_info* cell; m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles m_ast.capacity(num_styles, 64); m_asm.allocate((num_styles + 7) >> 3, 8); m_asm.zero(); if(num_cells) { // Pre-add zero (for no-fill style, that is, -1). // We need that to ensure that the "-1 style" would go first. m_asm[0] |= 1; m_ast.add(0); style = &m_styles[0]; style->start_cell = 0; style->num_cells = 0; style->last_x = -0x7FFFFFFF; m_sl_start = cells[0]->x; m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; while(num_cells--) { curr_cell = *cells++; add_style(curr_cell->left); add_style(curr_cell->right); } // Convert the Y-histogram into the array of starting indexes unsigned i; unsigned start_cell = 0; for(i = 0; i < m_ast.size(); i++) { style_info& st = m_styles[m_ast[i]]; unsigned v = st.start_cell; st.start_cell = start_cell; start_cell += v; } cells = m_outline.scanline_cells(m_scan_y); num_cells = m_outline.scanline_num_cells(m_scan_y); while(num_cells--) { curr_cell = *cells++; style_id = (curr_cell->left < 0) ? 0 : curr_cell->left - m_min_style + 1; style = &m_styles[style_id]; if(curr_cell->x == style->last_x) { cell = &m_cells[style->start_cell + style->num_cells - 1]; cell->area += curr_cell->area; cell->cover += curr_cell->cover; } else { cell = &m_cells[style->start_cell + style->num_cells]; cell->x = curr_cell->x; cell->area = curr_cell->area; cell->cover = curr_cell->cover; style->last_x = curr_cell->x; style->num_cells++; } style_id = (curr_cell->right < 0) ? 0 : curr_cell->right - m_min_style + 1; style = &m_styles[style_id]; if(curr_cell->x == style->last_x) { cell = &m_cells[style->start_cell + style->num_cells - 1]; cell->area -= curr_cell->area; cell->cover -= curr_cell->cover; } else { cell = &m_cells[style->start_cell + style->num_cells]; cell->x = curr_cell->x; cell->area = -curr_cell->area; cell->cover = -curr_cell->cover; style->last_x = curr_cell->x; style->num_cells++; } } } if(m_ast.size() > 1) break; ++m_scan_y; } ++m_scan_y; if(m_layer_order != layer_unsorted) { range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1); if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater); else quick_sort(ra, unsigned_less); } return m_ast.size() - 1; } //------------------------------------------------------------------------ // Returns style ID depending of the existing style index template<class Clip> AGG_INLINE unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const { return m_ast[style_idx + 1] + m_min_style - 1; } //------------------------------------------------------------------------ template<class Clip> AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y) { m_outline.sort_cells(); if(m_outline.total_cells() == 0) { return false; } if(m_max_style < m_min_style) { return false; } if(y < m_outline.min_y() || y > m_outline.max_y()) { return false; } m_scan_y = y; m_styles.allocate(m_max_style - m_min_style + 2, 128); allocate_master_alpha(); return true; } //------------------------------------------------------------------------ template<class Clip> bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty) { if(!navigate_scanline(ty)) { return false; } unsigned num_styles = sweep_styles(); if(num_styles <= 0) { return false; } scanline_hit_test sl(tx); sweep_scanline(sl, -1); return sl.hit(); } //------------------------------------------------------------------------ template<class Clip> cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len) { m_cover_buf.allocate(len, 256); return &m_cover_buf[0]; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::allocate_master_alpha() { while((int)m_master_alpha.size() <= m_max_style) { m_master_alpha.add(aa_mask); } } //------------------------------------------------------------------------ template<class Clip> void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha) { if(style >= 0) { while((int)m_master_alpha.size() <= style) { m_master_alpha.add(aa_mask); } m_master_alpha[style] = uround(alpha * aa_mask); } } } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_image_filter.h���������������������������������������0000644�0024617�0000144�00000022027�12261257215�024130� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Image transformations with filtering. Span generator base class // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED #define AGG_SPAN_IMAGE_FILTER_INCLUDED #include "agg_basics.h" #include "agg_image_filters.h" #include "agg_span_interpolator_linear.h" namespace mapserver { //-------------------------------------------------------span_image_filter template<class Source, class Interpolator> class span_image_filter { public: typedef Source source_type; typedef Interpolator interpolator_type; //-------------------------------------------------------------------- span_image_filter() {} span_image_filter(source_type& src, interpolator_type& interpolator, const image_filter_lut* filter) : m_src(&src), m_interpolator(&interpolator), m_filter(filter), m_dx_dbl(0.5), m_dy_dbl(0.5), m_dx_int(image_subpixel_scale / 2), m_dy_int(image_subpixel_scale / 2) {} void attach(source_type& v) { m_src = &v; } //-------------------------------------------------------------------- source_type& source() { return *m_src; } const source_type& source() const { return *m_src; } const image_filter_lut& filter() const { return *m_filter; } int filter_dx_int() const { return m_dx_int; } int filter_dy_int() const { return m_dy_int; } double filter_dx_dbl() const { return m_dx_dbl; } double filter_dy_dbl() const { return m_dy_dbl; } //-------------------------------------------------------------------- void interpolator(interpolator_type& v) { m_interpolator = &v; } void filter(const image_filter_lut& v) { m_filter = &v; } void filter_offset(double dx, double dy) { m_dx_dbl = dx; m_dy_dbl = dy; m_dx_int = iround(dx * image_subpixel_scale); m_dy_int = iround(dy * image_subpixel_scale); } void filter_offset(double d) { filter_offset(d, d); } //-------------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } //-------------------------------------------------------------------- void prepare() {} //-------------------------------------------------------------------- private: source_type* m_src; interpolator_type* m_interpolator; const image_filter_lut* m_filter; double m_dx_dbl; double m_dy_dbl; unsigned m_dx_int; unsigned m_dy_int; }; //==============================================span_image_resample_affine template<class Source> class span_image_resample_affine : public span_image_filter<Source, span_interpolator_linear<trans_affine> > { public: typedef Source source_type; typedef span_interpolator_linear<trans_affine> interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; //-------------------------------------------------------------------- span_image_resample_affine() : m_scale_limit(200.0), m_blur_x(1.0), m_blur_y(1.0) {} //-------------------------------------------------------------------- span_image_resample_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter), m_scale_limit(200.0), m_blur_x(1.0), m_blur_y(1.0) {} //-------------------------------------------------------------------- int scale_limit() const { return uround(m_scale_limit); } void scale_limit(int v) { m_scale_limit = v; } //-------------------------------------------------------------------- double blur_x() const { return m_blur_x; } double blur_y() const { return m_blur_y; } void blur_x(double v) { m_blur_x = v; } void blur_y(double v) { m_blur_y = v; } void blur(double v) { m_blur_x = m_blur_y = v; } //-------------------------------------------------------------------- void prepare() { double scale_x; double scale_y; base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); if(scale_x * scale_y > m_scale_limit) { scale_x = scale_x * m_scale_limit / (scale_x * scale_y); scale_y = scale_y * m_scale_limit / (scale_x * scale_y); } if(scale_x < 1) scale_x = 1; if(scale_y < 1) scale_y = 1; if(scale_x > m_scale_limit) scale_x = m_scale_limit; if(scale_y > m_scale_limit) scale_y = m_scale_limit; scale_x *= m_blur_x; scale_y *= m_blur_y; if(scale_x < 1) scale_x = 1; if(scale_y < 1) scale_y = 1; m_rx = uround( scale_x * double(image_subpixel_scale)); m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); m_ry = uround( scale_y * double(image_subpixel_scale)); m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); } protected: int m_rx; int m_ry; int m_rx_inv; int m_ry_inv; private: double m_scale_limit; double m_blur_x; double m_blur_y; }; //=====================================================span_image_resample template<class Source, class Interpolator> class span_image_resample : public span_image_filter<Source, Interpolator> { public: typedef Source source_type; typedef Interpolator interpolator_type; typedef span_image_filter<source_type, interpolator_type> base_type; //-------------------------------------------------------------------- span_image_resample() : m_scale_limit(20), m_blur_x(image_subpixel_scale), m_blur_y(image_subpixel_scale) {} //-------------------------------------------------------------------- span_image_resample(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : base_type(src, inter, &filter), m_scale_limit(20), m_blur_x(image_subpixel_scale), m_blur_y(image_subpixel_scale) {} //-------------------------------------------------------------------- int scale_limit() const { return m_scale_limit; } void scale_limit(int v) { m_scale_limit = v; } //-------------------------------------------------------------------- double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); } double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); } void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); } void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); } void blur(double v) { m_blur_x = m_blur_y = uround(v * double(image_subpixel_scale)); } protected: AGG_INLINE void adjust_scale(int* rx, int* ry) { if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; if(*rx > image_subpixel_scale * m_scale_limit) { *rx = image_subpixel_scale * m_scale_limit; } if(*ry > image_subpixel_scale * m_scale_limit) { *ry = image_subpixel_scale * m_scale_limit; } *rx = (*rx * m_blur_x) >> image_subpixel_shift; *ry = (*ry * m_blur_y) >> image_subpixel_shift; if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; } int m_scale_limit; int m_blur_x; int m_blur_y; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_stroke.h���������������������������������������������0000644�0024617�0000144�00000006122�12261257215�023012� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // conv_stroke // //---------------------------------------------------------------------------- #ifndef AGG_CONV_STROKE_INCLUDED #define AGG_CONV_STROKE_INCLUDED #include "agg_basics.h" #include "agg_vcgen_stroke.h" #include "agg_conv_adaptor_vcgen.h" namespace mapserver { //-------------------------------------------------------------conv_stroke template<class VertexSource, class Markers=null_markers> struct conv_stroke : public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> { typedef Markers marker_type; typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type; conv_stroke(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs) { } void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } void line_join(line_join_e lj) { base_type::generator().line_join(lj); } void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } line_cap_e line_cap() const { return base_type::generator().line_cap(); } line_join_e line_join() const { return base_type::generator().line_join(); } inner_join_e inner_join() const { return base_type::generator().inner_join(); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } void approximation_scale(double as) { base_type::generator().approximation_scale(as); } double width() const { return base_type::generator().width(); } double miter_limit() const { return base_type::generator().miter_limit(); } double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } double approximation_scale() const { return base_type::generator().approximation_scale(); } void shorten(double s) { base_type::generator().shorten(s); } double shorten() const { return base_type::generator().shorten(); } private: conv_stroke(const conv_stroke<VertexSource, Markers>&); const conv_stroke<VertexSource, Markers>& operator = (const conv_stroke<VertexSource, Markers>&); }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_adaptor_vcgen.h��������������������������������������0000644�0024617�0000144�00000011556�12261257215�024326� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED #define AGG_CONV_ADAPTOR_VCGEN_INCLUDED #include "agg_basics.h" namespace mapserver { //------------------------------------------------------------null_markers struct null_markers { void remove_all() {} void add_vertex(double, double, unsigned) {} void prepare_src() {} void rewind(unsigned) {} unsigned vertex(double*, double*) { return path_cmd_stop; } }; //------------------------------------------------------conv_adaptor_vcgen template<class VertexSource, class Generator, class Markers=null_markers> class conv_adaptor_vcgen { enum status { initial, accumulate, generate }; public: explicit conv_adaptor_vcgen(VertexSource& source) : m_source(&source), m_status(initial) {} void attach(VertexSource& source) { m_source = &source; } Generator& generator() { return m_generator; } const Generator& generator() const { return m_generator; } Markers& markers() { return m_markers; } const Markers& markers() const { return m_markers; } void rewind(unsigned path_id) { m_source->rewind(path_id); m_status = initial; } unsigned vertex(double* x, double* y); private: // Prohibit copying conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); const conv_adaptor_vcgen<VertexSource, Generator, Markers>& operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); VertexSource* m_source; Generator m_generator; Markers m_markers; status m_status; unsigned m_last_cmd; double m_start_x; double m_start_y; }; //------------------------------------------------------------------------ template<class VertexSource, class Generator, class Markers> unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y) { unsigned cmd = path_cmd_stop; bool done = false; while(!done) { switch(m_status) { case initial: m_markers.remove_all(); m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); m_status = accumulate; case accumulate: if(is_stop(m_last_cmd)) return path_cmd_stop; m_generator.remove_all(); m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to); for(;;) { cmd = m_source->vertex(x, y); if(is_vertex(cmd)) { m_last_cmd = cmd; if(is_move_to(cmd)) { m_start_x = *x; m_start_y = *y; break; } m_generator.add_vertex(*x, *y, cmd); m_markers.add_vertex(*x, *y, path_cmd_line_to); } else { if(is_stop(cmd)) { m_last_cmd = path_cmd_stop; break; } if(is_end_poly(cmd)) { m_generator.add_vertex(*x, *y, cmd); break; } } } m_generator.rewind(0); m_status = generate; case generate: cmd = m_generator.vertex(x, y); if(is_stop(cmd)) { m_status = accumulate; break; } done = true; break; } } return cmd; } } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_contour.h�������������������������������������������0000644�0024617�0000144�00000006602�12261257215�023334� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_CONTOUR_INCLUDED #define AGG_VCGEN_CONTOUR_INCLUDED #include "agg_math_stroke.h" namespace mapserver { //----------------------------------------------------------vcgen_contour // // See Implementation agg_vcgen_contour.cpp // class vcgen_contour { enum status_e { initial, ready, outline, out_vertices, end_poly, stop }; public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; typedef pod_bvector<point_d, 6> coord_storage; vcgen_contour(); void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } void line_join(line_join_e lj) { m_stroker.line_join(lj); } void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } line_cap_e line_cap() const { return m_stroker.line_cap(); } line_join_e line_join() const { return m_stroker.line_join(); } inner_join_e inner_join() const { return m_stroker.inner_join(); } void width(double w) { m_stroker.width(m_width = w); } void miter_limit(double ml) { m_stroker.miter_limit(ml); } void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } void approximation_scale(double as) { m_stroker.approximation_scale(as); } double width() const { return m_width; } double miter_limit() const { return m_stroker.miter_limit(); } double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } double approximation_scale() const { return m_stroker.approximation_scale(); } void auto_detect_orientation(bool v) { m_auto_detect = v; } bool auto_detect_orientation() const { return m_auto_detect; } // Generator interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: vcgen_contour(const vcgen_contour&); const vcgen_contour& operator = (const vcgen_contour&); math_stroke<coord_storage> m_stroker; double m_width; vertex_storage m_src_vertices; coord_storage m_out_vertices; status_e m_status; unsigned m_src_vertex; unsigned m_out_vertex; unsigned m_closed; unsigned m_orientation; bool m_auto_detect; }; } #endif ������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_dash.h�����������������������������������������������0000644�0024617�0000144�00000004230�12261257215�022420� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // conv_dash // //---------------------------------------------------------------------------- #ifndef AGG_CONV_DASH_INCLUDED #define AGG_CONV_DASH_INCLUDED #include "agg_basics.h" #include "agg_vcgen_dash.h" #include "agg_conv_adaptor_vcgen.h" namespace mapserver { //---------------------------------------------------------------conv_dash template<class VertexSource, class Markers=null_markers> struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> { typedef Markers marker_type; typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type; conv_dash(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs) { } void remove_all_dashes() { base_type::generator().remove_all_dashes(); } void add_dash(double dash_len, double gap_len) { base_type::generator().add_dash(dash_len, gap_len); } void dash_start(double ds) { base_type::generator().dash_start(ds); } void shorten(double s) { base_type::generator().shorten(s); } double shorten() const { return base_type::generator().shorten(); } private: conv_dash(const conv_dash<VertexSource, Markers>&); const conv_dash<VertexSource, Markers>& operator = (const conv_dash<VertexSource, Markers>&); }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_gouraud.h��������������������������������������������0000644�0024617�0000144�00000013145�12261257215�023150� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_GOURAUD_INCLUDED #define AGG_SPAN_GOURAUD_INCLUDED #include "agg_basics.h" #include "agg_math.h" namespace mapserver { //============================================================span_gouraud template<class ColorT> class span_gouraud { public: typedef ColorT color_type; struct coord_type { double x; double y; color_type color; }; //-------------------------------------------------------------------- span_gouraud() : m_vertex(0) { m_cmd[0] = path_cmd_stop; } //-------------------------------------------------------------------- span_gouraud(const color_type& c1, const color_type& c2, const color_type& c3, double x1, double y1, double x2, double y2, double x3, double y3, double d) : m_vertex(0) { colors(c1, c2, c3); triangle(x1, y1, x2, y2, x3, y3, d); } //-------------------------------------------------------------------- void colors(ColorT c1, ColorT c2, ColorT c3) { m_coord[0].color = c1; m_coord[1].color = c2; m_coord[2].color = c3; } //-------------------------------------------------------------------- // Sets the triangle and dilates it if needed. // The trick here is to calculate beveled joins in the vertices of the // triangle and render it as a 6-vertex polygon. // It's necessary to achieve numerical stability. // However, the coordinates to interpolate colors are calculated // as miter joins (calc_intersection). void triangle(double x1, double y1, double x2, double y2, double x3, double y3, double d) { m_coord[0].x = m_x[0] = x1; m_coord[0].y = m_y[0] = y1; m_coord[1].x = m_x[1] = x2; m_coord[1].y = m_y[1] = y2; m_coord[2].x = m_x[2] = x3; m_coord[2].y = m_y[2] = y3; m_cmd[0] = path_cmd_move_to; m_cmd[1] = path_cmd_line_to; m_cmd[2] = path_cmd_line_to; m_cmd[3] = path_cmd_stop; if(d != 0.0) { dilate_triangle(m_coord[0].x, m_coord[0].y, m_coord[1].x, m_coord[1].y, m_coord[2].x, m_coord[2].y, m_x, m_y, d); calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], m_x[0], m_y[0], m_x[1], m_y[1], &m_coord[0].x, &m_coord[0].y); calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], m_x[2], m_y[2], m_x[3], m_y[3], &m_coord[1].x, &m_coord[1].y); calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], m_x[4], m_y[4], m_x[5], m_y[5], &m_coord[2].x, &m_coord[2].y); m_cmd[3] = path_cmd_line_to; m_cmd[4] = path_cmd_line_to; m_cmd[5] = path_cmd_line_to; m_cmd[6] = path_cmd_stop; } } //-------------------------------------------------------------------- // Vertex Source Interface to feed the coordinates to the rasterizer void rewind(unsigned) { m_vertex = 0; } //-------------------------------------------------------------------- unsigned vertex(double* x, double* y) { *x = m_x[m_vertex]; *y = m_y[m_vertex]; return m_cmd[m_vertex++]; } protected: //-------------------------------------------------------------------- void arrange_vertices(coord_type* coord) const { coord[0] = m_coord[0]; coord[1] = m_coord[1]; coord[2] = m_coord[2]; if(m_coord[0].y > m_coord[2].y) { coord[0] = m_coord[2]; coord[2] = m_coord[0]; } coord_type tmp; if(coord[0].y > coord[1].y) { tmp = coord[1]; coord[1] = coord[0]; coord[0] = tmp; } if(coord[1].y > coord[2].y) { tmp = coord[2]; coord[2] = coord[1]; coord[1] = tmp; } } private: //-------------------------------------------------------------------- coord_type m_coord[3]; double m_x[8]; double m_y[8]; unsigned m_cmd[8]; unsigned m_vertex; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rasterizer_scanline_aa.h����������������������������������0000644�0024617�0000144�00000041341�12261257215�025167� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // // The author gratefully acknowleges the support of David Turner, // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED #define AGG_RASTERIZER_SCANLINE_AA_INCLUDED #include "agg_rasterizer_cells_aa.h" #include "agg_rasterizer_sl_clip.h" #include "agg_gamma_functions.h" namespace mapserver { //-----------------------------------------------------------------cell_aa // A pixel cell. There're no constructors defined and it was done // intentionally in order to avoid extra overhead when allocating an // array of cells. struct cell_aa { int x; int y; int cover; int area; void initial() { x = 0x7FFFFFFF; y = 0x7FFFFFFF; cover = 0; area = 0; } void style(const cell_aa&) {} int not_equal(int ex, int ey, const cell_aa&) const { return (ex - x) | (ey - y); } }; //==================================================rasterizer_scanline_aa // Polygon rasterizer that is used to render filled polygons with // high-quality Anti-Aliasing. Internally, by default, the class uses // integer coordinates in format 24.8, i.e. 24 bits for integer part // and 8 bits for fractional - see poly_subpixel_shift. This class can be // used in the following way: // // 1. filling_rule(filling_rule_e ft) - optional. // // 2. gamma() - optional. // // 3. reset() // // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create // more than one contour, but each contour must consist of at least 3 // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); // is the absolute minimum of vertices that define a triangle. // The algorithm does not check either the number of vertices nor // coincidence of their coordinates, but in the worst case it just // won't draw anything. // The orger of the vertices (clockwise or counterclockwise) // is important when using the non-zero filling rule (fill_non_zero). // In this case the vertex order of all the contours must be the same // if you want your intersecting polygons to be without "holes". // You actually can use different vertices order. If the contours do not // intersect each other the order is not important anyway. If they do, // contours with the same vertex order will be rendered without "holes" // while the intersecting contours with different orders will have "holes". // // filling_rule() and gamma() can be called anytime before "sweeping". //------------------------------------------------------------------------ template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa { enum status { status_initial, status_move_to, status_line_to, status_closed }; public: typedef Clip clip_type; typedef typename Clip::conv_type conv_type; typedef typename Clip::coord_type coord_type; enum aa_scale_e { aa_shift = 8, aa_scale = 1 << aa_shift, aa_mask = aa_scale - 1, aa_scale2 = aa_scale * 2, aa_mask2 = aa_scale2 - 1 }; //-------------------------------------------------------------------- rasterizer_scanline_aa() : m_outline(), m_clipper(), m_filling_rule(fill_non_zero), m_auto_close(true), m_start_x(0), m_start_y(0), m_status(status_initial) { int i; for(i = 0; i < aa_scale; i++) m_gamma[i] = i; } //-------------------------------------------------------------------- template<class GammaF> rasterizer_scanline_aa(const GammaF& gamma_function) : m_outline(), m_clipper(m_outline), m_filling_rule(fill_non_zero), m_auto_close(true), m_start_x(0), m_start_y(0), m_status(status_initial) { gamma(gamma_function); } //-------------------------------------------------------------------- void reset(); void reset_clipping(); void clip_box(double x1, double y1, double x2, double y2); void filling_rule(filling_rule_e filling_rule); void auto_close(bool flag) { m_auto_close = flag; } //-------------------------------------------------------------------- template<class GammaF> void gamma(const GammaF& gamma_function) { int i; for(i = 0; i < aa_scale; i++) { m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); } } //-------------------------------------------------------------------- unsigned apply_gamma(unsigned cover) const { return m_gamma[cover]; } //-------------------------------------------------------------------- void move_to(int x, int y); void line_to(int x, int y); void move_to_d(double x, double y); void line_to_d(double x, double y); void close_polygon(); void add_vertex(double x, double y, unsigned cmd); void edge(int x1, int y1, int x2, int y2); void edge_d(double x1, double y1, double x2, double y2); //------------------------------------------------------------------- template<class VertexSource> void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; vs.rewind(path_id); if(m_outline.sorted()) reset(); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); } } //-------------------------------------------------------------------- int min_x() const { return m_outline.min_x(); } int min_y() const { return m_outline.min_y(); } int max_x() const { return m_outline.max_x(); } int max_y() const { return m_outline.max_y(); } //-------------------------------------------------------------------- void sort(); bool rewind_scanlines(); bool navigate_scanline(int y); //-------------------------------------------------------------------- AGG_INLINE unsigned calculate_alpha(int area) const { int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); if(cover < 0) cover = -cover; if(m_filling_rule == fill_even_odd) { cover &= aa_mask2; if(cover > aa_scale) { cover = aa_scale2 - cover; } } if(cover > aa_mask) cover = aa_mask; return m_gamma[cover]; } //-------------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { for(;;) { if(m_scan_y > m_outline.max_y()) return false; sl.reset_spans(); unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); int cover = 0; while(num_cells) { const cell_aa* cur_cell = *cells; int x = cur_cell->x; int area = cur_cell->area; unsigned alpha; cover += cur_cell->cover; //accumulate all cells with the same X while(--num_cells) { cur_cell = *++cells; if(cur_cell->x != x) break; area += cur_cell->area; cover += cur_cell->cover; } if(area) { alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); if(alpha) { sl.add_cell(x, alpha); } x++; } if(num_cells && cur_cell->x > x) { alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); if(alpha) { sl.add_span(x, cur_cell->x - x, alpha); } } } if(sl.num_spans()) break; ++m_scan_y; } sl.finalize(m_scan_y); ++m_scan_y; return true; } //-------------------------------------------------------------------- bool hit_test(int tx, int ty); private: //-------------------------------------------------------------------- // Disable copying rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&); const rasterizer_scanline_aa<Clip>& operator = (const rasterizer_scanline_aa<Clip>&); private: rasterizer_cells_aa<cell_aa> m_outline; clip_type m_clipper; int m_gamma[aa_scale]; filling_rule_e m_filling_rule; bool m_auto_close; coord_type m_start_x; coord_type m_start_y; unsigned m_status; int m_scan_y; }; //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::reset() { m_outline.reset(); m_status = status_initial; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule) { m_filling_rule = filling_rule; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1, double x2, double y2) { reset(); m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), conv_type::upscale(x2), conv_type::upscale(y2)); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::reset_clipping() { reset(); m_clipper.reset_clipping(); } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::close_polygon() { if(m_status == status_line_to) { m_clipper.line_to(m_outline, m_start_x, m_start_y); m_status = status_closed; } } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::move_to(int x, int y) { if(m_outline.sorted()) reset(); if(m_auto_close) close_polygon(); m_clipper.move_to(m_start_x = conv_type::downscale(x), m_start_y = conv_type::downscale(y)); m_status = status_move_to; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::line_to(int x, int y) { m_clipper.line_to(m_outline, conv_type::downscale(x), conv_type::downscale(y)); m_status = status_line_to; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y) { if(m_outline.sorted()) reset(); if(m_auto_close) close_polygon(); m_clipper.move_to(m_start_x = conv_type::upscale(x), m_start_y = conv_type::upscale(y)); m_status = status_move_to; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y) { m_clipper.line_to(m_outline, conv_type::upscale(x), conv_type::upscale(y)); m_status = status_line_to; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd) { if(is_move_to(cmd)) { move_to_d(x, y); } else if(is_vertex(cmd)) { line_to_d(x, y); } else if(is_close(cmd)) { close_polygon(); } } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2) { if(m_outline.sorted()) reset(); m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); m_clipper.line_to(m_outline, conv_type::downscale(x2), conv_type::downscale(y2)); m_status = status_move_to; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1, double x2, double y2) { if(m_outline.sorted()) reset(); m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); m_clipper.line_to(m_outline, conv_type::upscale(x2), conv_type::upscale(y2)); m_status = status_move_to; } //------------------------------------------------------------------------ template<class Clip> void rasterizer_scanline_aa<Clip>::sort() { if(m_auto_close) close_polygon(); m_outline.sort_cells(); } //------------------------------------------------------------------------ template<class Clip> AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines() { if(m_auto_close) close_polygon(); m_outline.sort_cells(); if(m_outline.total_cells() == 0) { return false; } m_scan_y = m_outline.min_y(); return true; } //------------------------------------------------------------------------ template<class Clip> AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y) { if(m_auto_close) close_polygon(); m_outline.sort_cells(); if(m_outline.total_cells() == 0 || y < m_outline.min_y() || y > m_outline.max_y()) { return false; } m_scan_y = y; return true; } //------------------------------------------------------------------------ template<class Clip> bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty) { if(!navigate_scanline(ty)) return false; scanline_hit_test sl(tx); sweep_scanline(sl); return sl.hit(); } } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_rendering_buffer_dynarow.h��������������������������������0000644�0024617�0000144�00000011655�12261257215�025536� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class rendering_buffer_dynarow // //---------------------------------------------------------------------------- #ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED #define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED #include "agg_array.h" namespace mapserver { //===============================================rendering_buffer_dynarow // Rendering buffer class with dynamic allocation of the rows. // The rows are allocated as needed when requesting for span_ptr(). // The class automatically calculates min_x and max_x for each row. // Generally it's more efficient to use this class as a temporary buffer // for rendering a few lines and then to blend it with another buffer. // class rendering_buffer_dynarow { public: typedef row_info<int8u> row_data; //------------------------------------------------------------------- ~rendering_buffer_dynarow() { init(0,0,0); } //------------------------------------------------------------------- rendering_buffer_dynarow() : m_rows(), m_width(0), m_height(0), m_byte_width(0) { } // Allocate and clear the buffer //-------------------------------------------------------------------- rendering_buffer_dynarow(unsigned width, unsigned height, unsigned byte_width) : m_rows(height), m_width(width), m_height(height), m_byte_width(byte_width) { memset(&m_rows[0], 0, sizeof(row_data) * height); } // Allocate and clear the buffer //-------------------------------------------------------------------- void init(unsigned width, unsigned height, unsigned byte_width) { unsigned i; for(i = 0; i < m_height; ++i) { pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width); } if(width && height) { m_width = width; m_height = height; m_byte_width = byte_width; m_rows.resize(height); memset(&m_rows[0], 0, sizeof(row_data) * height); } } //-------------------------------------------------------------------- unsigned width() const { return m_width; } unsigned height() const { return m_height; } unsigned byte_width() const { return m_byte_width; } // The main function used for rendering. Returns pointer to the // pre-allocated span. Memory for the row is allocated as needed. //-------------------------------------------------------------------- int8u* row_ptr(int x, int y, unsigned len) { row_data* r = &m_rows[y]; int x2 = x + len - 1; if(r->ptr) { if(x < r->x1) { r->x1 = x; } if(x2 > r->x2) { r->x2 = x2; } } else { int8u* p = pod_allocator<int8u>::allocate(m_byte_width); r->ptr = p; r->x1 = x; r->x2 = x2; memset(p, 0, m_byte_width); } return (int8u*)r->ptr; } //-------------------------------------------------------------------- const int8u* row_ptr(int y) const { return m_rows[y].ptr; } int8u* row_ptr(int y) { return row_ptr(0, y, m_width); } row_data row (int y) const { return m_rows[y]; } private: //-------------------------------------------------------------------- // Prohibit copying rendering_buffer_dynarow(const rendering_buffer_dynarow&); const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&); private: //-------------------------------------------------------------------- pod_array<row_data> m_rows; // Pointers to each row of the buffer unsigned m_width; // Width in pixels unsigned m_height; // Height in pixels unsigned m_byte_width; // Width in bytes }; } #endif �����������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_embedded_raster_fonts.h�����������������������������������0000644�0024617�0000144�00000004151�12261257215�025000� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED #define AGG_EMBEDDED_RASTER_FONTS_INCLUDED #include "agg_basics.h" namespace mapserver { extern const int8u gse4x6[]; extern const int8u gse4x8[]; extern const int8u gse5x7[]; extern const int8u gse5x9[]; extern const int8u gse6x12[]; extern const int8u gse6x9[]; extern const int8u gse7x11[]; extern const int8u gse7x11_bold[]; extern const int8u gse7x15[]; extern const int8u gse7x15_bold[]; extern const int8u gse8x16[]; extern const int8u gse8x16_bold[]; extern const int8u mcs11_prop[]; extern const int8u mcs11_prop_condensed[]; extern const int8u mcs12_prop[]; extern const int8u mcs13_prop[]; extern const int8u mcs5x10_mono[]; extern const int8u mcs5x11_mono[]; extern const int8u mcs6x10_mono[]; extern const int8u mcs6x11_mono[]; extern const int8u mcs7x12_mono_high[]; extern const int8u mcs7x12_mono_low[]; extern const int8u verdana12[]; extern const int8u verdana12_bold[]; extern const int8u verdana13[]; extern const int8u verdana13_bold[]; extern const int8u verdana14[]; extern const int8u verdana14_bold[]; extern const int8u verdana16[]; extern const int8u verdana16_bold[]; extern const int8u verdana17[]; extern const int8u verdana17_bold[]; extern const int8u verdana18[]; extern const int8u verdana18_bold[]; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_single_path.h���������������������������������������0000644�0024617�0000144�00000005654�12261257215�024173� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_TRANS_SINGLE_PATH_INCLUDED #define AGG_TRANS_SINGLE_PATH_INCLUDED #include "agg_basics.h" #include "agg_vertex_sequence.h" namespace mapserver { // See also: agg_trans_single_path.cpp // //-------------------------------------------------------trans_single_path class trans_single_path { enum status_e { initial, making_path, ready }; public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; trans_single_path(); //-------------------------------------------------------------------- void base_length(double v) { m_base_length = v; } double base_length() const { return m_base_length; } //-------------------------------------------------------------------- void preserve_x_scale(bool f) { m_preserve_x_scale = f; } bool preserve_x_scale() const { return m_preserve_x_scale; } //-------------------------------------------------------------------- void reset(); void move_to(double x, double y); void line_to(double x, double y); void finalize_path(); //-------------------------------------------------------------------- template<class VertexSource> void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { if(is_move_to(cmd)) { move_to(x, y); } else { if(is_vertex(cmd)) { line_to(x, y); } } } finalize_path(); } //-------------------------------------------------------------------- double total_length() const; void transform(double *x, double *y) const; private: vertex_storage m_src_vertices; double m_base_length; double m_kindex; status_e m_status; bool m_preserve_x_scale; }; } #endif ������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_interpolator_adaptor.h�������������������������������0000644�0024617�0000144�00000005160�12261257215�025734� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED #define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED #include "agg_basics.h" namespace mapserver { //===============================================span_interpolator_adaptor template<class Interpolator, class Distortion> class span_interpolator_adaptor : public Interpolator { public: typedef Interpolator base_type; typedef typename base_type::trans_type trans_type; typedef Distortion distortion_type; //-------------------------------------------------------------------- span_interpolator_adaptor() {} span_interpolator_adaptor(const trans_type& trans, const distortion_type& dist) : base_type(trans), m_distortion(&dist) { } //-------------------------------------------------------------------- span_interpolator_adaptor(const trans_type& trans, const distortion_type& dist, double x, double y, unsigned len) : base_type(trans, x, y, len), m_distortion(&dist) { } //-------------------------------------------------------------------- const distortion_type& distortion() const { return *m_distortion; } //-------------------------------------------------------------------- void distortion(const distortion_type& dist) { m_distortion = dist; } //-------------------------------------------------------------------- void coordinates(int* x, int* y) const { base_type::coordinates(x, y); m_distortion->calculate(x, y); } private: //-------------------------------------------------------------------- const distortion_type* m_distortion; }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_bilinear.h������������������������������������������0000644�0024617�0000144�00000012510�12261257215�023450� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Bilinear 2D transformations // //---------------------------------------------------------------------------- #ifndef AGG_TRANS_BILINEAR_INCLUDED #define AGG_TRANS_BILINEAR_INCLUDED #include "agg_basics.h" #include "agg_simul_eq.h" namespace mapserver { //==========================================================trans_bilinear class trans_bilinear { public: //-------------------------------------------------------------------- trans_bilinear() : m_valid(false) {} //-------------------------------------------------------------------- // Arbitrary quadrangle transformations trans_bilinear(const double* src, const double* dst) { quad_to_quad(src, dst); } //-------------------------------------------------------------------- // Direct transformations trans_bilinear(double x1, double y1, double x2, double y2, const double* quad) { rect_to_quad(x1, y1, x2, y2, quad); } //-------------------------------------------------------------------- // Reverse transformations trans_bilinear(const double* quad, double x1, double y1, double x2, double y2) { quad_to_rect(quad, x1, y1, x2, y2); } //-------------------------------------------------------------------- // Set the transformations using two arbitrary quadrangles. void quad_to_quad(const double* src, const double* dst) { double left[4][4]; double right[4][2]; unsigned i; for(i = 0; i < 4; i++) { unsigned ix = i * 2; unsigned iy = ix + 1; left[i][0] = 1.0; left[i][1] = src[ix] * src[iy]; left[i][2] = src[ix]; left[i][3] = src[iy]; right[i][0] = dst[ix]; right[i][1] = dst[iy]; } m_valid = simul_eq<4, 2>::solve(left, right, m_mtx); } //-------------------------------------------------------------------- // Set the direct transformations, i.e., rectangle -> quadrangle void rect_to_quad(double x1, double y1, double x2, double y2, const double* quad) { double src[8]; src[0] = src[6] = x1; src[2] = src[4] = x2; src[1] = src[3] = y1; src[5] = src[7] = y2; quad_to_quad(src, quad); } //-------------------------------------------------------------------- // Set the reverse transformations, i.e., quadrangle -> rectangle void quad_to_rect(const double* quad, double x1, double y1, double x2, double y2) { double dst[8]; dst[0] = dst[6] = x1; dst[2] = dst[4] = x2; dst[1] = dst[3] = y1; dst[5] = dst[7] = y2; quad_to_quad(quad, dst); } //-------------------------------------------------------------------- // Check if the equations were solved successfully bool is_valid() const { return m_valid; } //-------------------------------------------------------------------- // Transform a point (x, y) void transform(double* x, double* y) const { double tx = *x; double ty = *y; double xy = tx * ty; *x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty; *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty; } //-------------------------------------------------------------------- class iterator_x { double inc_x; double inc_y; public: double x; double y; iterator_x() {} iterator_x(double tx, double ty, double step, const double m[4][2]) : inc_x(m[1][0] * step * ty + m[2][0] * step), inc_y(m[1][1] * step * ty + m[2][1] * step), x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty), y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty) { } void operator ++ () { x += inc_x; y += inc_y; } }; iterator_x begin(double x, double y, double step) const { return iterator_x(x, y, step, m_mtx); } private: double m_mtx[4][2]; bool m_valid; }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_gsv_text.h������������������������������������������������0000644�0024617�0000144�00000007705�12261257215�022331� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Class gsv_text // //---------------------------------------------------------------------------- #ifndef AGG_GSV_TEXT_INCLUDED #define AGG_GSV_TEXT_INCLUDED #include "agg_array.h" #include "agg_conv_stroke.h" #include "agg_conv_transform.h" namespace mapserver { //---------------------------------------------------------------gsv_text // // See Implementation agg_gsv_text.cpp // class gsv_text { enum status { initial, next_char, start_glyph, glyph }; public: gsv_text(); void font(const void* font); void flip(bool flip_y) { m_flip = flip_y; } void load_font(const char* file); void size(double height, double width=0.0); void space(double space); void line_space(double line_space); void start_point(double x, double y); void text(const char* text); double text_width(); void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: // not supposed to be copied gsv_text(const gsv_text&); const gsv_text& operator = (const gsv_text&); int16u value(const int8u* p) const { int16u v; if(m_big_endian) { *(int8u*)&v = p[1]; *((int8u*)&v + 1) = p[0]; } else { *(int8u*)&v = p[0]; *((int8u*)&v + 1) = p[1]; } return v; } private: double m_x; double m_y; double m_start_x; double m_width; double m_height; double m_space; double m_line_space; char m_chr[2]; char* m_text; pod_array<char> m_text_buf; char* m_cur_chr; const void* m_font; pod_array<char> m_loaded_font; status m_status; bool m_big_endian; bool m_flip; int8u* m_indices; int8* m_glyphs; int8* m_bglyph; int8* m_eglyph; double m_w; double m_h; }; //--------------------------------------------------------gsv_text_outline template<class Transformer = trans_affine> class gsv_text_outline { public: gsv_text_outline(gsv_text& text, const Transformer& trans) : m_polyline(text), m_trans(m_polyline, trans) { } void width(double w) { m_polyline.width(w); } void transformer(const Transformer* trans) { m_trans->transformer(trans); } void rewind(unsigned path_id) { m_trans.rewind(path_id); m_polyline.line_join(round_join); m_polyline.line_cap(round_cap); } unsigned vertex(double* x, double* y) { return m_trans.vertex(x, y); } private: conv_stroke<gsv_text> m_polyline; conv_transform<conv_stroke<gsv_text>, Transformer> m_trans; }; } #endif �����������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_converter.h������������������������������������������0000644�0024617�0000144�00000003644�12261257215�023514� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_CONVERTER_INCLUDED #define AGG_SPAN_CONVERTER_INCLUDED #include "agg_basics.h" namespace mapserver { //----------------------------------------------------------span_converter template<class SpanGenerator, class SpanConverter> class span_converter { public: typedef typename SpanGenerator::color_type color_type; span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) : m_span_gen(&span_gen), m_span_cnv(&span_cnv) {} void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; } void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; } //-------------------------------------------------------------------- void prepare() { m_span_gen->prepare(); m_span_cnv->prepare(); } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) { m_span_gen->generate(span, x, y, len); m_span_cnv->generate(span, x, y, len); } private: SpanGenerator* m_span_gen; SpanConverter* m_span_cnv; }; } #endif ��������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_config.h��������������������������������������������������0000644�0024617�0000144�00000002361�12261257215�021724� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef AGG_CONFIG_INCLUDED #define AGG_CONFIG_INCLUDED // This file can be used to redefine certain data types. //--------------------------------------- // 1. Default basic types such as: // // AGG_INT8 // AGG_INT8U // AGG_INT16 // AGG_INT16U // AGG_INT32 // AGG_INT32U // AGG_INT64 // AGG_INT64U // // Just replace this file with new defines if necessary. // For example, if your compiler doesn't have a 64 bit integer type // you can still use AGG if you define the follows: // // #define AGG_INT64 int // #define AGG_INT64U unsigned // // It will result in overflow in 16 bit-per-component image/pattern resampling // but it won't result any crash and the rest of the library will remain // fully functional. //--------------------------------------- // 2. Default rendering_buffer type. Can be: // // Provides faster access for massive pixel operations, // such as blur, image filtering: // #define AGG_RENDERING_BUFFER row_ptr_cache<int8u> // // Provides cheaper creation and destruction (no mem allocs): // #define AGG_RENDERING_BUFFER row_accessor<int8u> // // You can still use both of them simultaneouslyin your applications // This #define is used only for default rendering_buffer type, // in short hand typedefs like pixfmt_rgba32. #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/Makefile.am���������������������������������������������������0000644�0024617�0000144�00000007107�12261257215�021527� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SUBDIRS = ctrl util platform aggincludedir = $(includedir)/agg2 agginclude_HEADERS = \ agg_alpha_mask_u8.h agg_glyph_raster_bin.h agg_span_allocator.h \ agg_arc.h agg_gsv_text.h agg_span_converter.h \ agg_array.h agg_image_accessors.h agg_span_gouraud.h \ agg_arrowhead.h agg_image_filters.h agg_span_gouraud_gray.h \ agg_basics.h agg_line_aa_basics.h agg_span_gouraud_rgba.h \ agg_bezier_arc.h agg_math.h agg_span_gradient.h \ agg_bitset_iterator.h agg_blur.h agg_math_stroke.h \ agg_span_gradient_alpha.h agg_gradient_lut.h \ agg_bounding_rect.h agg_path_length.h agg_span_image_filter.h \ agg_bspline.h agg_path_storage.h agg_span_image_filter_gray.h \ agg_clip_liang_barsky.h agg_path_storage_integer.h agg_span_image_filter_rgb.h \ agg_color_gray.h agg_pattern_filters_rgba.h agg_span_image_filter_rgba.h \ agg_color_rgba.h agg_pixfmt_amask_adaptor.h agg_span_interpolator_adaptor.h \ agg_config.h agg_pixfmt_gray.h agg_span_interpolator_linear.h \ agg_conv_adaptor_vcgen.h agg_pixfmt_rgb.h agg_span_interpolator_persp.h \ agg_conv_adaptor_vpgen.h agg_pixfmt_rgb_packed.h agg_span_interpolator_trans.h \ agg_conv_bspline.h agg_pixfmt_rgba.h agg_pixfmt_transposer.h \ agg_span_pattern_gray.h \ agg_conv_clip_polygon.h agg_rasterizer_cells_aa.h agg_span_pattern_rgb.h \ agg_conv_clip_polyline.h agg_rasterizer_compound_aa.h agg_span_pattern_rgba.h \ agg_conv_close_polygon.h agg_rasterizer_outline.h agg_span_solid.h \ agg_conv_concat.h agg_rasterizer_outline_aa.h agg_span_subdiv_adaptor.h \ agg_conv_contour.h agg_rasterizer_scanline_aa.h agg_trans_affine.h \ agg_conv_curve.h agg_rasterizer_sl_clip.h agg_trans_bilinear.h \ agg_conv_dash.h agg_renderer_base.h agg_trans_double_path.h \ agg_conv_gpc.h agg_renderer_markers.h \ agg_conv_marker.h agg_renderer_mclip.h agg_trans_perspective.h \ agg_conv_marker_adaptor.h agg_renderer_outline_aa.h agg_trans_single_path.h \ agg_conv_segmentator.h agg_renderer_outline_image.h agg_trans_viewport.h \ agg_conv_shorten_path.h agg_renderer_primitives.h agg_trans_warp_magnifier.h \ agg_conv_smooth_poly1.h agg_renderer_raster_text.h agg_vcgen_bspline.h \ agg_conv_stroke.h agg_renderer_scanline.h agg_vcgen_contour.h \ agg_conv_transform.h agg_rendering_buffer.h agg_vcgen_dash.h \ agg_conv_unclose_polygon.h agg_rendering_buffer_dynarow.h agg_vcgen_markers_term.h \ agg_curves.h agg_rounded_rect.h agg_vcgen_smooth_poly1.h \ agg_scanline_bin.h agg_vcgen_stroke.h \ agg_dda_line.h agg_scanline_boolean_algebra.h agg_vcgen_vertex_sequence.h \ agg_ellipse.h agg_scanline_p.h agg_vertex_sequence.h \ agg_ellipse_bresenham.h agg_scanline_storage_aa.h agg_vpgen_clip_polygon.h \ agg_embedded_raster_fonts.h agg_scanline_storage_bin.h agg_vpgen_clip_polyline.h \ agg_font_cache_manager.h agg_scanline_u.h agg_vpgen_segmentator.h \ agg_gamma_functions.h agg_shorten_path.h \ agg_gamma_lut.h agg_simul_eq.h ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_mclip.h������������������������������������������0000644�0024617�0000144�00000027011�12261257215�023450� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class renderer_mclip // //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_MCLIP_INCLUDED #define AGG_RENDERER_MCLIP_INCLUDED #include "agg_basics.h" #include "agg_array.h" #include "agg_renderer_base.h" namespace mapserver { //----------------------------------------------------------renderer_mclip template<class PixelFormat> class renderer_mclip { public: typedef PixelFormat pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::row_data row_data; typedef renderer_base<pixfmt_type> base_ren_type; //-------------------------------------------------------------------- explicit renderer_mclip(pixfmt_type& pixf) : m_ren(pixf), m_curr_cb(0), m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) {} void attach(pixfmt_type& pixf) { m_ren.attach(pixf); reset_clipping(true); } //-------------------------------------------------------------------- const pixfmt_type& ren() const { return m_ren.ren(); } pixfmt_type& ren() { return m_ren.ren(); } //-------------------------------------------------------------------- unsigned width() const { return m_ren.width(); } unsigned height() const { return m_ren.height(); } //-------------------------------------------------------------------- const rect_i& clip_box() const { return m_ren.clip_box(); } int xmin() const { return m_ren.xmin(); } int ymin() const { return m_ren.ymin(); } int xmax() const { return m_ren.xmax(); } int ymax() const { return m_ren.ymax(); } //-------------------------------------------------------------------- const rect_i& bounding_clip_box() const { return m_bounds; } int bounding_xmin() const { return m_bounds.x1; } int bounding_ymin() const { return m_bounds.y1; } int bounding_xmax() const { return m_bounds.x2; } int bounding_ymax() const { return m_bounds.y2; } //-------------------------------------------------------------------- void first_clip_box() { m_curr_cb = 0; if(m_clip.size()) { const rect_i& cb = m_clip[0]; m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); } } //-------------------------------------------------------------------- bool next_clip_box() { if(++m_curr_cb < m_clip.size()) { const rect_i& cb = m_clip[m_curr_cb]; m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); return true; } return false; } //-------------------------------------------------------------------- void reset_clipping(bool visibility) { m_ren.reset_clipping(visibility); m_clip.remove_all(); m_curr_cb = 0; m_bounds = m_ren.clip_box(); } //-------------------------------------------------------------------- void add_clip_box(int x1, int y1, int x2, int y2) { rect_i cb(x1, y1, x2, y2); cb.normalize(); if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) { m_clip.add(cb); if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1; if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1; if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2; if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2; } } //-------------------------------------------------------------------- void clear(const color_type& c) { m_ren.clear(c); } //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { first_clip_box(); do { if(m_ren.inbox(x, y)) { m_ren.ren().copy_pixel(x, y, c); break; } } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_pixel(int x, int y, const color_type& c, cover_type cover) { first_clip_box(); do { if(m_ren.inbox(x, y)) { m_ren.ren().blend_pixel(x, y, c, cover); break; } } while(next_clip_box()); } //-------------------------------------------------------------------- color_type pixel(int x, int y) const { first_clip_box(); do { if(m_ren.inbox(x, y)) { return m_ren.ren().pixel(x, y); } } while(next_clip_box()); return color_type::no_color(); } //-------------------------------------------------------------------- void copy_hline(int x1, int y, int x2, const color_type& c) { first_clip_box(); do { m_ren.copy_hline(x1, y, x2, c); } while(next_clip_box()); } //-------------------------------------------------------------------- void copy_vline(int x, int y1, int y2, const color_type& c) { first_clip_box(); do { m_ren.copy_vline(x, y1, y2, c); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_hline(int x1, int y, int x2, const color_type& c, cover_type cover) { first_clip_box(); do { m_ren.blend_hline(x1, y, x2, c, cover); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_vline(int x, int y1, int y2, const color_type& c, cover_type cover) { first_clip_box(); do { m_ren.blend_vline(x, y1, y2, c, cover); } while(next_clip_box()); } //-------------------------------------------------------------------- void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) { first_clip_box(); do { m_ren.copy_bar(x1, y1, x2, y2, c); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_bar(int x1, int y1, int x2, int y2, const color_type& c, cover_type cover) { first_clip_box(); do { m_ren.blend_bar(x1, y1, x2, y2, c, cover); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers) { first_clip_box(); do { m_ren.blend_solid_hspan(x, y, len, c, covers); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, int len, const color_type& c, const cover_type* covers) { first_clip_box(); do { m_ren.blend_solid_vspan(x, y, len, c, covers); } while(next_clip_box()); } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, int len, const color_type* colors) { first_clip_box(); do { m_ren.copy_color_hspan(x, y, len, colors); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, int len, const color_type* colors, const cover_type* covers, cover_type cover = cover_full) { first_clip_box(); do { m_ren.blend_color_hspan(x, y, len, colors, covers, cover); } while(next_clip_box()); } //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, int len, const color_type* colors, const cover_type* covers, cover_type cover = cover_full) { first_clip_box(); do { m_ren.blend_color_vspan(x, y, len, colors, covers, cover); } while(next_clip_box()); } //-------------------------------------------------------------------- void copy_from(const rendering_buffer& from, const rect_i* rc=0, int x_to=0, int y_to=0) { first_clip_box(); do { m_ren.copy_from(from, rc, x_to, y_to); } while(next_clip_box()); } //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& src, const rect_i* rect_src_ptr = 0, int dx = 0, int dy = 0, cover_type cover = cover_full) { first_clip_box(); do { m_ren.blend_from(src, rect_src_ptr, dx, dy, cover); } while(next_clip_box()); } private: renderer_mclip(const renderer_mclip<PixelFormat>&); const renderer_mclip<PixelFormat>& operator = (const renderer_mclip<PixelFormat>&); base_ren_type m_ren; pod_bvector<rect_i, 4> m_clip; unsigned m_curr_cb; rect_i m_bounds; }; } #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_interpolator_persp.h���������������������������������0000644�0024617�0000144�00000036504�12261257215�025441� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED #define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED #include "agg_trans_perspective.h" #include "agg_dda_line.h" namespace mapserver { //===========================================span_interpolator_persp_exact template<unsigned SubpixelShift = 8> class span_interpolator_persp_exact { public: typedef trans_perspective trans_type; typedef trans_perspective::iterator_x iterator_type; enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- span_interpolator_persp_exact() {} //-------------------------------------------------------------------- // Arbitrary quadrangle transformations span_interpolator_persp_exact(const double* src, const double* dst) { quad_to_quad(src, dst); } //-------------------------------------------------------------------- // Direct transformations span_interpolator_persp_exact(double x1, double y1, double x2, double y2, const double* quad) { rect_to_quad(x1, y1, x2, y2, quad); } //-------------------------------------------------------------------- // Reverse transformations span_interpolator_persp_exact(const double* quad, double x1, double y1, double x2, double y2) { quad_to_rect(quad, x1, y1, x2, y2); } //-------------------------------------------------------------------- // Set the transformations using two arbitrary quadrangles. void quad_to_quad(const double* src, const double* dst) { m_trans_dir.quad_to_quad(src, dst); m_trans_inv.quad_to_quad(dst, src); } //-------------------------------------------------------------------- // Set the direct transformations, i.e., rectangle -> quadrangle void rect_to_quad(double x1, double y1, double x2, double y2, const double* quad) { double src[8]; src[0] = src[6] = x1; src[2] = src[4] = x2; src[1] = src[3] = y1; src[5] = src[7] = y2; quad_to_quad(src, quad); } //-------------------------------------------------------------------- // Set the reverse transformations, i.e., quadrangle -> rectangle void quad_to_rect(const double* quad, double x1, double y1, double x2, double y2) { double dst[8]; dst[0] = dst[6] = x1; dst[2] = dst[4] = x2; dst[1] = dst[3] = y1; dst[5] = dst[7] = y2; quad_to_quad(quad, dst); } //-------------------------------------------------------------------- // Check if the equations were solved successfully bool is_valid() const { return m_trans_dir.is_valid(); } //---------------------------------------------------------------- void begin(double x, double y, unsigned len) { m_iterator = m_trans_dir.begin(x, y, 1.0); double xt = m_iterator.x; double yt = m_iterator.y; double dx; double dy; const double delta = 1/double(subpixel_scale); dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; x += len; xt = x; yt = y; m_trans_dir.transform(&xt, &yt); dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; m_scale_x = dda2_line_interpolator(sx1, sx2, len); m_scale_y = dda2_line_interpolator(sy1, sy2, len); } //---------------------------------------------------------------- void resynchronize(double xe, double ye, unsigned len) { // Assume x1,y1 are equal to the ones at the previous end point int sx1 = m_scale_x.y(); int sy1 = m_scale_y.y(); // Calculate transformed coordinates at x2,y2 double xt = xe; double yt = ye; m_trans_dir.transform(&xt, &yt); const double delta = 1/double(subpixel_scale); double dx; double dy; // Calculate scale by X at x2,y2 dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x2,y2 dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Initialize the interpolators m_scale_x = dda2_line_interpolator(sx1, sx2, len); m_scale_y = dda2_line_interpolator(sy1, sy2, len); } //---------------------------------------------------------------- void operator++() { ++m_iterator; ++m_scale_x; ++m_scale_y; } //---------------------------------------------------------------- void coordinates(int* x, int* y) const { *x = iround(m_iterator.x * subpixel_scale); *y = iround(m_iterator.y * subpixel_scale); } //---------------------------------------------------------------- void local_scale(int* x, int* y) { *x = m_scale_x.y(); *y = m_scale_y.y(); } //---------------------------------------------------------------- void transform(double* x, double* y) const { m_trans_dir.transform(x, y); } private: trans_type m_trans_dir; trans_type m_trans_inv; iterator_type m_iterator; dda2_line_interpolator m_scale_x; dda2_line_interpolator m_scale_y; }; //============================================span_interpolator_persp_lerp template<unsigned SubpixelShift = 8> class span_interpolator_persp_lerp { public: typedef trans_perspective trans_type; enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- span_interpolator_persp_lerp() {} //-------------------------------------------------------------------- // Arbitrary quadrangle transformations span_interpolator_persp_lerp(const double* src, const double* dst) { quad_to_quad(src, dst); } //-------------------------------------------------------------------- // Direct transformations span_interpolator_persp_lerp(double x1, double y1, double x2, double y2, const double* quad) { rect_to_quad(x1, y1, x2, y2, quad); } //-------------------------------------------------------------------- // Reverse transformations span_interpolator_persp_lerp(const double* quad, double x1, double y1, double x2, double y2) { quad_to_rect(quad, x1, y1, x2, y2); } //-------------------------------------------------------------------- // Set the transformations using two arbitrary quadrangles. void quad_to_quad(const double* src, const double* dst) { m_trans_dir.quad_to_quad(src, dst); m_trans_inv.quad_to_quad(dst, src); } //-------------------------------------------------------------------- // Set the direct transformations, i.e., rectangle -> quadrangle void rect_to_quad(double x1, double y1, double x2, double y2, const double* quad) { double src[8]; src[0] = src[6] = x1; src[2] = src[4] = x2; src[1] = src[3] = y1; src[5] = src[7] = y2; quad_to_quad(src, quad); } //-------------------------------------------------------------------- // Set the reverse transformations, i.e., quadrangle -> rectangle void quad_to_rect(const double* quad, double x1, double y1, double x2, double y2) { double dst[8]; dst[0] = dst[6] = x1; dst[2] = dst[4] = x2; dst[1] = dst[3] = y1; dst[5] = dst[7] = y2; quad_to_quad(quad, dst); } //-------------------------------------------------------------------- // Check if the equations were solved successfully bool is_valid() const { return m_trans_dir.is_valid(); } //---------------------------------------------------------------- void begin(double x, double y, unsigned len) { // Calculate transformed coordinates at x1,y1 double xt = x; double yt = y; m_trans_dir.transform(&xt, &yt); int x1 = iround(xt * subpixel_scale); int y1 = iround(yt * subpixel_scale); double dx; double dy; const double delta = 1/double(subpixel_scale); // Calculate scale by X at x1,y1 dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x1,y1 dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate transformed coordinates at x2,y2 x += len; xt = x; yt = y; m_trans_dir.transform(&xt, &yt); int x2 = iround(xt * subpixel_scale); int y2 = iround(yt * subpixel_scale); // Calculate scale by X at x2,y2 dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x2,y2 dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Initialize the interpolators m_coord_x = dda2_line_interpolator(x1, x2, len); m_coord_y = dda2_line_interpolator(y1, y2, len); m_scale_x = dda2_line_interpolator(sx1, sx2, len); m_scale_y = dda2_line_interpolator(sy1, sy2, len); } //---------------------------------------------------------------- void resynchronize(double xe, double ye, unsigned len) { // Assume x1,y1 are equal to the ones at the previous end point int x1 = m_coord_x.y(); int y1 = m_coord_y.y(); int sx1 = m_scale_x.y(); int sy1 = m_scale_y.y(); // Calculate transformed coordinates at x2,y2 double xt = xe; double yt = ye; m_trans_dir.transform(&xt, &yt); int x2 = iround(xt * subpixel_scale); int y2 = iround(yt * subpixel_scale); const double delta = 1/double(subpixel_scale); double dx; double dy; // Calculate scale by X at x2,y2 dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x2,y2 dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Initialize the interpolators m_coord_x = dda2_line_interpolator(x1, x2, len); m_coord_y = dda2_line_interpolator(y1, y2, len); m_scale_x = dda2_line_interpolator(sx1, sx2, len); m_scale_y = dda2_line_interpolator(sy1, sy2, len); } //---------------------------------------------------------------- void operator++() { ++m_coord_x; ++m_coord_y; ++m_scale_x; ++m_scale_y; } //---------------------------------------------------------------- void coordinates(int* x, int* y) const { *x = m_coord_x.y(); *y = m_coord_y.y(); } //---------------------------------------------------------------- void local_scale(int* x, int* y) { *x = m_scale_x.y(); *y = m_scale_y.y(); } //---------------------------------------------------------------- void transform(double* x, double* y) const { m_trans_dir.transform(x, y); } private: trans_type m_trans_dir; trans_type m_trans_inv; dda2_line_interpolator m_coord_x; dda2_line_interpolator m_coord_y; dda2_line_interpolator m_scale_x; dda2_line_interpolator m_scale_y; }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_basics.h��������������������������������������������������0000644�0024617�0000144�00000040665�12261257215�021734� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_BASICS_INCLUDED #define AGG_BASICS_INCLUDED #include <math.h> #include "agg_config.h" //---------------------------------------------------------AGG_CUSTOM_ALLOCATOR #ifdef AGG_CUSTOM_ALLOCATOR #include "agg_allocator.h" #else namespace mapserver { // The policy of all AGG containers and memory allocation strategy // in general is that no allocated data requires explicit construction. // It means that the allocator can be really simple; you can even // replace new/delete to malloc/free. The constructors and destructors // won't be called in this case, however everything will remain working. // The second argument of deallocate() is the size of the allocated // block. You can use this information if you wish. //------------------------------------------------------------pod_allocator template<class T> struct pod_allocator { static T* allocate(unsigned num) { return new T [num]; } static void deallocate(T* ptr, unsigned) { delete [] ptr; } }; // Single object allocator. It's also can be replaced with your custom // allocator. The difference is that it can only allocate a single // object and the constructor and destructor must be called. // In AGG there is no need to allocate an array of objects with // calling their constructors (only single ones). So that, if you // replace these new/delete to malloc/free make sure that the in-place // new is called and take care of calling the destructor too. //------------------------------------------------------------obj_allocator template<class T> struct obj_allocator { static T* allocate() { return new T; } static void deallocate(T* ptr) { delete ptr; } }; } #endif //-------------------------------------------------------- Default basic types // // If the compiler has different capacity of the basic types you can redefine // them via the compiler command line or by generating agg_config.h that is // empty by default. // #ifndef AGG_INT8 #define AGG_INT8 signed char #endif #ifndef AGG_INT8U #define AGG_INT8U unsigned char #endif #ifndef AGG_INT16 #define AGG_INT16 short #endif #ifndef AGG_INT16U #define AGG_INT16U unsigned short #endif #ifndef AGG_INT32 #define AGG_INT32 int #endif #ifndef AGG_INT32U #define AGG_INT32U unsigned #endif #ifndef AGG_INT64 #if defined(_MSC_VER) || defined(__BORLANDC__) #define AGG_INT64 signed __int64 #else #define AGG_INT64 signed long long #endif #endif #ifndef AGG_INT64U #if defined(_MSC_VER) || defined(__BORLANDC__) #define AGG_INT64U unsigned __int64 #else #define AGG_INT64U unsigned long long #endif #endif //------------------------------------------------ Some fixes for MS Visual C++ #if defined(_MSC_VER) #pragma warning(disable:4786) // Identifier was truncated... #endif #if defined(_MSC_VER) #define AGG_INLINE __forceinline #else #define AGG_INLINE inline #endif namespace mapserver { //------------------------------------------------------------------------- typedef AGG_INT8 int8; //----int8 typedef AGG_INT8U int8u; //----int8u typedef AGG_INT16 int16; //----int16 typedef AGG_INT16U int16u; //----int16u typedef AGG_INT32 int32; //----int32 typedef AGG_INT32U int32u; //----int32u typedef AGG_INT64 int64; //----int64 typedef AGG_INT64U int64u; //----int64u #if defined(AGG_FISTP) #pragma warning(push) #pragma warning(disable : 4035) //Disable warning "no return value" AGG_INLINE int iround(double v) //-------iround { int t; __asm fld qword ptr [v] __asm fistp dword ptr [t] __asm mov eax, dword ptr [t] } AGG_INLINE unsigned uround(double v) //-------uround { unsigned t; __asm fld qword ptr [v] __asm fistp dword ptr [t] __asm mov eax, dword ptr [t] } #pragma warning(pop) AGG_INLINE unsigned ufloor(double v) //-------ufloor { return unsigned(floor(v)); } AGG_INLINE unsigned uceil(double v) //--------uceil { return unsigned(ceil(v)); } #elif defined(AGG_QIFIST) AGG_INLINE int iround(double v) { return int(v); } AGG_INLINE int uround(double v) { return unsigned(v); } AGG_INLINE unsigned ufloor(double v) { return unsigned(floor(v)); } AGG_INLINE unsigned uceil(double v) { return unsigned(ceil(v)); } #else AGG_INLINE int iround(double v) { return int((v < 0.0) ? v - 0.5 : v + 0.5); } AGG_INLINE int uround(double v) { return unsigned(v + 0.5); } AGG_INLINE unsigned ufloor(double v) { return unsigned(v); } AGG_INLINE unsigned uceil(double v) { return unsigned(ceil(v)); } #endif //---------------------------------------------------------------saturation template<int Limit> struct saturation { AGG_INLINE static int iround(double v) { if(v < double(-Limit)) return -Limit; if(v > double( Limit)) return Limit; return mapserver::iround(v); } }; //------------------------------------------------------------------mul_one template<unsigned Shift> struct mul_one { AGG_INLINE static unsigned mul(unsigned a, unsigned b) { register unsigned q = a * b + (1 << (Shift-1)); return (q + (q >> Shift)) >> Shift; } }; //------------------------------------------------------------------------- typedef unsigned char cover_type; //----cover_type enum cover_scale_e { cover_shift = 8, //----cover_shift cover_size = 1 << cover_shift, //----cover_size cover_mask = cover_size - 1, //----cover_mask cover_none = 0, //----cover_none cover_full = cover_mask //----cover_full }; //----------------------------------------------------poly_subpixel_scale_e // These constants determine the subpixel accuracy, to be more precise, // the number of bits of the fractional part of the coordinates. // The possible coordinate capacity in bits can be calculated by formula: // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and // 8-bits fractional part the capacity is 24 bits. enum poly_subpixel_scale_e { poly_subpixel_shift = 8, //----poly_subpixel_shift poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask }; //----------------------------------------------------------filling_rule_e enum filling_rule_e { fill_non_zero, fill_even_odd }; //-----------------------------------------------------------------------pi const double pi = 3.14159265358979323846; //------------------------------------------------------------------deg2rad inline double deg2rad(double deg) { return deg * pi / 180.0; } //------------------------------------------------------------------rad2deg inline double rad2deg(double rad) { return rad * 180.0 / pi; } //----------------------------------------------------------------rect_base template<class T> struct rect_base { typedef T value_type; typedef rect_base<T> self_type; T x1, y1, x2, y2; rect_base() {} rect_base(T x1_, T y1_, T x2_, T y2_) : x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} void init(T x1_, T y1_, T x2_, T y2_) { x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; } const self_type& normalize() { T t; if(x1 > x2) { t = x1; x1 = x2; x2 = t; } if(y1 > y2) { t = y1; y1 = y2; y2 = t; } return *this; } bool clip(const self_type& r) { if(x2 > r.x2) x2 = r.x2; if(y2 > r.y2) y2 = r.y2; if(x1 < r.x1) x1 = r.x1; if(y1 < r.y1) y1 = r.y1; return x1 <= x2 && y1 <= y2; } bool is_valid() const { return x1 <= x2 && y1 <= y2; } bool hit_test(T x, T y) const { return (x >= x1 && x <= x2 && y >= y1 && y <= y2); } }; //-----------------------------------------------------intersect_rectangles template<class Rect> inline Rect intersect_rectangles(const Rect& r1, const Rect& r2) { Rect r = r1; // First process x2,y2 because the other order // results in Internal Compiler Error under // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in // case of "Maximize Speed" optimization option. //----------------- if(r.x2 > r2.x2) r.x2 = r2.x2; if(r.y2 > r2.y2) r.y2 = r2.y2; if(r.x1 < r2.x1) r.x1 = r2.x1; if(r.y1 < r2.y1) r.y1 = r2.y1; return r; } //---------------------------------------------------------unite_rectangles template<class Rect> inline Rect unite_rectangles(const Rect& r1, const Rect& r2) { Rect r = r1; if(r.x2 < r2.x2) r.x2 = r2.x2; if(r.y2 < r2.y2) r.y2 = r2.y2; if(r.x1 > r2.x1) r.x1 = r2.x1; if(r.y1 > r2.y1) r.y1 = r2.y1; return r; } typedef rect_base<int> rect_i; //----rect_i typedef rect_base<float> rect_f; //----rect_f typedef rect_base<double> rect_d; //----rect_d //---------------------------------------------------------path_commands_e enum path_commands_e { path_cmd_stop = 0, //----path_cmd_stop path_cmd_move_to = 1, //----path_cmd_move_to path_cmd_line_to = 2, //----path_cmd_line_to path_cmd_curve3 = 3, //----path_cmd_curve3 path_cmd_curve4 = 4, //----path_cmd_curve4 path_cmd_curveN = 5, //----path_cmd_curveN path_cmd_catrom = 6, //----path_cmd_catrom path_cmd_ubspline = 7, //----path_cmd_ubspline path_cmd_end_poly = 0x0F, //----path_cmd_end_poly path_cmd_mask = 0x0F //----path_cmd_mask }; //------------------------------------------------------------path_flags_e enum path_flags_e { path_flags_none = 0, //----path_flags_none path_flags_ccw = 0x10, //----path_flags_ccw path_flags_cw = 0x20, //----path_flags_cw path_flags_close = 0x40, //----path_flags_close path_flags_mask = 0xF0 //----path_flags_mask }; //---------------------------------------------------------------is_vertex inline bool is_vertex(unsigned c) { return c >= path_cmd_move_to && c < path_cmd_end_poly; } //--------------------------------------------------------------is_drawing inline bool is_drawing(unsigned c) { return c >= path_cmd_line_to && c < path_cmd_end_poly; } //-----------------------------------------------------------------is_stop inline bool is_stop(unsigned c) { return c == path_cmd_stop; } //--------------------------------------------------------------is_move_to inline bool is_move_to(unsigned c) { return c == path_cmd_move_to; } //--------------------------------------------------------------is_line_to inline bool is_line_to(unsigned c) { return c == path_cmd_line_to; } //----------------------------------------------------------------is_curve inline bool is_curve(unsigned c) { return c == path_cmd_curve3 || c == path_cmd_curve4; } //---------------------------------------------------------------is_curve3 inline bool is_curve3(unsigned c) { return c == path_cmd_curve3; } //---------------------------------------------------------------is_curve4 inline bool is_curve4(unsigned c) { return c == path_cmd_curve4; } //-------------------------------------------------------------is_end_poly inline bool is_end_poly(unsigned c) { return (c & path_cmd_mask) == path_cmd_end_poly; } //----------------------------------------------------------------is_close inline bool is_close(unsigned c) { return (c & ~(path_flags_cw | path_flags_ccw)) == (path_cmd_end_poly | path_flags_close); } //------------------------------------------------------------is_next_poly inline bool is_next_poly(unsigned c) { return is_stop(c) || is_move_to(c) || is_end_poly(c); } //-------------------------------------------------------------------is_cw inline bool is_cw(unsigned c) { return (c & path_flags_cw) != 0; } //------------------------------------------------------------------is_ccw inline bool is_ccw(unsigned c) { return (c & path_flags_ccw) != 0; } //-------------------------------------------------------------is_oriented inline bool is_oriented(unsigned c) { return (c & (path_flags_cw | path_flags_ccw)) != 0; } //---------------------------------------------------------------is_closed inline bool is_closed(unsigned c) { return (c & path_flags_close) != 0; } //----------------------------------------------------------get_close_flag inline unsigned get_close_flag(unsigned c) { return c & path_flags_close; } //-------------------------------------------------------clear_orientation inline unsigned clear_orientation(unsigned c) { return c & ~(path_flags_cw | path_flags_ccw); } //---------------------------------------------------------get_orientation inline unsigned get_orientation(unsigned c) { return c & (path_flags_cw | path_flags_ccw); } //---------------------------------------------------------set_orientation inline unsigned set_orientation(unsigned c, unsigned o) { return clear_orientation(c) | o; } //--------------------------------------------------------------point_base template<class T> struct point_base { typedef T value_type; T x,y; point_base() {} point_base(T x_, T y_) : x(x_), y(y_) {} }; typedef point_base<int> point_i; //-----point_i typedef point_base<float> point_f; //-----point_f typedef point_base<double> point_d; //-----point_d //-------------------------------------------------------------vertex_base template<class T> struct vertex_base { typedef T value_type; T x,y; unsigned cmd; vertex_base() {} vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {} }; typedef vertex_base<int> vertex_i; //-----vertex_i typedef vertex_base<float> vertex_f; //-----vertex_f typedef vertex_base<double> vertex_d; //-----vertex_d //----------------------------------------------------------------row_info template<class T> struct row_info { int x1, x2; T* ptr; row_info() {} row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {} }; //----------------------------------------------------------const_row_info template<class T> struct const_row_info { int x1, x2; const T* ptr; const_row_info() {} const_row_info(int x1_, int x2_, const T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {} }; //------------------------------------------------------------is_equal_eps template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon) { return fabs(v1 - v2) <= double(epsilon); } } #endif ���������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_marker_adaptor.h�������������������������������������0000644�0024617�0000144�00000003511�12261257215�024475� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED #define AGG_CONV_MARKER_ADAPTOR_INCLUDED #include "agg_basics.h" #include "agg_conv_adaptor_vcgen.h" #include "agg_vcgen_vertex_sequence.h" namespace mapserver { //=====================================================conv_marker_adaptor template<class VertexSource, class Markers=null_markers> struct conv_marker_adaptor : public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> { typedef Markers marker_type; typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type; conv_marker_adaptor(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs) { } void shorten(double s) { base_type::generator().shorten(s); } double shorten() const { return base_type::generator().shorten(); } private: conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&); const conv_marker_adaptor<VertexSource, Markers>& operator = (const conv_marker_adaptor<VertexSource, Markers>&); }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_color_gray.h����������������������������������������������0000644�0024617�0000144�00000032547�12261257215�022630� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- // // color types gray8, gray16 // //---------------------------------------------------------------------------- #ifndef AGG_COLOR_GRAY_INCLUDED #define AGG_COLOR_GRAY_INCLUDED #include "agg_basics.h" #include "agg_color_rgba.h" namespace mapserver { //===================================================================gray8 struct gray8 { typedef int8u value_type; typedef int32u calc_type; typedef int32 long_type; enum base_scale_e { base_shift = 8, base_scale = 1 << base_shift, base_mask = base_scale - 1 }; typedef gray8 self_type; value_type v; value_type a; //-------------------------------------------------------------------- gray8() {} //-------------------------------------------------------------------- gray8(unsigned v_, unsigned a_=base_mask) : v(int8u(v_)), a(int8u(a_)) {} //-------------------------------------------------------------------- gray8(const self_type& c, unsigned a_) : v(c.v), a(value_type(a_)) {} //-------------------------------------------------------------------- gray8(const rgba& c) : v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- gray8(const rgba& c, double a_) : v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- gray8(const rgba8& c) : v((c.r*77 + c.g*150 + c.b*29) >> 8), a(c.a) {} //-------------------------------------------------------------------- gray8(const rgba8& c, unsigned a_) : v((c.r*77 + c.g*150 + c.b*29) >> 8), a(a_) {} //-------------------------------------------------------------------- void clear() { v = a = 0; } //-------------------------------------------------------------------- const self_type& transparent() { a = 0; return *this; } //-------------------------------------------------------------------- void opacity(double a_) { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; a = (value_type)uround(a_ * double(base_mask)); } //-------------------------------------------------------------------- double opacity() const { return double(a) / double(base_mask); } //-------------------------------------------------------------------- const self_type& premultiply() { if(a == base_mask) return *this; if(a == 0) { v = 0; return *this; } v = value_type((calc_type(v) * a) >> base_shift); return *this; } //-------------------------------------------------------------------- const self_type& premultiply(unsigned a_) { if(a == base_mask && a_ >= base_mask) return *this; if(a == 0 || a_ == 0) { v = a = 0; return *this; } calc_type v_ = (calc_type(v) * a_) / a; v = value_type((v_ > a_) ? a_ : v_); a = value_type(a_); return *this; } //-------------------------------------------------------------------- const self_type& demultiply() { if(a == base_mask) return *this; if(a == 0) { v = 0; return *this; } calc_type v_ = (calc_type(v) * base_mask) / a; v = value_type((v_ > base_mask) ? (value_type)base_mask : v_); return *this; } //-------------------------------------------------------------------- self_type gradient(self_type c, double k) const { self_type ret; calc_type ik = uround(k * base_scale); ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); return ret; } //-------------------------------------------------------------------- AGG_INLINE void add(const self_type& c, unsigned cover) { calc_type cv, ca; if(cover == cover_mask) { if(c.a == base_mask) { *this = c; } else { cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } else { cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } //-------------------------------------------------------------------- static self_type no_color() { return self_type(0,0); } }; //-------------------------------------------------------------gray8_pre inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask) { return gray8(v,a).premultiply(); } inline gray8 gray8_pre(const gray8& c, unsigned a) { return gray8(c,a).premultiply(); } inline gray8 gray8_pre(const rgba& c) { return gray8(c).premultiply(); } inline gray8 gray8_pre(const rgba& c, double a) { return gray8(c,a).premultiply(); } inline gray8 gray8_pre(const rgba8& c) { return gray8(c).premultiply(); } inline gray8 gray8_pre(const rgba8& c, unsigned a) { return gray8(c,a).premultiply(); } //==================================================================gray16 struct gray16 { typedef int16u value_type; typedef int32u calc_type; typedef int64 long_type; enum base_scale_e { base_shift = 16, base_scale = 1 << base_shift, base_mask = base_scale - 1 }; typedef gray16 self_type; value_type v; value_type a; //-------------------------------------------------------------------- gray16() {} //-------------------------------------------------------------------- gray16(unsigned v_, unsigned a_=base_mask) : v(int16u(v_)), a(int16u(a_)) {} //-------------------------------------------------------------------- gray16(const self_type& c, unsigned a_) : v(c.v), a(value_type(a_)) {} //-------------------------------------------------------------------- gray16(const rgba& c) : v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- gray16(const rgba& c, double a_) : v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- gray16(const rgba8& c) : v(c.r*77 + c.g*150 + c.b*29), a((value_type(c.a) << 8) | c.a) {} //-------------------------------------------------------------------- gray16(const rgba8& c, unsigned a_) : v(c.r*77 + c.g*150 + c.b*29), a((value_type(a_) << 8) | c.a) {} //-------------------------------------------------------------------- void clear() { v = a = 0; } //-------------------------------------------------------------------- const self_type& transparent() { a = 0; return *this; } //-------------------------------------------------------------------- void opacity(double a_) { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; a = (value_type)uround(a_ * double(base_mask)); } //-------------------------------------------------------------------- double opacity() const { return double(a) / double(base_mask); } //-------------------------------------------------------------------- const self_type& premultiply() { if(a == base_mask) return *this; if(a == 0) { v = 0; return *this; } v = value_type((calc_type(v) * a) >> base_shift); return *this; } //-------------------------------------------------------------------- const self_type& premultiply(unsigned a_) { if(a == base_mask && a_ >= base_mask) return *this; if(a == 0 || a_ == 0) { v = a = 0; return *this; } calc_type v_ = (calc_type(v) * a_) / a; v = value_type((v_ > a_) ? a_ : v_); a = value_type(a_); return *this; } //-------------------------------------------------------------------- const self_type& demultiply() { if(a == base_mask) return *this; if(a == 0) { v = 0; return *this; } calc_type v_ = (calc_type(v) * base_mask) / a; v = value_type((v_ > base_mask) ? base_mask : v_); return *this; } //-------------------------------------------------------------------- self_type gradient(self_type c, double k) const { self_type ret; calc_type ik = uround(k * base_scale); ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); return ret; } //-------------------------------------------------------------------- AGG_INLINE void add(const self_type& c, unsigned cover) { calc_type cv, ca; if(cover == cover_mask) { if(c.a == base_mask) { *this = c; } else { cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } else { cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; } } //-------------------------------------------------------------------- static self_type no_color() { return self_type(0,0); } }; //------------------------------------------------------------gray16_pre inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask) { return gray16(v,a).premultiply(); } inline gray16 gray16_pre(const gray16& c, unsigned a) { return gray16(c,a).premultiply(); } inline gray16 gray16_pre(const rgba& c) { return gray16(c).premultiply(); } inline gray16 gray16_pre(const rgba& c, double a) { return gray16(c,a).premultiply(); } inline gray16 gray16_pre(const rgba8& c) { return gray16(c).premultiply(); } inline gray16 gray16_pre(const rgba8& c, unsigned a) { return gray16(c,a).premultiply(); } } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_svg_path_renderer.h���������������������������������������0000644�0024617�0000144�00000025732�12261257215�024167� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // SVG path renderer. // //---------------------------------------------------------------------------- #ifndef AGG_SVG_PATH_RENDERER_INCLUDED #define AGG_SVG_PATH_RENDERER_INCLUDED #include "agg_path_storage.h" #include "agg_conv_transform.h" #include "agg_conv_stroke.h" #include "agg_conv_contour.h" #include "agg_conv_curve.h" #include "agg_color_rgba.h" #include "agg_renderer_scanline.h" #include "agg_bounding_rect.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_svg_path_tokenizer.h" namespace mapserver { namespace svg { template<class VertexSource> class conv_count { public: conv_count(VertexSource& vs) : m_source(&vs), m_count(0) {} void count(unsigned n) { m_count = n; } unsigned count() const { return m_count; } void rewind(unsigned path_id) { m_source->rewind(path_id); } unsigned vertex(double* x, double* y) { ++m_count; return m_source->vertex(x, y); } private: VertexSource* m_source; unsigned m_count; }; //============================================================================ // Basic path attributes struct path_attributes { unsigned index; rgba8 fill_color; rgba8 stroke_color; bool fill_flag; bool stroke_flag; bool even_odd_flag; line_join_e line_join; line_cap_e line_cap; double miter_limit; double stroke_width; trans_affine transform; // Empty constructor path_attributes() : index(0), fill_color(rgba(0,0,0)), stroke_color(rgba(0,0,0)), fill_flag(true), stroke_flag(false), even_odd_flag(false), line_join(miter_join), line_cap(butt_cap), miter_limit(4.0), stroke_width(1.0), transform() { } // Copy constructor path_attributes(const path_attributes& attr) : index(attr.index), fill_color(attr.fill_color), stroke_color(attr.stroke_color), fill_flag(attr.fill_flag), stroke_flag(attr.stroke_flag), even_odd_flag(attr.even_odd_flag), line_join(attr.line_join), line_cap(attr.line_cap), miter_limit(attr.miter_limit), stroke_width(attr.stroke_width), transform(attr.transform) { } // Copy constructor with new index value path_attributes(const path_attributes& attr, unsigned idx) : index(idx), fill_color(attr.fill_color), stroke_color(attr.stroke_color), fill_flag(attr.fill_flag), stroke_flag(attr.stroke_flag), even_odd_flag(attr.even_odd_flag), line_join(attr.line_join), line_cap(attr.line_cap), miter_limit(attr.miter_limit), stroke_width(attr.stroke_width), transform(attr.transform) { } }; //============================================================================ // Path container and renderer. class path_renderer { public: typedef pod_bvector<path_attributes> attr_storage; typedef conv_curve<path_storage> curved; typedef conv_count<curved> curved_count; typedef conv_stroke<curved_count> curved_stroked; typedef conv_transform<curved_stroked> curved_stroked_trans; typedef conv_transform<curved_count> curved_trans; typedef conv_contour<curved_trans> curved_trans_contour; path_renderer(); void remove_all(); // Use these functions as follows: // begin_path() when the XML tag <path> comes ("start_element" handler) // parse_path() on "d=" tag attribute // end_path() when parsing of the entire tag is done. void begin_path(); void parse_path(path_tokenizer& tok); void end_path(); // The following functions are essentially a "reflection" of // the respective SVG path commands. void move_to(double x, double y, bool rel=false); // M, m void line_to(double x, double y, bool rel=false); // L, l void hline_to(double x, bool rel=false); // H, h void vline_to(double y, bool rel=false); // V, v void curve3(double x1, double y1, // Q, q double x, double y, bool rel=false); void curve3(double x, double y, bool rel=false); // T, t void curve4(double x1, double y1, // C, c double x2, double y2, double x, double y, bool rel=false); void curve4(double x2, double y2, // S, s double x, double y, bool rel=false); void close_subpath(); // Z, z // template<class VertexSource> // void add_path(VertexSource& vs, // unsigned path_id = 0, // bool solid_path = true) // { // m_storage.add_path(vs, path_id, solid_path); // } unsigned vertex_count() const { return m_curved_count.count(); } // Call these functions on <g> tag (start_element, end_element respectively) void push_attr(); void pop_attr(); // Attribute setting functions. void fill(const rgba8& f); void stroke(const rgba8& s); void even_odd(bool flag); void stroke_width(double w); void fill_none(); void stroke_none(); void fill_opacity(double op); void stroke_opacity(double op); void line_join(line_join_e join); void line_cap(line_cap_e cap); void miter_limit(double ml); trans_affine& transform(); // Make all polygons CCW-oriented void arrange_orientations() { m_storage.arrange_orientations_all_paths(path_flags_ccw); } // Expand all polygons void expand(double value) { m_curved_trans_contour.width(value); } unsigned operator [](unsigned idx) { m_transform = m_attr_storage[idx].transform; return m_attr_storage[idx].index; } void bounding_rect(double* x1, double* y1, double* x2, double* y2) { mapserver::conv_transform<mapserver::path_storage> trans(m_storage, m_transform); mapserver::bounding_rect(trans, *this, 0, m_attr_storage.size(), x1, y1, x2, y2); } // Rendering. One can specify two additional parameters: // trans_affine and opacity. They can be used to transform the whole // image and/or to make it translucent. template<class Rasterizer, class Scanline, class Renderer> void render(Rasterizer& ras, Scanline& sl, Renderer& ren, const trans_affine& mtx, const rect_i& cb, double opacity=1.0) { unsigned i; ras.clip_box(cb.x1, cb.y1, cb.x2, cb.y2); m_curved_count.count(0); for(i = 0; i < m_attr_storage.size(); i++) { const path_attributes& attr = m_attr_storage[i]; m_transform = attr.transform; m_transform *= mtx; double scl = m_transform.scale(); //m_curved.approximation_method(curve_inc); m_curved.approximation_scale(scl); m_curved.angle_tolerance(0.0); rgba8 color; if(attr.fill_flag) { ras.reset(); ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero); if(fabs(m_curved_trans_contour.width()) < 0.0001) { ras.add_path(m_curved_trans, attr.index); } else { m_curved_trans_contour.miter_limit(attr.miter_limit); ras.add_path(m_curved_trans_contour, attr.index); } color = attr.fill_color; color.opacity(color.opacity() * opacity); ren.color(color); mapserver::render_scanlines(ras, sl, ren); } if(attr.stroke_flag) { m_curved_stroked.width(attr.stroke_width); //m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join); m_curved_stroked.line_join(attr.line_join); m_curved_stroked.line_cap(attr.line_cap); m_curved_stroked.miter_limit(attr.miter_limit); m_curved_stroked.inner_join(inner_round); m_curved_stroked.approximation_scale(scl); // If the *visual* line width is considerable we // turn on processing of curve cusps. //--------------------- if(attr.stroke_width * scl > 1.0) { m_curved.angle_tolerance(0.2); } ras.reset(); ras.filling_rule(fill_non_zero); ras.add_path(m_curved_stroked_trans, attr.index); color = attr.stroke_color; color.opacity(color.opacity() * opacity); ren.color(color); mapserver::render_scanlines(ras, sl, ren); } } } private: path_attributes& cur_attr(); path_storage m_storage; attr_storage m_attr_storage; attr_storage m_attr_stack; trans_affine m_transform; curved m_curved; curved_count m_curved_count; curved_stroked m_curved_stroked; curved_stroked_trans m_curved_stroked_trans; curved_trans m_curved_trans; curved_trans_contour m_curved_trans_contour; }; } } #endif ��������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vpgen_segmentator.h���������������������������������������0000644�0024617�0000144�00000003417�12261257215�024211� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VPGEN_SEGMENTATOR_INCLUDED #define AGG_VPGEN_SEGMENTATOR_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { //=======================================================vpgen_segmentator // // See Implementation agg_vpgen_segmentator.cpp // class vpgen_segmentator { public: vpgen_segmentator() : m_approximation_scale(1.0) {} void approximation_scale(double s) { m_approximation_scale = s; } double approximation_scale() const { return m_approximation_scale; } static bool auto_close() { return false; } static bool auto_unclose() { return false; } void reset() { m_cmd = path_cmd_stop; } void move_to(double x, double y); void line_to(double x, double y); unsigned vertex(double* x, double* y); private: double m_approximation_scale; double m_x1; double m_y1; double m_dx; double m_dy; double m_dl; double m_ddl; unsigned m_cmd; }; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_span_pattern_gray.h���������������������������������������0000644�0024617�0000144�00000006332�12261257215�024201� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SPAN_PATTERN_GRAY_INCLUDED #define AGG_SPAN_PATTERN_GRAY_INCLUDED #include "agg_basics.h" namespace mapserver { //=======================================================span_pattern_gray template<class Source> class span_pattern_gray { public: typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; //-------------------------------------------------------------------- span_pattern_gray() {} span_pattern_gray(source_type& src, unsigned offset_x, unsigned offset_y) : m_src(&src), m_offset_x(offset_x), m_offset_y(offset_y), m_alpha(color_type::base_mask) {} //-------------------------------------------------------------------- void attach(source_type& v) { m_src = &v; } source_type& source() { return *m_src; } const source_type& source() const { return *m_src; } //-------------------------------------------------------------------- void offset_x(unsigned v) { m_offset_x = v; } void offset_y(unsigned v) { m_offset_y = v; } unsigned offset_x() const { return m_offset_x; } unsigned offset_y() const { return m_offset_y; } void alpha(value_type v) { m_alpha = v; } value_type alpha() const { return m_alpha; } //-------------------------------------------------------------------- void prepare() {} void generate(color_type* span, int x, int y, unsigned len) { x += m_offset_x; y += m_offset_y; const value_type* p = (const value_type*)m_src->span(x, y, len); do { span->v = *p; span->a = m_alpha; p = m_src->next_x(); ++span; } while(--len); } private: source_type* m_src; unsigned m_offset_x; unsigned m_offset_y; value_type m_alpha; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_path_storage.h��������������������������������������������0000644�0024617�0000144�00000142213�12261257215�023140� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_PATH_STORAGE_INCLUDED #define AGG_PATH_STORAGE_INCLUDED #include <string.h> #include <math.h> #include "agg_math.h" #include "agg_array.h" #include "agg_bezier_arc.h" namespace mapserver { //----------------------------------------------------vertex_block_storage template<class T, unsigned BlockShift=8, unsigned BlockPool=256> class vertex_block_storage { public: // Allocation parameters enum block_scale_e { block_shift = BlockShift, block_size = 1 << block_shift, block_mask = block_size - 1, block_pool = BlockPool }; typedef T value_type; typedef vertex_block_storage<T, BlockShift, BlockPool> self_type; ~vertex_block_storage(); vertex_block_storage(); vertex_block_storage(const self_type& v); const self_type& operator = (const self_type& ps); void remove_all(); void free_all(); void add_vertex(double x, double y, unsigned cmd); void modify_vertex(unsigned idx, double x, double y); void modify_vertex(unsigned idx, double x, double y, unsigned cmd); void modify_command(unsigned idx, unsigned cmd); void swap_vertices(unsigned v1, unsigned v2); unsigned last_command() const; unsigned last_vertex(double* x, double* y) const; unsigned prev_vertex(double* x, double* y) const; double last_x() const; double last_y() const; unsigned total_vertices() const; unsigned vertex(unsigned idx, double* x, double* y) const; unsigned command(unsigned idx) const; private: void allocate_block(unsigned nb); int8u* storage_ptrs(T** xy_ptr); private: unsigned m_total_vertices; unsigned m_total_blocks; unsigned m_max_blocks; T** m_coord_blocks; int8u** m_cmd_blocks; }; //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> void vertex_block_storage<T,S,P>::free_all() { if(m_total_blocks) { T** coord_blk = m_coord_blocks + m_total_blocks - 1; while(m_total_blocks--) { pod_allocator<T>::deallocate( *coord_blk, block_size * 2 + block_size / (sizeof(T) / sizeof(unsigned char))); --coord_blk; } pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); m_total_blocks = 0; m_max_blocks = 0; m_coord_blocks = 0; m_cmd_blocks = 0; m_total_vertices = 0; } } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> vertex_block_storage<T,S,P>::~vertex_block_storage() { free_all(); } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> vertex_block_storage<T,S,P>::vertex_block_storage() : m_total_vertices(0), m_total_blocks(0), m_max_blocks(0), m_coord_blocks(0), m_cmd_blocks(0) { } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) : m_total_vertices(0), m_total_blocks(0), m_max_blocks(0), m_coord_blocks(0), m_cmd_blocks(0) { *this = v; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> const vertex_block_storage<T,S,P>& vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v) { remove_all(); unsigned i; for(i = 0; i < v.total_vertices(); i++) { double x, y; unsigned cmd = v.vertex(i, &x, &y); add_vertex(x, y, cmd); } return *this; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::remove_all() { m_total_vertices = 0; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y, unsigned cmd) { T* coord_ptr = 0; *storage_ptrs(&coord_ptr) = (int8u)cmd; coord_ptr[0] = T(x); coord_ptr[1] = T(y); m_total_vertices++; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, double x, double y) { T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); pv[0] = T(x); pv[1] = T(y); } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, double x, double y, unsigned cmd) { unsigned block = idx >> block_shift; unsigned offset = idx & block_mask; T* pv = m_coord_blocks[block] + (offset << 1); pv[0] = T(x); pv[1] = T(y); m_cmd_blocks[block][offset] = (int8u)cmd; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx, unsigned cmd) { m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2) { unsigned b1 = v1 >> block_shift; unsigned b2 = v2 >> block_shift; unsigned o1 = v1 & block_mask; unsigned o2 = v2 & block_mask; T* pv1 = m_coord_blocks[b1] + (o1 << 1); T* pv2 = m_coord_blocks[b2] + (o2 << 1); T val; val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; int8u cmd = m_cmd_blocks[b1][o1]; m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; m_cmd_blocks[b2][o2] = cmd; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::last_command() const { if(m_total_vertices) return command(m_total_vertices - 1); return path_cmd_stop; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const { if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); return path_cmd_stop; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const { if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); return path_cmd_stop; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline double vertex_block_storage<T,S,P>::last_x() const { if(m_total_vertices) { unsigned idx = m_total_vertices - 1; return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; } return 0.0; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline double vertex_block_storage<T,S,P>::last_y() const { if(m_total_vertices) { unsigned idx = m_total_vertices - 1; return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; } return 0.0; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::total_vertices() const { return m_total_vertices; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx, double* x, double* y) const { unsigned nb = idx >> block_shift; const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); *x = pv[0]; *y = pv[1]; return m_cmd_blocks[nb][idx & block_mask]; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const { return m_cmd_blocks[idx >> block_shift][idx & block_mask]; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> void vertex_block_storage<T,S,P>::allocate_block(unsigned nb) { if(nb >= m_max_blocks) { T** new_coords = pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2); unsigned char** new_cmds = (unsigned char**)(new_coords + m_max_blocks + block_pool); if(m_coord_blocks) { memcpy(new_coords, m_coord_blocks, m_max_blocks * sizeof(T*)); memcpy(new_cmds, m_cmd_blocks, m_max_blocks * sizeof(unsigned char*)); pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); } m_coord_blocks = new_coords; m_cmd_blocks = new_cmds; m_max_blocks += block_pool; } m_coord_blocks[nb] = pod_allocator<T>::allocate(block_size * 2 + block_size / (sizeof(T) / sizeof(unsigned char))); m_cmd_blocks[nb] = (unsigned char*)(m_coord_blocks[nb] + block_size * 2); m_total_blocks++; } //------------------------------------------------------------------------ template<class T, unsigned S, unsigned P> int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr) { unsigned nb = m_total_vertices >> block_shift; if(nb >= m_total_blocks) { allocate_block(nb); } *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); return m_cmd_blocks[nb] + (m_total_vertices & block_mask); } //-----------------------------------------------------poly_plain_adaptor template<class T> class poly_plain_adaptor { public: typedef T value_type; poly_plain_adaptor() : m_data(0), m_ptr(0), m_end(0), m_closed(false), m_stop(false) {} poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : m_data(data), m_ptr(data), m_end(data + num_points * 2), m_closed(closed), m_stop(false) {} void init(const T* data, unsigned num_points, bool closed) { m_data = data; m_ptr = data; m_end = data + num_points * 2; m_closed = closed; m_stop = false; } void rewind(unsigned) { m_ptr = m_data; m_stop = false; } unsigned vertex(double* x, double* y) { if(m_ptr < m_end) { bool first = m_ptr == m_data; *x = *m_ptr++; *y = *m_ptr++; return first ? path_cmd_move_to : path_cmd_line_to; } *x = *y = 0.0; if(m_closed && !m_stop) { m_stop = true; return path_cmd_end_poly | path_flags_close; } return path_cmd_stop; } private: const T* m_data; const T* m_ptr; const T* m_end; bool m_closed; bool m_stop; }; //-------------------------------------------------poly_container_adaptor template<class Container> class poly_container_adaptor { public: typedef typename Container::value_type vertex_type; poly_container_adaptor() : m_container(0), m_index(0), m_closed(false), m_stop(false) {} poly_container_adaptor(const Container& data, bool closed) : m_container(&data), m_index(0), m_closed(closed), m_stop(false) {} void init(const Container& data, bool closed) { m_container = &data; m_index = 0; m_closed = closed; m_stop = false; } void rewind(unsigned) { m_index = 0; m_stop = false; } unsigned vertex(double* x, double* y) { if(m_index < m_container->size()) { bool first = m_index == 0; const vertex_type& v = (*m_container)[m_index++]; *x = v.x; *y = v.y; return first ? path_cmd_move_to : path_cmd_line_to; } *x = *y = 0.0; if(m_closed && !m_stop) { m_stop = true; return path_cmd_end_poly | path_flags_close; } return path_cmd_stop; } private: const Container* m_container; unsigned m_index; bool m_closed; bool m_stop; }; //-----------------------------------------poly_container_reverse_adaptor template<class Container> class poly_container_reverse_adaptor { public: typedef typename Container::value_type vertex_type; poly_container_reverse_adaptor() : m_container(0), m_index(-1), m_closed(false), m_stop(false) {} poly_container_reverse_adaptor(const Container& data, bool closed) : m_container(&data), m_index(-1), m_closed(closed), m_stop(false) {} void init(const Container& data, bool closed) { m_container = &data; m_index = m_container->size() - 1; m_closed = closed; m_stop = false; } void rewind(unsigned) { m_index = m_container->size() - 1; m_stop = false; } unsigned vertex(double* x, double* y) { if(m_index >= 0) { bool first = m_index == int(m_container->size() - 1); const vertex_type& v = (*m_container)[m_index--]; *x = v.x; *y = v.y; return first ? path_cmd_move_to : path_cmd_line_to; } *x = *y = 0.0; if(m_closed && !m_stop) { m_stop = true; return path_cmd_end_poly | path_flags_close; } return path_cmd_stop; } private: const Container* m_container; int m_index; bool m_closed; bool m_stop; }; //--------------------------------------------------------line_adaptor class line_adaptor { public: typedef double value_type; line_adaptor() : m_line(m_coord, 2, false) {} line_adaptor(double x1, double y1, double x2, double y2) : m_line(m_coord, 2, false) { m_coord[0] = x1; m_coord[1] = y1; m_coord[2] = x2; m_coord[3] = y2; } void init(double x1, double y1, double x2, double y2) { m_coord[0] = x1; m_coord[1] = y1; m_coord[2] = x2; m_coord[3] = y2; m_line.rewind(0); } void rewind(unsigned) { m_line.rewind(0); } unsigned vertex(double* x, double* y) { return m_line.vertex(x, y); } private: double m_coord[4]; poly_plain_adaptor<double> m_line; }; //---------------------------------------------------------------path_base // A container to store vertices with their flags. // A path consists of a number of contours separated with "move_to" // commands. The path storage can keep and maintain more than one // path. // To navigate to the beginning of a particular path, use rewind(path_id); // Where path_id is what start_new_path() returns. So, when you call // start_new_path() you need to store its return value somewhere else // to navigate to the path afterwards. // // See also: vertex_source concept //------------------------------------------------------------------------ template<class VertexContainer> class path_base { public: typedef VertexContainer container_type; typedef path_base<VertexContainer> self_type; //-------------------------------------------------------------------- path_base() : m_vertices(), m_iterator(0) {} void remove_all() { m_vertices.remove_all(); m_iterator = 0; } void free_all() { m_vertices.free_all(); m_iterator = 0; } // Make path functions //-------------------------------------------------------------------- unsigned start_new_path(); void move_to(double x, double y); void move_rel(double dx, double dy); void line_to(double x, double y); void line_rel(double dx, double dy); void hline_to(double x); void hline_rel(double dx); void vline_to(double y); void vline_rel(double dy); void arc_to(double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x, double y); void arc_rel(double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double dx, double dy); void curve3(double x_ctrl, double y_ctrl, double x_to, double y_to); void curve3_rel(double dx_ctrl, double dy_ctrl, double dx_to, double dy_to); void curve3(double x_to, double y_to); void curve3_rel(double dx_to, double dy_to); void curve4(double x_ctrl1, double y_ctrl1, double x_ctrl2, double y_ctrl2, double x_to, double y_to); void curve4_rel(double dx_ctrl1, double dy_ctrl1, double dx_ctrl2, double dy_ctrl2, double dx_to, double dy_to); void curve4(double x_ctrl2, double y_ctrl2, double x_to, double y_to); void curve4_rel(double x_ctrl2, double y_ctrl2, double x_to, double y_to); void end_poly(unsigned flags = path_flags_close); void close_polygon(unsigned flags = path_flags_none); // Accessors //-------------------------------------------------------------------- const container_type& vertices() const { return m_vertices; } container_type& vertices() { return m_vertices; } unsigned total_vertices() const; void rel_to_abs(double* x, double* y) const; unsigned last_vertex(double* x, double* y) const; unsigned prev_vertex(double* x, double* y) const; double last_x() const; double last_y() const; unsigned vertex(unsigned idx, double* x, double* y) const; unsigned command(unsigned idx) const; void modify_vertex(unsigned idx, double x, double y); void modify_vertex(unsigned idx, double x, double y, unsigned cmd); void modify_command(unsigned idx, unsigned cmd); // VertexSource interface //-------------------------------------------------------------------- void rewind(unsigned path_id); unsigned vertex(double* x, double* y); // Arrange the orientation of a polygon, all polygons in a path, // or in all paths. After calling arrange_orientations() or // arrange_orientations_all_paths(), all the polygons will have // the same orientation, i.e. path_flags_cw or path_flags_ccw //-------------------------------------------------------------------- unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation); unsigned arrange_orientations(unsigned path_id, path_flags_e orientation); void arrange_orientations_all_paths(path_flags_e orientation); void invert_polygon(unsigned start); // Flip all vertices horizontally or vertically, // between x1 and x2, or between y1 and y2 respectively //-------------------------------------------------------------------- void flip_x(double x1, double x2); void flip_y(double y1, double y2); // Concatenate path. The path is added as is. //-------------------------------------------------------------------- template<class VertexSource> void concat_path(VertexSource& vs, unsigned path_id = 0) { double x, y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { m_vertices.add_vertex(x, y, cmd); } } //-------------------------------------------------------------------- // Join path. The path is joined with the existing one, that is, // it behaves as if the pen of a plotter was always down (drawing) template<class VertexSource> void join_path(VertexSource& vs, unsigned path_id = 0) { double x, y; unsigned cmd; vs.rewind(path_id); cmd = vs.vertex(&x, &y); if(!is_stop(cmd)) { if(is_vertex(cmd)) { double x0, y0; unsigned cmd0 = last_vertex(&x0, &y0); if(is_vertex(cmd0)) { if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon) { if(is_move_to(cmd)) cmd = path_cmd_line_to; m_vertices.add_vertex(x, y, cmd); } } else { if(is_stop(cmd0)) { cmd = path_cmd_move_to; } else { if(is_move_to(cmd)) cmd = path_cmd_line_to; } m_vertices.add_vertex(x, y, cmd); } } while(!is_stop(cmd = vs.vertex(&x, &y))) { m_vertices.add_vertex(x, y, is_move_to(cmd) ? unsigned(path_cmd_line_to) : cmd); } } } // Concatenate polygon/polyline. //-------------------------------------------------------------------- template<class T> void concat_poly(const T* data, unsigned num_points, bool closed) { poly_plain_adaptor<T> poly(data, num_points, closed); concat_path(poly); } // Join polygon/polyline continuously. //-------------------------------------------------------------------- template<class T> void join_poly(const T* data, unsigned num_points, bool closed) { poly_plain_adaptor<T> poly(data, num_points, closed); join_path(poly); } //-------------------------------------------------------------------- void translate(double dx, double dy, unsigned path_id=0); void translate_all_paths(double dx, double dy); //-------------------------------------------------------------------- template<class Trans> void transform(const Trans& trans, unsigned path_id=0) { unsigned num_ver = m_vertices.total_vertices(); for(; path_id < num_ver; path_id++) { double x, y; unsigned cmd = m_vertices.vertex(path_id, &x, &y); if(is_stop(cmd)) break; if(is_vertex(cmd)) { trans.transform(&x, &y); m_vertices.modify_vertex(path_id, x, y); } } } //-------------------------------------------------------------------- template<class Trans> void transform_all_paths(const Trans& trans) { unsigned idx; unsigned num_ver = m_vertices.total_vertices(); for(idx = 0; idx < num_ver; idx++) { double x, y; if(is_vertex(m_vertices.vertex(idx, &x, &y))) { trans.transform(&x, &y); m_vertices.modify_vertex(idx, x, y); } } } private: unsigned perceive_polygon_orientation(unsigned start, unsigned end); void invert_polygon(unsigned start, unsigned end); VertexContainer m_vertices; unsigned m_iterator; }; //------------------------------------------------------------------------ template<class VC> unsigned path_base<VC>::start_new_path() { if(!is_stop(m_vertices.last_command())) { m_vertices.add_vertex(0.0, 0.0, path_cmd_stop); } return m_vertices.total_vertices(); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::rel_to_abs(double* x, double* y) const { if(m_vertices.total_vertices()) { double x2; double y2; if(is_vertex(m_vertices.last_vertex(&x2, &y2))) { *x += x2; *y += y2; } } } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::move_to(double x, double y) { m_vertices.add_vertex(x, y, path_cmd_move_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::move_rel(double dx, double dy) { rel_to_abs(&dx, &dy); m_vertices.add_vertex(dx, dy, path_cmd_move_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::line_to(double x, double y) { m_vertices.add_vertex(x, y, path_cmd_line_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::line_rel(double dx, double dy) { rel_to_abs(&dx, &dy); m_vertices.add_vertex(dx, dy, path_cmd_line_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::hline_to(double x) { m_vertices.add_vertex(x, last_y(), path_cmd_line_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::hline_rel(double dx) { double dy = 0; rel_to_abs(&dx, &dy); m_vertices.add_vertex(dx, dy, path_cmd_line_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::vline_to(double y) { m_vertices.add_vertex(last_x(), y, path_cmd_line_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::vline_rel(double dy) { double dx = 0; rel_to_abs(&dx, &dy); m_vertices.add_vertex(dx, dy, path_cmd_line_to); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::arc_to(double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x, double y) { if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command())) { const double epsilon = 1e-30; double x0 = 0.0; double y0 = 0.0; m_vertices.last_vertex(&x0, &y0); rx = fabs(rx); ry = fabs(ry); // Ensure radii are valid //------------------------- if(rx < epsilon || ry < epsilon) { line_to(x, y); return; } if(calc_distance(x0, y0, x, y) < epsilon) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. return; } bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); if(a.radii_ok()) { join_path(a); } else { line_to(x, y); } } else { move_to(x, y); } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::arc_rel(double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double dx, double dy) { rel_to_abs(&dx, &dy); arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve3(double x_ctrl, double y_ctrl, double x_to, double y_to) { m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); m_vertices.add_vertex(x_to, y_to, path_cmd_curve3); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve3_rel(double dx_ctrl, double dy_ctrl, double dx_to, double dy_to) { rel_to_abs(&dx_ctrl, &dy_ctrl); rel_to_abs(&dx_to, &dy_to); m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve3(double x_to, double y_to) { double x0; double y0; if(is_vertex(m_vertices.last_vertex(&x0, &y0))) { double x_ctrl; double y_ctrl; unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl); if(is_curve(cmd)) { x_ctrl = x0 + x0 - x_ctrl; y_ctrl = y0 + y0 - y_ctrl; } else { x_ctrl = x0; y_ctrl = y0; } curve3(x_ctrl, y_ctrl, x_to, y_to); } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve3_rel(double dx_to, double dy_to) { rel_to_abs(&dx_to, &dy_to); curve3(dx_to, dy_to); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve4(double x_ctrl1, double y_ctrl1, double x_ctrl2, double y_ctrl2, double x_to, double y_to) { m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); m_vertices.add_vertex(x_to, y_to, path_cmd_curve4); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1, double dx_ctrl2, double dy_ctrl2, double dx_to, double dy_to) { rel_to_abs(&dx_ctrl1, &dy_ctrl1); rel_to_abs(&dx_ctrl2, &dy_ctrl2); rel_to_abs(&dx_to, &dy_to); m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve4(double x_ctrl2, double y_ctrl2, double x_to, double y_to) { double x0; double y0; if(is_vertex(last_vertex(&x0, &y0))) { double x_ctrl1; double y_ctrl1; unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); if(is_curve(cmd)) { x_ctrl1 = x0 + x0 - x_ctrl1; y_ctrl1 = y0 + y0 - y_ctrl1; } else { x_ctrl1 = x0; y_ctrl1 = y0; } curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::curve4_rel(double dx_ctrl2, double dy_ctrl2, double dx_to, double dy_to) { rel_to_abs(&dx_ctrl2, &dy_ctrl2); rel_to_abs(&dx_to, &dy_to); curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::end_poly(unsigned flags) { if(is_vertex(m_vertices.last_command())) { m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags); } } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::close_polygon(unsigned flags) { end_poly(path_flags_close | flags); } //------------------------------------------------------------------------ template<class VC> inline unsigned path_base<VC>::total_vertices() const { return m_vertices.total_vertices(); } //------------------------------------------------------------------------ template<class VC> inline unsigned path_base<VC>::last_vertex(double* x, double* y) const { return m_vertices.last_vertex(x, y); } //------------------------------------------------------------------------ template<class VC> inline unsigned path_base<VC>::prev_vertex(double* x, double* y) const { return m_vertices.prev_vertex(x, y); } //------------------------------------------------------------------------ template<class VC> inline double path_base<VC>::last_x() const { return m_vertices.last_x(); } //------------------------------------------------------------------------ template<class VC> inline double path_base<VC>::last_y() const { return m_vertices.last_y(); } //------------------------------------------------------------------------ template<class VC> inline unsigned path_base<VC>::vertex(unsigned idx, double* x, double* y) const { return m_vertices.vertex(idx, x, y); } //------------------------------------------------------------------------ template<class VC> inline unsigned path_base<VC>::command(unsigned idx) const { return m_vertices.command(idx); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::modify_vertex(unsigned idx, double x, double y) { m_vertices.modify_vertex(idx, x, y); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::modify_vertex(unsigned idx, double x, double y, unsigned cmd) { m_vertices.modify_vertex(idx, x, y, cmd); } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::modify_command(unsigned idx, unsigned cmd) { m_vertices.modify_command(idx, cmd); } //------------------------------------------------------------------------ template<class VC> inline void path_base<VC>::rewind(unsigned path_id) { m_iterator = path_id; } //------------------------------------------------------------------------ template<class VC> inline unsigned path_base<VC>::vertex(double* x, double* y) { if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop; return m_vertices.vertex(m_iterator++, x, y); } //------------------------------------------------------------------------ template<class VC> unsigned path_base<VC>::perceive_polygon_orientation(unsigned start, unsigned end) { // Calculate signed area (double area to be exact) //--------------------- unsigned np = end - start; double area = 0.0; unsigned i; for(i = 0; i < np; i++) { double x1, y1, x2, y2; m_vertices.vertex(start + i, &x1, &y1); m_vertices.vertex(start + (i + 1) % np, &x2, &y2); area += x1 * y2 - y1 * x2; } return (area < 0.0) ? path_flags_cw : path_flags_ccw; } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::invert_polygon(unsigned start, unsigned end) { unsigned i; unsigned tmp_cmd = m_vertices.command(start); --end; // Make "end" inclusive // Shift all commands to one position for(i = start; i < end; i++) { m_vertices.modify_command(i, m_vertices.command(i + 1)); } // Assign starting command to the ending command m_vertices.modify_command(end, tmp_cmd); // Reverse the polygon while(end > start) { m_vertices.swap_vertices(start++, end--); } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::invert_polygon(unsigned start) { // Skip all non-vertices at the beginning while(start < m_vertices.total_vertices() && !is_vertex(m_vertices.command(start))) ++start; // Skip all insignificant move_to while(start+1 < m_vertices.total_vertices() && is_move_to(m_vertices.command(start)) && is_move_to(m_vertices.command(start+1))) ++start; // Find the last vertex unsigned end = start + 1; while(end < m_vertices.total_vertices() && !is_next_poly(m_vertices.command(end))) ++end; invert_polygon(start, end); } //------------------------------------------------------------------------ template<class VC> unsigned path_base<VC>::arrange_polygon_orientation(unsigned start, path_flags_e orientation) { if(orientation == path_flags_none) return start; // Skip all non-vertices at the beginning while(start < m_vertices.total_vertices() && !is_vertex(m_vertices.command(start))) ++start; // Skip all insignificant move_to while(start+1 < m_vertices.total_vertices() && is_move_to(m_vertices.command(start)) && is_move_to(m_vertices.command(start+1))) ++start; // Find the last vertex unsigned end = start + 1; while(end < m_vertices.total_vertices() && !is_next_poly(m_vertices.command(end))) ++end; if(end - start > 2) { if(perceive_polygon_orientation(start, end) != unsigned(orientation)) { // Invert polygon, set orientation flag, and skip all end_poly invert_polygon(start, end); unsigned cmd; while(end < m_vertices.total_vertices() && is_end_poly(cmd = m_vertices.command(end))) { m_vertices.modify_command(end++, set_orientation(cmd, orientation)); } } } return end; } //------------------------------------------------------------------------ template<class VC> unsigned path_base<VC>::arrange_orientations(unsigned start, path_flags_e orientation) { if(orientation != path_flags_none) { while(start < m_vertices.total_vertices()) { start = arrange_polygon_orientation(start, orientation); if(is_stop(m_vertices.command(start))) { ++start; break; } } } return start; } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation) { if(orientation != path_flags_none) { unsigned start = 0; while(start < m_vertices.total_vertices()) { start = arrange_orientations(start, orientation); } } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::flip_x(double x1, double x2) { unsigned i; double x, y; for(i = 0; i < m_vertices.total_vertices(); i++) { unsigned cmd = m_vertices.vertex(i, &x, &y); if(is_vertex(cmd)) { m_vertices.modify_vertex(i, x2 - x + x1, y); } } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::flip_y(double y1, double y2) { unsigned i; double x, y; for(i = 0; i < m_vertices.total_vertices(); i++) { unsigned cmd = m_vertices.vertex(i, &x, &y); if(is_vertex(cmd)) { m_vertices.modify_vertex(i, x, y2 - y + y1); } } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::translate(double dx, double dy, unsigned path_id) { unsigned num_ver = m_vertices.total_vertices(); for(; path_id < num_ver; path_id++) { double x, y; unsigned cmd = m_vertices.vertex(path_id, &x, &y); if(is_stop(cmd)) break; if(is_vertex(cmd)) { x += dx; y += dy; m_vertices.modify_vertex(path_id, x, y); } } } //------------------------------------------------------------------------ template<class VC> void path_base<VC>::translate_all_paths(double dx, double dy) { unsigned idx; unsigned num_ver = m_vertices.total_vertices(); for(idx = 0; idx < num_ver; idx++) { double x, y; if(is_vertex(m_vertices.vertex(idx, &x, &y))) { x += dx; y += dy; m_vertices.modify_vertex(idx, x, y); } } } //-----------------------------------------------------vertex_stl_storage template<class Container> class vertex_stl_storage { public: typedef typename Container::value_type vertex_type; typedef typename vertex_type::value_type value_type; void remove_all() { m_vertices.clear(); } void free_all() { m_vertices.clear(); } void add_vertex(double x, double y, unsigned cmd) { m_vertices.push_back(vertex_type(value_type(x), value_type(y), int8u(cmd))); } void modify_vertex(unsigned idx, double x, double y) { vertex_type& v = m_vertices[idx]; v.x = value_type(x); v.y = value_type(y); } void modify_vertex(unsigned idx, double x, double y, unsigned cmd) { vertex_type& v = m_vertices[idx]; v.x = value_type(x); v.y = value_type(y); v.cmd = int8u(cmd); } void modify_command(unsigned idx, unsigned cmd) { m_vertices[idx].cmd = int8u(cmd); } void swap_vertices(unsigned v1, unsigned v2) { vertex_type t = m_vertices[v1]; m_vertices[v1] = m_vertices[v2]; m_vertices[v2] = t; } unsigned last_command() const { return m_vertices.size() ? m_vertices[m_vertices.size() - 1].cmd : path_cmd_stop; } unsigned last_vertex(double* x, double* y) const { if(m_vertices.size() == 0) { *x = *y = 0.0; return path_cmd_stop; } return vertex(m_vertices.size() - 1, x, y); } unsigned prev_vertex(double* x, double* y) const { if(m_vertices.size() < 2) { *x = *y = 0.0; return path_cmd_stop; } return vertex(m_vertices.size() - 2, x, y); } double last_x() const { return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0; } double last_y() const { return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0; } unsigned total_vertices() const { return m_vertices.size(); } unsigned vertex(unsigned idx, double* x, double* y) const { const vertex_type& v = m_vertices[idx]; *x = v.x; *y = v.y; return v.cmd; } unsigned command(unsigned idx) const { return m_vertices[idx].cmd; } private: Container m_vertices; }; //-----------------------------------------------------------path_storage typedef path_base<vertex_block_storage<double> > path_storage; // Example of declarations path_storage with pod_bvector as a container //----------------------------------------------------------------------- //typedef path_base<vertex_stl_storage<pod_bvector<vertex_d> > > path_storage; } // Example of declarations path_storage with std::vector as a container //--------------------------------------------------------------------------- //#include <vector> //namespace mapserver //{ // typedef path_base<vertex_stl_storage<std::vector<vertex_d> > > stl_path_storage; //} #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_scanline_bin.h��������������������������������������������0000644�0024617�0000144�00000017112�12261257215�023103� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Class scanline_bin - binary scanline. // //---------------------------------------------------------------------------- // // Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_BIN_INCLUDED #define AGG_SCANLINE_BIN_INCLUDED #include "agg_array.h" namespace mapserver { //=============================================================scanline_bin // // This is binary scaline container which supports the interface // used in the rasterizer::render(). See description of agg_scanline_u8 // for details. // //------------------------------------------------------------------------ class scanline_bin { public: typedef int32 coord_type; struct span { int16 x; int16 len; }; typedef const span* const_iterator; //-------------------------------------------------------------------- scanline_bin() : m_last_x(0x7FFFFFF0), m_spans(), m_cur_span(0) { } //-------------------------------------------------------------------- void reset(int min_x, int max_x) { unsigned max_len = max_x - min_x + 3; if(max_len > m_spans.size()) { m_spans.resize(max_len); } m_last_x = 0x7FFFFFF0; m_cur_span = &m_spans[0]; } //-------------------------------------------------------------------- void add_cell(int x, unsigned) { if(x == m_last_x+1) { m_cur_span->len++; } else { ++m_cur_span; m_cur_span->x = (int16)x; m_cur_span->len = 1; } m_last_x = x; } //-------------------------------------------------------------------- void add_span(int x, unsigned len, unsigned) { if(x == m_last_x+1) { m_cur_span->len = (int16)(m_cur_span->len + len); } else { ++m_cur_span; m_cur_span->x = (int16)x; m_cur_span->len = (int16)len; } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void add_cells(int x, unsigned len, const void*) { add_span(x, len, 0); } //-------------------------------------------------------------------- void finalize(int y) { m_y = y; } //-------------------------------------------------------------------- void reset_spans() { m_last_x = 0x7FFFFFF0; m_cur_span = &m_spans[0]; } //-------------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } const_iterator begin() const { return &m_spans[1]; } private: scanline_bin(const scanline_bin&); const scanline_bin operator = (const scanline_bin&); int m_last_x; int m_y; pod_array<span> m_spans; span* m_cur_span; }; //===========================================================scanline32_bin class scanline32_bin { public: typedef int32 coord_type; //-------------------------------------------------------------------- struct span { span() {} span(coord_type x_, coord_type len_) : x(x_), len(len_) {} coord_type x; coord_type len; }; typedef pod_bvector<span, 4> span_array_type; //-------------------------------------------------------------------- class const_iterator { public: const_iterator(const span_array_type& spans) : m_spans(spans), m_span_idx(0) {} const span& operator*() const { return m_spans[m_span_idx]; } const span* operator->() const { return &m_spans[m_span_idx]; } void operator ++ () { ++m_span_idx; } private: const span_array_type& m_spans; unsigned m_span_idx; }; //-------------------------------------------------------------------- scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {} //-------------------------------------------------------------------- void reset(int min_x, int max_x) { m_last_x = 0x7FFFFFF0; m_spans.remove_all(); } //-------------------------------------------------------------------- void add_cell(int x, unsigned) { if(x == m_last_x+1) { m_spans.last().len++; } else { m_spans.add(span(coord_type(x), 1)); } m_last_x = x; } //-------------------------------------------------------------------- void add_span(int x, unsigned len, unsigned) { if(x == m_last_x+1) { m_spans.last().len += coord_type(len); } else { m_spans.add(span(coord_type(x), coord_type(len))); } m_last_x = x + len - 1; } //-------------------------------------------------------------------- void add_cells(int x, unsigned len, const void*) { add_span(x, len, 0); } //-------------------------------------------------------------------- void finalize(int y) { m_y = y; } //-------------------------------------------------------------------- void reset_spans() { m_last_x = 0x7FFFFFF0; m_spans.remove_all(); } //-------------------------------------------------------------------- int y() const { return m_y; } unsigned num_spans() const { return m_spans.size(); } const_iterator begin() const { return const_iterator(m_spans); } private: scanline32_bin(const scanline32_bin&); const scanline32_bin operator = (const scanline32_bin&); unsigned m_max_len; int m_last_x; int m_y; span_array_type m_spans; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_scanline.h���������������������������������������0000644�0024617�0000144�00000102574�12261257215�024150� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_SCANLINE_INCLUDED #define AGG_RENDERER_SCANLINE_INCLUDED #include "agg_basics.h" #include "agg_renderer_base.h" namespace mapserver { //================================================render_scanline_aa_solid template<class Scanline, class BaseRenderer, class ColorT> void render_scanline_aa_solid(const Scanline& sl, BaseRenderer& ren, const ColorT& color) { int y = sl.y(); unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); for(;;) { int x = span->x; if(span->len > 0) { ren.blend_solid_hspan(x, y, (unsigned)span->len, color, span->covers); } else { ren.blend_hline(x, y, (unsigned)(x - span->len - 1), color, *(span->covers)); } if(--num_spans == 0) break; ++span; } } //===============================================render_scanlines_aa_solid template<class Rasterizer, class Scanline, class BaseRenderer, class ColorT> void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, const ColorT& color) { if(ras.rewind_scanlines()) { // Explicitly convert "color" to the BaseRenderer color type. // For example, it can be called with color type "rgba", while // "rgba8" is needed. Otherwise it will be implicitly // converted in the loop many times. //---------------------- typename BaseRenderer::color_type ren_color(color); sl.reset(ras.min_x(), ras.max_x()); while(ras.sweep_scanline(sl)) { //render_scanline_aa_solid(sl, ren, ren_color); // This code is equivalent to the above call (copy/paste). // It's just a "manual" optimization for old compilers, // like Microsoft Visual C++ v6.0 //------------------------------- int y = sl.y(); unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); for(;;) { int x = span->x; if(span->len > 0) { ren.blend_solid_hspan(x, y, (unsigned)span->len, ren_color, span->covers); } else { ren.blend_hline(x, y, (unsigned)(x - span->len - 1), ren_color, *(span->covers)); } if(--num_spans == 0) break; ++span; } } } } //==============================================renderer_scanline_aa_solid template<class BaseRenderer> class renderer_scanline_aa_solid { public: typedef BaseRenderer base_ren_type; typedef typename base_ren_type::color_type color_type; //-------------------------------------------------------------------- renderer_scanline_aa_solid() : m_ren(0) {} explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {} void attach(base_ren_type& ren) { m_ren = &ren; } //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- void prepare() {} //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { render_scanline_aa_solid(sl, *m_ren, m_color); } private: base_ren_type* m_ren; color_type m_color; }; //======================================================render_scanline_aa template<class Scanline, class BaseRenderer, class SpanAllocator, class SpanGenerator> void render_scanline_aa(const Scanline& sl, BaseRenderer& ren, SpanAllocator& alloc, SpanGenerator& span_gen) { int y = sl.y(); unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); for(;;) { int x = span->x; int len = span->len; const typename Scanline::cover_type* covers = span->covers; if(len < 0) len = -len; typename BaseRenderer::color_type* colors = alloc.allocate(len); span_gen.generate(colors, x, y, len); ren.blend_color_hspan(x, y, len, colors, (span->len < 0) ? 0 : covers, *covers); if(--num_spans == 0) break; ++span; } } //=====================================================render_scanlines_aa template<class Rasterizer, class Scanline, class BaseRenderer, class SpanAllocator, class SpanGenerator> void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, SpanAllocator& alloc, SpanGenerator& span_gen) { if(ras.rewind_scanlines()) { sl.reset(ras.min_x(), ras.max_x()); span_gen.prepare(); while(ras.sweep_scanline(sl)) { render_scanline_aa(sl, ren, alloc, span_gen); } } } //====================================================renderer_scanline_aa template<class BaseRenderer, class SpanAllocator, class SpanGenerator> class renderer_scanline_aa { public: typedef BaseRenderer base_ren_type; typedef SpanAllocator alloc_type; typedef SpanGenerator span_gen_type; //-------------------------------------------------------------------- renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} renderer_scanline_aa(base_ren_type& ren, alloc_type& alloc, span_gen_type& span_gen) : m_ren(&ren), m_alloc(&alloc), m_span_gen(&span_gen) {} void attach(base_ren_type& ren, alloc_type& alloc, span_gen_type& span_gen) { m_ren = &ren; m_alloc = &alloc; m_span_gen = &span_gen; } //-------------------------------------------------------------------- void prepare() { m_span_gen->prepare(); } //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); } private: base_ren_type* m_ren; alloc_type* m_alloc; span_gen_type* m_span_gen; }; //===============================================render_scanline_bin_solid template<class Scanline, class BaseRenderer, class ColorT> void render_scanline_bin_solid(const Scanline& sl, BaseRenderer& ren, const ColorT& color) { unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); for(;;) { ren.blend_hline(span->x, sl.y(), span->x - 1 + ((span->len < 0) ? -span->len : span->len), color, cover_full); if(--num_spans == 0) break; ++span; } } //==============================================render_scanlines_bin_solid template<class Rasterizer, class Scanline, class BaseRenderer, class ColorT> void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, const ColorT& color) { if(ras.rewind_scanlines()) { // Explicitly convert "color" to the BaseRenderer color type. // For example, it can be called with color type "rgba", while // "rgba8" is needed. Otherwise it will be implicitly // converted in the loop many times. //---------------------- typename BaseRenderer::color_type ren_color(color); sl.reset(ras.min_x(), ras.max_x()); while(ras.sweep_scanline(sl)) { //render_scanline_bin_solid(sl, ren, ren_color); // This code is equivalent to the above call (copy/paste). // It's just a "manual" optimization for old compilers, // like Microsoft Visual C++ v6.0 //------------------------------- unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); for(;;) { ren.blend_hline(span->x, sl.y(), span->x - 1 + ((span->len < 0) ? -span->len : span->len), ren_color, cover_full); if(--num_spans == 0) break; ++span; } } } } //=============================================renderer_scanline_bin_solid template<class BaseRenderer> class renderer_scanline_bin_solid { public: typedef BaseRenderer base_ren_type; typedef typename base_ren_type::color_type color_type; //-------------------------------------------------------------------- renderer_scanline_bin_solid() : m_ren(0) {} explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} void attach(base_ren_type& ren) { m_ren = &ren; } //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- void prepare() {} //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { render_scanline_bin_solid(sl, *m_ren, m_color); } private: base_ren_type* m_ren; color_type m_color; }; //======================================================render_scanline_bin template<class Scanline, class BaseRenderer, class SpanAllocator, class SpanGenerator> void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, SpanAllocator& alloc, SpanGenerator& span_gen) { int y = sl.y(); unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); for(;;) { int x = span->x; int len = span->len; if(len < 0) len = -len; typename BaseRenderer::color_type* colors = alloc.allocate(len); span_gen.generate(colors, x, y, len); ren.blend_color_hspan(x, y, len, colors, 0, cover_full); if(--num_spans == 0) break; ++span; } } //=====================================================render_scanlines_bin template<class Rasterizer, class Scanline, class BaseRenderer, class SpanAllocator, class SpanGenerator> void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, SpanAllocator& alloc, SpanGenerator& span_gen) { if(ras.rewind_scanlines()) { sl.reset(ras.min_x(), ras.max_x()); span_gen.prepare(); while(ras.sweep_scanline(sl)) { render_scanline_bin(sl, ren, alloc, span_gen); } } } //====================================================renderer_scanline_bin template<class BaseRenderer, class SpanAllocator, class SpanGenerator> class renderer_scanline_bin { public: typedef BaseRenderer base_ren_type; typedef SpanAllocator alloc_type; typedef SpanGenerator span_gen_type; //-------------------------------------------------------------------- renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} renderer_scanline_bin(base_ren_type& ren, alloc_type& alloc, span_gen_type& span_gen) : m_ren(&ren), m_alloc(&alloc), m_span_gen(&span_gen) {} void attach(base_ren_type& ren, alloc_type& alloc, span_gen_type& span_gen) { m_ren = &ren; m_alloc = &alloc; m_span_gen = &span_gen; } //-------------------------------------------------------------------- void prepare() { m_span_gen->prepare(); } //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); } private: base_ren_type* m_ren; alloc_type* m_alloc; span_gen_type* m_span_gen; }; //========================================================render_scanlines template<class Rasterizer, class Scanline, class Renderer> void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) { if(ras.rewind_scanlines()) { sl.reset(ras.min_x(), ras.max_x()); ren.prepare(); while(ras.sweep_scanline(sl)) { ren.render(sl); } } } //========================================================render_all_paths template<class Rasterizer, class Scanline, class Renderer, class VertexSource, class ColorStorage, class PathId> void render_all_paths(Rasterizer& ras, Scanline& sl, Renderer& r, VertexSource& vs, const ColorStorage& as, const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { ras.reset(); ras.add_path(vs, path_id[i]); r.color(as[i]); render_scanlines(ras, sl, r); } } //=============================================render_scanlines_compound template<class Rasterizer, class ScanlineAA, class ScanlineBin, class BaseRenderer, class SpanAllocator, class StyleHandler> void render_scanlines_compound(Rasterizer& ras, ScanlineAA& sl_aa, ScanlineBin& sl_bin, BaseRenderer& ren, SpanAllocator& alloc, StyleHandler& sh) { if(ras.rewind_scanlines()) { int min_x = ras.min_x(); int len = ras.max_x() - min_x + 2; sl_aa.reset(min_x, ras.max_x()); sl_bin.reset(min_x, ras.max_x()); typedef typename BaseRenderer::color_type color_type; color_type* color_span = alloc.allocate(len * 2); color_type* mix_buffer = color_span + len; unsigned num_spans; unsigned num_styles; unsigned style; bool solid; while((num_styles = ras.sweep_styles()) > 0) { typename ScanlineAA::const_iterator span_aa; if(num_styles == 1) { // Optimization for a single style. Happens often //------------------------- if(ras.sweep_scanline(sl_aa, 0)) { style = ras.style(0); if(sh.is_solid(style)) { // Just solid fill //----------------------- render_scanline_aa_solid(sl_aa, ren, sh.color(style)); } else { // Arbitrary span generator //----------------------- span_aa = sl_aa.begin(); num_spans = sl_aa.num_spans(); for(;;) { len = span_aa->len; sh.generate_span(color_span, span_aa->x, sl_aa.y(), len, style); ren.blend_color_hspan(span_aa->x, sl_aa.y(), span_aa->len, color_span, span_aa->covers); if(--num_spans == 0) break; ++span_aa; } } } } else { if(ras.sweep_scanline(sl_bin, -1)) { // Clear the spans of the mix_buffer //-------------------- typename ScanlineBin::const_iterator span_bin = sl_bin.begin(); num_spans = sl_bin.num_spans(); for(;;) { memset(mix_buffer + span_bin->x - min_x, 0, span_bin->len * sizeof(color_type)); if(--num_spans == 0) break; ++span_bin; } unsigned i; for(i = 0; i < num_styles; i++) { style = ras.style(i); solid = sh.is_solid(style); if(ras.sweep_scanline(sl_aa, i)) { color_type* colors; color_type* cspan; typename ScanlineAA::cover_type* covers; span_aa = sl_aa.begin(); num_spans = sl_aa.num_spans(); if(solid) { // Just solid fill //----------------------- for(;;) { color_type c = sh.color(style); len = span_aa->len; colors = mix_buffer + span_aa->x - min_x; covers = span_aa->covers; do { if(*covers == cover_full) { *colors = c; } else { colors->add(c, *covers); } ++colors; ++covers; } while(--len); if(--num_spans == 0) break; ++span_aa; } } else { // Arbitrary span generator //----------------------- for(;;) { len = span_aa->len; colors = mix_buffer + span_aa->x - min_x; cspan = color_span; sh.generate_span(cspan, span_aa->x, sl_aa.y(), len, style); covers = span_aa->covers; do { if(*covers == cover_full) { *colors = *cspan; } else { colors->add(*cspan, *covers); } ++cspan; ++colors; ++covers; } while(--len); if(--num_spans == 0) break; ++span_aa; } } } } // Emit the blended result as a color hspan //------------------------- span_bin = sl_bin.begin(); num_spans = sl_bin.num_spans(); for(;;) { ren.blend_color_hspan(span_bin->x, sl_bin.y(), span_bin->len, mix_buffer + span_bin->x - min_x, 0, cover_full); if(--num_spans == 0) break; ++span_bin; } } // if(ras.sweep_scanline(sl_bin, -1)) } // if(num_styles == 1) ... else } // while((num_styles = ras.sweep_styles()) > 0) } // if(ras.rewind_scanlines()) } //=======================================render_scanlines_compound_layered template<class Rasterizer, class ScanlineAA, class BaseRenderer, class SpanAllocator, class StyleHandler> void render_scanlines_compound_layered(Rasterizer& ras, ScanlineAA& sl_aa, BaseRenderer& ren, SpanAllocator& alloc, StyleHandler& sh) { if(ras.rewind_scanlines()) { int min_x = ras.min_x(); int len = ras.max_x() - min_x + 2; sl_aa.reset(min_x, ras.max_x()); typedef typename BaseRenderer::color_type color_type; color_type* color_span = alloc.allocate(len * 2); color_type* mix_buffer = color_span + len; cover_type* cover_buffer = ras.allocate_cover_buffer(len); unsigned num_spans; unsigned num_styles; unsigned style; bool solid; while((num_styles = ras.sweep_styles()) > 0) { typename ScanlineAA::const_iterator span_aa; if(num_styles == 1) { // Optimization for a single style. Happens often //------------------------- if(ras.sweep_scanline(sl_aa, 0)) { style = ras.style(0); if(sh.is_solid(style)) { // Just solid fill //----------------------- render_scanline_aa_solid(sl_aa, ren, sh.color(style)); } else { // Arbitrary span generator //----------------------- span_aa = sl_aa.begin(); num_spans = sl_aa.num_spans(); for(;;) { len = span_aa->len; sh.generate_span(color_span, span_aa->x, sl_aa.y(), len, style); ren.blend_color_hspan(span_aa->x, sl_aa.y(), span_aa->len, color_span, span_aa->covers); if(--num_spans == 0) break; ++span_aa; } } } } else { int sl_start = ras.scanline_start(); unsigned sl_len = ras.scanline_length(); if(sl_len) { memset(mix_buffer + sl_start - min_x, 0, sl_len * sizeof(color_type)); memset(cover_buffer + sl_start - min_x, 0, sl_len * sizeof(cover_type)); int sl_y = 0x7FFFFFFF; unsigned i; for(i = 0; i < num_styles; i++) { style = ras.style(i); solid = sh.is_solid(style); if(ras.sweep_scanline(sl_aa, i)) { unsigned cover; color_type* colors; color_type* cspan; cover_type* src_covers; cover_type* dst_covers; span_aa = sl_aa.begin(); num_spans = sl_aa.num_spans(); sl_y = sl_aa.y(); if(solid) { // Just solid fill //----------------------- for(;;) { color_type c = sh.color(style); len = span_aa->len; colors = mix_buffer + span_aa->x - min_x; src_covers = span_aa->covers; dst_covers = cover_buffer + span_aa->x - min_x; do { cover = *src_covers; if(*dst_covers + cover > cover_full) { cover = cover_full - *dst_covers; } if(cover) { colors->add(c, cover); *dst_covers += cover; } ++colors; ++src_covers; ++dst_covers; } while(--len); if(--num_spans == 0) break; ++span_aa; } } else { // Arbitrary span generator //----------------------- for(;;) { len = span_aa->len; colors = mix_buffer + span_aa->x - min_x; cspan = color_span; sh.generate_span(cspan, span_aa->x, sl_aa.y(), len, style); src_covers = span_aa->covers; dst_covers = cover_buffer + span_aa->x - min_x; do { cover = *src_covers; if(*dst_covers + cover > cover_full) { cover = cover_full - *dst_covers; } if(cover) { colors->add(*cspan, cover); *dst_covers += cover; } ++cspan; ++colors; ++src_covers; ++dst_covers; } while(--len); if(--num_spans == 0) break; ++span_aa; } } } } ren.blend_color_hspan(sl_start, sl_y, sl_len, mix_buffer + sl_start - min_x, 0, cover_full); } //if(sl_len) } //if(num_styles == 1) ... else } //while((num_styles = ras.sweep_styles()) > 0) } //if(ras.rewind_scanlines()) } } #endif ������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_trans_affine.h��������������������������������������������0000644�0024617�0000144�00000044675�12261257215�023134� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // Affine transformation classes. // //---------------------------------------------------------------------------- #ifndef AGG_TRANS_AFFINE_INCLUDED #define AGG_TRANS_AFFINE_INCLUDED #include <math.h> #include "agg_basics.h" namespace mapserver { const double affine_epsilon = 1e-14; //============================================================trans_affine // // See Implementation agg_trans_affine.cpp // // Affine transformation are linear transformations in Cartesian coordinates // (strictly speaking not only in Cartesian, but for the beginning we will // think so). They are rotation, scaling, translation and skewing. // After any affine transformation a line segment remains a line segment // and it will never become a curve. // // There will be no math about matrix calculations, since it has been // described many times. Ask yourself a very simple question: // "why do we need to understand and use some matrix stuff instead of just // rotating, scaling and so on". The answers are: // // 1. Any combination of transformations can be done by only 4 multiplications // and 4 additions in floating point. // 2. One matrix transformation is equivalent to the number of consecutive // discrete transformations, i.e. the matrix "accumulates" all transformations // in the order of their settings. Suppose we have 4 transformations: // * rotate by 30 degrees, // * scale X to 2.0, // * scale Y to 1.5, // * move to (100, 100). // The result will depend on the order of these transformations, // and the advantage of matrix is that the sequence of discret calls: // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) // will have exactly the same result as the following matrix transformations: // // affine_matrix m; // m *= rotate_matrix(30); // m *= scaleX_matrix(2.0); // m *= scaleY_matrix(1.5); // m *= move_matrix(100,100); // // m.transform_my_point_at_last(x, y); // // What is the good of it? In real life we will set-up the matrix only once // and then transform many points, let alone the convenience to set any // combination of transformations. // // So, how to use it? Very easy - literally as it's shown above. Not quite, // let us write a correct example: // // mapserver::trans_affine m; // m *= mapserver::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // m *= mapserver::trans_affine_scaling(2.0, 1.5); // m *= mapserver::trans_affine_translation(100.0, 100.0); // m.transform(&x, &y); // // The affine matrix is all you need to perform any linear transformation, // but all transformations have origin point (0,0). It means that we need to // use 2 translations if we want to rotate someting around (100,100): // // m *= mapserver::trans_affine_translation(-100.0, -100.0); // move to (0,0) // m *= mapserver::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate // m *= mapserver::trans_affine_translation(100.0, 100.0); // move back to (100,100) //---------------------------------------------------------------------- struct trans_affine { double sx, shy, shx, sy, tx, ty; //------------------------------------------ Construction // Identity matrix trans_affine() : sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0) {} // Custom matrix. Usually used in derived classes trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) : sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5) {} // Custom matrix from m[6] explicit trans_affine(const double* m) : sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5]) {} // Rectangle to a parallelogram. trans_affine(double x1, double y1, double x2, double y2, const double* parl) { rect_to_parl(x1, y1, x2, y2, parl); } // Parallelogram to a rectangle. trans_affine(const double* parl, double x1, double y1, double x2, double y2) { parl_to_rect(parl, x1, y1, x2, y2); } // Arbitrary parallelogram transformation. trans_affine(const double* src, const double* dst) { parl_to_parl(src, dst); } //---------------------------------- Parellelogram transformations // transform a parallelogram to another one. Src and dst are // pointers to arrays of three points (double[6], x1,y1,...) that // identify three corners of the parallelograms assuming implicit // fourth point. The arguments are arrays of double[6] mapped // to x1,y1, x2,y2, x3,y3 where the coordinates are: // *-----------------* // / (x3,y3)/ // / / // /(x1,y1) (x2,y2)/ // *-----------------* const trans_affine& parl_to_parl(const double* src, const double* dst); const trans_affine& rect_to_parl(double x1, double y1, double x2, double y2, const double* parl); const trans_affine& parl_to_rect(const double* parl, double x1, double y1, double x2, double y2); //------------------------------------------ Operations // Reset - load an identity matrix const trans_affine& reset(); // Direct transformations operations const trans_affine& translate(double x, double y); const trans_affine& rotate(double a); const trans_affine& scale(double s); const trans_affine& scale(double x, double y); // Multiply matrix to another one const trans_affine& multiply(const trans_affine& m); // Multiply "m" to "this" and assign the result to "this" const trans_affine& premultiply(const trans_affine& m); // Multiply matrix to inverse of another one const trans_affine& multiply_inv(const trans_affine& m); // Multiply inverse of "m" to "this" and assign the result to "this" const trans_affine& premultiply_inv(const trans_affine& m); // Invert matrix. Do not try to invert degenerate matrices, // there's no check for validity. If you set scale to 0 and // then try to invert matrix, expect unpredictable result. const trans_affine& invert(); // Mirroring around X const trans_affine& flip_x(); // Mirroring around Y const trans_affine& flip_y(); //------------------------------------------- Load/Store // Store matrix to an array [6] of double void store_to(double* m) const { *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty; } // Load matrix from an array [6] of double const trans_affine& load_from(const double* m) { sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++; return *this; } //------------------------------------------- Operators // Multiply the matrix by another one const trans_affine& operator *= (const trans_affine& m) { return multiply(m); } // Multiply the matrix by inverse of another one const trans_affine& operator /= (const trans_affine& m) { return multiply_inv(m); } // Multiply the matrix by another one and return // the result in a separete matrix. trans_affine operator * (const trans_affine& m) { return trans_affine(*this).multiply(m); } // Multiply the matrix by inverse of another one // and return the result in a separete matrix. trans_affine operator / (const trans_affine& m) { return trans_affine(*this).multiply_inv(m); } // Calculate and return the inverse matrix trans_affine operator ~ () const { trans_affine ret = *this; return ret.invert(); } // Equal operator with default epsilon bool operator == (const trans_affine& m) const { return is_equal(m, affine_epsilon); } // Not Equal operator with default epsilon bool operator != (const trans_affine& m) const { return !is_equal(m, affine_epsilon); } //-------------------------------------------- Transformations // Direct transformation of x and y void transform(double* x, double* y) const; // Direct transformation of x and y, 2x2 matrix only, no translation void transform_2x2(double* x, double* y) const; // Inverse transformation of x and y. It works slower than the // direct transformation. For massive operations it's better to // invert() the matrix and then use direct transformations. void inverse_transform(double* x, double* y) const; //-------------------------------------------- Auxiliary // Calculate the determinant of matrix double determinant() const { return sx * sy - shy * shx; } // Calculate the reciprocal of the determinant double determinant_reciprocal() const { return 1.0 / (sx * sy - shy * shx); } // Get the average scale (by X and Y). // Basically used to calculate the approximation_scale when // decomposinting curves into line segments. double scale() const; // Check to see if the matrix is not degenerate bool is_valid(double epsilon = affine_epsilon) const; // Check to see if it's an identity matrix bool is_identity(double epsilon = affine_epsilon) const; // Check to see if two matrices are equal bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; // Determine the major parameters. Use with caution considering // possible degenerate cases. double rotation() const; void translation(double* dx, double* dy) const; void scaling(double* x, double* y) const; void scaling_abs(double* x, double* y) const; }; //------------------------------------------------------------------------ inline void trans_affine::transform(double* x, double* y) const { register double tmp = *x; *x = tmp * sx + *y * shx + tx; *y = tmp * shy + *y * sy + ty; } //------------------------------------------------------------------------ inline void trans_affine::transform_2x2(double* x, double* y) const { register double tmp = *x; *x = tmp * sx + *y * shx; *y = tmp * shy + *y * sy; } //------------------------------------------------------------------------ inline void trans_affine::inverse_transform(double* x, double* y) const { register double d = determinant_reciprocal(); register double a = (*x - tx) * d; register double b = (*y - ty) * d; *x = a * sy - b * shx; *y = b * sx - a * shy; } //------------------------------------------------------------------------ inline double trans_affine::scale() const { double x = 0.707106781 * sx + 0.707106781 * shx; double y = 0.707106781 * shy + 0.707106781 * sy; return sqrt(x*x + y*y); } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::translate(double x, double y) { tx += x; ty += y; return *this; } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::rotate(double a) { double ca = cos(a); double sa = sin(a); double t0 = sx * ca - shy * sa; double t2 = shx * ca - sy * sa; double t4 = tx * ca - ty * sa; shy = sx * sa + shy * ca; sy = shx * sa + sy * ca; ty = tx * sa + ty * ca; sx = t0; shx = t2; tx = t4; return *this; } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::scale(double x, double y) { double mm0 = x; // Possible hint for the optimizer double mm3 = y; sx *= mm0; shx *= mm0; tx *= mm0; shy *= mm3; sy *= mm3; ty *= mm3; return *this; } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::scale(double s) { double m = s; // Possible hint for the optimizer sx *= m; shx *= m; tx *= m; shy *= m; sy *= m; ty *= m; return *this; } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::premultiply(const trans_affine& m) { trans_affine t = m; return *this = t.multiply(*this); } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) { trans_affine t = m; t.invert(); return multiply(t); } //------------------------------------------------------------------------ inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) { trans_affine t = m; t.invert(); return *this = t.multiply(*this); } //------------------------------------------------------------------------ inline void trans_affine::scaling_abs(double* x, double* y) const { // Used to calculate scaling coefficients in image resampling. // When there is considerable shear this method gives us much // better estimation than just sx, sy. *x = sqrt(sx * sx + shx * shx); *y = sqrt(shy * shy + sy * sy); } //====================================================trans_affine_rotation // Rotation matrix. sin() and cos() are calculated twice for the same angle. // There's no harm because the performance of sin()/cos() is very good on all // modern processors. Besides, this operation is not going to be invoked too // often. class trans_affine_rotation : public trans_affine { public: trans_affine_rotation(double a) : trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0) {} }; //====================================================trans_affine_scaling // Scaling matrix. x, y - scale coefficients by X and Y respectively class trans_affine_scaling : public trans_affine { public: trans_affine_scaling(double x, double y) : trans_affine(x, 0.0, 0.0, y, 0.0, 0.0) {} trans_affine_scaling(double s) : trans_affine(s, 0.0, 0.0, s, 0.0, 0.0) {} }; //================================================trans_affine_translation // Translation matrix class trans_affine_translation : public trans_affine { public: trans_affine_translation(double x, double y) : trans_affine(1.0, 0.0, 0.0, 1.0, x, y) {} }; //====================================================trans_affine_skewing // Sckewing (shear) matrix class trans_affine_skewing : public trans_affine { public: trans_affine_skewing(double x, double y) : trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0) {} }; //===============================================trans_affine_line_segment // Rotate, Scale and Translate, associating 0...dist with line segment // x1,y1,x2,y2 class trans_affine_line_segment : public trans_affine { public: trans_affine_line_segment(double x1, double y1, double x2, double y2, double dist) { double dx = x2 - x1; double dy = y2 - y1; if(dist > 0.0) { multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist)); } multiply(trans_affine_rotation(atan2(dy, dx))); multiply(trans_affine_translation(x1, y1)); } }; //============================================trans_affine_reflection_unit // Reflection matrix. Reflect coordinates across the line through // the origin containing the unit vector (ux, uy). // Contributed by John Horigan class trans_affine_reflection_unit : public trans_affine { public: trans_affine_reflection_unit(double ux, double uy) : trans_affine(2.0 * ux * ux - 1.0, 2.0 * ux * uy, 2.0 * ux * uy, 2.0 * uy * uy - 1.0, 0.0, 0.0) {} }; //=================================================trans_affine_reflection // Reflection matrix. Reflect coordinates across the line through // the origin at the angle a or containing the non-unit vector (x, y). // Contributed by John Horigan class trans_affine_reflection : public trans_affine_reflection_unit { public: trans_affine_reflection(double a) : trans_affine_reflection_unit(cos(a), sin(a)) {} trans_affine_reflection(double x, double y) : trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y)) {} }; } #endif �������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_contour.h��������������������������������������������0000644�0024617�0000144�00000005556�12261257215�023206� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // conv_stroke // //---------------------------------------------------------------------------- #ifndef AGG_CONV_CONTOUR_INCLUDED #define AGG_CONV_CONTOUR_INCLUDED #include "agg_basics.h" #include "agg_vcgen_contour.h" #include "agg_conv_adaptor_vcgen.h" namespace mapserver { //-----------------------------------------------------------conv_contour template<class VertexSource> struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour> { typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type; conv_contour(VertexSource& vs) : conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs) { } void line_join(line_join_e lj) { base_type::generator().line_join(lj); } void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } void approximation_scale(double as) { base_type::generator().approximation_scale(as); } void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); } line_join_e line_join() const { return base_type::generator().line_join(); } inner_join_e inner_join() const { return base_type::generator().inner_join(); } double width() const { return base_type::generator().width(); } double miter_limit() const { return base_type::generator().miter_limit(); } double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } double approximation_scale() const { return base_type::generator().approximation_scale(); } bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } private: conv_contour(const conv_contour<VertexSource>&); const conv_contour<VertexSource>& operator = (const conv_contour<VertexSource>&); }; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_vcgen_stroke.h��������������������������������������������0000644�0024617�0000144�00000007002�12261257215�023145� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_VCGEN_STROKE_INCLUDED #define AGG_VCGEN_STROKE_INCLUDED #include "agg_math_stroke.h" namespace mapserver { //============================================================vcgen_stroke // // See Implementation agg_vcgen_stroke.cpp // Stroke generator // //------------------------------------------------------------------------ class vcgen_stroke { enum status_e { initial, ready, cap1, cap2, outline1, close_first, outline2, out_vertices, end_poly1, end_poly2, stop }; public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; typedef pod_bvector<point_d, 6> coord_storage; vcgen_stroke(); void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } void line_join(line_join_e lj) { m_stroker.line_join(lj); } void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } line_cap_e line_cap() const { return m_stroker.line_cap(); } line_join_e line_join() const { return m_stroker.line_join(); } inner_join_e inner_join() const { return m_stroker.inner_join(); } void width(double w) { m_stroker.width(w); } void miter_limit(double ml) { m_stroker.miter_limit(ml); } void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } void approximation_scale(double as) { m_stroker.approximation_scale(as); } double width() const { return m_stroker.width(); } double miter_limit() const { return m_stroker.miter_limit(); } double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } double approximation_scale() const { return m_stroker.approximation_scale(); } void shorten(double s) { m_shorten = s; } double shorten() const { return m_shorten; } // Vertex Generator Interface void remove_all(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: vcgen_stroke(const vcgen_stroke&); const vcgen_stroke& operator = (const vcgen_stroke&); math_stroke<coord_storage> m_stroker; vertex_storage m_src_vertices; coord_storage m_out_vertices; double m_shorten; unsigned m_closed; status_e m_status; status_e m_prev_status; unsigned m_src_vertex; unsigned m_out_vertex; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_outline_image.h����������������������������������0000644�0024617�0000144�00000104450�12261257215�025170� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED #include "agg_array.h" #include "agg_math.h" #include "agg_line_aa_basics.h" #include "agg_dda_line.h" #include "agg_rendering_buffer.h" #include "agg_clip_liang_barsky.h" namespace mapserver { //========================================================line_image_scale template<class Source> class line_image_scale { public: typedef typename Source::color_type color_type; line_image_scale(const Source& src, double height) : m_source(src), m_height(height), m_scale(src.height() / height) { } double width() const { return m_source.width(); } double height() const { return m_height; } color_type pixel(int x, int y) const { double src_y = (y + 0.5) * m_scale - 0.5; int h = m_source.height() - 1; int y1 = ufloor(src_y); int y2 = y1 + 1; color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1); color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2); return pix1.gradient(pix2, src_y - y1); } private: line_image_scale(const line_image_scale<Source>&); const line_image_scale<Source>& operator = (const line_image_scale<Source>&); const Source& m_source; double m_height; double m_scale; }; //======================================================line_image_pattern template<class Filter> class line_image_pattern { public: typedef Filter filter_type; typedef typename filter_type::color_type color_type; //-------------------------------------------------------------------- line_image_pattern(const Filter& filter) : m_filter(&filter), m_dilation(filter.dilation() + 1), m_dilation_hr(m_dilation << line_subpixel_shift), m_data(), m_width(0), m_height(0), m_width_hr(0), m_half_height_hr(0), m_offset_y_hr(0) { } // Create //-------------------------------------------------------------------- template<class Source> line_image_pattern(const Filter& filter, const Source& src) : m_filter(&filter), m_dilation(filter.dilation() + 1), m_dilation_hr(m_dilation << line_subpixel_shift), m_data(), m_width(0), m_height(0), m_width_hr(0), m_half_height_hr(0), m_offset_y_hr(0) { create(src); } // Create //-------------------------------------------------------------------- template<class Source> void create(const Source& src) { m_height = uceil(src.height()); m_width = uceil(src.width()); m_width_hr = uround(src.width() * line_subpixel_scale); m_half_height_hr = uround(src.height() * line_subpixel_scale/2); m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; m_half_height_hr += line_subpixel_scale/2; m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2)); m_buf.attach(&m_data[0], m_width + m_dilation * 2, m_height + m_dilation * 2, m_width + m_dilation * 2); unsigned x, y; color_type* d1; color_type* d2; for(y = 0; y < m_height; y++) { d1 = m_buf.row_ptr(y + m_dilation) + m_dilation; for(x = 0; x < m_width; x++) { *d1++ = src.pixel(x, y); } } const color_type* s1; const color_type* s2; for(y = 0; y < m_dilation; y++) { //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation; //s2 = m_buf.row_ptr(m_dilation) + m_dilation; d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation; d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation; for(x = 0; x < m_width; x++) { //*d1++ = color_type(*s1++, 0); //*d2++ = color_type(*s2++, 0); *d1++ = color_type::no_color(); *d2++ = color_type::no_color(); } } unsigned h = m_height + m_dilation * 2; for(y = 0; y < h; y++) { s1 = m_buf.row_ptr(y) + m_dilation; s2 = m_buf.row_ptr(y) + m_dilation + m_width; d1 = m_buf.row_ptr(y) + m_dilation + m_width; d2 = m_buf.row_ptr(y) + m_dilation; for(x = 0; x < m_dilation; x++) { *d1++ = *s1++; *--d2 = *--s2; } } } //-------------------------------------------------------------------- int pattern_width() const { return m_width_hr; } int line_width() const { return m_half_height_hr; } double width() const { return m_height; } //-------------------------------------------------------------------- void pixel(color_type* p, int x, int y) const { m_filter->pixel_high_res(m_buf.rows(), p, x % m_width_hr + m_dilation_hr, y + m_offset_y_hr); } //-------------------------------------------------------------------- const filter_type& filter() const { return *m_filter; } private: line_image_pattern(const line_image_pattern<filter_type>&); const line_image_pattern<filter_type>& operator = (const line_image_pattern<filter_type>&); protected: row_ptr_cache<color_type> m_buf; const filter_type* m_filter; unsigned m_dilation; int m_dilation_hr; pod_array<color_type> m_data; unsigned m_width; unsigned m_height; int m_width_hr; int m_half_height_hr; int m_offset_y_hr; }; //=================================================line_image_pattern_pow2 template<class Filter> class line_image_pattern_pow2 : public line_image_pattern<Filter> { public: typedef Filter filter_type; typedef typename filter_type::color_type color_type; typedef line_image_pattern<Filter> base_type; //-------------------------------------------------------------------- line_image_pattern_pow2(const Filter& filter) : line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {} //-------------------------------------------------------------------- template<class Source> line_image_pattern_pow2(const Filter& filter, const Source& src) : line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) { create(src); } //-------------------------------------------------------------------- template<class Source> void create(const Source& src) { line_image_pattern<Filter>::create(src); m_mask = 1; while(m_mask < base_type::m_width) { m_mask <<= 1; m_mask |= 1; } m_mask <<= line_subpixel_shift - 1; m_mask |= line_subpixel_mask; base_type::m_width_hr = m_mask + 1; } //-------------------------------------------------------------------- void pixel(color_type* p, int x, int y) const { base_type::m_filter->pixel_high_res( base_type::m_buf.rows(), p, (x & m_mask) + base_type::m_dilation_hr, y + base_type::m_offset_y_hr); } private: unsigned m_mask; }; //===================================================distance_interpolator4 class distance_interpolator4 { public: //--------------------------------------------------------------------- distance_interpolator4() {} distance_interpolator4(int x1, int y1, int x2, int y2, int sx, int sy, int ex, int ey, int len, double scale, int x, int y) : m_dx(x2 - x1), m_dy(y2 - y1), m_dx_start(line_mr(sx) - line_mr(x1)), m_dy_start(line_mr(sy) - line_mr(y1)), m_dx_end(line_mr(ex) - line_mr(x2)), m_dy_end(line_mr(ey) - line_mr(y2)), m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - double(y + line_subpixel_scale/2 - y2) * double(m_dx))), m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end), m_len(uround(len / scale)) { double d = len * scale; int dx = iround(((x2 - x1) << line_subpixel_shift) / d); int dy = iround(((y2 - y1) << line_subpixel_shift) / d); m_dx_pict = -dy; m_dy_pict = dx; m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> line_subpixel_shift; m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; m_dx_start <<= line_mr_subpixel_shift; m_dy_start <<= line_mr_subpixel_shift; m_dx_end <<= line_mr_subpixel_shift; m_dy_end <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_pict += m_dy_pict; m_dist_end += m_dy_end; } //--------------------------------------------------------------------- void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_pict -= m_dy_pict; m_dist_end -= m_dy_end; } //--------------------------------------------------------------------- void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_pict -= m_dx_pict; m_dist_end -= m_dx_end; } //--------------------------------------------------------------------- void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_pict += m_dx_pict; m_dist_end += m_dx_end; } //--------------------------------------------------------------------- void inc_x(int dy) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_pict += m_dy_pict; m_dist_end += m_dy_end; if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_pict -= m_dx_pict; m_dist_end -= m_dx_end; } if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_pict += m_dx_pict; m_dist_end += m_dx_end; } } //--------------------------------------------------------------------- void dec_x(int dy) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_pict -= m_dy_pict; m_dist_end -= m_dy_end; if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_pict -= m_dx_pict; m_dist_end -= m_dx_end; } if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_pict += m_dx_pict; m_dist_end += m_dx_end; } } //--------------------------------------------------------------------- void inc_y(int dx) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_pict -= m_dx_pict; m_dist_end -= m_dx_end; if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_pict += m_dy_pict; m_dist_end += m_dy_end; } if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_pict -= m_dy_pict; m_dist_end -= m_dy_end; } } //--------------------------------------------------------------------- void dec_y(int dx) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_pict += m_dx_pict; m_dist_end += m_dx_end; if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_pict += m_dy_pict; m_dist_end += m_dy_end; } if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_pict -= m_dy_pict; m_dist_end -= m_dy_end; } } //--------------------------------------------------------------------- int dist() const { return m_dist; } int dist_start() const { return m_dist_start; } int dist_pict() const { return m_dist_pict; } int dist_end() const { return m_dist_end; } //--------------------------------------------------------------------- int dx() const { return m_dx; } int dy() const { return m_dy; } int dx_start() const { return m_dx_start; } int dy_start() const { return m_dy_start; } int dx_pict() const { return m_dx_pict; } int dy_pict() const { return m_dy_pict; } int dx_end() const { return m_dx_end; } int dy_end() const { return m_dy_end; } int len() const { return m_len; } private: //--------------------------------------------------------------------- int m_dx; int m_dy; int m_dx_start; int m_dy_start; int m_dx_pict; int m_dy_pict; int m_dx_end; int m_dy_end; int m_dist; int m_dist_start; int m_dist_pict; int m_dist_end; int m_len; }; //==================================================line_interpolator_image template<class Renderer> class line_interpolator_image { public: typedef Renderer renderer_type; typedef typename Renderer::color_type color_type; //--------------------------------------------------------------------- enum max_half_width_e { max_half_width = 64 }; //--------------------------------------------------------------------- line_interpolator_image(renderer_type& ren, const line_parameters& lp, int sx, int sy, int ex, int ey, int pattern_start, double scale_x) : m_lp(lp), m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : line_dbl_hr(lp.y2 - lp.y1), lp.vertical ? abs(lp.y2 - lp.y1) : abs(lp.x2 - lp.x1) + 1), m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), m_ren(ren), m_x(lp.x1 >> line_subpixel_shift), m_y(lp.y1 >> line_subpixel_shift), m_old_x(m_x), m_old_y(m_y), m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : abs((lp.x2 >> line_subpixel_shift) - m_x))), m_width(ren.subpixel_width()), //m_max_extent(m_width >> (line_subpixel_shift - 2)), m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift), m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), m_step(0) { mapserver::dda2_line_interpolator li(0, lp.vertical ? (lp.dy << mapserver::line_subpixel_shift) : (lp.dx << mapserver::line_subpixel_shift), lp.len); unsigned i; int stop = m_width + line_subpixel_scale * 2; for(i = 0; i < max_half_width; ++i) { m_dist_pos[i] = li.y(); if(m_dist_pos[i] >= stop) break; ++li; } m_dist_pos[i] = 0x7FFF0000; int dist1_start; int dist2_start; int npix = 1; if(lp.vertical) { do { --m_li; m_y -= lp.inc; m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; if(lp.inc > 0) m_di.dec_y(m_x - m_old_x); else m_di.inc_y(m_x - m_old_x); m_old_x = m_x; dist1_start = dist2_start = m_di.dist_start(); int dx = 0; if(dist1_start < 0) ++npix; do { dist1_start += m_di.dy_start(); dist2_start -= m_di.dy_start(); if(dist1_start < 0) ++npix; if(dist2_start < 0) ++npix; ++dx; } while(m_dist_pos[dx] <= m_width); if(npix == 0) break; npix = 0; } while(--m_step >= -m_max_extent); } else { do { --m_li; m_x -= lp.inc; m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; if(lp.inc > 0) m_di.dec_x(m_y - m_old_y); else m_di.inc_x(m_y - m_old_y); m_old_y = m_y; dist1_start = dist2_start = m_di.dist_start(); int dy = 0; if(dist1_start < 0) ++npix; do { dist1_start -= m_di.dx_start(); dist2_start += m_di.dx_start(); if(dist1_start < 0) ++npix; if(dist2_start < 0) ++npix; ++dy; } while(m_dist_pos[dy] <= m_width); if(npix == 0) break; npix = 0; } while(--m_step >= -m_max_extent); } m_li.adjust_forward(); m_step -= m_max_extent; } //--------------------------------------------------------------------- bool step_hor() { ++m_li; m_x += m_lp.inc; m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y); else m_di.dec_x(m_y - m_old_y); m_old_y = m_y; int s1 = m_di.dist() / m_lp.len; int s2 = -s1; if(m_lp.inc < 0) s1 = -s1; int dist_start; int dist_pict; int dist_end; int dy; int dist; dist_start = m_di.dist_start(); dist_pict = m_di.dist_pict() + m_start; dist_end = m_di.dist_end(); color_type* p0 = m_colors + max_half_width + 2; color_type* p1 = p0; int npix = 0; p1->clear(); if(dist_end > 0) { if(dist_start <= 0) { m_ren.pixel(p1, dist_pict, s2); } ++npix; } ++p1; dy = 1; while((dist = m_dist_pos[dy]) - s1 <= m_width) { dist_start -= m_di.dx_start(); dist_pict -= m_di.dx_pict(); dist_end -= m_di.dx_end(); p1->clear(); if(dist_end > 0 && dist_start <= 0) { if(m_lp.inc > 0) dist = -dist; m_ren.pixel(p1, dist_pict, s2 - dist); ++npix; } ++p1; ++dy; } dy = 1; dist_start = m_di.dist_start(); dist_pict = m_di.dist_pict() + m_start; dist_end = m_di.dist_end(); while((dist = m_dist_pos[dy]) + s1 <= m_width) { dist_start += m_di.dx_start(); dist_pict += m_di.dx_pict(); dist_end += m_di.dx_end(); --p0; p0->clear(); if(dist_end > 0 && dist_start <= 0) { if(m_lp.inc > 0) dist = -dist; m_ren.pixel(p0, dist_pict, s2 + dist); ++npix; } ++dy; } m_ren.blend_color_vspan(m_x, m_y - dy + 1, unsigned(p1 - p0), p0); return npix && ++m_step < m_count; } //--------------------------------------------------------------------- bool step_ver() { ++m_li; m_y += m_lp.inc; m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x); else m_di.dec_y(m_x - m_old_x); m_old_x = m_x; int s1 = m_di.dist() / m_lp.len; int s2 = -s1; if(m_lp.inc > 0) s1 = -s1; int dist_start; int dist_pict; int dist_end; int dist; int dx; dist_start = m_di.dist_start(); dist_pict = m_di.dist_pict() + m_start; dist_end = m_di.dist_end(); color_type* p0 = m_colors + max_half_width + 2; color_type* p1 = p0; int npix = 0; p1->clear(); if(dist_end > 0) { if(dist_start <= 0) { m_ren.pixel(p1, dist_pict, s2); } ++npix; } ++p1; dx = 1; while((dist = m_dist_pos[dx]) - s1 <= m_width) { dist_start += m_di.dy_start(); dist_pict += m_di.dy_pict(); dist_end += m_di.dy_end(); p1->clear(); if(dist_end > 0 && dist_start <= 0) { if(m_lp.inc > 0) dist = -dist; m_ren.pixel(p1, dist_pict, s2 + dist); ++npix; } ++p1; ++dx; } dx = 1; dist_start = m_di.dist_start(); dist_pict = m_di.dist_pict() + m_start; dist_end = m_di.dist_end(); while((dist = m_dist_pos[dx]) + s1 <= m_width) { dist_start -= m_di.dy_start(); dist_pict -= m_di.dy_pict(); dist_end -= m_di.dy_end(); --p0; p0->clear(); if(dist_end > 0 && dist_start <= 0) { if(m_lp.inc > 0) dist = -dist; m_ren.pixel(p0, dist_pict, s2 - dist); ++npix; } ++dx; } m_ren.blend_color_hspan(m_x - dx + 1, m_y, unsigned(p1 - p0), p0); return npix && ++m_step < m_count; } //--------------------------------------------------------------------- int pattern_end() const { return m_start + m_di.len(); } //--------------------------------------------------------------------- bool vertical() const { return m_lp.vertical; } int width() const { return m_width; } int count() const { return m_count; } private: line_interpolator_image(const line_interpolator_image<Renderer>&); const line_interpolator_image<Renderer>& operator = (const line_interpolator_image<Renderer>&); protected: const line_parameters& m_lp; dda2_line_interpolator m_li; distance_interpolator4 m_di; renderer_type& m_ren; int m_plen; int m_x; int m_y; int m_old_x; int m_old_y; int m_count; int m_width; int m_max_extent; int m_start; int m_step; int m_dist_pos[max_half_width + 1]; color_type m_colors[max_half_width * 2 + 4]; }; //===================================================renderer_outline_image template<class BaseRenderer, class ImagePattern> class renderer_outline_image { public: //--------------------------------------------------------------------- typedef BaseRenderer base_ren_type; typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type; typedef typename base_ren_type::color_type color_type; typedef ImagePattern pattern_type; //--------------------------------------------------------------------- renderer_outline_image(base_ren_type& ren, const pattern_type& patt) : m_ren(&ren), m_pattern(&patt), m_start(0), m_scale_x(1.0), m_clip_box(0,0,0,0), m_clipping(false) {} void attach(base_ren_type& ren) { m_ren = &ren; } //--------------------------------------------------------------------- void pattern(const pattern_type& p) { m_pattern = &p; } const pattern_type& pattern() const { return *m_pattern; } //--------------------------------------------------------------------- void reset_clipping() { m_clipping = false; } void clip_box(double x1, double y1, double x2, double y2) { m_clip_box.x1 = line_coord_sat::conv(x1); m_clip_box.y1 = line_coord_sat::conv(y1); m_clip_box.x2 = line_coord_sat::conv(x2); m_clip_box.y2 = line_coord_sat::conv(y2); m_clipping = true; } //--------------------------------------------------------------------- void scale_x(double s) { m_scale_x = s; } double scale_x() const { return m_scale_x; } //--------------------------------------------------------------------- void start_x(double s) { m_start = iround(s * line_subpixel_scale); } double start_x() const { return double(m_start) / line_subpixel_scale; } //--------------------------------------------------------------------- int subpixel_width() const { return m_pattern->line_width(); } int pattern_width() const { return m_pattern->pattern_width(); } double width() const { return double(subpixel_width()) / line_subpixel_scale; } //------------------------------------------------------------------------- void pixel(color_type* p, int x, int y) const { m_pattern->pixel(p, x, y); } //------------------------------------------------------------------------- void blend_color_hspan(int x, int y, unsigned len, const color_type* colors) { m_ren->blend_color_hspan(x, y, len, colors, 0); } //------------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, const color_type* colors) { m_ren->blend_color_vspan(x, y, len, colors, 0); } //------------------------------------------------------------------------- static bool accurate_join_only() { return true; } //------------------------------------------------------------------------- template<class Cmp> void semidot(Cmp, int, int, int, int) { } //------------------------------------------------------------------------- void pie(int, int, int, int, int, int) { } //------------------------------------------------------------------------- void line0(const line_parameters&) { } //------------------------------------------------------------------------- void line1(const line_parameters&, int, int) { } //------------------------------------------------------------------------- void line2(const line_parameters&, int, int) { } //------------------------------------------------------------------------- void line3_no_clip(const line_parameters& lp, int sx, int sy, int ex, int ey) { if(lp.len > line_max_length) { line_parameters lp1, lp2; lp.divide(lp1, lp2); int mx = lp1.x2 + (lp1.y2 - lp1.y1); int my = lp1.y2 - (lp1.x2 - lp1.x1); line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); return; } fix_degenerate_bisectrix_start(lp, &sx, &sy); fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_image<self_type> li(*this, lp, sx, sy, ex, ey, m_start, m_scale_x); if(li.vertical()) { while(li.step_ver()); } else { while(li.step_hor()); } m_start += uround(lp.len / m_scale_x); } //------------------------------------------------------------------------- void line3(const line_parameters& lp, int sx, int sy, int ex, int ey) { if(m_clipping) { int x1 = lp.x1; int y1 = lp.y1; int x2 = lp.x2; int y2 = lp.y2; unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); int start = m_start; if((flags & 4) == 0) { if(flags) { line_parameters lp2(x1, y1, x2, y2, uround(calc_distance(x1, y1, x2, y2))); if(flags & 1) { m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x); sx = x1 + (y2 - y1); sy = y1 - (x2 - x1); } else { while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) { sx = (lp.x1 + sx) >> 1; sy = (lp.y1 + sy) >> 1; } } if(flags & 2) { ex = x2 + (y2 - y1); ey = y2 - (x2 - x1); } else { while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) { ex = (lp.x2 + ex) >> 1; ey = (lp.y2 + ey) >> 1; } } line3_no_clip(lp2, sx, sy, ex, ey); } else { line3_no_clip(lp, sx, sy, ex, ey); } } m_start = start + uround(lp.len / m_scale_x); } else { line3_no_clip(lp, sx, sy, ex, ey); } } private: base_ren_type* m_ren; const pattern_type* m_pattern; int m_start; double m_scale_x; rect_i m_clip_box; bool m_clipping; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_adaptor_vpgen.h��������������������������������������0000644�0024617�0000144�00000011645�12261257215�024342� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED #define AGG_CONV_ADAPTOR_VPGEN_INCLUDED #include "agg_basics.h" namespace mapserver { //======================================================conv_adaptor_vpgen template<class VertexSource, class VPGen> class conv_adaptor_vpgen { public: explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} void attach(VertexSource& source) { m_source = &source; } VPGen& vpgen() { return m_vpgen; } const VPGen& vpgen() const { return m_vpgen; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&); const conv_adaptor_vpgen<VertexSource, VPGen>& operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&); VertexSource* m_source; VPGen m_vpgen; double m_start_x; double m_start_y; unsigned m_poly_flags; int m_vertices; }; //------------------------------------------------------------------------ template<class VertexSource, class VPGen> void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id) { m_source->rewind(path_id); m_vpgen.reset(); m_start_x = 0; m_start_y = 0; m_poly_flags = 0; m_vertices = 0; } //------------------------------------------------------------------------ template<class VertexSource, class VPGen> unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y) { unsigned cmd = path_cmd_stop; for(;;) { cmd = m_vpgen.vertex(x, y); if(!is_stop(cmd)) break; if(m_poly_flags && !m_vpgen.auto_unclose()) { *x = 0.0; *y = 0.0; cmd = m_poly_flags; m_poly_flags = 0; break; } if(m_vertices < 0) { if(m_vertices < -1) { m_vertices = 0; return path_cmd_stop; } m_vpgen.move_to(m_start_x, m_start_y); m_vertices = 1; continue; } double tx, ty; cmd = m_source->vertex(&tx, &ty); if(is_vertex(cmd)) { if(is_move_to(cmd)) { if(m_vpgen.auto_close() && m_vertices > 2) { m_vpgen.line_to(m_start_x, m_start_y); m_poly_flags = path_cmd_end_poly | path_flags_close; m_start_x = tx; m_start_y = ty; m_vertices = -1; continue; } m_vpgen.move_to(tx, ty); m_start_x = tx; m_start_y = ty; m_vertices = 1; } else { m_vpgen.line_to(tx, ty); ++m_vertices; } } else { if(is_end_poly(cmd)) { m_poly_flags = cmd; if(is_closed(cmd) || m_vpgen.auto_close()) { if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; if(m_vertices > 2) { m_vpgen.line_to(m_start_x, m_start_y); } m_vertices = 0; } } else { // path_cmd_stop if(m_vpgen.auto_close() && m_vertices > 2) { m_vpgen.line_to(m_start_x, m_start_y); m_poly_flags = path_cmd_end_poly | path_flags_close; m_vertices = -2; continue; } break; } } } return cmd; } } #endif �������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_pixfmt_transposer.h���������������������������������������0000644�0024617�0000144�00000014120�12261257215�024242� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED #define AGG_PIXFMT_TRANSPOSER_INCLUDED #include "agg_basics.h" namespace mapserver { //=======================================================pixfmt_transposer template<class PixFmt> class pixfmt_transposer { public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; typedef typename pixfmt_type::row_data row_data; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; //-------------------------------------------------------------------- pixfmt_transposer() : m_pixf(0) {} explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {} void attach(pixfmt_type& pixf) { m_pixf = &pixf; } //-------------------------------------------------------------------- AGG_INLINE unsigned width() const { return m_pixf->height(); } AGG_INLINE unsigned height() const { return m_pixf->width(); } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { return m_pixf->pixel(y, x); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { m_pixf->copy_pixel(y, x, c); } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { m_pixf->blend_pixel(y, x, c, cover); } //-------------------------------------------------------------------- AGG_INLINE void copy_hline(int x, int y, unsigned len, const color_type& c) { m_pixf->copy_vline(y, x, len, c); } //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { m_pixf->copy_hline(y, x, len, c); } //-------------------------------------------------------------------- AGG_INLINE void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { m_pixf->blend_vline(y, x, len, c, cover); } //-------------------------------------------------------------------- AGG_INLINE void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { m_pixf->blend_hline(y, x, len, c, cover); } //-------------------------------------------------------------------- AGG_INLINE void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { m_pixf->blend_solid_vspan(y, x, len, c, covers); } //-------------------------------------------------------------------- AGG_INLINE void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { m_pixf->blend_solid_hspan(y, x, len, c, covers); } //-------------------------------------------------------------------- AGG_INLINE void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) { m_pixf->copy_color_vspan(y, x, len, colors); } //-------------------------------------------------------------------- AGG_INLINE void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) { m_pixf->copy_color_hspan(y, x, len, colors); } //-------------------------------------------------------------------- AGG_INLINE void blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { m_pixf->blend_color_vspan(y, x, len, colors, covers, cover); } //-------------------------------------------------------------------- AGG_INLINE void blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { m_pixf->blend_color_hspan(y, x, len, colors, covers, cover); } private: pixfmt_type* m_pixf; }; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_renderer_primitives.h�������������������������������������0000644�0024617�0000144�00000017203�12261257215�024541� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- // // class renderer_primitives // //---------------------------------------------------------------------------- #ifndef AGG_RENDERER_PRIMITIVES_INCLUDED #define AGG_RENDERER_PRIMITIVES_INCLUDED #include "agg_basics.h" #include "agg_renderer_base.h" #include "agg_dda_line.h" #include "agg_ellipse_bresenham.h" namespace mapserver { //-----------------------------------------------------renderer_primitives template<class BaseRenderer> class renderer_primitives { public: typedef BaseRenderer base_ren_type; typedef typename base_ren_type::color_type color_type; //-------------------------------------------------------------------- explicit renderer_primitives(base_ren_type& ren) : m_ren(&ren), m_fill_color(), m_line_color(), m_curr_x(0), m_curr_y(0) {} void attach(base_ren_type& ren) { m_ren = &ren; } //-------------------------------------------------------------------- static int coord(double c) { return iround(c * line_bresenham_interpolator::subpixel_scale); } //-------------------------------------------------------------------- void fill_color(const color_type& c) { m_fill_color = c; } void line_color(const color_type& c) { m_line_color = c; } const color_type& fill_color() const { return m_fill_color; } const color_type& line_color() const { return m_line_color; } //-------------------------------------------------------------------- void rectangle(int x1, int y1, int x2, int y2) { m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full); m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full); m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full); m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full); } //-------------------------------------------------------------------- void solid_rectangle(int x1, int y1, int x2, int y2) { m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full); } //-------------------------------------------------------------------- void outlined_rectangle(int x1, int y1, int x2, int y2) { rectangle(x1, y1, x2, y2); m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full); } //-------------------------------------------------------------------- void ellipse(int x, int y, int rx, int ry) { ellipse_bresenham_interpolator ei(rx, ry); int dx = 0; int dy = -ry; do { dx += ei.dx(); dy += ei.dy(); m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); ++ei; } while(dy < 0); } //-------------------------------------------------------------------- void solid_ellipse(int x, int y, int rx, int ry) { ellipse_bresenham_interpolator ei(rx, ry); int dx = 0; int dy = -ry; int dy0 = dy; int dx0 = dx; do { dx += ei.dx(); dy += ei.dy(); if(dy != dy0) { m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full); } dx0 = dx; dy0 = dy; ++ei; } while(dy < 0); m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); } //-------------------------------------------------------------------- void outlined_ellipse(int x, int y, int rx, int ry) { ellipse_bresenham_interpolator ei(rx, ry); int dx = 0; int dy = -ry; do { dx += ei.dx(); dy += ei.dy(); m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); if(ei.dy() && dx) { m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full); m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full); } ++ei; } while(dy < 0); } //-------------------------------------------------------------------- void line(int x1, int y1, int x2, int y2, bool last=false) { line_bresenham_interpolator li(x1, y1, x2, y2); unsigned len = li.len(); if(len == 0) { if(last) { m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full); } return; } if(last) ++len; if(li.is_ver()) { do { m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full); li.vstep(); } while(--len); } else { do { m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full); li.hstep(); } while(--len); } } //-------------------------------------------------------------------- void move_to(int x, int y) { m_curr_x = x; m_curr_y = y; } //-------------------------------------------------------------------- void line_to(int x, int y, bool last=false) { line(m_curr_x, m_curr_y, x, y, last); m_curr_x = x; m_curr_y = y; } //-------------------------------------------------------------------- const base_ren_type& ren() const { return *m_ren; } base_ren_type& ren() { return *m_ren; } //-------------------------------------------------------------------- const rendering_buffer& rbuf() const { return m_ren->rbuf(); } rendering_buffer& rbuf() { return m_ren->rbuf(); } private: base_ren_type* m_ren; color_type m_fill_color; color_type m_line_color; int m_curr_x; int m_curr_y; }; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/include/agg_conv_unclose_polygon.h������������������������������������0000644�0024617�0000144�00000003262�12261257215�024724� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- #ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED #define AGG_CONV_UNCLOSE_POLYGON_INCLUDED #include "agg_basics.h" namespace mapserver { //====================================================conv_unclose_polygon template<class VertexSource> class conv_unclose_polygon { public: explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} void attach(VertexSource& source) { m_source = &source; } void rewind(unsigned path_id) { m_source->rewind(path_id); } unsigned vertex(double* x, double* y) { unsigned cmd = m_source->vertex(x, y); if(is_end_poly(cmd)) cmd &= ~path_flags_close; return cmd; } private: conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&); const conv_unclose_polygon<VertexSource>& operator = (const conv_unclose_polygon<VertexSource>&); VertexSource* m_source; }; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������mapserver-6.4.1/renderers/agg/copying���������������������������������������������������������������0000644�0024617�0000144�00000004754�12261257215�017450� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������The Anti-Grain Geometry Project A high quality rendering engine for C++ http://antigrain.com Anti-Grain Geometry has dual licensing model. The Modified BSD License was first added in version v2.4 just for convenience. It is a simple, permissive non-copyleft free software license, compatible with the GNU GPL. It's well proven and recognizable. See http://www.fsf.org/licensing/licenses/index_html#ModifiedBSD for details. Note that the Modified BSD license DOES NOT restrict your rights if you choose the Anti-Grain Geometry Public License. Anti-Grain Geometry Public License ==================================================== Anti-Grain Geometry - Version 2.4 Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. Modified BSD License ==================================================== Anti-Grain Geometry - Version 2.4 Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ��������������������mapserver-6.4.1/renderers/agg/readme����������������������������������������������������������������0000644�0024617�0000144�00000003721�12261257215�017226� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������The Anti-Grain Geometry Project A high quality rendering engine for C++ http://antigrain.com Anti-Grain Geometry - Version 2.4 Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. --------------------------------- Use automake to build the library. If automake is not available you still can use the old make. There is a very simple Makefile that can be used. Note that if you use automake it will overwrite Makefile. --------------------------------- If building on AmigaOS 4.0 or higher type the following for instructions on what targets are available. make -f Makefile.AmigaOS To just build and install AGG into the standard AmigaOS SDK ready for use type: make -f Makefile.AmigaOS install If you just want to build one demo (e.g. lion) use: make -f Makefile.AmigaOS bin/lion If you have any questions about the AmigaOS port please contact Steven Solie (ssolie@telus.net) for help. --------------------------------- To build all examples using SDL (Mac or Linux) just type: cd /examples/sdl make Individual examples can be built with make aa_test In the same way the native Carbon examples can be built with cd /examples/macosx_carbon make In both cases the static library will be built (if it was not already) from the existing global Makefile in /src/. The Makefiles for both SDL and Carbon will also attempt to download the required .bmp files if they are not found in the system for a given example. If the files could not be fetched (wget) the user will receive a message explaining where to download the samples from (sphere.bmp, etc.) Since all programs reside in the same directory there is no need to duplicate the .bmp files for each program that needs to use them. --------------------------------- �����������������������������������������������mapserver-6.4.1/mapservutil.c�����������������������������������������������������������������������0000644�0024617�0000144�00000214411�12261257215�016036� 0����������������������������������������������������������������������������������������������������ustar �tbonfort������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/****************************************************************************** * $id$ * * Project: MapServer * Purpose: MapServer CGI utility functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "mapserv.h" #include "maptime.h" /* ** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h). */ static int numModes = 23; static char *modeStrings[23] = {"BROWSE","ZOOMIN","ZOOMOUT","MAP","LEGEND","LEGENDICON","REFERENCE","SCALEBAR","COORDINATE", "QUERY","NQUERY","ITEMQUERY","ITEMNQUERY", "FEATUREQUERY","FEATURENQUERY","ITEMFEATUREQUERY","ITEMFEATURENQUERY", "INDEXQUERY","TILE","OWS", "WFS", "MAPLEGEND", "MAPLEGENDICON" }; int msCGIWriteLog(mapservObj *mapserv, int show_error) { FILE *stream; int i; time_t t; char szPath[MS_MAXPATHLEN]; if(!mapserv) return(MS_SUCCESS); if(!mapserv->map) return(MS_SUCCESS); if(!mapserv->map->web.log) return(MS_SUCCESS); if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, mapserv->map->web.log),"a")) == NULL) { msSetError(MS_IOERR, "%s", "msCGIWriteLog()", mapserv->map->web.log); return(MS_FAILURE); } t = time(NULL); fprintf(stream,"%s,",msStringChop(ctime(&t))); fprintf(stream,"%d,",(int)getpid()); if(getenv("REMOTE_ADDR") != NULL) fprintf(stream,"%s,",getenv("REMOTE_ADDR")); else fprintf(stream,"NULL,"); fprintf(stream,"%s,",mapserv->map->name); fprintf(stream,"%d,",mapserv->Mode); fprintf(stream,"%f %f %f %f,", mapserv->map->extent.minx, mapserv->map->extent.miny, mapserv->map->extent.maxx, mapserv->map->extent.maxy); fprintf(stream,"%f %f,", mapserv->mappnt.x, mapserv->mappnt.y); for(i=0; i<mapserv->NumLayers; i++) fprintf(stream, "%s ", mapserv->Layers[i]); fprintf(stream,","); if(show_error == MS_TRUE) msWriteError(stream); else fprintf(stream, "normal execution"); fprintf(stream,"\n"); fclose(stream); return(MS_SUCCESS); } void msCGIWriteError(mapservObj *mapserv) { errorObj *ms_error = msGetErrorObj(); if(!ms_error || ms_error->code == MS_NOERR || ms_error->isreported) { /* either we have no error, or it was already reported by other means */ return; } msCGIWriteLog(mapserv,MS_TRUE); if(!mapserv || !mapserv->map) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("<HTML>\n"); msIO_printf("<HEAD><TITLE>MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); return; } if((ms_error->code == MS_NOTFOUND) && (mapserv->map->web.empty)) { /* msRedirect(mapserv->map->web.empty); */ if(msReturnURL(mapserv, mapserv->map->web.empty, BROWSE) != MS_SUCCESS) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); } } else { if(mapserv->map->web.error) { /* msRedirect(mapserv->map->web.error); */ if(msReturnURL(mapserv, mapserv->map->web.error, BROWSE) != MS_SUCCESS) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); } } else { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); } } } /* ** Converts a string (e.g. form parameter) to a double, first checking the format against ** a regular expression. returns an error if the format test fails. */ #define GET_NUMERIC(string,dbl) do { \ dbl = strtod((string), &strtoderr);\ if (*strtoderr) {\ msSetError(MS_TYPEERR, NULL, "GET_NUMERIC()");\ return MS_FAILURE;\ }\ } while (0) static void setClassGroup(layerObj *layer, char *classgroup) { int i; if(!layer || !classgroup) return; for(i=0; inumclasses; i++) { if(layer->class[i]->group && strcmp(layer->class[i]->group, classgroup) == 0) { msFree(layer->classgroup); layer->classgroup = msStrdup(classgroup); return; /* bail */ } } } /* ** Extract Map File name from params and load it. ** Returns map object or NULL on error. */ mapObj *msCGILoadMap(mapservObj *mapserv) { int i, j; mapObj *map = NULL; for(i=0; irequest->NumParams; i++) /* find the mapfile parameter first */ if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break; if(i == mapserv->request->NumParams) { char *ms_mapfile = getenv("MS_MAPFILE"); if(ms_mapfile) { map = msLoadMap(ms_mapfile,NULL); } else { msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */ return NULL; } } else { if(getenv(mapserv->request->ParamValues[i])) /* an environment variable references the actual file to use */ map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL); else { /* by here we know the request isn't for something in an environment variable */ if(getenv("MS_MAP_NO_PATH")) { msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()"); return NULL; } if(getenv("MS_MAP_PATTERN") && msEvalRegex(getenv("MS_MAP_PATTERN"), mapserv->request->ParamValues[i]) != MS_TRUE) { msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()"); return NULL; } /* ok to try to load now */ map = msLoadMap(mapserv->request->ParamValues[i], NULL); } } if(!map) return NULL; if(!msLookupHashTable(&(map->web.validation), "immutable")) { /* check for any %variable% substitutions here, also do any map_ changes, we do this here so WMS/WFS */ /* services can take advantage of these "vendor specific" extensions */ for(i=0; irequest->NumParams; i++) { /* ** a few CGI variables should be skipped altogether ** ** qstring: there is separate per layer validation for attribute queries and the substitution checks ** below conflict with that so we avoid it here */ if(strncasecmp(mapserv->request->ParamNames[i],"qstring",7) == 0) continue; /* check to see if there are any additions to the mapfile */ if(strncasecmp(mapserv->request->ParamNames[i],"map_",4) == 0 || strncasecmp(mapserv->request->ParamNames[i],"map.",4) == 0) { if(msUpdateMapFromURL(map, mapserv->request->ParamNames[i], mapserv->request->ParamValues[i]) != MS_SUCCESS) { msFreeMap(map); return NULL; } continue; } if(strncasecmp(mapserv->request->ParamNames[i],"classgroup",10) == 0) { /* #4207 */ for(j=0; jnumlayers; j++) { setClassGroup(GET_LAYER(map, j), mapserv->request->ParamValues[i]); } continue; } } msApplySubstitutions(map, mapserv->request->ParamNames, mapserv->request->ParamValues, mapserv->request->NumParams); msApplyDefaultSubstitutions(map); /* check to see if a ogc map context is passed as argument. if there */ /* is one load it */ for(i=0; irequest->NumParams; i++) { if(strcasecmp(mapserv->request->ParamNames[i],"context") == 0) { if(mapserv->request->ParamValues[i] && strlen(mapserv->request->ParamValues[i]) > 0) { if(strncasecmp(mapserv->request->ParamValues[i],"http",4) == 0) { if(msGetConfigOption(map, "CGI_CONTEXT_URL")) msLoadMapContextURL(map, mapserv->request->ParamValues[i], MS_FALSE); } else msLoadMapContext(map, mapserv->request->ParamValues[i], MS_FALSE); } } } } /* * RFC-42 HTTP Cookie Forwarding * Here we set the http_cookie_data metadata to handle the * HTTP Cookie Forwarding. The content of this metadata is the cookie * content. In the future, this metadata will probably be replaced * by an object that is part of the mapObject that would contain * information on the application status (such as cookie). */ if( mapserv->request->httpcookiedata != NULL ) { msInsertHashTable( &(map->web.metadata), "http_cookie_data", mapserv->request->httpcookiedata ); } return map; } /* ** Set operation mode. First look in MS_MODE env. var. as a ** default value that can be overridden by the mode=... CGI param. ** Returns silently, leaving mapserv->Mode unchanged if mode param not set. */ int msCGISetMode(mapservObj *mapserv) { const char *mode = NULL; int i, j; mode = getenv("MS_MODE"); for( i=0; irequest->NumParams; i++ ) { if(strcasecmp(mapserv->request->ParamNames[i], "mode") == 0) { mode = mapserv->request->ParamValues[i]; break; } } if (mode) { for(j=0; jMode = j; break; } } if(j == numModes) { msSetError(MS_WEBERR, "Invalid mode.", "msCGISetMode()"); return MS_FAILURE; } } if (mapserv->Mode >= 0) { int disabled = MS_FALSE; const char* enable_modes = msLookupHashTable(&mapserv->map->web.metadata, "ms_enable_modes"); if (!msOWSParseRequestMetadata(enable_modes, mode, &disabled) && disabled) { /* the current mode is disabled */ msSetError(MS_WEBERR, "The specified mode '%s' is not supported by the current map configuration", "msCGISetMode()", mode); return MS_FAILURE; } } return MS_SUCCESS; } /* ** Process CGI parameters. */ int msCGILoadForm(mapservObj *mapserv) { int i,n; char **tokens=NULL; int rosa_type=0; double tmpval; char *strtoderr; for(i=0; irequest->NumParams; i++) { /* now process the rest of the form variables */ if(strlen(mapserv->request->ParamValues[i]) == 0) continue; if(strcasecmp(mapserv->request->ParamNames[i],"icon") == 0) { mapserv->icon = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"queryfile") == 0) { mapserv->QueryFile = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"savequery") == 0) { mapserv->savequery = MS_TRUE; continue; } /* Insecure as implemented, need to save someplace non accessible by everyone in the universe if(strcasecmp(mapserv->request->ParamNames[i],"savemap") == 0) { mapserv->savemap = MS_TRUE; continue; } */ if(strcasecmp(mapserv->request->ParamNames[i],"zoom") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->Zoom); if((mapserv->Zoom > MAXZOOM) || (mapserv->Zoom < MINZOOM)) { msSetError(MS_WEBERR, "Zoom value out of range.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"zoomdir") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->ZoomDirection = (int)tmpval; if((mapserv->ZoomDirection != -1) && (mapserv->ZoomDirection != 1) && (mapserv->ZoomDirection != 0)) { msSetError(MS_WEBERR, "Zoom direction must be 1, 0 or -1.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"zoomsize") == 0) { /* absolute zoom magnitude */ GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->ZoomSize = (int)tmpval; if((mapserv->ZoomSize > MAXZOOM) || (mapserv->ZoomSize < 1)) { msSetError(MS_WEBERR, "Invalid zoom size.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgext") == 0) { /* extent of an existing image in a web application */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 4) { msSetError(MS_WEBERR, "Not enough arguments for imgext.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],mapserv->ImgExt.minx); GET_NUMERIC(tokens[1],mapserv->ImgExt.miny); GET_NUMERIC(tokens[2],mapserv->ImgExt.maxx); GET_NUMERIC(tokens[3],mapserv->ImgExt.maxy); msFreeCharArray(tokens, 4); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"searchmap") == 0) { mapserv->SearchMap = MS_TRUE; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"id") == 0) { if(msEvalRegex(IDPATTERN, mapserv->request->ParamValues[i]) == MS_FALSE) { msSetError(MS_WEBERR, "Parameter 'id' value fails to validate.", "msCGILoadForm()"); return MS_FAILURE; } strlcpy(mapserv->Id, mapserv->request->ParamValues[i], IDSIZE); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"mapext") == 0) { /* extent of the new map or query */ if(strncasecmp(mapserv->request->ParamValues[i],"shape",5) == 0) mapserv->UseShapes = MS_TRUE; else { tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 4) { msSetError(MS_WEBERR, "Not enough arguments for mapext.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],mapserv->map->extent.minx); GET_NUMERIC(tokens[1],mapserv->map->extent.miny); GET_NUMERIC(tokens[2],mapserv->map->extent.maxx); GET_NUMERIC(tokens[3],mapserv->map->extent.maxy); msFreeCharArray(tokens, 4); #ifdef USE_PROJ /* * If there is a projection in the map file, and it is not lon/lat, and the * extents "look like" they *are* lon/lat, based on their size, * then convert the extents to the map file projection. * * DANGER: If the extents are legitimately in the mapfile projection * and coincidentally fall in the lon/lat range, bad things * will ensue. */ if(mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj) && (mapserv->map->extent.minx >= -180.0 && mapserv->map->extent.minx <= 180.0) && (mapserv->map->extent.miny >= -90.0 && mapserv->map->extent.miny <= 90.0) && (mapserv->map->extent.maxx >= -180.0 && mapserv->map->extent.maxx <= 180.0) && (mapserv->map->extent.maxy >= -90.0 && mapserv->map->extent.maxy <= 90.0)) { msProjectRect(&(mapserv->map->latlon), &(mapserv->map->projection), &(mapserv->map->extent)); /* extent is a in lat/lon */ } #endif if((mapserv->map->extent.minx != mapserv->map->extent.maxx) && (mapserv->map->extent.miny != mapserv->map->extent.maxy)) { /* extent seems ok */ mapserv->CoordSource = FROMUSERBOX; mapserv->QueryCoordSource = FROMUSERBOX; } } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"minx") == 0) { /* extent of the new map, in pieces */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.minx); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"maxx") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.maxx); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"miny") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.miny); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"maxy") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.maxy); mapserv->CoordSource = FROMUSERBOX; mapserv->QueryCoordSource = FROMUSERBOX; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"mapxy") == 0) { /* user map coordinate */ if(strncasecmp(mapserv->request->ParamValues[i],"shape",5) == 0) { mapserv->UseShapes = MS_TRUE; } else { tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for mapxy.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],mapserv->mappnt.x ); GET_NUMERIC(tokens[1],mapserv->mappnt.y ); msFreeCharArray(tokens, 2); #ifdef USE_PROJ if(mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj) && (mapserv->mappnt.x >= -180.0 && mapserv->mappnt.x <= 180.0) && (mapserv->mappnt.y >= -90.0 && mapserv->mappnt.y <= 90.0)) { msProjectPoint(&(mapserv->map->latlon), &(mapserv->map->projection), &mapserv->mappnt); /* point is a in lat/lon */ } #endif if(mapserv->CoordSource == NONE) { /* don't override previous settings (i.e. buffer or scale ) */ mapserv->CoordSource = FROMUSERPNT; mapserv->QueryCoordSource = FROMUSERPNT; } } continue; } /* ** Query shape consisting of map or image coordinates. It's almost identical processing so we'll do either in this block... */ if(strcasecmp(mapserv->request->ParamNames[i], "mapshape") == 0 || strcasecmp(mapserv->request->ParamNames[i], "imgshape") == 0) { if(strcasecmp(mapserv->request->ParamNames[i],"mapshape") == 0) mapserv->QueryCoordSource = FROMUSERSHAPE; else mapserv->QueryCoordSource = FROMIMGSHAPE; if(strchr(mapserv->request->ParamValues[i], '(') != NULL) { /* try WKT */ if((mapserv->map->query.shape = msShapeFromWKT(mapserv->request->ParamValues[i])) == NULL) { msSetError(MS_WEBERR, "WKT parse failed for mapshape/imgshape.", "msCGILoadForm()"); return MS_FAILURE; } } else { lineObj line= {0,NULL}; char **tmp=NULL; int n, j; tmp = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(n%2 != 0 || n<8) { /* n must be even and be at least 8 */ msSetError(MS_WEBERR, "Malformed polygon geometry for mapshape/imgshape.", "msCGILoadForm()"); return MS_FAILURE; } line.numpoints = n/2; if((line.point = (pointObj *)malloc(sizeof(pointObj)*line.numpoints)) == NULL) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if((mapserv->map->query.shape = (shapeObj *) malloc(sizeof(shapeObj))) == NULL) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } msInitShape(mapserv->map->query.shape); mapserv->map->query.shape->type = MS_SHAPE_POLYGON; for(j=0; jQueryCoordSource == FROMUSERSHAPE && mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj) && (line.point[j].x >= -180.0 && line.point[j].x <= 180.0) && (line.point[j].y >= -90.0 && line.point[j].y <= 90.0)) { msProjectPoint(&(mapserv->map->latlon), &(mapserv->map->projection), &line.point[j]); /* point is a in lat/lon */ } #endif } if(msAddLine(mapserv->map->query.shape, &line) == -1) { msFree(line.point); msFreeCharArray(tmp, n); return MS_FAILURE; } msFree(line.point); msFreeCharArray(tmp, n); } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"img.x") == 0) { /* mouse click, in pieces */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ImgPnt.x); if((mapserv->ImgPnt.x > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.x < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"img.y") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ImgPnt.y); if((mapserv->ImgPnt.y > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgxy") == 0) { /* mouse click, single variable */ if(mapserv->CoordSource == FROMIMGPNT) continue; tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for imgxy.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],mapserv->ImgPnt.x ); GET_NUMERIC(tokens[1],mapserv->ImgPnt.y ); msFreeCharArray(tokens, 2); if((mapserv->ImgPnt.x > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.x < (-2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Reference map coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } if(mapserv->CoordSource == NONE) { /* override nothing since this parameter is usually used to hold a default value */ mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgbox") == 0) { /* selection box (eg. mouse drag) */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 4) { msSetError(MS_WEBERR, "Not enough arguments for imgbox.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],mapserv->ImgBox.minx); GET_NUMERIC(tokens[1],mapserv->ImgBox.miny); GET_NUMERIC(tokens[2],mapserv->ImgBox.maxx); GET_NUMERIC(tokens[3],mapserv->ImgBox.maxy); msFreeCharArray(tokens, 4); if((mapserv->ImgBox.minx != mapserv->ImgBox.maxx) && (mapserv->ImgBox.miny != mapserv->ImgBox.maxy)) { /* must not degenerate into a point */ mapserv->CoordSource = FROMIMGBOX; mapserv->QueryCoordSource = FROMIMGBOX; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"ref.x") == 0) { /* mouse click in reference image, in pieces */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->RefPnt.x); if((mapserv->RefPnt.x > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.x < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMREFPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"ref.y") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->RefPnt.y); if((mapserv->RefPnt.y > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMREFPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"refxy") == 0) { /* mouse click in reference image, single variable */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for imgxy.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],mapserv->RefPnt.x); GET_NUMERIC(tokens[1],mapserv->RefPnt.y); msFreeCharArray(tokens, 2); if((mapserv->RefPnt.x > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.x < (-2*mapserv->map->maxsize)) || (mapserv->RefPnt.y > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Reference map coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMREFPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"buffer") == 0) { /* radius (map units), actually 1/2 square side */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->Buffer); mapserv->CoordSource = FROMBUF; mapserv->QueryCoordSource = FROMUSERPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"scale") == 0 || strcasecmp(mapserv->request->ParamNames[i],"scaledenom") == 0) { /* scale for new map */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ScaleDenom); if(mapserv->ScaleDenom <= 0) { msSetError(MS_WEBERR, "Scale out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMSCALE; mapserv->QueryCoordSource = FROMUSERPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgsize") == 0) { /* size of existing image (pixels) */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for imgsize.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],tmpval); mapserv->ImgCols = (int)tmpval; GET_NUMERIC(tokens[1],tmpval); mapserv->ImgRows = (int)tmpval; msFreeCharArray(tokens, 2); if(mapserv->ImgCols > mapserv->map->maxsize || mapserv->ImgRows > mapserv->map->maxsize || mapserv->ImgCols <= 0 || mapserv->ImgRows <= 0) { msSetError(MS_WEBERR, "Image size out of range.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"mapsize") == 0) { /* size of new map (pixels) */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for mapsize.", "msCGILoadForm()"); return MS_FAILURE; } GET_NUMERIC(tokens[0],tmpval); mapserv->map->width = (int)tmpval; GET_NUMERIC(tokens[1],tmpval); mapserv->map->height = (int)tmpval; msFreeCharArray(tokens, 2); if(mapserv->map->width > mapserv->map->maxsize || mapserv->map->height > mapserv->map->maxsize || mapserv->map->width <= 0 || mapserv->map->height <= 0) { msSetError(MS_WEBERR, "Image size out of range.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strncasecmp(mapserv->request->ParamNames[i],"layers", 6) == 0) { /* turn a set of layers, delimited by spaces, on */ /* If layers=all then turn on all layers */ if (strcasecmp(mapserv->request->ParamValues[i], "all") == 0 && mapserv->map != NULL) { int l; /* Reset NumLayers=0. If individual layers were already selected then free the previous values. */ for(l=0; lNumLayers; l++) msFree(mapserv->Layers[l]); mapserv->NumLayers=0; for(mapserv->NumLayers=0; mapserv->NumLayers < mapserv->map->numlayers; mapserv->NumLayers++) { if(msGrowMapservLayers(mapserv) == MS_FAILURE) return MS_FAILURE; if(GET_LAYER(mapserv->map, mapserv->NumLayers)->name) { mapserv->Layers[mapserv->NumLayers] = msStrdup(GET_LAYER(mapserv->map, mapserv->NumLayers)->name); } else { mapserv->Layers[mapserv->NumLayers] = msStrdup(""); } } } else { int num_layers=0, l; char **layers=NULL; layers = msStringSplit(mapserv->request->ParamValues[i], ' ', &(num_layers)); for(l=0; lLayers[mapserv->NumLayers++] = msStrdup(layers[l]); } msFreeCharArray(layers, num_layers); num_layers = 0; } continue; } if(strncasecmp(mapserv->request->ParamNames[i],"layer", 5) == 0) { /* turn a single layer/group on */ if(msGrowMapservLayers(mapserv) == MS_FAILURE) return MS_FAILURE; mapserv->Layers[mapserv->NumLayers] = msStrdup(mapserv->request->ParamValues[i]); mapserv->NumLayers++; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qlayer") == 0) { /* layer to query (i.e search) */ mapserv->QueryLayer = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qitem") == 0) { /* attribute to query on (optional) */ mapserv->QueryItem = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qstring") == 0) { /* attribute query string */ mapserv->QueryString = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qformat") == 0) { /* format to apply to query results (shortcut instead of having to use "map.web=QUERYFORMAT+foo") */ if(mapserv->map->web.queryformat) free(mapserv->map->web.queryformat); /* avoid leak */ mapserv->map->web.queryformat = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"slayer") == 0) { /* layer to select (for feature based search) */ mapserv->SelectLayer = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"shapeindex") == 0) { /* used for index queries */ GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->ShapeIndex = (int)tmpval; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"tileindex") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->TileIndex = (int)tmpval; continue; } /* -------------------------------------------------------------------- * The following code is used to support mode=tile * -------------------------------------------------------------------- */ if(strcasecmp(mapserv->request->ParamNames[i], "tilemode") == 0) { /* currently, only valid tilemode is "spheremerc" */ if( strcasecmp(mapserv->request->ParamValues[i], "gmap") == 0) { mapserv->TileMode = TILE_GMAP; } else if ( strcasecmp(mapserv->request->ParamValues[i], "ve") == 0 ) { mapserv->TileMode = TILE_VE; } else { msSetError(MS_WEBERR, "Invalid tilemode. Use one of: gmap, ve", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"tile") == 0) { if( strlen(mapserv->request->ParamValues[i]) < 1 ) { msSetError(MS_WEBERR, "Empty tile parameter.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMTILE; mapserv->TileCoords = msStrdup(mapserv->request->ParamValues[i]); continue; } /* -------------------------------------------------------------------- */ /* The following code is used to support the rosa applet (for */ /* more information on Rosa, please consult : */ /* http://www.maptools.org/rosa/) . */ /* This code was provided by Tim.Mackey@agso.gov.au. */ /* */ /* For Application using it can be seen at : */ /* http://www.agso.gov.au/map/pilbara/ */ /* */ /* -------------------------------------------------------------------- */ if(strcasecmp(mapserv->request->ParamNames[i],"INPUT_TYPE") == 0) { /* Rosa input type */ if(strcasecmp(mapserv->request->ParamValues[i],"auto_rect") == 0) { rosa_type=1; /* rectangle */ continue; } if(strcasecmp(mapserv->request->ParamValues[i],"auto_point") == 0) { rosa_type=2; /* point */ continue; } } if(strcasecmp(mapserv->request->ParamNames[i],"INPUT_COORD") == 0) { /* Rosa coordinates */ switch(rosa_type) { case 1: sscanf(mapserv->request->ParamValues[i],"%lf,%lf;%lf,%lf", &mapserv->ImgBox.minx,&mapserv->ImgBox.miny,&mapserv->ImgBox.maxx, &mapserv->ImgBox.maxy); if((mapserv->ImgBox.minx != mapserv->ImgBox.maxx) && (mapserv->ImgBox.miny != mapserv->ImgBox.maxy)) { mapserv->CoordSource = FROMIMGBOX; mapserv->QueryCoordSource = FROMIMGBOX; } else { mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; mapserv->ImgPnt.x=mapserv->ImgBox.minx; mapserv->ImgPnt.y=mapserv->ImgBox.miny; } break; case 2: sscanf(mapserv->request->ParamValues[i],"%lf,%lf",&mapserv->ImgPnt.x, &mapserv->ImgPnt.y); mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; break; } continue; } /* -------------------------------------------------------------------- */ /* end of code for Rosa support. */ /* -------------------------------------------------------------------- */ } /* next parameter */ if(mapserv->Mode == ZOOMIN) { mapserv->ZoomDirection = 1; mapserv->Mode = BROWSE; } if(mapserv->Mode == ZOOMOUT) { mapserv->ZoomDirection = -1; mapserv->Mode = BROWSE; } if(mapserv->ZoomSize != 0) { /* use direction and magnitude to calculate zoom */ if(mapserv->ZoomDirection == 0) { mapserv->fZoom = 1; } else { mapserv->fZoom = mapserv->ZoomSize*mapserv->ZoomDirection; if(mapserv->fZoom < 0) mapserv->fZoom = 1.0/MS_ABS(mapserv->fZoom); } } else { /* use single value for zoom */ if((mapserv->Zoom >= -1) && (mapserv->Zoom <= 1)) { mapserv->fZoom = 1; /* pan */ } else { if(mapserv->Zoom < 0) mapserv->fZoom = 1.0/MS_ABS(mapserv->Zoom); else mapserv->fZoom = mapserv->Zoom; } } if(mapserv->ImgRows == -1) mapserv->ImgRows = mapserv->map->height; if(mapserv->ImgCols == -1) mapserv->ImgCols = mapserv->map->width; if(mapserv->map->height == -1) mapserv->map->height = mapserv->ImgRows; if(mapserv->map->width == -1) mapserv->map->width = mapserv->ImgCols; return MS_SUCCESS; } int setExtentFromShapes(mapservObj *mapserv) { double dx, dy, cellsize; rectObj tmpext= {-1.0,-1.0,-1.0,-1.0}; pointObj tmppnt= {-1.0,-1.0}; msGetQueryResultBounds(mapserv->map, &(tmpext)); dx = tmpext.maxx - tmpext.minx; dy = tmpext.maxy - tmpext.miny; tmppnt.x = (tmpext.maxx + tmpext.minx)/2; tmppnt.y = (tmpext.maxy + tmpext.miny)/2; tmpext.minx -= dx*EXTENT_PADDING/2.0; tmpext.maxx += dx*EXTENT_PADDING/2.0; tmpext.miny -= dy*EXTENT_PADDING/2.0; tmpext.maxy += dy*EXTENT_PADDING/2.0; if(mapserv->ScaleDenom != 0) { /* apply the scale around the center point (tmppnt) */ cellsize = (mapserv->ScaleDenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale */ tmpext.minx = tmppnt.x - cellsize*mapserv->map->width/2.0; tmpext.miny = tmppnt.y - cellsize*mapserv->map->height/2.0; tmpext.maxx = tmppnt.x + cellsize*mapserv->map->width/2.0; tmpext.maxy = tmppnt.y + cellsize*mapserv->map->height/2.0; } else if(mapserv->Buffer != 0) { /* apply the buffer around the center point (tmppnt) */ tmpext.minx = tmppnt.x - mapserv->Buffer; tmpext.miny = tmppnt.y - mapserv->Buffer; tmpext.maxx = tmppnt.x + mapserv->Buffer; tmpext.maxy = tmppnt.y + mapserv->Buffer; } /* in case we don't get usable extent at this point (i.e. single point result) */ if(!MS_VALID_EXTENT(tmpext)) { if(mapserv->map->web.minscaledenom > 0) { /* try web object minscale first */ cellsize = (mapserv->map->web.minscaledenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale */ tmpext.minx = tmppnt.x - cellsize*mapserv->map->width/2.0; tmpext.miny = tmppnt.y - cellsize*mapserv->map->height/2.0; tmpext.maxx = tmppnt.x + cellsize*mapserv->map->width/2.0; tmpext.maxy = tmppnt.y + cellsize*mapserv->map->height/2.0; } else { msSetError(MS_WEBERR, "No way to generate a valid map extent from selected shapes.", "mapserv()"); return MS_FAILURE; } } mapserv->mappnt = tmppnt; mapserv->map->extent = mapserv->RawExt = tmpext; /* save unadjusted extent */ return MS_SUCCESS; } /* FIX: NEED ERROR CHECKING HERE FOR IMGPNT or MAPPNT */ void setCoordinate(mapservObj *mapserv) { double cellx,celly; cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->ImgPnt.x, mapserv->ImgExt.minx, cellx); mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->ImgPnt.y, mapserv->ImgExt.maxy, celly); return; } int msCGIDispatchBrowseRequest(mapservObj *mapserv) { char *template = NULL; int i,status; for(i=0; irequest->NumParams; i++) /* find the template param value */ if (strcasecmp(mapserv->request->ParamNames[i], "template") == 0) template = mapserv->request->ParamValues[i]; if ( (!mapserv->map->web.template) && (template==NULL || (strcasecmp(template, "openlayers")!=0)) ) { msSetError(MS_WEBERR, "Traditional BROWSE mode requires a TEMPLATE in the WEB section, but none was provided.", "mapserv()"); return MS_FAILURE; } if(mapserv->QueryFile) { status = msLoadQuery(mapserv->map, mapserv->QueryFile); if(status != MS_SUCCESS) return MS_FAILURE; } status = setExtent(mapserv); if(status != MS_SUCCESS) return MS_FAILURE; status = checkWebScale(mapserv); if(status != MS_SUCCESS) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* generate map, legend, scalebar and refernce images. */ /* -------------------------------------------------------------------- */ if(msGenerateImages(mapserv, MS_FALSE, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; if ( (template != NULL) && (strcasecmp(template, "openlayers")==0) ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); if (msReturnOpenLayersPage(mapserv) != MS_SUCCESS) return MS_FAILURE; } else if(mapserv->QueryFile) { if(msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, NULL) != MS_SUCCESS) return MS_FAILURE; } else { if(TEMPLATE_TYPE(mapserv->map->web.template) == MS_FILE) { /* if thers's an html template, then use it */ if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s", mapserv->map->web.browseformat); /* write MIME header */ msIO_sendHeaders(); } if(msReturnPage(mapserv, mapserv->map->web.template, BROWSE, NULL) != MS_SUCCESS) return MS_FAILURE; } else { if(msReturnURL(mapserv, mapserv->map->web.template, BROWSE) != MS_SUCCESS) return MS_FAILURE; } } return MS_SUCCESS; } int msCGIDispatchCoordinateRequest(mapservObj *mapserv) { setCoordinate(mapserv); /* mouse click => map coord */ msIO_printf("Your \"click\" corresponds to (approximately): (%g, %g).", mapserv->mappnt.x, mapserv->mappnt.y); #ifdef USE_PROJ if(mapserv->map->projection.proj != NULL && !pj_is_latlong(mapserv->map->projection.proj) ) { pointObj p=mapserv->mappnt; msProjectPoint(&(mapserv->map->projection), &(mapserv->map->latlon), &p); msIO_printf("Computed lat/lon value is (%g, %g).\n",p.x, p.y); } #endif return MS_SUCCESS; } int msCGIDispatchQueryRequest(mapservObj *mapserv) { int status,i,j; char buffer[1024]; if(mapserv->QueryFile) { /* already got a completed query */ status = msLoadQuery(mapserv->map, mapserv->QueryFile); if(status != MS_SUCCESS) return MS_FAILURE; } else { if((mapserv->QueryLayerIndex = msGetLayerIndex(mapserv->map, mapserv->QueryLayer)) != -1) /* force the query layer on */ GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->status = MS_ON; switch(mapserv->Mode) { case ITEMFEATUREQUERY: case ITEMFEATURENQUERY: if((mapserv->SelectLayerIndex = msGetLayerIndex(mapserv->map, mapserv->SelectLayer)) == -1) { /* force the selection layer on */ msSetError(MS_WEBERR, "Selection layer not set or references an invalid layer.", "mapserv()"); return MS_FAILURE; } GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->status = MS_ON; /* validate the qstring parameter */ if(msValidateParameter(mapserv->QueryString, msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->validation), "qstring"), msLookupHashTable(&(mapserv->map->web.validation), "qstring"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_WEBERR, "Parameter 'qstring' value fails to validate.", "mapserv()"); return MS_FAILURE; } if(mapserv->QueryCoordSource != NONE && !mapserv->UseShapes) if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */ return MS_FAILURE; mapserv->map->query.type = MS_QUERY_BY_ATTRIBUTE; if(mapserv->QueryItem) mapserv->map->query.item = msStrdup(mapserv->QueryItem); if(mapserv->QueryString) mapserv->map->query.str = msStrdup(mapserv->QueryString); mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.mode = MS_QUERY_MULTIPLE; if(mapserv->Mode == ITEMFEATUREQUERY) mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.slayer = mapserv->SelectLayerIndex; /* this will trigger the feature query eventually */ break; case FEATUREQUERY: case FEATURENQUERY: if((mapserv->SelectLayerIndex = msGetLayerIndex(mapserv->map, mapserv->SelectLayer)) == -1) { /* force the selection layer on */ msSetError(MS_WEBERR, "Selection layer not set or references an invalid layer.", "mapserv()"); return MS_FAILURE; } GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->status = MS_ON; if(mapserv->Mode == FEATUREQUERY) { switch(mapserv->QueryCoordSource) { case FROMIMGPNT: mapserv->map->extent = mapserv->ImgExt; /* use the existing map extent */ setCoordinate(mapserv); break; case FROMUSERPNT: break; default: msSetError(MS_WEBERR, "No way to perform the initial search, not enough information.", "mapserv()"); return MS_FAILURE; break; } mapserv->map->query.type = MS_QUERY_BY_POINT; mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.buffer = mapserv->Buffer; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.slayer = mapserv->SelectLayerIndex; /* this will trigger the feature query eventually */ } else { /* FEATURENQUERY */ switch(mapserv->QueryCoordSource) { case FROMIMGPNT: mapserv->map->extent = mapserv->ImgExt; /* use the existing map extent */ setCoordinate(mapserv); mapserv->map->query.type = MS_QUERY_BY_POINT; break; case FROMIMGBOX: /* TODO: this option was present but with no code to leverage the image box... */ break; case FROMUSERPNT: mapserv->map->query.type = MS_QUERY_BY_POINT; default: if(MS_SUCCESS != setExtent(mapserv)) { return MS_FAILURE; } mapserv->map->query.type = MS_QUERY_BY_RECT; break; } } mapserv->map->query.mode = MS_QUERY_MULTIPLE; mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.buffer = mapserv->Buffer; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.slayer = mapserv->SelectLayerIndex; break; case ITEMQUERY: case ITEMNQUERY: if(mapserv->QueryLayerIndex < 0 || mapserv->QueryLayerIndex >= mapserv->map->numlayers) { msSetError(MS_WEBERR, "Query layer not set or references an invalid layer.", "mapserv()"); return MS_FAILURE; } /* validate the qstring parameter */ if(msValidateParameter(mapserv->QueryString, msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->validation), "qstring"), msLookupHashTable(&(mapserv->map->web.validation), "qstring"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_WEBERR, "Parameter 'qstring' value fails to validate.", "mapserv()"); return MS_FAILURE; } if(mapserv->QueryCoordSource != NONE && !mapserv->UseShapes) if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */ return MS_FAILURE; mapserv->map->query.type = MS_QUERY_BY_ATTRIBUTE; mapserv->map->query.layer = mapserv->QueryLayerIndex; if(mapserv->QueryItem) mapserv->map->query.item = msStrdup(mapserv->QueryItem); if(mapserv->QueryString) mapserv->map->query.str = msStrdup(mapserv->QueryString); mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.mode = MS_QUERY_MULTIPLE; if(mapserv->Mode == ITEMQUERY) mapserv->map->query.mode = MS_QUERY_SINGLE; break; case NQUERY: mapserv->map->query.mode = MS_QUERY_MULTIPLE; /* all of these cases return multiple results */ mapserv->map->query.layer = mapserv->QueryLayerIndex; switch(mapserv->QueryCoordSource) { case FROMIMGPNT: setCoordinate(mapserv); if(mapserv->SearchMap) { /* compute new extent, pan etc then search that extent */ if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */ return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; } else { mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.type = MS_QUERY_BY_POINT; } break; case FROMIMGBOX: if(mapserv->SearchMap) { /* compute new extent, pan etc then search that extent */ setExtent(mapserv); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; } else { double cellx, celly; mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); /* calculate the new search extent */ celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->RawExt.minx = MS_IMAGE2MAP_X(mapserv->ImgBox.minx, mapserv->ImgExt.minx, cellx); mapserv->RawExt.maxx = MS_IMAGE2MAP_X(mapserv->ImgBox.maxx, mapserv->ImgExt.minx, cellx); mapserv->RawExt.maxy = MS_IMAGE2MAP_Y(mapserv->ImgBox.miny, mapserv->ImgExt.maxy, celly); /* y's are flip flopped because img/map coordinate systems are */ mapserv->RawExt.miny = MS_IMAGE2MAP_Y(mapserv->ImgBox.maxy, mapserv->ImgExt.maxy, celly); mapserv->map->query.rect = mapserv->RawExt; mapserv->map->query.type = MS_QUERY_BY_RECT; } break; case FROMIMGSHAPE: mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; /* convert from image to map coordinates here (see setCoordinate) */ for(i=0; imap->query.shape->numlines; i++) { for(j=0; jmap->query.shape->line[i].numpoints; j++) { mapserv->map->query.shape->line[i].point[j].x = MS_IMAGE2MAP_X(mapserv->map->query.shape->line[i].point[j].x, mapserv->map->extent.minx, mapserv->map->cellsize); mapserv->map->query.shape->line[i].point[j].y = MS_IMAGE2MAP_Y(mapserv->map->query.shape->line[i].point[j].y, mapserv->map->extent.maxy, mapserv->map->cellsize); } } mapserv->map->query.type = MS_QUERY_BY_SHAPE; break; case FROMUSERPNT: if(mapserv->Buffer == 0) { /* do a *pure* point query */ mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.type = MS_QUERY_BY_POINT; setExtent(mapserv); } else { setExtent(mapserv); if(mapserv->SearchMap) { /* the extent should be tied to a map, so we need to "adjust" it */ if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); } mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; } break; case FROMUSERSHAPE: setExtent(mapserv); mapserv->map->query.type = MS_QUERY_BY_SHAPE; break; default: /* from an extent of some sort */ setExtent(mapserv); if(mapserv->SearchMap) { /* the extent should be tied to a map, so we need to "adjust" it */ if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); } mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; break; } break; case QUERY: switch(mapserv->QueryCoordSource) { case FROMIMGPNT: setCoordinate(mapserv); mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; break; case FROMUSERPNT: /* only a buffer makes sense, DOES IT? */ if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; break; default: msSetError(MS_WEBERR, "Query mode needs a point, imgxy and mapxy are not set.", "mapserv()"); return MS_FAILURE; break; } mapserv->map->query.type = MS_QUERY_BY_POINT; mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.buffer = mapserv->Buffer; break; case INDEXQUERY: mapserv->map->query.type = MS_QUERY_BY_INDEX; mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.shapeindex = mapserv->ShapeIndex; mapserv->map->query.tileindex = mapserv->TileIndex; break; } /* end mode switch */ /* finally execute the query */ if((status = msExecuteQuery(mapserv->map)) != MS_SUCCESS) return MS_FAILURE; } if(mapserv->map->querymap.width != -1) mapserv->map->width = mapserv->map->querymap.width; /* make sure we use the right size */ if(mapserv->map->querymap.height != -1) mapserv->map->height = mapserv->map->querymap.height; if(mapserv->UseShapes) if(MS_SUCCESS != setExtentFromShapes(mapserv)) return MS_FAILURE; if(msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, NULL) != MS_SUCCESS) return MS_FAILURE; if(mapserv->savequery) { snprintf(buffer, sizeof(buffer), "%s%s%s%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_QUERY_EXTENSION); if((status = msSaveQuery(mapserv->map, buffer, MS_FALSE)) != MS_SUCCESS) return status; } return MS_SUCCESS; } int msCGIDispatchImageRequest(mapservObj *mapserv) { int status; imageObj *img = NULL; switch(mapserv->Mode) { case MAP: if(mapserv->QueryFile) { status = msLoadQuery(mapserv->map, mapserv->QueryFile); if(status != MS_SUCCESS) return MS_FAILURE; img = msDrawMap(mapserv->map, MS_TRUE); } else img = msDrawMap(mapserv->map, MS_FALSE); break; case REFERENCE: mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); img = msDrawReferenceMap(mapserv->map); break; case SCALEBAR: img = msDrawScalebar(mapserv->map); break; case TILE: msTileSetExtent(mapserv); img = msTileDraw(mapserv); break; case LEGEND: case MAPLEGEND: img = msDrawLegend(mapserv->map, MS_FALSE, mapserv->hittest); break; default: msSetError(MS_CGIERR,"Invalid CGI mode", "msCGIDispatchImageRequest()"); break; } if(!img) return MS_FAILURE; /* ** Set the Cache control headers if the option is set. */ if( mapserv->sendheaders && msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age") ) { msIO_setHeader("Cache-Control","max-age=%s", msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age")); } if(mapserv->sendheaders) { const char *attachment = msGetOutputFormatOption(mapserv->map->outputformat, "ATTACHMENT", NULL ); if(attachment) msIO_setHeader("Content-disposition","attachment; filename=%s", attachment); msIO_setHeader("Content-Type","%s", MS_IMAGE_MIME_TYPE(mapserv->map->outputformat)); msIO_sendHeaders(); } if( mapserv->Mode == MAP || mapserv->Mode == TILE ) status = msSaveImage(mapserv->map, img, NULL); else status = msSaveImage(NULL,img, NULL); if(status != MS_SUCCESS) return MS_FAILURE; msFreeImage(img); return MS_SUCCESS; } int msCGIDispatchLegendRequest(mapservObj *mapserv) { int status; if(mapserv->Mode == MAPLEGEND) { if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; if(checkWebScale(mapserv) != MS_SUCCESS) return MS_FAILURE; mapserv->hittest = msSmallMalloc(sizeof(map_hittest)); initMapHitTests(mapserv->map,mapserv->hittest); status = msHitTestMap(mapserv->map,mapserv->hittest); if(status != MS_SUCCESS) return MS_FAILURE; } if(mapserv->map->legend.template) { char *legendTemplate; legendTemplate = generateLegendTemplate(mapserv); if(legendTemplate) { if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s",mapserv->map->web.legendformat); msIO_sendHeaders(); } msIO_fwrite(legendTemplate, strlen(legendTemplate), 1, stdout); free(legendTemplate); return MS_SUCCESS; } else {/* error already generated by (generateLegendTemplate()) */ return MS_FAILURE; } } else { return msCGIDispatchImageRequest(mapserv); } } int msCGIDispatchLegendIconRequest(mapservObj *mapserv) { char **tokens; int numtokens=0; int layerindex=-1, classindex=0, status; outputFormatObj *format = NULL; imageObj *img; /* TODO: do we want to set scale here? */ /* do we have enough information */ if(!mapserv->icon) { msSetError(MS_WEBERR, "Mode=LEGENDICON requires an icon parameter.", "mapserv()"); return MS_FAILURE; } /* process the icon definition */ tokens = msStringSplit(mapserv->icon, ',', &numtokens); if(numtokens != 1 && numtokens != 2) { msSetError(MS_WEBERR, "%d Malformed icon parameter, should be 'layer,class' or just 'layer' if the layer has only 1 class defined.", "mapserv()", numtokens); return MS_FAILURE; } if((layerindex = msGetLayerIndex(mapserv->map, tokens[0])) == -1) { msSetError(MS_WEBERR, "Icon layer=%s not found in mapfile.", "mapserv()", tokens[0]); return MS_FAILURE; } if(numtokens == 2) { /* check the class index */ classindex = atoi(tokens[1]); if(classindex >= GET_LAYER(mapserv->map, layerindex)->numclasses) { msSetError(MS_WEBERR, "Icon class=%d not found in layer=%s.", "mapserv()", classindex, GET_LAYER(mapserv->map, layerindex)->name); return MS_FAILURE; } } if(mapserv->Mode == MAPLEGENDICON) { if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; if(checkWebScale(mapserv) != MS_SUCCESS) return MS_FAILURE; mapserv->hittest = msSmallMalloc(sizeof(map_hittest)); initMapHitTests(mapserv->map,mapserv->hittest); status = msHitTestLayer(mapserv->map, GET_LAYER(mapserv->map,layerindex),&mapserv->hittest->layerhits[layerindex]); if(status != MS_SUCCESS) return MS_FAILURE; } /* ensure we have an image format representing the options for the legend. */ msApplyOutputFormat(&format, mapserv->map->outputformat, mapserv->map->legend.transparent, mapserv->map->legend.interlace, MS_NOOVERRIDE); /* initialize the legend image */ if( ! MS_RENDERER_PLUGIN(format) ) { msSetError(MS_RENDERERERR, "unsupported renderer for legend icon", "mapserv main()"); return MS_FAILURE; } img = msImageCreate(mapserv->map->legend.keysizex, mapserv->map->legend.keysizey, format, mapserv->map->web.imagepath, mapserv->map->web.imageurl, mapserv->map->resolution, mapserv->map->defresolution, &(mapserv->map->legend.imagecolor)); /* drop this reference to output format */ msApplyOutputFormat(&format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); if(msDrawLegendIcon(mapserv->map, GET_LAYER(mapserv->map, layerindex), GET_LAYER(mapserv->map, layerindex)->class[classindex], mapserv->map->legend.keysizex, mapserv->map->legend.keysizey, img, 0, 0, MS_TRUE, ((mapserv->hittest)?(&mapserv->hittest->layerhits[layerindex].classhits[classindex]):(NULL))) != MS_SUCCESS) return MS_FAILURE; if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s",MS_IMAGE_MIME_TYPE(mapserv->map->outputformat)); msIO_sendHeaders(); } /* ** Set the Cache control headers if the option is set. */ if( mapserv->sendheaders && msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age") ) { msIO_printf("Cache-Control: max-age=%s%c", msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age"), 10); } if( msSaveImage(NULL, img, NULL) != MS_SUCCESS) return MS_FAILURE; msFreeCharArray(tokens, numtokens); msFreeImage(img); return MS_SUCCESS; } int msCGIDispatchRequest(mapservObj *mapserv) { int i; int status; /* ** Determine 'mode': Check for MS_MODE env. var. and mode=... CGI param */ mapserv->Mode = -1; /* Not set */ if( msCGISetMode(mapserv) != MS_SUCCESS) { return MS_FAILURE; } /* ** Start by calling the WMS/WFS/WCS Dispatchers. If they fail then we'll ** process this as a regular MapServer request. */ if((mapserv->Mode == -1 || mapserv->Mode == OWS || mapserv->Mode == WFS) && (status = msOWSDispatch(mapserv->map, mapserv->request, mapserv->Mode)) != MS_DONE ) { /* ** OWSDispatch returned either MS_SUCCESS or MS_FAILURE */ if( status == MS_FAILURE ) { return MS_FAILURE; } if (status == MS_SUCCESS && strcasecmp(mapserv->map->imagetype, "application/openlayers")==0) { char *service = NULL; for( i=0; irequest->NumParams; i++) { if(strcasecmp(mapserv->request->ParamNames[i], "SERVICE") == 0) { service = mapserv->request->ParamValues[i]; break; } } if (service && strcasecmp(service,"WMS")==0) { if(mapserv->sendheaders) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); } if (msReturnOpenLayersPage(mapserv) != MS_SUCCESS) return MS_FAILURE; } } return MS_SUCCESS; } /* done OGC/OWS case */ /* ** Do "traditional" mode processing. */ if (mapserv->Mode == -1) mapserv->Mode = BROWSE; if(MS_SUCCESS != msCGILoadForm(mapserv)) { return MS_FAILURE; } /* Insecure as implemented, need to save someplace non accessible by everyone in the universe if(mapserv->savemap) { snprintf(buffer, sizeof(buffer), "%s%s%s.map", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id); if(msSaveMap(mapserv->map, buffer) == -1) return MS_FAILURE; } */ if((mapserv->CoordSource == FROMIMGPNT) || (mapserv->CoordSource == FROMIMGBOX)) /* make sure extent of existing image matches shape of image */ mapserv->map->cellsize = msAdjustExtent(&mapserv->ImgExt, mapserv->ImgCols, mapserv->ImgRows); /* ** For each layer let's set layer status */ for(i=0; imap->numlayers; i++) { if((GET_LAYER(mapserv->map, i)->status != MS_DEFAULT)) { if(isOn(mapserv, GET_LAYER(mapserv->map, i)->name, GET_LAYER(mapserv->map, i)->group) == MS_TRUE) /* Set layer status */ GET_LAYER(mapserv->map, i)->status = MS_ON; else GET_LAYER(mapserv->map, i)->status = MS_OFF; } } if(mapserv->CoordSource == FROMREFPNT) /* force browse mode if the reference coords are set */ mapserv->Mode = BROWSE; if(mapserv->Mode == TILE) { /* ** Tile mode: ** Set the projection up and test the parameters for legality. */ if( msTileSetup(mapserv) != MS_SUCCESS ) { return MS_FAILURE; } } if(mapserv->Mode == BROWSE) { return msCGIDispatchBrowseRequest(mapserv); } else if(mapserv->Mode == MAP || mapserv->Mode == SCALEBAR || mapserv->Mode == REFERENCE || mapserv->Mode == TILE) { /* "image" only modes */ /* tile, map, scalebar and reference all need the extent to be set up correctly */ if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; if(checkWebScale(mapserv) != MS_SUCCESS) return MS_FAILURE; return msCGIDispatchImageRequest(mapserv); } else if(mapserv->Mode == LEGEND || mapserv->Mode == MAPLEGEND) { return msCGIDispatchLegendRequest(mapserv); } else if(mapserv->Mode == LEGENDICON || mapserv->Mode == MAPLEGENDICON) { return msCGIDispatchLegendIconRequest(mapserv); } else if(mapserv->Mode >= QUERY) { return msCGIDispatchQueryRequest(mapserv); } else if(mapserv->Mode == COORDINATE) { return msCGIDispatchCoordinateRequest(mapserv); } else { msSetError(MS_WEBERR, "Bug: unsupported mode", "msDispatchRequest"); return MS_FAILURE; } } int msCGIHandler(const char *query_string, void **out_buffer, size_t *buffer_length) { int x,m=0; struct mstimeval execstarttime, execendtime; struct mstimeval requeststarttime, requestendtime; mapservObj* mapserv = NULL; char *queryString = NULL; int maxParams = MS_DEFAULT_CGI_PARAMS; msIOContext *ctx; msIOBuffer *buf; msIO_installStdoutToBuffer(); /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if( msDebugInitFromEnv() != MS_SUCCESS ) { msCGIWriteError(mapserv); goto end_request; } if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); mapserv = msAllocMapServObj(); mapserv->request->type = MS_GET_REQUEST; if(!query_string || !*query_string) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("No query information to decode. QUERY_STRING not set.\n"); goto end_request; } /* don't modify the string */ queryString = msStrdup(query_string); for(x=0; queryString[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; mapserv->request->ParamNames = (char **) realloc(mapserv->request->ParamNames,sizeof(char *) * maxParams); if (mapserv->request->ParamNames == NULL) { msIO_printf("Out of memory trying to allocate name/value pairs.\n"); goto end_request; } mapserv->request->ParamValues = (char **) realloc(mapserv->request->ParamValues,sizeof(char *) * maxParams); if (mapserv->request->ParamValues == NULL) { msIO_printf("Out of memory trying to allocate name/value pairs.\n"); goto end_request; } } mapserv->request->ParamValues[m] = makeword(queryString,'&'); plustospace(mapserv->request->ParamValues[m]); unescape_url(mapserv->request->ParamValues[m]); mapserv->request->ParamNames[m] = makeword(mapserv->request->ParamValues[m],'='); m++; } mapserv->request->NumParams = m; if( mapserv->request->NumParams == 0 ) { msCGIWriteError(mapserv); goto end_request; } mapserv->map = msCGILoadMap(mapserv); if(!mapserv->map) { msCGIWriteError(mapserv); goto end_request; } if( mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&requeststarttime, NULL); if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { msCGIWriteError(mapserv); goto end_request; } end_request: if(mapserv) { if(mapserv->map && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCGIWriteLog(mapserv,MS_FALSE); msFreeMapServObj(mapserv); } /* normal case, processing is complete */ if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&execendtime, NULL); msDebug("mapserv total execution time: %.3fs\n", (execendtime.tv_sec+execendtime.tv_usec/1.0e6)- (execstarttime.tv_sec+execstarttime.tv_usec/1.0e6) ); } ctx = msIO_getHandler( (FILE *) "stdout" ); buf = (msIOBuffer *) ctx->cbData; *out_buffer = buf->data; *buffer_length = buf->data_offset; free(queryString); return 0; } mapserver-6.4.1/mapwfslayer.c0000644002461700001440000013454712261257215016030 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of WFS CONNECTIONTYPE - client to WFS servers * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2002, Daniel Morissette, DM Solutions Group Inc * * 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 ****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapows.h" #include "mapproject.h" #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #endif #define WFS_V_0_0_14 14 #define WFS_V_1_0_0 100 /*==================================================================== * Private (static) functions *====================================================================*/ #ifdef USE_WFS_LYR /************************************************************************/ /* msBuildRequestParms */ /* */ /* Build the params object based on the metadata */ /* information. This object will be used when building the Get */ /* and Post requsests. */ /* Note : Verify the connection string to extract some values */ /* for backward compatiblity. (It is though depricated). */ /* This will also set layer projection and compute BBOX in that */ /* projection. */ /* */ /************************************************************************/ static wfsParamsObj *msBuildRequestParams(mapObj *map, layerObj *lp, rectObj *bbox_ret) { wfsParamsObj *psParams = NULL; rectObj bbox; const char *pszTmp; int nLength, i = 0; char *pszVersion, *pszTypeName; if (!map || !lp || !bbox_ret) return NULL; if (lp->connection == NULL) return NULL; psParams = msWFSCreateParamsObj(); pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "version"); if (pszTmp) psParams->pszVersion = msStrdup(pszTmp); else { pszTmp = strstr(lp->connection, "VERSION="); if (!pszTmp) pszTmp = strstr(lp->connection, "version="); if (pszTmp) { pszVersion = strchr(pszTmp, '=')+1; if (strncmp(pszVersion, "0.0.14", 6) == 0) psParams->pszVersion = msStrdup("0.0.14"); else if (strncmp(pszVersion, "1.0.0", 5) == 0) psParams->pszVersion = msStrdup("1.0.0"); } } /*the service is always set to WFS : see bug 1302 */ psParams->pszService = msStrdup("WFS"); /* pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "service"); if (pszTmp) psParams->pszService = msStrdup(pszTmp); else { pszTmp = strstr(lp->connection, "SERVICE="); if (!pszTmp) pszTmp = strstr(lp->connection, "service="); if (pszTmp) { pszService = strchr(pszTmp, '=')+1; if (strncmp(pszService, "WFS", 3) == 0) psParams->pszService = msStrdup("WFS"); } } */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "geometryname"); if (pszTmp) psParams->pszGeometryName = msStrdup(pszTmp); pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "typename"); if (pszTmp) psParams->pszTypeName = msStrdup(pszTmp); else { pszTmp = strstr(lp->connection, "TYPENAME="); if (!pszTmp) pszTmp = strstr(lp->connection, "typename="); if (pszTmp) { pszTypeName = strchr(pszTmp, '=')+1; if (pszTypeName) { nLength = strlen(pszTypeName); if (nLength > 0) { for (i=0; ipszTypeName = msStrdup(pszTypeNameTmp); free(pszTypeNameTmp); } else psParams->pszTypeName = msStrdup(pszTypeName); } } } } pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "filter"); if (pszTmp && strlen(pszTmp) > 0) { if (strstr(pszTmp, "") !=NULL || strstr(pszTmp, "pszFilter = msStrdup(pszTmp); else { psParams->pszFilter = msStringConcatenate(psParams->pszFilter, ""); psParams->pszFilter = msStringConcatenate(psParams->pszFilter, (char*)pszTmp); psParams->pszFilter = msStringConcatenate(psParams->pszFilter, ""); } } pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "maxfeatures"); if (pszTmp) psParams->nMaxFeatures = atoi(pszTmp); /* Request is always GetFeature; */ psParams->pszRequest = msStrdup("GetFeature"); /* ------------------------------------------------------------------ * Figure the SRS we'll use for the request. * - Fetch the map SRS (if it's EPSG) * - Check if map SRS is listed in layer wfs_srs metadata * - If map SRS is valid for this layer then use it * - Otherwise request layer in its default SRS and we'll reproject later * ------------------------------------------------------------------ */ /* __TODO__ WFS servers support only one SRS... need to decide how we'll */ /* handle this and document it well. */ /* It's likely that we'll simply reproject the BBOX to teh layer's projection. */ /* ------------------------------------------------------------------ * Set layer SRS and reproject map extents to the layer's SRS * ------------------------------------------------------------------ */ #ifdef __TODO__ /* No need to set lp->proj if it's already set to the right EPSG code */ if ((pszTmp = msGetEPSGProj(&(lp->projection), NULL, MS_TRUE)) == NULL || strcasecmp(pszEPSG, pszTmp) != 0) { char szProj[20]; snprintf(szProj, sizeof(szProj), "init=epsg:%s", pszEPSG+5); if (msLoadProjectionString(&(lp->projection), szProj) != 0) return NULL; } #endif bbox = map->extent; if (msProjectionsDiffer(&(map->projection), &(lp->projection))) { msProjectRect(&(map->projection), &(lp->projection), &bbox); } if (bbox_ret != NULL) *bbox_ret = bbox; return psParams; } /********************************************************************** * msBuildWFSLayerPostRequest() * * Build a WFS GetFeature xml document for a Post Request. * * Returns a reference to a newly allocated string that should be freed * by the caller. **********************************************************************/ static char *msBuildWFSLayerPostRequest(mapObj *map, layerObj *lp, rectObj *bbox, wfsParamsObj *psParams) { char *pszPostReq = NULL; char *pszFilter = NULL; char *pszGeometryName = "Geometry"; size_t bufferSize = 0; if (psParams->pszVersion == NULL || (strncmp(psParams->pszVersion, "0.0.14", 6) != 0 && strncmp(psParams->pszVersion, "1.0.0", 5)) != 0) { msSetError(MS_WFSCONNERR, "MapServer supports only WFS 1.0.0 or 0.0.14 (please verify the version metadata wfs_version).", "msBuildWFSLayerPostRequest()"); return NULL; } if (psParams->pszTypeName == NULL) { msSetError(MS_WFSCONNERR, "Metadata wfs_typename must be set in the layer", "msBuildWFSLayerPostRequest()"); return NULL; } if (psParams->pszGeometryName) { pszGeometryName = psParams->pszGeometryName; } if (psParams->pszFilter) pszFilter = psParams->pszFilter; else { bufferSize = 500; pszFilter = (char *)msSmallMalloc(bufferSize); snprintf(pszFilter, bufferSize, "\n" "\n" "%s\n" "\n" "%f,%f %f,%f\n" "\n" "\n" "", pszGeometryName, bbox->minx, bbox->miny, bbox->maxx, bbox->maxy); } bufferSize = strlen(pszFilter)+500; pszPostReq = (char *)msSmallMalloc(bufferSize); if (psParams->nMaxFeatures > 0) snprintf(pszPostReq, bufferSize, "\n" "\n" "\n" "%s" "\n" "\n", psParams->nMaxFeatures, psParams->pszTypeName, pszFilter); else snprintf(pszPostReq, bufferSize, "\n" "\n" "\n" "%s" "\n" "\n", psParams->pszTypeName, pszFilter); if (psParams->pszFilter == NULL) free(pszFilter); return pszPostReq; } /********************************************************************** * msBuildWFSLayerGetURL() * * Build a WFS GetFeature URL for a Get Request. * * Returns a reference to a newly allocated string that should be freed * by the caller. **********************************************************************/ static char *msBuildWFSLayerGetURL(mapObj *map, layerObj *lp, rectObj *bbox, wfsParamsObj *psParams) { char *pszURL = NULL, *pszOnlineResource=NULL; const char *pszTmp; char *pszVersion, *pszService, *pszTypename = NULL; int bVersionInConnection = 0, bServiceInConnection = 0; int bTypenameInConnection = 0; size_t bufferSize = 0; if (lp->connectiontype != MS_WFS || lp->connection == NULL) { msSetError(MS_WFSCONNERR, "Call supported only for CONNECTIONTYPE WFS", "msBuildWFSLayerGetURL()"); return NULL; } /* -------------------------------------------------------------------- */ /* Find out request version. Look first for the wfs_version */ /* metedata. If not available try to find out if the CONNECTION */ /* string contains the version. This last test is done for */ /* backward compatiblity but is depericated. */ /* -------------------------------------------------------------------- */ pszVersion = psParams->pszVersion; if (!pszVersion) { if ((pszTmp = strstr(lp->connection, "VERSION=")) == NULL && (pszTmp = strstr(lp->connection, "version=")) == NULL ) { msSetError(MS_WFSCONNERR, "Metadata wfs_version must be set in the layer", "msBuildWFSLayerGetURL()"); return NULL; } pszVersion = strchr(pszTmp, '=')+1; bVersionInConnection = 1; } if (strncmp(pszVersion, "0.0.14", 6) != 0 && strncmp(pszVersion, "1.0.0", 5) != 0 && strncmp(pszVersion, "1.1", 3) != 0) { msSetError(MS_WFSCONNERR, "MapServer supports only WFS 1.0.0 or 0.0.14 (please verify the version metadata wfs_version).", "msBuildWFSLayerGetURL()"); return NULL; } /* -------------------------------------------------------------------- */ /* Find out the service. It is always set to WFS in function */ /* msBuildRequestParms (check Bug 1302 for details). */ /* -------------------------------------------------------------------- */ pszService = psParams->pszService; /* -------------------------------------------------------------------- */ /* Find out the typename. Look first for the wfs_tyename */ /* metadata. If not available try to find out if the CONNECTION */ /* string contains it. This last test is done for */ /* backward compatiblity but is depericated. */ /* -------------------------------------------------------------------- */ pszTypename = psParams->pszTypeName; if (!pszTypename) { if ((pszTmp = strstr(lp->connection, "TYPENAME=")) == NULL && (pszTmp = strstr(lp->connection, "typename=")) == NULL ) { msSetError(MS_WFSCONNERR, "Metadata wfs_typename must be set in the layer", "msBuildWFSLayerGetURL()"); return NULL; } bTypenameInConnection = 1; } /* -------------------------------------------------------------------- * Build the request URL. * At this point we set only the following parameters for GetFeature: * REQUEST * BBOX * VERSION * SERVICE * TYPENAME * FILTER * MAXFEATURES * * For backward compatiblity the user could also have in the connection * string the following parameters (but it is depricated): * VERSION * SERVICE * TYPENAME * -------------------------------------------------------------------- */ /* Make sure we have a big enough buffer for the URL */ bufferSize = strlen(lp->connection)+1024; pszURL = (char *)malloc(bufferSize); MS_CHECK_ALLOC(pszURL, bufferSize, NULL); /* __TODO__ We have to urlencode each value... especially the BBOX values */ /* because if they end up in exponent format (123e+06) the + will be seen */ /* as a space by the remote server. */ /* -------------------------------------------------------------------- */ /* build the URL, */ /* -------------------------------------------------------------------- */ /* make sure connection ends with "&" or "?" */ pszOnlineResource = msOWSTerminateOnlineResource(lp->connection); snprintf(pszURL, bufferSize, "%s", pszOnlineResource); msFree(pszOnlineResource); /* REQUEST */ snprintf(pszURL + strlen(pszURL), bufferSize-strlen(pszURL), "&REQUEST=GetFeature"); /* VERSION */ if (!bVersionInConnection) snprintf(pszURL + strlen(pszURL), bufferSize-strlen(pszURL), "&VERSION=%s", pszVersion); /* SERVICE */ if (!bServiceInConnection) snprintf(pszURL + strlen(pszURL), bufferSize-strlen(pszURL), "&SERVICE=%s", pszService); /* TYPENAME */ if (!bTypenameInConnection) snprintf(pszURL + strlen(pszURL), bufferSize-strlen(pszURL), "&TYPENAME=%s", pszTypename); /* -------------------------------------------------------------------- */ /* If the filter parameter is given in the wfs_filter metadata, */ /* we use it and do not send the BBOX paramter as they are */ /* mutually exclusive. */ /* -------------------------------------------------------------------- */ if (psParams->pszFilter) { snprintf(pszURL + strlen(pszURL), bufferSize-strlen(pszURL), "&FILTER=%s", msEncodeUrl(psParams->pszFilter)); } else { /* * take care about the axis order for WFS 1.1 */ char *projUrn; const char *projEpsg; projUrn = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", 1); projEpsg = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", 1); /* * WFS 1.1 supports including the SRS in the BBOX parameter, should * respect axis order in the BBOX and has a separate SRSNAME parameter for * the desired result SRS. * WFS 1.0 is always easting, northing, doesn't include the SRS as part of * the BBOX parameter and has no SRSNAME parameter: if we don't have a * URN then fallback to WFS 1.0 style */ if ((strncmp(pszVersion, "1.1", 3) == 0) && projUrn) { if (projEpsg && (strncmp(projEpsg, "EPSG:", 5) == 0) && msIsAxisInverted(atoi(projEpsg + 5))) { snprintf(pszURL + strlen(pszURL), bufferSize - strlen(pszURL), "&BBOX=%.15g,%.15g,%.15g,%.15g,%s&SRSNAME=%s", bbox->miny, bbox->minx, bbox->maxy, bbox->maxx, projUrn, projUrn); } else { snprintf(pszURL + strlen(pszURL), bufferSize - strlen(pszURL), "&BBOX=%.15g,%.15g,%.15g,%.15g,%s&SRSNAME=%s", bbox->minx, bbox->miny, bbox->maxy, bbox->maxy, projUrn, projUrn); } } else { snprintf(pszURL + strlen(pszURL), bufferSize - strlen(pszURL), "&BBOX=%.15g,%.15g,%.15g,%.15g", bbox->minx, bbox->miny, bbox->maxx, bbox->maxy); } msFree(projUrn); } if (psParams->nMaxFeatures > 0) snprintf(pszURL + strlen(pszURL), bufferSize-strlen(pszURL), "&MAXFEATURES=%d", psParams->nMaxFeatures); return pszURL; } /********************************************************************** * msWFSLayerInfo * **********************************************************************/ typedef struct ms_wfs_layer_info_t { char *pszGMLFilename; rectObj rect; /* set by WhichShapes */ char *pszGetUrl; int nStatus; /* HTTP status */ int bLayerHasValidGML; /* False until msWFSLayerWhichShapes() is called and determines the result GML is valid with features*/ } msWFSLayerInfo; /********************************************************************** * msAllocWFSLayerInfo() * **********************************************************************/ static msWFSLayerInfo *msAllocWFSLayerInfo(void) { msWFSLayerInfo *psInfo; psInfo = (msWFSLayerInfo*)calloc(1,sizeof(msWFSLayerInfo)); MS_CHECK_ALLOC(psInfo, sizeof(msWFSLayerInfo), NULL); psInfo->pszGMLFilename = NULL; psInfo->rect.minx = psInfo->rect.maxx = 0; psInfo->rect.miny = psInfo->rect.maxy = 0; psInfo->pszGetUrl = NULL; psInfo->nStatus = 0; return psInfo; } /********************************************************************** * msFreeWFSLayerInfo() * **********************************************************************/ static void msFreeWFSLayerInfo(msWFSLayerInfo *psInfo) { if (psInfo) { if (psInfo->pszGMLFilename) free(psInfo->pszGMLFilename); if (psInfo->pszGetUrl) free(psInfo->pszGetUrl); free(psInfo); } } #endif /* USE_WFS_LYR */ /*==================================================================== * Public functions *====================================================================*/ /********************************************************************** * msPrepareWFSLayerRequest() * **********************************************************************/ int msPrepareWFSLayerRequest(int nLayerId, mapObj *map, layerObj *lp, httpRequestObj *pasReqInfo, int *numRequests) { #ifdef USE_WFS_LYR char *pszURL = NULL; const char *pszTmp; rectObj bbox; int nTimeout; int nStatus = MS_SUCCESS; msWFSLayerInfo *psInfo = NULL; int bPostRequest = 0; wfsParamsObj *psParams = NULL; char *pszHTTPCookieData = NULL; if (lp->connectiontype != MS_WFS || lp->connection == NULL) return MS_FAILURE; /* ------------------------------------------------------------------ * Build a params object that will be used by to build the request, this will also set layer projection and compute BBOX in that projection. * ------------------------------------------------------------------ */ psParams = msBuildRequestParams(map, lp, &bbox); if (!psParams) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* Depending on the metadata wfs_request_method, build a Get or */ /* a Post URL. */ /* If it is a Get request the URL would contain all the parameters in*/ /* the string; */ /* If it is a Post request, the URL will only contain the */ /* connection string comming from the layer. */ /* -------------------------------------------------------------------- */ if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "request_method")) != NULL) { if (strncmp(pszTmp, "GET", 3) ==0) { pszURL = msBuildWFSLayerGetURL(map, lp, &bbox, psParams); if (!pszURL) { /* an error was already reported. */ return MS_FAILURE; } } } /* else it is a post request and just get the connection string */ if (!pszURL) { bPostRequest = 1; pszURL = msStrdup(lp->connection); } /* ------------------------------------------------------------------ * check to see if a the metadata wfs_connectiontimeout is set. If it is * the case we will use it, else we use the default which is 30 seconds. * First check the metadata in the layer object and then in the map object. * ------------------------------------------------------------------ */ nTimeout = 30; /* Default is 30 seconds */ if ((pszTmp = msOWSLookupMetadata2(&(lp->metadata), &(map->web.metadata), "FO", "connectiontimeout")) != NULL) { nTimeout = atoi(pszTmp); } /*------------------------------------------------------------------ * Check to see if there's a HTTP Cookie to forward * If Cookie differ between the two connection, it's NOT OK to merge * the connection * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "http_cookie")) != NULL) { if(strcasecmp(pszTmp, "forward") == 0) { pszTmp= msLookupHashTable(&(map->web.metadata),"http_cookie_data"); if(pszTmp != NULL) { pszHTTPCookieData = msStrdup(pszTmp); } } else { pszHTTPCookieData = msStrdup(pszTmp); } } else if ((pszTmp = msOWSLookupMetadata(&(map->web.metadata), "FO", "http_cookie")) != NULL) { if(strcasecmp(pszTmp, "forward") == 0) { pszTmp= msLookupHashTable(&(map->web.metadata),"http_cookie_data"); if(pszTmp != NULL) { pszHTTPCookieData = msStrdup(pszTmp); } } else { pszHTTPCookieData = msStrdup(pszTmp); } } /* ------------------------------------------------------------------ * If nLayerId == -1 then we need to figure it * ------------------------------------------------------------------ */ if (nLayerId == -1) { int iLayer; for(iLayer=0; iLayer < map->numlayers; iLayer++) { if (GET_LAYER(map, iLayer) == lp) { nLayerId = iLayer; break; } } } /* ------------------------------------------------------------------ * Add a request to the array (already preallocated) * ------------------------------------------------------------------ */ pasReqInfo[(*numRequests)].nLayerId = nLayerId; pasReqInfo[(*numRequests)].pszGetUrl = pszURL; if (bPostRequest) { pasReqInfo[(*numRequests)].pszPostRequest = msBuildWFSLayerPostRequest(map, lp, &bbox, psParams); pasReqInfo[(*numRequests)].pszPostContentType = msStrdup("text/xml"); } /* We'll store the remote server's response to a tmp file. */ pasReqInfo[(*numRequests)].pszOutputFile = msTmpFile(map, map->mappath, NULL, "tmp.gml"); /* TODO: Implement Caching of GML responses. There was an older caching * method, but it suffered from a race condition. See #3137. */ pasReqInfo[(*numRequests)].pszHTTPCookieData = pszHTTPCookieData; pszHTTPCookieData = NULL; pasReqInfo[(*numRequests)].nStatus = 0; pasReqInfo[(*numRequests)].nTimeout = nTimeout; pasReqInfo[(*numRequests)].bbox = bbox; pasReqInfo[(*numRequests)].debug = lp->debug; if (msHTTPAuthProxySetup(&(map->web.metadata), &(lp->metadata), pasReqInfo, *numRequests, map, "FO") != MS_SUCCESS) return MS_FAILURE; /* ------------------------------------------------------------------ * Pre-Open the layer now, (i.e. alloc and fill msWFSLayerInfo inside * layer obj). Layer will be ready for use when the main mapserver * code calls msLayerOpen(). * ------------------------------------------------------------------ */ if (lp->wfslayerinfo != NULL) { psInfo =(msWFSLayerInfo*)(lp->wfslayerinfo); } else { lp->wfslayerinfo = psInfo = msAllocWFSLayerInfo(); } if (psInfo->pszGMLFilename) free(psInfo->pszGMLFilename); psInfo->pszGMLFilename=msStrdup(pasReqInfo[(*numRequests)].pszOutputFile); psInfo->rect = pasReqInfo[(*numRequests)].bbox; if (psInfo->pszGetUrl) free(psInfo->pszGetUrl); psInfo->pszGetUrl = msStrdup(pasReqInfo[(*numRequests)].pszGetUrl); psInfo->nStatus = 0; (*numRequests)++; if (psParams) { msWFSFreeParamsObj(psParams); psParams = NULL; } return nStatus; #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msPrepareWFSLayerRequest"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSUpdateRequestInfo() * * This function is called after a WFS request has been completed so that * we can copy request result information from the httpRequestObj to the * msWFSLayerInfo struct. Things to copy here are the HTTP status, exceptions * information, mime type, etc. **********************************************************************/ void msWFSUpdateRequestInfo(layerObj *lp, httpRequestObj *pasReqInfo) { #ifdef USE_WFS_LYR if (lp->wfslayerinfo) { msWFSLayerInfo *psInfo = NULL; psInfo =(msWFSLayerInfo*)(lp->wfslayerinfo); /* Copy request results infos to msWFSLayerInfo struct */ /* For now there is only nStatus, but we should eventually add */ /* mime type and WFS exceptions information. */ psInfo->nStatus = pasReqInfo->nStatus; } #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSUpdateRequestInfo()"); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerOpen() * * WFS layers are just a special case of OGR connection. Only the open/close * methods differ since they have to download and maintain GML files in cache * but the rest is mapped directly to OGR function calls in maplayer.c * **********************************************************************/ int msWFSLayerOpen(layerObj *lp, const char *pszGMLFilename, rectObj *defaultBBOX) { #ifdef USE_WFS_LYR int status = MS_SUCCESS; msWFSLayerInfo *psInfo = NULL; if ( msCheckParentPointer(lp->map,"map")==MS_FAILURE ) return MS_FAILURE; if (lp->wfslayerinfo != NULL) { psInfo =(msWFSLayerInfo*)lp->wfslayerinfo; /* Layer already opened. If explicit filename requested then check */ /* that file was already opened with the same filename. */ /* If no explicit filename requested then we'll try to reuse the */ /* previously opened layer... this will happen in a msDrawMap() call. */ if (pszGMLFilename == NULL || (psInfo->pszGMLFilename && pszGMLFilename && strcmp(psInfo->pszGMLFilename, pszGMLFilename) == 0) ) { if (lp->layerinfo == NULL) { if (msWFSLayerWhichShapes(lp, psInfo->rect, MS_FALSE) == MS_FAILURE) /* no access to context (draw vs. query) here, although I doubt it matters... */ return MS_FAILURE; } return MS_SUCCESS; /* Nothing to do... layer is already opened */ } else { /* Hmmm... should we produce a fatal error? */ /* For now we'll just close the layer and reopen it. */ if (lp->debug) msDebug("msWFSLayerOpen(): Layer already opened (%s)\n", lp->name?lp->name:"(null)" ); msWFSLayerClose(lp); } } /* ------------------------------------------------------------------ * Alloc and fill msWFSLayerInfo inside layer obj * ------------------------------------------------------------------ */ lp->wfslayerinfo = psInfo = msAllocWFSLayerInfo(); if (pszGMLFilename) psInfo->pszGMLFilename = msStrdup(pszGMLFilename); else { psInfo->pszGMLFilename = msTmpFile(lp->map, lp->map->mappath, NULL, "tmp.gml"); } if (defaultBBOX) { /* __TODO__ If new bbox differs from current one then we should */ /* invalidate current GML file in cache */ psInfo->rect = *defaultBBOX; } else { /* Use map bbox by default */ psInfo->rect = lp->map->extent; } /* We will call whichshapes() now and force downloading layer right */ /* away. This saves from having to call DescribeFeatureType and */ /* parsing the response (being lazy I guess) and anyway given the */ /* way we work with layers right now the bbox is unlikely to change */ /* between now and the time whichshapes() would have been called by */ /* the MapServer core. */ #ifdef USE_PROJ if((lp->map->projection.numargs > 0) && (lp->projection.numargs > 0)) msProjectRect(&lp->map->projection, &lp->projection, &psInfo->rect); /* project the searchrect to source coords */ #endif if (msWFSLayerWhichShapes(lp, psInfo->rect, MS_FALSE) == MS_FAILURE) /* no access to context (draw vs. query) here, although I doubt it matters... */ status = MS_FAILURE; return status; #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerOpen()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerOpenVT() * * Overloaded version of msWFSLayerOpen for virtual table architecture **********************************************************************/ int msWFSLayerOpenVT(layerObj *lp) { return msWFSLayerOpen(lp, NULL, NULL); } /********************************************************************** * msWFSLayerIsOpen() * * Returns MS_TRUE if layer is already open, MS_FALSE otherwise. * **********************************************************************/ int msWFSLayerIsOpen(layerObj *lp) { #ifdef USE_WFS_LYR if (lp->wfslayerinfo != NULL) return MS_TRUE; return MS_FALSE; #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerIsOpen()"); return(MS_FALSE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerInitItemInfo() * **********************************************************************/ int msWFSLayerInitItemInfo(layerObj *layer) { /* Nothing to do here. OGR will do its own initialization when it */ /* opens the actual file. */ /* Note that we didn't implement our own msWFSLayerFreeItemInfo() */ /* so that the OGR one gets called. */ return MS_SUCCESS; } /********************************************************************** * msWFSLayerGetShape() * **********************************************************************/ int msWFSLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifdef USE_WFS_LYR msWFSLayerInfo* psInfo = NULL; if(layer != NULL && layer->wfslayerinfo != NULL) psInfo = (msWFSLayerInfo*)layer->wfslayerinfo; else { msSetError(MS_WFSERR, "Layer is not opened.", "msWFSLayerGetShape()"); return MS_FAILURE; } if(psInfo->bLayerHasValidGML) return msOGRLayerGetShape(layer, shape, record); else { /* Layer is successful, but there is no data to process */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_FAILURE; } #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerGetShape()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerGetNextShape() * **********************************************************************/ int msWFSLayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_WFS_LYR msWFSLayerInfo* psInfo = NULL; if(layer != NULL && layer->wfslayerinfo != NULL) psInfo = (msWFSLayerInfo*)layer->wfslayerinfo; else { msSetError(MS_WFSERR, "Layer is not opened.", "msWFSLayerNextShape()"); return MS_FAILURE; } if(psInfo->bLayerHasValidGML) return msOGRLayerNextShape(layer, shape); else { /* Layer is successful, but there is no data to process */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_FAILURE; } #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerNextShape()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerGetExtent() * **********************************************************************/ int msWFSLayerGetExtent(layerObj *layer, rectObj *extent) { #ifdef USE_WFS_LYR msWFSLayerInfo* psInfo = NULL; if(layer != NULL && layer->wfslayerinfo != NULL) psInfo = (msWFSLayerInfo*)layer->wfslayerinfo; else { msSetError(MS_WFSERR, "Layer is not opened.", "msWFSLayerGetExtent()"); return MS_FAILURE; } if(psInfo->bLayerHasValidGML) return msOGRLayerGetExtent(layer, extent); else { /* Layer is successful, but there is no data to process */ msSetError(MS_WFSERR, "Unable to get extents for this layer.", "msWFSLayerGetExtent()"); return MS_FAILURE; } #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerGetExtent()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerGetItems() * **********************************************************************/ int msWFSLayerGetItems(layerObj *layer) { #ifdef USE_WFS_LYR /* For now this method simply lets OGR parse the GML and figure the */ /* schema itself. */ /* It could also be implemented to call DescribeFeatureType for */ /* this layer, but we don't need to do it so why waste resources? */ msWFSLayerInfo* psInfo = NULL; if(layer != NULL && layer->wfslayerinfo != NULL) psInfo = (msWFSLayerInfo*)layer->wfslayerinfo; else { msSetError(MS_WFSERR, "Layer is not opened.", "msWFSLayerGetItems()"); return MS_FAILURE; } if(psInfo->bLayerHasValidGML) return msOGRLayerGetItems(layer); else { /* Layer is successful, but there is no data to process */ layer->numitems = 0; layer->items = NULL; return MS_SUCCESS; } #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerGetItems()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerWhichShapes() * **********************************************************************/ int msWFSLayerWhichShapes(layerObj *lp, rectObj rect, int isQuery) { #ifdef USE_WFS_LYR msWFSLayerInfo *psInfo; int status = MS_SUCCESS; const char *pszTmp; FILE *fp; if ( msCheckParentPointer(lp->map,"map")==MS_FAILURE ) return MS_FAILURE; psInfo =(msWFSLayerInfo*)lp->wfslayerinfo; if (psInfo == NULL) { msSetError(MS_WFSCONNERR, "Assertion failed: WFS layer not opened!!!", "msWFSLayerWhichShapes()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Check if layer overlaps current view window (using wfs_latlonboundingbox) * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "latlonboundingbox")) != NULL) { char **tokens; int n; rectObj ext; tokens = msStringSplit(pszTmp, ' ', &n); if (tokens==NULL || n != 4) { msSetError(MS_WFSCONNERR, "Wrong number of values in 'wfs_latlonboundingbox' metadata.", "msWFSLayerWhichShapes()"); return MS_FAILURE; } ext.minx = atof(tokens[0]); ext.miny = atof(tokens[1]); ext.maxx = atof(tokens[2]); ext.maxy = atof(tokens[3]); msFreeCharArray(tokens, n); /* Reproject latlonboundingbox to the selected SRS for the layer and */ /* check if it overlaps the bbox that we calculated for the request */ msProjectRect(&(lp->map->latlon), &(lp->projection), &ext); if (!msRectOverlap(&rect, &ext)) { /* No overlap... nothing to do. If layer was never opened, go open it.*/ if (lp->layerinfo) return MS_DONE; /* No overlap. */ } } /* ------------------------------------------------------------------ * __TODO__ If new bbox differs from current one then we should * invalidate current GML file in cache * ------------------------------------------------------------------ */ psInfo->rect = rect; /* ------------------------------------------------------------------ * If file not downloaded yet then do it now. * ------------------------------------------------------------------ */ if (psInfo->nStatus == 0) { httpRequestObj asReqInfo[2]; int numReq = 0; msHTTPInitRequestObj(asReqInfo, 2); if ( msPrepareWFSLayerRequest(-1, lp->map, lp, asReqInfo, &numReq) == MS_FAILURE || msOWSExecuteRequests(asReqInfo, numReq, lp->map, MS_TRUE) == MS_FAILURE ) { /* Delete tmp file... we don't want it to stick around. */ unlink(asReqInfo[0].pszOutputFile); return MS_FAILURE; } /* Cleanup */ msHTTPFreeRequestObj(asReqInfo, numReq); } if ( !MS_HTTP_SUCCESS( psInfo->nStatus ) ) { /* Delete tmp file... we don't want it to stick around. */ unlink(psInfo->pszGMLFilename); msSetError(MS_WFSCONNERR, "Got HTTP status %d downloading WFS layer %s", "msWFSLayerWhichShapes()", psInfo->nStatus, lp->name?lp->name:"(null)"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Check that file is really GML... it could be an exception, or just junk. * ------------------------------------------------------------------ */ if ((fp = fopen(psInfo->pszGMLFilename, "r")) != NULL) { char szHeader[2000]; int nBytes = 0; nBytes = fread( szHeader, 1, sizeof(szHeader)-1, fp ); fclose(fp); if (nBytes < 0) nBytes = 0; szHeader[nBytes] = '\0'; if ( nBytes == 0 ) { msSetError(MS_WFSCONNERR, "WFS request produced no oputput for layer %s.", "msWFSLayerWhichShapes()", lp->name?lp->name:"(null)"); return(MS_FAILURE); } if ( strstr(szHeader, "") || strstr(szHeader, "") ) { msOWSProcessException(lp, psInfo->pszGMLFilename, MS_WFSCONNERR, "msWFSLayerWhichShapes()" ); return MS_FAILURE; } else if ( strstr(szHeader,"opengis.net/gml") && strstr(szHeader,"featureMember>") == NULL ) { /* This looks like valid GML, but contains 0 features. */ return MS_DONE; } else if ( strstr(szHeader,"opengis.net/gml") == NULL || strstr(szHeader,"featureMember>") == NULL ) { /* This is probably just junk. */ msSetError(MS_WFSCONNERR, "WFS request produced unexpected output (junk?) for layer %s.", "msWFSLayerWhichShapes()", lp->name?lp->name:"(null)"); return(MS_FAILURE); } /* If we got this far, it must be a valid GML dataset... keep going */ } /* ------------------------------------------------------------------ * Open GML file using OGR. * ------------------------------------------------------------------ */ if ((status = msOGRLayerOpen(lp, psInfo->pszGMLFilename)) != MS_SUCCESS) return status; status = msOGRLayerWhichShapes(lp, rect, isQuery); /* Mark that the OGR Layer is valid */ psInfo->bLayerHasValidGML = MS_TRUE; return status; #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerWhichShapes()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSLayerClose() * **********************************************************************/ int msWFSLayerClose(layerObj *lp) { #ifdef USE_WFS_LYR /* ------------------------------------------------------------------ * Cleanup OGR connection * ------------------------------------------------------------------ */ if (lp->layerinfo) msOGRLayerClose(lp); /* ------------------------------------------------------------------ * Cleanup WFS connection info. * __TODO__ For now we flush everything, but we should try to cache some stuff * ------------------------------------------------------------------ */ /* __TODO__ unlink() .gml file and OGR's schema file if they exist */ /* unlink( */ msFreeWFSLayerInfo(lp->wfslayerinfo); lp->wfslayerinfo = NULL; return MS_SUCCESS; #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerClose()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ } /********************************************************************** * msWFSExecuteGetFeature() * Returns the temporary gml file name. User shpuld free the return string. **********************************************************************/ char *msWFSExecuteGetFeature(layerObj *lp) { #ifdef USE_WFS_LYR char *gmltmpfile = NULL; msWFSLayerInfo *psInfo = NULL; if (lp == NULL || lp->connectiontype != MS_WFS) return NULL; msWFSLayerOpen(lp, NULL, NULL); psInfo =(msWFSLayerInfo*)lp->wfslayerinfo; if (psInfo && psInfo->pszGMLFilename) gmltmpfile = msStrdup(psInfo->pszGMLFilename); msWFSLayerClose(lp); return gmltmpfile; #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msExecuteWFSGetFeature()"); return NULL; #endif /* USE_WFS_LYR */ } int msWFSLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msWFSLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msOGRLayerFreeItemInfo; /* yes, OGR */ layer->vtable->LayerOpen = msWFSLayerOpenVT; layer->vtable->LayerIsOpen = msWFSLayerIsOpen; layer->vtable->LayerWhichShapes = msWFSLayerWhichShapes; layer->vtable->LayerNextShape = msWFSLayerNextShape; /* layer->vtable->LayerResultsGetShape = msWFSLayerResultGetShape; */ layer->vtable->LayerGetShape = msWFSLayerGetShape; layer->vtable->LayerClose = msWFSLayerClose; layer->vtable->LayerGetItems = msWFSLayerGetItems; layer->vtable->LayerGetExtent = msWFSLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection, use defaut*/ return MS_SUCCESS; } mapserver-6.4.1/legend.c0000644002461700001440000000414012261257215014715 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Mainline of commandline legend generation test utility. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" int main(int argc, char *argv[]) { mapObj *map=NULL; imageObj *img=NULL; if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } if( argc < 3 ) { fprintf(stdout,"Syntax: legend [mapfile] [output image]\n" ); exit(0); } map = msLoadMap(argv[1], NULL); if(!map) { msWriteError(stderr); exit(0); } img = msDrawLegend(map, MS_FALSE, NULL); if(!img) { msWriteError(stderr); exit(0); } msSaveImage(NULL, img, argv[2]); msFreeImage(img); msFreeMap(map); return(MS_TRUE); } mapserver-6.4.1/opengl/0000755002461700001440000000000012261257215014600 5ustar tbonfortusersmapserver-6.4.1/opengl/glext.h0000644002461700001440000123412012261257215016077 0ustar tbonfortusers#ifndef __glext_h_ #define __glext_h_ #ifdef __cplusplus extern "C" { #endif /****************************************************************************** Copyright NVIDIA Corporation 2005 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ******************************************************************************/ /* ** License Applicability. Except to the extent portions of this file are ** made subject to an alternative license as permitted in the SGI Free ** Software License B, Version 1.1 (the "License"), the contents of this ** file are subject only to the provisions of the License. You may not use ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: ** ** http://oss.sgi.com/projects/FreeB ** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. ** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. ** ** Additional Notice Provisions: This software was created using the ** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has ** not been independently verified as being compliant with the OpenGL(R) ** version 1.2.1 Specification. */ #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) #define WIN32_LEAN_AND_MEAN 1 #include #endif #ifndef APIENTRY #define APIENTRY #endif #ifndef APIENTRYP #define APIENTRYP APIENTRY * #endif #ifndef GLAPI #define GLAPI extern #endif /*************************************************************/ /* Header file version number, required by OpenGL ABI for Linux */ /* glext.h last updated 2005/06/06 */ /* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ #define GL_GLEXT_VERSION 28 #ifndef GL_VERSION_1_2 #define GL_UNSIGNED_BYTE_3_3_2 0x8032 #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #define GL_UNSIGNED_INT_8_8_8_8 0x8035 #define GL_UNSIGNED_INT_10_10_10_2 0x8036 #define GL_RESCALE_NORMAL 0x803A #define GL_TEXTURE_BINDING_3D 0x806A #define GL_PACK_SKIP_IMAGES 0x806B #define GL_PACK_IMAGE_HEIGHT 0x806C #define GL_UNPACK_SKIP_IMAGES 0x806D #define GL_UNPACK_IMAGE_HEIGHT 0x806E #define GL_TEXTURE_3D 0x806F #define GL_PROXY_TEXTURE_3D 0x8070 #define GL_TEXTURE_DEPTH 0x8071 #define GL_TEXTURE_WRAP_R 0x8072 #define GL_MAX_3D_TEXTURE_SIZE 0x8073 #define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 #define GL_UNSIGNED_SHORT_5_6_5 0x8363 #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #define GL_BGR 0x80E0 #define GL_BGRA 0x80E1 #define GL_MAX_ELEMENTS_VERTICES 0x80E8 #define GL_MAX_ELEMENTS_INDICES 0x80E9 #define GL_CLAMP_TO_EDGE 0x812F #define GL_TEXTURE_MIN_LOD 0x813A #define GL_TEXTURE_MAX_LOD 0x813B #define GL_TEXTURE_BASE_LEVEL 0x813C #define GL_TEXTURE_MAX_LEVEL 0x813D #define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 #define GL_SINGLE_COLOR 0x81F9 #define GL_SEPARATE_SPECULAR_COLOR 0x81FA #define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 #define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 #define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 #define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 #define GL_ALIASED_POINT_SIZE_RANGE 0x846D #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E #endif #ifndef GL_ARB_imaging #define GL_CONSTANT_COLOR 0x8001 #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 #define GL_CONSTANT_ALPHA 0x8003 #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 #define GL_BLEND_COLOR 0x8005 #define GL_FUNC_ADD 0x8006 #define GL_MIN 0x8007 #define GL_MAX 0x8008 #define GL_BLEND_EQUATION 0x8009 #define GL_FUNC_SUBTRACT 0x800A #define GL_FUNC_REVERSE_SUBTRACT 0x800B #define GL_CONVOLUTION_1D 0x8010 #define GL_CONVOLUTION_2D 0x8011 #define GL_SEPARABLE_2D 0x8012 #define GL_CONVOLUTION_BORDER_MODE 0x8013 #define GL_CONVOLUTION_FILTER_SCALE 0x8014 #define GL_CONVOLUTION_FILTER_BIAS 0x8015 #define GL_REDUCE 0x8016 #define GL_CONVOLUTION_FORMAT 0x8017 #define GL_CONVOLUTION_WIDTH 0x8018 #define GL_CONVOLUTION_HEIGHT 0x8019 #define GL_MAX_CONVOLUTION_WIDTH 0x801A #define GL_MAX_CONVOLUTION_HEIGHT 0x801B #define GL_POST_CONVOLUTION_RED_SCALE 0x801C #define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D #define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E #define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F #define GL_POST_CONVOLUTION_RED_BIAS 0x8020 #define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 #define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 #define GL_HISTOGRAM 0x8024 #define GL_PROXY_HISTOGRAM 0x8025 #define GL_HISTOGRAM_WIDTH 0x8026 #define GL_HISTOGRAM_FORMAT 0x8027 #define GL_HISTOGRAM_RED_SIZE 0x8028 #define GL_HISTOGRAM_GREEN_SIZE 0x8029 #define GL_HISTOGRAM_BLUE_SIZE 0x802A #define GL_HISTOGRAM_ALPHA_SIZE 0x802B #define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C #define GL_HISTOGRAM_SINK 0x802D #define GL_MINMAX 0x802E #define GL_MINMAX_FORMAT 0x802F #define GL_MINMAX_SINK 0x8030 #define GL_TABLE_TOO_LARGE 0x8031 #define GL_COLOR_MATRIX 0x80B1 #define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 #define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 #define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 #define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 #define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 #define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 #define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 #define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 #define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA #define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB #define GL_COLOR_TABLE 0x80D0 #define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 #define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 #define GL_PROXY_COLOR_TABLE 0x80D3 #define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 #define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 #define GL_COLOR_TABLE_SCALE 0x80D6 #define GL_COLOR_TABLE_BIAS 0x80D7 #define GL_COLOR_TABLE_FORMAT 0x80D8 #define GL_COLOR_TABLE_WIDTH 0x80D9 #define GL_COLOR_TABLE_RED_SIZE 0x80DA #define GL_COLOR_TABLE_GREEN_SIZE 0x80DB #define GL_COLOR_TABLE_BLUE_SIZE 0x80DC #define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD #define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE #define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF #define GL_CONSTANT_BORDER 0x8151 #define GL_REPLICATE_BORDER 0x8153 #define GL_CONVOLUTION_BORDER_COLOR 0x8154 #endif #ifndef GL_VERSION_1_3 #define GL_TEXTURE0 0x84C0 #define GL_TEXTURE1 0x84C1 #define GL_TEXTURE2 0x84C2 #define GL_TEXTURE3 0x84C3 #define GL_TEXTURE4 0x84C4 #define GL_TEXTURE5 0x84C5 #define GL_TEXTURE6 0x84C6 #define GL_TEXTURE7 0x84C7 #define GL_TEXTURE8 0x84C8 #define GL_TEXTURE9 0x84C9 #define GL_TEXTURE10 0x84CA #define GL_TEXTURE11 0x84CB #define GL_TEXTURE12 0x84CC #define GL_TEXTURE13 0x84CD #define GL_TEXTURE14 0x84CE #define GL_TEXTURE15 0x84CF #define GL_TEXTURE16 0x84D0 #define GL_TEXTURE17 0x84D1 #define GL_TEXTURE18 0x84D2 #define GL_TEXTURE19 0x84D3 #define GL_TEXTURE20 0x84D4 #define GL_TEXTURE21 0x84D5 #define GL_TEXTURE22 0x84D6 #define GL_TEXTURE23 0x84D7 #define GL_TEXTURE24 0x84D8 #define GL_TEXTURE25 0x84D9 #define GL_TEXTURE26 0x84DA #define GL_TEXTURE27 0x84DB #define GL_TEXTURE28 0x84DC #define GL_TEXTURE29 0x84DD #define GL_TEXTURE30 0x84DE #define GL_TEXTURE31 0x84DF #define GL_ACTIVE_TEXTURE 0x84E0 #define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 #define GL_MAX_TEXTURE_UNITS 0x84E2 #define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 #define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 #define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 #define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 #define GL_MULTISAMPLE 0x809D #define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E #define GL_SAMPLE_ALPHA_TO_ONE 0x809F #define GL_SAMPLE_COVERAGE 0x80A0 #define GL_SAMPLE_BUFFERS 0x80A8 #define GL_SAMPLES 0x80A9 #define GL_SAMPLE_COVERAGE_VALUE 0x80AA #define GL_SAMPLE_COVERAGE_INVERT 0x80AB #define GL_MULTISAMPLE_BIT 0x20000000 #define GL_NORMAL_MAP 0x8511 #define GL_REFLECTION_MAP 0x8512 #define GL_TEXTURE_CUBE_MAP 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C #define GL_COMPRESSED_ALPHA 0x84E9 #define GL_COMPRESSED_LUMINANCE 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB #define GL_COMPRESSED_INTENSITY 0x84EC #define GL_COMPRESSED_RGB 0x84ED #define GL_COMPRESSED_RGBA 0x84EE #define GL_TEXTURE_COMPRESSION_HINT 0x84EF #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 #define GL_TEXTURE_COMPRESSED 0x86A1 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 #define GL_CLAMP_TO_BORDER 0x812D #define GL_COMBINE 0x8570 #define GL_COMBINE_RGB 0x8571 #define GL_COMBINE_ALPHA 0x8572 #define GL_SOURCE0_RGB 0x8580 #define GL_SOURCE1_RGB 0x8581 #define GL_SOURCE2_RGB 0x8582 #define GL_SOURCE0_ALPHA 0x8588 #define GL_SOURCE1_ALPHA 0x8589 #define GL_SOURCE2_ALPHA 0x858A #define GL_OPERAND0_RGB 0x8590 #define GL_OPERAND1_RGB 0x8591 #define GL_OPERAND2_RGB 0x8592 #define GL_OPERAND0_ALPHA 0x8598 #define GL_OPERAND1_ALPHA 0x8599 #define GL_OPERAND2_ALPHA 0x859A #define GL_RGB_SCALE 0x8573 #define GL_ADD_SIGNED 0x8574 #define GL_INTERPOLATE 0x8575 #define GL_SUBTRACT 0x84E7 #define GL_CONSTANT 0x8576 #define GL_PRIMARY_COLOR 0x8577 #define GL_PREVIOUS 0x8578 #define GL_DOT3_RGB 0x86AE #define GL_DOT3_RGBA 0x86AF #endif #ifndef GL_VERSION_1_4 #define GL_BLEND_DST_RGB 0x80C8 #define GL_BLEND_SRC_RGB 0x80C9 #define GL_BLEND_DST_ALPHA 0x80CA #define GL_BLEND_SRC_ALPHA 0x80CB #define GL_POINT_SIZE_MIN 0x8126 #define GL_POINT_SIZE_MAX 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 #define GL_POINT_DISTANCE_ATTENUATION 0x8129 #define GL_GENERATE_MIPMAP 0x8191 #define GL_GENERATE_MIPMAP_HINT 0x8192 #define GL_DEPTH_COMPONENT16 0x81A5 #define GL_DEPTH_COMPONENT24 0x81A6 #define GL_DEPTH_COMPONENT32 0x81A7 #define GL_MIRRORED_REPEAT 0x8370 #define GL_FOG_COORDINATE_SOURCE 0x8450 #define GL_FOG_COORDINATE 0x8451 #define GL_FRAGMENT_DEPTH 0x8452 #define GL_CURRENT_FOG_COORDINATE 0x8453 #define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 #define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 #define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 #define GL_FOG_COORDINATE_ARRAY 0x8457 #define GL_COLOR_SUM 0x8458 #define GL_CURRENT_SECONDARY_COLOR 0x8459 #define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A #define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B #define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C #define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D #define GL_SECONDARY_COLOR_ARRAY 0x845E #define GL_MAX_TEXTURE_LOD_BIAS 0x84FD #define GL_TEXTURE_FILTER_CONTROL 0x8500 #define GL_TEXTURE_LOD_BIAS 0x8501 #define GL_INCR_WRAP 0x8507 #define GL_DECR_WRAP 0x8508 #define GL_TEXTURE_DEPTH_SIZE 0x884A #define GL_DEPTH_TEXTURE_MODE 0x884B #define GL_TEXTURE_COMPARE_MODE 0x884C #define GL_TEXTURE_COMPARE_FUNC 0x884D #define GL_COMPARE_R_TO_TEXTURE 0x884E #endif #ifndef GL_VERSION_1_5 #define GL_BUFFER_SIZE 0x8764 #define GL_BUFFER_USAGE 0x8765 #define GL_QUERY_COUNTER_BITS 0x8864 #define GL_CURRENT_QUERY 0x8865 #define GL_QUERY_RESULT 0x8866 #define GL_QUERY_RESULT_AVAILABLE 0x8867 #define GL_ARRAY_BUFFER 0x8892 #define GL_ELEMENT_ARRAY_BUFFER 0x8893 #define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 #define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 #define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 #define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 #define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D #define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F #define GL_READ_ONLY 0x88B8 #define GL_WRITE_ONLY 0x88B9 #define GL_READ_WRITE 0x88BA #define GL_BUFFER_ACCESS 0x88BB #define GL_BUFFER_MAPPED 0x88BC #define GL_BUFFER_MAP_POINTER 0x88BD #define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_READ 0x88E1 #define GL_STREAM_COPY 0x88E2 #define GL_STATIC_DRAW 0x88E4 #define GL_STATIC_READ 0x88E5 #define GL_STATIC_COPY 0x88E6 #define GL_DYNAMIC_DRAW 0x88E8 #define GL_DYNAMIC_READ 0x88E9 #define GL_DYNAMIC_COPY 0x88EA #define GL_SAMPLES_PASSED 0x8914 #define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE #define GL_FOG_COORD GL_FOG_COORDINATE #define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE #define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE #define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE #define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER #define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY #define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING #define GL_SRC0_RGB GL_SOURCE0_RGB #define GL_SRC1_RGB GL_SOURCE1_RGB #define GL_SRC2_RGB GL_SOURCE2_RGB #define GL_SRC0_ALPHA GL_SOURCE0_ALPHA #define GL_SRC1_ALPHA GL_SOURCE1_ALPHA #define GL_SRC2_ALPHA GL_SOURCE2_ALPHA #endif #ifndef GL_VERSION_2_0 #define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION #define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 #define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 #define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 #define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 #define GL_CURRENT_VERTEX_ATTRIB 0x8626 #define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 #define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 #define GL_STENCIL_BACK_FUNC 0x8800 #define GL_STENCIL_BACK_FAIL 0x8801 #define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 #define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 #define GL_MAX_DRAW_BUFFERS 0x8824 #define GL_DRAW_BUFFER0 0x8825 #define GL_DRAW_BUFFER1 0x8826 #define GL_DRAW_BUFFER2 0x8827 #define GL_DRAW_BUFFER3 0x8828 #define GL_DRAW_BUFFER4 0x8829 #define GL_DRAW_BUFFER5 0x882A #define GL_DRAW_BUFFER6 0x882B #define GL_DRAW_BUFFER7 0x882C #define GL_DRAW_BUFFER8 0x882D #define GL_DRAW_BUFFER9 0x882E #define GL_DRAW_BUFFER10 0x882F #define GL_DRAW_BUFFER11 0x8830 #define GL_DRAW_BUFFER12 0x8831 #define GL_DRAW_BUFFER13 0x8832 #define GL_DRAW_BUFFER14 0x8833 #define GL_DRAW_BUFFER15 0x8834 #define GL_BLEND_EQUATION_ALPHA 0x883D #define GL_POINT_SPRITE 0x8861 #define GL_COORD_REPLACE 0x8862 #define GL_MAX_VERTEX_ATTRIBS 0x8869 #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A #define GL_MAX_TEXTURE_COORDS 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 #define GL_FRAGMENT_SHADER 0x8B30 #define GL_VERTEX_SHADER 0x8B31 #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 #define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A #define GL_MAX_VARYING_FLOATS 0x8B4B #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D #define GL_SHADER_TYPE 0x8B4F #define GL_FLOAT_VEC2 0x8B50 #define GL_FLOAT_VEC3 0x8B51 #define GL_FLOAT_VEC4 0x8B52 #define GL_INT_VEC2 0x8B53 #define GL_INT_VEC3 0x8B54 #define GL_INT_VEC4 0x8B55 #define GL_BOOL 0x8B56 #define GL_BOOL_VEC2 0x8B57 #define GL_BOOL_VEC3 0x8B58 #define GL_BOOL_VEC4 0x8B59 #define GL_FLOAT_MAT2 0x8B5A #define GL_FLOAT_MAT3 0x8B5B #define GL_FLOAT_MAT4 0x8B5C #define GL_SAMPLER_1D 0x8B5D #define GL_SAMPLER_2D 0x8B5E #define GL_SAMPLER_3D 0x8B5F #define GL_SAMPLER_CUBE 0x8B60 #define GL_SAMPLER_1D_SHADOW 0x8B61 #define GL_SAMPLER_2D_SHADOW 0x8B62 #define GL_DELETE_STATUS 0x8B80 #define GL_COMPILE_STATUS 0x8B81 #define GL_LINK_STATUS 0x8B82 #define GL_VALIDATE_STATUS 0x8B83 #define GL_INFO_LOG_LENGTH 0x8B84 #define GL_ATTACHED_SHADERS 0x8B85 #define GL_ACTIVE_UNIFORMS 0x8B86 #define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 #define GL_SHADER_SOURCE_LENGTH 0x8B88 #define GL_ACTIVE_ATTRIBUTES 0x8B89 #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B #define GL_SHADING_LANGUAGE_VERSION 0x8B8C #define GL_CURRENT_PROGRAM 0x8B8D #define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 #define GL_LOWER_LEFT 0x8CA1 #define GL_UPPER_LEFT 0x8CA2 #define GL_STENCIL_BACK_REF 0x8CA3 #define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 #define GL_STENCIL_BACK_WRITEMASK 0x8CA5 #endif #ifndef GL_ARB_multitexture #define GL_TEXTURE0_ARB 0x84C0 #define GL_TEXTURE1_ARB 0x84C1 #define GL_TEXTURE2_ARB 0x84C2 #define GL_TEXTURE3_ARB 0x84C3 #define GL_TEXTURE4_ARB 0x84C4 #define GL_TEXTURE5_ARB 0x84C5 #define GL_TEXTURE6_ARB 0x84C6 #define GL_TEXTURE7_ARB 0x84C7 #define GL_TEXTURE8_ARB 0x84C8 #define GL_TEXTURE9_ARB 0x84C9 #define GL_TEXTURE10_ARB 0x84CA #define GL_TEXTURE11_ARB 0x84CB #define GL_TEXTURE12_ARB 0x84CC #define GL_TEXTURE13_ARB 0x84CD #define GL_TEXTURE14_ARB 0x84CE #define GL_TEXTURE15_ARB 0x84CF #define GL_TEXTURE16_ARB 0x84D0 #define GL_TEXTURE17_ARB 0x84D1 #define GL_TEXTURE18_ARB 0x84D2 #define GL_TEXTURE19_ARB 0x84D3 #define GL_TEXTURE20_ARB 0x84D4 #define GL_TEXTURE21_ARB 0x84D5 #define GL_TEXTURE22_ARB 0x84D6 #define GL_TEXTURE23_ARB 0x84D7 #define GL_TEXTURE24_ARB 0x84D8 #define GL_TEXTURE25_ARB 0x84D9 #define GL_TEXTURE26_ARB 0x84DA #define GL_TEXTURE27_ARB 0x84DB #define GL_TEXTURE28_ARB 0x84DC #define GL_TEXTURE29_ARB 0x84DD #define GL_TEXTURE30_ARB 0x84DE #define GL_TEXTURE31_ARB 0x84DF #define GL_ACTIVE_TEXTURE_ARB 0x84E0 #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 #define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 #endif #ifndef GL_ARB_transpose_matrix #define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 #define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 #define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 #define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 #endif #ifndef GL_ARB_multisample #define GL_MULTISAMPLE_ARB 0x809D #define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E #define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F #define GL_SAMPLE_COVERAGE_ARB 0x80A0 #define GL_SAMPLE_BUFFERS_ARB 0x80A8 #define GL_SAMPLES_ARB 0x80A9 #define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA #define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB #define GL_MULTISAMPLE_BIT_ARB 0x20000000 #endif #ifndef GL_ARB_texture_env_add #endif #ifndef GL_ARB_texture_cube_map #define GL_NORMAL_MAP_ARB 0x8511 #define GL_REFLECTION_MAP_ARB 0x8512 #define GL_TEXTURE_CUBE_MAP_ARB 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C #endif #ifndef GL_ARB_texture_compression #define GL_COMPRESSED_ALPHA_ARB 0x84E9 #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB #define GL_COMPRESSED_INTENSITY_ARB 0x84EC #define GL_COMPRESSED_RGB_ARB 0x84ED #define GL_COMPRESSED_RGBA_ARB 0x84EE #define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 #define GL_TEXTURE_COMPRESSED_ARB 0x86A1 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 #endif #ifndef GL_ARB_texture_border_clamp #define GL_CLAMP_TO_BORDER_ARB 0x812D #endif #ifndef GL_ARB_point_parameters #define GL_POINT_SIZE_MIN_ARB 0x8126 #define GL_POINT_SIZE_MAX_ARB 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 #define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 #endif #ifndef GL_ARB_vertex_blend #define GL_MAX_VERTEX_UNITS_ARB 0x86A4 #define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 #define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 #define GL_VERTEX_BLEND_ARB 0x86A7 #define GL_CURRENT_WEIGHT_ARB 0x86A8 #define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 #define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA #define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB #define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC #define GL_WEIGHT_ARRAY_ARB 0x86AD #define GL_MODELVIEW0_ARB 0x1700 #define GL_MODELVIEW1_ARB 0x850A #define GL_MODELVIEW2_ARB 0x8722 #define GL_MODELVIEW3_ARB 0x8723 #define GL_MODELVIEW4_ARB 0x8724 #define GL_MODELVIEW5_ARB 0x8725 #define GL_MODELVIEW6_ARB 0x8726 #define GL_MODELVIEW7_ARB 0x8727 #define GL_MODELVIEW8_ARB 0x8728 #define GL_MODELVIEW9_ARB 0x8729 #define GL_MODELVIEW10_ARB 0x872A #define GL_MODELVIEW11_ARB 0x872B #define GL_MODELVIEW12_ARB 0x872C #define GL_MODELVIEW13_ARB 0x872D #define GL_MODELVIEW14_ARB 0x872E #define GL_MODELVIEW15_ARB 0x872F #define GL_MODELVIEW16_ARB 0x8730 #define GL_MODELVIEW17_ARB 0x8731 #define GL_MODELVIEW18_ARB 0x8732 #define GL_MODELVIEW19_ARB 0x8733 #define GL_MODELVIEW20_ARB 0x8734 #define GL_MODELVIEW21_ARB 0x8735 #define GL_MODELVIEW22_ARB 0x8736 #define GL_MODELVIEW23_ARB 0x8737 #define GL_MODELVIEW24_ARB 0x8738 #define GL_MODELVIEW25_ARB 0x8739 #define GL_MODELVIEW26_ARB 0x873A #define GL_MODELVIEW27_ARB 0x873B #define GL_MODELVIEW28_ARB 0x873C #define GL_MODELVIEW29_ARB 0x873D #define GL_MODELVIEW30_ARB 0x873E #define GL_MODELVIEW31_ARB 0x873F #endif #ifndef GL_ARB_matrix_palette #define GL_MATRIX_PALETTE_ARB 0x8840 #define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 #define GL_MAX_PALETTE_MATRICES_ARB 0x8842 #define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 #define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 #define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 #define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 #define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 #define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 #define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 #endif #ifndef GL_ARB_texture_env_combine #define GL_COMBINE_ARB 0x8570 #define GL_COMBINE_RGB_ARB 0x8571 #define GL_COMBINE_ALPHA_ARB 0x8572 #define GL_SOURCE0_RGB_ARB 0x8580 #define GL_SOURCE1_RGB_ARB 0x8581 #define GL_SOURCE2_RGB_ARB 0x8582 #define GL_SOURCE0_ALPHA_ARB 0x8588 #define GL_SOURCE1_ALPHA_ARB 0x8589 #define GL_SOURCE2_ALPHA_ARB 0x858A #define GL_OPERAND0_RGB_ARB 0x8590 #define GL_OPERAND1_RGB_ARB 0x8591 #define GL_OPERAND2_RGB_ARB 0x8592 #define GL_OPERAND0_ALPHA_ARB 0x8598 #define GL_OPERAND1_ALPHA_ARB 0x8599 #define GL_OPERAND2_ALPHA_ARB 0x859A #define GL_RGB_SCALE_ARB 0x8573 #define GL_ADD_SIGNED_ARB 0x8574 #define GL_INTERPOLATE_ARB 0x8575 #define GL_SUBTRACT_ARB 0x84E7 #define GL_CONSTANT_ARB 0x8576 #define GL_PRIMARY_COLOR_ARB 0x8577 #define GL_PREVIOUS_ARB 0x8578 #endif #ifndef GL_ARB_texture_env_crossbar #endif #ifndef GL_ARB_texture_env_dot3 #define GL_DOT3_RGB_ARB 0x86AE #define GL_DOT3_RGBA_ARB 0x86AF #endif #ifndef GL_ARB_texture_mirrored_repeat #define GL_MIRRORED_REPEAT_ARB 0x8370 #endif #ifndef GL_ARB_depth_texture #define GL_DEPTH_COMPONENT16_ARB 0x81A5 #define GL_DEPTH_COMPONENT24_ARB 0x81A6 #define GL_DEPTH_COMPONENT32_ARB 0x81A7 #define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A #define GL_DEPTH_TEXTURE_MODE_ARB 0x884B #endif #ifndef GL_ARB_shadow #define GL_TEXTURE_COMPARE_MODE_ARB 0x884C #define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D #define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E #endif #ifndef GL_ARB_shadow_ambient #define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF #endif #ifndef GL_ARB_window_pos #endif #ifndef GL_ARB_vertex_program #define GL_COLOR_SUM_ARB 0x8458 #define GL_VERTEX_PROGRAM_ARB 0x8620 #define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 #define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 #define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 #define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 #define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 #define GL_PROGRAM_LENGTH_ARB 0x8627 #define GL_PROGRAM_STRING_ARB 0x8628 #define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E #define GL_MAX_PROGRAM_MATRICES_ARB 0x862F #define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 #define GL_CURRENT_MATRIX_ARB 0x8641 #define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 #define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 #define GL_PROGRAM_ERROR_POSITION_ARB 0x864B #define GL_PROGRAM_BINDING_ARB 0x8677 #define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A #define GL_PROGRAM_ERROR_STRING_ARB 0x8874 #define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 #define GL_PROGRAM_FORMAT_ARB 0x8876 #define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 #define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 #define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 #define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 #define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 #define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 #define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 #define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 #define GL_PROGRAM_PARAMETERS_ARB 0x88A8 #define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 #define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA #define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB #define GL_PROGRAM_ATTRIBS_ARB 0x88AC #define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD #define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE #define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF #define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 #define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 #define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 #define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 #define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 #define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 #define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 #define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 #define GL_MATRIX0_ARB 0x88C0 #define GL_MATRIX1_ARB 0x88C1 #define GL_MATRIX2_ARB 0x88C2 #define GL_MATRIX3_ARB 0x88C3 #define GL_MATRIX4_ARB 0x88C4 #define GL_MATRIX5_ARB 0x88C5 #define GL_MATRIX6_ARB 0x88C6 #define GL_MATRIX7_ARB 0x88C7 #define GL_MATRIX8_ARB 0x88C8 #define GL_MATRIX9_ARB 0x88C9 #define GL_MATRIX10_ARB 0x88CA #define GL_MATRIX11_ARB 0x88CB #define GL_MATRIX12_ARB 0x88CC #define GL_MATRIX13_ARB 0x88CD #define GL_MATRIX14_ARB 0x88CE #define GL_MATRIX15_ARB 0x88CF #define GL_MATRIX16_ARB 0x88D0 #define GL_MATRIX17_ARB 0x88D1 #define GL_MATRIX18_ARB 0x88D2 #define GL_MATRIX19_ARB 0x88D3 #define GL_MATRIX20_ARB 0x88D4 #define GL_MATRIX21_ARB 0x88D5 #define GL_MATRIX22_ARB 0x88D6 #define GL_MATRIX23_ARB 0x88D7 #define GL_MATRIX24_ARB 0x88D8 #define GL_MATRIX25_ARB 0x88D9 #define GL_MATRIX26_ARB 0x88DA #define GL_MATRIX27_ARB 0x88DB #define GL_MATRIX28_ARB 0x88DC #define GL_MATRIX29_ARB 0x88DD #define GL_MATRIX30_ARB 0x88DE #define GL_MATRIX31_ARB 0x88DF #endif #ifndef GL_ARB_fragment_program #define GL_FRAGMENT_PROGRAM_ARB 0x8804 #define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 #define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 #define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 #define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 #define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 #define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A #define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B #define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C #define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D #define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E #define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F #define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 #define GL_MAX_TEXTURE_COORDS_ARB 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 #endif #ifndef GL_ARB_vertex_buffer_object #define GL_BUFFER_SIZE_ARB 0x8764 #define GL_BUFFER_USAGE_ARB 0x8765 #define GL_ARRAY_BUFFER_ARB 0x8892 #define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 #define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 #define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 #define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 #define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 #define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D #define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F #define GL_READ_ONLY_ARB 0x88B8 #define GL_WRITE_ONLY_ARB 0x88B9 #define GL_READ_WRITE_ARB 0x88BA #define GL_BUFFER_ACCESS_ARB 0x88BB #define GL_BUFFER_MAPPED_ARB 0x88BC #define GL_BUFFER_MAP_POINTER_ARB 0x88BD #define GL_STREAM_DRAW_ARB 0x88E0 #define GL_STREAM_READ_ARB 0x88E1 #define GL_STREAM_COPY_ARB 0x88E2 #define GL_STATIC_DRAW_ARB 0x88E4 #define GL_STATIC_READ_ARB 0x88E5 #define GL_STATIC_COPY_ARB 0x88E6 #define GL_DYNAMIC_DRAW_ARB 0x88E8 #define GL_DYNAMIC_READ_ARB 0x88E9 #define GL_DYNAMIC_COPY_ARB 0x88EA #endif #ifndef GL_ARB_occlusion_query #define GL_QUERY_COUNTER_BITS_ARB 0x8864 #define GL_CURRENT_QUERY_ARB 0x8865 #define GL_QUERY_RESULT_ARB 0x8866 #define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 #define GL_SAMPLES_PASSED_ARB 0x8914 #endif #ifndef GL_ARB_shader_objects #define GL_PROGRAM_OBJECT_ARB 0x8B40 #define GL_SHADER_OBJECT_ARB 0x8B48 #define GL_OBJECT_TYPE_ARB 0x8B4E #define GL_OBJECT_SUBTYPE_ARB 0x8B4F #define GL_FLOAT_VEC2_ARB 0x8B50 #define GL_FLOAT_VEC3_ARB 0x8B51 #define GL_FLOAT_VEC4_ARB 0x8B52 #define GL_INT_VEC2_ARB 0x8B53 #define GL_INT_VEC3_ARB 0x8B54 #define GL_INT_VEC4_ARB 0x8B55 #define GL_BOOL_ARB 0x8B56 #define GL_BOOL_VEC2_ARB 0x8B57 #define GL_BOOL_VEC3_ARB 0x8B58 #define GL_BOOL_VEC4_ARB 0x8B59 #define GL_FLOAT_MAT2_ARB 0x8B5A #define GL_FLOAT_MAT3_ARB 0x8B5B #define GL_FLOAT_MAT4_ARB 0x8B5C #define GL_SAMPLER_1D_ARB 0x8B5D #define GL_SAMPLER_2D_ARB 0x8B5E #define GL_SAMPLER_3D_ARB 0x8B5F #define GL_SAMPLER_CUBE_ARB 0x8B60 #define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 #define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 #define GL_SAMPLER_2D_RECT_ARB 0x8B63 #define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 #define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 #define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 #define GL_OBJECT_LINK_STATUS_ARB 0x8B82 #define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 #define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 #define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 #define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 #define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 #define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 #endif #ifndef GL_ARB_vertex_shader #define GL_VERTEX_SHADER_ARB 0x8B31 #define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A #define GL_MAX_VARYING_FLOATS_ARB 0x8B4B #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D #define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 #define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A #endif #ifndef GL_ARB_fragment_shader #define GL_FRAGMENT_SHADER_ARB 0x8B30 #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B #endif #ifndef GL_ARB_shading_language_100 #define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C #endif #ifndef GL_ARB_texture_non_power_of_two #endif #ifndef GL_ARB_point_sprite #define GL_POINT_SPRITE_ARB 0x8861 #define GL_COORD_REPLACE_ARB 0x8862 #endif #ifndef GL_ARB_fragment_program_shadow #endif #ifndef GL_ARB_draw_buffers #define GL_MAX_DRAW_BUFFERS_ARB 0x8824 #define GL_DRAW_BUFFER0_ARB 0x8825 #define GL_DRAW_BUFFER1_ARB 0x8826 #define GL_DRAW_BUFFER2_ARB 0x8827 #define GL_DRAW_BUFFER3_ARB 0x8828 #define GL_DRAW_BUFFER4_ARB 0x8829 #define GL_DRAW_BUFFER5_ARB 0x882A #define GL_DRAW_BUFFER6_ARB 0x882B #define GL_DRAW_BUFFER7_ARB 0x882C #define GL_DRAW_BUFFER8_ARB 0x882D #define GL_DRAW_BUFFER9_ARB 0x882E #define GL_DRAW_BUFFER10_ARB 0x882F #define GL_DRAW_BUFFER11_ARB 0x8830 #define GL_DRAW_BUFFER12_ARB 0x8831 #define GL_DRAW_BUFFER13_ARB 0x8832 #define GL_DRAW_BUFFER14_ARB 0x8833 #define GL_DRAW_BUFFER15_ARB 0x8834 #endif #ifndef GL_ARB_texture_rectangle #define GL_TEXTURE_RECTANGLE_ARB 0x84F5 #define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 #define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 #define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 #endif #ifndef GL_ARB_color_buffer_float #define GL_RGBA_FLOAT_MODE_ARB 0x8820 #define GL_CLAMP_VERTEX_COLOR_ARB 0x891A #define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B #define GL_CLAMP_READ_COLOR_ARB 0x891C #define GL_FIXED_ONLY_ARB 0x891D #endif #ifndef GL_ARB_half_float_pixel #define GL_HALF_FLOAT_ARB 0x140B #endif #ifndef GL_ARB_texture_float #define GL_TEXTURE_RED_TYPE_ARB 0x8C10 #define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 #define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 #define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 #define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 #define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 #define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 #define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 #define GL_RGBA32F_ARB 0x8814 #define GL_RGB32F_ARB 0x8815 #define GL_ALPHA32F_ARB 0x8816 #define GL_INTENSITY32F_ARB 0x8817 #define GL_LUMINANCE32F_ARB 0x8818 #define GL_LUMINANCE_ALPHA32F_ARB 0x8819 #define GL_RGBA16F_ARB 0x881A #define GL_RGB16F_ARB 0x881B #define GL_ALPHA16F_ARB 0x881C #define GL_INTENSITY16F_ARB 0x881D #define GL_LUMINANCE16F_ARB 0x881E #define GL_LUMINANCE_ALPHA16F_ARB 0x881F #endif #ifndef GL_ARB_pixel_buffer_object #define GL_PIXEL_PACK_BUFFER_ARB 0x88EB #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC #define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED #define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF #endif #ifndef GL_EXT_abgr #define GL_ABGR_EXT 0x8000 #endif #ifndef GL_EXT_blend_color #define GL_CONSTANT_COLOR_EXT 0x8001 #define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 #define GL_CONSTANT_ALPHA_EXT 0x8003 #define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 #define GL_BLEND_COLOR_EXT 0x8005 #endif #ifndef GL_EXT_polygon_offset #define GL_POLYGON_OFFSET_EXT 0x8037 #define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 #define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 #endif #ifndef GL_EXT_texture #define GL_ALPHA4_EXT 0x803B #define GL_ALPHA8_EXT 0x803C #define GL_ALPHA12_EXT 0x803D #define GL_ALPHA16_EXT 0x803E #define GL_LUMINANCE4_EXT 0x803F #define GL_LUMINANCE8_EXT 0x8040 #define GL_LUMINANCE12_EXT 0x8041 #define GL_LUMINANCE16_EXT 0x8042 #define GL_LUMINANCE4_ALPHA4_EXT 0x8043 #define GL_LUMINANCE6_ALPHA2_EXT 0x8044 #define GL_LUMINANCE8_ALPHA8_EXT 0x8045 #define GL_LUMINANCE12_ALPHA4_EXT 0x8046 #define GL_LUMINANCE12_ALPHA12_EXT 0x8047 #define GL_LUMINANCE16_ALPHA16_EXT 0x8048 #define GL_INTENSITY_EXT 0x8049 #define GL_INTENSITY4_EXT 0x804A #define GL_INTENSITY8_EXT 0x804B #define GL_INTENSITY12_EXT 0x804C #define GL_INTENSITY16_EXT 0x804D #define GL_RGB2_EXT 0x804E #define GL_RGB4_EXT 0x804F #define GL_RGB5_EXT 0x8050 #define GL_RGB8_EXT 0x8051 #define GL_RGB10_EXT 0x8052 #define GL_RGB12_EXT 0x8053 #define GL_RGB16_EXT 0x8054 #define GL_RGBA2_EXT 0x8055 #define GL_RGBA4_EXT 0x8056 #define GL_RGB5_A1_EXT 0x8057 #define GL_RGBA8_EXT 0x8058 #define GL_RGB10_A2_EXT 0x8059 #define GL_RGBA12_EXT 0x805A #define GL_RGBA16_EXT 0x805B #define GL_TEXTURE_RED_SIZE_EXT 0x805C #define GL_TEXTURE_GREEN_SIZE_EXT 0x805D #define GL_TEXTURE_BLUE_SIZE_EXT 0x805E #define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F #define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 #define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 #define GL_REPLACE_EXT 0x8062 #define GL_PROXY_TEXTURE_1D_EXT 0x8063 #define GL_PROXY_TEXTURE_2D_EXT 0x8064 #define GL_TEXTURE_TOO_LARGE_EXT 0x8065 #endif #ifndef GL_EXT_texture3D #define GL_PACK_SKIP_IMAGES_EXT 0x806B #define GL_PACK_IMAGE_HEIGHT_EXT 0x806C #define GL_UNPACK_SKIP_IMAGES_EXT 0x806D #define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E #define GL_TEXTURE_3D_EXT 0x806F #define GL_PROXY_TEXTURE_3D_EXT 0x8070 #define GL_TEXTURE_DEPTH_EXT 0x8071 #define GL_TEXTURE_WRAP_R_EXT 0x8072 #define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 #endif #ifndef GL_SGIS_texture_filter4 #define GL_FILTER4_SGIS 0x8146 #define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 #endif #ifndef GL_EXT_subtexture #endif #ifndef GL_EXT_copy_texture #endif #ifndef GL_EXT_histogram #define GL_HISTOGRAM_EXT 0x8024 #define GL_PROXY_HISTOGRAM_EXT 0x8025 #define GL_HISTOGRAM_WIDTH_EXT 0x8026 #define GL_HISTOGRAM_FORMAT_EXT 0x8027 #define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 #define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 #define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A #define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B #define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C #define GL_HISTOGRAM_SINK_EXT 0x802D #define GL_MINMAX_EXT 0x802E #define GL_MINMAX_FORMAT_EXT 0x802F #define GL_MINMAX_SINK_EXT 0x8030 #define GL_TABLE_TOO_LARGE_EXT 0x8031 #endif #ifndef GL_EXT_convolution #define GL_CONVOLUTION_1D_EXT 0x8010 #define GL_CONVOLUTION_2D_EXT 0x8011 #define GL_SEPARABLE_2D_EXT 0x8012 #define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 #define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 #define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 #define GL_REDUCE_EXT 0x8016 #define GL_CONVOLUTION_FORMAT_EXT 0x8017 #define GL_CONVOLUTION_WIDTH_EXT 0x8018 #define GL_CONVOLUTION_HEIGHT_EXT 0x8019 #define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A #define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B #define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C #define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D #define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E #define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F #define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 #define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 #define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 #endif #ifndef GL_SGI_color_matrix #define GL_COLOR_MATRIX_SGI 0x80B1 #define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 #define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 #define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 #define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 #define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 #define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 #define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 #define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 #define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA #define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB #endif #ifndef GL_SGI_color_table #define GL_COLOR_TABLE_SGI 0x80D0 #define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 #define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 #define GL_PROXY_COLOR_TABLE_SGI 0x80D3 #define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 #define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 #define GL_COLOR_TABLE_SCALE_SGI 0x80D6 #define GL_COLOR_TABLE_BIAS_SGI 0x80D7 #define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 #define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 #define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA #define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB #define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC #define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD #define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE #define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF #endif #ifndef GL_SGIS_pixel_texture #define GL_PIXEL_TEXTURE_SGIS 0x8353 #define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 #define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 #define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 #endif #ifndef GL_SGIX_pixel_texture #define GL_PIXEL_TEX_GEN_SGIX 0x8139 #define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B #endif #ifndef GL_SGIS_texture4D #define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 #define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 #define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 #define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 #define GL_TEXTURE_4D_SGIS 0x8134 #define GL_PROXY_TEXTURE_4D_SGIS 0x8135 #define GL_TEXTURE_4DSIZE_SGIS 0x8136 #define GL_TEXTURE_WRAP_Q_SGIS 0x8137 #define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 #define GL_TEXTURE_4D_BINDING_SGIS 0x814F #endif #ifndef GL_SGI_texture_color_table #define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC #define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD #endif #ifndef GL_EXT_cmyka #define GL_CMYK_EXT 0x800C #define GL_CMYKA_EXT 0x800D #define GL_PACK_CMYK_HINT_EXT 0x800E #define GL_UNPACK_CMYK_HINT_EXT 0x800F #endif #ifndef GL_EXT_texture_object #define GL_TEXTURE_PRIORITY_EXT 0x8066 #define GL_TEXTURE_RESIDENT_EXT 0x8067 #define GL_TEXTURE_1D_BINDING_EXT 0x8068 #define GL_TEXTURE_2D_BINDING_EXT 0x8069 #define GL_TEXTURE_3D_BINDING_EXT 0x806A #endif #ifndef GL_SGIS_detail_texture #define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 #define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 #define GL_LINEAR_DETAIL_SGIS 0x8097 #define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 #define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 #define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A #define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B #define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C #endif #ifndef GL_SGIS_sharpen_texture #define GL_LINEAR_SHARPEN_SGIS 0x80AD #define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE #define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF #define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 #endif #ifndef GL_EXT_packed_pixels #define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 #define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 #define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 #define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 #define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 #endif #ifndef GL_SGIS_texture_lod #define GL_TEXTURE_MIN_LOD_SGIS 0x813A #define GL_TEXTURE_MAX_LOD_SGIS 0x813B #define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C #define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D #endif #ifndef GL_SGIS_multisample #define GL_MULTISAMPLE_SGIS 0x809D #define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E #define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F #define GL_SAMPLE_MASK_SGIS 0x80A0 #define GL_1PASS_SGIS 0x80A1 #define GL_2PASS_0_SGIS 0x80A2 #define GL_2PASS_1_SGIS 0x80A3 #define GL_4PASS_0_SGIS 0x80A4 #define GL_4PASS_1_SGIS 0x80A5 #define GL_4PASS_2_SGIS 0x80A6 #define GL_4PASS_3_SGIS 0x80A7 #define GL_SAMPLE_BUFFERS_SGIS 0x80A8 #define GL_SAMPLES_SGIS 0x80A9 #define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA #define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB #define GL_SAMPLE_PATTERN_SGIS 0x80AC #endif #ifndef GL_EXT_rescale_normal #define GL_RESCALE_NORMAL_EXT 0x803A #endif #ifndef GL_EXT_vertex_array #define GL_VERTEX_ARRAY_EXT 0x8074 #define GL_NORMAL_ARRAY_EXT 0x8075 #define GL_COLOR_ARRAY_EXT 0x8076 #define GL_INDEX_ARRAY_EXT 0x8077 #define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 #define GL_EDGE_FLAG_ARRAY_EXT 0x8079 #define GL_VERTEX_ARRAY_SIZE_EXT 0x807A #define GL_VERTEX_ARRAY_TYPE_EXT 0x807B #define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C #define GL_VERTEX_ARRAY_COUNT_EXT 0x807D #define GL_NORMAL_ARRAY_TYPE_EXT 0x807E #define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F #define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 #define GL_COLOR_ARRAY_SIZE_EXT 0x8081 #define GL_COLOR_ARRAY_TYPE_EXT 0x8082 #define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 #define GL_COLOR_ARRAY_COUNT_EXT 0x8084 #define GL_INDEX_ARRAY_TYPE_EXT 0x8085 #define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 #define GL_INDEX_ARRAY_COUNT_EXT 0x8087 #define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 #define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 #define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A #define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B #define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C #define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D #define GL_VERTEX_ARRAY_POINTER_EXT 0x808E #define GL_NORMAL_ARRAY_POINTER_EXT 0x808F #define GL_COLOR_ARRAY_POINTER_EXT 0x8090 #define GL_INDEX_ARRAY_POINTER_EXT 0x8091 #define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 #define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 #endif #ifndef GL_EXT_misc_attribute #endif #ifndef GL_SGIS_generate_mipmap #define GL_GENERATE_MIPMAP_SGIS 0x8191 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 #endif #ifndef GL_SGIX_clipmap #define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 #define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 #define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 #define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 #define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 #define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 #define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 #define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 #define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 #define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D #define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E #define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F #endif #ifndef GL_SGIX_shadow #define GL_TEXTURE_COMPARE_SGIX 0x819A #define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B #define GL_TEXTURE_LEQUAL_R_SGIX 0x819C #define GL_TEXTURE_GEQUAL_R_SGIX 0x819D #endif #ifndef GL_SGIS_texture_edge_clamp #define GL_CLAMP_TO_EDGE_SGIS 0x812F #endif #ifndef GL_SGIS_texture_border_clamp #define GL_CLAMP_TO_BORDER_SGIS 0x812D #endif #ifndef GL_EXT_blend_minmax #define GL_FUNC_ADD_EXT 0x8006 #define GL_MIN_EXT 0x8007 #define GL_MAX_EXT 0x8008 #define GL_BLEND_EQUATION_EXT 0x8009 #endif #ifndef GL_EXT_blend_subtract #define GL_FUNC_SUBTRACT_EXT 0x800A #define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B #endif #ifndef GL_EXT_blend_logic_op #endif #ifndef GL_SGIX_interlace #define GL_INTERLACE_SGIX 0x8094 #endif #ifndef GL_SGIX_pixel_tiles #define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E #define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F #define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 #define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 #define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 #define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 #define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 #define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 #endif #ifndef GL_SGIS_texture_select #define GL_DUAL_ALPHA4_SGIS 0x8110 #define GL_DUAL_ALPHA8_SGIS 0x8111 #define GL_DUAL_ALPHA12_SGIS 0x8112 #define GL_DUAL_ALPHA16_SGIS 0x8113 #define GL_DUAL_LUMINANCE4_SGIS 0x8114 #define GL_DUAL_LUMINANCE8_SGIS 0x8115 #define GL_DUAL_LUMINANCE12_SGIS 0x8116 #define GL_DUAL_LUMINANCE16_SGIS 0x8117 #define GL_DUAL_INTENSITY4_SGIS 0x8118 #define GL_DUAL_INTENSITY8_SGIS 0x8119 #define GL_DUAL_INTENSITY12_SGIS 0x811A #define GL_DUAL_INTENSITY16_SGIS 0x811B #define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C #define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D #define GL_QUAD_ALPHA4_SGIS 0x811E #define GL_QUAD_ALPHA8_SGIS 0x811F #define GL_QUAD_LUMINANCE4_SGIS 0x8120 #define GL_QUAD_LUMINANCE8_SGIS 0x8121 #define GL_QUAD_INTENSITY4_SGIS 0x8122 #define GL_QUAD_INTENSITY8_SGIS 0x8123 #define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 #define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 #endif #ifndef GL_SGIX_sprite #define GL_SPRITE_SGIX 0x8148 #define GL_SPRITE_MODE_SGIX 0x8149 #define GL_SPRITE_AXIS_SGIX 0x814A #define GL_SPRITE_TRANSLATION_SGIX 0x814B #define GL_SPRITE_AXIAL_SGIX 0x814C #define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D #define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E #endif #ifndef GL_SGIX_texture_multi_buffer #define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E #endif #ifndef GL_EXT_point_parameters #define GL_POINT_SIZE_MIN_EXT 0x8126 #define GL_POINT_SIZE_MAX_EXT 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 #define GL_DISTANCE_ATTENUATION_EXT 0x8129 #endif #ifndef GL_SGIS_point_parameters #define GL_POINT_SIZE_MIN_SGIS 0x8126 #define GL_POINT_SIZE_MAX_SGIS 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 #define GL_DISTANCE_ATTENUATION_SGIS 0x8129 #endif #ifndef GL_SGIX_instruments #define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 #define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 #endif #ifndef GL_SGIX_texture_scale_bias #define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 #define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A #define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B #define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C #endif #ifndef GL_SGIX_framezoom #define GL_FRAMEZOOM_SGIX 0x818B #define GL_FRAMEZOOM_FACTOR_SGIX 0x818C #define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D #endif #ifndef GL_SGIX_tag_sample_buffer #endif #ifndef GL_FfdMaskSGIX #define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 #define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 #endif #ifndef GL_SGIX_polynomial_ffd #define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 #define GL_TEXTURE_DEFORMATION_SGIX 0x8195 #define GL_DEFORMATIONS_MASK_SGIX 0x8196 #define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 #endif #ifndef GL_SGIX_reference_plane #define GL_REFERENCE_PLANE_SGIX 0x817D #define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E #endif #ifndef GL_SGIX_flush_raster #endif #ifndef GL_SGIX_depth_texture #define GL_DEPTH_COMPONENT16_SGIX 0x81A5 #define GL_DEPTH_COMPONENT24_SGIX 0x81A6 #define GL_DEPTH_COMPONENT32_SGIX 0x81A7 #endif #ifndef GL_SGIS_fog_function #define GL_FOG_FUNC_SGIS 0x812A #define GL_FOG_FUNC_POINTS_SGIS 0x812B #define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C #endif #ifndef GL_SGIX_fog_offset #define GL_FOG_OFFSET_SGIX 0x8198 #define GL_FOG_OFFSET_VALUE_SGIX 0x8199 #endif #ifndef GL_HP_image_transform #define GL_IMAGE_SCALE_X_HP 0x8155 #define GL_IMAGE_SCALE_Y_HP 0x8156 #define GL_IMAGE_TRANSLATE_X_HP 0x8157 #define GL_IMAGE_TRANSLATE_Y_HP 0x8158 #define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 #define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A #define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B #define GL_IMAGE_MAG_FILTER_HP 0x815C #define GL_IMAGE_MIN_FILTER_HP 0x815D #define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E #define GL_CUBIC_HP 0x815F #define GL_AVERAGE_HP 0x8160 #define GL_IMAGE_TRANSFORM_2D_HP 0x8161 #define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 #define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 #endif #ifndef GL_HP_convolution_border_modes #define GL_IGNORE_BORDER_HP 0x8150 #define GL_CONSTANT_BORDER_HP 0x8151 #define GL_REPLICATE_BORDER_HP 0x8153 #define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 #endif #ifndef GL_INGR_palette_buffer #endif #ifndef GL_SGIX_texture_add_env #define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE #endif #ifndef GL_EXT_color_subtable #endif #ifndef GL_PGI_vertex_hints #define GL_VERTEX_DATA_HINT_PGI 0x1A22A #define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B #define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C #define GL_MAX_VERTEX_HINT_PGI 0x1A22D #define GL_COLOR3_BIT_PGI 0x00010000 #define GL_COLOR4_BIT_PGI 0x00020000 #define GL_EDGEFLAG_BIT_PGI 0x00040000 #define GL_INDEX_BIT_PGI 0x00080000 #define GL_MAT_AMBIENT_BIT_PGI 0x00100000 #define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 #define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 #define GL_MAT_EMISSION_BIT_PGI 0x00800000 #define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 #define GL_MAT_SHININESS_BIT_PGI 0x02000000 #define GL_MAT_SPECULAR_BIT_PGI 0x04000000 #define GL_NORMAL_BIT_PGI 0x08000000 #define GL_TEXCOORD1_BIT_PGI 0x10000000 #define GL_TEXCOORD2_BIT_PGI 0x20000000 #define GL_TEXCOORD3_BIT_PGI 0x40000000 #define GL_TEXCOORD4_BIT_PGI 0x80000000 #define GL_VERTEX23_BIT_PGI 0x00000004 #define GL_VERTEX4_BIT_PGI 0x00000008 #endif #ifndef GL_PGI_misc_hints #define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 #define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD #define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE #define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 #define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 #define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 #define GL_ALWAYS_FAST_HINT_PGI 0x1A20C #define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D #define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E #define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F #define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 #define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 #define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 #define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 #define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 #define GL_FULL_STIPPLE_HINT_PGI 0x1A219 #define GL_CLIP_NEAR_HINT_PGI 0x1A220 #define GL_CLIP_FAR_HINT_PGI 0x1A221 #define GL_WIDE_LINE_HINT_PGI 0x1A222 #define GL_BACK_NORMALS_HINT_PGI 0x1A223 #endif #ifndef GL_EXT_paletted_texture #define GL_COLOR_INDEX1_EXT 0x80E2 #define GL_COLOR_INDEX2_EXT 0x80E3 #define GL_COLOR_INDEX4_EXT 0x80E4 #define GL_COLOR_INDEX8_EXT 0x80E5 #define GL_COLOR_INDEX12_EXT 0x80E6 #define GL_COLOR_INDEX16_EXT 0x80E7 #define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED #endif #ifndef GL_EXT_clip_volume_hint #define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 #endif #ifndef GL_SGIX_list_priority #define GL_LIST_PRIORITY_SGIX 0x8182 #endif #ifndef GL_SGIX_ir_instrument1 #define GL_IR_INSTRUMENT1_SGIX 0x817F #endif #ifndef GL_SGIX_calligraphic_fragment #define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 #endif #ifndef GL_SGIX_texture_lod_bias #define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E #define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F #define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 #endif #ifndef GL_SGIX_shadow_ambient #define GL_SHADOW_AMBIENT_SGIX 0x80BF #endif #ifndef GL_EXT_index_texture #endif #ifndef GL_EXT_index_material #define GL_INDEX_MATERIAL_EXT 0x81B8 #define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 #define GL_INDEX_MATERIAL_FACE_EXT 0x81BA #endif #ifndef GL_EXT_index_func #define GL_INDEX_TEST_EXT 0x81B5 #define GL_INDEX_TEST_FUNC_EXT 0x81B6 #define GL_INDEX_TEST_REF_EXT 0x81B7 #endif #ifndef GL_EXT_index_array_formats #define GL_IUI_V2F_EXT 0x81AD #define GL_IUI_V3F_EXT 0x81AE #define GL_IUI_N3F_V2F_EXT 0x81AF #define GL_IUI_N3F_V3F_EXT 0x81B0 #define GL_T2F_IUI_V2F_EXT 0x81B1 #define GL_T2F_IUI_V3F_EXT 0x81B2 #define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 #define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 #endif #ifndef GL_EXT_compiled_vertex_array #define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 #define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 #endif #ifndef GL_EXT_cull_vertex #define GL_CULL_VERTEX_EXT 0x81AA #define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB #define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC #endif #ifndef GL_SGIX_ycrcb #define GL_YCRCB_422_SGIX 0x81BB #define GL_YCRCB_444_SGIX 0x81BC #endif #ifndef GL_SGIX_fragment_lighting #define GL_FRAGMENT_LIGHTING_SGIX 0x8400 #define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 #define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 #define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 #define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 #define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 #define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 #define GL_LIGHT_ENV_MODE_SGIX 0x8407 #define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 #define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 #define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A #define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B #define GL_FRAGMENT_LIGHT0_SGIX 0x840C #define GL_FRAGMENT_LIGHT1_SGIX 0x840D #define GL_FRAGMENT_LIGHT2_SGIX 0x840E #define GL_FRAGMENT_LIGHT3_SGIX 0x840F #define GL_FRAGMENT_LIGHT4_SGIX 0x8410 #define GL_FRAGMENT_LIGHT5_SGIX 0x8411 #define GL_FRAGMENT_LIGHT6_SGIX 0x8412 #define GL_FRAGMENT_LIGHT7_SGIX 0x8413 #endif #ifndef GL_IBM_rasterpos_clip #define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 #endif #ifndef GL_HP_texture_lighting #define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 #define GL_TEXTURE_POST_SPECULAR_HP 0x8168 #define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 #endif #ifndef GL_EXT_draw_range_elements #define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 #define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 #endif #ifndef GL_WIN_phong_shading #define GL_PHONG_WIN 0x80EA #define GL_PHONG_HINT_WIN 0x80EB #endif #ifndef GL_WIN_specular_fog #define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC #endif #ifndef GL_EXT_light_texture #define GL_FRAGMENT_MATERIAL_EXT 0x8349 #define GL_FRAGMENT_NORMAL_EXT 0x834A #define GL_FRAGMENT_COLOR_EXT 0x834C #define GL_ATTENUATION_EXT 0x834D #define GL_SHADOW_ATTENUATION_EXT 0x834E #define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F #define GL_TEXTURE_LIGHT_EXT 0x8350 #define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 #define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 /* reuse GL_FRAGMENT_DEPTH_EXT */ #endif #ifndef GL_SGIX_blend_alpha_minmax #define GL_ALPHA_MIN_SGIX 0x8320 #define GL_ALPHA_MAX_SGIX 0x8321 #endif #ifndef GL_SGIX_impact_pixel_texture #define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184 #define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185 #define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186 #define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187 #define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188 #define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189 #define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A #endif #ifndef GL_EXT_bgra #define GL_BGR_EXT 0x80E0 #define GL_BGRA_EXT 0x80E1 #endif #ifndef GL_SGIX_async #define GL_ASYNC_MARKER_SGIX 0x8329 #endif #ifndef GL_SGIX_async_pixel #define GL_ASYNC_TEX_IMAGE_SGIX 0x835C #define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D #define GL_ASYNC_READ_PIXELS_SGIX 0x835E #define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F #define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 #define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 #endif #ifndef GL_SGIX_async_histogram #define GL_ASYNC_HISTOGRAM_SGIX 0x832C #define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D #endif #ifndef GL_INTEL_texture_scissor #endif #ifndef GL_INTEL_parallel_arrays #define GL_PARALLEL_ARRAYS_INTEL 0x83F4 #define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 #define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 #define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 #define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 #endif #ifndef GL_HP_occlusion_test #define GL_OCCLUSION_TEST_HP 0x8165 #define GL_OCCLUSION_TEST_RESULT_HP 0x8166 #endif #ifndef GL_EXT_pixel_transform #define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 #define GL_PIXEL_MAG_FILTER_EXT 0x8331 #define GL_PIXEL_MIN_FILTER_EXT 0x8332 #define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 #define GL_CUBIC_EXT 0x8334 #define GL_AVERAGE_EXT 0x8335 #define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 #define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 #define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 #endif #ifndef GL_EXT_pixel_transform_color_table #endif #ifndef GL_EXT_shared_texture_palette #define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB #endif #ifndef GL_EXT_separate_specular_color #define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 #define GL_SINGLE_COLOR_EXT 0x81F9 #define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA #endif #ifndef GL_EXT_secondary_color #define GL_COLOR_SUM_EXT 0x8458 #define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 #define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A #define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B #define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C #define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D #define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E #endif #ifndef GL_EXT_texture_perturb_normal #define GL_PERTURB_EXT 0x85AE #define GL_TEXTURE_NORMAL_EXT 0x85AF #endif #ifndef GL_EXT_multi_draw_arrays #endif #ifndef GL_EXT_fog_coord #define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 #define GL_FOG_COORDINATE_EXT 0x8451 #define GL_FRAGMENT_DEPTH_EXT 0x8452 #define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 #define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 #define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 #define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 #define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 #endif #ifndef GL_REND_screen_coordinates #define GL_SCREEN_COORDINATES_REND 0x8490 #define GL_INVERTED_SCREEN_W_REND 0x8491 #endif #ifndef GL_EXT_coordinate_frame #define GL_TANGENT_ARRAY_EXT 0x8439 #define GL_BINORMAL_ARRAY_EXT 0x843A #define GL_CURRENT_TANGENT_EXT 0x843B #define GL_CURRENT_BINORMAL_EXT 0x843C #define GL_TANGENT_ARRAY_TYPE_EXT 0x843E #define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F #define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 #define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 #define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 #define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 #define GL_MAP1_TANGENT_EXT 0x8444 #define GL_MAP2_TANGENT_EXT 0x8445 #define GL_MAP1_BINORMAL_EXT 0x8446 #define GL_MAP2_BINORMAL_EXT 0x8447 #endif #ifndef GL_EXT_texture_env_combine #define GL_COMBINE_EXT 0x8570 #define GL_COMBINE_RGB_EXT 0x8571 #define GL_COMBINE_ALPHA_EXT 0x8572 #define GL_RGB_SCALE_EXT 0x8573 #define GL_ADD_SIGNED_EXT 0x8574 #define GL_INTERPOLATE_EXT 0x8575 #define GL_CONSTANT_EXT 0x8576 #define GL_PRIMARY_COLOR_EXT 0x8577 #define GL_PREVIOUS_EXT 0x8578 #define GL_SOURCE0_RGB_EXT 0x8580 #define GL_SOURCE1_RGB_EXT 0x8581 #define GL_SOURCE2_RGB_EXT 0x8582 #define GL_SOURCE0_ALPHA_EXT 0x8588 #define GL_SOURCE1_ALPHA_EXT 0x8589 #define GL_SOURCE2_ALPHA_EXT 0x858A #define GL_OPERAND0_RGB_EXT 0x8590 #define GL_OPERAND1_RGB_EXT 0x8591 #define GL_OPERAND2_RGB_EXT 0x8592 #define GL_OPERAND0_ALPHA_EXT 0x8598 #define GL_OPERAND1_ALPHA_EXT 0x8599 #define GL_OPERAND2_ALPHA_EXT 0x859A #endif #ifndef GL_APPLE_specular_vector #define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 #endif #ifndef GL_APPLE_transform_hint #define GL_TRANSFORM_HINT_APPLE 0x85B1 #endif #ifndef GL_SGIX_fog_scale #define GL_FOG_SCALE_SGIX 0x81FC #define GL_FOG_SCALE_VALUE_SGIX 0x81FD #endif #ifndef GL_SUNX_constant_data #define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 #define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 #endif #ifndef GL_SUN_global_alpha #define GL_GLOBAL_ALPHA_SUN 0x81D9 #define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA #endif #ifndef GL_SUN_triangle_list #define GL_RESTART_SUN 0x0001 #define GL_REPLACE_MIDDLE_SUN 0x0002 #define GL_REPLACE_OLDEST_SUN 0x0003 #define GL_TRIANGLE_LIST_SUN 0x81D7 #define GL_REPLACEMENT_CODE_SUN 0x81D8 #define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 #define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 #define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 #define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 #define GL_R1UI_V3F_SUN 0x85C4 #define GL_R1UI_C4UB_V3F_SUN 0x85C5 #define GL_R1UI_C3F_V3F_SUN 0x85C6 #define GL_R1UI_N3F_V3F_SUN 0x85C7 #define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 #define GL_R1UI_T2F_V3F_SUN 0x85C9 #define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA #define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB #endif #ifndef GL_SUN_vertex #endif #ifndef GL_EXT_blend_func_separate #define GL_BLEND_DST_RGB_EXT 0x80C8 #define GL_BLEND_SRC_RGB_EXT 0x80C9 #define GL_BLEND_DST_ALPHA_EXT 0x80CA #define GL_BLEND_SRC_ALPHA_EXT 0x80CB #endif #ifndef GL_INGR_color_clamp #define GL_RED_MIN_CLAMP_INGR 0x8560 #define GL_GREEN_MIN_CLAMP_INGR 0x8561 #define GL_BLUE_MIN_CLAMP_INGR 0x8562 #define GL_ALPHA_MIN_CLAMP_INGR 0x8563 #define GL_RED_MAX_CLAMP_INGR 0x8564 #define GL_GREEN_MAX_CLAMP_INGR 0x8565 #define GL_BLUE_MAX_CLAMP_INGR 0x8566 #define GL_ALPHA_MAX_CLAMP_INGR 0x8567 #endif #ifndef GL_INGR_interlace_read #define GL_INTERLACE_READ_INGR 0x8568 #endif #ifndef GL_EXT_stencil_wrap #define GL_INCR_WRAP_EXT 0x8507 #define GL_DECR_WRAP_EXT 0x8508 #endif #ifndef GL_EXT_422_pixels #define GL_422_EXT 0x80CC #define GL_422_REV_EXT 0x80CD #define GL_422_AVERAGE_EXT 0x80CE #define GL_422_REV_AVERAGE_EXT 0x80CF #endif #ifndef GL_NV_texgen_reflection #define GL_NORMAL_MAP_NV 0x8511 #define GL_REFLECTION_MAP_NV 0x8512 #endif #ifndef GL_EXT_texture_cube_map #define GL_NORMAL_MAP_EXT 0x8511 #define GL_REFLECTION_MAP_EXT 0x8512 #define GL_TEXTURE_CUBE_MAP_EXT 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C #endif #ifndef GL_SUN_convolution_border_modes #define GL_WRAP_BORDER_SUN 0x81D4 #endif #ifndef GL_EXT_texture_env_add #endif #ifndef GL_EXT_texture_lod_bias #define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD #define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 #define GL_TEXTURE_LOD_BIAS_EXT 0x8501 #endif #ifndef GL_EXT_texture_filter_anisotropic #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF #endif #ifndef GL_EXT_vertex_weighting #define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH #define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 #define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX #define GL_MODELVIEW1_MATRIX_EXT 0x8506 #define GL_VERTEX_WEIGHTING_EXT 0x8509 #define GL_MODELVIEW0_EXT GL_MODELVIEW #define GL_MODELVIEW1_EXT 0x850A #define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B #define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C #define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D #define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E #define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F #define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 #endif #ifndef GL_NV_light_max_exponent #define GL_MAX_SHININESS_NV 0x8504 #define GL_MAX_SPOT_EXPONENT_NV 0x8505 #endif #ifndef GL_NV_vertex_array_range #define GL_VERTEX_ARRAY_RANGE_NV 0x851D #define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E #define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F #define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 #define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 #endif #ifndef GL_NV_register_combiners #define GL_REGISTER_COMBINERS_NV 0x8522 #define GL_VARIABLE_A_NV 0x8523 #define GL_VARIABLE_B_NV 0x8524 #define GL_VARIABLE_C_NV 0x8525 #define GL_VARIABLE_D_NV 0x8526 #define GL_VARIABLE_E_NV 0x8527 #define GL_VARIABLE_F_NV 0x8528 #define GL_VARIABLE_G_NV 0x8529 #define GL_CONSTANT_COLOR0_NV 0x852A #define GL_CONSTANT_COLOR1_NV 0x852B #define GL_PRIMARY_COLOR_NV 0x852C #define GL_SECONDARY_COLOR_NV 0x852D #define GL_SPARE0_NV 0x852E #define GL_SPARE1_NV 0x852F #define GL_DISCARD_NV 0x8530 #define GL_E_TIMES_F_NV 0x8531 #define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 #define GL_UNSIGNED_IDENTITY_NV 0x8536 #define GL_UNSIGNED_INVERT_NV 0x8537 #define GL_EXPAND_NORMAL_NV 0x8538 #define GL_EXPAND_NEGATE_NV 0x8539 #define GL_HALF_BIAS_NORMAL_NV 0x853A #define GL_HALF_BIAS_NEGATE_NV 0x853B #define GL_SIGNED_IDENTITY_NV 0x853C #define GL_SIGNED_NEGATE_NV 0x853D #define GL_SCALE_BY_TWO_NV 0x853E #define GL_SCALE_BY_FOUR_NV 0x853F #define GL_SCALE_BY_ONE_HALF_NV 0x8540 #define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 #define GL_COMBINER_INPUT_NV 0x8542 #define GL_COMBINER_MAPPING_NV 0x8543 #define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 #define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 #define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 #define GL_COMBINER_MUX_SUM_NV 0x8547 #define GL_COMBINER_SCALE_NV 0x8548 #define GL_COMBINER_BIAS_NV 0x8549 #define GL_COMBINER_AB_OUTPUT_NV 0x854A #define GL_COMBINER_CD_OUTPUT_NV 0x854B #define GL_COMBINER_SUM_OUTPUT_NV 0x854C #define GL_MAX_GENERAL_COMBINERS_NV 0x854D #define GL_NUM_GENERAL_COMBINERS_NV 0x854E #define GL_COLOR_SUM_CLAMP_NV 0x854F #define GL_COMBINER0_NV 0x8550 #define GL_COMBINER1_NV 0x8551 #define GL_COMBINER2_NV 0x8552 #define GL_COMBINER3_NV 0x8553 #define GL_COMBINER4_NV 0x8554 #define GL_COMBINER5_NV 0x8555 #define GL_COMBINER6_NV 0x8556 #define GL_COMBINER7_NV 0x8557 /* reuse GL_TEXTURE0_ARB */ /* reuse GL_TEXTURE1_ARB */ /* reuse GL_ZERO */ /* reuse GL_NONE */ /* reuse GL_FOG */ #endif #ifndef GL_NV_fog_distance #define GL_FOG_DISTANCE_MODE_NV 0x855A #define GL_EYE_RADIAL_NV 0x855B #define GL_EYE_PLANE_ABSOLUTE_NV 0x855C /* reuse GL_EYE_PLANE */ #endif #ifndef GL_NV_texgen_emboss #define GL_EMBOSS_LIGHT_NV 0x855D #define GL_EMBOSS_CONSTANT_NV 0x855E #define GL_EMBOSS_MAP_NV 0x855F #endif #ifndef GL_NV_blend_square #endif #ifndef GL_NV_texture_env_combine4 #define GL_COMBINE4_NV 0x8503 #define GL_SOURCE3_RGB_NV 0x8583 #define GL_SOURCE3_ALPHA_NV 0x858B #define GL_OPERAND3_RGB_NV 0x8593 #define GL_OPERAND3_ALPHA_NV 0x859B #endif #ifndef GL_MESA_resize_buffers #endif #ifndef GL_MESA_window_pos #endif #ifndef GL_EXT_texture_compression_s3tc #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 #endif #ifndef GL_IBM_cull_vertex #define GL_CULL_VERTEX_IBM 103050 #endif #ifndef GL_IBM_multimode_draw_arrays #endif #ifndef GL_IBM_vertex_array_lists #define GL_VERTEX_ARRAY_LIST_IBM 103070 #define GL_NORMAL_ARRAY_LIST_IBM 103071 #define GL_COLOR_ARRAY_LIST_IBM 103072 #define GL_INDEX_ARRAY_LIST_IBM 103073 #define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 #define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 #define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 #define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 #define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 #define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 #define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 #define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 #define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 #define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 #define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 #define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 #endif #ifndef GL_SGIX_subsample #define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 #define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 #define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 #define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 #define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 #endif #ifndef GL_SGIX_ycrcb_subsample #endif #ifndef GL_SGIX_ycrcba #define GL_YCRCB_SGIX 0x8318 #define GL_YCRCBA_SGIX 0x8319 #endif #ifndef GL_SGI_depth_pass_instrument #define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 #define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 #define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 #endif #ifndef GL_3DFX_texture_compression_FXT1 #define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 #define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 #endif #ifndef GL_3DFX_multisample #define GL_MULTISAMPLE_3DFX 0x86B2 #define GL_SAMPLE_BUFFERS_3DFX 0x86B3 #define GL_SAMPLES_3DFX 0x86B4 #define GL_MULTISAMPLE_BIT_3DFX 0x20000000 #endif #ifndef GL_3DFX_tbuffer #endif #ifndef GL_EXT_multisample #define GL_MULTISAMPLE_EXT 0x809D #define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E #define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F #define GL_SAMPLE_MASK_EXT 0x80A0 #define GL_1PASS_EXT 0x80A1 #define GL_2PASS_0_EXT 0x80A2 #define GL_2PASS_1_EXT 0x80A3 #define GL_4PASS_0_EXT 0x80A4 #define GL_4PASS_1_EXT 0x80A5 #define GL_4PASS_2_EXT 0x80A6 #define GL_4PASS_3_EXT 0x80A7 #define GL_SAMPLE_BUFFERS_EXT 0x80A8 #define GL_SAMPLES_EXT 0x80A9 #define GL_SAMPLE_MASK_VALUE_EXT 0x80AA #define GL_SAMPLE_MASK_INVERT_EXT 0x80AB #define GL_SAMPLE_PATTERN_EXT 0x80AC #define GL_MULTISAMPLE_BIT_EXT 0x20000000 #endif #ifndef GL_SGIX_vertex_preclip #define GL_VERTEX_PRECLIP_SGIX 0x83EE #define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF #endif #ifndef GL_SGIX_convolution_accuracy #define GL_CONVOLUTION_HINT_SGIX 0x8316 #endif #ifndef GL_SGIX_resample #define GL_PACK_RESAMPLE_SGIX 0x842C #define GL_UNPACK_RESAMPLE_SGIX 0x842D #define GL_RESAMPLE_REPLICATE_SGIX 0x842E #define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F #define GL_RESAMPLE_DECIMATE_SGIX 0x8430 #endif #ifndef GL_SGIS_point_line_texgen #define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 #define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 #define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 #define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 #define GL_EYE_POINT_SGIS 0x81F4 #define GL_OBJECT_POINT_SGIS 0x81F5 #define GL_EYE_LINE_SGIS 0x81F6 #define GL_OBJECT_LINE_SGIS 0x81F7 #endif #ifndef GL_SGIS_texture_color_mask #define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF #endif #ifndef GL_EXT_texture_env_dot3 #define GL_DOT3_RGB_EXT 0x8740 #define GL_DOT3_RGBA_EXT 0x8741 #endif #ifndef GL_ATI_texture_mirror_once #define GL_MIRROR_CLAMP_ATI 0x8742 #define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 #endif #ifndef GL_NV_fence #define GL_ALL_COMPLETED_NV 0x84F2 #define GL_FENCE_STATUS_NV 0x84F3 #define GL_FENCE_CONDITION_NV 0x84F4 #endif #ifndef GL_IBM_texture_mirrored_repeat #define GL_MIRRORED_REPEAT_IBM 0x8370 #endif #ifndef GL_NV_evaluators #define GL_EVAL_2D_NV 0x86C0 #define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 #define GL_MAP_TESSELLATION_NV 0x86C2 #define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 #define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 #define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 #define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 #define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 #define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 #define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 #define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA #define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB #define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC #define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD #define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE #define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF #define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 #define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 #define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 #define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 #define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 #define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 #define GL_MAX_MAP_TESSELLATION_NV 0x86D6 #define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 #endif #ifndef GL_NV_packed_depth_stencil #define GL_DEPTH_STENCIL_NV 0x84F9 #define GL_UNSIGNED_INT_24_8_NV 0x84FA #endif #ifndef GL_NV_register_combiners2 #define GL_PER_STAGE_CONSTANTS_NV 0x8535 #endif #ifndef GL_NV_texture_compression_vtc #endif #ifndef GL_NV_texture_rectangle #define GL_TEXTURE_RECTANGLE_NV 0x84F5 #define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 #define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 #define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 #endif #ifndef GL_NV_texture_shader #define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C #define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D #define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E #define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 #define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA #define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB #define GL_DSDT_MAG_INTENSITY_NV 0x86DC #define GL_SHADER_CONSISTENT_NV 0x86DD #define GL_TEXTURE_SHADER_NV 0x86DE #define GL_SHADER_OPERATION_NV 0x86DF #define GL_CULL_MODES_NV 0x86E0 #define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 #define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 #define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 #define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV #define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV #define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV #define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 #define GL_CONST_EYE_NV 0x86E5 #define GL_PASS_THROUGH_NV 0x86E6 #define GL_CULL_FRAGMENT_NV 0x86E7 #define GL_OFFSET_TEXTURE_2D_NV 0x86E8 #define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 #define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA #define GL_DOT_PRODUCT_NV 0x86EC #define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED #define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE #define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 #define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 #define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 #define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 #define GL_HILO_NV 0x86F4 #define GL_DSDT_NV 0x86F5 #define GL_DSDT_MAG_NV 0x86F6 #define GL_DSDT_MAG_VIB_NV 0x86F7 #define GL_HILO16_NV 0x86F8 #define GL_SIGNED_HILO_NV 0x86F9 #define GL_SIGNED_HILO16_NV 0x86FA #define GL_SIGNED_RGBA_NV 0x86FB #define GL_SIGNED_RGBA8_NV 0x86FC #define GL_SIGNED_RGB_NV 0x86FE #define GL_SIGNED_RGB8_NV 0x86FF #define GL_SIGNED_LUMINANCE_NV 0x8701 #define GL_SIGNED_LUMINANCE8_NV 0x8702 #define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 #define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 #define GL_SIGNED_ALPHA_NV 0x8705 #define GL_SIGNED_ALPHA8_NV 0x8706 #define GL_SIGNED_INTENSITY_NV 0x8707 #define GL_SIGNED_INTENSITY8_NV 0x8708 #define GL_DSDT8_NV 0x8709 #define GL_DSDT8_MAG8_NV 0x870A #define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B #define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C #define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D #define GL_HI_SCALE_NV 0x870E #define GL_LO_SCALE_NV 0x870F #define GL_DS_SCALE_NV 0x8710 #define GL_DT_SCALE_NV 0x8711 #define GL_MAGNITUDE_SCALE_NV 0x8712 #define GL_VIBRANCE_SCALE_NV 0x8713 #define GL_HI_BIAS_NV 0x8714 #define GL_LO_BIAS_NV 0x8715 #define GL_DS_BIAS_NV 0x8716 #define GL_DT_BIAS_NV 0x8717 #define GL_MAGNITUDE_BIAS_NV 0x8718 #define GL_VIBRANCE_BIAS_NV 0x8719 #define GL_TEXTURE_BORDER_VALUES_NV 0x871A #define GL_TEXTURE_HI_SIZE_NV 0x871B #define GL_TEXTURE_LO_SIZE_NV 0x871C #define GL_TEXTURE_DS_SIZE_NV 0x871D #define GL_TEXTURE_DT_SIZE_NV 0x871E #define GL_TEXTURE_MAG_SIZE_NV 0x871F #endif #ifndef GL_NV_texture_shader2 #define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF #endif #ifndef GL_NV_vertex_array_range2 #define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 #endif #ifndef GL_NV_vertex_program #define GL_VERTEX_PROGRAM_NV 0x8620 #define GL_VERTEX_STATE_PROGRAM_NV 0x8621 #define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 #define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 #define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 #define GL_CURRENT_ATTRIB_NV 0x8626 #define GL_PROGRAM_LENGTH_NV 0x8627 #define GL_PROGRAM_STRING_NV 0x8628 #define GL_MODELVIEW_PROJECTION_NV 0x8629 #define GL_IDENTITY_NV 0x862A #define GL_INVERSE_NV 0x862B #define GL_TRANSPOSE_NV 0x862C #define GL_INVERSE_TRANSPOSE_NV 0x862D #define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E #define GL_MAX_TRACK_MATRICES_NV 0x862F #define GL_MATRIX0_NV 0x8630 #define GL_MATRIX1_NV 0x8631 #define GL_MATRIX2_NV 0x8632 #define GL_MATRIX3_NV 0x8633 #define GL_MATRIX4_NV 0x8634 #define GL_MATRIX5_NV 0x8635 #define GL_MATRIX6_NV 0x8636 #define GL_MATRIX7_NV 0x8637 #define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 #define GL_CURRENT_MATRIX_NV 0x8641 #define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 #define GL_PROGRAM_PARAMETER_NV 0x8644 #define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 #define GL_PROGRAM_TARGET_NV 0x8646 #define GL_PROGRAM_RESIDENT_NV 0x8647 #define GL_TRACK_MATRIX_NV 0x8648 #define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 #define GL_VERTEX_PROGRAM_BINDING_NV 0x864A #define GL_PROGRAM_ERROR_POSITION_NV 0x864B #define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 #define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 #define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 #define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 #define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 #define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 #define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 #define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 #define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 #define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 #define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A #define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B #define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C #define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D #define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E #define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F #define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 #define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 #define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 #define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 #define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 #define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 #define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 #define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 #define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 #define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 #define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A #define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B #define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C #define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D #define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E #define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F #define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 #define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 #define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 #define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 #define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 #define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 #define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 #define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 #define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 #define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 #define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A #define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B #define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C #define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D #define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E #define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F #endif #ifndef GL_SGIX_texture_coordinate_clamp #define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 #define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A #define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B #endif #ifndef GL_SGIX_scalebias_hint #define GL_SCALEBIAS_HINT_SGIX 0x8322 #endif #ifndef GL_OML_interlace #define GL_INTERLACE_OML 0x8980 #define GL_INTERLACE_READ_OML 0x8981 #endif #ifndef GL_OML_subsample #define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 #define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 #endif #ifndef GL_OML_resample #define GL_PACK_RESAMPLE_OML 0x8984 #define GL_UNPACK_RESAMPLE_OML 0x8985 #define GL_RESAMPLE_REPLICATE_OML 0x8986 #define GL_RESAMPLE_ZERO_FILL_OML 0x8987 #define GL_RESAMPLE_AVERAGE_OML 0x8988 #define GL_RESAMPLE_DECIMATE_OML 0x8989 #endif #ifndef GL_NV_copy_depth_to_color #define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E #define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F #endif #ifndef GL_ATI_envmap_bumpmap #define GL_BUMP_ROT_MATRIX_ATI 0x8775 #define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 #define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 #define GL_BUMP_TEX_UNITS_ATI 0x8778 #define GL_DUDV_ATI 0x8779 #define GL_DU8DV8_ATI 0x877A #define GL_BUMP_ENVMAP_ATI 0x877B #define GL_BUMP_TARGET_ATI 0x877C #endif #ifndef GL_ATI_fragment_shader #define GL_FRAGMENT_SHADER_ATI 0x8920 #define GL_REG_0_ATI 0x8921 #define GL_REG_1_ATI 0x8922 #define GL_REG_2_ATI 0x8923 #define GL_REG_3_ATI 0x8924 #define GL_REG_4_ATI 0x8925 #define GL_REG_5_ATI 0x8926 #define GL_REG_6_ATI 0x8927 #define GL_REG_7_ATI 0x8928 #define GL_REG_8_ATI 0x8929 #define GL_REG_9_ATI 0x892A #define GL_REG_10_ATI 0x892B #define GL_REG_11_ATI 0x892C #define GL_REG_12_ATI 0x892D #define GL_REG_13_ATI 0x892E #define GL_REG_14_ATI 0x892F #define GL_REG_15_ATI 0x8930 #define GL_REG_16_ATI 0x8931 #define GL_REG_17_ATI 0x8932 #define GL_REG_18_ATI 0x8933 #define GL_REG_19_ATI 0x8934 #define GL_REG_20_ATI 0x8935 #define GL_REG_21_ATI 0x8936 #define GL_REG_22_ATI 0x8937 #define GL_REG_23_ATI 0x8938 #define GL_REG_24_ATI 0x8939 #define GL_REG_25_ATI 0x893A #define GL_REG_26_ATI 0x893B #define GL_REG_27_ATI 0x893C #define GL_REG_28_ATI 0x893D #define GL_REG_29_ATI 0x893E #define GL_REG_30_ATI 0x893F #define GL_REG_31_ATI 0x8940 #define GL_CON_0_ATI 0x8941 #define GL_CON_1_ATI 0x8942 #define GL_CON_2_ATI 0x8943 #define GL_CON_3_ATI 0x8944 #define GL_CON_4_ATI 0x8945 #define GL_CON_5_ATI 0x8946 #define GL_CON_6_ATI 0x8947 #define GL_CON_7_ATI 0x8948 #define GL_CON_8_ATI 0x8949 #define GL_CON_9_ATI 0x894A #define GL_CON_10_ATI 0x894B #define GL_CON_11_ATI 0x894C #define GL_CON_12_ATI 0x894D #define GL_CON_13_ATI 0x894E #define GL_CON_14_ATI 0x894F #define GL_CON_15_ATI 0x8950 #define GL_CON_16_ATI 0x8951 #define GL_CON_17_ATI 0x8952 #define GL_CON_18_ATI 0x8953 #define GL_CON_19_ATI 0x8954 #define GL_CON_20_ATI 0x8955 #define GL_CON_21_ATI 0x8956 #define GL_CON_22_ATI 0x8957 #define GL_CON_23_ATI 0x8958 #define GL_CON_24_ATI 0x8959 #define GL_CON_25_ATI 0x895A #define GL_CON_26_ATI 0x895B #define GL_CON_27_ATI 0x895C #define GL_CON_28_ATI 0x895D #define GL_CON_29_ATI 0x895E #define GL_CON_30_ATI 0x895F #define GL_CON_31_ATI 0x8960 #define GL_MOV_ATI 0x8961 #define GL_ADD_ATI 0x8963 #define GL_MUL_ATI 0x8964 #define GL_SUB_ATI 0x8965 #define GL_DOT3_ATI 0x8966 #define GL_DOT4_ATI 0x8967 #define GL_MAD_ATI 0x8968 #define GL_LERP_ATI 0x8969 #define GL_CND_ATI 0x896A #define GL_CND0_ATI 0x896B #define GL_DOT2_ADD_ATI 0x896C #define GL_SECONDARY_INTERPOLATOR_ATI 0x896D #define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E #define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F #define GL_NUM_PASSES_ATI 0x8970 #define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 #define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 #define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 #define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 #define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 #define GL_SWIZZLE_STR_ATI 0x8976 #define GL_SWIZZLE_STQ_ATI 0x8977 #define GL_SWIZZLE_STR_DR_ATI 0x8978 #define GL_SWIZZLE_STQ_DQ_ATI 0x8979 #define GL_SWIZZLE_STRQ_ATI 0x897A #define GL_SWIZZLE_STRQ_DQ_ATI 0x897B #define GL_RED_BIT_ATI 0x00000001 #define GL_GREEN_BIT_ATI 0x00000002 #define GL_BLUE_BIT_ATI 0x00000004 #define GL_2X_BIT_ATI 0x00000001 #define GL_4X_BIT_ATI 0x00000002 #define GL_8X_BIT_ATI 0x00000004 #define GL_HALF_BIT_ATI 0x00000008 #define GL_QUARTER_BIT_ATI 0x00000010 #define GL_EIGHTH_BIT_ATI 0x00000020 #define GL_SATURATE_BIT_ATI 0x00000040 #define GL_COMP_BIT_ATI 0x00000002 #define GL_NEGATE_BIT_ATI 0x00000004 #define GL_BIAS_BIT_ATI 0x00000008 #endif #ifndef GL_ATI_pn_triangles #define GL_PN_TRIANGLES_ATI 0x87F0 #define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 #define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 #define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 #define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 #define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 #define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 #define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 #define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 #endif #ifndef GL_ATI_vertex_array_object #define GL_STATIC_ATI 0x8760 #define GL_DYNAMIC_ATI 0x8761 #define GL_PRESERVE_ATI 0x8762 #define GL_DISCARD_ATI 0x8763 #define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 #define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 #define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 #define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 #endif #ifndef GL_EXT_vertex_shader #define GL_VERTEX_SHADER_EXT 0x8780 #define GL_VERTEX_SHADER_BINDING_EXT 0x8781 #define GL_OP_INDEX_EXT 0x8782 #define GL_OP_NEGATE_EXT 0x8783 #define GL_OP_DOT3_EXT 0x8784 #define GL_OP_DOT4_EXT 0x8785 #define GL_OP_MUL_EXT 0x8786 #define GL_OP_ADD_EXT 0x8787 #define GL_OP_MADD_EXT 0x8788 #define GL_OP_FRAC_EXT 0x8789 #define GL_OP_MAX_EXT 0x878A #define GL_OP_MIN_EXT 0x878B #define GL_OP_SET_GE_EXT 0x878C #define GL_OP_SET_LT_EXT 0x878D #define GL_OP_CLAMP_EXT 0x878E #define GL_OP_FLOOR_EXT 0x878F #define GL_OP_ROUND_EXT 0x8790 #define GL_OP_EXP_BASE_2_EXT 0x8791 #define GL_OP_LOG_BASE_2_EXT 0x8792 #define GL_OP_POWER_EXT 0x8793 #define GL_OP_RECIP_EXT 0x8794 #define GL_OP_RECIP_SQRT_EXT 0x8795 #define GL_OP_SUB_EXT 0x8796 #define GL_OP_CROSS_PRODUCT_EXT 0x8797 #define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 #define GL_OP_MOV_EXT 0x8799 #define GL_OUTPUT_VERTEX_EXT 0x879A #define GL_OUTPUT_COLOR0_EXT 0x879B #define GL_OUTPUT_COLOR1_EXT 0x879C #define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D #define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E #define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F #define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 #define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 #define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 #define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 #define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 #define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 #define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 #define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 #define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 #define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 #define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA #define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB #define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC #define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD #define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE #define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF #define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 #define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 #define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 #define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 #define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 #define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 #define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 #define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 #define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 #define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 #define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA #define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB #define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC #define GL_OUTPUT_FOG_EXT 0x87BD #define GL_SCALAR_EXT 0x87BE #define GL_VECTOR_EXT 0x87BF #define GL_MATRIX_EXT 0x87C0 #define GL_VARIANT_EXT 0x87C1 #define GL_INVARIANT_EXT 0x87C2 #define GL_LOCAL_CONSTANT_EXT 0x87C3 #define GL_LOCAL_EXT 0x87C4 #define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 #define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 #define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 #define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 #define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 #define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA #define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB #define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC #define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD #define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE #define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF #define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 #define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 #define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 #define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 #define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 #define GL_X_EXT 0x87D5 #define GL_Y_EXT 0x87D6 #define GL_Z_EXT 0x87D7 #define GL_W_EXT 0x87D8 #define GL_NEGATIVE_X_EXT 0x87D9 #define GL_NEGATIVE_Y_EXT 0x87DA #define GL_NEGATIVE_Z_EXT 0x87DB #define GL_NEGATIVE_W_EXT 0x87DC #define GL_ZERO_EXT 0x87DD #define GL_ONE_EXT 0x87DE #define GL_NEGATIVE_ONE_EXT 0x87DF #define GL_NORMALIZED_RANGE_EXT 0x87E0 #define GL_FULL_RANGE_EXT 0x87E1 #define GL_CURRENT_VERTEX_EXT 0x87E2 #define GL_MVP_MATRIX_EXT 0x87E3 #define GL_VARIANT_VALUE_EXT 0x87E4 #define GL_VARIANT_DATATYPE_EXT 0x87E5 #define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 #define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 #define GL_VARIANT_ARRAY_EXT 0x87E8 #define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 #define GL_INVARIANT_VALUE_EXT 0x87EA #define GL_INVARIANT_DATATYPE_EXT 0x87EB #define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC #define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED #endif #ifndef GL_ATI_vertex_streams #define GL_MAX_VERTEX_STREAMS_ATI 0x876B #define GL_VERTEX_STREAM0_ATI 0x876C #define GL_VERTEX_STREAM1_ATI 0x876D #define GL_VERTEX_STREAM2_ATI 0x876E #define GL_VERTEX_STREAM3_ATI 0x876F #define GL_VERTEX_STREAM4_ATI 0x8770 #define GL_VERTEX_STREAM5_ATI 0x8771 #define GL_VERTEX_STREAM6_ATI 0x8772 #define GL_VERTEX_STREAM7_ATI 0x8773 #define GL_VERTEX_SOURCE_ATI 0x8774 #endif #ifndef GL_ATI_element_array #define GL_ELEMENT_ARRAY_ATI 0x8768 #define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 #define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A #endif #ifndef GL_SUN_mesh_array #define GL_QUAD_MESH_SUN 0x8614 #define GL_TRIANGLE_MESH_SUN 0x8615 #endif #ifndef GL_SUN_slice_accum #define GL_SLICE_ACCUM_SUN 0x85CC #endif #ifndef GL_NV_multisample_filter_hint #define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 #endif #ifndef GL_NV_depth_clamp #define GL_DEPTH_CLAMP_NV 0x864F #endif #ifndef GL_NV_occlusion_query #define GL_PIXEL_COUNTER_BITS_NV 0x8864 #define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 #define GL_PIXEL_COUNT_NV 0x8866 #define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 #endif #ifndef GL_NV_point_sprite #define GL_POINT_SPRITE_NV 0x8861 #define GL_COORD_REPLACE_NV 0x8862 #define GL_POINT_SPRITE_R_MODE_NV 0x8863 #endif #ifndef GL_NV_texture_shader3 #define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 #define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 #define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 #define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 #define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 #define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 #define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 #define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 #define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 #define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 #define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A #define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B #define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C #define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D #define GL_HILO8_NV 0x885E #define GL_SIGNED_HILO8_NV 0x885F #define GL_FORCE_BLUE_TO_ONE_NV 0x8860 #endif #ifndef GL_NV_vertex_program1_1 #endif #ifndef GL_EXT_shadow_funcs #endif #ifndef GL_EXT_stencil_two_side #define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 #define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 #endif #ifndef GL_ATI_text_fragment_shader #define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 #endif #ifndef GL_APPLE_client_storage #define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 #endif #ifndef GL_APPLE_element_array #define GL_ELEMENT_ARRAY_APPLE 0x8768 #define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769 #define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A #endif #ifndef GL_APPLE_fence #define GL_DRAW_PIXELS_APPLE 0x8A0A #define GL_FENCE_APPLE 0x8A0B #endif #ifndef GL_APPLE_vertex_array_object #define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 #endif #ifndef GL_APPLE_vertex_array_range #define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D #define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E #define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F #define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 #define GL_STORAGE_CACHED_APPLE 0x85BE #define GL_STORAGE_SHARED_APPLE 0x85BF #endif #ifndef GL_APPLE_ycbcr_422 #define GL_YCBCR_422_APPLE 0x85B9 #define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA #define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB #endif #ifndef GL_S3_s3tc #define GL_RGB_S3TC 0x83A0 #define GL_RGB4_S3TC 0x83A1 #define GL_RGBA_S3TC 0x83A2 #define GL_RGBA4_S3TC 0x83A3 #endif #ifndef GL_ATI_draw_buffers #define GL_MAX_DRAW_BUFFERS_ATI 0x8824 #define GL_DRAW_BUFFER0_ATI 0x8825 #define GL_DRAW_BUFFER1_ATI 0x8826 #define GL_DRAW_BUFFER2_ATI 0x8827 #define GL_DRAW_BUFFER3_ATI 0x8828 #define GL_DRAW_BUFFER4_ATI 0x8829 #define GL_DRAW_BUFFER5_ATI 0x882A #define GL_DRAW_BUFFER6_ATI 0x882B #define GL_DRAW_BUFFER7_ATI 0x882C #define GL_DRAW_BUFFER8_ATI 0x882D #define GL_DRAW_BUFFER9_ATI 0x882E #define GL_DRAW_BUFFER10_ATI 0x882F #define GL_DRAW_BUFFER11_ATI 0x8830 #define GL_DRAW_BUFFER12_ATI 0x8831 #define GL_DRAW_BUFFER13_ATI 0x8832 #define GL_DRAW_BUFFER14_ATI 0x8833 #define GL_DRAW_BUFFER15_ATI 0x8834 #endif #ifndef GL_ATI_pixel_format_float #define GL_TYPE_RGBA_FLOAT_ATI 0x8820 #define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 #endif #ifndef GL_ATI_texture_env_combine3 #define GL_MODULATE_ADD_ATI 0x8744 #define GL_MODULATE_SIGNED_ADD_ATI 0x8745 #define GL_MODULATE_SUBTRACT_ATI 0x8746 #endif #ifndef GL_ATI_texture_float #define GL_RGBA_FLOAT32_ATI 0x8814 #define GL_RGB_FLOAT32_ATI 0x8815 #define GL_ALPHA_FLOAT32_ATI 0x8816 #define GL_INTENSITY_FLOAT32_ATI 0x8817 #define GL_LUMINANCE_FLOAT32_ATI 0x8818 #define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 #define GL_RGBA_FLOAT16_ATI 0x881A #define GL_RGB_FLOAT16_ATI 0x881B #define GL_ALPHA_FLOAT16_ATI 0x881C #define GL_INTENSITY_FLOAT16_ATI 0x881D #define GL_LUMINANCE_FLOAT16_ATI 0x881E #define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F #endif #ifndef GL_NV_float_buffer #define GL_FLOAT_R_NV 0x8880 #define GL_FLOAT_RG_NV 0x8881 #define GL_FLOAT_RGB_NV 0x8882 #define GL_FLOAT_RGBA_NV 0x8883 #define GL_FLOAT_R16_NV 0x8884 #define GL_FLOAT_R32_NV 0x8885 #define GL_FLOAT_RG16_NV 0x8886 #define GL_FLOAT_RG32_NV 0x8887 #define GL_FLOAT_RGB16_NV 0x8888 #define GL_FLOAT_RGB32_NV 0x8889 #define GL_FLOAT_RGBA16_NV 0x888A #define GL_FLOAT_RGBA32_NV 0x888B #define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C #define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D #define GL_FLOAT_RGBA_MODE_NV 0x888E #endif #ifndef GL_NV_fragment_program #define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 #define GL_FRAGMENT_PROGRAM_NV 0x8870 #define GL_MAX_TEXTURE_COORDS_NV 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 #define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 #define GL_PROGRAM_ERROR_STRING_NV 0x8874 #endif #ifndef GL_NV_half_float #define GL_HALF_FLOAT_NV 0x140B #endif #ifndef GL_NV_pixel_data_range #define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 #define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 #define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A #define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B #define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C #define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D #endif #ifndef GL_NV_primitive_restart #define GL_PRIMITIVE_RESTART_NV 0x8558 #define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 #endif #ifndef GL_NV_texture_expand_normal #define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F #endif #ifndef GL_NV_vertex_program2 #endif #ifndef GL_ATI_map_object_buffer #endif #ifndef GL_ATI_separate_stencil #define GL_STENCIL_BACK_FUNC_ATI 0x8800 #define GL_STENCIL_BACK_FAIL_ATI 0x8801 #define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 #define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 #endif #ifndef GL_ATI_vertex_attrib_array_object #endif #ifndef GL_OES_read_format #define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A #define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B #endif #ifndef GL_EXT_depth_bounds_test #define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 #define GL_DEPTH_BOUNDS_EXT 0x8891 #endif #ifndef GL_EXT_texture_mirror_clamp #define GL_MIRROR_CLAMP_EXT 0x8742 #define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 #define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 #endif #ifndef GL_EXT_blend_equation_separate #define GL_BLEND_EQUATION_RGB_EXT GL_BLEND_EQUATION #define GL_BLEND_EQUATION_ALPHA_EXT 0x883D #endif #ifndef GL_MESA_pack_invert #define GL_PACK_INVERT_MESA 0x8758 #endif #ifndef GL_MESA_ycbcr_texture #define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA #define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB #define GL_YCBCR_MESA 0x8757 #endif #ifndef GL_EXT_pixel_buffer_object #define GL_PIXEL_PACK_BUFFER_EXT 0x88EB #define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC #define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED #define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF #endif #ifndef GL_NV_fragment_program_option #endif #ifndef GL_NV_fragment_program2 #define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 #define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 #define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 #define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 #define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 #endif #ifndef GL_NV_vertex_program2_option /* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */ /* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */ #endif #ifndef GL_NV_vertex_program3 /* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */ #endif #ifndef GL_EXT_framebuffer_object #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 #define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 #define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 #define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD #define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF #define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 #define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 #define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 #define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 #define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 #define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 #define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 #define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 #define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 #define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 #define GL_COLOR_ATTACHMENT10_EXT 0x8CEA #define GL_COLOR_ATTACHMENT11_EXT 0x8CEB #define GL_COLOR_ATTACHMENT12_EXT 0x8CEC #define GL_COLOR_ATTACHMENT13_EXT 0x8CED #define GL_COLOR_ATTACHMENT14_EXT 0x8CEE #define GL_COLOR_ATTACHMENT15_EXT 0x8CEF #define GL_DEPTH_ATTACHMENT_EXT 0x8D00 #define GL_STENCIL_ATTACHMENT_EXT 0x8D20 #define GL_FRAMEBUFFER_EXT 0x8D40 #define GL_RENDERBUFFER_EXT 0x8D41 #define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 #define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 #define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 #define GL_STENCIL_INDEX_EXT 0x8D45 #define GL_STENCIL_INDEX1_EXT 0x8D46 #define GL_STENCIL_INDEX4_EXT 0x8D47 #define GL_STENCIL_INDEX8_EXT 0x8D48 #define GL_STENCIL_INDEX16_EXT 0x8D49 #define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 #define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 #define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 #define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 #define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 #define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 #endif #ifndef GL_GREMEDY_string_marker #endif #ifndef GL_EXT_Cg_shader #define GL_CG_VERTEX_SHADER_EXT 0x890E #define GL_CG_FRAGMENT_SHADER_EXT 0x890E #endif #ifndef GL_NV_element_array #define GL_ELEMENT_ARRAY_TYPE_NV 0x8769 #define GL_ELEMENT_ARRAY_POINTER_NV 0x876A #endif #ifndef GL_NV_pixel_buffer_object #define GL_PIXEL_PACK_BUFFER_NV 0x88EB #define GL_PIXEL_UNPACK_BUFFER_NV 0x88EC #define GL_PIXEL_PACK_BUFFER_BINDING_NV 0x88ED #define GL_PIXEL_UNPACK_BUFFER_BINDING_NV 0x88EF #endif #ifndef GL_NV_stencil_two_side #define GL_STENCIL_TEST_TWO_SIDE_NV 0x8910 #define GL_ACTIVE_STENCIL_FACE_NV 0x8911 #endif /*************************************************************/ #include #ifndef GL_VERSION_2_0 /* GL type for program/shader text */ typedef char GLchar; /* native character */ #endif #ifndef GL_VERSION_1_5 /* GL types for handling large vertex buffer objects */ typedef ptrdiff_t GLintptr; typedef ptrdiff_t GLsizeiptr; #endif #ifndef GL_ARB_vertex_buffer_object /* GL types for handling large vertex buffer objects */ typedef ptrdiff_t GLintptrARB; typedef ptrdiff_t GLsizeiptrARB; #endif #ifndef GL_ARB_shader_objects /* GL types for handling shader object handles and program/shader text */ typedef char GLcharARB; /* native character */ typedef unsigned int GLhandleARB; /* shader object handle */ #endif /* GL types for "half" precision (s10e5) float data in host memory */ #ifndef GL_ARB_half_float_pixel typedef unsigned short GLhalfARB; #endif #ifndef GL_NV_half_float typedef unsigned short GLhalfNV; #endif #ifndef GL_VERSION_1_2 #define GL_VERSION_1_2 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf); GLAPI void APIENTRY glBlendEquation (GLenum); GLAPI void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); GLAPI void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei); GLAPI void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *); GLAPI void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei); GLAPI void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat); GLAPI void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint); GLAPI void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei); GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); GLAPI void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); GLAPI void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); GLAPI void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *); GLAPI void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean); GLAPI void APIENTRY glMinmax (GLenum, GLenum, GLboolean); GLAPI void APIENTRY glResetHistogram (GLenum); GLAPI void APIENTRY glResetMinmax (GLenum); GLAPI void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target); typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target); typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); #endif #ifndef GL_VERSION_1_3 #define GL_VERSION_1_3 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glActiveTexture (GLenum); GLAPI void APIENTRY glClientActiveTexture (GLenum); GLAPI void APIENTRY glMultiTexCoord1d (GLenum, GLdouble); GLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord1f (GLenum, GLfloat); GLAPI void APIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord1i (GLenum, GLint); GLAPI void APIENTRY glMultiTexCoord1iv (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord1s (GLenum, GLshort); GLAPI void APIENTRY glMultiTexCoord1sv (GLenum, const GLshort *); GLAPI void APIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble); GLAPI void APIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat); GLAPI void APIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord2i (GLenum, GLint, GLint); GLAPI void APIENTRY glMultiTexCoord2iv (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort); GLAPI void APIENTRY glMultiTexCoord2sv (GLenum, const GLshort *); GLAPI void APIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint); GLAPI void APIENTRY glMultiTexCoord3iv (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort); GLAPI void APIENTRY glMultiTexCoord3sv (GLenum, const GLshort *); GLAPI void APIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint); GLAPI void APIENTRY glMultiTexCoord4iv (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glMultiTexCoord4sv (GLenum, const GLshort *); GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *); GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *); GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *); GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *); GLAPI void APIENTRY glSampleCoverage (GLclampf, GLboolean); GLAPI void APIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m); typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m); typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m); typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m); typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img); #endif #ifndef GL_VERSION_1_4 #define GL_VERSION_1_4 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glFogCoordf (GLfloat); GLAPI void APIENTRY glFogCoordfv (const GLfloat *); GLAPI void APIENTRY glFogCoordd (GLdouble); GLAPI void APIENTRY glFogCoorddv (const GLdouble *); GLAPI void APIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei); GLAPI void APIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); GLAPI void APIENTRY glPointParameterf (GLenum, GLfloat); GLAPI void APIENTRY glPointParameterfv (GLenum, const GLfloat *); GLAPI void APIENTRY glPointParameteri (GLenum, GLint); GLAPI void APIENTRY glPointParameteriv (GLenum, const GLint *); GLAPI void APIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte); GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *); GLAPI void APIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *); GLAPI void APIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *); GLAPI void APIENTRY glSecondaryColor3i (GLint, GLint, GLint); GLAPI void APIENTRY glSecondaryColor3iv (const GLint *); GLAPI void APIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort); GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *); GLAPI void APIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte); GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *); GLAPI void APIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint); GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *); GLAPI void APIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort); GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *); GLAPI void APIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glWindowPos2d (GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos2dv (const GLdouble *); GLAPI void APIENTRY glWindowPos2f (GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos2fv (const GLfloat *); GLAPI void APIENTRY glWindowPos2i (GLint, GLint); GLAPI void APIENTRY glWindowPos2iv (const GLint *); GLAPI void APIENTRY glWindowPos2s (GLshort, GLshort); GLAPI void APIENTRY glWindowPos2sv (const GLshort *); GLAPI void APIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos3dv (const GLdouble *); GLAPI void APIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos3fv (const GLfloat *); GLAPI void APIENTRY glWindowPos3i (GLint, GLint, GLint); GLAPI void APIENTRY glWindowPos3iv (const GLint *); GLAPI void APIENTRY glWindowPos3s (GLshort, GLshort, GLshort); GLAPI void APIENTRY glWindowPos3sv (const GLshort *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord); typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord); typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord); typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord); typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v); #endif #ifndef GL_VERSION_1_5 #define GL_VERSION_1_5 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGenQueries (GLsizei, GLuint *); GLAPI void APIENTRY glDeleteQueries (GLsizei, const GLuint *); GLAPI GLboolean APIENTRY glIsQuery (GLuint); GLAPI void APIENTRY glBeginQuery (GLenum, GLuint); GLAPI void APIENTRY glEndQuery (GLenum); GLAPI void APIENTRY glGetQueryiv (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *); GLAPI void APIENTRY glBindBuffer (GLenum, GLuint); GLAPI void APIENTRY glDeleteBuffers (GLsizei, const GLuint *); GLAPI void APIENTRY glGenBuffers (GLsizei, GLuint *); GLAPI GLboolean APIENTRY glIsBuffer (GLuint); GLAPI void APIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum); GLAPI void APIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *); GLAPI void APIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *); GLAPI GLvoid* APIENTRY glMapBuffer (GLenum, GLenum); GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum); GLAPI void APIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id); typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target); typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params); #endif #ifndef GL_VERSION_2_0 #define GL_VERSION_2_0 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendEquationSeparate (GLenum, GLenum); GLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *); GLAPI void APIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint); GLAPI void APIENTRY glStencilMaskSeparate (GLenum, GLuint); GLAPI void APIENTRY glAttachShader (GLuint, GLuint); GLAPI void APIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *); GLAPI void APIENTRY glCompileShader (GLuint); GLAPI GLuint APIENTRY glCreateProgram (void); GLAPI GLuint APIENTRY glCreateShader (GLenum); GLAPI void APIENTRY glDeleteProgram (GLuint); GLAPI void APIENTRY glDeleteShader (GLuint); GLAPI void APIENTRY glDetachShader (GLuint, GLuint); GLAPI void APIENTRY glDisableVertexAttribArray (GLuint); GLAPI void APIENTRY glEnableVertexAttribArray (GLuint); GLAPI void APIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); GLAPI void APIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); GLAPI void APIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *); GLAPI GLint APIENTRY glGetAttribLocation (GLuint, const GLchar *); GLAPI void APIENTRY glGetProgramiv (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *); GLAPI void APIENTRY glGetShaderiv (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *); GLAPI void APIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *); GLAPI GLint APIENTRY glGetUniformLocation (GLuint, const GLchar *); GLAPI void APIENTRY glGetUniformfv (GLuint, GLint, GLfloat *); GLAPI void APIENTRY glGetUniformiv (GLuint, GLint, GLint *); GLAPI void APIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *); GLAPI void APIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *); GLAPI GLboolean APIENTRY glIsProgram (GLuint); GLAPI GLboolean APIENTRY glIsShader (GLuint); GLAPI void APIENTRY glLinkProgram (GLuint); GLAPI void APIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *); GLAPI void APIENTRY glUseProgram (GLuint); GLAPI void APIENTRY glUniform1f (GLint, GLfloat); GLAPI void APIENTRY glUniform2f (GLint, GLfloat, GLfloat); GLAPI void APIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glUniform1i (GLint, GLint); GLAPI void APIENTRY glUniform2i (GLint, GLint, GLint); GLAPI void APIENTRY glUniform3i (GLint, GLint, GLint, GLint); GLAPI void APIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint); GLAPI void APIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform1iv (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniform2iv (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniform3iv (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniform4iv (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *); GLAPI void APIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *); GLAPI void APIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *); GLAPI void APIENTRY glValidateProgram (GLuint); GLAPI void APIENTRY glVertexAttrib1d (GLuint, GLdouble); GLAPI void APIENTRY glVertexAttrib1dv (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib1f (GLuint, GLfloat); GLAPI void APIENTRY glVertexAttrib1fv (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib1s (GLuint, GLshort); GLAPI void APIENTRY glVertexAttrib1sv (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib2dv (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib2fv (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib2sv (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib3dv (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib3fv (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib3sv (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *); GLAPI void APIENTRY glVertexAttrib4Niv (GLuint, const GLint *); GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *); GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *); GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *); GLAPI void APIENTRY glVertexAttrib4bv (GLuint, const GLbyte *); GLAPI void APIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib4dv (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib4fv (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib4iv (GLuint, const GLint *); GLAPI void APIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib4sv (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *); GLAPI void APIENTRY glVertexAttrib4uiv (GLuint, const GLuint *); GLAPI void APIENTRY glVertexAttrib4usv (GLuint, const GLushort *); GLAPI void APIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj); typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader); typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); #endif #ifndef GL_ARB_multitexture #define GL_ARB_multitexture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glActiveTextureARB (GLenum); GLAPI void APIENTRY glClientActiveTextureARB (GLenum); GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble); GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat); GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum, GLint); GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort); GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *); GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble); GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat); GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint); GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort); GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *); GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint); GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort); GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *); GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *); GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *); GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint); GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *); GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture); typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); #endif #ifndef GL_ARB_transpose_matrix #define GL_ARB_transpose_matrix 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *); GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *); GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *); GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); #endif #ifndef GL_ARB_multisample #define GL_ARB_multisample 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSampleCoverageARB (GLclampf, GLboolean); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); #endif #ifndef GL_ARB_texture_env_add #define GL_ARB_texture_env_add 1 #endif #ifndef GL_ARB_texture_cube_map #define GL_ARB_texture_cube_map 1 #endif #ifndef GL_ARB_texture_compression #define GL_ARB_texture_compression 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img); #endif #ifndef GL_ARB_texture_border_clamp #define GL_ARB_texture_border_clamp 1 #endif #ifndef GL_ARB_point_parameters #define GL_ARB_point_parameters 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat); GLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params); #endif #ifndef GL_ARB_vertex_blend #define GL_ARB_vertex_blend 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glWeightbvARB (GLint, const GLbyte *); GLAPI void APIENTRY glWeightsvARB (GLint, const GLshort *); GLAPI void APIENTRY glWeightivARB (GLint, const GLint *); GLAPI void APIENTRY glWeightfvARB (GLint, const GLfloat *); GLAPI void APIENTRY glWeightdvARB (GLint, const GLdouble *); GLAPI void APIENTRY glWeightubvARB (GLint, const GLubyte *); GLAPI void APIENTRY glWeightusvARB (GLint, const GLushort *); GLAPI void APIENTRY glWeightuivARB (GLint, const GLuint *); GLAPI void APIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glVertexBlendARB (GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights); typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights); typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights); typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights); typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights); typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights); typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights); typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights); typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count); #endif #ifndef GL_ARB_matrix_palette #define GL_ARB_matrix_palette 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint); GLAPI void APIENTRY glMatrixIndexubvARB (GLint, const GLubyte *); GLAPI void APIENTRY glMatrixIndexusvARB (GLint, const GLushort *); GLAPI void APIENTRY glMatrixIndexuivARB (GLint, const GLuint *); GLAPI void APIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices); typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices); typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices); typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); #endif #ifndef GL_ARB_texture_env_combine #define GL_ARB_texture_env_combine 1 #endif #ifndef GL_ARB_texture_env_crossbar #define GL_ARB_texture_env_crossbar 1 #endif #ifndef GL_ARB_texture_env_dot3 #define GL_ARB_texture_env_dot3 1 #endif #ifndef GL_ARB_texture_mirrored_repeat #define GL_ARB_texture_mirrored_repeat 1 #endif #ifndef GL_ARB_depth_texture #define GL_ARB_depth_texture 1 #endif #ifndef GL_ARB_shadow #define GL_ARB_shadow 1 #endif #ifndef GL_ARB_shadow_ambient #define GL_ARB_shadow_ambient 1 #endif #ifndef GL_ARB_window_pos #define GL_ARB_window_pos 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glWindowPos2dARB (GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *); GLAPI void APIENTRY glWindowPos2fARB (GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *); GLAPI void APIENTRY glWindowPos2iARB (GLint, GLint); GLAPI void APIENTRY glWindowPos2ivARB (const GLint *); GLAPI void APIENTRY glWindowPos2sARB (GLshort, GLshort); GLAPI void APIENTRY glWindowPos2svARB (const GLshort *); GLAPI void APIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *); GLAPI void APIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *); GLAPI void APIENTRY glWindowPos3iARB (GLint, GLint, GLint); GLAPI void APIENTRY glWindowPos3ivARB (const GLint *); GLAPI void APIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort); GLAPI void APIENTRY glWindowPos3svARB (const GLshort *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v); #endif #ifndef GL_ARB_vertex_program #define GL_ARB_vertex_program 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertexAttrib1dARB (GLuint, GLdouble); GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib1fARB (GLuint, GLfloat); GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib1sARB (GLuint, GLshort); GLAPI void APIENTRY glVertexAttrib1svARB (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib2svARB (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib3svARB (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *); GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint, const GLint *); GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *); GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *); GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *); GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *); GLAPI void APIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint, const GLint *); GLAPI void APIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib4svARB (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *); GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *); GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *); GLAPI void APIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint); GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint); GLAPI void APIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glBindProgramARB (GLenum, GLuint); GLAPI void APIENTRY glDeleteProgramsARB (GLsizei, const GLuint *); GLAPI void APIENTRY glGenProgramsARB (GLsizei, GLuint *); GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *); GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *); GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *); GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *); GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *); GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *); GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *); GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *); GLAPI void APIENTRY glGetProgramivARB (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *); GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *); GLAPI GLboolean APIENTRY glIsProgramARB (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer); typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program); #endif #ifndef GL_ARB_fragment_program #define GL_ARB_fragment_program 1 /* All ARB_fragment_program entry points are shared with ARB_vertex_program. */ #endif #ifndef GL_ARB_vertex_buffer_object #define GL_ARB_vertex_buffer_object 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBindBufferARB (GLenum, GLuint); GLAPI void APIENTRY glDeleteBuffersARB (GLsizei, const GLuint *); GLAPI void APIENTRY glGenBuffersARB (GLsizei, GLuint *); GLAPI GLboolean APIENTRY glIsBufferARB (GLuint); GLAPI void APIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum); GLAPI void APIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *); GLAPI void APIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *); GLAPI GLvoid* APIENTRY glMapBufferARB (GLenum, GLenum); GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum); GLAPI void APIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer); typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target); typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params); #endif #ifndef GL_ARB_occlusion_query #define GL_ARB_occlusion_query 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGenQueriesARB (GLsizei, GLuint *); GLAPI void APIENTRY glDeleteQueriesARB (GLsizei, const GLuint *); GLAPI GLboolean APIENTRY glIsQueryARB (GLuint); GLAPI void APIENTRY glBeginQueryARB (GLenum, GLuint); GLAPI void APIENTRY glEndQueryARB (GLenum); GLAPI void APIENTRY glGetQueryivARB (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids); typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id); typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target); typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params); #endif #ifndef GL_ARB_shader_objects #define GL_ARB_shader_objects 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB); GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum); GLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB); GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum); GLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *); GLAPI void APIENTRY glCompileShaderARB (GLhandleARB); GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void); GLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB); GLAPI void APIENTRY glLinkProgramARB (GLhandleARB); GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB); GLAPI void APIENTRY glValidateProgramARB (GLhandleARB); GLAPI void APIENTRY glUniform1fARB (GLint, GLfloat); GLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat); GLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glUniform1iARB (GLint, GLint); GLAPI void APIENTRY glUniform2iARB (GLint, GLint, GLint); GLAPI void APIENTRY glUniform3iARB (GLint, GLint, GLint, GLint); GLAPI void APIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint); GLAPI void APIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *); GLAPI void APIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *); GLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *); GLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *); GLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *); GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *); GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *); GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *); GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *); GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *); GLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *); GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname); typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void); typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); #endif #ifndef GL_ARB_vertex_shader #define GL_ARB_vertex_shader 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *); GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); #endif #ifndef GL_ARB_fragment_shader #define GL_ARB_fragment_shader 1 #endif #ifndef GL_ARB_shading_language_100 #define GL_ARB_shading_language_100 1 #endif #ifndef GL_ARB_texture_non_power_of_two #define GL_ARB_texture_non_power_of_two 1 #endif #ifndef GL_ARB_point_sprite #define GL_ARB_point_sprite 1 #endif #ifndef GL_ARB_fragment_program_shadow #define GL_ARB_fragment_program_shadow 1 #endif #ifndef GL_ARB_draw_buffers #define GL_ARB_draw_buffers 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDrawBuffersARB (GLsizei, const GLenum *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs); #endif #ifndef GL_ARB_texture_rectangle #define GL_ARB_texture_rectangle 1 #endif #ifndef GL_ARB_color_buffer_float #define GL_ARB_color_buffer_float 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glClampColorARB (GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); #endif #ifndef GL_ARB_half_float_pixel #define GL_ARB_half_float_pixel 1 #endif #ifndef GL_ARB_texture_float #define GL_ARB_texture_float 1 #endif #ifndef GL_ARB_pixel_buffer_object #define GL_ARB_pixel_buffer_object 1 #endif #ifndef GL_EXT_abgr #define GL_EXT_abgr 1 #endif #ifndef GL_EXT_blend_color #define GL_EXT_blend_color 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); #endif #ifndef GL_EXT_polygon_offset #define GL_EXT_polygon_offset 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); #endif #ifndef GL_EXT_texture #define GL_EXT_texture 1 #endif #ifndef GL_EXT_texture3D #define GL_EXT_texture3D 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); #endif #ifndef GL_SGIS_texture_filter4 #define GL_SGIS_texture_filter4 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); #endif #ifndef GL_EXT_subtexture #define GL_EXT_subtexture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); #endif #ifndef GL_EXT_copy_texture #define GL_EXT_copy_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei); GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); #endif #ifndef GL_EXT_histogram #define GL_EXT_histogram 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *); GLAPI void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean); GLAPI void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean); GLAPI void APIENTRY glResetHistogramEXT (GLenum); GLAPI void APIENTRY glResetMinmaxEXT (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target); #endif #ifndef GL_EXT_convolution #define GL_EXT_convolution 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat); GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint); GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei); GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); #endif #ifndef GL_EXT_color_matrix #define GL_EXT_color_matrix 1 #endif #ifndef GL_SGI_color_table #define GL_SGI_color_table 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei); GLAPI void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); #endif #ifndef GL_SGIX_pixel_texture #define GL_SGIX_pixel_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPixelTexGenSGIX (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); #endif #ifndef GL_SGIS_pixel_texture #define GL_SGIS_pixel_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint); GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *); GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat); GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *); GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *); GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); #endif #ifndef GL_SGIS_texture4D #define GL_SGIS_texture4D 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); #endif #ifndef GL_SGI_texture_color_table #define GL_SGI_texture_color_table 1 #endif #ifndef GL_EXT_cmyka #define GL_EXT_cmyka 1 #endif #ifndef GL_EXT_texture_object #define GL_EXT_texture_object 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *); GLAPI void APIENTRY glBindTextureEXT (GLenum, GLuint); GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *); GLAPI void APIENTRY glGenTexturesEXT (GLsizei, GLuint *); GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint); GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture); typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); #endif #ifndef GL_SGIS_detail_texture #define GL_SGIS_detail_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *); GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); #endif #ifndef GL_SGIS_sharpen_texture #define GL_SGIS_sharpen_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *); GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); #endif #ifndef GL_EXT_packed_pixels #define GL_EXT_packed_pixels 1 #endif #ifndef GL_SGIS_texture_lod #define GL_SGIS_texture_lod 1 #endif #ifndef GL_SGIS_multisample #define GL_SGIS_multisample 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean); GLAPI void APIENTRY glSamplePatternSGIS (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); #endif #ifndef GL_EXT_rescale_normal #define GL_EXT_rescale_normal 1 #endif #ifndef GL_EXT_vertex_array #define GL_EXT_vertex_array 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glArrayElementEXT (GLint); GLAPI void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); GLAPI void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei); GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *); GLAPI void APIENTRY glGetPointervEXT (GLenum, GLvoid* *); GLAPI void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); GLAPI void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); GLAPI void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); GLAPI void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i); typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); #endif #ifndef GL_EXT_misc_attribute #define GL_EXT_misc_attribute 1 #endif #ifndef GL_SGIS_generate_mipmap #define GL_SGIS_generate_mipmap 1 #endif #ifndef GL_SGIX_clipmap #define GL_SGIX_clipmap 1 #endif #ifndef GL_SGIX_shadow #define GL_SGIX_shadow 1 #endif #ifndef GL_SGIS_texture_edge_clamp #define GL_SGIS_texture_edge_clamp 1 #endif #ifndef GL_SGIS_texture_border_clamp #define GL_SGIS_texture_border_clamp 1 #endif #ifndef GL_EXT_blend_minmax #define GL_EXT_blend_minmax 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendEquationEXT (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); #endif #ifndef GL_EXT_blend_subtract #define GL_EXT_blend_subtract 1 #endif #ifndef GL_EXT_blend_logic_op #define GL_EXT_blend_logic_op 1 #endif #ifndef GL_SGIX_interlace #define GL_SGIX_interlace 1 #endif #ifndef GL_SGIX_pixel_tiles #define GL_SGIX_pixel_tiles 1 #endif #ifndef GL_SGIX_texture_select #define GL_SGIX_texture_select 1 #endif #ifndef GL_SGIX_sprite #define GL_SGIX_sprite 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat); GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *); GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum, GLint); GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); #endif #ifndef GL_SGIX_texture_multi_buffer #define GL_SGIX_texture_multi_buffer 1 #endif #ifndef GL_EXT_point_parameters #define GL_EXT_point_parameters 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat); GLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); #endif #ifndef GL_SGIS_point_parameters #define GL_SGIS_point_parameters 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPointParameterfSGIS (GLenum, GLfloat); GLAPI void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); #endif #ifndef GL_SGIX_instruments #define GL_SGIX_instruments 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLint APIENTRY glGetInstrumentsSGIX (void); GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *); GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *); GLAPI void APIENTRY glReadInstrumentsSGIX (GLint); GLAPI void APIENTRY glStartInstrumentsSGIX (void); GLAPI void APIENTRY glStopInstrumentsSGIX (GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void); typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void); typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); #endif #ifndef GL_SGIX_texture_scale_bias #define GL_SGIX_texture_scale_bias 1 #endif #ifndef GL_SGIX_framezoom #define GL_SGIX_framezoom 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFrameZoomSGIX (GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor); #endif #ifndef GL_SGIX_tag_sample_buffer #define GL_SGIX_tag_sample_buffer 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTagSampleBufferSGIX (void); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); #endif #ifndef GL_SGIX_polynomial_ffd #define GL_SGIX_polynomial_ffd 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *); GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *); GLAPI void APIENTRY glDeformSGIX (GLbitfield); GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask); typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask); #endif #ifndef GL_SGIX_reference_plane #define GL_SGIX_reference_plane 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); #endif #ifndef GL_SGIX_flush_raster #define GL_SGIX_flush_raster 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFlushRasterSGIX (void); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void); #endif #ifndef GL_SGIX_depth_texture #define GL_SGIX_depth_texture 1 #endif #ifndef GL_SGIS_fog_function #define GL_SGIS_fog_function 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *); GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points); #endif #ifndef GL_SGIX_fog_offset #define GL_SGIX_fog_offset 1 #endif #ifndef GL_HP_image_transform #define GL_HP_image_transform 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint); GLAPI void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat); GLAPI void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); #endif #ifndef GL_HP_convolution_border_modes #define GL_HP_convolution_border_modes 1 #endif #ifndef GL_SGIX_texture_add_env #define GL_SGIX_texture_add_env 1 #endif #ifndef GL_EXT_color_subtable #define GL_EXT_color_subtable 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); #endif #ifndef GL_PGI_vertex_hints #define GL_PGI_vertex_hints 1 #endif #ifndef GL_PGI_misc_hints #define GL_PGI_misc_hints 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glHintPGI (GLenum, GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode); #endif #ifndef GL_EXT_paletted_texture #define GL_EXT_paletted_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); GLAPI void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *); GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); #endif #ifndef GL_EXT_clip_volume_hint #define GL_EXT_clip_volume_hint 1 #endif #ifndef GL_SGIX_list_priority #define GL_SGIX_list_priority 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *); GLAPI void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat); GLAPI void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *); GLAPI void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint); GLAPI void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); #endif #ifndef GL_SGIX_ir_instrument1 #define GL_SGIX_ir_instrument1 1 #endif #ifndef GL_SGIX_calligraphic_fragment #define GL_SGIX_calligraphic_fragment 1 #endif #ifndef GL_SGIX_texture_lod_bias #define GL_SGIX_texture_lod_bias 1 #endif #ifndef GL_SGIX_shadow_ambient #define GL_SGIX_shadow_ambient 1 #endif #ifndef GL_EXT_index_texture #define GL_EXT_index_texture 1 #endif #ifndef GL_EXT_index_material #define GL_EXT_index_material 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glIndexMaterialEXT (GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); #endif #ifndef GL_EXT_index_func #define GL_EXT_index_func 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glIndexFuncEXT (GLenum, GLclampf); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); #endif #ifndef GL_EXT_index_array_formats #define GL_EXT_index_array_formats 1 #endif #ifndef GL_EXT_compiled_vertex_array #define GL_EXT_compiled_vertex_array 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glLockArraysEXT (GLint, GLsizei); GLAPI void APIENTRY glUnlockArraysEXT (void); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void); #endif #ifndef GL_EXT_cull_vertex #define GL_EXT_cull_vertex 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *); GLAPI void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); #endif #ifndef GL_SGIX_ycrcb #define GL_SGIX_ycrcb 1 #endif #ifndef GL_SGIX_fragment_lighting #define GL_SGIX_fragment_lighting 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum); GLAPI void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat); GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint); GLAPI void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat); GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *); GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint); GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *); GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat); GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint); GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *); GLAPI void APIENTRY glLightEnviSGIX (GLenum, GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); #endif #ifndef GL_IBM_rasterpos_clip #define GL_IBM_rasterpos_clip 1 #endif #ifndef GL_HP_texture_lighting #define GL_HP_texture_lighting 1 #endif #ifndef GL_EXT_draw_range_elements #define GL_EXT_draw_range_elements 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); #endif #ifndef GL_WIN_phong_shading #define GL_WIN_phong_shading 1 #endif #ifndef GL_WIN_specular_fog #define GL_WIN_specular_fog 1 #endif #ifndef GL_EXT_light_texture #define GL_EXT_light_texture 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glApplyTextureEXT (GLenum); GLAPI void APIENTRY glTextureLightEXT (GLenum); GLAPI void APIENTRY glTextureMaterialEXT (GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); #endif #ifndef GL_SGIX_blend_alpha_minmax #define GL_SGIX_blend_alpha_minmax 1 #endif #ifndef GL_EXT_bgra #define GL_EXT_bgra 1 #endif #ifndef GL_SGIX_async #define GL_SGIX_async 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint); GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *); GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *); GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei); GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei); GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker); typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp); typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp); typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); #endif #ifndef GL_SGIX_async_pixel #define GL_SGIX_async_pixel 1 #endif #ifndef GL_SGIX_async_histogram #define GL_SGIX_async_histogram 1 #endif #ifndef GL_INTEL_parallel_arrays #define GL_INTEL_parallel_arrays 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *); GLAPI void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *); GLAPI void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *); GLAPI void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); #endif #ifndef GL_HP_occlusion_test #define GL_HP_occlusion_test 1 #endif #ifndef GL_EXT_pixel_transform #define GL_EXT_pixel_transform 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint); GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat); GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); #endif #ifndef GL_EXT_pixel_transform_color_table #define GL_EXT_pixel_transform_color_table 1 #endif #ifndef GL_EXT_shared_texture_palette #define GL_EXT_shared_texture_palette 1 #endif #ifndef GL_EXT_separate_specular_color #define GL_EXT_separate_specular_color 1 #endif #ifndef GL_EXT_secondary_color #define GL_EXT_secondary_color 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte); GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *); GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *); GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *); GLAPI void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint); GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *); GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort); GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *); GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte); GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *); GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint); GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *); GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort); GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *); GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); #endif #ifndef GL_EXT_texture_perturb_normal #define GL_EXT_texture_perturb_normal 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTextureNormalEXT (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode); #endif #ifndef GL_EXT_multi_draw_arrays #define GL_EXT_multi_draw_arrays 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); #endif #ifndef GL_EXT_fog_coord #define GL_EXT_fog_coord 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFogCoordfEXT (GLfloat); GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *); GLAPI void APIENTRY glFogCoorddEXT (GLdouble); GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *); GLAPI void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord); typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord); typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); #endif #ifndef GL_REND_screen_coordinates #define GL_REND_screen_coordinates 1 #endif #ifndef GL_EXT_coordinate_frame #define GL_EXT_coordinate_frame 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte); GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *); GLAPI void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *); GLAPI void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *); GLAPI void APIENTRY glTangent3iEXT (GLint, GLint, GLint); GLAPI void APIENTRY glTangent3ivEXT (const GLint *); GLAPI void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort); GLAPI void APIENTRY glTangent3svEXT (const GLshort *); GLAPI void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte); GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *); GLAPI void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *); GLAPI void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *); GLAPI void APIENTRY glBinormal3iEXT (GLint, GLint, GLint); GLAPI void APIENTRY glBinormal3ivEXT (const GLint *); GLAPI void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort); GLAPI void APIENTRY glBinormal3svEXT (const GLshort *); GLAPI void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v); typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v); typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); #endif #ifndef GL_EXT_texture_env_combine #define GL_EXT_texture_env_combine 1 #endif #ifndef GL_APPLE_specular_vector #define GL_APPLE_specular_vector 1 #endif #ifndef GL_APPLE_transform_hint #define GL_APPLE_transform_hint 1 #endif #ifndef GL_SGIX_fog_scale #define GL_SGIX_fog_scale 1 #endif #ifndef GL_SUNX_constant_data #define GL_SUNX_constant_data 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFinishTextureSUNX (void); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void); #endif #ifndef GL_SUN_global_alpha #define GL_SUN_global_alpha 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte); GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort); GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint); GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat); GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble); GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte); GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort); GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); #endif #ifndef GL_SUN_triangle_list #define GL_SUN_triangle_list 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint); GLAPI void APIENTRY glReplacementCodeusSUN (GLushort); GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte); GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *); GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *); GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *); GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); #endif #ifndef GL_SUN_vertex #define GL_SUN_vertex 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat); GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *); GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *); GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *); GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *); GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *); GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *); GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *); GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *); GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); #endif #ifndef GL_EXT_blend_func_separate #define GL_EXT_blend_func_separate 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); #endif #ifndef GL_INGR_blend_func_separate #define GL_INGR_blend_func_separate 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); #endif #ifndef GL_INGR_color_clamp #define GL_INGR_color_clamp 1 #endif #ifndef GL_INGR_interlace_read #define GL_INGR_interlace_read 1 #endif #ifndef GL_EXT_stencil_wrap #define GL_EXT_stencil_wrap 1 #endif #ifndef GL_EXT_422_pixels #define GL_EXT_422_pixels 1 #endif #ifndef GL_NV_texgen_reflection #define GL_NV_texgen_reflection 1 #endif #ifndef GL_SUN_convolution_border_modes #define GL_SUN_convolution_border_modes 1 #endif #ifndef GL_EXT_texture_env_add #define GL_EXT_texture_env_add 1 #endif #ifndef GL_EXT_texture_lod_bias #define GL_EXT_texture_lod_bias 1 #endif #ifndef GL_EXT_texture_filter_anisotropic #define GL_EXT_texture_filter_anisotropic 1 #endif #ifndef GL_EXT_vertex_weighting #define GL_EXT_vertex_weighting 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertexWeightfEXT (GLfloat); GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *); GLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); #endif #ifndef GL_NV_light_max_exponent #define GL_NV_light_max_exponent 1 #endif #ifndef GL_NV_vertex_array_range #define GL_NV_vertex_array_range 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glFlushVertexArrayRangeNV (void); GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer); #endif #ifndef GL_NV_register_combiners #define GL_NV_register_combiners 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *); GLAPI void APIENTRY glCombinerParameterfNV (GLenum, GLfloat); GLAPI void APIENTRY glCombinerParameterivNV (GLenum, const GLint *); GLAPI void APIENTRY glCombinerParameteriNV (GLenum, GLint); GLAPI void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); GLAPI void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); #endif #ifndef GL_NV_fog_distance #define GL_NV_fog_distance 1 #endif #ifndef GL_NV_texgen_emboss #define GL_NV_texgen_emboss 1 #endif #ifndef GL_NV_blend_square #define GL_NV_blend_square 1 #endif #ifndef GL_NV_texture_env_combine4 #define GL_NV_texture_env_combine4 1 #endif #ifndef GL_MESA_resize_buffers #define GL_MESA_resize_buffers 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glResizeBuffersMESA (void); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void); #endif #ifndef GL_MESA_window_pos #define GL_MESA_window_pos 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *); GLAPI void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *); GLAPI void APIENTRY glWindowPos2iMESA (GLint, GLint); GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *); GLAPI void APIENTRY glWindowPos2sMESA (GLshort, GLshort); GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *); GLAPI void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *); GLAPI void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *); GLAPI void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint); GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *); GLAPI void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort); GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *); GLAPI void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *); GLAPI void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *); GLAPI void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint); GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *); GLAPI void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); #endif #ifndef GL_EXT_texture_compression_s3tc #define GL_EXT_texture_compression_s3tc 1 #endif #ifndef GL_IBM_cull_vertex #define GL_IBM_cull_vertex 1 #endif #ifndef GL_IBM_multimode_draw_arrays #define GL_IBM_multimode_draw_arrays 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint); GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); #endif #ifndef GL_IBM_vertex_array_lists #define GL_IBM_vertex_array_lists 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint); GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); GLAPI void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); GLAPI void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); GLAPI void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); GLAPI void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); #endif #ifndef GL_SGIX_subsample #define GL_SGIX_subsample 1 #endif #ifndef GL_SGIX_ycrcba #define GL_SGIX_ycrcba 1 #endif #ifndef GL_SGIX_ycrcb_subsample #define GL_SGIX_ycrcb_subsample 1 #endif #ifndef GL_SGIX_depth_pass_instrument #define GL_SGIX_depth_pass_instrument 1 #endif #ifndef GL_3DFX_texture_compression_FXT1 #define GL_3DFX_texture_compression_FXT1 1 #endif #ifndef GL_3DFX_multisample #define GL_3DFX_multisample 1 #endif #ifndef GL_3DFX_tbuffer #define GL_3DFX_tbuffer 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTbufferMask3DFX (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); #endif #ifndef GL_EXT_multisample #define GL_EXT_multisample 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSampleMaskEXT (GLclampf, GLboolean); GLAPI void APIENTRY glSamplePatternEXT (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); #endif #ifndef GL_SGIX_vertex_preclip #define GL_SGIX_vertex_preclip 1 #endif #ifndef GL_SGIX_convolution_accuracy #define GL_SGIX_convolution_accuracy 1 #endif #ifndef GL_SGIX_resample #define GL_SGIX_resample 1 #endif #ifndef GL_SGIS_point_line_texgen #define GL_SGIS_point_line_texgen 1 #endif #ifndef GL_SGIS_texture_color_mask #define GL_SGIS_texture_color_mask 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); #endif #ifndef GL_SGIX_igloo_interface #define GL_SGIX_igloo_interface 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params); #endif #ifndef GL_EXT_texture_env_dot3 #define GL_EXT_texture_env_dot3 1 #endif #ifndef GL_ATI_texture_mirror_once #define GL_ATI_texture_mirror_once 1 #endif #ifndef GL_NV_fence #define GL_NV_fence 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDeleteFencesNV (GLsizei, const GLuint *); GLAPI void APIENTRY glGenFencesNV (GLsizei, GLuint *); GLAPI GLboolean APIENTRY glIsFenceNV (GLuint); GLAPI GLboolean APIENTRY glTestFenceNV (GLuint); GLAPI void APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *); GLAPI void APIENTRY glFinishFenceNV (GLuint); GLAPI void APIENTRY glSetFenceNV (GLuint, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); #endif #ifndef GL_NV_evaluators #define GL_NV_evaluators 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *); GLAPI void APIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *); GLAPI void APIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *); GLAPI void APIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *); GLAPI void APIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glEvalMapsNV (GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); #endif #ifndef GL_NV_packed_depth_stencil #define GL_NV_packed_depth_stencil 1 #endif #ifndef GL_NV_register_combiners2 #define GL_NV_register_combiners2 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *); GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); #endif #ifndef GL_NV_texture_compression_vtc #define GL_NV_texture_compression_vtc 1 #endif #ifndef GL_NV_texture_rectangle #define GL_NV_texture_rectangle 1 #endif #ifndef GL_NV_texture_shader #define GL_NV_texture_shader 1 #endif #ifndef GL_NV_texture_shader2 #define GL_NV_texture_shader2 1 #endif #ifndef GL_NV_vertex_array_range2 #define GL_NV_vertex_array_range2 1 #endif #ifndef GL_NV_vertex_program #define GL_NV_vertex_program 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *); GLAPI void APIENTRY glBindProgramNV (GLenum, GLuint); GLAPI void APIENTRY glDeleteProgramsNV (GLsizei, const GLuint *); GLAPI void APIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *); GLAPI void APIENTRY glGenProgramsNV (GLsizei, GLuint *); GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *); GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetProgramivNV (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *); GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *); GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *); GLAPI GLboolean APIENTRY glIsProgramNV (GLuint); GLAPI void APIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *); GLAPI void APIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *); GLAPI void APIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *); GLAPI void APIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *); GLAPI void APIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *); GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *); GLAPI void APIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum); GLAPI void APIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glVertexAttrib1dNV (GLuint, GLdouble); GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib1fNV (GLuint, GLfloat); GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib1sNV (GLuint, GLshort); GLAPI void APIENTRY glVertexAttrib1svNV (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib2svNV (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib3svNV (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *); GLAPI void APIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *); GLAPI void APIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexAttrib4svNV (GLuint, const GLshort *); GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *); GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *); GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *); GLAPI void APIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *); GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *); GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *); GLAPI void APIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *); GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *); GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *); GLAPI void APIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *); GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *); GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *); GLAPI void APIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *); GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id); typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v); typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v); typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); #endif #ifndef GL_SGIX_texture_coordinate_clamp #define GL_SGIX_texture_coordinate_clamp 1 #endif #ifndef GL_SGIX_scalebias_hint #define GL_SGIX_scalebias_hint 1 #endif #ifndef GL_OML_interlace #define GL_OML_interlace 1 #endif #ifndef GL_OML_subsample #define GL_OML_subsample 1 #endif #ifndef GL_OML_resample #define GL_OML_resample 1 #endif #ifndef GL_NV_copy_depth_to_color #define GL_NV_copy_depth_to_color 1 #endif #ifndef GL_ATI_envmap_bumpmap #define GL_ATI_envmap_bumpmap 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glTexBumpParameterivATI (GLenum, const GLint *); GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *); GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum, GLint *); GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param); typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param); typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); #endif #ifndef GL_ATI_fragment_shader #define GL_ATI_fragment_shader 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint); GLAPI void APIENTRY glBindFragmentShaderATI (GLuint); GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint); GLAPI void APIENTRY glBeginFragmentShaderATI (void); GLAPI void APIENTRY glEndFragmentShaderATI (void); GLAPI void APIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum); GLAPI void APIENTRY glSampleMapATI (GLuint, GLuint, GLenum); GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void); typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void); typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value); #endif #ifndef GL_ATI_pn_triangles #define GL_ATI_pn_triangles 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPNTrianglesiATI (GLenum, GLint); GLAPI void APIENTRY glPNTrianglesfATI (GLenum, GLfloat); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); #endif #ifndef GL_ATI_vertex_array_object #define GL_ATI_vertex_array_object 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum); GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint); GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum); GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *); GLAPI void APIENTRY glFreeObjectBufferATI (GLuint); GLAPI void APIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint); GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *); GLAPI void APIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *); GLAPI void APIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint); GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage); typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params); #endif #ifndef GL_EXT_vertex_shader #define GL_EXT_vertex_shader 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBeginVertexShaderEXT (void); GLAPI void APIENTRY glEndVertexShaderEXT (void); GLAPI void APIENTRY glBindVertexShaderEXT (GLuint); GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint); GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint); GLAPI void APIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint); GLAPI void APIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint); GLAPI void APIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint); GLAPI void APIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint); GLAPI void APIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint); GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint); GLAPI void APIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *); GLAPI void APIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *); GLAPI void APIENTRY glVariantbvEXT (GLuint, const GLbyte *); GLAPI void APIENTRY glVariantsvEXT (GLuint, const GLshort *); GLAPI void APIENTRY glVariantivEXT (GLuint, const GLint *); GLAPI void APIENTRY glVariantfvEXT (GLuint, const GLfloat *); GLAPI void APIENTRY glVariantdvEXT (GLuint, const GLdouble *); GLAPI void APIENTRY glVariantubvEXT (GLuint, const GLubyte *); GLAPI void APIENTRY glVariantusvEXT (GLuint, const GLushort *); GLAPI void APIENTRY glVariantuivEXT (GLuint, const GLuint *); GLAPI void APIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *); GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint); GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint); GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum, GLenum); GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum, GLenum); GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum); GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum); GLAPI GLuint APIENTRY glBindParameterEXT (GLenum); GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint, GLenum); GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *); GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *); GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *); GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *); GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void); typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void); typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr); typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr); typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr); typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr); typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr); typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr); typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr); typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr); typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value); typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data); typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); #endif #ifndef GL_ATI_vertex_streams #define GL_ATI_vertex_streams 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertexStream1sATI (GLenum, GLshort); GLAPI void APIENTRY glVertexStream1svATI (GLenum, const GLshort *); GLAPI void APIENTRY glVertexStream1iATI (GLenum, GLint); GLAPI void APIENTRY glVertexStream1ivATI (GLenum, const GLint *); GLAPI void APIENTRY glVertexStream1fATI (GLenum, GLfloat); GLAPI void APIENTRY glVertexStream1fvATI (GLenum, const GLfloat *); GLAPI void APIENTRY glVertexStream1dATI (GLenum, GLdouble); GLAPI void APIENTRY glVertexStream1dvATI (GLenum, const GLdouble *); GLAPI void APIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort); GLAPI void APIENTRY glVertexStream2svATI (GLenum, const GLshort *); GLAPI void APIENTRY glVertexStream2iATI (GLenum, GLint, GLint); GLAPI void APIENTRY glVertexStream2ivATI (GLenum, const GLint *); GLAPI void APIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat); GLAPI void APIENTRY glVertexStream2fvATI (GLenum, const GLfloat *); GLAPI void APIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble); GLAPI void APIENTRY glVertexStream2dvATI (GLenum, const GLdouble *); GLAPI void APIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexStream3svATI (GLenum, const GLshort *); GLAPI void APIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint); GLAPI void APIENTRY glVertexStream3ivATI (GLenum, const GLint *); GLAPI void APIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexStream3fvATI (GLenum, const GLfloat *); GLAPI void APIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexStream3dvATI (GLenum, const GLdouble *); GLAPI void APIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort); GLAPI void APIENTRY glVertexStream4svATI (GLenum, const GLshort *); GLAPI void APIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint); GLAPI void APIENTRY glVertexStream4ivATI (GLenum, const GLint *); GLAPI void APIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glVertexStream4fvATI (GLenum, const GLfloat *); GLAPI void APIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glVertexStream4dvATI (GLenum, const GLdouble *); GLAPI void APIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte); GLAPI void APIENTRY glNormalStream3bvATI (GLenum, const GLbyte *); GLAPI void APIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort); GLAPI void APIENTRY glNormalStream3svATI (GLenum, const GLshort *); GLAPI void APIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint); GLAPI void APIENTRY glNormalStream3ivATI (GLenum, const GLint *); GLAPI void APIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glNormalStream3fvATI (GLenum, const GLfloat *); GLAPI void APIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glNormalStream3dvATI (GLenum, const GLdouble *); GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum); GLAPI void APIENTRY glVertexBlendEnviATI (GLenum, GLint); GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum, GLfloat); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords); typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz); typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); #endif #ifndef GL_ATI_element_array #define GL_ATI_element_array 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glElementPointerATI (GLenum, const GLvoid *); GLAPI void APIENTRY glDrawElementArrayATI (GLenum, GLsizei); GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer); typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); #endif #ifndef GL_SUN_mesh_array #define GL_SUN_mesh_array 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width); #endif #ifndef GL_SUN_slice_accum #define GL_SUN_slice_accum 1 #endif #ifndef GL_NV_multisample_filter_hint #define GL_NV_multisample_filter_hint 1 #endif #ifndef GL_NV_depth_clamp #define GL_NV_depth_clamp 1 #endif #ifndef GL_NV_occlusion_query #define GL_NV_occlusion_query 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *); GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *); GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint); GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint); GLAPI void APIENTRY glEndOcclusionQueryNV (void); GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void); typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); #endif #ifndef GL_NV_point_sprite #define GL_NV_point_sprite 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPointParameteriNV (GLenum, GLint); GLAPI void APIENTRY glPointParameterivNV (GLenum, const GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params); #endif #ifndef GL_NV_texture_shader3 #define GL_NV_texture_shader3 1 #endif #ifndef GL_NV_vertex_program1_1 #define GL_NV_vertex_program1_1 1 #endif #ifndef GL_EXT_shadow_funcs #define GL_EXT_shadow_funcs 1 #endif #ifndef GL_EXT_stencil_two_side #define GL_EXT_stencil_two_side 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); #endif #ifndef GL_ATI_text_fragment_shader #define GL_ATI_text_fragment_shader 1 #endif #ifndef GL_APPLE_client_storage #define GL_APPLE_client_storage 1 #endif #ifndef GL_APPLE_element_array #define GL_APPLE_element_array 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glElementPointerAPPLE (GLenum, const GLvoid *); GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei); GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei); GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei); GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer); typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); #endif #ifndef GL_APPLE_fence #define GL_APPLE_fence 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGenFencesAPPLE (GLsizei, GLuint *); GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *); GLAPI void APIENTRY glSetFenceAPPLE (GLuint); GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint); GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint); GLAPI void APIENTRY glFinishFenceAPPLE (GLuint); GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum, GLuint); GLAPI void APIENTRY glFinishObjectAPPLE (GLenum, GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences); typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences); typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence); typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence); typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence); typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); #endif #ifndef GL_APPLE_vertex_array_object #define GL_APPLE_vertex_array_object 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint); GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *); GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei, const GLuint *); GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); #endif #ifndef GL_APPLE_vertex_array_range #define GL_APPLE_vertex_array_range 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *); GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *); GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); #endif #ifndef GL_APPLE_ycbcr_422 #define GL_APPLE_ycbcr_422 1 #endif #ifndef GL_S3_s3tc #define GL_S3_s3tc 1 #endif #ifndef GL_ATI_draw_buffers #define GL_ATI_draw_buffers 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDrawBuffersATI (GLsizei, const GLenum *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs); #endif #ifndef GL_ATI_pixel_format_float #define GL_ATI_pixel_format_float 1 /* This is really a WGL extension, but defines some associated GL enums. * ATI does not export "GL_ATI_pixel_format_float" in the GL_EXTENSIONS string. */ #endif #ifndef GL_ATI_texture_env_combine3 #define GL_ATI_texture_env_combine3 1 #endif #ifndef GL_ATI_texture_float #define GL_ATI_texture_float 1 #endif #ifndef GL_NV_float_buffer #define GL_NV_float_buffer 1 #endif #ifndef GL_NV_fragment_program #define GL_NV_fragment_program 1 /* Some NV_fragment_program entry points are shared with ARB_vertex_program. */ #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat); GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble); GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *); GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *); GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *); GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); #endif #ifndef GL_NV_half_float #define GL_NV_half_float 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertex2hNV (GLhalfNV, GLhalfNV); GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *); GLAPI void APIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *); GLAPI void APIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *); GLAPI void APIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *); GLAPI void APIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *); GLAPI void APIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *); GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV); GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *); GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV); GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *); GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *); GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *); GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV); GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *); GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *); GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *); GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *); GLAPI void APIENTRY glFogCoordhNV (GLhalfNV); GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *); GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *); GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV); GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *); GLAPI void APIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV); GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *); GLAPI void APIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *); GLAPI void APIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *); GLAPI void APIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *); GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *); GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *); GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *); GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y); typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z); typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s); typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t); typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r); typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s); typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t); typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v); typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); #endif #ifndef GL_NV_pixel_data_range #define GL_NV_pixel_data_range 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *); GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); #endif #ifndef GL_NV_primitive_restart #define GL_NV_primitive_restart 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPrimitiveRestartNV (void); GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void); typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); #endif #ifndef GL_NV_texture_expand_normal #define GL_NV_texture_expand_normal 1 #endif #ifndef GL_NV_vertex_program2 #define GL_NV_vertex_program2 1 #endif #ifndef GL_ATI_map_object_buffer #define GL_ATI_map_object_buffer 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint); GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); #endif #ifndef GL_ATI_separate_stencil #define GL_ATI_separate_stencil 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum); GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); #endif #ifndef GL_ATI_vertex_attrib_array_object #define GL_ATI_vertex_attrib_array_object 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint); GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *); GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params); #endif #ifndef GL_OES_read_format #define GL_OES_read_format 1 #endif #ifndef GL_EXT_depth_bounds_test #define GL_EXT_depth_bounds_test 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDepthBoundsEXT (GLclampd, GLclampd); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); #endif #ifndef GL_EXT_texture_mirror_clamp #define GL_EXT_texture_mirror_clamp 1 #endif #ifndef GL_EXT_blend_equation_separate #define GL_EXT_blend_equation_separate 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum, GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); #endif #ifndef GL_MESA_pack_invert #define GL_MESA_pack_invert 1 #endif #ifndef GL_MESA_ycbcr_texture #define GL_MESA_ycbcr_texture 1 #endif #ifndef GL_EXT_pixel_buffer_object #define GL_EXT_pixel_buffer_object 1 #endif #ifndef GL_NV_fragment_program_option #define GL_NV_fragment_program_option 1 #endif #ifndef GL_NV_fragment_program2 #define GL_NV_fragment_program2 1 #endif #ifndef GL_NV_vertex_program2_option #define GL_NV_vertex_program2_option 1 #endif #ifndef GL_NV_vertex_program3 #define GL_NV_vertex_program3 1 #endif #ifndef GL_EXT_framebuffer_object #define GL_EXT_framebuffer_object 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint); GLAPI void APIENTRY glBindRenderbufferEXT (GLenum, GLuint); GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei, const GLuint *); GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei, GLuint *); GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum, GLenum, GLsizei, GLsizei); GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum, GLenum, GLint *); GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint); GLAPI void APIENTRY glBindFramebufferEXT (GLenum, GLuint); GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei, const GLuint *); GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei, GLuint *); GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum); GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum, GLenum, GLenum, GLuint, GLint); GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum, GLenum, GLenum, GLuint, GLint); GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLint); GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum, GLenum, GLenum, GLuint); GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum, GLenum, GLenum, GLint *); GLAPI void APIENTRY glGenerateMipmapEXT (GLenum); #endif /* GL_GLEXT_PROTOTYPES */ typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); #endif #ifndef GL_GREMEDY_string_marker #define GL_GREMEDY_string_marker 1 #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string); #endif #ifndef GL_EXT_Cg_shader #define GL_EXT_Cg_shader 1 #endif #ifndef GL_NV_element_array #define GL_NV_element_array 1 #ifdef GL_GLEXT_PROTOTYPES extern void APIENTRY glElementPointerNV(GLenum type, const GLvoid *pointer); extern void APIENTRY glDrawElementArrayNV(GLenum mode, GLint first, GLsizei count); extern void APIENTRY glDrawRangeElementArrayNV(GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); extern void APIENTRY glMultiDrawElementArrayNV(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); extern void APIENTRY glMultiDrawRangeElementArrayNV(GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); #endif typedef void (APIENTRY * PFNGLELEMENTPOINTERNVPROC) (GLenum type, const GLvoid *pointer); typedef void (APIENTRY * PFNGLDRAWELEMENTARRAYNVPROC) (GLenum mode, GLint first, GLsizei count); typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTARRAYNVPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); typedef void (APIENTRY * PFNGLMULTIDRAWELEMENTARRAYNVPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); typedef void (APIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYNVPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); #endif #ifndef GL_NV_pixel_buffer_object #define GL_NV_pixel_buffer_object 1 #endif #ifndef GL_NV_stencil_two_side #define GL_NV_stencil_two_side 1 #ifdef GL_GLEXT_PROTOTYPES extern void APIENTRY glActiveStencilFaceNV(GLenum face); #endif typedef void (APIENTRY * PFNGLACTIVESTENCILFACENVPROC) (GLenum face); #endif #ifdef __cplusplus } #endif #endif mapserver-6.4.1/opengl/wglext.h0000644002461700001440000007105712261257215016275 0ustar tbonfortusers#ifndef __wglext_h_ #define __wglext_h_ #ifdef __cplusplus extern "C" { #endif /* ** License Applicability. Except to the extent portions of this file are ** made subject to an alternative license as permitted in the SGI Free ** Software License B, Version 1.1 (the "License"), the contents of this ** file are subject only to the provisions of the License. You may not use ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: ** ** http://oss.sgi.com/projects/FreeB ** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. ** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. ** ** Additional Notice Provisions: This software was created using the ** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has ** not been independently verified as being compliant with the OpenGL(R) ** version 1.2.1 Specification. */ #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) #define WIN32_LEAN_AND_MEAN 1 #include #endif #ifndef APIENTRY #define APIENTRY #endif #ifndef APIENTRYP #define APIENTRYP APIENTRY * #endif #ifndef GLAPI #define GLAPI extern #endif /*************************************************************/ /* Header file version number */ /* wglext.h last updated 2005/01/07 */ /* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ #define WGL_WGLEXT_VERSION 6 #ifndef WGL_ARB_buffer_region #define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 #define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 #define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 #define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 #endif #ifndef WGL_ARB_multisample #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 #endif #ifndef WGL_ARB_extensions_string #endif #ifndef WGL_ARB_pixel_format #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_BITMAP_ARB 0x2002 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NEED_PALETTE_ARB 0x2004 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 #define WGL_SWAP_METHOD_ARB 0x2007 #define WGL_NUMBER_OVERLAYS_ARB 0x2008 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 #define WGL_TRANSPARENT_ARB 0x200A #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B #define WGL_SHARE_DEPTH_ARB 0x200C #define WGL_SHARE_STENCIL_ARB 0x200D #define WGL_SHARE_ACCUM_ARB 0x200E #define WGL_SUPPORT_GDI_ARB 0x200F #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_STEREO_ARB 0x2012 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 #define WGL_GREEN_BITS_ARB 0x2017 #define WGL_GREEN_SHIFT_ARB 0x2018 #define WGL_BLUE_BITS_ARB 0x2019 #define WGL_BLUE_SHIFT_ARB 0x201A #define WGL_ALPHA_BITS_ARB 0x201B #define WGL_ALPHA_SHIFT_ARB 0x201C #define WGL_ACCUM_BITS_ARB 0x201D #define WGL_ACCUM_RED_BITS_ARB 0x201E #define WGL_ACCUM_GREEN_BITS_ARB 0x201F #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_AUX_BUFFERS_ARB 0x2024 #define WGL_NO_ACCELERATION_ARB 0x2025 #define WGL_GENERIC_ACCELERATION_ARB 0x2026 #define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_SWAP_EXCHANGE_ARB 0x2028 #define WGL_SWAP_COPY_ARB 0x2029 #define WGL_SWAP_UNDEFINED_ARB 0x202A #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_TYPE_COLORINDEX_ARB 0x202C #endif #ifndef WGL_ARB_make_current_read #define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 #endif #ifndef WGL_ARB_pbuffer #define WGL_DRAW_TO_PBUFFER_ARB 0x202D #define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E #define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F #define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 #define WGL_PBUFFER_LARGEST_ARB 0x2033 #define WGL_PBUFFER_WIDTH_ARB 0x2034 #define WGL_PBUFFER_HEIGHT_ARB 0x2035 #define WGL_PBUFFER_LOST_ARB 0x2036 #endif #ifndef WGL_ARB_render_texture #define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 #define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 #define WGL_TEXTURE_FORMAT_ARB 0x2072 #define WGL_TEXTURE_TARGET_ARB 0x2073 #define WGL_MIPMAP_TEXTURE_ARB 0x2074 #define WGL_TEXTURE_RGB_ARB 0x2075 #define WGL_TEXTURE_RGBA_ARB 0x2076 #define WGL_NO_TEXTURE_ARB 0x2077 #define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 #define WGL_TEXTURE_1D_ARB 0x2079 #define WGL_TEXTURE_2D_ARB 0x207A #define WGL_MIPMAP_LEVEL_ARB 0x207B #define WGL_CUBE_MAP_FACE_ARB 0x207C #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 #define WGL_FRONT_LEFT_ARB 0x2083 #define WGL_FRONT_RIGHT_ARB 0x2084 #define WGL_BACK_LEFT_ARB 0x2085 #define WGL_BACK_RIGHT_ARB 0x2086 #define WGL_AUX0_ARB 0x2087 #define WGL_AUX1_ARB 0x2088 #define WGL_AUX2_ARB 0x2089 #define WGL_AUX3_ARB 0x208A #define WGL_AUX4_ARB 0x208B #define WGL_AUX5_ARB 0x208C #define WGL_AUX6_ARB 0x208D #define WGL_AUX7_ARB 0x208E #define WGL_AUX8_ARB 0x208F #define WGL_AUX9_ARB 0x2090 #endif #ifndef WGL_ARB_pixel_format_float #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 #endif #ifndef WGL_EXT_make_current_read #define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 #endif #ifndef WGL_EXT_pixel_format #define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 #define WGL_DRAW_TO_WINDOW_EXT 0x2001 #define WGL_DRAW_TO_BITMAP_EXT 0x2002 #define WGL_ACCELERATION_EXT 0x2003 #define WGL_NEED_PALETTE_EXT 0x2004 #define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 #define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 #define WGL_SWAP_METHOD_EXT 0x2007 #define WGL_NUMBER_OVERLAYS_EXT 0x2008 #define WGL_NUMBER_UNDERLAYS_EXT 0x2009 #define WGL_TRANSPARENT_EXT 0x200A #define WGL_TRANSPARENT_VALUE_EXT 0x200B #define WGL_SHARE_DEPTH_EXT 0x200C #define WGL_SHARE_STENCIL_EXT 0x200D #define WGL_SHARE_ACCUM_EXT 0x200E #define WGL_SUPPORT_GDI_EXT 0x200F #define WGL_SUPPORT_OPENGL_EXT 0x2010 #define WGL_DOUBLE_BUFFER_EXT 0x2011 #define WGL_STEREO_EXT 0x2012 #define WGL_PIXEL_TYPE_EXT 0x2013 #define WGL_COLOR_BITS_EXT 0x2014 #define WGL_RED_BITS_EXT 0x2015 #define WGL_RED_SHIFT_EXT 0x2016 #define WGL_GREEN_BITS_EXT 0x2017 #define WGL_GREEN_SHIFT_EXT 0x2018 #define WGL_BLUE_BITS_EXT 0x2019 #define WGL_BLUE_SHIFT_EXT 0x201A #define WGL_ALPHA_BITS_EXT 0x201B #define WGL_ALPHA_SHIFT_EXT 0x201C #define WGL_ACCUM_BITS_EXT 0x201D #define WGL_ACCUM_RED_BITS_EXT 0x201E #define WGL_ACCUM_GREEN_BITS_EXT 0x201F #define WGL_ACCUM_BLUE_BITS_EXT 0x2020 #define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 #define WGL_DEPTH_BITS_EXT 0x2022 #define WGL_STENCIL_BITS_EXT 0x2023 #define WGL_AUX_BUFFERS_EXT 0x2024 #define WGL_NO_ACCELERATION_EXT 0x2025 #define WGL_GENERIC_ACCELERATION_EXT 0x2026 #define WGL_FULL_ACCELERATION_EXT 0x2027 #define WGL_SWAP_EXCHANGE_EXT 0x2028 #define WGL_SWAP_COPY_EXT 0x2029 #define WGL_SWAP_UNDEFINED_EXT 0x202A #define WGL_TYPE_RGBA_EXT 0x202B #define WGL_TYPE_COLORINDEX_EXT 0x202C #endif #ifndef WGL_EXT_pbuffer #define WGL_DRAW_TO_PBUFFER_EXT 0x202D #define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E #define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F #define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 #define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 #define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 #define WGL_PBUFFER_LARGEST_EXT 0x2033 #define WGL_PBUFFER_WIDTH_EXT 0x2034 #define WGL_PBUFFER_HEIGHT_EXT 0x2035 #endif #ifndef WGL_EXT_depth_float #define WGL_DEPTH_FLOAT_EXT 0x2040 #endif #ifndef WGL_3DFX_multisample #define WGL_SAMPLE_BUFFERS_3DFX 0x2060 #define WGL_SAMPLES_3DFX 0x2061 #endif #ifndef WGL_EXT_multisample #define WGL_SAMPLE_BUFFERS_EXT 0x2041 #define WGL_SAMPLES_EXT 0x2042 #endif #ifndef WGL_I3D_digital_video_control #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 #define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 #define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 #endif #ifndef WGL_I3D_gamma #define WGL_GAMMA_TABLE_SIZE_I3D 0x204E #define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F #endif #ifndef WGL_I3D_genlock #define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 #define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 #define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 #define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 #define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 #define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 #define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A #define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B #define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C #endif #ifndef WGL_I3D_image_buffer #define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 #define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 #endif #ifndef WGL_I3D_swap_frame_lock #endif #ifndef WGL_NV_render_depth_texture #define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 #define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 #define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 #define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 #define WGL_DEPTH_COMPONENT_NV 0x20A7 #endif #ifndef WGL_NV_render_texture_rectangle #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 #define WGL_TEXTURE_RECTANGLE_NV 0x20A2 #endif #ifndef WGL_ATI_pixel_format_float #define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 #define WGL_RGBA_FLOAT_MODE_ATI 0x8820 #define WGL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 #endif #ifndef WGL_NV_float_buffer #define WGL_FLOAT_COMPONENTS_NV 0x20B0 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 #define WGL_TEXTURE_FLOAT_R_NV 0x20B5 #define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 #define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 #define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 #endif #ifndef WGL_NV_swap_group #endif /*************************************************************/ #ifndef WGL_ARB_pbuffer DECLARE_HANDLE(HPBUFFERARB); #endif #ifndef WGL_EXT_pbuffer DECLARE_HANDLE(HPBUFFEREXT); #endif #ifndef WGL_ARB_buffer_region #define WGL_ARB_buffer_region 1 #ifdef WGL_WGLEXT_PROTOTYPES extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); #endif #ifndef WGL_ARB_multisample #define WGL_ARB_multisample 1 #endif #ifndef WGL_ARB_extensions_string #define WGL_ARB_extensions_string 1 #ifdef WGL_WGLEXT_PROTOTYPES extern const char * WINAPI wglGetExtensionsStringARB (HDC); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); #endif #ifndef WGL_ARB_pixel_format #define WGL_ARB_pixel_format 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); #endif #ifndef WGL_ARB_make_current_read #define WGL_ARB_make_current_read 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); extern HDC WINAPI wglGetCurrentReadDCARB (void); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); #endif #ifndef WGL_ARB_pbuffer #define WGL_ARB_pbuffer 1 #ifdef WGL_WGLEXT_PROTOTYPES extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); #endif #ifndef WGL_ARB_render_texture #define WGL_ARB_render_texture 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int); extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int); extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); #endif #ifndef WGL_ARB_pixel_format_float #define WGL_ARB_pixel_format_float 1 #endif #ifndef WGL_EXT_display_color_table #define WGL_EXT_display_color_table 1 #ifdef WGL_WGLEXT_PROTOTYPES extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); #endif #ifndef WGL_EXT_extensions_string #define WGL_EXT_extensions_string 1 #ifdef WGL_WGLEXT_PROTOTYPES extern const char * WINAPI wglGetExtensionsStringEXT (void); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); #endif #ifndef WGL_EXT_make_current_read #define WGL_EXT_make_current_read 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); extern HDC WINAPI wglGetCurrentReadDCEXT (void); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); #endif #ifndef WGL_EXT_pbuffer #define WGL_EXT_pbuffer 1 #ifdef WGL_WGLEXT_PROTOTYPES extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); #endif #ifndef WGL_EXT_pixel_format #define WGL_EXT_pixel_format 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); #endif #ifndef WGL_EXT_swap_control #define WGL_EXT_swap_control 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglSwapIntervalEXT (int); extern int WINAPI wglGetSwapIntervalEXT (void); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); #endif #ifndef WGL_EXT_depth_float #define WGL_EXT_depth_float 1 #endif #ifndef WGL_NV_vertex_array_range #define WGL_NV_vertex_array_range 1 #ifdef WGL_WGLEXT_PROTOTYPES extern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); extern void WINAPI wglFreeMemoryNV (void *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); #endif #ifndef WGL_3DFX_multisample #define WGL_3DFX_multisample 1 #endif #ifndef WGL_EXT_multisample #define WGL_EXT_multisample 1 #endif #ifndef WGL_OML_sync_control #define WGL_OML_sync_control 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *); extern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *); extern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64); extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64); extern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *); extern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); #endif #ifndef WGL_I3D_digital_video_control #define WGL_I3D_digital_video_control 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *); extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); #endif #ifndef WGL_I3D_gamma #define WGL_I3D_gamma 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *); extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *); extern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *); extern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); #endif #ifndef WGL_I3D_genlock #define WGL_I3D_genlock 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglEnableGenlockI3D (HDC); extern BOOL WINAPI wglDisableGenlockI3D (HDC); extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *); extern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT); extern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *); extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT); extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *); extern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT); extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *); extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT); extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *); extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource); typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge); typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate); typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); #endif #ifndef WGL_I3D_image_buffer #define WGL_I3D_image_buffer 1 #ifdef WGL_WGLEXT_PROTOTYPES extern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT); extern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID); extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT); extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); #endif #ifndef WGL_I3D_swap_frame_lock #define WGL_I3D_swap_frame_lock 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglEnableFrameLockI3D (void); extern BOOL WINAPI wglDisableFrameLockI3D (void); extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *); extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); #endif #ifndef WGL_I3D_swap_frame_usage #define WGL_I3D_swap_frame_usage 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglGetFrameUsageI3D (float *); extern BOOL WINAPI wglBeginFrameTrackingI3D (void); extern BOOL WINAPI wglEndFrameTrackingI3D (void); extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, float *); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); #endif #ifndef WGL_ATI_pixel_format_float #define WGL_ATI_pixel_format_float 1 #endif #ifndef WGL_NV_render_depth_texture #define WGL_NV_render_depth_texture 1 #endif #ifndef WGL_NV_render_texture_rectangle #define WGL_NV_render_texture_rectangle 1 #endif #ifndef WGL_NV_float_buffer #define WGL_NV_float_buffer 1 #endif #ifndef WGL_NV_swap_group #define WGL_NV_swap_group 1 #ifdef WGL_WGLEXT_PROTOTYPES extern BOOL WINAPI wglJoinSwapGroupNV(HDC hDC, GLuint group); extern BOOL WINAPI wglBindSwapBarrierNV(GLuint group, GLuint barrier); extern BOOL WINAPI wglQuerySwapGroupNV(HDC hDC GLuint *group, GLuint *barrier); extern BOOL WINAPI wglQueryMaxSwapGroupsNV(HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); extern BOOL WINAPI wglQueryFrameCountNV(HDC hDC, GLuint *count); extern BOOL WINAPI wglResetFrameCountNV(HDC hDC); #endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier); typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count); typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); #endif #ifdef __cplusplus } #endif #endif mapserver-6.4.1/maptemplate.h0000644002461700001440000001412612261257215016002 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Template processing related declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPTEMPLATE_H #define MAPTEMPLATE_H #include "mapserver.h" #include "maphash.h" #define IDPATTERN "^[0-9A-Za-z]{1,63}$" #define IDSIZE 64 #define TEMPLATE_TYPE(s) (((strncmp("http://", s, 7) == 0) || (strncmp("https://", s, 8) == 0) || (strncmp("ftp://", s, 6)) == 0) ? MS_URL : MS_FILE) #define MAXZOOM 25 #define MINZOOM -25 #define DEFAULT_DATE_FORMAT "%d/%b/%Y:%H:%M:%S %z" enum coordSources {NONE, FROMIMGPNT, FROMIMGBOX, FROMIMGSHAPE, FROMREFPNT, FROMUSERPNT, FROMUSERBOX, FROMUSERSHAPE, FROMBUF, FROMSCALE, FROMTILE}; enum modes {BROWSE, ZOOMIN, ZOOMOUT, MAP, LEGEND, LEGENDICON, REFERENCE, SCALEBAR, COORDINATE, QUERY, NQUERY, ITEMQUERY, ITEMNQUERY, FEATUREQUERY, FEATURENQUERY, ITEMFEATUREQUERY, ITEMFEATURENQUERY, INDEXQUERY, TILE, OWS, WFS, MAPLEGEND, MAPLEGENDICON }; /* struct mapservObj * Global structure used by templates and mapserver CGI interface. * * This structur was created to seperate template functionality * from the main mapserv file. Instead of moving all template * related functions in a new file (maptemplate.c) and change * their signatures to pass all global variables, we created this * structure with all global variables needed by template. */ typedef struct { /* should the query and/or map be saved */ int savemap, savequery; cgiRequestObj *request; int sendheaders; /* should mime-type header be output, default will be MS_TRUE */ mapObj *map; char **Layers; char *icon; /* layer:class combination that defines a legend icon */ int NumLayers; /* number of layers specfied by a use */ int MaxLayers; /* Allocated size of Layers[] array */ layerObj *resultlayer; int UseShapes; /* are results of a query to be used in calculating an extent of some sort */ shapeObj resultshape; rectObj RawExt; pointObj mappnt; double fZoom, Zoom; int ZoomDirection; /* whether zooming in or out, default is pan or 0 */ int Mode; /* can be BROWSE, QUERY, etc. */ int TileMode; /* can be GMAP, VE */ char *TileCoords; /* for GMAP: 0 0 1; for VE: 013021023 */ char Id[IDSIZE]; /* big enough for time + pid */ int CoordSource; double ScaleDenom; /* used to create a map extent around a point */ int ImgRows, ImgCols; rectObj ImgExt; /* Existing image's mapextent */ rectObj ImgBox; pointObj RefPnt; pointObj ImgPnt; double Buffer; int SearchMap; /* apply pan/zoom BEFORE doing the query (e.g. query the output image rather than the input image) */ char *QueryFile; char *QueryLayer; char *SelectLayer; int QueryLayerIndex; int SelectLayerIndex; char *QueryItem; char *QueryString; int ShapeIndex; int TileIndex; int QueryCoordSource; int ZoomSize; /* zoom absolute magnitude (i.e. > 0) */ /* ** variables for multiple query results processing */ int RN; /* overall result number */ int LRN; /* result number within a layer */ int NL; /* total number of layers with results */ int NR; /* total number or results */ int NLR; /* number of results in a layer */ map_hittest *hittest; } mapservObj; /*! \fn msAllocMapServObj * Allocate memory for all variables in strusture * and initiate default values */ MS_DLL_EXPORT mapservObj* msAllocMapServObj(void); /*! \fn msFreeMapServObj * free all variables in structure */ MS_DLL_EXPORT void msFreeMapServObj(mapservObj* msObj); /* For Mapserv.c */ MS_DLL_EXPORT int isOn(mapservObj* msObj, char *name, char *group); MS_DLL_EXPORT int checkWebScale(mapservObj *msObj); MS_DLL_EXPORT int setExtent(mapservObj *msObj); MS_DLL_EXPORT int msReturnPage(mapservObj* msObj, char* , int, char **); MS_DLL_EXPORT int msReturnURL(mapservObj* msObj, char*, int); MS_DLL_EXPORT int msReturnNestedTemplateQuery(mapservObj* msObj, char* pszMimeType, char **papszBuffer); MS_DLL_EXPORT int msReturnTemplateQuery(mapservObj *msObj, char* pszMimeType, char **papszBuffer); MS_DLL_EXPORT int msReturnOpenLayersPage(mapservObj *mapserv); MS_DLL_EXPORT int msRedirect(char* url); MS_DLL_EXPORT char *generateLegendTemplate(mapservObj *msObj); MS_DLL_EXPORT int msGenerateImages(mapservObj *msObj, int bQueryMap, int bReturnOnError); MS_DLL_EXPORT char *msProcessTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries); MS_DLL_EXPORT char *msProcessLegendTemplate(mapObj *map, char **names, char **values, int numentries); MS_DLL_EXPORT char *msProcessQueryTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries); MS_DLL_EXPORT int msGrowMapservLayers( mapservObj* msObj ); #endif mapserver-6.4.1/mapogcfilter.h0000644002461700001440000001533112261257215016144 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Filter Encoding implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #ifndef MAPOGCFILTER_H #define MAPOGCFILTER_H #include "mapserver.h" /*dont need ogr for these functikons*/ MS_DLL_EXPORT int FLTIsNumeric(char *pszValue); MS_DLL_EXPORT int FLTApplyExpressionToLayer(layerObj *lp, char *pszExpression); MS_DLL_EXPORT char *FLTGetExpressionForValuesRanges(layerObj *lp, char *item, char *value, int forcecharcter); #ifdef USE_OGR /* There is a dependency to OGR for the MiniXML parser */ #include "cpl_minixml.h" #ifdef USE_LIBXML2 #include #include #endif typedef struct { char *pszWildCard; char *pszSingleChar; char *pszEscapeChar; int bCaseInsensitive; } FEPropertyIsLike; /* -------------------------------------------------------------------- */ /* prototypes. */ /* -------------------------------------------------------------------- */ MS_DLL_EXPORT FilterEncodingNode *FLTParseFilterEncoding(char *szXMLString); MS_DLL_EXPORT FilterEncodingNode *FLTCreateFilterEncodingNode(void); MS_DLL_EXPORT int FLTApplyFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT int FLTLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT void FLTFreeFilterEncodingNode(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTValidFilterNode(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTValidForBBoxFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTNumberOfFilterType(FilterEncodingNode *psFilterNode, const char *szType); MS_DLL_EXPORT int FLTIsBBoxFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsPointFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsLineFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsPolygonFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTValidForPropertyIsLikeFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT char *FLTGetMapserverIsPropertyExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT int FLTIsOnlyPropertyIsLike(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT void FLTInsertElementInNode(FilterEncodingNode *psFilterNode, CPLXMLNode *psXMLNode); MS_DLL_EXPORT int FLTIsLogicalFilterType(char *pszValue); MS_DLL_EXPORT int FLTIsBinaryComparisonFilterType(char *pszValue); MS_DLL_EXPORT int FLTIsComparisonFilterType(char *pszValue); MS_DLL_EXPORT int FLTIsFeatureIdFilterType(char *pszValue); MS_DLL_EXPORT int FLTIsSpatialFilterType(char *pszValue); MS_DLL_EXPORT int FLTIsSupportedFilterType(CPLXMLNode *psXMLNode); MS_DLL_EXPORT char *FLTGetMapserverExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetNodeExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetBBOX(FilterEncodingNode *psFilterNode, rectObj *psRect); MS_DLL_EXPORT shapeObj *FLTGetShape(FilterEncodingNode *psFilterNode, double *pdfDistance, int *pnUnit); MS_DLL_EXPORT char *FLTGetLogicalComparisonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetBinaryComparisonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetIsBetweenComparisonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetIsLikeComparisonExpression(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTHasSpatialFilter(FilterEncodingNode *psFilterNode); /*SQL expressions related functions.*/ MS_DLL_EXPORT int FLTApplySimpleSQLFilter(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT char *FLTGetSQLExpression(FilterEncodingNode *psFilterNode,layerObj *lp); MS_DLL_EXPORT char *FLTGetBinaryComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetIsBetweenComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetIsLikeComparisonSQLExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetLogicalComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT int FLTIsSimpleFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT FilterEncodingNode *FLTCreateFeatureIdFilterEncoding(char *pszString); MS_DLL_EXPORT int FLTParseEpsgString(char *pszEpsg, projectionObj *psProj); MS_DLL_EXPORT int FLTParseGMLEnvelope(CPLXMLNode *psRoot, rectObj *psBbox, char **ppszSRS); MS_DLL_EXPORT int FLTParseGMLBox(CPLXMLNode *psBox, rectObj *psBbox, char **ppszSRS); /*common-expressions*/ MS_DLL_EXPORT char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, char *pszExpression); #ifdef USE_LIBXML2 MS_DLL_EXPORT xmlNodePtr FLTGetCapabilities(xmlNsPtr psNsParent, xmlNsPtr psNsOgc, int bTemporal); #endif void FLTPreParseFilterForAlias(FilterEncodingNode *psFilterNode, mapObj *map, int i, const char *namespaces); #endif #endif mapserver-6.4.1/README0000644002461700001440000000633412261257215014202 0ustar tbonfortusers------- Summary ------- MapServer is a system for developing web-based GIS applications. The basic system consists of a CGI program that can be configured to respond to a variety of spatial requests like making maps, scalebars, and point, area and feature queries. Virtually all aspects of an application, from web interface to map appearance can be developed without any programming. For the more ambitious user, MapServer applications can be enhanced using Java, JavaScript or many other web technologies. For more information and complete documentation please visit: http://www.mapserver.org/ Bug reports and enhancment submissions can be reported in the MapServer issue tracker at the following url. If you do make changes and/or enhancements, please let us know so that they might be incorporated into future releases. https://github.com/mapserver/mapserver/issues Join the MapServer user mailing list online at: http://www.mapserver.org/community/lists.html ----------- Credits ----------- MapServer was originally written by Stephen Lime. Major funding for development of MapServer has been provided by NASA through cooperative argreements with the University of Minnesota, Department of Forest Resources. PHP/MapScript developed by DM Solutions Group. GDAL/OGR support and significant WMS support provided by DM Solutions Group which received funding support from Canadian Government's GeoConnections Program and the Canadian Forest Service. Raster support developed by Pete Olson of the State of Minnesota, Land Management Information Center, and maintained by Frank Warmerdam (DM Solutions). PostGIS spatial database support provided by Dave Blasby of Refractions Research. PDF support developed by Jeff Spielberg and Jamie Wall of Market Insite Group, Inc. OracleSpatial support developed by Rodrigo Cabral of CTTMAR/UNIVALI, Brazil. Portions Copyright (c) 1998 State of Minnesota, Land Management Information Center. Portions derived from Shapelib, Copyright 1995-1999 Frank Warmerdam. Supporting packages are covered by their own copyrights. ----------- License ----------- :: 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. mapserver-6.4.1/maporaclespatial.c0000644002461700001440000037024512261257215017014 0ustar tbonfortusers/****************************************************************************** * Project: MapServer * Purpose: Native access to Oracle Spatial (SDO) data. * Author: Fernando Simon (fsimon@univali.br) * Rodrigo Becke Cabral * Adriana Gomes Alves * * Notes: Developed under several funding agreements: * * 1) n.45/00 between CTTMAR/UNIVALI (www.cttmar.univali.br) * and CEPSUL/IBAMA (www.ibama.gov.br) * * 2) CNPq (www.cnpq.br) under process 401263.03-7 * * 3) FUNCITEC (www.funcitec.rct-sc.br) under process FCTP1523-031 * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ #include "mapserver.h" #include #if defined(USE_ORACLESPATIAL) || defined(USE_ORACLE_PLUGIN) #include #include #define ARRAY_SIZE 1024 #define QUERY_SIZE 1 #define TEXT_SIZE 4000 /* ticket #2260 */ #define TYPE_OWNER "MDSYS" #define SDO_GEOMETRY TYPE_OWNER".SDO_GEOMETRY" #define SDO_ORDINATE_ARRAY TYPE_OWNER".SDO_ORDINATE_ARRAY" #define SDO_GEOMETRY_LEN strlen( SDO_GEOMETRY ) #define FUNCTION_FILTER 1 #define FUNCTION_RELATE 2 #define FUNCTION_GEOMRELATE 3 #define FUNCTION_NONE 4 #define VERSION_8i 1 #define VERSION_9i 2 #define VERSION_10g 3 #define TOLERANCE 0.001 #define NULLERRCODE 1405 #define TABLE_NAME_SIZE 2000 typedef struct { OCINumber x; OCINumber y; OCINumber z; } SDOPointObj; typedef struct { OCINumber gtype; OCINumber srid; SDOPointObj point; OCIArray *elem_info; OCIArray *ordinates; } SDOGeometryObj; typedef struct { OCIInd _atomic; OCIInd x; OCIInd y; OCIInd z; } SDOPointInd; typedef struct { OCIInd _atomic; OCIInd gtype; OCIInd srid; SDOPointInd point; OCIInd elem_info; OCIInd ordinates; } SDOGeometryInd; typedef text item_text[TEXT_SIZE]; typedef item_text item_text_array[ARRAY_SIZE]; typedef item_text item_text_array_query[QUERY_SIZE]; typedef struct { /*Oracle handlers (global to connection)*/ OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; int last_oci_status; text last_oci_error[2048]; /* This references counter is to avoid the cache freed if there are other layers that could use it */ int ref_count; } msOracleSpatialHandler; typedef struct { /* Oracle data handlers (global to connection) */ OCIDescribe *dschp; OCIType *tdo; } msOracleSpatialDataHandler; typedef struct { OCIStmt *stmthp; /* fetch data buffer */ ub4 rows_count; /* total number of rows (so far) within cursor */ ub4 row_num; /* current row index within cursor results */ ub4 rows_fetched; /* total number of rows fetched into our buffer */ ub4 row; /* current row index within our buffer */ item_text_array *items; /* items buffer */ item_text_array_query *items_query; /* items buffer */ SDOGeometryObj *obj[ARRAY_SIZE]; /* spatial object buffer */ SDOGeometryInd *ind[ARRAY_SIZE]; /* object indicator (null) buffer */ int uniqueidindex; /*allows to keep whic attribute id index is used as unique id*/ } msOracleSpatialStatement; typedef struct { /* oracle handlers */ msOracleSpatialHandler *orahandlers; /* oracle data handlers */ msOracleSpatialDataHandler *oradatahandlers; msOracleSpatialStatement *orastmt; /* Following items are setup by WhichShapes * used by NextShape, ResultGetShape * disposed by CloseLayer (if set) */ msOracleSpatialStatement *orastmt2; /* Driver handling of pagination, enabled by default */ int paging; } msOracleSpatialLayerInfo; /* local prototypes */ static int TRY( msOracleSpatialHandler *hand, sword status ); static int ERROR( char *routine, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ); static void msSplitLogin( char *connection, mapObj *map, char **username, char **password, char **dblink ); static int msSplitData( char *data, char **geometry_column_name, char **table_name, char **unique, char **srid, int *function, int * version); static void msOCICloseConnection( void *layerinfo ); static msOracleSpatialHandler *msOCISetHandlers( char *username, char *password, char *dblink ); static int msOCISetDataHandlers( msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ); static void msOCICloseDataHandlers ( msOracleSpatialDataHandler *dthand ); static void msOCICloseHandlers( msOracleSpatialHandler *hand ); static void msOCIClearLayerInfo( msOracleSpatialLayerInfo *layerinfo ); static int msOCIOpenStatement( msOracleSpatialHandler *hand, msOracleSpatialStatement *sthand ); static void msOCIFinishStatement( msOracleSpatialStatement *sthand ); static int msOCIGet2DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIGet3DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIGet4DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIConvertCircle( pointObj *pt ); static void osFilteritem(layerObj *layer, int function, char *query_str, size_t size, int mode); static void osAggrGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name); static void osConvexHullGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name); static void osGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect); static void osNoGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect); static double osCalculateArcRadius(pointObj *pnt); static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double area, double radius, double npoints, int side, lineObj arcline, shapeObj *shape); static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points, int i, int n, int data3d, int data4d); static void osShapeBounds ( shapeObj *shp ); static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d, int data4d); static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int interpretation, int data3d, int data4d); static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int elem_type, int data3d, int data4d); static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj arcpoints,int elem_type,int data3d, int data4d); static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, SDOGeometryInd *ind); static int osCheck2DGtype(int pIntGtype); static int osCheck3DGtype(int pIntGtype); static int osCheck4DGtype(int pIntGtype); /****************************************************************************** * Local Helper Functions * ******************************************************************************/ /* if an error ocurred call msSetError, sets last_oci_status to MS_FAILURE and return 0; * otherwise returns 1 */ static int TRY( msOracleSpatialHandler *hand, sword status ) { sb4 errcode = 0; if (hand->last_oci_status == MS_FAILURE) return 0; /* error from previous call */ switch (status) { case OCI_SUCCESS_WITH_INFO: case OCI_ERROR: OCIErrorGet((dvoid *)hand->errhp, (ub4)1, (text *)NULL, &errcode, hand->last_oci_error, (ub4)sizeof(hand->last_oci_error), OCI_HTYPE_ERROR ); if (errcode == NULLERRCODE) { hand->last_oci_error[0] = (text)'\0'; return 1; } hand->last_oci_error[sizeof(hand->last_oci_error)-1] = 0; /* terminate string!? */ break; case OCI_NEED_DATA: strlcpy( (char *)hand->last_oci_error, "OCI_NEED_DATA", sizeof(hand->last_oci_error)); break; case OCI_INVALID_HANDLE: strlcpy( (char *)hand->last_oci_error, "OCI_INVALID_HANDLE", sizeof(hand->last_oci_error)); break; case OCI_STILL_EXECUTING: ((char*)hand->last_oci_error)[sizeof(hand->last_oci_error)-1] = 0; break; case OCI_CONTINUE: strlcpy( (char *)hand->last_oci_error, "OCI_CONTINUE", sizeof(hand->last_oci_error)); break; default: return 1; /* no error */ } /* if I got here, there was an error */ hand->last_oci_status = MS_FAILURE; return 0; /* error! */ } OCIType *get_tdo(char *typename, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ) { OCIParam *paramp = NULL; OCIRef *type_ref = NULL; OCIType *tdoe = NULL; int success = 0; success = TRY( hand, OCIDescribeAny(hand->svchp, hand->errhp, (text *)typename, (ub4)strlen((char *)typename), OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE, dthand->dschp)) &&TRY( hand, OCIAttrGet((dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (dvoid *)¶mp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, hand->errhp)) &&TRY( hand, OCIAttrGet((dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp)) &&TRY( hand, OCIObjectPin(hand->envhp, hand->errhp, type_ref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&tdoe)); if (success) return tdoe; /* if failure, return NULL*/ return NULL; } /* check last_oci_status for MS_FAILURE (set by TRY()) if an error ocurred return 1; * otherwise, returns 0 */ static int ERROR( char *routine, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ) { if (hand->last_oci_status == MS_FAILURE) { /* there was an error */ msSetError( MS_ORACLESPATIALERR, "%s", routine, (char *)hand->last_oci_error); /* reset error flag */ hand->last_oci_status = MS_SUCCESS; return 1; /* error processed */ } else return 0; /* no error */ } /* break layer->connection (username/password@dblink) into username, password and dblink */ static void msSplitLogin( char *connection, mapObj *map, char **username, char **password, char **dblink ) { char *src, *tgt, *conn_decrypted; size_t buffer_size = 0; /* bad 'connection' */ if (connection == NULL) return; buffer_size = strlen(connection)+1; *username = (char*)malloc(buffer_size); *password = (char*)malloc(buffer_size); *dblink = (char*)malloc(buffer_size); /* clearup */ **username = **password = **dblink = 0; /* Decrypt any encrypted token */ conn_decrypted = msDecryptStringTokens(map, connection); if (conn_decrypted == NULL) return; /* ok, split connection */ for( tgt=*username, src=conn_decrypted; *src; src++, tgt++ ) if (*src=='/' || *src=='@') break; else *tgt = *src; *tgt = 0; if (*src == '/') { for( tgt=*password, ++src; *src; src++, tgt++ ) if (*src == '@') break; else *tgt = *src; *tgt = 0; } if (*src == '@') { strlcpy( *dblink, ++src, buffer_size); } msFree(conn_decrypted); } /* break layer->data into geometry_column_name, table_name and srid */ static int msSplitData( char *data, char **geometry_column_name, char **table_name, char **unique, char **srid, int *function, int *version ) { char *tok_from = "from"; char *tok_using = "using"; char *tok_unique = "unique"; char *tok_srid = "srid"; char *tok_version = "version"; char data_version[4] = ""; char tok_function[11] = ""; int parenthesis, i; char *src = data, *tgt; int table_name_size = TABLE_NAME_SIZE; size_t buffer_size = 0; /* bad 'data' */ if (data == NULL) return 0; buffer_size = strlen(data)+1; *geometry_column_name = (char*)malloc(buffer_size); *unique = (char*)malloc(buffer_size); *srid = (char*)malloc(buffer_size); /* clearup */ **geometry_column_name = **table_name = 0; /* parsing 'geometry_column_name' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=*geometry_column_name; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; /* parsing 'from' */ for( ; *src && isspace( *src ); src++ ) ; /* skip blanks */ for( ; *src && *tok_from && tolower(*src)==*tok_from; src++, tok_from++ ); if (*tok_from != '\0') return 0; /* parsing 'table_name' or '(SELECT stmt)' */ i = 0; for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=*table_name, parenthesis=0; *src; src++, tgt++, ++i ) { if (*src == '(') parenthesis++; else if (*src == ')') parenthesis--; else if (parenthesis==0 && isspace( *src )) break; /* stop on spaces */ /* double the size of the table_name array if necessary */ if (i == table_name_size) { table_name_size *= 2; *table_name = (char *) realloc(*table_name,sizeof(char *) * table_name_size); } *tgt = *src; } *tgt = 0; strlcpy( *unique, "", buffer_size); strlcpy( *srid, "NULL", buffer_size); *function = -1; *version = -1; /* parsing 'unique' */ for( ; *src && isspace( *src ); src++ ) ; /* skip blanks */ if (*src != '\0') { /* parse 'using' */ for( ; *src && *tok_using && tolower(*src)==*tok_using; src++, tok_using++ ); if (*tok_using != '\0') return 0; /* parsing 'unique' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( ; *src && *tok_unique && tolower(*src)==*tok_unique; src++, tok_unique++ ); if (*tok_unique == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*unique; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_unique != '\0') return 0; } /* parsing 'srid' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( ; *src && *tok_srid && tolower(*src)==*tok_srid; src++, tok_srid++ ); if (*tok_srid == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*srid; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_srid != '\0') return 0; } /*parsing function/version */ for( ; *src && isspace( *src ); src++ ); if (*src != '\0') { for( tgt=tok_function; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; } /*Upcase conversion for the FUNCTION/VERSION token*/ for (i=0; tok_function[i] != '\0'; i++) tok_function[i] = toupper(tok_function[i]); if (strcmp(tok_function, "VERSION")) { if (!strcmp(tok_function, "FILTER") || !strcmp(tok_function, "")) *function = FUNCTION_FILTER; else if(!strcmp(tok_function, "RELATE")) *function = FUNCTION_RELATE; else if (!strcmp(tok_function,"GEOMRELATE")) *function = FUNCTION_GEOMRELATE; else if (!strcmp(tok_function,"NONE")) *function = FUNCTION_NONE; else { *function = -1; return 0; } /*parsing VERSION token when user defined one function*/ for( ; *src && isspace( *src ); src++ ); for( ; *src && *tok_version && tolower(*src)==*tok_version; src++, tok_version++ ); } else { for(tgt = "VERSION"; *tgt && *tok_version && toupper(*tgt)==toupper(*tok_version); tgt++, tok_version++ ); *function = FUNCTION_FILTER; } /*parsing version*/ if (*tok_version == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=data_version; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; for (i=0; data_version[i] != '\0'; i++) data_version[i] = tolower(data_version[i]); if (!strcmp(data_version, "8i")) *version = VERSION_8i; else if(!strcmp(data_version, "9i")) *version = VERSION_9i; else if (!strcmp(data_version, "10g")) *version = VERSION_10g; else return 0; } } /* finish parsing */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ return (*src == '\0'); } /****************************************************************************** * OCI Helper Functions * ******************************************************************************/ /* create statement handle from database connection */ static int msOCIOpenStatement( msOracleSpatialHandler *hand, msOracleSpatialStatement *sthand) { int success = 0; /* allocate stmthp */ success = TRY( hand, OCIHandleAlloc( (dvoid *)hand->envhp, (dvoid **)&sthand->stmthp, (ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0 ) ); sthand->rows_count = 0; sthand->row_num = 0; sthand->rows_fetched = 0; sthand->row = 0; sthand->items = NULL; sthand->items_query = NULL; /* fprintf(stderr, "Creating statement handle at %p\n", sthand->stmthp); */ return success; } /* create statement handle from database connection */ static void msOCIFinishStatement( msOracleSpatialStatement *sthand ) { if(sthand != NULL) { /* fprintf(stderr, "Freeing statement handle at %p\n", sthand->stmthp); */ if (sthand->stmthp != NULL) OCIHandleFree( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT ); if (sthand->items != NULL) free( sthand->items ); if (sthand->items_query != NULL) free( sthand->items_query ); memset(sthand, 0, sizeof( msOracleSpatialStatement ) ); free(sthand); } } static int msOCISetDataHandlers(msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand) { int success = 0; OCIParam *paramp = NULL; OCIRef *type_ref = NULL; success = TRY( hand, /* allocate dschp */ OCIHandleAlloc( hand->envhp, (dvoid **)&dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (size_t)0, (dvoid **)0 ) ) && TRY( hand, /* describe SDO_GEOMETRY in svchp (dschp) */ OCIDescribeAny( hand->svchp, hand->errhp, (text *)SDO_GEOMETRY, (ub4)SDO_GEOMETRY_LEN, OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE, dthand->dschp ) ) && TRY( hand, /* get param for SDO_GEOMETRY */ OCIAttrGet( (dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (dvoid *)¶mp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, hand->errhp ) ) && TRY( hand, /* get type_ref for SDO_GEOMETRY */ OCIAttrGet( (dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp ) ) && TRY( hand, /* get TDO for SDO_GEOMETRY */ OCIObjectPin( hand->envhp, hand->errhp, type_ref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&dthand->tdo ) ); return success; } /* connect to database */ static msOracleSpatialHandler *msOCISetHandlers( char *username, char *password, char *dblink ) { int success; msOracleSpatialHandler *hand = NULL; hand = (msOracleSpatialHandler *) malloc( sizeof(msOracleSpatialHandler)); if (hand == NULL) { msSetError(MS_MEMERR, NULL, "msOCISetHandlers()"); return NULL; } memset( hand, 0, sizeof(msOracleSpatialHandler) ); hand->ref_count = 1; hand->last_oci_status = MS_SUCCESS; hand->last_oci_error[0] = (text)'\0'; success = TRY( hand, /* allocate envhp */ #ifdef USE_THREAD OCIEnvCreate( &hand->envhp, OCI_OBJECT|OCI_THREADED, (dvoid *)0, 0, 0, 0, (size_t) 0, (dvoid **)0 ) ) #else OCIEnvCreate( &hand->envhp, OCI_OBJECT, (dvoid *)0, 0, 0, 0, (size_t) 0, (dvoid **)0 ) ) #endif && TRY( hand, /* allocate errhp */ OCIHandleAlloc( (dvoid *)hand->envhp, (dvoid **)&hand->errhp, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 ) ) && TRY( hand, /* logon */ OCILogon( hand->envhp, hand->errhp, &hand->svchp, (text *)username, strlen(username), (text *)password, strlen(password), (text *)dblink, strlen(dblink) ) ); if ( !success ) { msSetError( MS_ORACLESPATIALERR, "Cannot create OCI Handlers. " "Connection failure. Check the connection string. " "Error: %s.", "msOracleSpatialLayerOpen()", hand->last_oci_error); msOCICloseHandlers(hand); return NULL; } return hand; } /* disconnect from database */ static void msOCICloseHandlers( msOracleSpatialHandler *hand ) { if (hand->svchp != NULL) OCILogoff( hand->svchp, hand->errhp ); if (hand->errhp != NULL) OCIHandleFree( (dvoid *)hand->errhp, (ub4)OCI_HTYPE_ERROR ); if (hand->envhp != NULL) OCIHandleFree( (dvoid *)hand->envhp, (ub4)OCI_HTYPE_ENV ); if (hand != NULL) memset( hand, 0, sizeof (msOracleSpatialHandler)); free(hand); } static void msOCICloseDataHandlers( msOracleSpatialDataHandler *dthand ) { if (dthand->dschp != NULL) OCIHandleFree( (dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE ); if (dthand != NULL) memset( dthand, 0, sizeof (msOracleSpatialDataHandler)); free(dthand); } static void msOCIClearLayerInfo( msOracleSpatialLayerInfo *layerinfo ) { if (layerinfo != NULL) { memset( layerinfo, 0, sizeof( msOracleSpatialLayerInfo ) ); free(layerinfo); } } /*function that creates the correct sql for geoditical srid for version 9i*/ static void osGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect) { switch (function) { case FUNCTION_FILTER: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates ), :srid)," "'querytype=window') = 'TRUE'", geom_column_name); break; } case FUNCTION_RELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_RELATE( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates ), :srid)," "'mask=anyinteract querytype=window') = 'TRUE'", geom_column_name); break; } case FUNCTION_GEOMRELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_GEOM.RELATE( %s, 'anyinteract', SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates), :srid)," "%f) = 'TRUE' AND %s IS NOT NULL", geom_column_name, TOLERANCE, geom_column_name ); break; } case FUNCTION_NONE: { break; } default: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates), :srid)," "'querytype=window') = 'TRUE'", geom_column_name ); } } } /*function that generate the correct sql for no geoditic srid's*/ static void osNoGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect) { switch (function) { case FUNCTION_FILTER: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," /* "MDSYS.SDO_ORDINATE_ARRAY(%.9g,%.9g,%.9g,%.9g)" */ ":ordinates" " ),'querytype=window') = 'TRUE'", geom_column_name); break; } case FUNCTION_RELATE: { if (version == VERSION_10g) { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_ANYINTERACT( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)) = 'TRUE'", geom_column_name); } else { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_RELATE( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "'mask=anyinteract querytype=window') = 'TRUE'", geom_column_name); } break; } case FUNCTION_GEOMRELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_GEOM.RELATE( %s, 'anyinteract', MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "%f) = 'TRUE' AND %s IS NOT NULL", geom_column_name, TOLERANCE, geom_column_name ); break; } case FUNCTION_NONE: { break; } default: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "'querytype=window') = 'TRUE'", geom_column_name); } } } /* get ordinates from SDO buffer */ static int msOCIGet2DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=2, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ); if (success) { pt[n].x = x; pt[n].y = y; } } return success ? n : 0; } static int msOCIGet3DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; #ifdef USE_POINT_Z_M double z; boolean numnull; #endif /* USE_POINT_Z_M */ OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=3, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ) #ifdef USE_POINT_Z_M && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) #endif /* USE_POINT_Z_M */ ; #ifdef USE_POINT_Z_M if (success) { success = TRY(hand, OCINumberIsZero( hand->errhp, oci_number, (boolean *)&numnull)); if (success) { success = TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&z ) ); } else { hand->last_oci_status = MS_SUCCESS; strlcpy( (char *)hand->last_oci_error, "Retrieve z value, but NULL value for z. Setting z to 0.", sizeof(hand->last_oci_error)); z = 0; success = 1; } } #endif /* USE_POINT_Z_M */ if (success) { pt[n].x = x; pt[n].y = y; #ifdef USE_POINT_Z_M pt[n].z = z; #endif /* USE_POINT_Z_M */ } } return success ? n : 0; } static int msOCIGet4DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; #ifdef USE_POINT_Z_M double z; boolean numnull; #endif /* USE_POINT_Z_M */ OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=4, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ) #ifdef USE_POINT_Z_M && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) #endif /* USE_POINT_Z_M */ ; #ifdef USE_POINT_Z_M if (success) { success = TRY(hand, OCINumberIsZero( hand->errhp, oci_number, (boolean *)&numnull)); if (success) { success = TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&z ) ); } else { hand->last_oci_status = MS_SUCCESS; strlcpy( (char *)hand->last_oci_error, "Retrieve z value, but NULL value for z. Setting z to 0.", sizeof(hand->last_oci_error)); z = 0; success = 1; } } #endif /* USE_POINT_Z_M */ if (success) { pt[n].x = x; pt[n].y = y; #ifdef USE_POINT_Z_M pt[n].z = z; #endif /* USE_POINT_Z_M */ } } return success ? n : 0; } /* convert three-point circle to two-point rectangular bounds */ static int msOCIConvertCircle( pointObj *pt ) { pointObj ptaux; double dXa, dXb; double ma, mb; double cx, cy, r; int success; dXa = pt[1].x - pt[0].x; success = (fabs( dXa ) > 1e-8); if (!success) { /* switch points 1 & 2 */ ptaux = pt[1]; pt[1] = pt[2]; pt[2] = ptaux; dXa = pt[1].x - pt[0].x; success = (fabs( dXa ) > 1e-8); } if (success) { dXb = pt[2].x - pt[1].x; success = (fabs( dXb ) > 1e-8); if (!success) { /* insert point 2 before point 0 */ ptaux = pt[2]; pt[2] = pt[1]; pt[1] = pt[0]; pt[0] = ptaux; dXb = dXa; /* segment A has become B */ dXa = pt[1].x - pt[0].x; /* recalculate new segment A */ success = (fabs( dXa ) > 1e-8); } } if (success) { ma = (pt[1].y - pt[0].y)/dXa; mb = (pt[2].y - pt[1].y)/dXb; success = (fabs( mb - ma ) > 1e-8); } if (!success) return 0; /* calculate center and radius */ cx = (ma*mb*(pt[0].y - pt[2].y) + mb*(pt[0].x + pt[1].x) - ma*(pt[1].x + pt[2].x))/(2*(mb - ma)); cy = (fabs( ma ) > 1e-8) ? ((pt[0].y + pt[1].y)/2 - (cx - (pt[0].x + pt[1].x)/2)/ma) : ((pt[1].y + pt[2].y)/2 - (cx - (pt[1].x + pt[2].x)/2)/mb); r = sqrt( pow( pt[0].x - cx, 2 ) + pow( pt[0].y - cy, 2 ) ); /* update pt buffer with rectangular bounds */ pt[0].x = cx - r; pt[0].y = cy - r; pt[1].x = cx + r; pt[1].y = cy + r; return 1; } /*function that creates the correct sql for filter and filteritem*/ static void osFilteritem(layerObj *layer, int function, char *query_str, size_t size, int mode) { if (layer->filter.string != NULL) { if (mode == 1) strlcat( query_str, " WHERE ", size); else strlcat( query_str, " AND ", size); if (layer->filteritem != NULL) { snprintf (query_str + strlen(query_str), size-strlen(query_str), " %s = ", layer->filteritem); /* snprintf (query_str + strlen(query_str), " %s = ", layer->filteritem); */ } snprintf (query_str + strlen(query_str), size-strlen(query_str), " %s ", layer->filter.string); /* snprintf(buffer, n, "gfdg %s %s %s", layer->filter.string, (layer->filteritem != NULL ? layer->filteritem : ""), ); */ if (function != FUNCTION_NONE) snprintf (query_str + strlen(query_str), size-strlen(query_str), " AND "); } else { if (function != FUNCTION_NONE) strlcat( query_str, " WHERE ", size); } } static void osAggrGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name) { char query_str2[6000]; int i = 0; snprintf( query_str2, sizeof(query_str2), "(SELECT"); for( i = 0; i < layer->numitems; ++i ) snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s,", layer->items[i] ); snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s FROM %s", geom_column_name, table_name); osFilteritem(layer, FUNCTION_NONE, query_str2, sizeof(query_str2), 1); snprintf( query_str, size, "SELECT SDO_AGGR_MBR(%s) AS GEOM from %s)", geom_column_name, query_str2); if (layer->debug) msDebug("osAggrGetExtent was called: %s.\n", query_str); } static void osConvexHullGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name) { char query_str2[6000]; int i = 0; snprintf( query_str2, sizeof(query_str2), "(SELECT"); for( i = 0; i < layer->numitems; ++i ) snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s,", layer->items[i] ); snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s FROM %s", geom_column_name, table_name); osFilteritem(layer, FUNCTION_NONE, query_str2, sizeof(query_str2), 1); snprintf( query_str, size, "SELECT SDO_GEOM.SDO_CONVEXHULL(%s, %f) AS GEOM from %s)", geom_column_name, TOLERANCE, query_str2); } static double osCalculateArcRadius(pointObj *pnt) { double rc; double r1, r2, r3; r1 = sqrt( pow(pnt[0].x-pnt[1].x,2) + pow(pnt[0].y-pnt[1].y,2) ); r2 = sqrt( pow(pnt[1].x-pnt[2].x,2) + pow(pnt[1].y-pnt[2].y,2) ); r3 = sqrt( pow(pnt[2].x-pnt[0].x,2) + pow(pnt[2].y-pnt[0].y,2) ); rc = ( r1+r2+r3 )/2; return ( ( r1*r2*r3 )/( 4*sqrt( rc * (rc-r1) * (rc-r2) * (rc-r3) ) ) ); } static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double area, double radius, double npoints, int side, lineObj arcline, shapeObj *shape) { double length, ctrl, angle; double divbas, plusbas, cosbas, sinbas = 0; #ifdef USE_POINT_Z_M double zrange = 0; #endif /* USE_POINT_Z_M */ int i = 0; if ( npoints > 0 ) { length = sqrt(((pnt[1].x-pnt[0].x)*(pnt[1].x-pnt[0].x))+((pnt[1].y-pnt[0].y)*(pnt[1].y-pnt[0].y))); ctrl = length/(2*radius); #ifdef USE_POINT_Z_M if (data3d||data4d) { zrange = labs(pnt[0].z-pnt[1].z)/npoints; if ((pnt[0].z > pnt[1].z) && side == 1) zrange *= -1; else if ((pnt[0].z < pnt[1].z) && side == 1) zrange = zrange; else if ((pnt[0].z > pnt[1].z) && side != 1) zrange *= -1; else if ((pnt[0].z < pnt[1].z) && side != 1) zrange = zrange; } #endif /* USE_POINT_Z_M */ if( ctrl <= 1 ) { divbas = 2 * asin(ctrl); plusbas = divbas/(npoints); cosbas = (pnt[0].x-pnt[3].x)/radius; sinbas = (pnt[0].y-pnt[3].y)/radius; angle = plusbas; arcline.point = (pointObj *)malloc(sizeof(pointObj)*(npoints+1)); arcline.point[0].x = pnt[0].x; arcline.point[0].y = pnt[0].y; #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[0].z = pnt[0].z; #endif /* USE_POINT_Z_M */ for (i = 1; i <= npoints; i++) { if( side == 1) { arcline.point[i].x = pnt[3].x + radius * ((cosbas*cos(angle))-(sinbas*sin(angle))); arcline.point[i].y = pnt[3].y + radius * ((sinbas*cos(angle))+(cosbas*sin(angle))); #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z + (zrange*i); #endif /* USE_POINT_Z_M */ } else { if ( side == -1) { arcline.point[i].x = pnt[3].x + radius * ((cosbas*cos(angle))+(sinbas*sin(angle))); arcline.point[i].y = pnt[3].y + radius * ((sinbas*cos(angle))-(cosbas*sin(angle))); #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z + (zrange*i); #endif /* USE_POINT_Z_M */ } else { arcline.point[i].x = pnt[0].x; arcline.point[i].y = pnt[0].y; #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z; #endif /* USE_POINT_Z_M */ } } angle += plusbas; } arcline.numpoints = npoints+1; msAddLine( shape, &arcline ); free (arcline.point); } } else { arcline.point = (pointObj *)malloc(sizeof(pointObj)*(2)); arcline.point[0].x = pnt[0].x; arcline.point[0].y = pnt[0].y; arcline.point[1].x = pnt[1].x; arcline.point[1].y = pnt[1].y; #ifdef USE_POINT_Z_M if(data3d||data4d) { arcline.point[0].z = pnt[0].z; arcline.point[1].z = pnt[1].z; } #endif /* USE_POINT_Z_M */ arcline.numpoints = 2; msAddLine( shape, &arcline ); free (arcline.point); } } /* Part of this function was based on Terralib function TeGenerateArc * found in TeGeometryAlgorith.cpp (www.terralib.org). * Part of this function was based on Dr. Ialo (Univali/Cttmar) functions. */ static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points, int i, int n, int data3d, int data4d) { double mult, plus1, plus2, plus3, bpoint; double cx, cy; double radius, side, area, npoints; double dist1 = 0; double dist2 = 0; pointObj point5[4]; mult = ( points.point[i+1].x - points.point[i].x ) * ( points.point[i+2].y - points.point[i].y ) - ( points.point[i+1].y - points.point[i].y ) * ( points.point[i+2].x - points.point[i].x ); if (mult) { /*point5 = (pointObj *)malloc(sizeof(pointObj)*(4));*/ plus1 = points.point[i].x * points.point[i].x + points.point[i].y * points.point[i].y; plus2 = points.point[i+1].x * points.point[i+1].x + points.point[i+1].y * points.point[i+1].y; plus3 = points.point[i+2].x * points.point[i+2].x + points.point[i+2].y * points.point[i+2].y; bpoint = plus1 * ( points.point[i+1].y - points.point[i+2].y ) + plus2 * ( points.point[i+2].y - points.point[i].y ) + plus3 * ( points.point[i].y - points.point[i+1].y ); cx = bpoint / (2.0 * mult); bpoint = plus1 * ( points.point[i+2].x - points.point[i+1].x ) + plus2 * ( points.point[i].x - points.point[i+2].x ) + plus3 * ( points.point[i+1].x - points.point[i].x ); cy = bpoint / (2.0 * mult); dist1 = (points.point[i+1].x - points.point[i].x) * (cy - points.point[i].y); dist2 = (points.point[i+1].y - points.point[i].y) * (cx - points.point[i].x); side = 0; if((dist1-dist2) > 0) side = 1; else { if((dist1-dist2) < 0) side = -1; } point5[0] = points.point[i]; point5[1] = points.point[i+1]; point5[2] = points.point[i+2]; point5[3].x = cx; point5[3].y = cy; radius = osCalculateArcRadius(point5); area = ((points.point[i].x + points.point[i+1].x) * (points.point[i+1].y - points.point[i].y)) + ((points.point[i+1].x + points.point[i+2].x) * (points.point[i+2].y - points.point[i+1].y)); npoints = labs(area/radius); point5[0] = points.point[i]; point5[1] = points.point[i+1]; osCalculateArc(point5, data3d, data4d, area, radius, (npoints>1000)?1000:npoints, side, arcline, shape); point5[0] = points.point[i+1]; point5[1] = points.point[i+2]; osCalculateArc(point5, data3d, data4d, area, radius, (npoints>1000)?1000:npoints, side, arcline, shape); } else { arcline.point = (pointObj *)malloc(sizeof(pointObj)*(2)); arcline.point[0].x = points.point[i].x; arcline.point[0].y = points.point[i].y; arcline.point[1].x = points.point[i+2].x; arcline.point[1].y = points.point[i+2].y; #ifdef USE_POINT_Z_M if (data3d||data4d) { arcline.point[0].z = points.point[i].z; arcline.point[1].z = points.point[i+2].z; } #endif /* USE_POINT_Z_M */ arcline.numpoints = 2; msAddLine( shape, &arcline ); free (arcline.point); } } static void osShapeBounds ( shapeObj *shp ) { int i, f; if ( (shp->numlines > 0) && (shp->line[0].numpoints > 0) ) { shp->bounds.minx = shp->line[0].point[0].x; shp->bounds.maxx = shp->line[0].point[0].x; shp->bounds.miny = shp->line[0].point[0].y; shp->bounds.maxy = shp->line[0].point[0].y; } for ( i = 0 ; i < shp->numlines; i++) { for( f = 0; f < shp->line[i].numpoints; f++) { if (shp->line[i].point[f].x < shp->bounds.minx) shp->bounds.minx = shp->line[i].point[f].x; if (shp->line[i].point[f].x > shp->bounds.maxx) shp->bounds.maxx = shp->line[i].point[f].x; if (shp->line[i].point[f].y < shp->bounds.miny) shp->bounds.miny = shp->line[i].point[f].y; if (shp->line[i].point[f].y > shp->bounds.maxy) shp->bounds.maxy = shp->line[i].point[f].y; } } } static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d, int data4d) { int max_points = 0; int i,f,g; lineObj shapeline = {0, NULL}; for (i = 0; i < shape->numlines; i++) max_points += shape->line[i].numpoints; if (max_points > 0) shapeline.point = (pointObj *)malloc( sizeof(pointObj)*max_points ); g = 0; for ( i = 0 ; i < shape->numlines; i++) { for( f = 0; f < shape->line[i].numpoints && g <= max_points; f++, g++) { shapeline.point[g].x = shape->line[i].point[f].x; shapeline.point[g].y = shape->line[i].point[f].y; #ifdef USE_POINT_Z_M if (data3d||data4d) shapeline.point[g].z = shape->line[i].point[f].z; #endif /* USE_POINT_Z_M */ } } if (g) { shapeline.numpoints = g; newshape->type = shape->type; /* jimk: 2009/09/23 Fixes compound linestrings being converted to polygons */ msAddLine( newshape, &shapeline ); } } static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int interpretation, int data3d, int data4d) { int n; n = (end - start)/2; /* n = interpretation; */ /* if (n == interpretation) { */ points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n == interpretation && n>0) { shape->type = MS_SHAPE_POINT; points.numpoints = n; msAddLine( shape, &points ); } free( points.point ); /* } */ } static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 1) { shape->type = MS_SHAPE_POINT; points.numpoints = 1; points.point = pnt; msAddLine( shape, &points ); } } static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int elem_type, int data3d, int data4d) { int n; n = (end - start)/2; points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n > 0) { shape->type = (elem_type==21) ? MS_SHAPE_LINE : MS_SHAPE_POLYGON; points.numpoints = n; msAddLine( shape, &points ); } free( points.point ); } static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 2) { shape->type = MS_SHAPE_POLYGON; points.numpoints = 5; points.point = pnt; /* point5 [0] & [1] contains the lower-left and upper-right points of the rectangle */ pnt[2] = pnt[1]; pnt[1].x = pnt[0].x; pnt[3].x = pnt[2].x; pnt[3].y = pnt[0].y; pnt[4] = pnt[0]; #ifdef USE_POINT_Z_M if (data3d||data4d) { pnt[1].z = pnt[0].z; pnt[3].z = pnt[2].z; } #endif /* USE_POINT_Z_M */ msAddLine( shape, &points ); } } static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 3) { if (msOCIConvertCircle( pnt )) { shape->type = MS_SHAPE_POINT; points.numpoints = 2; points.point = pnt; msAddLine( shape, &points ); } else { strlcpy( (char *)hand->last_oci_error, "Points in circle object are colinear", sizeof(hand->last_oci_error)); hand->last_oci_status = MS_FAILURE; } } } static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj arcpoints, int elem_type, int data3d, int data4d) { int n, i; lineObj points = {0, NULL}; n = (end - start)/2; points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n > 2) { shape->type = (elem_type==32) ? MS_SHAPE_POLYGON : MS_SHAPE_LINE; points.numpoints = n; for (i = 0; i < n-2; i = i+2) osGenerateArc(shape, arcpoints, points, i, n, data3d, data4d); } free (points.point); } static int osCheck2DGtype(int pIntGtype) { if (pIntGtype > 2000 && pIntGtype < 2008) { if (pIntGtype != 2004) return MS_TRUE; } return MS_FALSE; } static int osCheck3DGtype(int pIntGtype) { if (pIntGtype > 3000 && pIntGtype < 3308) { if (pIntGtype > 3007) pIntGtype-= 300; if (pIntGtype <= 3007 && pIntGtype != 3004) return MS_TRUE; } /* * Future version, untested * return (pIntGtype & 2208 && (pIntGtype & 3000 || pIntGtype & 3296) && pIntGtype & 3); */ return MS_FALSE; } static int osCheck4DGtype(int pIntGtype) { if (pIntGtype > 4000 && pIntGtype < 4408) { if (pIntGtype > 4007) pIntGtype-= 400; if (pIntGtype <= 4007 && pIntGtype != 4004) return MS_TRUE; } return MS_FALSE; } static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, SDOGeometryInd *ind) { int gtype, elem_type, compound_type; float compound_lenght, compound_count; ub4 etype; ub4 interpretation; int nelems, nords, data3d, data4d; int elem, ord_start, ord_end; boolean exists; OCINumber *oci_number; double x, y; #ifdef USE_POINT_Z_M double z; #endif /* USE_POINT_Z_M */ int success; lineObj points = {0, NULL}; pointObj point5[5]; /* for quick access */ shapeObj newshape; /* for compound polygons */ /*stat the variables for compound polygons*/ compound_lenght = 0; compound_type = 0; compound_count = -1; data3d = 0; data4d = 0; if (ind->_atomic != OCI_IND_NULL) { /* not a null object */ nelems = nords = 0; success = TRY( hand, OCICollSize( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, &nelems ) ) && TRY( hand, OCICollSize( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, &nords ) ) && TRY( hand, OCINumberToInt( hand->errhp, &(obj->gtype), (uword)sizeof(int), OCI_NUMBER_SIGNED, (dvoid *)>ype ) ); /*&& (nords%2==0 && nelems%3==0);*/ /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ if (success && osCheck2DGtype(gtype)) { success = (nords%2==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ } else if (success && osCheck3DGtype(gtype)) { success = (nords%3==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ data3d = 1; } else if (success && osCheck4DGtype(gtype)) { success = (nords%4==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ data4d = 1; } if (success) { /* reading SDO_POINT from SDO_GEOMETRY for a 2D/3D point geometry */ if ((gtype==2001 || gtype==3001 || gtype==4001 ) && ind->point._atomic == OCI_IND_NOTNULL && ind->point.x == OCI_IND_NOTNULL && ind->point.y == OCI_IND_NOTNULL) { success = TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.x), (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.y), (uword)sizeof(double), (dvoid *)&y ) ); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; shape->type = MS_SHAPE_POINT; points.numpoints = 1; points.point = point5; point5[0].x = x; point5[0].y = y; #ifdef USE_POINT_Z_M if (data3d || data4d) { if (ind->point.z == OCI_IND_NOTNULL) { success = TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.z), (uword)sizeof(double), (dvoid *)&z )); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; else point5[0].z = z; } else point5[0].z = z; } #endif /* USE_POINT_Z_M */ msAddLine( shape, &points ); return MS_SUCCESS; } /* if SDO_POINT not fetched, proceed reading elements (element info/ordinates) */ success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info,(sb4)0, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_SIGNED, (dvoid *)&ord_end ) ); elem = 0; ord_end--; /* shifts offset from 1..n to 0..n-1 */ do { ord_start = ord_end; if (elem+3 >= nelems) { /* processing last element */ ord_end = nords; success = 1; } else { /* get start ordinate position for next element which is ord_end for this element */ success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+3, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_SIGNED, (dvoid *)&ord_end ) ); ord_end--; /* shifts offset from 1..n to 0..n-1 */ } success = (success && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *)&etype ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *)&interpretation ) )); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; if ( etype == 1005 || etype == 2005 || etype == 4 ) { compound_type = 1; compound_lenght = interpretation; compound_count = 0; msInitShape(&newshape); } elem_type = (etype == 1 && interpretation > 1) ? 10 : ((etype%10)*10 + interpretation); /* msDebug("osGetOrdinates shape->index = %ld\telem_type = %d\n",shape->index, elem_type); */ switch (elem_type) { case 10: /* point cluster with 'interpretation'-points */ osPointCluster (hand, shape, obj, ord_start, ord_end, points, interpretation, data3d, data4d); break; case 11: /* point type */ osPoint(hand, shape, obj, ord_start, ord_end, points, point5, data3d, data4d); break; case 21: /* line string whose vertices are connected by straight line segments */ if (compound_type) osClosedPolygon(hand, &newshape, obj, ord_start, (compound_count= compound_lenght) { osCloneShape(&newshape, shape, data3d, data4d); msFreeShape(&newshape); } if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; /* prepare for next cycle */ ord_start = ord_end; elem += 3; if (compound_type) compound_count++; } while (elem < nelems); /* end of element loop */ } /* end of gtype big-if */ } /* end of not-null-object if */ if (compound_type) msFreeShape(&newshape); return MS_SUCCESS; } static void msOCICloseConnection( void *hand ) { msOCICloseHandlers( (msOracleSpatialHandler *)hand ); } /* opens a layer by connecting to db with username/password@database stored in layer->connection */ int msOracleSpatialLayerOpen( layerObj *layer ) { char *username = NULL, *password = NULL, *dblink = NULL; msOracleSpatialLayerInfo *layerinfo = NULL; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialStatement *sthand = NULL, *sthand2 = NULL; msOracleSpatialHandler *hand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerOpen called with: %s (Layer pointer %p)\n",layer->data, layer); if (layer->layerinfo != NULL) /* Skip if layer is already open */ return MS_SUCCESS; if (layer->data == NULL) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be:" "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'." "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE.", "msOracleSpatialLayerOpen()"); return MS_FAILURE; } layerinfo = (msOracleSpatialLayerInfo *)malloc(sizeof(msOracleSpatialLayerInfo)); dthand = (msOracleSpatialDataHandler *)malloc(sizeof(msOracleSpatialDataHandler)); sthand = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement)); sthand2 = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement)); if ((dthand == NULL) || (layerinfo == NULL)) { msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerOpen()"); return MS_FAILURE; } memset( dthand, 0, sizeof(msOracleSpatialDataHandler) ); memset( sthand, 0, sizeof(msOracleSpatialStatement) ); memset( sthand2, 0, sizeof(msOracleSpatialStatement) ); memset( layerinfo, 0, sizeof(msOracleSpatialLayerInfo) ); layerinfo->paging = MS_TRUE; msSplitLogin( layer->connection, layer->map, &username, &password, &dblink ); hand = (msOracleSpatialHandler *) msConnPoolRequest( layer ); if( hand == NULL ) { hand = msOCISetHandlers( username, password, dblink ); if (hand == NULL) { msOCICloseDataHandlers( dthand ); msOCIFinishStatement( sthand ); msOCIFinishStatement( sthand2 ); msOCIClearLayerInfo( layerinfo ); if (username) free(username); if (password) free(password); if (dblink) free(dblink); return MS_FAILURE; } if ( layer->debug ) msDebug("msOracleSpatialLayerOpen. Shared connection not available. Creating one.\n"); msConnPoolRegister( layer, hand, msOCICloseConnection ); } else { hand->ref_count++; hand->last_oci_status = MS_SUCCESS; hand->last_oci_error[0] = (text)'\0'; } if (!(msOCISetDataHandlers(hand, dthand) & msOCIOpenStatement(hand, sthand) & msOCIOpenStatement(hand, sthand2))) { msSetError( MS_ORACLESPATIALERR, "Cannot create OCI LayerInfo. " "Connection failure.", "msOracleSpatialLayerOpen()"); if (layer->debug) msDebug("msOracleSpatialLayerOpen. Cannot create OCI LayerInfo. Connection failure.\n"); msOCICloseDataHandlers ( dthand ); msOCICloseHandlers( hand ); msOCIClearLayerInfo( layerinfo ); } layerinfo->orahandlers = hand; layerinfo->oradatahandlers = dthand; layerinfo->orastmt = sthand; layerinfo->orastmt2 = sthand2; layer->layerinfo = layerinfo; if (username) free(username); if (password) free(password); if (dblink) free(dblink); return layer->layerinfo != NULL ? MS_SUCCESS : MS_FAILURE; } /* return MS_TRUE if layer is open, MS_FALSE otherwise.*/ int msOracleSpatialLayerIsOpen(layerObj *layer) { if (layer->layerinfo != NULL) return MS_TRUE; return MS_FALSE; } /* closes the layer, disconnecting from db if connected. layer->layerinfo is freed */ int msOracleSpatialLayerClose( layerObj *layer ) { msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; /*int lIntSuccessFree = 0;*/ if (layer->debug) msDebug("msOracleSpatialLayerClose was called. Layer: %p, Layer name: %s. Layer connection: %s\n", layer, layer->name, layer->connection); if (layerinfo != NULL) { /* * Some errors with the OCIObjectFree with query function * If uncomment draw mode will work but no query modes * Need to investigate the error cause */ /*lIntSuccessFree = TRY (layerinfo->orahandlers, OCIObjectFree(layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp, (dvoid *)layerinfo->obj, (ub2)OCI_OBJECTFREE_FORCE)); *if (!lIntSuccessFree) * msDebug("Error: %s\n", layerinfo->orahandlers->last_oci_error); */ /* Release Statement Handles */ if (layerinfo->orastmt != NULL) { msOCIFinishStatement(layerinfo->orastmt); layerinfo->orastmt = NULL; } if (layerinfo->orastmt2 != NULL) { msOCIFinishStatement(layerinfo->orastmt2); layerinfo->orastmt2 = NULL; } /* Release Datahandlers */ if (layer->debug) msDebug("msOracleSpatialLayerClose. Cleaning layerinfo handlers.\n"); msOCICloseDataHandlers( layerinfo->oradatahandlers ); layerinfo->oradatahandlers = NULL; /* Free the OCI cache only if there is no more layer that could use it */ layerinfo->orahandlers->ref_count--; if (layerinfo->orahandlers->ref_count == 0) OCICacheFree (layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp, layerinfo->orahandlers->svchp); /* Release Mapserver Pool */ if (layer->debug) msDebug("msOracleSpatialLayerClose. Release the Oracle Pool.\n"); msConnPoolRelease( layer, layerinfo->orahandlers ); /* Release Layerinfo */ layerinfo->orahandlers = NULL; msOCIClearLayerInfo( layerinfo ); layer->layerinfo = NULL; } return MS_SUCCESS; } /* create SQL statement for retrieving shapes */ /* Sets up cursor for use in *NextShape and *GetShape */ int msOracleSpatialLayerWhichShapes( layerObj *layer, rectObj rect, int isQuery) { int success, i; int function = 0; int version = 0; char query_str[6000]; char query_str2[256]; char *tmp_str=NULL, *tmp1_str=NULL; char *table_name; char *geom_column_name = NULL, *unique = NULL, *srid = NULL; OCIDefine *adtp = NULL; OCIDefine **items = NULL; OCINumber oci_number; OCIBind *bnd1p = NULL, *bnd2p = NULL; OCIType *ordinates_tdo = NULL; OCIArray *ordinates = NULL; int existunique = MS_FALSE; int rownumisuniquekey = MS_FALSE; int numitemsinselect = 0; /* get layerinfo */ msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerWhichShapes called on unopened layer", "msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; } /*init uniqueindex field*/ sthand->uniqueidindex=0; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); /* parse geom_column_name and table_name */ if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version)) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be:" "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'." "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE." "Your data statement: %s", "msOracleSpatialLayerWhichShapes()", layer->data ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /*rownum will be the first in the select if no UNIQUE key is defined or will be added at the end of the select*/ rownumisuniquekey = MS_TRUE; /*Define the unique*/ if (unique[0] == '\0') strcpy( unique, "rownum" ); else rownumisuniquekey = MS_FALSE; /* Check if the unique field is already in the items list */ existunique = MS_FALSE; if (unique) { for( i=0; i < layer->numitems; ++i ) { if (strcasecmp(unique, layer->items[i])==0) { sthand->uniqueidindex = i; existunique = MS_TRUE; break; } } } /* If no SRID is provided, set it to -1 (NULL) for binding */ if (strcmp(srid,"NULL") == 0) strcpy(srid,"-1"); snprintf( query_str, sizeof(query_str), "SELECT "); numitemsinselect = layer->numitems; /* allocate enough space for items */ if (layer->numitems >= 0) { /*we will always add a rownumber in the selection*/ numitemsinselect++; /*if unique key in the data is specfied and is not part of the current item lists, we should add it to the select*/ if(existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) numitemsinselect++; /*the usinque index is there was no uniqueid given or the uniqueid given was not part of the items lists*/ if (existunique == MS_FALSE) sthand->uniqueidindex = layer->numitems; sthand->items = (item_text_array *)malloc( sizeof(item_text_array) * (numitemsinselect) ); if (sthand->items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate layerinfo->items buffer","msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } items = (OCIDefine **)malloc(sizeof(OCIDefine *)*(numitemsinselect)); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*(numitemsinselect)); } /* define SQL query */ for( i=0; i < layer->numitems; ++i ) { snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s, ", layer->items[i] ); } /*we add the uniqueid if it was not part of the current item list*/ if(existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s,", unique); /*we always want to add rownum is the selection to allow paging to work*/ snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s, ", "rownum"); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s FROM %s", geom_column_name, table_name ); osFilteritem(layer, function, query_str, sizeof(query_str), 1); if (layerinfo->paging && layer->maxfeatures > 0 && layer->startindex < 0) { if (function == FUNCTION_NONE && layer->filter.string == NULL) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s"," WHERE "); else if (function == FUNCTION_NONE && layer->filter.string != NULL) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s"," AND "); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " ROWNUM<=%d ", layer->maxfeatures); if (function != FUNCTION_NONE) snprintf (query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " AND "); } if ((((atol(srid) >= 8192) && (atol(srid) <= 8330)) || (atol(srid) == 2) || (atol(srid) == 5242888) || (atol(srid) == 2000001)) && (version == VERSION_9i)) osGeodeticData(function, version, query_str, sizeof(query_str), geom_column_name, srid, rect); else osNoGeodeticData(function, version, query_str, sizeof(query_str), geom_column_name, srid, rect); /*assuming startindex starts at 1*/ if (layerinfo->paging && layer->startindex > 0) { tmp1_str = msStrdup("SELECT * from (SELECT atmp.*, ROWNUM rnum from ("); tmp_str = msStringConcatenate(tmp_str, tmp1_str); msFree(tmp1_str); tmp_str = msStringConcatenate(tmp_str, query_str); /*oder by rowid does not seem to work with function using the spatial filter, at least on layers loaded using ogr in a 11g database*/ if (function == FUNCTION_NONE || function == FUNCTION_RELATE || function == FUNCTION_GEOMRELATE) tmp1_str = msStrdup( "order by rowid"); else tmp1_str = msStrdup(""); if (layer->maxfeatures > 0) snprintf(query_str2, sizeof(query_str2), " %s) atmp where ROWNUM<=%d) where rnum >=%d", tmp1_str, layer->maxfeatures+layer->startindex-1, layer->startindex); else snprintf( query_str2, sizeof(query_str2), " %s) atmp) where rnum >=%d", tmp1_str, layer->startindex); msFree(tmp1_str); tmp_str = msStringConcatenate(tmp_str, query_str2); snprintf(query_str, sizeof(query_str), "%s", tmp_str); msFree(tmp_str); } if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes. Using this Sql to retrieve the data: %s\n", query_str); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes. Bind values: srid:%s minx:%f miny:%f maxx:%f maxy:%f \n", srid, rect.minx, rect.miny, rect.maxx, rect.maxy); /* prepare */ success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes getting ordinate definition.\n"); /* get the object definition of the ordinate array */ ordinates_tdo = get_tdo(SDO_ORDINATE_ARRAY, hand, dthand ); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes converting to OCIColl.\n"); /* initialized the collection array */ success = TRY( hand, OCIObjectNew(hand->envhp, hand->errhp, hand->svchp, OCI_TYPECODE_VARRAY, ordinates_tdo, (dvoid *)NULL, OCI_DURATION_SESSION, FALSE, (dvoid **)&ordinates) ); /* convert it to a OCI number and then append minx...maxy to the collection */ success = TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.minx), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.miny), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxx), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxy), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes bind by name and object.\n"); /* do the actual binding */ if (success && function != FUNCTION_NONE) { const char* bind_key; char* bind_value; char* bind_tag; success = TRY( hand, /* bind in srid */ OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *) ":srid", strlen(":srid"),(ub1 *) srid, strlen(srid)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT) ) && TRY(hand, /* bind in rect by name */ OCIBindByName( sthand->stmthp, &bnd1p, hand->errhp, (text *)":ordinates", -1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0,(ub2 *)0, (ub4)0, (ub4 *)0, (ub4)OCI_DEFAULT)) && TRY(hand, /* bind in rect object */ OCIBindObject(bnd1p, hand->errhp, ordinates_tdo, (dvoid **)&ordinates, (ub4 *)0, (dvoid **)0, (ub4 *)0)); /* bind the variables from the bindvals hash */ bind_key = (char*)msFirstKeyFromHashTable(&layer->bindvals); while(bind_key != NULL) { bind_value = msLookupHashTable(&layer->bindvals, bind_key); bind_tag = (char*)malloc(sizeof(char) * strlen(bind_key) + 2); sprintf(bind_tag, ":%s", bind_key); success = success && TRY(hand, OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *)bind_tag, strlen(bind_tag),(ub1 *) bind_value, strlen(bind_value)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)); bind_key = msNextKeyFromHashTable(&layer->bindvals, bind_key); } } if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes name and object now bound.\n"); if (success && layer->numitems >= 0) { for( i=0; i < numitemsinselect && success; ++i ) success = TRY( hand, OCIDefineByPos( sthand->stmthp, &items[i], hand->errhp, (ub4)i+1, (dvoid *)sthand->items[i], (sb4)TEXT_SIZE, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ); } if (success) { int cursor_type = OCI_DEFAULT; if(isQuery) cursor_type =OCI_STMT_SCROLLABLE_READONLY; success = TRY( hand, /* define spatial position adtp ADT object */ OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)numitemsinselect+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, /* define object tdo from adtp */ OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY(hand, /* execute */ OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)cursor_type ) ) && TRY( hand, /* get rows fetched */ OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ) && TRY( hand, /* get rows count */ OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_count, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); } if (!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerWhichShapes()", hand->last_oci_error, query_str ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /* should begin processing first row */ sthand->row_num = sthand->row = 0; /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_SUCCESS; } /* fetch next shape from previous SELECT stmt (see *WhichShape()) */ int msOracleSpatialLayerNextShape( layerObj *layer, shapeObj *shape ) { SDOGeometryObj *obj; SDOGeometryInd *ind; int success, /*lIntSuccessFree,*/ i; /* get layerinfo */ msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerWhichShapes called on unopened layer", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; } /* no rows fetched */ if (sthand->rows_fetched == 0) return MS_DONE; if(layer->debug >=5 ) msDebug("msOracleSpatialLayerNextShape on layer %p, row_num: %d\n", layer, sthand->row_num); do { /* is buffer empty? */ if (sthand->row >= sthand->rows_fetched) { /* fetch more */ success = TRY( hand, OCIStmtFetch2( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_count, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); if (!success || sthand->rows_fetched == 0 || sthand->row_num >= sthand->rows_count) { hand->last_oci_status=MS_SUCCESS; return MS_DONE; } if(layer->debug >= 4 ) msDebug("msOracleSpatialLayerNextShape on layer %p, Fetched %d more rows (%d total)\n", layer, sthand->rows_fetched, sthand->rows_count); sthand->row = 0; /* reset buffer row index */ } /* set obj & ind for current row */ obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->index = atol( (char *)(sthand->items[sthand->uniqueidindex][ sthand->row ])); /* Primary Key */ shape->resultindex = sthand->row_num; shape->numvalues = layer->numitems; shape->values = (char **)malloc( sizeof(char*) * shape->numvalues ); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } for( i=0; i < shape->numvalues; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items[i][ sthand->row ])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { strcpy(shape->values[i], (char *)sthand->items[i][ sthand->row ]); shape->values[i][strlen((char *)sthand->items[i][ sthand->row ])] = '\0'; } } /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); /* increment for next row */ sthand->row_num++; sthand->row++; if (success != MS_SUCCESS) { return MS_FAILURE; } osShapeBounds(shape); } while(shape->type == MS_SHAPE_NULL); return MS_SUCCESS; } int msOracleSpatialLayerGetShape( layerObj *layer, shapeObj *shape, resultObj *record) { int success, i; SDOGeometryObj *obj; SDOGeometryInd *ind; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialLayerInfo *layerinfo; msOracleSpatialStatement *sthand = NULL; long shapeindex = record->shapeindex; int resultindex = record->resultindex; if(layer == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called on unopened layer","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called on unopened layer (layerinfo)","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } /* If resultindex is set, fetch the shape from the resultcache, otherwise fetch it from the DB */ if (resultindex >= 0) { long buffer_first_row_num, buffer_last_row_num; /* get layerinfo */ dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; if (layer->resultcache == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called before msOracleSpatialLayerWhichShapes()","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } if (resultindex >= sthand->rows_count) { if (layer->debug >= 5) msDebug("msOracleSpatialLayerGetShape problem with cursor. Trying to fetch record = %d of %d, falling back to GetShape\n", resultindex, sthand->rows_count); msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape record out of range","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } if (layer->debug >= 5) msDebug("msOracleSpatialLayerGetShape was called. Using the record = %d of %d. (shape: %ld should equal pkey: %ld)\n", resultindex, layer->resultcache->numresults, layer->resultcache->results[resultindex].shapeindex, shapeindex); /* NOTE: with the way the resultcache works, we should see items in increasing order, but some may have been filtered out. */ /* Best case: item in buffer */ /* Next best case: item is in next fetch block */ /* Worst case: item is random access */ buffer_first_row_num = sthand->row_num - sthand->row; /* cursor id of first item in buffer */ buffer_last_row_num = buffer_first_row_num + sthand->rows_fetched - 1; /* cursor id of last item in buffer */ if(resultindex >= buffer_first_row_num && resultindex <= buffer_last_row_num) { /* Item is in buffer. Calculate position in buffer */ sthand->row += resultindex - sthand->row_num; /* move sthand row an row_num by offset from last call */ sthand->row_num += resultindex - sthand->row_num; } else { /* Item is not in buffer. Fetch item from Oracle */ if (layer->debug >= 4) msDebug("msOracleSpatialLayerGetShape: Fetching result from DB start: %ld end:%ld record: %d\n", buffer_first_row_num, buffer_last_row_num, resultindex); success = TRY( hand, OCIStmtFetch2( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_ABSOLUTE, (sb4)resultindex+1, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); sthand->row_num = resultindex; sthand->row = 0; /* reset row index */ if(ERROR("msOracleSpatialLayerGetShape", hand, dthand)) return MS_FAILURE; if (!success || sthand->rows_fetched == 0) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape could not fetch specified record.", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } } /* set obj & ind for current row */ obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->index = shapeindex; /* By definition this is what we asked for */ shape->numvalues = layer->numitems; shape->values = (char **)malloc( sizeof(char*) * shape->numvalues ); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } for( i=0; i < shape->numvalues; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items[i][ sthand->row ])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { strcpy(shape->values[i], (char *)sthand->items[i][ sthand->row ]); shape->values[i][strlen((char *)sthand->items[i][ sthand->row ])] = '\0'; } } /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Call to osGetOrdinates failed.", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } osShapeBounds(shape); if(shape->type == MS_SHAPE_NULL) { msSetError( MS_ORACLESPATIALERR, "Shape type is null... this probably means a record number was requested that could not have beeen in a result set (as returned by NextShape).", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } return (MS_SUCCESS); } else { /* no resultindex, fetch the shape from the DB */ char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL; int function = 0; int version = 0; sb2 *nullind = NULL; /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/ OCIDefine *adtp = NULL; OCIDefine **items = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetShape was called. Using the record = %ld.\n", shapeindex); dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; /* allocate enough space for items */ if (layer->numitems > 0) { if (sthand->items_query == NULL) sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items_query buffer", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } nullind = (sb2 *)malloc( sizeof(sb2) * (layer->numitems) ); if (nullind == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate nullind buffer", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } memset(nullind ,0, sizeof(sb2) * (layer->numitems) ); items = (OCIDefine **)malloc(sizeof(OCIDefine *)*layer->numitems); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); /* clean nullind */ free(nullind); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*layer->numitems); } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version )) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetShape()", layer->data ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /*Define the first query to retrive itens*/ if (unique[0] == '\0') { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable for query. To execute " "query functions you need to define one " "unique column [USING UNIQUE <#column>]", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else snprintf( query_str, sizeof(query_str), "SELECT"); /*Define the query*/ for( i = 0; i < layer->numitems; ++i ) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " %s,", layer->items[i] ); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " %s FROM %s WHERE %s = %ld", geom_column_name, table_name, unique, shapeindex); /*if (layer->filter.string != NULL) sprintf( query_str + strlen(query_str), " AND %s", (layer->filter.string));*/ osFilteritem(layer, FUNCTION_NONE, query_str, sizeof(query_str), 2); if (layer->debug) msDebug("msOracleSpatialLayerGetShape. Sql: %s\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand,OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (success && layer->numitems > 0) { for( i = 0; i < layer->numitems && success; i++ ) success = TRY( hand, OCIDefineByPos( sthand->stmthp, &items[i], hand->errhp, (ub4)i+1, (dvoid *)sthand->items_query[i], (sb4)TEXT_SIZE, SQLT_STR, (sb2 *)&nullind[i], (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetShape()", hand->last_oci_error, query_str ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (success) { success = TRY( hand, OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)layer->numitems+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY (hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT )) && TRY (hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp )); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s ." "Check your data statement.", "msOracleSpatialLayerGetShape()", hand->last_oci_error, query_str ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } shape->type = MS_SHAPE_NULL; /* no rows fetched */ if (sthand->rows_fetched == 0) { /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return (MS_DONE); } obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->numvalues = layer->numitems; shape->values = (char **) malloc(sizeof(char *) * layer->numitems); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values.", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } shape->index = shapeindex; for( i = 0; i < layer->numitems; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items_query[sthand->row][i])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer.", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { if (nullind[i] != OCI_IND_NULL) { strcpy(shape->values[i], (char *)sthand->items_query[sthand->row][i]); shape->values[i][strlen((char *)sthand->items_query[sthand->row][i])] = '\0'; } else { shape->values[i][0] = '\0'; } } } /* increment for next row */ sthand->row_num++; sthand->row++; /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Cannot execute query", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } osShapeBounds(shape); sthand->row = sthand->row_num = 0; /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return (MS_SUCCESS); } } int msOracleSpatialLayerInitItemInfo( layerObj *layer ) { int i; int *itemindexes ; if (layer->debug) msDebug("msOracleSpatialLayerInitItemInfo was called.\n"); if (layer->numitems == 0) return MS_SUCCESS; if (layer->iteminfo) free( layer->iteminfo ); if ((layer->iteminfo = (long *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerInitItemInfo()"); return MS_FAILURE; } itemindexes = (int*)layer->iteminfo; for(i=0; i < layer->numitems; i++) itemindexes[i] = i; /*last one is always the geometry one - the rest are non-geom*/ return MS_SUCCESS; } /* AutoProjection Support for RFC 37 #3333 * TODO: Needs testing */ int msOracleSpatialLayerGetAutoProjection( layerObj *layer, projectionObj *projection ) { char *table_name; char *query_str, *geom_column_name = NULL, *unique = NULL, *srid = NULL; int success; int function = 0; int version = 0; char wktext[4000]; OCIDefine *def1p = NULL; OCIBind *bnd1p = NULL, *bnd2p = NULL; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetAutoProjection was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetAutoProjection called on unopened layer","msOracleSpatialLayerGetAutoProjection()"); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version )) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetAutoProjection()", layer->data ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } query_str = "SELECT wktext FROM mdsys.all_sdo_geom_metadata m, mdsys.cs_srs c WHERE c.srid = m.srid and m.owner||'.'||m.table_name = :table_name and m.column_name = :geo_col_name " "UNION SELECT wktext from mdsys.user_sdo_geom_metadata m, mdsys.cs_srs c WHERE c.srid = m.srid and m.table_name = :table_name and m.column_name = :geo_col_name"; if (layer->debug) msDebug("msOracleSpatialLayerGetAutoProjection. Using this Sql to retrieve the projection: %s.\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *) ":table_name", strlen(":table_name"), (ub1*) table_name, strlen(table_name)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT ) ) && TRY( hand, OCIBindByName( sthand->stmthp, &bnd1p, hand->errhp, (text *) ":geo_col_name", strlen(":geo_col_name"), (ub1*) geom_column_name, strlen(geom_column_name)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT ) ) && TRY( hand, OCIDefineByPos( sthand->stmthp, &def1p, hand->errhp, (ub4)1, (dvoid *)wktext, (sb4)4000, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)0, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetAutoProjection()", hand->last_oci_error, query_str ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } do { success = TRY( hand, OCIStmtFetch( sthand->stmthp, hand->errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); if (success && sthand->rows_fetched > 0) { if( layer->debug ) msDebug("Found WKT projection for table %s: %s\n", table_name, wktext); if(wktext != NULL && projection != NULL) if(msOGCWKT2ProjectionObj(wktext, projection, layer->debug) == MS_FAILURE) return(MS_FAILURE); } } while (sthand->rows_fetched > 0); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_SUCCESS; } /********************************************************************** * msOracleSpatialGetFieldDefn() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ static void msOracleSpatialGetFieldDefn( layerObj *layer, msOracleSpatialHandler *hand, const char *item, OCIParam *pard ) { const char *gml_type = "Character"; char md_item_name[256]; char gml_width[32], gml_precision[32]; int success; ub2 rzttype, nOCILen; gml_width[0] = '\0'; gml_precision[0] = '\0'; /* -------------------------------------------------------------------- */ /* Get basic parameter details. */ /* -------------------------------------------------------------------- */ success = TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&rzttype,(ub4 *)0, (ub4) OCI_ATTR_DATA_TYPE, hand->errhp )) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&nOCILen ,(ub4 *)0, (ub4) OCI_ATTR_DATA_SIZE, hand->errhp )); if( !success ) return; switch( rzttype ) { case SQLT_CHR: case SQLT_AFC: gml_type = "Character"; if( nOCILen <= 4000 ) sprintf( gml_width, "%d", nOCILen ); break; case SQLT_NUM: { /* NOTE: OCI docs say this should be ub1 type, but we have determined that oracle is actually returning a short so we use that type and try to compensate for possible problems by initializing, and dividing by 256 if it is large. */ unsigned short byPrecision = 0; sb1 nScale = 0; if( !TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&byPrecision ,(ub4 *)0, (ub4) OCI_ATTR_PRECISION, hand->errhp )) || !TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&nScale,(ub4 *)0, (ub4) OCI_ATTR_SCALE, hand->errhp )) ) return; if( byPrecision > 255 ) byPrecision = byPrecision / 256; if( nScale > 0 ) { gml_type = "Real"; sprintf( gml_width, "%d", byPrecision ); sprintf( gml_precision, "%d", nScale ); } else if( nScale < 0 ) gml_type = "Real"; else { gml_type = "Integer"; if( byPrecision < 38 ) sprintf( gml_width, "%d", byPrecision ); } } break; case SQLT_DAT: case SQLT_DATE: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_TIME: case SQLT_TIME_TZ: gml_type = "Date"; break; default: gml_type = "Character"; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } int msOracleSpatialLayerGetItems( layerObj *layer ) { char *rzt = ""; ub2 rzttype = 0; char *flk = ""; int function = 0; int version = 0; int existgeom; int count_item, flk_len, success, i; char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL; OCIParam *pard = (OCIParam *) 0; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *) layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; int get_field_details = 0; const char *value; if (layer->debug) msDebug("msOracleSpatialLayerGetItems was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetItems called on unopened layer", "msOracleSpatialLayerGetItems()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } /* Will we want to capture the field details? */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) get_field_details = 1; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version)) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetItems()", layer->data ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } snprintf( query_str, sizeof(query_str), "SELECT * FROM %s", table_name ); success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DESCRIBE_ONLY) ) && TRY( hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DESCRIBE_ONLY ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&layer->numitems, (ub4 *)0, OCI_ATTR_PARAM_COUNT, hand->errhp) ); if (!success) { msSetError( MS_QUERYERR, "Cannot retrieve column list", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } sthand->row_num = sthand->row = 0; layer->numitems = layer->numitems-1; layer->items = malloc (sizeof(char *) * (layer->numitems)); if (layer->items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (layer->numitems > 0) { if (sthand->items_query == NULL) sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } } count_item = 0; existgeom = 0; /*Upcase conversion for the geom_column_name*/ for (i=0; geom_column_name[i] != '\0'; i++) geom_column_name[i] = toupper(geom_column_name[i]); /*Retrive columns name from the user table*/ for (i = 0; i <= layer->numitems; i++) { success = TRY( hand, OCIParamGet ((dvoid*) sthand->stmthp, (ub4)OCI_HTYPE_STMT,hand->errhp,(dvoid*)&pard, (ub4)i+1)) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM,(dvoid*)&rzttype,(ub4 *)0, (ub4) OCI_ATTR_DATA_TYPE, hand->errhp )) && TRY( hand, OCIParamGet ((dvoid*) sthand->stmthp, (ub4)OCI_HTYPE_STMT,hand->errhp,(dvoid*)&pard, (ub4)i+1)) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM,(dvoid*)&rzt,(ub4 *)&flk_len, (ub4) OCI_ATTR_NAME, hand->errhp )); /* if (layer->debug) msDebug("msOracleSpatialLayerGetItems checking type. Column = %s Type = %d\n", rzt, rzttype); */ flk = (char *)malloc(sizeof(char*) * flk_len+1); if (flk == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { strlcpy(flk, rzt, flk_len+1); } /*Comapre the column name (flk) with geom_column_name and ignore with true*/ if (strcmp(flk, geom_column_name) != 0) { if (rzttype!=OCI_TYPECODE_BLOB) { layer->items[count_item] = (char *)malloc(sizeof(char) * flk_len+1); if (layer->items[count_item] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } strcpy(layer->items[count_item], flk); count_item++; if( get_field_details ) msOracleSpatialGetFieldDefn( layer, hand, layer->items[count_item-1], pard ); } } else existgeom = 1; strcpy( rzt, "" ); free(flk); /* Better?!*/ flk_len = 0; } layer->numitems = count_item; if (!(existgeom)) { msSetError (MS_ORACLESPATIALERR, "No geometry column, check stmt", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return msOracleSpatialLayerInitItemInfo( layer ); } int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) { char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL; int success, i; int function = 0; int version = 0; SDOGeometryObj *obj = NULL; SDOGeometryInd *ind = NULL; shapeObj shape; rectObj bounds; /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/ OCIDefine *adtp = NULL; OCIDefine **items = NULL; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetExtent was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetExtent called on unopened layer","msOracleSpatialLayerGetExtent()"); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } /* allocate enough space for items */ if (layer->numitems > 0) { sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items buffer", "msOracleSpatialLayerGetExtent()" ); return MS_FAILURE; } items = (OCIDefine **)malloc(sizeof(OCIDefine *)*layer->numitems); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*layer->numitems); } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version )) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetExtent()", layer->data ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (version == VERSION_10g) osAggrGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); else { if (((atol(srid) < 8192) || (atol(srid) > 8330)) && (atol(srid) != 2) && (atol(srid) != 5242888) && (atol(srid) != 2000001)) { if (version == VERSION_9i) osAggrGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); else osConvexHullGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); } else osConvexHullGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); } if (layer->debug) msDebug("msOracleSpatialLayerGetExtent. Using this Sql to retrieve the extent: %s.\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand,OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (success && layer->numitems > 0) { for( i = 0; i < layer->numitems && success; ++i ) success = TRY( hand, OCIDefineByPos( sthand->stmthp, &items[i], hand->errhp, (ub4)i+1, (dvoid *)sthand->items_query[i], (sb4)TEXT_SIZE, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetExtent()", hand->last_oci_error, query_str ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (success) { success = TRY( hand, OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)layer->numitems+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY (hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT )) && TRY (hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp )); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s ." "Check your data statement.", "msOracleSpatialLayerGetExtent()", hand->last_oci_error, query_str ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /* should begin processing first row */ sthand->row_num = sthand->row = 0; msInitShape( &shape ); do { /* is buffer empty? */ if (sthand->row_num >= sthand->rows_fetched) { /* fetch more */ success = TRY( hand, OCIStmtFetch( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); if (!success || sthand->rows_fetched == 0 || sthand->row_num >= sthand->rows_fetched) { hand->last_oci_status=MS_SUCCESS; break; } sthand->row = 0; /* reset row index */ } /* no rows fetched */ if (sthand->rows_fetched == 0) break; obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape.numvalues = layer->numitems; shape.values = (char **) malloc(sizeof(char *) * layer->numitems); if (shape.values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values.", "msOracleSpatialLayerGetExtent()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } shape.index = sthand->row_num; for( i = 0; i < layer->numitems; ++i ) { shape.values[i] = (char *)malloc(strlen((char *)sthand->items_query[sthand->row][i])+1); if (shape.values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer.", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { strcpy(shape.values[i], (char *)sthand->items_query[sthand->row][i]); shape.values[i][strlen((char *)sthand->items_query[sthand->row][i])] = '\0'; } } /* increment for next row */ sthand->row_num++; sthand->row++; /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, &shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Cannot execute query", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } } while(sthand->row <= sthand->rows_fetched); sthand->row = sthand->row_num = 0; osShapeBounds(&shape); bounds = shape.bounds; extent->minx = bounds.minx; extent->miny = bounds.miny; extent->maxx = bounds.maxx; extent->maxy = bounds.maxy; msFreeShape(&shape); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return(MS_SUCCESS); } void msOracleSpatialLayerFreeItemInfo( layerObj *layer ) { if (layer->debug) msDebug("msOracleSpatialLayerFreeItemInfo was called.\n"); if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; /* nothing to do */ } int msOracleSpatialLayerGetAutoStyle( mapObj *map, layerObj *layer, classObj *c, shapeObj *shape ) { msSetError( MS_ORACLESPATIALERR, "Function not implemented yet", "msLayerGetAutoStyle()" ); return MS_FAILURE; } int msOracleSpatialGetPaging(layerObj *layer) { msOracleSpatialLayerInfo *layerinfo = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetPaging was called.\n"); if(!msOracleSpatialLayerIsOpen(layer)) return MS_TRUE; assert( layer->layerinfo != NULL); layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; return layerinfo->paging; } void msOracleSpatialEnablePaging(layerObj *layer, int value) { msOracleSpatialLayerInfo *layerinfo = NULL; if (layer->debug) msDebug("msOracleSpatialLayerEnablePaging was called.\n"); if(!msOracleSpatialLayerIsOpen(layer)) msOracleSpatialLayerOpen(layer); assert( layer->layerinfo != NULL); layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; layerinfo->paging = value; return; } #else /* OracleSpatial "not-supported" procedures */ int msOracleSpatialLayerOpen(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerOpen()" ); return MS_FAILURE; } int msOracleSpatialLayerIsOpen(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerIsOpen()" ); return MS_FALSE; } int msOracleSpatialLayerClose(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerClose()" ); return MS_FAILURE; } int msOracleSpatialLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } int msOracleSpatialLayerNextShape(layerObj *layer, shapeObj *shape) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } int msOracleSpatialLayerGetItems(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetItems()" ); return MS_FAILURE; } int msOracleSpatialLayerGetShape( layerObj *layer, shapeObj *shape, resultObj *record ) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetExtent()" ); return MS_FAILURE; } int msOracleSpatialLayerInitItemInfo(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerInitItemInfo()" ); return MS_FAILURE; } void msOracleSpatialLayerFreeItemInfo(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerFreeItemInfo()" ); } int msOracleSpatialLayerGetAutoStyle( mapObj *map, layerObj *layer, classObj *c, shapeObj *shape ) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerGetAutoStyle()" ); return MS_FAILURE; } void msOracleSpatialEnablePaging(layerObj *layer, int value) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerEnablePaging()" ); return; } int msOracleSpatialGetPaging(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerGetPaging()" ); return MS_FAILURE; } #endif #if defined USE_ORACLE_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo; vtable->LayerOpen = msOracleSpatialLayerOpen; vtable->LayerIsOpen = msOracleSpatialLayerIsOpen; vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes; vtable->LayerNextShape = msOracleSpatialLayerNextShape; vtable->LayerGetShape = msOracleSpatialLayerGetShape; vtable->LayerClose = msOracleSpatialLayerClose; vtable->LayerGetItems = msOracleSpatialLayerGetItems; vtable->LayerGetExtent = msOracleSpatialLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ vtable->LayerCloseConnection = msOracleSpatialLayerClose; vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ vtable->LayerEnablePaging = msOracleSpatialEnablePaging; vtable->LayerGetPaging = msOracleSpatialGetPaging; return MS_SUCCESS; } #else /*if ORACLE_PLUGIN is defined, then this file is not used by libmapserver and therefre there is no need to include this function */ int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo; layer->vtable->LayerOpen = msOracleSpatialLayerOpen; layer->vtable->LayerIsOpen = msOracleSpatialLayerIsOpen; layer->vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes; layer->vtable->LayerNextShape = msOracleSpatialLayerNextShape; layer->vtable->LayerGetShape = msOracleSpatialLayerGetShape; layer->vtable->LayerClose = msOracleSpatialLayerClose; layer->vtable->LayerGetItems = msOracleSpatialLayerGetItems; layer->vtable->LayerGetExtent = msOracleSpatialLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ layer->vtable->LayerCloseConnection = msOracleSpatialLayerClose; layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ layer->vtable->LayerEnablePaging = msOracleSpatialEnablePaging; layer->vtable->LayerGetPaging = msOracleSpatialGetPaging; return MS_SUCCESS; } #endif mapserver-6.4.1/mapgeos.c0000644002461700001440000011542212261257215015120 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapServer-GEOS integration. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include "mapserver.h" #ifdef USE_GEOS #include /* ** Error handling... */ static void msGEOSError(const char *format, ...) { va_list args; va_start (args, format); msSetError(MS_GEOSERR, format, "msGEOSError()", args); /* just pass along to MapServer error handling */ va_end(args); return; } static void msGEOSNotice(const char *fmt, ...) { return; /* do nothing with notices at this point */ } #ifndef USE_THREAD static GEOSContextHandle_t geos_handle; static inline GEOSContextHandle_t msGetGeosContextHandle() { return geos_handle; } #else #include "mapthread.h" typedef struct geos_thread_info { struct geos_thread_info *next; int thread_id; GEOSContextHandle_t geos_handle; } geos_thread_info_t; static geos_thread_info_t *geos_list = NULL; static GEOSContextHandle_t msGetGeosContextHandle() { geos_thread_info_t *link; GEOSContextHandle_t ret_obj; int thread_id; msAcquireLock( TLOCK_GEOS ); thread_id = msGetThreadId(); /* find link for this thread */ for( link = geos_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} /* If the target thread link is already at the head of the list were ok */ if( geos_list != NULL && geos_list->thread_id == thread_id ) { } /* We don't have one ... initialize one. */ else if( link == NULL || link->next == NULL ) { geos_thread_info_t *new_link; new_link = (geos_thread_info_t *) malloc(sizeof(geos_thread_info_t)); new_link->next = geos_list; new_link->thread_id = thread_id; new_link->geos_handle = initGEOS_r(msGEOSNotice, msGEOSError); geos_list = new_link; } /* If the link is not already at the head of the list, promote it */ else if( link != NULL && link->next != NULL ) { geos_thread_info_t *target = link->next; link->next = link->next->next; target->next = geos_list; geos_list = target; } ret_obj = geos_list->geos_handle; msReleaseLock( TLOCK_GEOS ); return ret_obj; } #endif /* ** Setup/Cleanup wrappers */ void msGEOSSetup() { #ifndef USE_THREAD geos_handle = initGEOS_r(msGEOSNotice, msGEOSError); #endif } void msGEOSCleanup() { #ifndef USE_THREAD finishGEOS_r(geos_handle); #else geos_thread_info_t *link; msAcquireLock( TLOCK_GEOS ); for( link = geos_list; link != NULL;) { geos_thread_info_t *cur = link; link = link->next; finishGEOS_r(cur->geos_handle); free(cur); } geos_list = NULL; msReleaseLock( TLOCK_GEOS ); #endif } /* ** Translation functions */ static GEOSGeom msGEOSShape2Geometry_point(pointObj *point) { GEOSCoordSeq coords; GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!point) return NULL; coords = GEOSCoordSeq_create_r(handle,1, 2); /* todo handle z's */ if(!coords) return NULL; GEOSCoordSeq_setX_r(handle,coords, 0, point->x); GEOSCoordSeq_setY_r(handle,coords, 0, point->y); /* GEOSCoordSeq_setY(coords, 0, point->z); */ g = GEOSGeom_createPoint_r(handle,coords); /* g owns the coordinate in coords */ return g; } static GEOSGeom msGEOSShape2Geometry_multipoint(lineObj *multipoint) { int i; GEOSGeom g; GEOSGeom *points; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!multipoint) return NULL; points = malloc(multipoint->numpoints*sizeof(GEOSGeom)); if(!points) return NULL; for(i=0; inumpoints; i++) points[i] = msGEOSShape2Geometry_point(&(multipoint->point[i])); g = GEOSGeom_createCollection_r(handle,GEOS_MULTIPOINT, points, multipoint->numpoints); free(points); return g; } static GEOSGeom msGEOSShape2Geometry_line(lineObj *line) { int i; GEOSGeom g; GEOSCoordSeq coords; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!line) return NULL; coords = GEOSCoordSeq_create_r(handle,line->numpoints, 2); /* todo handle z's */ if(!coords) return NULL; for(i=0; inumpoints; i++) { GEOSCoordSeq_setX_r(handle,coords, i, line->point[i].x); GEOSCoordSeq_setY_r(handle,coords, i, line->point[i].y); /* GEOSCoordSeq_setZ(coords, i, line->point[i].z); */ } g = GEOSGeom_createLineString_r(handle,coords); /* g owns the coordinates in coords */ return g; } static GEOSGeom msGEOSShape2Geometry_multiline(shapeObj *multiline) { int i; GEOSGeom g; GEOSGeom *lines; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!multiline) return NULL; lines = malloc(multiline->numlines*sizeof(GEOSGeom)); if(!lines) return NULL; for(i=0; inumlines; i++) lines[i] = msGEOSShape2Geometry_line(&(multiline->line[i])); g = GEOSGeom_createCollection_r(handle,GEOS_MULTILINESTRING, lines, multiline->numlines); free(lines); return g; } static GEOSGeom msGEOSShape2Geometry_simplepolygon(shapeObj *shape, int r, int *outerList) { int i, j, k; GEOSCoordSeq coords; GEOSGeom g; GEOSGeom outerRing; GEOSGeom *innerRings=NULL; int numInnerRings=0, *innerList; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape || !outerList) return NULL; /* build the outer shell */ coords = GEOSCoordSeq_create_r(handle,shape->line[r].numpoints, 2); /* todo handle z's */ if(!coords) return NULL; for(i=0; iline[r].numpoints; i++) { GEOSCoordSeq_setX_r(handle,coords, i, shape->line[r].point[i].x); GEOSCoordSeq_setY_r(handle,coords, i, shape->line[r].point[i].y); /* GEOSCoordSeq_setZ(coords, i, shape->line[r].point[i].z); */ } outerRing = GEOSGeom_createLinearRing_r(handle,coords); /* outerRing owns the coordinates in coords */ /* build the holes */ innerList = msGetInnerList(shape, r, outerList); for(j=0; jnumlines; j++) if(innerList[j] == MS_TRUE) numInnerRings++; if(numInnerRings > 0) { k = 0; /* inner ring counter */ innerRings = malloc(numInnerRings*sizeof(GEOSGeom)); if(!innerRings) return NULL; /* todo, this will leak memory (outerRing) */ for(j=0; jnumlines; j++) { if(innerList[j] == MS_FALSE) continue; coords = GEOSCoordSeq_create_r(handle,shape->line[j].numpoints, 2); /* todo handle z's */ if(!coords) return NULL; /* todo, this will leak memory (shell + allocated holes) */ for(i=0; iline[j].numpoints; i++) { GEOSCoordSeq_setX_r(handle,coords, i, shape->line[j].point[i].x); GEOSCoordSeq_setY_r(handle,coords, i, shape->line[j].point[i].y); /* GEOSCoordSeq_setZ(coords, i, shape->line[j].point[i].z); */ } innerRings[k] = GEOSGeom_createLinearRing_r(handle,coords); /* innerRings[k] owns the coordinates in coords */ k++; } } g = GEOSGeom_createPolygon_r(handle,outerRing, innerRings, numInnerRings); free(innerList); /* clean up */ free(innerRings); /* clean up */ return g; } static GEOSGeom msGEOSShape2Geometry_polygon(shapeObj *shape) { int i, j; GEOSGeom *polygons; int *outerList, numOuterRings=0, lastOuterRing=0; GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); outerList = msGetOuterList(shape); for(i=0; inumlines; i++) { if(outerList[i] == MS_TRUE) { numOuterRings++; lastOuterRing = i; /* save for the simple case */ } } if(numOuterRings == 1) { g = msGEOSShape2Geometry_simplepolygon(shape, lastOuterRing, outerList); } else { /* a true multipolygon */ polygons = malloc(numOuterRings*sizeof(GEOSGeom)); if(!polygons) return NULL; j = 0; /* part counter */ for(i=0; inumlines; i++) { if(outerList[i] == MS_FALSE) continue; polygons[j] = msGEOSShape2Geometry_simplepolygon(shape, i, outerList); /* TODO: account for NULL return values */ j++; } g = GEOSGeom_createCollection_r(handle,GEOS_MULTIPOLYGON, polygons, numOuterRings); free(polygons); } free(outerList); return g; } GEOSGeom msGEOSShape2Geometry(shapeObj *shape) { if(!shape) return NULL; /* a NULL shape generates a NULL geometry */ switch(shape->type) { case MS_SHAPE_POINT: if(shape->numlines == 0 || shape->line[0].numpoints == 0) /* not enough info for a point */ return NULL; if(shape->line[0].numpoints == 1) /* simple point */ return msGEOSShape2Geometry_point(&(shape->line[0].point[0])); else /* multi-point */ return msGEOSShape2Geometry_multipoint(&(shape->line[0])); break; case MS_SHAPE_LINE: if(shape->numlines == 0 || shape->line[0].numpoints < 2) /* not enough info for a line */ return NULL; if(shape->numlines == 1) /* simple line */ return msGEOSShape2Geometry_line(&(shape->line[0])); else /* multi-line */ return msGEOSShape2Geometry_multiline(shape); break; case MS_SHAPE_POLYGON: if(shape->numlines == 0 || shape->line[0].numpoints < 4) /* not enough info for a polygon (first=last) */ return NULL; return msGEOSShape2Geometry_polygon(shape); /* simple and multipolygon cases are addressed */ break; default: break; } return NULL; /* should not get here */ } static shapeObj *msGEOSGeometry2Shape_point(GEOSGeom g) { GEOSCoordSeq coords; shapeObj *shape=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!g) return NULL; shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)); shape->line[0].numpoints = 1; shape->geometry = (GEOSGeom) g; coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,g); GEOSCoordSeq_getX_r(handle,coords, 0, &(shape->line[0].point[0].x)); GEOSCoordSeq_getY_r(handle,coords, 0, &(shape->line[0].point[0].y)); /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[0].z)); */ shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y; return shape; } static shapeObj *msGEOSGeometry2Shape_multipoint(GEOSGeom g) { int i; int numPoints; GEOSCoordSeq coords; GEOSGeom point; shapeObj *shape=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!g) return NULL; numPoints = GEOSGetNumGeometries_r(handle,g); /* each geometry has 1 point */ shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints); shape->line[0].numpoints = numPoints; shape->geometry = (GEOSGeom) g; for(i=0; iline[0].point[i].x)); GEOSCoordSeq_getY_r(handle,coords, 0, &(shape->line[0].point[i].y)); /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[i].z)); */ } msComputeBounds(shape); return shape; } static shapeObj *msGEOSGeometry2Shape_line(GEOSGeom g) { shapeObj *shape=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); int i; int numPoints; GEOSCoordSeq coords; if(!g) return NULL; numPoints = GEOSGetNumCoordinates_r(handle,g); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,g); shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints); shape->line[0].numpoints = numPoints; shape->geometry = (GEOSGeom) g; for(i=0; iline[0].point[i].x)); GEOSCoordSeq_getY_r(handle,coords, i, &(shape->line[0].point[i].y)); /* GEOSCoordSeq_getZ(coords, i, &(shape->line[0].point[i].z)); */ } msComputeBounds(shape); return shape; } static shapeObj *msGEOSGeometry2Shape_multiline(GEOSGeom g) { int i, j; int numPoints, numLines; GEOSCoordSeq coords; GEOSGeom lineString; shapeObj *shape=NULL; lineObj line; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!g) return NULL; numLines = GEOSGetNumGeometries_r(handle,g); shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_LINE; shape->geometry = (GEOSGeom) g; for(j=0; jtype = MS_SHAPE_POLYGON; shape->geometry = (GEOSGeom) g; /* exterior ring */ ring = (GEOSGeom) GEOSGetExteriorRing_r(handle,g); numPoints = GEOSGetNumCoordinates_r(handle,ring); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,ring); line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints); line.numpoints = numPoints; for(i=0; itype = MS_SHAPE_POLYGON; shape->geometry = (GEOSGeom) g; for(k=0; ktype = MS_SHAPE_LINE; shape->geometry = (GEOSGeom) g; numGeoms = GEOSGetNumGeometries_r(handle,g); for(i = 0; i < numGeoms; i++) { /* for each geometry */ shapeObj* shape2 = msGEOSGeometry2Shape((GEOSGeom)GEOSGetGeometryN_r(handle,g, i)); if (shape2) { for (j = 0; j < shape2->numlines; j++) msAddLineDirectly(shape, &shape2->line[j]); shape2->numlines = 0; shape2->geometry = NULL; /* not owned */ msFreeShape(shape2); } } msComputeBounds(shape); return shape; } break; default: msSetError(MS_GEOSERR, "Unsupported GEOS geometry type (%d).", "msGEOSGeometry2Shape()", type); } return NULL; } #endif /* ** Maintenence functions exposed to MapServer/MapScript. */ void msGEOSFreeGeometry(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape || !shape->geometry) return; g = (GEOSGeom) shape->geometry; GEOSGeom_destroy_r(handle,g); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSFreeGEOSGeom()"); return; #endif } /* ** WKT input and output functions */ shapeObj *msGEOSShapeFromWKT(const char *wkt) { #ifdef USE_GEOS GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!wkt) return NULL; g = GEOSGeomFromWKT_r(handle,wkt); if(!g) { msSetError(MS_GEOSERR, "Error reading WKT geometry \"%s\".", "msGEOSShapeFromWKT()", wkt); return NULL; } else { return msGEOSGeometry2Shape(g); } #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSShapeFromWKT()"); return NULL; #endif } /* Return should be freed with msGEOSFreeWKT */ char *msGEOSShapeToWKT(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; /* if we have a geometry, we should update it*/ msGEOSFreeGeometry(shape); shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g = (GEOSGeom) shape->geometry; if(!g) return NULL; return GEOSGeomToWKT_r(handle,g); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSShapeToWKT()"); return NULL; #endif } void msGEOSFreeWKT(char* pszGEOSWKT) { #ifdef USE_GEOS GEOSContextHandle_t handle = msGetGeosContextHandle(); #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2) GEOSFree_r(handle,pszGEOSWKT); #endif #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSFreeWKT()"); #endif } shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset) { #if defined USE_GEOS && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)) GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!p) return NULL; if(!p->geometry) /* if no geometry for the shape then build one */ p->geometry = (GEOSGeom) msGEOSShape2Geometry(p); g1 = (GEOSGeom) p->geometry; if(!g1) return NULL; g2 = GEOSOffsetCurve_r(handle,g1, offset, 4, GEOSBUF_JOIN_MITRE, fabs(offset*1.5)); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS Offset Curve support is not available.", "msGEOSingleSidedBuffer()"); return NULL; #endif } /* ** Analytical functions exposed to MapServer/MapScript. */ shapeObj *msGEOSBuffer(shapeObj *shape, double width) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSBuffer_r(handle,g1, width, 30); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSBuffer()"); return NULL; #endif } shapeObj *msGEOSSimplify(shapeObj *shape, double tolerance) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSSimplify_r(handle,g1, tolerance); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS Simplify support is not available.", "msGEOSSimplify()"); return NULL; #endif } shapeObj *msGEOSTopologyPreservingSimplify(shapeObj *shape, double tolerance) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSTopologyPreserveSimplify_r(handle,g1, tolerance); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS Simplify support is not available.", "msGEOSTopologyPreservingSimplify()"); return NULL; #endif } shapeObj *msGEOSConvexHull(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSConvexHull_r(handle,g1); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSConvexHull()"); return NULL; #endif } shapeObj *msGEOSBoundary(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSBoundary_r(handle,g1); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSBoundary()"); return NULL; #endif } pointObj *msGEOSGetCentroid(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSCoordSeq coords; pointObj *point; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSGetCentroid_r(handle,g1); point = (pointObj *) malloc(sizeof(pointObj)); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,g2); GEOSCoordSeq_getX_r(handle,coords, 0, &(point->x)); GEOSCoordSeq_getY_r(handle,coords, 0, &(point->y)); /* GEOSCoordSeq_getZ(coords, 0, &(point->z)); */ GEOSCoordSeq_destroy_r(handle,coords); return point; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSGetCentroid()"); return NULL; #endif } shapeObj *msGEOSUnion(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSUnion_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSUnion()"); return NULL; #endif } shapeObj *msGEOSIntersection(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSIntersection_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSIntersection()"); return NULL; #endif } shapeObj *msGEOSDifference(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSDifference_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSDifference()"); return NULL; #endif } shapeObj *msGEOSSymDifference(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSSymDifference_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSSymDifference()"); return NULL; #endif } /* ** Binary predicates exposed to MapServer/MapScript */ /* ** Does shape1 contain shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSContains(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSContains_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSContains()"); return -1; #endif } /* ** Does shape1 overlap shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSOverlaps(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSOverlaps_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSOverlaps()"); return -1; #endif } /* ** Is shape1 within shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSWithin(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSWithin_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSWithin()"); return -1; #endif } /* ** Does shape1 cross shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSCrosses(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSCrosses_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSCrosses()"); return -1; #endif } /* ** Does shape1 intersect shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSIntersects(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSIntersects_r(handle,g1, g2); return ((result==2) ? -1 : result); #else if(!shape1 || !shape2) return -1; switch(shape1->type) { /* todo: deal with point shapes */ case(MS_SHAPE_LINE): switch(shape2->type) { case(MS_SHAPE_LINE): return msIntersectPolylines(shape1, shape2); case(MS_SHAPE_POLYGON): return msIntersectPolylinePolygon(shape1, shape2); } break; case(MS_SHAPE_POLYGON): switch(shape2->type) { case(MS_SHAPE_LINE): return msIntersectPolylinePolygon(shape2, shape1); case(MS_SHAPE_POLYGON): return msIntersectPolygons(shape1, shape2); } break; } return -1; #endif } /* ** Does shape1 touch shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSTouches(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSTouches_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSTouches()"); return -1; #endif } /* ** Does shape1 equal shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSEquals(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSEquals_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSEquals()"); return -1; #endif } /* ** Are shape1 and shape2 disjoint, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSDisjoint(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSDisjoint_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSDisjoint()"); return -1; #endif } /* ** Useful misc. functions that return -1 on failure. */ double msGEOSArea(shapeObj *shape) { #if defined(USE_GEOS) && defined(GEOS_CAPI_VERSION_MAJOR) && defined(GEOS_CAPI_VERSION_MINOR) && (GEOS_CAPI_VERSION_MAJOR > 1 || GEOS_CAPI_VERSION_MINOR >= 1) GEOSGeom g; double area; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return -1; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g = (GEOSGeom) shape->geometry; if(!g) return -1; result = GEOSArea_r(handle,g, &area); return ((result==0) ? -1 : area); #elif defined(USE_GEOS) msSetError(MS_GEOSERR, "GEOS support enabled, but old version lacks GEOSArea().", "msGEOSArea()"); return -1; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSArea()"); return -1; #endif } double msGEOSLength(shapeObj *shape) { #if defined(USE_GEOS) && defined(GEOS_CAPI_VERSION_MAJOR) && defined(GEOS_CAPI_VERSION_MINOR) && (GEOS_CAPI_VERSION_MAJOR > 1 || GEOS_CAPI_VERSION_MINOR >= 1) GEOSGeom g; double length; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return -1; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g = (GEOSGeom) shape->geometry; if(!g) return -1; result = GEOSLength_r(handle,g, &length); return ((result==0) ? -1 : length); #elif defined(USE_GEOS) msSetError(MS_GEOSERR, "GEOS support enabled, but old version lacks GEOSLength().", "msGEOSLength()"); return -1; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSLength()"); return -1; #endif } double msGEOSDistance(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; double distance; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSDistance_r(handle,g1, g2, &distance); return ((result==0) ? -1 : distance); #else return msDistanceShapeToShape(shape1, shape2); /* fall back on brute force method (for MapScript) */ #endif } mapserver-6.4.1/mapresample.h0000644002461700001440000000460012261257215015773 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: CFS OGC MapServer * Purpose: Definitions related to raster resampling support. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2001, Frank Warmerdam, DM Solutions Group Inc * * 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 RESAMPLE_H #define RESAMPLE_H #include "mapserver.h" #include "mapproject.h" #ifdef USE_GDAL # include # include #endif typedef int (*SimpleTransformer)( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ); void *msInitProjTransformer( projectionObj *psSrc, double *padfSrcGeoTransform, projectionObj *psDst, double *padfDstGeoTransform ); void msFreeProjTransformer( void * ); int msProjTransformer( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ); #ifdef USE_GDAL int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, GDALDatasetH hDS ); #endif #endif /* ndef RESAMPLE_H */ mapserver-6.4.1/mapthread.h0000644002461700001440000000505612261257215015440 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Multithreading / locking related declarations. * Author: Frank Warmerdam * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPTHREAD_H #define MAPTHREAD_H #ifdef __cplusplus extern "C" { #endif #ifdef USE_THREAD void msThreadInit(void); int msGetThreadId(void); void msAcquireLock(int); void msReleaseLock(int); #else #define msThreadInit() #define msGetThreadId() (0) #define msAcquireLock(x) #define msReleaseLock(x) #endif /* ** lock ids - note there is a corresponding lock_names[] array in ** mapthread.c that needs to be extended when new ids are added. */ #define TLOCK_PARSER 1 #define TLOCK_GDAL 2 #define TLOCK_ERROROBJ 3 #define TLOCK_PROJ 4 #define TLOCK_TTF 5 #define TLOCK_POOL 6 #define TLOCK_SDE 7 #define TLOCK_ORACLE 8 #define TLOCK_OWS 9 #define TLOCK_LAYER_VTABLE 10 #define TLOCK_IOCONTEXT 11 #define TLOCK_TMPFILE 12 #define TLOCK_DEBUGOBJ 13 #define TLOCK_OGR 14 #define TLOCK_TIME 15 #define TLOCK_FRIBIDI 16 #define TLOCK_WxS 17 #define TLOCK_GEOS 18 #define TLOCK_STATIC_MAX 20 #define TLOCK_MAX 100 #ifdef __cplusplus } #endif #endif /* MAPTHREAD_H */ mapserver-6.4.1/maputil.c0000644002461700001440000024373312261257215015147 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various utility functions ... a real hodgepodge. * Author: Steve Lime and the MapServer team. * * Notes: Some code (notably msAlphaBlend()) are directly derived from GD. See * the mapserver/GD-COPYING file for the GD license. Use of this code in this * manner is compatible with the MapServer license. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include #include "mapserver.h" #include "maptime.h" #include "mapthread.h" #include "mapcopy.h" #if defined(_WIN32) && !defined(__CYGWIN__) # include # include # include # include #include #endif #ifdef USE_RSVG #include #endif #ifdef USE_GEOS #include #endif extern char *msyystring_buffer; extern int msyylex_destroy(void); extern int yyparse(parseObj *); int msScaleInBounds(double scale, double minscale, double maxscale) { if(scale > 0) { if(maxscale != -1 && scale >= maxscale) return MS_FALSE; if(minscale != -1 && scale < minscale) return MS_FALSE; } return MS_TRUE; } /* ** Helper functions to convert from strings to other types or objects. */ static int bindIntegerAttribute(int *attribute, char *value) { if(!value || strlen(value) == 0) return MS_FAILURE; *attribute = MS_NINT(atof(value)); /*use atof instead of atoi as a fix for bug 2394*/ return MS_SUCCESS; } static int bindDoubleAttribute(double *attribute, char *value) { if(!value || strlen(value) == 0) return MS_FAILURE; *attribute = atof(value); return MS_SUCCESS; } static int bindColorAttribute(colorObj *attribute, char *value) { int len; if(!value || ((len = strlen(value)) == 0)) return MS_FAILURE; if(value[0] == '#' && (len == 7 || len == 9)) { /* got a hex color */ char hex[2]; hex[0] = value[1]; hex[1] = value[2]; attribute->red = msHexToInt(hex); hex[0] = value[3]; hex[1] = value[4]; attribute->green = msHexToInt(hex); hex[0] = value[5]; hex[1] = value[6]; attribute->blue = msHexToInt(hex); if(len == 9) { hex[0] = value[7]; hex[1] = value[8]; attribute->alpha = msHexToInt(hex); } return MS_SUCCESS; } else { /* try a space delimited string */ char **tokens=NULL; int numtokens=0; tokens = msStringSplit(value, ' ', &numtokens); if(tokens==NULL || numtokens != 3) { msFreeCharArray(tokens, numtokens); return MS_FAILURE; /* punt */ } attribute->red = atoi(tokens[0]); attribute->green = atoi(tokens[1]); attribute->blue = atoi(tokens[2]); msFreeCharArray(tokens, numtokens); return MS_SUCCESS; } return MS_FAILURE; /* shouldn't get here */ } static void bindStyle(layerObj *layer, shapeObj *shape, styleObj *style, int drawmode) { assert(MS_DRAW_FEATURES(drawmode)); if(style->numbindings > 0) { if(style->bindings[MS_STYLE_BINDING_SYMBOL].index != -1) { style->symbol = msGetSymbolIndex(&(layer->map->symbolset), shape->values[style->bindings[MS_STYLE_BINDING_SYMBOL].index], MS_TRUE); if(style->symbol == -1) style->symbol = 0; /* a reasonable default (perhaps should throw an error?) */ } if(style->bindings[MS_STYLE_BINDING_ANGLE].index != -1) { style->angle = 360.0; bindDoubleAttribute(&style->angle, shape->values[style->bindings[MS_STYLE_BINDING_ANGLE].index]); } if(style->bindings[MS_STYLE_BINDING_SIZE].index != -1) { style->size = 1; bindDoubleAttribute(&style->size, shape->values[style->bindings[MS_STYLE_BINDING_SIZE].index]); } if(style->bindings[MS_STYLE_BINDING_WIDTH].index != -1) { style->width = 1; bindDoubleAttribute(&style->width, shape->values[style->bindings[MS_STYLE_BINDING_WIDTH].index]); } if(style->bindings[MS_STYLE_BINDING_COLOR].index != -1 && !MS_DRAW_QUERY(drawmode)) { MS_INIT_COLOR(style->color, -1,-1,-1,255); bindColorAttribute(&style->color, shape->values[style->bindings[MS_STYLE_BINDING_COLOR].index]); } if(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].index != -1 && !MS_DRAW_QUERY(drawmode)) { MS_INIT_COLOR(style->outlinecolor, -1,-1,-1,255); bindColorAttribute(&style->outlinecolor, shape->values[style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].index]); } if(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index != -1) { style->outlinewidth = 1; bindDoubleAttribute(&style->outlinewidth, shape->values[style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index]); } if(style->bindings[MS_STYLE_BINDING_OPACITY].index != -1) { style->opacity = 100; bindIntegerAttribute(&style->opacity, shape->values[style->bindings[MS_STYLE_BINDING_OPACITY].index]); } if(style->bindings[MS_STYLE_BINDING_OFFSET_X].index != -1) { style->offsetx = 0; bindDoubleAttribute(&style->offsetx, shape->values[style->bindings[MS_STYLE_BINDING_OFFSET_X].index]); } if(style->bindings[MS_STYLE_BINDING_OFFSET_Y].index != -1) { style->offsety = 0; bindDoubleAttribute(&style->offsety, shape->values[style->bindings[MS_STYLE_BINDING_OFFSET_Y].index]); } if(style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].index != -1) { style->polaroffsetpixel = 0; bindDoubleAttribute(&style->polaroffsetpixel, shape->values[style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].index]); } if(style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].index != -1) { style->polaroffsetangle = 0; bindDoubleAttribute(&style->polaroffsetangle, shape->values[style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].index]); } if(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index != -1) { style->outlinewidth = 1; bindDoubleAttribute(&style->outlinewidth, shape->values[style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index]); } if(style->opacity < 100 || style->color.alpha != 255 ) { int alpha; alpha = MS_NINT(style->opacity*2.55); style->color.alpha = alpha; style->outlinecolor.alpha = alpha; style->backgroundcolor.alpha = alpha; style->mincolor.alpha = alpha; style->maxcolor.alpha = alpha; } } } static void bindLabel(layerObj *layer, shapeObj *shape, labelObj *label, int drawmode) { int i; assert(MS_DRAW_LABELS(drawmode)); /* check the label styleObj's (TODO: do we need to use querymapMode here? */ for(i=0; inumstyles; i++) { /* force MS_DRAWMODE_FEATURES for label styles */ bindStyle(layer, shape, label->styles[i], drawmode|MS_DRAWMODE_FEATURES); } if(label->numbindings > 0) { if(label->bindings[MS_LABEL_BINDING_ANGLE].index != -1) { label->angle = 0.0; bindDoubleAttribute(&label->angle, shape->values[label->bindings[MS_LABEL_BINDING_ANGLE].index]); } if(label->bindings[MS_LABEL_BINDING_SIZE].index != -1) { label->size = 1; bindDoubleAttribute(&label->size, shape->values[label->bindings[MS_LABEL_BINDING_SIZE].index]); } if(label->bindings[MS_LABEL_BINDING_COLOR].index != -1) { MS_INIT_COLOR(label->color, -1,-1,-1,255); bindColorAttribute(&label->color, shape->values[label->bindings[MS_LABEL_BINDING_COLOR].index]); } if(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].index != -1) { MS_INIT_COLOR(label->outlinecolor, -1,-1,-1,255); bindColorAttribute(&label->outlinecolor, shape->values[label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].index]); } if(label->bindings[MS_LABEL_BINDING_FONT].index != -1) { msFree(label->font); label->font = msStrdup(shape->values[label->bindings[MS_LABEL_BINDING_FONT].index]); } if(label->bindings[MS_LABEL_BINDING_PRIORITY].index != -1) { label->priority = MS_DEFAULT_LABEL_PRIORITY; bindIntegerAttribute(&label->priority, shape->values[label->bindings[MS_LABEL_BINDING_PRIORITY].index]); } if(label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].index != -1) { label->shadowsizex = 1; bindIntegerAttribute(&label->shadowsizex, shape->values[label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].index]); } if(label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].index != -1) { label->shadowsizey = 1; bindIntegerAttribute(&label->shadowsizey, shape->values[label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].index]); } if(label->bindings[MS_LABEL_BINDING_POSITION].index != -1) { int tmpPosition; bindIntegerAttribute(&tmpPosition, shape->values[label->bindings[MS_LABEL_BINDING_POSITION].index]); if(tmpPosition != 0) { /* is this test sufficient? */ label->position = tmpPosition; } else { /* Integer binding failed, look for strings like cc, ul, lr, etc... */ if(strlen(shape->values[label->bindings[MS_LABEL_BINDING_POSITION].index]) == 2) { char *vp = shape->values[label->bindings[MS_LABEL_BINDING_POSITION].index]; if(!strncasecmp(vp,"ul",2)) label->position = MS_UL; else if(!strncasecmp(vp,"lr",2)) label->position = MS_LR; else if(!strncasecmp(vp,"ur",2)) label->position = MS_UR; else if(!strncasecmp(vp,"ll",2)) label->position = MS_LL; else if(!strncasecmp(vp,"cr",2)) label->position = MS_CR; else if(!strncasecmp(vp,"cl",2)) label->position = MS_CL; else if(!strncasecmp(vp,"uc",2)) label->position = MS_UC; else if(!strncasecmp(vp,"lc",2)) label->position = MS_LC; else if(!strncasecmp(vp,"cc",2)) label->position = MS_CC; } } } } } /* ** Function to bind various layer properties to shape attributes. */ int msBindLayerToShape(layerObj *layer, shapeObj *shape, int drawmode) { int i, j; if(!layer || !shape) return MS_FAILURE; for(i=0; inumclasses; i++) { /* check the styleObj's */ if(MS_DRAW_FEATURES(drawmode)) { for(j=0; jclass[i]->numstyles; j++) { bindStyle(layer, shape, layer->class[i]->styles[j], drawmode); } } /* check the labelObj's */ if(MS_DRAW_LABELS(drawmode)) { for(j=0; jclass[i]->numlabels; j++) { bindLabel(layer, shape, layer->class[i]->labels[j], drawmode); } } } /* next classObj */ return MS_SUCCESS; } /* * Used to get red, green, blue integers separately based upon the color index */ int getRgbColor(mapObj *map,int i,int *r,int *g,int *b) { /* check index range */ int status=1; *r=*g=*b=-1; if ((i > 0 ) && (i <= map->palette.numcolors) ) { *r=map->palette.colors[i-1].red; *g=map->palette.colors[i-1].green; *b=map->palette.colors[i-1].blue; status=0; } return status; } static int searchContextForTag(mapObj *map, char **ltags, char *tag, char *context, int requires) { int i; if(!context) return MS_FAILURE; /* printf("\tin searchContextForTag, searching %s for %s\n", context, tag); */ if(strstr(context, tag) != NULL) return MS_SUCCESS; /* found the tag */ /* check referenced layers for the tag too */ for(i=0; inumlayers; i++) { if(strstr(context, ltags[i]) != NULL) { /* need to check this layer */ if(requires == MS_TRUE) { if(searchContextForTag(map, ltags, tag, GET_LAYER(map, i)->requires, MS_TRUE) == MS_SUCCESS) return MS_SUCCESS; } else { if(searchContextForTag(map, ltags, tag, GET_LAYER(map, i)->labelrequires, MS_FALSE) == MS_SUCCESS) return MS_SUCCESS; } } } return MS_FAILURE; } /* ** Function to take a look at all layers with REQUIRES/LABELREQUIRES set to make sure there are no ** recursive context requirements set (e.g. layer1 requires layer2 and layer2 requires layer1). This ** is bug 1059. */ int msValidateContexts(mapObj *map) { int i; char **ltags; int status = MS_SUCCESS; ltags = (char **) msSmallMalloc(map->numlayers*sizeof(char *)); for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->name == NULL) { ltags[i] = msStrdup("[NULL]"); } else { ltags[i] = (char *) msSmallMalloc(sizeof(char)*strlen(GET_LAYER(map, i)->name) + 3); sprintf(ltags[i], "[%s]", GET_LAYER(map, i)->name); } } /* check each layer's REQUIRES and LABELREQUIRES parameters */ for(i=0; inumlayers; i++) { /* printf("working on layer %s, looking for references to %s\n", GET_LAYER(map, i)->name, ltags[i]); */ if(searchContextForTag(map, ltags, ltags[i], GET_LAYER(map, i)->requires, MS_TRUE) == MS_SUCCESS) { msSetError(MS_PARSEERR, "Recursion error found for REQUIRES parameter for layer %s.", "msValidateContexts", GET_LAYER(map, i)->name); status = MS_FAILURE; break; } if(searchContextForTag(map, ltags, ltags[i], GET_LAYER(map, i)->labelrequires, MS_FALSE) == MS_SUCCESS) { msSetError(MS_PARSEERR, "Recursion error found for LABELREQUIRES parameter for layer %s.", "msValidateContexts", GET_LAYER(map, i)->name); status = MS_FAILURE; break; } /* printf("done layer %s\n", GET_LAYER(map, i)->name); */ } /* clean up */ msFreeCharArray(ltags, map->numlayers); return status; } int msEvalContext(mapObj *map, layerObj *layer, char *context) { int i, status; char *tag=NULL; expressionObj e; parseObj p; if(!context) return(MS_TRUE); /* initialize a temporary expression (e) */ initExpression(&e); e.string = msStrdup(context); e.type = MS_EXPRESSION; /* todo */ for(i=0; inumlayers; i++) { /* step through all the layers */ if(layer->index == i) continue; /* skip the layer in question */ if (GET_LAYER(map, i)->name == NULL) continue; /* Layer without name cannot be used in contexts */ tag = (char *)msSmallMalloc(sizeof(char)*strlen(GET_LAYER(map, i)->name) + 3); sprintf(tag, "[%s]", GET_LAYER(map, i)->name); if(strstr(e.string, tag)) { if(msLayerIsVisible(map, (GET_LAYER(map, i)))) e.string = msReplaceSubstring(e.string, tag, "1"); else e.string = msReplaceSubstring(e.string, tag, "0"); } free(tag); } msTokenizeExpression(&e, NULL, NULL); p.shape = NULL; p.expr = &e; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); freeExpression(&e); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse context", "msEvalContext"); return MS_FALSE; /* error in parse */ } return p.result.intval; } /* msEvalExpression() * * Evaluates a mapserver expression for a given set of attribute values and * returns the result of the expression (MS_TRUE or MS_FALSE) * May also return MS_FALSE in case of parsing errors or invalid expressions * (check the error stack if you care) * */ int msEvalExpression(layerObj *layer, shapeObj *shape, expressionObj *expression, int itemindex) { if(!expression->string) return MS_TRUE; /* empty expressions are ALWAYS true */ switch(expression->type) { case(MS_STRING): if(itemindex == -1) { msSetError(MS_MISCERR, "Cannot evaluate expression, no item index defined.", "msEvalExpression()"); return MS_FALSE; } if(itemindex >= layer->numitems || itemindex >= shape->numvalues) { msSetError(MS_MISCERR, "Invalid item index.", "msEvalExpression()"); return MS_FALSE; } if(expression->flags & MS_EXP_INSENSITIVE) { if(strcasecmp(expression->string, shape->values[itemindex]) == 0) return MS_TRUE; /* got a match */ } else { if(strcmp(expression->string, shape->values[itemindex]) == 0) return MS_TRUE; /* got a match */ } break; case(MS_LIST): if(itemindex == -1) { msSetError(MS_MISCERR, "Cannot evaluate expression, no item index defined.", "msEvalExpression()"); return MS_FALSE; } if(itemindex >= layer->numitems || itemindex >= shape->numvalues) { msSetError(MS_MISCERR, "Invalid item index.", "msEvalExpression()"); return MS_FALSE; } { char *start,*end; start = expression->string; while((end = strchr(start,',')) != NULL) { if(!strncmp(start,shape->values[itemindex],end-start)) return MS_TRUE; start = end+1; } if(!strcmp(start,shape->values[itemindex])) return MS_TRUE; } break; case(MS_EXPRESSION): { int status; parseObj p; p.shape = shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse expression: %s", "msEvalExpression", expression->string); return MS_FALSE; } return p.result.intval; break; } case(MS_REGEX): if(itemindex == -1) { msSetError(MS_MISCERR, "Cannot evaluate expression, no item index defined.", "msEvalExpression()"); return MS_FALSE; } if(itemindex >= layer->numitems || itemindex >= shape->numvalues) { msSetError(MS_MISCERR, "Invalid item index.", "msEvalExpression()"); return MS_FALSE; } if(!expression->compiled) { if(expression->flags & MS_EXP_INSENSITIVE) { if(ms_regcomp(&(expression->regex), expression->string, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msEvalExpression()"); return MS_FALSE; } } else { if(ms_regcomp(&(expression->regex), expression->string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msEvalExpression()"); return MS_FALSE; } } expression->compiled = MS_TRUE; } if(ms_regexec(&(expression->regex), shape->values[itemindex], 0, NULL, 0) == 0) return MS_TRUE; /* got a match */ break; } return MS_FALSE; } int *msAllocateValidClassGroups(layerObj *lp, int *nclasses) { int *classgroup = NULL; int nvalidclass = 0, i=0; if (!lp || !lp->classgroup || lp->numclasses <=0 || !nclasses) return NULL; classgroup = (int *)msSmallMalloc(sizeof(int)*lp->numclasses); nvalidclass = 0; for (i=0; inumclasses; i++) { if (lp->class[i]->group && strcasecmp(lp->class[i]->group, lp->classgroup) == 0) { classgroup[nvalidclass] = i; nvalidclass++; } } if (nvalidclass > 0) { classgroup = (int *)msSmallRealloc(classgroup, sizeof(int)*nvalidclass); *nclasses = nvalidclass; return classgroup; } if (classgroup) msFree(classgroup); return NULL; } int msShapeGetClass(layerObj *layer, mapObj *map, shapeObj *shape, int *classgroup, int numclasses) { int i, iclass; if (layer->numclasses > 0) { if (classgroup == NULL || numclasses <=0) numclasses = layer->numclasses; for(i=0; i= layer->numclasses) continue; /* this should never happen but just in case */ if(map->scaledenom > 0) { /* verify scaledenom here */ if((layer->class[iclass]->maxscaledenom > 0) && (map->scaledenom > layer->class[iclass]->maxscaledenom)) continue; /* can skip this one, next class */ if((layer->class[iclass]->minscaledenom > 0) && (map->scaledenom <= layer->class[iclass]->minscaledenom)) continue; /* can skip this one, next class */ } /* verify the minfeaturesize */ if ((shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) && (layer->class[iclass]->minfeaturesize > 0)) { double minfeaturesize = Pix2LayerGeoref(map, layer, layer->class[iclass]->minfeaturesize); if (msShapeCheckSize(shape, minfeaturesize) == MS_FALSE) continue; /* skip this one, next class */ } if(layer->class[iclass]->status != MS_DELETE && msEvalExpression(layer, shape, &(layer->class[iclass]->expression), layer->classitemindex) == MS_TRUE) return(iclass); } } return(-1); /* no match */ } static char *evalTextExpression(expressionObj *expr, shapeObj *shape) { char *result=NULL; if(!expr->string) return result; /* nothing to do */ switch(expr->type) { case(MS_STRING): { char *target=NULL; tokenListNodeObjPtr node=NULL; tokenListNodeObjPtr nextNode=NULL; result = msStrdup(expr->string); node = expr->tokens; if(node) { while(node != NULL) { nextNode = node->next; if(node->token == MS_TOKEN_BINDING_DOUBLE || node->token == MS_TOKEN_BINDING_INTEGER || node->token == MS_TOKEN_BINDING_STRING || node->token == MS_TOKEN_BINDING_TIME) { target = (char *) msSmallMalloc(strlen(node->tokenval.bindval.item) + 3); sprintf(target, "[%s]", node->tokenval.bindval.item); result = msReplaceSubstring(result, target, shape->values[node->tokenval.bindval.index]); msFree(target); } node = nextNode; } } if(!strlen(result)) { msFree(result); result = NULL; } } break; case(MS_EXPRESSION): { int status; parseObj p; p.shape = shape; p.expr = expr; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_STRING; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process text expression: %s", "evalTextExpression", expr->string); return NULL; } result = p.result.strval; break; } default: break; } if(result && !strlen(result)) { msFree(result); result = NULL; } return result; } int msShapeGetAnnotation(layerObj *layer, shapeObj *shape) { int i, j; /* RFC77 TODO: check and throw some errors here... */ if(!layer || !shape) return MS_FAILURE; i = shape->classindex; for(j=0; jclass[i]->numlabels; j++) { labelObj *lbl = layer->class[i]->labels[j]; /* shortcut */ lbl->status = MS_ON; if(layer->map->scaledenom > 0) { if((lbl->maxscaledenom != -1) && (layer->map->scaledenom >= lbl->maxscaledenom)) { lbl->status = MS_OFF; continue; /* next label */ } if((lbl->minscaledenom != -1) && (layer->map->scaledenom < lbl->minscaledenom)) { lbl->status = MS_OFF; continue; /* next label */ } } if(msEvalExpression(layer, shape, &(lbl->expression), layer->labelitemindex) != MS_TRUE) { lbl->status = MS_OFF; continue; /* next label */ } msFree(lbl->annotext); lbl->annotext = NULL; if(lbl->text.string) { lbl->annotext = evalTextExpression(&(lbl->text), shape); } else if(layer->class[i]->text.string) { lbl->annotext = evalTextExpression(&(layer->class[i]->text), shape); } else { if (shape->values && layer->labelitemindex >= 0 && shape->values[layer->labelitemindex] && strlen(shape->values[layer->labelitemindex]) ) lbl->annotext = msStrdup(shape->values[layer->labelitemindex]); else if(shape->text) lbl->annotext = msStrdup(shape->text); /* last resort but common with iniline features */ } if(lbl->annotext && (lbl->encoding || lbl->wrap || lbl->maxlength)) { char *newtext = msTransformLabelText(layer->map , lbl, lbl->annotext); free(lbl->annotext); lbl->annotext = newtext; } } return MS_SUCCESS; } /* Check if the shape is enough big to be drawn with the layer::minfeaturesize setting. The minfeaturesize parameter should be the value in geo ref (not in pixel) and should have been multiplied by the resolution factor. */ int msShapeCheckSize(shapeObj *shape, double minfeaturesize) { double dx = (shape->bounds.maxx-shape->bounds.minx); double dy = (shape->bounds.maxy-shape->bounds.miny); if (pow(minfeaturesize,2.0) > (pow(dx,2.0)+pow(dy,2.0))) return MS_FALSE; return MS_TRUE; } /* ** Adjusts an image size in one direction to fit an extent. */ int msAdjustImage(rectObj rect, int *width, int *height) { if(*width == -1 && *height == -1) { msSetError(MS_MISCERR, "Cannot calculate both image height and width.", "msAdjustImage()"); return(-1); } if(*width > 0) *height = MS_NINT((rect.maxy - rect.miny)/((rect.maxx - rect.minx)/(*width))); else *width = MS_NINT((rect.maxx - rect.minx)/((rect.maxy - rect.miny)/(*height))); return(0); } /* ** Make sure extent fits image window to be created. Returns cellsize of output image. */ double msAdjustExtent(rectObj *rect, int width, int height) { double cellsize, ox, oy; if(width == 1 || height == 1) return 0; cellsize = MS_MAX(MS_CELLSIZE(rect->minx, rect->maxx, width), MS_CELLSIZE(rect->miny, rect->maxy, height)); if(cellsize <= 0) /* avoid division by zero errors */ return(0); ox = MS_MAX(((width-1) - (rect->maxx - rect->minx)/cellsize)/2,0); /* these were width-1 and height-1 */ oy = MS_MAX(((height-1) - (rect->maxy - rect->miny)/cellsize)/2,0); rect->minx = rect->minx - ox*cellsize; rect->miny = rect->miny - oy*cellsize; rect->maxx = rect->maxx + ox*cellsize; rect->maxy = rect->maxy + oy*cellsize; return(cellsize); } /* ** Rect must always contain a portion of bounds. If not, rect is ** shifted to overlap by overlay percent. The dimensions of rect do ** not change but placement relative to bounds can. */ int msConstrainExtent(rectObj *bounds, rectObj *rect, double overlay) { double offset=0; /* check left edge, and if necessary the right edge of bounds */ if(rect->maxx <= bounds->minx) { offset = overlay*(rect->maxx - rect->minx); rect->minx += offset; /* shift right */ rect->maxx += offset; } else if(rect->minx >= bounds->maxx) { offset = overlay*(rect->maxx - rect->minx); rect->minx -= offset; /* shift left */ rect->maxx -= offset; } /* check top edge, and if necessary the bottom edge of bounds */ if(rect->maxy <= bounds->miny) { offset = overlay*(rect->maxy - rect->miny); rect->miny -= offset; /* shift down */ rect->maxy -= offset; } else if(rect->miny >= bounds->maxy) { offset = overlay*(rect->maxy - rect->miny); rect->miny += offset; /* shift up */ rect->maxy += offset; } return(MS_SUCCESS); } /* ** Generic function to save an image to a file. ** ** Note that map may be NULL. If it is set, then it is used for two things: ** - Deal with relative imagepaths (compute absolute path relative to map path) ** - Extract the georeferenced extents and coordinate system ** of the map for writing out with the image when appropriate ** (primarily this means via msSaveImageGDAL() to something like GeoTIFF). ** ** The filename is NULL when the image is supposed to be written to stdout. */ int msSaveImage(mapObj *map, imageObj *img, char *filename) { int nReturnVal = MS_FAILURE; char szPath[MS_MAXPATHLEN]; struct mstimeval starttime, endtime; if(map && map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&starttime, NULL); } if (img) { #ifdef USE_GDAL if( MS_DRIVER_GDAL(img->format) ) { if (map != NULL && filename != NULL ) nReturnVal = msSaveImageGDAL(map, img, msBuildPath(szPath, map->mappath, filename)); else nReturnVal = msSaveImageGDAL(map, img, filename); } else #endif if (MS_RENDERER_PLUGIN(img->format)) { rendererVTableObj *renderer = img->format->vtable; FILE *stream = NULL; if(filename) { if(map) stream = fopen(msBuildPath(szPath, map->mappath, filename),"wb"); else stream = fopen(filename,"wb"); if(!stream) { msSetError(MS_IOERR, "Failed to create output file (%s).", "msSaveImage()", (map?szPath:filename) ); return MS_FAILURE; } } else { if ( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; stream = stdout; } if(renderer->supports_pixel_buffer) { rasterBufferObj data; if(renderer->getRasterBufferHandle(img,&data) != MS_SUCCESS) return MS_FAILURE; nReturnVal = msSaveRasterBuffer(map,&data,stream,img->format ); } else { nReturnVal = renderer->saveImage(img, map, stream, img->format); } if( stream != stdout ) fclose(stream); } else if( MS_DRIVER_IMAGEMAP(img->format) ) nReturnVal = msSaveImageIM(img, filename, img->format); else msSetError(MS_MISCERR, "Unknown image type", "msSaveImage()"); } if(map && map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msSaveImage(%s) total time: %.3fs\n", (filename ? filename : "stdout"), (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } return nReturnVal; } /* ** Generic function to save an image to a byte array. ** - the return value is the pointer to the byte array ** - size_ptr contains the number of bytes returned ** - format: the desired output format ** ** The caller is responsible to free the returned array ** The function returns NULL if the output format is not supported. */ unsigned char *msSaveImageBuffer(imageObj* image, int *size_ptr, outputFormatObj *format) { *size_ptr = 0; if( MS_RENDERER_PLUGIN(image->format)) { rasterBufferObj data; rendererVTableObj *renderer = image->format->vtable; if(renderer->supports_pixel_buffer) { bufferObj buffer; msBufferInit(&buffer); renderer->getRasterBufferHandle(image,&data); msSaveRasterBufferToBuffer(&data,&buffer,format); *size_ptr = buffer.size; return buffer.data; /* don't free the bufferObj as we don't own the bytes anymore */ } else { /* check if the renderer supports native buffer output */ if (renderer->saveImageBuffer) return renderer->saveImageBuffer(image, size_ptr, format); msSetError(MS_MISCERR, "Unsupported image type", "msSaveImageBuffer()"); return NULL; } } msSetError(MS_MISCERR, "Unsupported image type", "msSaveImage()"); return NULL; } /** * Generic function to free the imageObj */ void msFreeImage(imageObj *image) { if (image) { if(MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; tileCacheObj *next,*cur = image->tilecache; while(cur) { msFreeImage(cur->image); next = cur->next; free(cur); cur = next; } image->ntiles = 0; renderer->freeImage(image); } else if( MS_RENDERER_IMAGEMAP(image->format) ) msFreeImageIM(image); else if( MS_RENDERER_RAWDATA(image->format) ) msFree(image->img.raw_16bit); else msSetError(MS_MISCERR, "Unknown image type", "msFreeImage()"); if (image->imagepath) free(image->imagepath); if (image->imageurl) free(image->imageurl); if( --image->format->refcount < 1 ) msFreeOutputFormat( image->format ); image->imagepath = NULL; image->imageurl = NULL; msFree( image->img_mask ); image->img_mask= NULL; msFree( image ); } } /* ** Return an array containing all the layer's index given a group name. ** If nothing is found, NULL is returned. The nCount is initalized ** to the number of elements in the returned array. ** Note : the caller of the function should free the array. */ int *msGetLayersIndexByGroup(mapObj *map, char *groupname, int *pnCount) { int i; int iLayer = 0; int *aiIndex; if(!groupname || !map || !pnCount) { return NULL; } aiIndex = (int *)msSmallMalloc(sizeof(int) * map->numlayers); for(i=0; inumlayers; i++) { if(!GET_LAYER(map, i)->group) /* skip it */ continue; if(strcmp(groupname, GET_LAYER(map, i)->group) == 0) { aiIndex[iLayer] = i; iLayer++; } } if (iLayer == 0) { free(aiIndex); aiIndex = NULL; *pnCount = 0; } else { aiIndex = (int *)msSmallRealloc(aiIndex, sizeof(int)* iLayer); *pnCount = iLayer; } return aiIndex; } /* ==================================================================== */ /* Measured shape utility functions. */ /* ==================================================================== */ /************************************************************************/ /* pointObj *msGetPointUsingMeasure(shapeObj *shape, double m) */ /* */ /* Using a measured value get the XY location it corresonds */ /* to. */ /* */ /************************************************************************/ pointObj *msGetPointUsingMeasure(shapeObj *shape, double m) { #ifdef USE_POINT_Z_M pointObj *point = NULL; lineObj line; double dfMin = 0; double dfMax = 0; int i,j = 0; int bFound = 0; double dfFirstPointX = 0; double dfFirstPointY = 0; double dfFirstPointM = 0; double dfSecondPointX = 0; double dfSecondPointY = 0; double dfSecondPointM = 0; double dfCurrentM = 0; double dfFactor = 0; if (shape && shape->numlines > 0) { /* -------------------------------------------------------------------- */ /* check fir the first value (min) and the last value(max) to */ /* see if the m is contained between these min and max. */ /* -------------------------------------------------------------------- */ line = shape->line[0]; dfMin = line.point[0].m; line = shape->line[shape->numlines-1]; dfMax = line.point[line.numpoints-1].m; if (m >= dfMin && m <= dfMax) { for (i=0; inumlines; i++) { line = shape->line[i]; for (j=0; j m) { bFound = 1; dfSecondPointX = line.point[j].x; dfSecondPointY = line.point[j].y; dfSecondPointM = line.point[j].m; /* -------------------------------------------------------------------- */ /* get the previous node xy values. */ /* -------------------------------------------------------------------- */ if (j > 0) { /* not the first point of the line */ dfFirstPointX = line.point[j-1].x; dfFirstPointY = line.point[j-1].y; dfFirstPointM = line.point[j-1].m; } else { /* get last point of previous line */ dfFirstPointX = shape->line[i-1].point[0].x; dfFirstPointY = shape->line[i-1].point[0].y; dfFirstPointM = shape->line[i-1].point[0].m; } break; } } } } if (!bFound) return NULL; /* -------------------------------------------------------------------- */ /* extrapolate the m value to get t he xy coordinate. */ /* -------------------------------------------------------------------- */ if (dfFirstPointM != dfSecondPointM) dfFactor = (m-dfFirstPointM)/(dfSecondPointM - dfFirstPointM); else dfFactor = 0; point = (pointObj *)msSmallMalloc(sizeof(pointObj)); point->x = dfFirstPointX + (dfFactor * (dfSecondPointX - dfFirstPointX)); point->y = dfFirstPointY + (dfFactor * (dfSecondPointY - dfFirstPointY)); point->m = dfFirstPointM + (dfFactor * (dfSecondPointM - dfFirstPointM)); return point; } return NULL; #else msSetError(MS_MISCERR, "The \"m\" parameter for points is unavailable in your build.", "msGetPointUsingMeasure()"); return NULL; #endif /* USE_POINT_Z_M */ } /************************************************************************/ /* IntersectionPointLinepointObj *p, pointObj *a, pointObj *b) */ /* */ /* Retunrs a point object corresponding to the intersection of */ /* point p and a line formed of 2 points : a and b. */ /* */ /* Alorith base on : */ /* http://www.faqs.org/faqs/graphics/algorithms-faq/ */ /* */ /* Subject 1.02:How do I find the distance from a point to a line? */ /* */ /* Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).*/ /* Let P be the point of perpendicular projection of C on AB. The parameter*/ /* r, which indicates P's position along AB, is computed by the dot product */ /* of AC and AB divided by the square of the length of AB: */ /* */ /* (1) AC dot AB */ /* r = --------- */ /* ||AB||^2 */ /* */ /* r has the following meaning: */ /* */ /* r=0 P = A */ /* r=1 P = B */ /* r<0 P is on the backward extension of AB */ /* r>1 P is on the forward extension of AB */ /* 00 C is right of AB */ /* s=0 C is on AB */ /* */ /* Compute s as follows: */ /* */ /* (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) */ /* s = ----------------------------- */ /* L^2 */ /* */ /* */ /* Then the distance from C to P = |s|*L. */ /* */ /************************************************************************/ pointObj *msIntersectionPointLine(pointObj *p, pointObj *a, pointObj *b) { double r = 0; double L = 0; pointObj *result = NULL; if (p && a && b) { L = sqrt(((b->x - a->x)*(b->x - a->x)) + ((b->y - a->y)*(b->y - a->y))); if (L != 0) r = ((p->x - a->x)*(b->x - a->x) + (p->y - a->y)*(b->y - a->y))/(L*L); else r = 0; result = (pointObj *)msSmallMalloc(sizeof(pointObj)); /* -------------------------------------------------------------------- */ /* We want to make sure that the point returned is on the line */ /* */ /* r=0 P = A */ /* r=1 P = B */ /* r<0 P is on the backward extension of AB */ /* r>1 P is on the forward extension of AB */ /* 0x = a->x; result->y = a->y; } else if (r > 1) { result->x = b->x; result->y = b->y; } else { result->x = a->x + r*(b->x - a->x); result->y = a->y + r*(b->y - a->y); } #ifdef USE_POINT_Z_M result->m = 0; #endif } return result; } /************************************************************************/ /* pointObj *msGetMeasureUsingPoint(shapeObj *shape, pointObj */ /* *point) */ /* */ /* Calculate the intersection point betwwen the point and the */ /* shape and return the Measured value at the intersection. */ /************************************************************************/ pointObj *msGetMeasureUsingPoint(shapeObj *shape, pointObj *point) { double dfMinDist = 1e35; double dfDist = 0; pointObj oFirst; pointObj oSecond; int i, j = 0; lineObj line; pointObj *poIntersectionPt = NULL; #ifdef USE_POINT_Z_M double dfFactor = 0; double dfDistTotal, dfDistToIntersection = 0; #endif if (shape && point) { for (i=0; inumlines; i++) { line = shape->line[i]; /* -------------------------------------------------------------------- */ /* for each line (2 consecutive lines) get the distance between */ /* the line and the point and determine which line segment is */ /* the closeset to the point. */ /* -------------------------------------------------------------------- */ for (j=0; jx - oFirst.x)* (poIntersectionPt->x - oFirst.x)) + ((poIntersectionPt->y - oFirst.y)* (poIntersectionPt->y - oFirst.y))); dfFactor = dfDistToIntersection / dfDistTotal; poIntersectionPt->m = oFirst.m + (oSecond.m - oFirst.m)*dfFactor; #endif return poIntersectionPt; } } return NULL; } /* ==================================================================== */ /* End Measured shape utility functions. */ /* ==================================================================== */ char **msGetAllGroupNames(mapObj *map, int *numTok) { char **papszGroups = NULL; int bFound = 0; int nCount = 0; int i = 0, j = 0; *numTok = 0; if (!map->layerorder) { map->layerorder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); /* * Initiate to default order */ for (i=0; inumlayers; i++) map->layerorder[i] = i; } if (map != NULL && map->numlayers > 0) { nCount = map->numlayers; papszGroups = (char **)msSmallMalloc(sizeof(char *)*nCount); for (i=0; ilayerorder[i])); bFound = 0; if (lp->group && lp->status != MS_DELETE) { for (j=0; j<*numTok; j++) { if (papszGroups[j] && strcmp(lp->group, papszGroups[j]) == 0) { bFound = 1; break; } } if (!bFound) { /* New group... add to the list of groups found */ papszGroups[(*numTok)] = msStrdup(lp->group); (*numTok)++; } } } } return papszGroups; } /************************************************************************/ /* msForceTmpFileBase() */ /************************************************************************/ static int tmpCount = 0; static char *ForcedTmpBase = NULL; void msForceTmpFileBase( const char *new_base ) { /* -------------------------------------------------------------------- */ /* Clear previous setting, if any. */ /* -------------------------------------------------------------------- */ if( ForcedTmpBase != NULL ) { free( ForcedTmpBase ); ForcedTmpBase = NULL; } tmpCount = -1; if( new_base == NULL ) return; /* -------------------------------------------------------------------- */ /* Record new base. */ /* -------------------------------------------------------------------- */ ForcedTmpBase = msStrdup( new_base ); tmpCount = 0; } /********************************************************************** * msTmpFile() * * Generate a Unique temporary file. * * Returns char* which must be freed by caller. **********************************************************************/ char *msTmpFile(mapObj *map, const char *mappath, const char *tmppath, const char *ext) { char szPath[MS_MAXPATHLEN]; const char *fullFname; char *tmpFileName; /* big enough for time + pid + ext */ char *tmpBase = NULL; tmpBase = msTmpPath(map, mappath, tmppath); tmpFileName = msTmpFilename(ext); fullFname = msBuildPath(szPath, tmpBase, tmpFileName); free(tmpFileName); free(tmpBase); if (fullFname) return msStrdup(fullFname); return NULL; } /********************************************************************** * msTmpPath() * * Return the temporary path based on the platform. * * Returns char* which must be freed by caller. **********************************************************************/ char *msTmpPath(mapObj *map, const char *mappath, const char *tmppath) { char szPath[MS_MAXPATHLEN]; const char *fullPath; const char *tmpBase; #ifdef _WIN32 DWORD dwRetVal = 0; TCHAR lpTempPathBuffer[MAX_PATH]; #endif if( ForcedTmpBase != NULL ) tmpBase = ForcedTmpBase; else if (tmppath != NULL) tmpBase = tmppath; else if (getenv("MS_TEMPPATH")) tmpBase = getenv("MS_TEMPPATH"); else if (map && map->web.temppath) tmpBase = map->web.temppath; else { /* default paths */ #ifndef _WIN32 tmpBase = "/tmp/"; #else dwRetVal = GetTempPath(MAX_PATH, /* length of the buffer */ lpTempPathBuffer); /* buffer for path */ if (dwRetVal > MAX_PATH || (dwRetVal == 0)) { tmpBase = "C:\\"; } else { tmpBase = (char*)lpTempPathBuffer; } #endif } fullPath = msBuildPath(szPath, mappath, tmpBase); return strdup(fullPath); } /********************************************************************** * msTmpFilename() * * Generate a Unique temporary filename. * * Returns char* which must be freed by caller. **********************************************************************/ char *msTmpFilename(const char *ext) { char *tmpFname; int tmpFnameBufsize; char *fullFname; char tmpId[128]; /* big enough for time + pid + ext */ snprintf(tmpId, sizeof(tmpId), "%lx_%x",(long)time(NULL),(int)getpid()); if (ext == NULL) ext = ""; tmpFnameBufsize = strlen(tmpId) + 10 + strlen(ext) + 1; tmpFname = (char*)msSmallMalloc(tmpFnameBufsize); msAcquireLock( TLOCK_TMPFILE ); snprintf(tmpFname, tmpFnameBufsize, "%s_%x.%s", tmpId, tmpCount++, ext); msReleaseLock( TLOCK_TMPFILE ); fullFname = strdup(tmpFname); free(tmpFname); return fullFname; } /** * Generic function to Initalize an image object. */ imageObj *msImageCreate(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution, colorObj *bg) { imageObj *image = NULL; if(MS_RENDERER_PLUGIN(format)) { image = format->vtable->createImage(width,height,format,bg); if (image == NULL) { msSetError(MS_MEMERR, "Unable to create new image object.", "msImageCreate()"); return NULL; } image->format = format; format->refcount++; image->width = width; image->height = height; image->imagepath = NULL; image->imageurl = NULL; image->tilecache = NULL; image->ntiles = 0; image->resolution = resolution; image->resolutionfactor = resolution/defresolution; if (imagepath) image->imagepath = msStrdup(imagepath); if (imageurl) image->imageurl = msStrdup(imageurl); } else if( MS_RENDERER_RAWDATA(format) ) { if( format->imagemode != MS_IMAGEMODE_INT16 && format->imagemode != MS_IMAGEMODE_FLOAT32 && format->imagemode != MS_IMAGEMODE_BYTE ) { msSetError(MS_IMGERR, "Attempt to use illegal imagemode with rawdata renderer.", "msImageCreate()" ); return NULL; } image = (imageObj *)calloc(1,sizeof(imageObj)); if (image == NULL) { msSetError(MS_MEMERR, "Unable to create new image object.", "msImageCreate()"); return NULL; } if( format->imagemode == MS_IMAGEMODE_INT16 ) image->img.raw_16bit = (short *) msSmallCalloc(sizeof(short),width*height*format->bands); else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) image->img.raw_float = (float *) msSmallCalloc(sizeof(float),width*height*format->bands); else if( format->imagemode == MS_IMAGEMODE_BYTE ) image->img.raw_byte = (unsigned char *) msSmallCalloc(sizeof(unsigned char),width*height*format->bands); if( image->img.raw_16bit == NULL ) { msFree( image ); msSetError(MS_IMGERR, "Attempt to allocate raw image failed, out of memory.", "msImageCreate()" ); return NULL; } image->img_mask = msAllocBitArray( width*height ); image->format = format; format->refcount++; image->width = width; image->height = height; image->imagepath = NULL; image->imageurl = NULL; image->resolution = resolution; image->resolutionfactor = resolution/defresolution; if (imagepath) image->imagepath = msStrdup(imagepath); if (imageurl) image->imageurl = msStrdup(imageurl); /* initialize to requested nullvalue if there is one */ if( msGetOutputFormatOption(image->format,"NULLVALUE",NULL) != NULL ) { int i = image->width * image->height * format->bands; const char *nullvalue = msGetOutputFormatOption(image->format, "NULLVALUE",NULL); if( atof(nullvalue) == 0.0 ) /* nothing to do */; else if( format->imagemode == MS_IMAGEMODE_INT16 ) { short nv = atoi(nullvalue); for( ; i > 0; ) image->img.raw_16bit[--i] = nv; } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { float nv = atof(nullvalue); for( ; i > 0; ) image->img.raw_float[--i] = nv; } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { unsigned char nv = (unsigned char) atoi(nullvalue); memset( image->img.raw_byte, nv, i ); } } } else if( MS_RENDERER_IMAGEMAP(format) ) { image = msImageCreateIM(width, height, format, imagepath, imageurl, resolution, defresolution); } else { msSetError(MS_MISCERR, "Unsupported renderer requested, unable to initialize image.", "msImageCreate()"); return NULL; } if(!image) msSetError(MS_GDERR, "Unable to initialize image.", "msImageCreate()"); image->refpt.x = image->refpt.y = 0; return image; } /** * Generic function to transorm a point. * */ void msTransformPoint(pointObj *point, rectObj *extent, double cellsize, imageObj *image) { double invcellsize; /*We should probabaly have a function defined at all the renders*/ if (image != NULL && MS_RENDERER_PLUGIN(image->format)) { if(image->format->renderer == MS_RENDER_WITH_KML) { return; } else if(image->format->renderer == MS_RENDER_WITH_GD) { point->x = MS_MAP2IMAGE_X(point->x, extent->minx, cellsize); point->y = MS_MAP2IMAGE_Y(point->y, extent->maxy, cellsize); return; } } invcellsize = 1.0/cellsize; point->x = MS_MAP2IMAGE_X_IC_DBL(point->x, extent->minx, invcellsize); point->y = MS_MAP2IMAGE_Y_IC_DBL(point->y, extent->maxy, invcellsize); } /* ** Helper functions supplied as part of bug #2868 solution. Consider moving these to ** mapprimitive.c for more general use. */ /* vector difference */ static pointObj point_diff(const pointObj a, const pointObj b) { pointObj retv; retv.x = a.x-b.x; retv.y = a.y-b.y; #ifdef USE_POINT_Z_M retv.z = a.z-b.z; retv.m = a.m-b.m; #endif return retv; } /* vector sum */ static pointObj point_sum(const pointObj a, const pointObj b) { pointObj retv; retv.x = a.x+b.x; retv.y = a.y+b.y; #ifdef USE_POINT_Z_M retv.z = a.z+b.z; retv.m = a.m+b.m; #endif return retv; } /* vector multiply */ static pointObj point_mul(const pointObj a, double b) { pointObj retv; retv.x = a.x*b; retv.y = a.y*b; #ifdef USE_POINT_Z_M retv.z = a.z*b; retv.m = a.m*b; #endif return retv; } /* vector ??? */ static double point_abs2(const pointObj a) { #ifdef USE_POINT_Z_M return a.x*a.x+a.y*a.y+a.z*a.z+a.m*a.m; #else return a.x*a.x+a.y*a.y; #endif } /* vector normal */ static pointObj point_norm(const pointObj a) { double lenmul; pointObj retv; #ifdef USE_POINT_Z_M if (a.x==0 && a.y==0 && a.z==0 && a.m==0) #else if (a.x==0 && a.y==0) #endif return a; lenmul=1.0/sqrt(point_abs2(a)); /* this seems to be the costly operation */ retv.x = a.x*lenmul; retv.y = a.y*lenmul; #ifdef USE_POINT_Z_M retv.z = a.z*lenmul; retv.m = a.m*lenmul; #endif return retv; } /* rotate a vector 90 degrees */ static pointObj point_rotz90(const pointObj a) { double nx=-1.0*a.y, ny=a.x; pointObj retv=a; retv.x=nx; retv.y=ny; return retv; } /* vector cross product (warning: z and m dimensions are ignored!) */ static double point_cross(const pointObj a, const pointObj b) { return a.x*b.y-a.y*b.x; } shapeObj *msOffsetCurve(shapeObj *p, double offset) { shapeObj *ret; int i, j, first,idx,ok=0; #if defined USE_GEOS && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)) ret = msGEOSOffsetCurve(p,offset); /* GEOS curve offsetting can fail sometimes, we continue with our own implementation if that is the case.*/ if(ret) return ret; #endif /* ** For offset corner point calculation 1/sin() is used ** to avoid 1/0 division (and long spikes) we define a ** limit for sin(). */ #define CURVE_SIN_LIMIT 0.3 ret = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(ret); ret->numlines = p->numlines; ret->line=(lineObj*)msSmallMalloc(sizeof(lineObj)*ret->numlines); for(i=0; inumlines; i++) { ret->line[i].numpoints=p->line[i].numpoints; ret->line[i].point=(pointObj*)msSmallMalloc(sizeof(pointObj)*ret->line[i].numpoints); } for (i = 0; i < p->numlines; i++) { pointObj old_pt, old_diffdir, old_offdir; if(p->line[i].numpoints<2) { ret->line[i].numpoints = 0; continue; /* skip degenerate points */ } ok = 1; /* initialize old_offdir and old_diffdir, as gcc isn't smart enough to see that it * is not an error to do so, and prints a warning */ old_offdir.x=old_offdir.y=old_diffdir.x=old_diffdir.y = 0; idx=0; first = 1; /* saved metrics of the last processed point */ if (p->line[i].numpoints>0) old_pt=p->line[i].point[0]; for(j=1; jline[i].numpoints; j++) { const pointObj pt = p->line[i].point[j]; /* place of the point */ const pointObj diffdir = point_norm(point_diff(pt,old_pt)); /* direction of the line */ const pointObj offdir = point_rotz90(diffdir); /* direction where the distance between the line and the offset is measured */ pointObj offpt; /* this will be the corner point of the offset line */ /* offset line points computation */ if(first == 1) { /* first point */ first = 0; offpt = point_sum(old_pt,point_mul(offdir,offset)); } else { /* middle points */ /* curve is the angle of the last and the current line's direction (supplementary angle of the shape's inner angle) */ double sin_curve = point_cross(diffdir,old_diffdir); double cos_curve = point_cross(old_offdir,diffdir); if ((-1.0)*CURVE_SIN_LIMIT < sin_curve && sin_curve < CURVE_SIN_LIMIT) { /* do not calculate 1/sin, instead use a corner point approximation: average of the last and current offset direction and length */ /* ** TODO: fair for obtuse inner angles, however, positive and negative ** acute inner angles would need special handling - similar to LINECAP ** to avoid drawing of long spikes */ offpt = point_sum(old_pt, point_mul(point_sum(offdir, old_offdir),0.5*offset)); } else { double base_shift = -1.0*(1.0+cos_curve)/sin_curve; offpt = point_sum(old_pt, point_mul(point_sum(point_mul(diffdir,base_shift),offdir), offset)); } } ret->line[i].point[idx]=offpt; idx++; old_pt=pt; old_diffdir=diffdir; old_offdir=offdir; } /* last point */ if(first == 0) { pointObj offpt=point_sum(old_pt,point_mul(old_offdir,offset)); ret->line[i].point[idx]=offpt; idx++; } if(idx != p->line[i].numpoints) { /* printf("shouldn't happen :(\n"); */ ret->line[i].numpoints=idx; ret->line=msSmallRealloc(ret->line,ret->line[i].numpoints*sizeof(pointObj)); } } if(!ok) ret->numlines = 0; /* all lines where degenerate */ return ret; } shapeObj *msOffsetPolyline(shapeObj *p, double offsetx, double offsety) { int i, j; shapeObj *ret; if(offsety == MS_STYLE_SINGLE_SIDED_OFFSET) { /* complex calculations */ return msOffsetCurve(p,offsetx); } else if(offsety == MS_STYLE_DOUBLE_SIDED_OFFSET) { shapeObj *tmp1; ret = msOffsetCurve(p,offsetx/2.0); tmp1 = msOffsetCurve(p, -offsetx/2.0); for(i=0;inumlines; i++) { msAddLineDirectly(ret,tmp1->line + i); } msFreeShape(tmp1); free(tmp1); return ret; } ret = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(ret); ret->numlines = p->numlines; ret->line=(lineObj*)msSmallMalloc(sizeof(lineObj)*ret->numlines); for(i=0; inumlines; i++) { ret->line[i].numpoints=p->line[i].numpoints; ret->line[i].point=(pointObj*)msSmallMalloc(sizeof(pointObj)*ret->line[i].numpoints); } for (i = 0; i < p->numlines; i++) { for(j=0; jline[i].numpoints; j++) { ret->line[i].point[j].x=p->line[i].point[j].x+offsetx; ret->line[i].point[j].y=p->line[i].point[j].y+offsety; } } return ret; } /* ------------------------------------------------------------------------------- msSetup() Contributed by Jerry Pisk in bug 1203. Heads off potential race condition in initializing GD font cache with multiple threads. Should be called from mapscript module initialization code. ------------------------------------------------------------------------------- */ int msSetup() { #ifdef USE_THREAD msThreadInit(); #endif /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if (msDebugInitFromEnv() != MS_SUCCESS) return MS_FAILURE; #ifdef USE_GD msGDSetup(); #endif #ifdef USE_GEOS msGEOSSetup(); #endif #ifdef USE_RSVG #if !GLIB_CHECK_VERSION(2, 35, 0) g_type_init(); #endif #endif return MS_SUCCESS; } /* This is intended to be a function to cleanup anything that "hangs around" when all maps are destroyed, like Registered GDAL drivers, and so forth. */ #ifndef NDEBUG #if defined(USE_LIBXML2) #include "maplibxml2.h" #endif #endif void msCleanup(int signal) { msForceTmpFileBase( NULL ); msConnPoolFinalCleanup(); /* Lexer string parsing variable */ if (msyystring_buffer != NULL) { msFree(msyystring_buffer); msyystring_buffer = NULL; } msyylex_destroy(); #ifdef USE_OGR msOGRCleanup(); #endif #ifdef USE_GDAL msGDALCleanup(); #endif #ifdef USE_PROJ # if PJ_VERSION >= 480 pj_clear_initcache(); # endif pj_deallocate_grids(); msSetPROJ_LIB( NULL, NULL ); #endif #if defined(USE_CURL) msHTTPCleanup(); #endif #ifdef USE_GD msGDCleanup(signal); #endif #ifdef USE_GEOS msGEOSCleanup(); #endif /* make valgrind happy on debug code */ #ifndef NDEBUG #ifdef USE_CAIRO msCairoCleanup(); #endif #if defined(USE_LIBXML2) xmlCleanupParser(); #endif #endif msTimeCleanup(); msIO_Cleanup(); msResetErrorList(); /* Close/cleanup log/debug output. Keep this at the very end. */ msDebugCleanup(); /* Clean up the vtable factory */ msPluginFreeVirtualTableFactory(); } /************************************************************************/ /* msAlphaBlend() */ /* */ /* Function to overlay/blend an RGBA value into an existing */ /* RGBA value using the Porter-Duff "over" operator. */ /* Primarily intended for use with rasterBufferObj */ /* raster rendering. The "src" is the overlay value, and "dst" */ /* is the existing value being overlaid. dst is expected to be */ /* premultiplied, but the source should not be. */ /* */ /* NOTE: alpha_dst may be NULL. */ /************************************************************************/ void msAlphaBlend( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ) { /* -------------------------------------------------------------------- */ /* Simple cases we want to handle fast. */ /* -------------------------------------------------------------------- */ if( alpha_src == 0 ) return; if( alpha_src == 255 ) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; if( alpha_dst ) *alpha_dst = 255; return; } /* -------------------------------------------------------------------- */ /* Premultiple alpha for source values now. */ /* -------------------------------------------------------------------- */ red_src = red_src * alpha_src / 255; green_src = green_src * alpha_src / 255; blue_src = blue_src * alpha_src / 255; /* -------------------------------------------------------------------- */ /* Another pretty fast case if there is nothing in the */ /* destination to mix with. */ /* -------------------------------------------------------------------- */ if( alpha_dst && *alpha_dst == 0) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; *alpha_dst = alpha_src; return; } /* -------------------------------------------------------------------- */ /* Cases with actual blending. */ /* -------------------------------------------------------------------- */ if(!alpha_dst || *alpha_dst == 255) { int weight_dst = 256 - alpha_src; *red_dst = (256 * red_src + *red_dst * weight_dst) >> 8; *green_dst = (256 * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (256 * blue_src + *blue_dst * weight_dst) >> 8; } else { int weight_dst = (256 - alpha_src); *red_dst = (256 * red_src + *red_dst * weight_dst) >> 8; *green_dst = (256 * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (256 * blue_src + *blue_dst * weight_dst) >> 8; *alpha_dst = (256 * alpha_src + *alpha_dst * weight_dst) >> 8; } } /************************************************************************/ /* msAlphaBlendPM() */ /* */ /* Same as msAlphaBlend() except that the source RGBA is */ /* assumed to already be premultiplied. */ /************************************************************************/ void msAlphaBlendPM( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ) { /* -------------------------------------------------------------------- */ /* Simple cases we want to handle fast. */ /* -------------------------------------------------------------------- */ if( alpha_src == 0 ) return; if( alpha_src == 255 ) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; if( alpha_dst ) *alpha_dst = 255; return; } /* -------------------------------------------------------------------- */ /* Another pretty fast case if there is nothing in the */ /* destination to mix with. */ /* -------------------------------------------------------------------- */ if( alpha_dst && *alpha_dst == 0) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; *alpha_dst = alpha_src; return; } /* -------------------------------------------------------------------- */ /* Cases with actual blending. */ /* -------------------------------------------------------------------- */ if(!alpha_dst || *alpha_dst == 255) { int weight_dst = 256 - alpha_src; *red_dst = (256 * red_src + *red_dst * weight_dst) >> 8; *green_dst = (256 * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (256 * blue_src + *blue_dst * weight_dst) >> 8; } else { int weight_dst = (256 - alpha_src); *red_dst = (256 * red_src + *red_dst * weight_dst) >> 8; *green_dst = (256 * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (256 * blue_src + *blue_dst * weight_dst) >> 8; *alpha_dst = (256 * alpha_src + *alpha_dst * weight_dst) >> 8; } } /* RFC 24: check if the parent pointer is NULL and raise an error otherwise */ int msCheckParentPointer(void* p, char *objname) { char* fmt="The %s parent object is null"; char* msg=NULL; if (p == NULL) { if(objname != NULL) { msg=malloc( sizeof(char) * ( ( strlen(fmt)+strlen(objname) ) ) ); if(msg == NULL) { msg="A required parent object is null"; } else { sprintf(msg, "The %s parent object is null", objname); } } else { msg="A required parent object is null"; } msSetError(MS_NULLPARENTERR, "%s", "", msg); return MS_FAILURE; } return MS_SUCCESS; } void msBufferInit(bufferObj *buffer) { buffer->data=NULL; buffer->size=0; buffer->available=0; buffer->_next_allocation_size = MS_DEFAULT_BUFFER_ALLOC; } void msBufferResize(bufferObj *buffer, size_t target_size) { while(buffer->available <= target_size) { buffer->data = msSmallRealloc(buffer->data,buffer->available+buffer->_next_allocation_size); buffer->available += buffer->_next_allocation_size; buffer->_next_allocation_size *= 2; } } void msBufferAppend(bufferObj *buffer, void *data, size_t length) { if(buffer->available < buffer->size+length) { msBufferResize(buffer,buffer->size+length); } memcpy(&(buffer->data[buffer->size]),data,length); buffer->size += length; } void msBufferFree(bufferObj *buffer) { if(buffer->available>0) free(buffer->data); } void msFreeRasterBuffer(rasterBufferObj *b) { switch(b->type) { case MS_BUFFER_BYTE_RGBA: msFree(b->data.rgba.pixels); b->data.rgba.pixels = NULL; break; case MS_BUFFER_BYTE_PALETTE: msFree(b->data.palette.pixels); msFree(b->data.palette.palette); b->data.palette.pixels = NULL; b->data.palette.palette = NULL; break; #ifdef USE_GD case MS_BUFFER_GD: gdImageDestroy(b->data.gd_img); b->data.gd_img = NULL; break; #endif } } /* ** Issue #3043: Layer extent comparison short circuit. ** ** msExtentsOverlap() ** ** Returns MS_TRUE if map extent and layer extent overlap, ** MS_FALSE if they are disjoint, and MS_UNKNOWN if there is ** not enough info to calculate a deterministic answer. ** */ int msExtentsOverlap(mapObj *map, layerObj *layer) { #ifdef USE_PROJ rectObj map_extent; rectObj layer_extent; #endif /* No extent info? Nothing we can do, return MS_UNKNOWN. */ if( (map->extent.minx == -1) && (map->extent.miny == -1) && (map->extent.maxx == -1 ) && (map->extent.maxy == -1) ) return MS_UNKNOWN; if( (layer->extent.minx == -1) && (layer->extent.miny == -1) && (layer->extent.maxx == -1 ) && (layer->extent.maxy == -1) ) return MS_UNKNOWN; #ifdef USE_PROJ /* No map projection? Let someone else sort this out. */ if( ! (map->projection.numargs > 0) ) return MS_UNKNOWN; /* No layer projection? Perform naive comparison, because they are ** in the same projection. */ if( ! (layer->projection.numargs > 0) ) return msRectOverlap( &(map->extent), &(layer->extent) ); /* We need to transform our rectangles for comparison, ** so we will work with copies and leave the originals intact. */ MS_COPYRECT(&map_extent, &(map->extent) ); MS_COPYRECT(&layer_extent, &(layer->extent) ); /* Transform map extents into geographics for comparison. */ if( msProjectRect(&(map->projection), &(map->latlon), &map_extent) ) return MS_UNKNOWN; /* Transform layer extents into geographics for comparison. */ if( msProjectRect(&(layer->projection), &(map->latlon), &layer_extent) ) return MS_UNKNOWN; /* Simple case? Return simple answer. */ if ( map_extent.minx < map_extent.maxx && layer_extent.minx < layer_extent.maxx ) return msRectOverlap( &(map_extent), &(layer_extent) ); /* Uh oh, one of the rects crosses the dateline! ** Let someone else handle it. */ return MS_UNKNOWN; #else /* No proj? Naive comparison. */ if( msRectOverlap( &(map->extent), &(layer->extent) ) ) return MS_TRUE; return MS_FALSE; #endif } /************************************************************************/ /* msSmallMalloc() */ /************************************************************************/ /* Safe version of malloc(). This function is taken from gdal/cpl. */ void *msSmallMalloc( size_t nSize ) { void *pReturn; if( nSize == 0 ) return NULL; pReturn = malloc( nSize ); if( pReturn == NULL ) { msIO_fprintf(stderr, "msSmallMalloc(): Out of memory allocating %ld bytes.\n", (long) nSize ); exit(1); } return pReturn; } /************************************************************************/ /* msSmallRealloc() */ /************************************************************************/ /* Safe version of realloc(). This function is taken from gdal/cpl. */ void * msSmallRealloc( void * pData, size_t nNewSize ) { void *pReturn; if ( nNewSize == 0 ) return NULL; pReturn = realloc( pData, nNewSize ); if( pReturn == NULL ) { msIO_fprintf(stderr, "msSmallRealloc(): Out of memory allocating %ld bytes.\n", (long)nNewSize ); exit(1); } return pReturn; } /************************************************************************/ /* msSmallCalloc() */ /************************************************************************/ /* Safe version of calloc(). This function is taken from gdal/cpl. */ void *msSmallCalloc( size_t nCount, size_t nSize ) { void *pReturn; if( nSize * nCount == 0 ) return NULL; pReturn = calloc( nCount, nSize ); if( pReturn == NULL ) { msIO_fprintf(stderr, "msSmallCalloc(): Out of memory allocating %ld bytes.\n", (long)(nCount*nSize)); exit(1); } return pReturn; } /* ** msBuildOnlineResource() ** ** Try to build the online resource (mapserv URL) for this service. ** "http://$(SERVER_NAME):$(SERVER_PORT)$(SCRIPT_NAME)?" ** (+append the map=... param if it was explicitly passed in QUERY_STRING) ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char *msBuildOnlineResource(mapObj *map, cgiRequestObj *req) { char *online_resource = NULL; const char *value, *hostname, *port, *script, *protocol="http", *mapparam=NULL; int mapparam_len = 0; hostname = getenv("SERVER_NAME"); port = getenv("SERVER_PORT"); script = getenv("SCRIPT_NAME"); /* HTTPS is set by Apache to "on" in an HTTPS server ... if not set */ /* then check SERVER_PORT: 443 is the default https port. */ if ( ((value=getenv("HTTPS")) && strcasecmp(value, "on") == 0) || ((value=getenv("SERVER_PORT")) && atoi(value) == 443) ) { protocol = "https"; } /* If map=.. was explicitly set then we'll include it in onlineresource */ if (req->type == MS_GET_REQUEST) { int i; for(i=0; iNumParams; i++) { if (strcasecmp(req->ParamNames[i], "map") == 0) { mapparam = req->ParamValues[i]; mapparam_len = strlen(mapparam)+5; /* +5 for "map="+"&" */ break; } } } if (hostname && port && script) { size_t buffer_size; buffer_size = strlen(hostname)+strlen(port)+strlen(script)+mapparam_len+11; /* 11 comes from https://[host]:[port][scriptname]?[map]\0, i.e. "https://:?\0" */ online_resource = (char*)msSmallMalloc(buffer_size); if ((atoi(port) == 80 && strcmp(protocol, "http") == 0) || (atoi(port) == 443 && strcmp(protocol, "https") == 0) ) snprintf(online_resource, buffer_size, "%s://%s%s?", protocol, hostname, script); else snprintf(online_resource, buffer_size, "%s://%s:%s%s?", protocol, hostname, port, script); if (mapparam) { int baselen; baselen = strlen(online_resource); snprintf(online_resource+baselen, buffer_size-baselen, "map=%s&", mapparam); } } else { msSetError(MS_CGIERR, "Impossible to establish server URL.", "msBuildOnlineResource()"); return NULL; } return online_resource; } /************************************************************************/ /* msIntegerInArray() */ /************************************************************************/ /* Check if a integer is in a array */ int msIntegerInArray(const int value, int *array, int numelements) { int i; for (i=0; iprojection.numargs <= 0) { msSetError(MS_WMSERR, "Cannot set new SRS on a map that doesn't " "have any projection set. Please make sure your mapfile " "has a PROJECTION defined at the top level.", "msTileSetProjectionst()"); return(MS_FAILURE); } for(i=0; inumlayers; i++) { /* This layer is turned on and needs a projection? */ if (GET_LAYER(map, i)->projection.numargs <= 0 && GET_LAYER(map, i)->status != MS_OFF && GET_LAYER(map, i)->transform == MS_TRUE) { /* Fetch main map projection string only now that we need it */ if (mapProjStr == NULL) mapProjStr = msGetProjectionString(&(map->projection)); /* Set the projection to the map file projection */ if (msLoadProjectionString(&(GET_LAYER(map, i)->projection), mapProjStr) != 0) { msSetError(MS_CGIERR, "Unable to set projection on layer.", "msTileSetProjectionst()"); return(MS_FAILURE); } GET_LAYER(map, i)->project = MS_TRUE; } } msFree(mapProjStr); return(MS_SUCCESS); } /* Generalize a shape based of the tolerance. Ref: http://trac.osgeo.org/gdal/ticket/966 */ shapeObj* msGeneralize(shapeObj *shape, double tolerance) { shapeObj *newShape; lineObj newLine = {0,NULL}; double sqTolerance = tolerance*tolerance; double dX0, dY0, dX1, dY1, dX, dY, dSqDist; int i; newShape = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(newShape); msCopyShape(shape, newShape); if (shape->numlines<1) return newShape; /* Clean shape */ for (i=0; i < newShape->numlines; i++) free(newShape->line[i].point); newShape->numlines = 0; if (newShape->line) free(newShape->line); msAddLine(newShape, &newLine); if (shape->line[0].numpoints>0) { msAddPointToLine(&newShape->line[0], &shape->line[0].point[0]); dX0 = shape->line[0].point[0].x; dY0 = shape->line[0].point[0].y; } for(i=1; iline[0].numpoints; i++) { dX1 = shape->line[0].point[i].x; dY1 = shape->line[0].point[i].y; dX = dX1-dX0; dY = dY1-dY0; dSqDist = dX*dX + dY*dY; if (i == shape->line[0].numpoints-1 || dSqDist >= sqTolerance) { pointObj p; p.x = dX1; p.y = dY1; /* Keep this point (always keep the last point) */ msAddPointToLine(&newShape->line[0], &p); dX0 = dX1; dY0 = dY1; } } return newShape; } mapserver-6.4.1/testexpr.c0000644002461700001440000000452112261257215015340 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Commandline tester for expression evaluation * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include "mapserver.h" #include "mapparser.h" #include "mapfile.h" extern int msyyparse(); extern int msyylex(); extern char *msyystring_buffer; extern int msyyresult; /* result of parsing, true/false */ extern int msyystate; extern char *msyystring; int main(int argc, char *argv[]) { int status; if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } /* ---- check the number of arguments, return syntax if not correct ---- */ if( argc < 2) { fprintf(stdout, "Syntax: testexpr [string]\n"); exit(0); } msyystate = MS_TOKENIZE_EXPRESSION; msyystring = argv[1]; status = msyyparse(); if(status != 0) printf("Error parsing expression near %s.\n", msyystring_buffer); else printf("Expression evalulated to: %d.\n", msyyresult); exit(0); } mapserver-6.4.1/mapoglrenderer.cpp0000644002461700001440000005656712261257215017051 0ustar tbonfortusers/****************************************************************************** * $id: mapoglrenderer.cpp 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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. ****************************************************************************/ #ifdef USE_OGL #include #include #include "mapserver.h" #include "maperror.h" #include "mapoglrenderer.h" using namespace std; double OglRenderer::SIZE_RES = 100.0 / 72.0; ms_uint32 OglRenderer::OUTLINE_WIDTH = 2; ms_uint32 OglRenderer::FONT_SIZE = 20; ms_uint32 OglRenderer::FONT_RES = 200; double OglRenderer::OGL_PI = 3.14159265; ms_uint32 OglRenderer::SHAPE_CIRCLE_RES = 10; double OglRenderer::SHAPE_CIRCLE_RADIUS = 10.0; OglRenderer::fontCache_t OglRenderer::fontCache = OglRenderer::fontCache_t(); OglRenderer::dashCache_t OglRenderer::dashCache = OglRenderer::dashCache_t(); std::vector OglRenderer::shapes = std::vector(); GLvoid CALLBACK beginCallback(GLenum which); GLvoid CALLBACK errorCallback(GLenum errorCode); GLvoid CALLBACK endCallback(void); GLvoid CALLBACK combineDataCallback(GLdouble coords[3], GLdouble* vertex_data[4], GLfloat weight[4], void** dataOut, void* polygon_data); GLvoid CALLBACK vertexCallback(GLdouble *vertex); OglRenderer::OglRenderer(ms_uint32 width, ms_uint32 height, colorObj* color) : width(width), height(height), texture(NULL), transparency(1.0), valid(false) { context = new OglContext(width, height); if (!context->isValid()) return; if (!context->makeCurrent()) return; int viewPort[4]; glGetIntegerv(GL_VIEWPORT ,viewPort); viewportX = viewPort[0]; viewportY = viewPort[1]; viewportWidth = viewPort[2]; viewportHeight = viewPort[3]; glPushMatrix(); // set read/write context to pbuffer glEnable(GL_MULTISAMPLE_ARB); glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glDisable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // draw & read the front buffer of pbuffer glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); if (!(tess = gluNewTess())) { msSetError(MS_OGLERR, "P-buffer Error: Unable to create tessalotor", "OglRenderer"); return; } gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK*)(void)) vertexCallback); gluTessCallback(tess, GLU_TESS_BEGIN, (void(CALLBACK*)(void)) beginCallback); gluTessCallback(tess, GLU_TESS_END, (void(CALLBACK*)(void)) endCallback); gluTessCallback(tess, GLU_TESS_ERROR, (void(CALLBACK*)(void)) errorCallback); gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (void(CALLBACK*)(void)) combineDataCallback); if (color) { glClearColor((double) color->red / 255, (double) color->green / 255, (double) color->blue / 255, (double)color->alpha / 100); } else { glClearColor(0.0, 0.0, 0.0, 0.0); } glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, width, 0.0, height, -3.0, 3.0); createShapes(); valid = true; } OglRenderer::~OglRenderer() { makeCurrent(); glViewport(viewportX, viewportY, viewportWidth, viewportHeight); glPopMatrix(); delete context; } OglCachePtr OglRenderer::getTexture() { if (!texture) { makeCurrent(); texture = new OglCache(); texture->texture = createTexture(0,0);//TEXTURE_BORDER/2, TEXTURE_BORDER/2); texture->width = this->width; texture->height = this->height; } return texture; } GLuint OglRenderer::createTexture(ms_uint32 offsetX, ms_uint32 offsetY) { GLuint texture = 0; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST); if (OglContext::MAX_ANISOTROPY != 0) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, OglContext::MAX_ANISOTROPY); } glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offsetX, offsetY, context->getWidth(), context->getHeight(), 0); glBindTexture(GL_TEXTURE_2D,0); return texture; } bool OglRenderer::getStringBBox(char *font, double size, char *string, rectObj *rect, double** advances) { FTFont* face = getFTFont(font, size); if (!face) { msSetError(MS_OGLERR, "Failed to load font (%s).", "OglRenderer::getStringBBox()", font); return false; } float llx =0.0f, lly=0.0f, llz=0.0f, urx=0.0f, ury=0.0f, urz=0.0f; glPushAttrib( GL_ALL_ATTRIB_BITS ); FTBBox boundingBox = face->BBox(string); glPopAttrib(); rect->minx = boundingBox.Lower().X(); rect->maxx = boundingBox.Upper().X(); rect->miny = -boundingBox.Upper().Y(); rect->maxy = -boundingBox.Lower().Y(); if (advances) { int length = strlen(string); *advances = new double[length]; for (int i = 0; i < length; ++i) { (*advances)[i] = face->Advance(&string[i], 1); } } return true; } void OglRenderer::initializeRasterBuffer(rasterBufferObj * rb, int width, int height, bool useAlpha) { unsigned char* buffer = new unsigned char[4 * width * height]; rb->data.rgba.pixels = buffer; rb->data.rgba.r = &buffer[2]; rb->data.rgba.g = &buffer[1]; rb->data.rgba.b = &buffer[0]; if (useAlpha) rb->data.rgba.a = &buffer[3]; rb->type =MS_BUFFER_BYTE_RGBA; rb->data.rgba.row_step = 4*width; rb->data.rgba.pixel_step = 4; rb->width = width; rb->height = height; } void OglRenderer::readRasterBuffer(rasterBufferObj * rb) { makeCurrent(); unsigned char* buffer = new unsigned char[4 * width * height]; glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, buffer); rb->type =MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixels = buffer; rb->data.rgba.row_step = 4*width; rb->data.rgba.pixel_step = 4; rb->width = width; rb->height = height; rb->data.rgba.r = &buffer[2]; rb->data.rgba.g = &buffer[1]; rb->data.rgba.b = &buffer[0]; rb->data.rgba.a = NULL; } void OglRenderer::drawRasterBuffer(rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { // todo to support all alpha and srcx/y this needs to be done by creating a texture makeCurrent(); glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, overlay->data.rgba.pixels); } void OglRenderer::setTransparency(double transparency) { this->transparency = transparency; } void OglRenderer::setColor(colorObj *color) { if (color && MS_VALID_COLOR(*color)) { glColor4d((double) color->red / 255, (double) color->green / 255, (double) color->blue / 255, transparency); } else { glColor4d(0.0, 0.0, 0.0, 1.0); } } void OglRenderer::drawVectorLineStrip(symbolObj *symbol, double width) { glPushMatrix(); glLineWidth(width); glBegin(GL_LINE_STRIP); for (int i = 0; i < symbol->numpoints; i++) { if (symbol->points[i].x < 0 && symbol->points[i].y < 0) { glEnd(); glBegin(GL_LINE_STRIP); } else { glVertex2d(symbol->points[i].x, symbol->points[i].y); } } glEnd(); glPopMatrix(); } double OglRenderer::drawTriangles(pointObj* p1, pointObj* p2, double width, double tilelength, double textureStart) { double dx = p1->x - p2->x; double dy = p1->y - p2->y; double dist = sqrt(dx * dx + dy * dy); double theta; if (dx != 0) theta = atan(dy / dx); else theta = (dy > 0 ? 1 : -1) * OGL_PI / 2; double xw = sin(theta) * width / 2; double yw = cos(theta) * width / 2; double textureEnd = dist / tilelength; glTexCoord2d(textureStart, 1); glVertex2d(p1->x + xw, p1->y - yw); // Bottom Left Of The Texture and Quad glTexCoord2d(textureStart, 0); glVertex2d(p1->x - xw, p1->y + yw); // Bottom Right Of The Texture and Quad glTexCoord2d(textureStart + textureEnd, 1); glVertex2d(p2->x + xw, p2->y - yw); // Top Right Of The Texture and Quad glTexCoord2d(textureStart + textureEnd, 0); glVertex2d(p2->x - xw, p2->y + yw); // Top Left Of The Texture and Quad return dist; } double OglRenderer::drawQuad(pointObj* p1, pointObj* p2, double width, double tilelength, double textureStart) { double dx = p1->x - p2->x; double dy = p1->y - p2->y; double dist = sqrt(dx * dx + dy * dy); double theta; if (dx) theta = atan(dy / dx); else theta = (dy > 0 ? 1 : -1) * OGL_PI / 2; glPushMatrix(); glTranslated(p1->x, p1->y, 0); glRotated((p1->x < p2->x ? 0 : 180) + theta * (180 / OGL_PI), 0, 0, 1); glTranslated(-p1->x, -p1->y, 0); glBegin(GL_QUADS); glTexCoord2d(textureStart, 1); glVertex2d(p1->x, p1->y - width / 2); // Bottom Left Of The Texture and Quad glTexCoord2d(textureStart + (dist / tilelength), 1); glVertex2d(p1->x + dist, p1->y - width / 2); // Bottom Right Of The Texture and Quad glTexCoord2d(textureStart + (dist / tilelength), 0); glVertex2d(p1->x + dist, p1->y + width / 2); // Top Right Of The Texture and Quad glTexCoord2d(textureStart, 0); glVertex2d(p1->x, p1->y + width / 2); // Top Left Of The Texture and Quad glEnd(); glPopMatrix(); return dist; } void OglRenderer::renderTile(const OglCachePtr& tile, double x, double y, double angle) { makeCurrent(); glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glBindTexture(GL_TEXTURE_2D, tile->texture); glPushMatrix(); glTranslated(x, y, 0); if (angle) { glRotated(angle, 0, 0, 1); } glTranslated(-x, -y, 0); glBegin(GL_QUADS); glTexCoord2d(0, 1); glVertex2d( x-(tile->width/2), y+(tile->height/2)); // Bottom Left Of The Texture and Quad glTexCoord2d(1, 1); glVertex2d( x+(tile->width/2), y+(tile->height/2)); // Bottom Right Of The Texture and Quad glTexCoord2d(1, 0); glVertex2d( x+(tile->width/2), y-(tile->height/2)); // Top Right Of The Texture and Quad glTexCoord2d(0, 0); glVertex2d( x-(tile->width/2), y-(tile->height/2)); // Top Left Of The Texture and Quad glEnd(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); } void OglRenderer::renderPolylineTile(shapeObj *shape, const OglCachePtr& tile) { makeCurrent(); glBindTexture(GL_TEXTURE_2D, tile->texture); // Select Our Texture glBegin(GL_TRIANGLE_STRIP); double place = 0.0; for (int i = 0; i < shape->numlines; i++) { for (int j = 0; j < shape->line[i].numpoints - 1; j++) { double dist = drawTriangles(&shape->line[i].point[j], &shape->line[i].point[j + 1], tile->height, tile->width, place / tile->width); place = (place + dist); while (place >= tile->width) place -= tile->width; } } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } void OglRenderer::renderVectorSymbol(double x, double y, symbolObj *symbol, double scale, double angle, colorObj *c, colorObj *oc, double ow) { makeCurrent(); glPushMatrix(); glTranslated(x, y, 0); glRotated(angle, 0, 0, 1); glScaled(scale, scale, 0); glTranslated(-symbol->sizex/2, -symbol->sizey/2, 0.0); if (oc != NULL && MS_VALID_COLOR(*oc) && ow > 0) { setColor(oc); drawVectorLineStrip(symbol, ow); } if (c != NULL && MS_VALID_COLOR(*c) && ow > 0) { setColor(c); drawVectorLineStrip(symbol, ow); } glPopMatrix(); } void OglRenderer::renderPolyline(shapeObj *p, colorObj *c, double width, int patternlength, double* pattern, int lineCap, int joinStyle, colorObj *outlinecolor, double outlinewidth) { makeCurrent(); if (outlinecolor) { glEnable(GL_DEPTH_TEST); glPushMatrix(); glTranslated(0, 0, 1); } setColor(c); if (patternlength > 0) { if (p->renderer_cache == NULL) { loadLine(p, width, patternlength, pattern); } /* FIXME */ if (p->renderer_cache == NULL) return; OglCache* cache = (OglCache*) p->renderer_cache; GLuint texture = cache->texture; if (cache->patternDistance > 0) { glBindTexture(GL_TEXTURE_2D, texture); double place = 0; glBegin(GL_TRIANGLE_STRIP); for (int j = 0; j < p->numlines; j++) { for (int i = 0; i < p->line[j].numpoints - 1; i++) { double dist = drawTriangles(&p->line[j].point[i], &p->line[j].point[i + 1], width, cache->patternDistance, place / cache->patternDistance); place = (place + dist); while (place >= cache->patternDistance) place -= cache->patternDistance; // better than mod, no rounding } } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } } else { float widthRange[2]; glGetFloatv(GL_LINE_WIDTH_RANGE, widthRange); bool quads = !(width >= widthRange[0] && width <= widthRange[1]); double circleScale = width / SHAPE_CIRCLE_RADIUS / 2; glLineWidth(width); if (quads || (width > 1.0 && (lineCap == MS_CJC_ROUND || joinStyle == MS_CJC_ROUND))) { for (int j = 0; j < p->numlines; j++) { for (int i = 0; i < p->line[j].numpoints; i++) { if (i != p->line[j].numpoints - 1) { if (quads) { drawQuad(&p->line[j].point[i], &p->line[j].point[i + 1], width); } else { glBegin(GL_LINES); glVertex2f(p->line[j].point[i].x, p->line[j].point[i].y); glVertex2f(p->line[j].point[i + 1].x,p->line[j].point[i + 1].y); glEnd(); } } if ((lineCap == MS_CJC_ROUND && (i == 0 || i == p->line[j].numpoints - 1)) || (joinStyle == MS_CJC_ROUND && (i > 0 && i < p->line[j].numpoints - 1))) { glPushMatrix(); glTranslated(p->line[j].point[i].x, p->line[j].point[i].y, 0); glScaled(circleScale, circleScale, 0); glCallList(shapes[circle]); glPopMatrix(); } } } } else { for (int j = 0; j < p->numlines; j++) { glBegin(GL_LINE_STRIP); for (int i = 0; i < p->line[j].numpoints; i++) { glVertex2f(p->line[j].point[i].x, p->line[j].point[i].y); } glEnd(); } } } if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor)) { glPopMatrix(); double owidth = MS_MAX(width + OUTLINE_WIDTH, outlinewidth); glPushMatrix(); glTranslated(0, 0, -1); renderPolyline(p, outlinecolor, owidth, patternlength, pattern, lineCap, joinStyle); glPopMatrix(); glDisable(GL_DEPTH_TEST); } } void OglRenderer::renderPolygon(shapeObj *p, colorObj *color, colorObj *outlinecolor, double outlinewidth, const OglCachePtr& tile, int lineCap, int joinStyle) { /* OpenGL cannot draw complex polygons so we need to use a Tessallator to draw the polygon using a GL_TRIANGLE_FAN ISSUE: There's a problem here. It would seem that changing the dimensions or bounding box area breaks the code. Reports need for a combine callback. */ makeCurrent(); std::vector pointers; double texWidth = 0; double texHeight = 0; if (tile) { glBindTexture(GL_TEXTURE_2D, tile->texture); // Select Our Texture texWidth = tile->width; texHeight = tile->height; } setColor(color); gluTessBeginPolygon(tess, NULL ); for (int j = 0; j < p->numlines; j++) { gluTessBeginContour(tess); for (int i = 0; i < p->line[j].numpoints; i++) { // create temp array and place GLdouble* dbls = new GLdouble[5]; pointers.push_back(dbls); dbls[0] = p->line[j].point[i].x; dbls[1] = p->line[j].point[i].y; dbls[2] = 0.0; dbls[3] = texWidth; dbls[4] = texHeight; gluTessVertex(tess, dbls, dbls); } gluTessEndContour(tess); } gluTessEndPolygon(tess); // destroy temp arrays for (std::vector::iterator iter = pointers.begin(); iter != pointers.end(); iter++) { delete[] *iter; } glBindTexture(GL_TEXTURE_2D, 0); // Select Our Texture if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor) && outlinewidth > 0) { renderPolyline(p, outlinecolor, outlinewidth, 0, NULL, lineCap, joinStyle); } } void OglRenderer::renderGlyphs(double x, double y, colorObj *color, colorObj *outlinecolor, double size, const char* font, char *thechars, double angle, colorObj *shadowcolor, double shdx, double shdy) { makeCurrent(); FTFont* face = getFTFont(font, size); if (!face) { msSetError(MS_OGLERR, "Failed to load font (%s).", "OglRenderer::renderGlyphs()", font); return; } glPushAttrib(GL_ALL_ATTRIB_BITS); glPushMatrix(); glTranslated(floor(x), floor(y), 0); glScaled(1.0, -1.0, 1); glRotated(angle * (180 / OGL_PI), 0, 0, 1); if (outlinecolor && MS_VALID_COLOR(*outlinecolor)) { setColor(outlinecolor); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i || j) { glPushMatrix(); glTranslated(i, j, 0); face->Render(thechars); glPopMatrix(); } } } } if (color != NULL && MS_VALID_COLOR(*color)) { setColor(color); face->Render(thechars); } glPopMatrix(); glPopAttrib(); } void OglRenderer::renderPixmap(symbolObj *symbol, double x, double y, double angle, double scale) { makeCurrent(); float zoomX, zoomY; glGetFloatv(GL_ZOOM_X, &zoomX); glGetFloatv(GL_ZOOM_Y, &zoomY); GLubyte* imgdata = symbol->pixmap_buffer->data.rgba.pixels; glPixelZoom(zoomX*scale, zoomY*scale); glRasterPos2d(x-symbol->pixmap_buffer->width/2, y-symbol->pixmap_buffer->height/2); glDrawPixels(symbol->pixmap_buffer->width, symbol->pixmap_buffer->height, GL_BGRA, GL_UNSIGNED_BYTE, imgdata); glPixelZoom(zoomX, zoomY); } void OglRenderer::renderEllipse(double x, double y, double angle, double width, double height, colorObj *color, colorObj *outlinecolor, double outlinewidth = 1.0) { makeCurrent(); if (outlinecolor && MS_VALID_COLOR(*outlinecolor)) { glEnable(GL_DEPTH_TEST); glPushMatrix(); glTranslated(0, 0, 1); } setColor(color); glPushMatrix(); if (angle) { glRotated(angle, 0, 0, 1); } glTranslated(x, y, 0); glScaled(width / SHAPE_CIRCLE_RADIUS / 2, height / SHAPE_CIRCLE_RADIUS / 2, 1); glCallList(shapes[circle]); glPopMatrix(); if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor)) { glPopMatrix(); glPushMatrix(); glTranslated(0, 0, -1); renderEllipse(x, y, angle, width + outlinewidth, height, outlinecolor, NULL, 0); glPopMatrix(); glDisable(GL_DEPTH_TEST); } } bool OglRenderer::loadLine(shapeObj* shape, double width, int patternlength, double* pattern) { /* OglCache* cache = (OglCache*) shape->renderer_cache; if (cache->patternDistance == 0) { for (int i = 0; i < patternlength; i++) { cache->patternDistance += pattern[i]; } } GLubyte imgdata[TEX_SIZE * TEX_SIZE * 4]; int pow2length = min(max(NextPowerOf2(cache->patternDistance), MIN_TEX_SIZE), TEX_SIZE); int pow2width = min(max(NextPowerOf2(width), MIN_TEX_SIZE), TEX_SIZE); double lengthScale = (double) pow2length / cache->patternDistance; glColor3d(0, 0, 0); double place = 0; double xRadii = width / 2 * lengthScale; double yRadii = pow2width / 2; for (int i = 0; i < patternlength; i++) { double next = pattern[i] * lengthScale; if (i % 2 == 0) { glPushMatrix(); glTranslated(place + xRadii, yRadii, 0); glScaled(xRadii / SHAPE_CIRCLE_RADIUS, yRadii / SHAPE_CIRCLE_RADIUS, 0); glCallList(shapes[circle]); glPopMatrix(); glBegin(GL_QUADS); glVertex2d(place + pow2width / 2, 0); glVertex2d(place + next - pow2width / 2, 0); glVertex2d(place + next - pow2width / 2, pow2width); glVertex2d(place + pow2width / 2, pow2width); glEnd(); glPushMatrix(); glTranslated(place + next - xRadii, yRadii, 0); glScaled(xRadii / SHAPE_CIRCLE_RADIUS, yRadii / SHAPE_CIRCLE_RADIUS, 0); glCallList(shapes[circle]); glPopMatrix(); } place += next; } glReadPixels(0, 0, pow2length, pow2width, GL_RGBA, GL_UNSIGNED_BYTE, imgdata); //createTexture(pow2length, pow2width, GL_ALPHA, imgdata);*/ return true; } FTFont* OglRenderer::getFTFont(const char* font, double size) { FTFont** face = &fontCache[font][size]; if (*face == NULL && ifstream(font)) { *face = new FTGLTextureFont( font ); if (*face) { (*face)->UseDisplayList(true); (*face)->FaceSize(size*SIZE_RES); } } return *face; } GLvoid CALLBACK beginCallback(GLenum which) { glBegin(which); } GLvoid CALLBACK errorCallback(GLenum errorCode) { const GLubyte *estring; estring = gluErrorString(errorCode); fprintf(stderr, "Tessellation Error: %d %s\n", errorCode, estring); exit(0); } GLvoid CALLBACK endCallback(void) { glEnd(); } GLvoid CALLBACK combineDataCallback(GLdouble coords[3], GLdouble* vertex_data[4], GLfloat weight[4], void** dataOut, void* polygon_data) { GLdouble *vertex; vertex = (GLdouble *) malloc(5 * sizeof(GLdouble)); vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; vertex[3] = vertex_data[0][3]; vertex[4] = vertex_data[0][4]; *dataOut = vertex; } GLvoid CALLBACK vertexCallback(GLdouble *vertex) { if (vertex[3] > 0) glTexCoord2d(vertex[0]/vertex[3], vertex[1]/vertex[4]); glVertex3dv(vertex); } void OglRenderer::createShapes() { double da = MS_MIN(OGL_PI / 2, OGL_PI / SHAPE_CIRCLE_RES); GLuint circle = glGenLists(1); glNewList(circle, GL_COMPILE); glBegin(GL_TRIANGLE_FAN); glVertex2d(0, 0); for (double a = 0.0; a <= 2 * OGL_PI; a += da) { glVertex2d(0 + cos(a) * SHAPE_CIRCLE_RADIUS, 0 + sin(a) * SHAPE_CIRCLE_RADIUS); } glVertex2d(0 + SHAPE_CIRCLE_RADIUS, 0); glEnd(); glEndList(); shapes.push_back(circle); } void OglRenderer::makeCurrent() { context->makeCurrent(); } #endif mapserver-6.4.1/mapaxisorder.h0000644002461700001440000113324112261257215016170 0ustar tbonfortusers/****************************************************************************** * $Id: $ * * Project: MapServer * Purpose: Axis lookup table * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* * Generated file * * This file was generated from by means of a script. Do not edit manually. */ #ifdef __cplusplus extern "C" { #endif static unsigned char axisOrientationEpsgCodes[] = { 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0 }; #ifdef __cplusplus } #endif mapserver-6.4.1/mapwms.c0000644002461700001440000066546512261257215015012 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OpenGIS Web Mapping Service support implementation. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #define _GNU_SOURCE #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include "mapgml.h" #include #include "maptemplate.h" #include "mapogcsld.h" #include "mapogcfilter.h" #include "maptime.h" #include "mapproject.h" #include #include #include #ifdef WIN32 #include #endif /* ================================================================== * WMS Server stuff. * ================================================================== */ #ifdef USE_WMS_SVR #ifdef USE_OGR int ogrEnabled = 1; #else int ogrEnabled = 0; #endif /* USE_OGR */ /* ** msWMSException() ** ** Report current MapServer error in requested format. */ int msWMSException(mapObj *map, int nVersion, const char *exception_code, char *wms_exception_format) { const char *encoding; char *schemalocation = NULL; /* Default to WMS 1.3.0 exceptions if version not set yet */ if (nVersion <= 0) nVersion = OWS_1_3_0; /* get scheam location */ schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); /* Establish default exception format depending on VERSION */ if (wms_exception_format == NULL) { if (nVersion <= OWS_1_0_0) wms_exception_format = "INIMAGE"; /* WMS 1.0.0 */ else if (nVersion <= OWS_1_0_7) wms_exception_format = "SE_XML"; /* WMS 1.0.1 to 1.0.7 */ else if (nVersion <= OWS_1_1_1) wms_exception_format = "application/vnd.ogc.se_xml"; /* WMS 1.1.0 and later */ else wms_exception_format = "text/xml"; } if (strcasecmp(wms_exception_format, "INIMAGE") == 0 || strcasecmp(wms_exception_format, "BLANK") == 0 || strcasecmp(wms_exception_format, "application/vnd.ogc.se_inimage")== 0 || strcasecmp(wms_exception_format, "application/vnd.ogc.se_blank") == 0) { int blank = 0; if (strcasecmp(wms_exception_format, "BLANK") == 0 || strcasecmp(wms_exception_format, "application/vnd.ogc.se_blank") == 0) { blank = 1; } msWriteErrorImage(map, NULL, blank); } else if (strcasecmp(wms_exception_format, "WMS_XML") == 0) { /* Only in V1.0.0 */ if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf("\n"); } else /* XML error, the default: SE_XML (1.0.1 to 1.0.7) */ /* or application/vnd.ogc.se_xml (1.1.0 and later) */ { if (nVersion <= OWS_1_0_7) { /* In V1.0.1 to 1.0.7, the MIME type was text/xml */ if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n"); msIO_printf("\n"); } else if (nVersion <= OWS_1_1_0) { /* In V1.1.0 and later, we have OGC-specific MIME types */ /* we cannot return anything else than application/vnd.ogc.se_xml here. */ if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.se_xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.se_xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n",schemalocation); msIO_printf("\n"); } else if (nVersion <= OWS_1_1_1) { /* 1.1.1 */ if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.se_xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.se_xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n", schemalocation); msIO_printf("\n"); } else { /*1.3.0*/ if (strcasecmp(wms_exception_format, "application/vnd.ogc.se_xml") == 0) { if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.se_xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.se_xml"); } else { if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); } msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n", schemalocation); } if (exception_code) msIO_printf("\n", exception_code); else msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf("\n"); msIO_printf("\n"); } free(schemalocation); return MS_FAILURE; /* so that we can call 'return msWMSException();' anywhere */ } int msWMSSetTimePattern(const char *timepatternstring, char *timestring, int checkonly) { char **atimes, **ranges, **patterns; int numtimes, numpatterns, numranges, i, j, k; char *tmpstr = NULL; int ret = MS_SUCCESS; if (timepatternstring && timestring) { /* parse the time parameter to extract a distinct time. */ /* time value can be dicrete times (eg 2004-09-21), */ /* multiple times (2004-09-21, 2004-09-22, ...) */ /* and range(s) (2004-09-21/2004-09-25, 2004-09-27/2004-09-29) */ atimes = msStringSplit(timestring, ',', &numtimes); /* get the pattern to use */ if (numtimes>0) { patterns = msStringSplit(timepatternstring, ',', &numpatterns); for (j=0; j 0) { msStringTrimBlanks(patterns[i]); tmpstr = msStringTrimLeft(patterns[i]); if (msTimeMatchPattern(ranges[k], tmpstr) == MS_TRUE) { if (!checkonly) msSetLimitedPattersToUse(tmpstr); match = MS_TRUE; break; } } } if (match == MS_FALSE) { msSetError(MS_WMSERR, "Time value %s given does not match the time format pattern.", "msWMSSetTimePattern", ranges[k]); ret = MS_FAILURE; break; } } msFreeCharArray(ranges, numranges); if (ret == MS_FAILURE) break; } msFreeCharArray(patterns, numpatterns); msFreeCharArray(atimes, numtimes); } } return ret; } /* ** Apply the TIME parameter to layers that are time aware */ int msWMSApplyTime(mapObj *map, int version, char *time, char *wms_exception_format) { int i=0; layerObj *lp = NULL; const char *timeextent, *timefield, *timedefault, *timpattern = NULL; if (map) { timpattern = msOWSLookupMetadata(&(map->web.metadata), "MO", "timeformat"); for (i=0; inumlayers; i++) { lp = (GET_LAYER(map, i)); if (lp->status != MS_ON && lp->status != MS_DEFAULT) continue; /* check if the layer is time aware */ timeextent = msOWSLookupMetadata(&(lp->metadata), "MO", "timeextent"); timefield = msOWSLookupMetadata(&(lp->metadata), "MO", "timeitem"); timedefault = msOWSLookupMetadata(&(lp->metadata), "MO", "timedefault"); if (timeextent && timefield) { /* check to see if the time value is given. If not */ /* use default time. If default time is not available */ /* send an exception */ if (time == NULL || strlen(time) <=0) { if (timedefault == NULL) { msSetError(MS_WMSERR, "No Time value was given, and no default time value defined.", "msWMSApplyTime"); return msWMSException(map, version, "MissingDimensionValue", wms_exception_format); } else { if (msValidateTimeValue((char *)timedefault, timeextent) == MS_FALSE) { msSetError(MS_WMSERR, "No Time value was given, and the default time value %s is invalid or outside the time extent defined %s", "msWMSApplyTime", timedefault, timeextent); /* return MS_FALSE; */ return msWMSException(map, version, "InvalidDimensionValue", wms_exception_format); } msLayerSetTimeFilter(lp, timedefault, timefield); } } else { /* check to see if there is a list of possible patterns defined */ /* if it is the case, use it to set the time pattern to use */ /* for the request. Last argument is set to TRUE (checkonly) to not trigger the patterns info setting.. to only apply the wms_timeformats on the user request values, not the mapfile values. */ if (timpattern && time && strlen(time) > 0) if (msWMSSetTimePattern(timpattern, time, MS_TRUE) == MS_FAILURE) return msWMSException(map, version,"InvalidDimensionValue", wms_exception_format); /* check if given time is in the range */ if (msValidateTimeValue(time, timeextent) == MS_FALSE) { if (timedefault == NULL) { msSetError(MS_WMSERR, "Time value(s) %s given is invalid or outside the time extent defined (%s).", "msWMSApplyTime", time, timeextent); /* return MS_FALSE; */ return msWMSException(map, version, "InvalidDimensionValue", wms_exception_format); } else { if (msValidateTimeValue((char *)timedefault, timeextent) == MS_FALSE) { msSetError(MS_WMSERR, "Time value(s) %s given is invalid or outside the time extent defined (%s), and default time set is invalid (%s)", "msWMSApplyTime", time, timeextent, timedefault); /* return MS_FALSE; */ return msWMSException(map, version, "InvalidDimensionValue", wms_exception_format); } else msLayerSetTimeFilter(lp, timedefault, timefield); } } else { /* build the time string */ msLayerSetTimeFilter(lp, time, timefield); timeextent= NULL; } } } } /* last argument is MS_FALSE to trigger a method call that set the patterns info. some drivers use it */ if (timpattern && time && strlen(time) > 0) if (msWMSSetTimePattern(timpattern, time, MS_FALSE) == MS_FAILURE) return msWMSException(map, version,"InvalidDimensionValue", wms_exception_format); } return MS_SUCCESS; } /* ** msWMSPrepareNestedGroups() ** ** purpose: Parse WMS_LAYER_GROUP settings into arrays ** ** params: ** - nestedGroups: This array holds the arrays of groups that have been set ** through the WMS_LAYER_GROUP metadata ** - numNestedGroups: This array holds the number of groups set in ** WMS_LAYER_GROUP for each layer ** - isUsedInNestedGroup: This array indicates if the layer is used as group ** as set through the WMS_LAYER_GROUP metadata */ void msWMSPrepareNestedGroups(mapObj* map, int nVersion, char*** nestedGroups, int* numNestedGroups, int* isUsedInNestedGroup) { int i, j, k; const char* groups; char* errorMsg; for (i = 0; i < map->numlayers; i++) { nestedGroups[i] = NULL; /* default */ numNestedGroups[i] = 0; /* default */ isUsedInNestedGroup[i] = 0; /* default */ groups = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "MO", "layer_group"); if ((groups != NULL) && (strlen(groups) != 0)) { if (GET_LAYER(map, i)->group != NULL && strlen(GET_LAYER(map, i)->group) != 0) { errorMsg = "It is not allowed to set both the GROUP and WMS_LAYER_GROUP for a layer"; msSetError(MS_WMSERR, errorMsg, "msWMSPrepareNestedGroups()", NULL); msIO_fprintf(stdout, "\n", errorMsg); /* cannot return exception at this point because we are already writing to stdout */ } else { if (groups[0] != '/') { errorMsg = "The WMS_LAYER_GROUP metadata does not start with a '/'"; msSetError(MS_WMSERR, errorMsg, "msWMSPrepareNestedGroups()", NULL); msIO_fprintf(stdout, "\n", errorMsg); /* cannot return exception at this point because we are already writing to stdout */ } else { /* split into subgroups. Start at address + 1 because the first '/' would cause an extra empty group */ nestedGroups[i] = msStringSplit(groups + 1, '/', &numNestedGroups[i]); /* */ for (j = 0; j < map->numlayers; j++) { if (isUsedInNestedGroup[j]) continue; for (k=0; kname && strcasecmp(GET_LAYER(map, j)->name, nestedGroups[i][k]) == 0 ) { isUsedInNestedGroup[j] = 1; break; } } } } } } } } /* ** Validate that a given dimension is inside the extents defined */ int msWMSValidateDimensionValue(char *value, const char *dimensionextent, int forcecharcter) { char **extents=NULL, **ranges=NULL, **onerange=NULL; int numextents; char **aextentvalues = NULL; int nextentvalues=0; pointObj *aextentranges=NULL; int nextentranges=0; int isextentavalue = MS_FALSE, isextentarange=MS_FALSE; int i,j, ntmp; char **uservalues=NULL; int numuservalues=0; char *stmp = NULL; int ischaracter = MS_FALSE; float minval, maxval,currentval,mincurrentval,maxcurrentval, mincurrentrange, maxcurrentrange; int uservaluevalid= MS_FALSE; if (forcecharcter) ischaracter = MS_TRUE; if (!value || !dimensionextent) return MS_FALSE; /*for the value, we support descrete values (2005) */ /* multiple values (abc, def, ...) */ /* and range(s) (1000/2000, 3000/5000) */ /** we do not support resolution*/ /* -------------------------------------------------------------------- */ /* parse the extent first. */ /* -------------------------------------------------------------------- */ extents = msStringSplit (dimensionextent, ',', &numextents); if (numextents == 1) { if (strstr(dimensionextent, "/") == NULL) { /*single value*/ isextentavalue = MS_TRUE; nextentvalues = 1; aextentvalues = (char **)msSmallMalloc(sizeof(char *)); msStringTrim(extents[0]); aextentvalues[0] = msStrdup(dimensionextent); if (!forcecharcter) ischaracter= !FLTIsNumeric((char *)dimensionextent); } else { ntmp = -1; ranges = msStringSplit (dimensionextent, '/', &ntmp); if(ranges && (ntmp == 2 || ntmp == 3)) { /*single range*/ isextentarange = MS_TRUE; aextentranges = msSmallMalloc(sizeof(pointObj)); nextentranges=1; aextentranges[0].x = atof(ranges[0]); aextentranges[0].y = atof(ranges[1]); /*ranges should be numeric*/ ischaracter = MS_FALSE; } if (ranges && ntmp > 0) { msFreeCharArray(ranges, ntmp); ranges = NULL; } } } else if (numextents > 1) { /*check if it is muliple values or mutliple ranges*/ if (strstr(dimensionextent, "/") == NULL) { /*multiple values*/ isextentavalue = MS_TRUE; aextentvalues = (char **)msSmallMalloc(sizeof(char *)*numextents); for (i=0; i 0 ) { msFreeCharArray(onerange, ntmp); onerange = NULL; } } if (!isvalidextent) { msFree(aextentranges); nextentranges = 0; isextentarange = MS_FALSE; } } } if (numextents > 0) { msFreeCharArray(extents, numextents); extents = NULL; } /* make sure that we got a valid extent*/ if (!isextentavalue && !isextentarange) { return MS_FALSE; } /*for the extent of the dimesion, we support single value, or list of mulitiple values comma separated, a single range or multipe ranges */ uservalues = msStringSplit (value, ',', &numuservalues); uservaluevalid = MS_FALSE; if (numuservalues == 1) { /*user iput=single*/ /*is it descret or range*/ ranges = msStringSplit(uservalues[0], '/', &ntmp); if (ntmp == 1) { /*discrete*/ if (isextentavalue) { /*single user value, single/multiple values extent*/ for (i=0; i= minval && currentval <= maxval) { uservaluevalid= MS_TRUE; break; } } } } else if (ntmp == 2 || ntmp == 3) { /*range*/ /*user input=single range. In this case the extents must be of a range type.*/ mincurrentval = atof(ranges[0]); maxcurrentval = atof(ranges[1]); if (isextentarange) { for (i=0; i= maxcurrentval && minval <= maxval) { uservaluevalid= MS_TRUE; break; } } } } if (ranges && ntmp > 0) msFreeCharArray(ranges, ntmp); } else if (numuservalues > 1) { /*user input=multiple*/ if (strstr(value, "/") == NULL) { /*user input=multiple value*/ int valueisvalid = MS_FALSE; for (i=0; i= currentval && minval <= maxval) { valueisvalid = MS_TRUE; break; } } if (!valueisvalid) break; } } uservaluevalid = valueisvalid; } else { /*user input multiple ranges*/ int valueisvalid = MS_TRUE; for (i=0; i=mincurrentrange && maxcurrentval <= maxcurrentrange && mincurrentval <= maxcurrentval) { break; } } if (j == nextentranges) { valueisvalid = MS_FALSE; msFreeCharArray(onerange, ntmp); break; } } } else { valueisvalid = MS_FALSE; } msFreeCharArray(onerange, ntmp); } uservaluevalid = valueisvalid; } } if(uservalues && numuservalues > 0) msFreeCharArray(uservalues, numuservalues); if (aextentvalues && nextentvalues > 0) { for (i=0; i 0) { msFree(aextentranges); } if(uservaluevalid) return MS_TRUE; return MS_FALSE; } int msWMSApplyDimensionLayer(layerObj *lp, const char *item, char *value, int forcecharcter) { int result = MS_FALSE; char *pszExpression=NULL; if (lp && item && value) { /*for the value, we support descrete values (2005) */ /* multiple values (abc, def, ...) */ /* and range(s) (1000/2000, 3000/5000) */ pszExpression = FLTGetExpressionForValuesRanges(lp, (char *)item, value, forcecharcter); if (pszExpression) { if(FLTApplyExpressionToLayer(lp, pszExpression)) result = MS_TRUE; msFree(pszExpression); } } return result; } int msWMSApplyDimension(layerObj *lp, int version, char *dimensionname, char *value, char *wms_exception_format) { char *dimensionitemname=NULL, *dimensionextentname=NULL, *dimensiontypename=NULL; char *dimensionunitname=NULL, *dimensiondefaultname=NULL; const char *dimensionitem, *dimensionextent, *dimensiontype, *dimensionunit, *dimensiondefault; int forcecharcter; int result = MS_FALSE; char *dimension = NULL, *currentvalue=NULL; if (lp && dimensionname && value) { /*check if the dimension name passes starts with dim_. All dimensions should start with dim_, except elevation*/ if (strncasecmp(dimensionname, "dim_", 4) == 0) dimension = msStrdup(dimensionname+4); else dimension = msStrdup(dimensionname); /*if value is empty and a default is defined, use it*/ if (strlen(value) > 0) currentvalue = msStrdup(value); else { dimensiondefaultname = msStrdup(dimension); dimensiondefaultname = msStringConcatenate(dimensiondefaultname, "_default"); dimensiondefault = msOWSLookupMetadata(&(lp->metadata), "M", dimensiondefaultname); if (dimensiondefault && strlen(dimensiondefault) > 0) currentvalue = msStrdup(dimensiondefault); } /*check if the manadatory metada related to the dimension are set*/ dimensionitemname = msStrdup(dimension); dimensionitemname = msStringConcatenate(dimensionitemname, "_item"); dimensionitem = msOWSLookupMetadata(&(lp->metadata), "M", dimensionitemname); dimensionextentname = msStrdup(dimension); dimensionextentname = msStringConcatenate(dimensionextentname, "_extent"); dimensionextent = msOWSLookupMetadata(&(lp->metadata), "M", dimensionextentname); dimensionunitname = msStrdup(dimension); dimensionunitname = msStringConcatenate(dimensionunitname, "_units"); dimensionunit = msOWSLookupMetadata(&(lp->metadata), "M", dimensionunitname); /*if the server want to force the type to character*/ dimensiontypename = msStrdup(dimension); dimensiontypename = msStringConcatenate(dimensiontypename, "_type"); dimensiontype = msOWSLookupMetadata(&(lp->metadata), "M", dimensiontypename); forcecharcter = MS_FALSE; if (dimensiontype && strcasecmp(dimensiontype, "Character") == 0) forcecharcter = MS_TRUE; if (dimensionitem && dimensionextent && dimensionunit && currentvalue) { if(msWMSValidateDimensionValue(currentvalue, dimensionextent, forcecharcter)) { result = msWMSApplyDimensionLayer(lp, dimensionitem, currentvalue, forcecharcter); } else { msSetError(MS_WMSERR, "Dimension %s with a value of %s is invalid or outside the extents defined", "msWMSApplyDimension", dimension, currentvalue); result = MS_FALSE; } } else msSetError(MS_WMSERR, "Dimension %s : invalid settings. Make sure that item, units and extent are set.", "msWMSApplyDimension", dimension); msFree(dimensionitemname); msFree(dimensionextentname); msFree(dimensiontypename); msFree(dimensionunitname); msFree(dimensiondefaultname); msFree(dimension); msFree(currentvalue); } return result; } /* ** */ int msWMSLoadGetMapParams(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format, const char *wms_request, owsRequestObj *ows_request) { int i, adjust_extent = MS_FALSE, nonsquare_enabled = MS_FALSE; int iUnits = -1; int nLayerOrder = 0; int transparent = MS_NOOVERRIDE; int bbox_pixel_is_point = MS_FALSE; outputFormatObj *format = NULL; int validlayers = 0; char *styles = NULL; int numlayers = 0; char **layers = NULL; int layerfound =0; int invalidlayers = 0; char epsgbuf[100]; char srsbuffer[100]; int epsgvalid = MS_FALSE; const char *projstring; int timerequest = 0; char *stime = NULL; char **tokens=NULL; int n,j; int srsfound = 0; int bboxfound = 0; int formatfound = 0; int widthfound = 0; int heightfound = 0; char *request = NULL; int status = 0; const char *layerlimit = NULL; const char *sldenabled=NULL; char *sld_url=NULL, *sld_body=NULL; epsgbuf[0]='\0'; srsbuffer[0]='\0'; /* Some of the getMap parameters are actually required depending on the */ /* request, but for now we assume all are optional and the map file */ /* defaults will apply. */ msAdjustExtent(&(map->extent), map->width, map->height); /* Check for SLDs first. If SLD is available LAYERS and STYLES parameters are non mandatory */ for(i=0; map && iweb.metadata), "MO", "sld_enabled"); if (sldenabled == NULL) sldenabled = "true"; if (ogrEnabled == 0) { msSetError(MS_WMSERR, "OGR support is not available.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } else { if (strcasecmp(sldenabled, "true") == 0) { if (strcasecmp(names[i], "SLD") == 0) { sld_url = values[i]; } if (strcasecmp(names[i], "SLD_BODY") == 0) { sld_body = values[i]; } } } } } for(i=0; map && inumlayers * sizeof(int)); MS_CHECK_ALLOC(layerOrder, map->numlayers * sizeof(int), MS_FAILURE) layers = msStringSplit(values[i], ',', &numlayers); if (layers==NULL || strlen(values[i]) <=0 || numlayers < 1) { numlayers = 0; if (sld_url == NULL && sld_body == NULL) { msFreeCharArray(layers,numlayers); msFree(layerOrder); msSetError(MS_WMSERR, "At least one layer name required in LAYERS.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } } if (nVersion >= OWS_1_3_0) { layerlimit = msOWSLookupMetadata(&(map->web.metadata), "MO", "layerlimit"); if(layerlimit) { if (numlayers > atoi(layerlimit)) { msFreeCharArray(layers,numlayers); msFree(layerOrder); msSetError(MS_WMSERR, "Number of layers requested exceeds LayerLimit.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } } } for (iLayer=0; iLayer < map->numlayers; iLayer++) { map->layerorder[iLayer] = iLayer; layerOrder[iLayer] = 0; } for(j=0; jnumlayers; j++) { /* Keep only layers with status=DEFAULT by default */ /* Layer with status DEFAULT is drawn first. */ if (GET_LAYER(map, j)->status != MS_DEFAULT) GET_LAYER(map, j)->status = MS_OFF; else { map->layerorder[nLayerOrder++] = j; layerOrder[j] = 1; } } nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); for (k=0; knumlayers; j++) { /* Turn on selected layers only. */ if ( ((GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, layers[k]) == 0) || (map->name && strcasecmp(map->name, layers[k]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[k]) == 0) || ((numNestedGroups[j] >0) && msStringInArray(layers[k], nestedGroups[j], numNestedGroups[j]))) && ((msIntegerInArray(GET_LAYER(map, j)->index, ows_request->enabled_layers, ows_request->numlayers))) ) { if (GET_LAYER(map, j)->status != MS_DEFAULT) { if (layerOrder[j] == 0) { map->layerorder[nLayerOrder++] = j; layerOrder[j] = 1; GET_LAYER(map, j)->status = MS_ON; } } validlayers++; layerfound = 1; } } if (layerfound == 0 && numlayers>0) invalidlayers++; } /* free the stuff used for nested layers */ for (k = 0; k < map->numlayers; k++) { if (numNestedGroups[k] > 0) { msFreeCharArray(nestedGroups[k], numNestedGroups[k]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); /* set all layers with status off at end of array */ for (j=0; jnumlayers; j++) { if (GET_LAYER(map, j)->status == MS_OFF) if (layerOrder[j] == 0) map->layerorder[nLayerOrder++] = j; } free(layerOrder); msFreeCharArray(layers, numlayers); } else if (strcasecmp(names[i], "STYLES") == 0) { styles = values[i]; } else if ((strcasecmp(names[i], "SRS") == 0 && nVersion < OWS_1_3_0) || (strcasecmp(names[i], "CRS") == 0 && nVersion >= OWS_1_3_0)) { srsfound = 1; /* SRS is in format "EPSG:epsg_id" or "AUTO:proj_id,unit_id,lon0,lat0" */ if (strncasecmp(values[i], "EPSG:", 5) == 0) { /* SRS=EPSG:xxxx */ /* don't need to copy init=xxx since the srsbudder is only used with msLoadProjection and that does alreay the job */ /* snprintf(srsbuffer, 100, "init=epsg:%.20s", values[i]+5); */ snprintf(srsbuffer, sizeof(srsbuffer), "EPSG:%.20s",values[i]+5); snprintf(epsgbuf, sizeof(epsgbuf), "EPSG:%.20s",values[i]+5); /* This test was to correct a request by the OCG cite 1.3.0 test sending CRS=ESPG:4326, Bug:*/ if (nVersion >= OWS_1_3_0) { if (srsbuffer[strlen(srsbuffer)-1] == ',') srsbuffer[strlen(srsbuffer)-1] = '\0'; if (epsgbuf[strlen(epsgbuf)-1] == ',') epsgbuf[strlen(epsgbuf)-1] = '\0'; } /* we need to wait until all params are read before */ /* loding the projection into the map. This will help */ /* insure that the passes srs is valid for all layers. */ /* if (msLoadProjectionString(&(map->projection), buffer) != 0) return msWMSException(map, nVersion, NULL); iUnits = GetMapserverUnitUsingProj(&(map->projection)); if (iUnits != -1) map->units = iUnits; */ } else if (strncasecmp(values[i], "AUTO:", 5) == 0 && nVersion < OWS_1_3_0) { snprintf(srsbuffer, sizeof(srsbuffer), "%s", values[i]); /* SRS=AUTO:proj_id,unit_id,lon0,lat0 */ /* if (msLoadProjectionString(&(map->projection), values[i]) != 0) return msWMSException(map, nVersion, NULL); iUnits = GetMapserverUnitUsingProj(&(map->projection)); if (iUnits != -1) map->units = iUnits; */ } else if (nVersion >= OWS_1_3_0 && (strncasecmp(values[i], "AUTO2:", 6) == 0 || strncasecmp(values[i], "CRS:", 4) == 0)) { snprintf(srsbuffer, sizeof(srsbuffer), "%s", values[i]); } else { if (nVersion >= OWS_1_3_0) { msSetError(MS_WMSERR, "Unsupported CRS namespace (only EPSG, AUTO2, CRS currently supported).", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "InvalidCRS", wms_exception_format); } else { msSetError(MS_WMSERR, "Unsupported SRS namespace (only EPSG and AUTO currently supported).", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "InvalidSRS", wms_exception_format); } } } else if (strcasecmp(names[i], "BBOX") == 0) { char **tokens; int n; bboxfound = 1; tokens = msStringSplit(values[i], ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_WMSERR, "Wrong number of arguments for BBOX.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } map->extent.minx = atof(tokens[0]); map->extent.miny = atof(tokens[1]); map->extent.maxx = atof(tokens[2]); map->extent.maxy = atof(tokens[3]); msFreeCharArray(tokens, n); /*for wms 1.3.0 we will do the validation of the bbox after all parameters are read to account for the axes order*/ if (nVersion < OWS_1_3_0) { /* validate bbox values */ if ( map->extent.minx >= map->extent.maxx || map->extent.miny >= map->extent.maxy) { msSetError(MS_WMSERR, "Invalid values for BBOX.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } adjust_extent = MS_TRUE; } } else if (strcasecmp(names[i], "WIDTH") == 0) { widthfound = 1; map->width = atoi(values[i]); } else if (strcasecmp(names[i], "HEIGHT") == 0) { heightfound = 1; map->height = atoi(values[i]); } else if (strcasecmp(names[i], "FORMAT") == 0) { const char *format_list = NULL; formatfound = 1; if (strcasecmp(values[i], "application/openlayers")!=0) { /*check to see if a predefined list is given*/ format_list = msOWSLookupMetadata(&(map->web.metadata), "M","getmap_formatlist"); if (format_list) { format = msOwsIsOutputFormatValid(map, values[i], &(map->web.metadata), "M", "getmap_formatlist"); if (format == NULL) { msSetError(MS_IMGERR, "Unsupported output format (%s).", "msWMSLoadGetMapParams()", values[i] ); return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); } } else { format = msSelectOutputFormat( map, values[i] ); if( format == NULL || (strncasecmp(format->driver, "GD/", 3) != 0 && strncasecmp(format->driver, "GDAL/", 5) != 0 && strncasecmp(format->driver, "AGG/", 4) != 0 && strncasecmp(format->driver, "CAIRO/", 6) != 0 && strncasecmp(format->driver, "OGL/", 4) != 0 && strncasecmp(format->driver, "KML", 3) != 0 && strncasecmp(format->driver, "KMZ", 3) != 0)) { msSetError(MS_IMGERR, "Unsupported output format (%s).", "msWMSLoadGetMapParams()", values[i] ); return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); } } } msFree( map->imagetype ); map->imagetype = msStrdup(values[i]); } else if (strcasecmp(names[i], "TRANSPARENT") == 0) { transparent = (strcasecmp(values[i], "TRUE") == 0); } else if (strcasecmp(names[i], "BGCOLOR") == 0) { long c; c = strtol(values[i], NULL, 16); map->imagecolor.red = (c/0x10000)&0xff; map->imagecolor.green = (c/0x100)&0xff; map->imagecolor.blue = c&0xff; } /* value of time can be empty. We should look for a default value */ /* see function msWMSApplyTime */ else if (strcasecmp(names[i], "TIME") == 0) { /* && values[i]) */ stime = values[i]; timerequest = 1; } /* Vendor-specific ANGLE param (for map rotation), added in ticket #3332, * also supported by GeoServer */ else if (strcasecmp(names[i], "ANGLE") == 0) { msMapSetRotation(map, atof(values[i])); } /* Vendor-specific bbox_pixel_is_point, added in ticket #4652 */ else if (strcasecmp(names[i], "BBOX_PIXEL_IS_POINT") == 0) { bbox_pixel_is_point = (strcasecmp(values[i], "TRUE") == 0); } } /*validate the exception format WMS 1.3.0 section 7.3.3.11*/ if (nVersion >= OWS_1_3_0 && wms_exception_format != NULL) { if (strcasecmp(wms_exception_format, "INIMAGE") != 0 && strcasecmp(wms_exception_format, "BLANK") != 0 && strcasecmp(wms_exception_format, "XML") != 0) { msSetError(MS_WMSERR, "Invalid format %s for the EXCEPTIONS parameter.", "msWMSLoadGetMapParams()", wms_exception_format); return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); } } if (bboxfound && nVersion >= OWS_1_3_0) { rectObj rect; projectionObj proj; /*we have already validated that the request format when reding the request parameters*/ rect = map->extent; /*try to adjust the axes if necessary*/ if (strlen(srsbuffer) > 1) { msInitProjection(&proj); if (msLoadProjectionStringEPSG(&proj, (char *)srsbuffer) == 0) { msAxisNormalizePoints( &proj, 1, &rect.minx, &rect.miny ); msAxisNormalizePoints( &proj, 1, &rect.maxx, &rect.maxy ); } msFreeProjection( &proj ); } /*if the CRS is AUTO2:auto_crs_id,factor,lon0,lat0, we need to grab the factor patameter and use it with the bbox*/ if (strlen(srsbuffer) > 1 && strncasecmp(srsbuffer, "AUTO2:", 6) == 0) { char **args; int numargs; double factor; args = msStringSplit(srsbuffer, ',', &numargs); if (numargs == 4) { factor = atof(args[1]); if (factor > 0 && factor != 1.0) { rect.minx = rect.minx*factor; rect.miny = rect.miny*factor; rect.maxx = rect.maxx*factor; rect.maxx = rect.maxy*factor; } } msFreeCharArray(args, numargs); } map->extent = rect; /* validate bbox values */ if ( map->extent.minx >= map->extent.maxx || map->extent.miny >= map->extent.maxy) { msSetError(MS_WMSERR, "Invalid values for BBOX.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } adjust_extent = MS_TRUE; } /* ** If any select layers have a default time, we will apply the default ** time value even if no TIME request was in the url. */ if( !timerequest && map ) { for (i=0; inumlayers && !timerequest; i++) { layerObj *lp = NULL; lp = (GET_LAYER(map, i)); if (lp->status != MS_ON && lp->status != MS_DEFAULT) continue; if( msOWSLookupMetadata(&(lp->metadata), "MO", "timedefault") ) timerequest = 1; } } /* ** Apply time filters if available in the request. */ if (timerequest) { if (msWMSApplyTime(map, nVersion, stime, wms_exception_format) == MS_FAILURE) { return MS_FAILURE;/* msWMSException(map, nVersion, "InvalidTimeRequest"); */ } } /* ** Check/apply wms dimensions ** all dimension requests shoul start with dim_xxxx, except time and elevation. */ for (i=0; inumlayers; i++) { layerObj *lp = NULL; const char *dimensionlist = NULL; char **tokens; int ntokens=0,k; lp = (GET_LAYER(map, i)); if (lp->status != MS_ON && lp->status != MS_DEFAULT) continue; dimensionlist = msOWSLookupMetadata(&(lp->metadata), "M", "dimensionlist"); /* if (!dimensionlist) dimensionlist = msOWSLookupMetadata(&(map->web.metadata), "M", "dimensionlist"); */ if (dimensionlist) { tokens = msStringSplit(dimensionlist, ',', &ntokens); if (tokens && ntokens > 0) { char *dimensionname=NULL; char *stmp = NULL; for (j=0; jmap, nVersion, "InvalidDimensionValue", wms_exception_format); } msFree(dimensionname); msFree(stmp); break; } msFree(dimensionname); msFree(stmp); } } msFreeCharArray(tokens, ntokens); } } } /* ** Apply the selected output format (if one was selected), and override ** the transparency if needed. */ if( format != NULL ) msApplyOutputFormat( &(map->outputformat), format, transparent, MS_NOOVERRIDE, MS_NOOVERRIDE ); /* Validate all layers given. ** If an invalid layer is sent, return an exception. */ if (validlayers == 0 || invalidlayers > 0) { if (invalidlayers > 0) { msSetError(MS_WMSERR, "Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for \ this request. Check wms/ows_enable_request settings.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } if (validlayers == 0 && sld_url == NULL && sld_body == NULL) { msSetError(MS_WMSERR, "Missing required parameter LAYERS", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } } /* validate srs value: When the SRS parameter in a GetMap request contains a ** SRS that is valid for some, but not all of the layers being requested, ** then the server shall throw a Service Exception (code = "InvalidSRS"). ** Validate first against epsg in the map and if no matching srs is found ** validate all layers requested. */ if (epsgbuf != NULL && strlen(epsgbuf) > 1) { epsgvalid = MS_FALSE; projstring = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_FALSE); if (projstring) { tokens = msStringSplit(projstring, ' ', &n); if (tokens && n > 0) { for(i=0; inumlayers; i++) { epsgvalid = MS_FALSE; if (GET_LAYER(map, i)->status == MS_ON) { projstring = msOWSGetEPSGProj(&(GET_LAYER(map, i)->projection), &(GET_LAYER(map, i)->metadata), "MO", MS_FALSE); if (projstring) { tokens = msStringSplit(projstring, ' ', &n); if (tokens && n > 0) { for(j=0; j= OWS_1_3_0) { msSetError(MS_WMSERR, "Invalid CRS given : CRS must be valid for all requested layers.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "InvalidSRS", wms_exception_format); } else { msSetError(MS_WMSERR, "Invalid SRS given : SRS must be valid for all requested layers.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "InvalidSRS", wms_exception_format); } } } } } } /* Validate requested image size. */ if(map->width > map->maxsize || map->height > map->maxsize || map->width < 1 || map->height < 1) { msSetError(MS_WMSERR, "Image size out of range, WIDTH and HEIGHT must be between 1 and %d pixels.", "msWMSLoadGetMapParams()", map->maxsize); /* Restore valid default values in case errors INIMAGE are used */ map->width = 400; map->height= 300; return msWMSException(map, nVersion, NULL, wms_exception_format); } /* Check whether requested BBOX and width/height result in non-square pixels */ nonsquare_enabled = msTestConfigOption( map, "MS_NONSQUARE", MS_FALSE ); if (!nonsquare_enabled) { double dx, dy, reqy; dx = MS_ABS(map->extent.maxx - map->extent.minx); dy = MS_ABS(map->extent.maxy - map->extent.miny); reqy = ((double)map->width) * dy / dx; /* Allow up to 1 pixel of error on the width/height ratios. */ /* If more than 1 pixel then enable non-square pixels */ if ( MS_ABS((reqy - (double)map->height)) > 1.0 ) { if (map->debug) msDebug("msWMSLoadGetMapParams(): enabling non-square pixels.\n"); msSetConfigOption(map, "MS_NONSQUARE", "YES"); nonsquare_enabled = MS_TRUE; } } /* If the requested SRS is different from the default mapfile projection, or ** if a BBOX resulting in non-square pixels is requested then ** copy the original mapfile's projection to any layer that doesn't already ** have a projection. This will prevent problems when users forget to ** explicitly set a projection on all layers in a WMS mapfile. */ if ((srsbuffer != NULL && strlen(srsbuffer) > 1) || nonsquare_enabled) { projectionObj newProj; if (map->projection.numargs <= 0) { if (nVersion >= OWS_1_3_0) { msSetError(MS_WMSERR, "Cannot set new CRS on a map that doesn't " "have any projection set. Please make sure your mapfile " "has a projection defined at the top level.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "InvalidCRS", wms_exception_format); } else { msSetError(MS_WMSERR, "Cannot set new SRS on a map that doesn't " "have any projection set. Please make sure your mapfile " "has a projection defined at the top level.", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "InvalidSRS", wms_exception_format); } } msInitProjection(&newProj); if (srsbuffer != NULL && strlen(srsbuffer) > 1) { int nTmp; if (nVersion >= OWS_1_3_0) nTmp = msLoadProjectionStringEPSG(&newProj, srsbuffer); else nTmp = msLoadProjectionString(&newProj, srsbuffer); if (nTmp != 0) { msFreeProjection(&newProj); return msWMSException(map, nVersion, NULL, wms_exception_format); } } if (nonsquare_enabled || msProjectionsDiffer(&(map->projection), &newProj)) { char *original_srs = NULL; for(i=0; inumlayers; i++) { if (GET_LAYER(map, i)->projection.numargs <= 0 && GET_LAYER(map, i)->status != MS_OFF && GET_LAYER(map, i)->transform == MS_TRUE) { /* This layer is turned on and needs a projection */ /* Fetch main map projection string only now that we need it */ if (original_srs == NULL) original_srs = msGetProjectionString(&(map->projection)); if (msLoadProjectionString(&(GET_LAYER(map, i)->projection), original_srs) != 0) { msFreeProjection(&newProj); return msWMSException(map, nVersion, NULL, wms_exception_format); } GET_LAYER(map, i)->project = MS_TRUE; } } msFree(original_srs); } msFreeProjection(&newProj); } /* apply the srs to the map file. This is only done after validating */ /* that the srs given as parameter is valid for all layers */ if (srsbuffer != NULL && strlen(srsbuffer) > 1) { int nTmp; msFreeProjection(&map->projection); msInitProjection(&map->projection); if (nVersion >= OWS_1_3_0) nTmp = msLoadProjectionStringEPSG(&(map->projection), srsbuffer); else nTmp = msLoadProjectionString(&(map->projection), srsbuffer); if (nTmp != 0) return msWMSException(map, nVersion, NULL, wms_exception_format); iUnits = GetMapserverUnitUsingProj(&(map->projection)); if (iUnits != -1) map->units = iUnits; } if (sld_url || sld_body) { int nLayersBefore, nLayerAfter; char request_tmp[32]; char *pszLayerNames = NULL; nLayersBefore = map->numlayers; /* -------------------------------------------------------------------- */ /* if LAYERS parameter was not given, set all layers to off */ /* -------------------------------------------------------------------- */ if (validlayers == 0) { /*no LAYERS parameter is give*/ for(j=0; jnumlayers; j++) { if (GET_LAYER(map, j)->status != MS_DEFAULT) GET_LAYER(map, j)->status = MS_OFF; } } /*apply sld if defined. This is done here so that bbox and srs are already applied*/ if (sld_url) { if ((status = msSLDApplySLDURL(map, sld_url, -1, NULL, &pszLayerNames)) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); } else if (sld_body) { if ((status =msSLDApplySLD(map, sld_body, -1, NULL, &pszLayerNames)) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); } /* -------------------------------------------------------------------- */ /* SLD and styles can use the same layer multiple times. If */ /* that is the case we duplicate the layer for drawing */ /* purpose. We need to reset the ows request enable settings (#1602)*/ /* -------------------------------------------------------------------- */ nLayerAfter=map->numlayers; if (nLayersBefore != nLayerAfter) { strlcpy(request_tmp, "GetMap", sizeof(request_tmp)); msOWSRequestLayersEnabled(map, "M", request_tmp, ows_request); } /* -------------------------------------------------------------------- */ /* We need to take into account where the LAYERS parameter was */ /* not given (the LAYERS is option when an SLD is given). In */ /* this particular case, we need to turn on the layers */ /* identified the SLD (#1166). */ /* */ /* -------------------------------------------------------------------- */ if (validlayers == 0) { if (pszLayerNames) { char **tokens; int ntokens=0; tokens = msStringSplit(pszLayerNames, ',', &ntokens); if (ntokens >0) { for (i=0; inumlayers; j++) { if ( ((GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, tokens[i]) == 0) || (map->name && strcasecmp(map->name, tokens[i]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, tokens[i]) == 0)) && ((msIntegerInArray(GET_LAYER(map, j)->index, ows_request->enabled_layers, ows_request->numlayers))) ) { if (GET_LAYER(map, j)->status != MS_DEFAULT) GET_LAYER(map, j)->status = MS_ON; } } } } } } msFree(pszLayerNames); } /* Validate Styles : ** MapServer advertize styles through th group setting in a class object. ** If no styles are set MapServer expects to have empty values ** for the styles parameter (...&STYLES=&...) Or for multiple Styles/Layers, ** we could have ...&STYLES=,,,. If that is not the ** case, we generate an exception. */ if(styles && strlen(styles) > 0) { char **tokens; int n=0, i=0, k=0, l=0,m=0; char **layers=NULL; int numlayers =0; layerObj *lp = NULL; tokens = msStringSplitComplex(styles, ",",&n,MS_ALLOWEMPTYTOKENS); for (i=0; i 0 && strcasecmp(tokens[i],"default") != 0) { if (layers == NULL) { int bLayerInserted = MS_FALSE; char request_tmp[32]; for(j=0; j0) { for (m=0; mvtable) msInitializeVirtualTable(psTmpLayer); /*make the name unique*/ snprintf(tmpId, sizeof(tmpId), "%lx_%x_%d",(long)time(NULL),(int)getpid(), map->numlayers); if (psTmpLayer->name) msFree(psTmpLayer->name); psTmpLayer->name = strdup(tmpId); msFree(layers[l]); layers[l] = strdup(tmpId); msInsertLayer(map, psTmpLayer, -1); bLayerInserted =MS_TRUE; /* layer was copied, we need to decrement its refcount */ MS_REFCNT_DECR(psTmpLayer); } } } } if (bLayerInserted) { strlcpy(request_tmp, "GetMap", sizeof(request_tmp)); msOWSRequestLayersEnabled(map, "M", request_tmp, ows_request); } } if (layers && numlayers == n) { for (j=0; jnumlayers; j++) { if ((GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, layers[i]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[i]) == 0)) { lp = GET_LAYER(map, j); for (k=0; knumclasses; k++) { if (lp->class[k]->group && strcasecmp(lp->class[k]->group, tokens[i]) == 0) { msFree(lp->classgroup); lp->classgroup = msStrdup( tokens[i]); break; } } if (k == lp->numclasses) { msSetError(MS_WMSERR, "Style (%s) not defined on layer.", "msWMSLoadGetMapParams()", tokens[i]); msFreeCharArray(tokens, n); msFreeCharArray(layers, numlayers); return msWMSException(map, nVersion, "StyleNotDefined", wms_exception_format); } /* Check the style of the root layer */ } else if (map->name && strcasecmp(map->name, layers[i]) == 0) { const char *styleName = NULL; char *pszEncodedStyleName = NULL; styleName = msOWSLookupMetadata(&(map->web.metadata), "MO", "style_name"); if (styleName == NULL) styleName = "default"; pszEncodedStyleName = msEncodeHTMLEntities(styleName); if (strcasecmp(pszEncodedStyleName, tokens[i]) != 0) { msSetError(MS_WMSERR, "Style (%s) not defined on root layer.", "msWMSLoadGetMapParams()", tokens[i]); msFreeCharArray(tokens, n); msFreeCharArray(layers, numlayers); msFree(pszEncodedStyleName); return msWMSException(map, nVersion, "StyleNotDefined", wms_exception_format); } msFree(pszEncodedStyleName); } } } else { msSetError(MS_WMSERR, "Invalid style (%s). Mapserver is expecting an empty string for the STYLES : STYLES= or STYLES=,,, or using keyword default STYLES=default,default, ...", "msWMSLoadGetMapParams()", styles); msFreeCharArray(tokens, n); msFreeCharArray(layers, numlayers); return msWMSException(map, nVersion, "StyleNotDefined", wms_exception_format); } } } msFreeCharArray(tokens, n); msFreeCharArray(layers, numlayers); } /* ** WMS extents are edge to edge while MapServer extents are center of ** pixel to center of pixel. Here we try to adjust the WMS extents ** in by half a pixel. We wait till here because we want to ensure we ** are doing this in terms of the correct WIDTH and HEIGHT. */ if( adjust_extent && map->width>1 && map->height>1 && !bbox_pixel_is_point) { double dx, dy; dx = (map->extent.maxx - map->extent.minx) / map->width; map->extent.minx += dx*0.5; map->extent.maxx -= dx*0.5; dy = (map->extent.maxy - map->extent.miny) / map->height; map->extent.miny += dy*0.5; map->extent.maxy -= dy*0.5; } if (request && strcasecmp(request, "DescribeLayer") != 0) { if (srsfound == 0) { if ( nVersion >= OWS_1_3_0) msSetError(MS_WMSERR, "Missing required parameter CRS", "msWMSLoadGetMapParams()"); else msSetError(MS_WMSERR, "Missing required parameter SRS", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } if (bboxfound == 0) { msSetError(MS_WMSERR, "Missing required parameter BBOX", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } if (formatfound == 0 && (strcasecmp(request, "GetMap") == 0 || strcasecmp(request, "map") == 0)) { msSetError(MS_WMSERR, "Missing required parameter FORMAT", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } if (widthfound == 0) { msSetError(MS_WMSERR, "Missing required parameter WIDTH", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } if (heightfound == 0) { msSetError(MS_WMSERR, "Missing required parameter HEIGHT", "msWMSLoadGetMapParams()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } } return MS_SUCCESS; } /* ** */ static void msWMSPrintRequestCap(int nVersion, const char *request, const char *script_url, const char *formats, ...) { va_list argp; const char *fmt; char *encoded; msIO_printf(" <%s>\n", request); /* We expect to receive a NULL-terminated args list of formats */ va_start(argp, formats); fmt = formats; while(fmt != NULL) { /* Special case for early WMS with subelements in Format (bug 908) */ if( nVersion <= OWS_1_0_7 ) { encoded = msStrdup( fmt ); } /* otherwise we HTML code special characters */ else { encoded = msEncodeHTMLEntities(fmt); } msIO_printf(" %s\n", encoded); msFree(encoded); fmt = va_arg(argp, const char *); } va_end(argp); msIO_printf(" \n"); msIO_printf(" \n"); /* The URL should already be HTML encoded. */ if (nVersion == OWS_1_0_0) { msIO_printf(" \n", script_url); msIO_printf(" \n", script_url); } else { msIO_printf(" \n", script_url); msIO_printf(" \n", script_url); } msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", request); } void msWMSPrintAttribution(FILE *stream, const char *tabspace, hashTableObj *metadata, const char *namespaces) { const char *title, *onlineres, *logourl; char * pszEncodedValue=NULL; if (stream && metadata) { title = msOWSLookupMetadata(metadata, "MO", "attribution_title"); onlineres = msOWSLookupMetadata(metadata, "MO", "attribution_onlineresource"); logourl = msOWSLookupMetadata(metadata, "MO", "attribution_logourl_width"); if (title || onlineres || logourl) { msIO_printf("%s\n",tabspace); if (title) { pszEncodedValue = msEncodeHTMLEntities(title); msIO_fprintf(stream, "%s%s%s\n", tabspace, tabspace, pszEncodedValue); free(pszEncodedValue); } if (onlineres) { pszEncodedValue = msEncodeHTMLEntities(onlineres); msIO_fprintf(stream, "%s%s\n", tabspace, tabspace, pszEncodedValue); free(pszEncodedValue); } if (logourl) { msOWSPrintURLType(stream, metadata, "MO","attribution_logourl", OWS_NOERR, NULL, "LogoURL", NULL, " width=\"%s\"", " height=\"%s\"", ">\n %s\n" " ", MS_FALSE, MS_TRUE, MS_TRUE, MS_TRUE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); } msIO_printf("%s\n", tabspace); } } } /* ** msWMSPrintScaleHint() ** ** Print a Min/MaxScaleDenominator tag for the layer if applicable. ** used for WMS >=1.3.0 */ void msWMSPrintScaleDenominator(const char *tabspace, double minscaledenom, double maxscaledenom) { if (minscaledenom > 0) msIO_printf("%s%g\n", tabspace, minscaledenom); if (maxscaledenom > 0) msIO_printf("%s%g\n", tabspace, maxscaledenom); } /* ** msWMSPrintScaleHint() ** ** Print a ScaleHint tag for this layer if applicable. ** ** (see WMS 1.1.0 sect. 7.1.5.4) The WMS defines the scalehint values as ** the ground distance in meters of the southwest to northeast diagonal of ** the central pixel of a map. ScaleHint values are the min and max ** recommended values of that diagonal. */ void msWMSPrintScaleHint(const char *tabspace, double minscaledenom, double maxscaledenom, double resolution) { double scalehintmin=0.0, scalehintmax=0.0, diag; diag = sqrt(2.0); if (minscaledenom > 0) scalehintmin = diag*(minscaledenom/resolution)/msInchesPerUnit(MS_METERS,0); if (maxscaledenom > 0) scalehintmax = diag*(maxscaledenom/resolution)/msInchesPerUnit(MS_METERS,0); if (scalehintmin > 0.0 || scalehintmax > 0.0) { msIO_printf("%s\n", tabspace, scalehintmin, scalehintmax); if (scalehintmax == 0.0) msIO_printf("%s\n", tabspace); } } /* ** msWMSPrintAuthorityURL() ** ** Print an AuthorityURL tag if applicable. */ void msWMSPrintAuthorityURL(FILE *stream, const char *tabspace, hashTableObj *metadata, const char *namespaces) { const char *pszWmsAuthorityName; const char *pszWMSAuthorityHref; char *pszTemplateName=NULL, *pszTemplateHref=NULL; if (stream && metadata) { pszWmsAuthorityName = msOWSLookupMetadata(metadata, namespaces, "authorityurl_name"); pszWMSAuthorityHref = msOWSLookupMetadata(metadata, namespaces, "authorityurl_href"); /* AuthorityURL only makes sense if you have *both* the name and url */ if( pszWmsAuthorityName && pszWMSAuthorityHref ) { pszTemplateName = msStringConcatenate(msStrdup(tabspace), "\n"); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "authorityurl_name", OWS_NOERR, pszTemplateName, NULL); pszTemplateHref = msStringConcatenate(msStrdup(tabspace), " \n"); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "authorityurl_href", OWS_NOERR, pszTemplateHref, NULL); msIO_printf("%s\n", tabspace); } else if ( pszWmsAuthorityName || pszWMSAuthorityHref ) { msIO_printf("%s\n", tabspace); } } msFree(pszTemplateName); msFree(pszTemplateHref); } /* ** msWMSPrintIdentifier() ** ** Print an Identifier tag if applicable. */ void msWMSPrintIdentifier(FILE *stream, const char *tabspace, hashTableObj *metadata, const char *namespaces) { const char *pszWMSIdentifierAuthority; const char *pszWMSIdentifierValue; char *pszTemplate=NULL; if (stream && metadata) { pszWMSIdentifierAuthority = msOWSLookupMetadata(metadata, namespaces, "identifier_authority"); pszWMSIdentifierValue = msOWSLookupMetadata(metadata, namespaces, "identifier_value"); /* Identifier only makes sense if you have *both* the authority and value */ if( pszWMSIdentifierAuthority && pszWMSIdentifierValue ) { pszTemplate = msStringConcatenate(msStrdup(tabspace), ""); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "identifier_authority", OWS_NOERR, pszTemplate, NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "identifier_value", OWS_NOERR, "%s\n", NULL); } else if ( pszWMSIdentifierAuthority || pszWMSIdentifierValue ) { msIO_printf("%s\n", tabspace); } } msFree(pszTemplate); } /* ** msWMSPrintKeywordlist() ** ** Print a Keywordlist tag if applicable. */ void msWMSPrintKeywordlist(FILE *stream, const char *tabspace, const char *name, hashTableObj *metadata, const char *namespaces, int nVersion) { char newname[28]; /* max. rootlayer_keywordlist_items */ char vocname[33]; /* max. rootlayer_keywordlist_vocabulary */ const char *vocabularylist; /* to be read from metadata */ char **tokens = NULL; /* splitted vocabularylist */ char *pszName=NULL, /* key to lookup keywords with vocabulary */ *pszTemplate1=NULL, /* templates for msOWSPrintEncodeMetadataList*/ *pszTemplate2=NULL; int i, sName, sTemplate, ntokens = 0; newname[0]='\0'; vocname[0]='\0'; snprintf(newname, sizeof(newname), "%s_items", name); snprintf(vocname, sizeof(vocname), "%s_vocabulary", name); if (nVersion == OWS_1_0_0) { /* in V 1.0.0 */ /* The 1.0.0 spec doesn't specify which delimiter to use so let's use spaces */ pszTemplate1 = msStringConcatenate(msStrdup(tabspace), ""); pszTemplate2 = msStringConcatenate(msStrdup(tabspace), "\n"); msOWSPrintEncodeMetadataList(stream, metadata, namespaces, name, pszTemplate1, pszTemplate2, "%s ", NULL); } else if ( msOWSLookupMetadata(metadata, namespaces, name) || msOWSLookupMetadata(metadata, namespaces, newname) || msOWSLookupMetadata(metadata, namespaces, vocname) ) { /* ... in V1.0.6+ */ msIO_printf("%s\n", tabspace); pszTemplate1 = msStringConcatenate(msStrdup(tabspace), " %s\n"); /* print old styled ..._keywordlist */ msOWSPrintEncodeMetadataList(stream, metadata, namespaces, name, NULL, NULL, pszTemplate1, NULL); /* print new styled ..._keywordlist_items */ msOWSPrintEncodeMetadataList(stream, metadata, namespaces, newname, NULL, NULL, pszTemplate1, NULL); /* find out if there's a vocabulary list set */ vocabularylist = msOWSLookupMetadata(metadata, namespaces, vocname); if ( vocabularylist && nVersion >= OWS_1_3_0 ) { tokens = msStringSplit(vocabularylist, ',', &ntokens); if ( tokens && ntokens > 0 ) { /* In order to do malloc only once, the length of the metadata*/ /* key to lookup is calculated from "rootlayer_keywordlist" */ /* plus "_items" plus the length of all vocabulary items */ /* concatenate. */ /* The same is done with template string used for printing the*/ /* keyword list. Here the string is tabspace + " %s\n" */ sName = 22 + 6 + strlen(vocabularylist) +1; pszName = (char*)msSmallMalloc(sName); sTemplate = strlen(tabspace)+4+21+strlen(vocabularylist)+17+1; pszTemplate2 = (char*)msSmallMalloc(sTemplate); for (i=0; i%s\n", tabspace, tokens[i], "%s"); msOWSPrintEncodeMetadataList(stream, metadata, namespaces, pszName, NULL, NULL, pszTemplate2, NULL); } msFree(pszName); } msFreeCharArray(tokens, ntokens); } msIO_printf("%s\n", tabspace); } msFree(pszTemplate1); msFree(pszTemplate2); } /* ** msDumpLayer() */ int msDumpLayer(mapObj *map, layerObj *lp, int nVersion, const char *script_url_encoded, const char *indent, const char *validated_language, int grouplayer) { rectObj ext; const char *value; const char *pszWmsTimeExtent, *pszWmsTimeDefault= NULL, *pszStyle=NULL; const char *pszLegendURL=NULL; char *pszMetadataName=NULL, *mimetype=NULL; char **classgroups = NULL; int iclassgroups=0; char szVersionBuf[OWS_VERSION_MAXLEN]; size_t bufferSize = 0; const char *pszDimensionlist=NULL; /* if the layer status is set to MS_DEFAULT, output a warning */ if (lp->status == MS_DEFAULT) msIO_fprintf(stdout, "\n"); if (nVersion <= OWS_1_0_7) { msIO_printf("%s \n", indent, msIsLayerQueryable(lp)); } else { /* 1.1.0 and later: opaque and cascaded are new. */ int cascaded=0, opaque=0; if ((value = msOWSLookupMetadata(&(lp->metadata), "MO", "opaque")) != NULL) opaque = atoi(value); if (lp->connectiontype == MS_WMS) cascaded = 1; msIO_printf("%s \n", indent, msIsLayerQueryable(lp), opaque, cascaded); } if (lp->name && strlen(lp->name) > 0 && (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0]))) msIO_fprintf(stdout, "\n", lp->name); msOWSPrintEncodeParam(stdout, "LAYER.NAME", lp->name, OWS_NOERR, " %s\n", NULL); /* the majority of this section is dependent on appropriately named metadata in the LAYER object */ msOWSPrintEncodeMetadata2(stdout, &(lp->metadata), "MO", "title", OWS_WARN, " %s\n", lp->name, validated_language); msOWSPrintEncodeMetadata2(stdout, &(lp->metadata), "MO", "abstract", OWS_NOERR, " %s\n", NULL, validated_language); msWMSPrintKeywordlist(stdout, " ", "keywordlist", &(lp->metadata), "MO", nVersion); if (msOWSGetEPSGProj(&(map->projection),&(map->web.metadata), "MO", MS_FALSE) == NULL) { /* If map has no proj then every layer MUST have one or produce a warning */ if (nVersion > OWS_1_1_0) { /* starting 1.1.1 SRS are given in individual tags */ if (nVersion >= OWS_1_3_0) msOWSPrintEncodeParamList(stdout, "(at least one of) " "MAP.PROJECTION, LAYER.PROJECTION " "or wms_srs metadata", msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE), OWS_WARN, ' ', NULL, NULL, " %s\n", NULL); else msOWSPrintEncodeParamList(stdout, "(at least one of) " "MAP.PROJECTION, LAYER.PROJECTION " "or wms_srs metadata", msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE), OWS_WARN, ' ', NULL, NULL, " %s\n", NULL); } else msOWSPrintEncodeParam(stdout, "(at least one of) MAP.PROJECTION, " "LAYER.PROJECTION or wms_srs metadata", msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE), OWS_WARN, " %s\n", NULL); } else { /* No warning required in this case since there's at least a map proj. */ if (nVersion > OWS_1_1_0) { /* starting 1.1.1 SRS are given in individual tags */ if (nVersion >= OWS_1_3_0) msOWSPrintEncodeParamList(stdout, "(at least one of) " "MAP.PROJECTION, LAYER.PROJECTION " "or wms_srs metadata", msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE), OWS_NOERR, ' ', NULL, NULL, " %s\n", NULL); else msOWSPrintEncodeParamList(stdout, "(at least one of) " "MAP.PROJECTION, LAYER.PROJECTION " "or wms_srs metadata", msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE), OWS_NOERR, ' ', NULL, NULL, " %s\n", NULL); } else msOWSPrintEncodeParam(stdout, " LAYER.PROJECTION (or wms_srs metadata)", msOWSGetEPSGProj(&(lp->projection), &(lp->metadata),"MO",MS_FALSE), OWS_NOERR, " %s\n", NULL); } /* If layer has no proj set then use map->proj for bounding box. */ if (msOWSGetLayerExtent(map, lp, "MO", &ext) == MS_SUCCESS) { if(lp->projection.numargs > 0) { if (nVersion >= OWS_1_3_0) msOWSPrintEX_GeographicBoundingBox(stdout, " ", &(ext), &(lp->projection)); else msOWSPrintLatLonBoundingBox(stdout, " ", &(ext), &(lp->projection), NULL, OWS_WMS); msOWSPrintBoundingBox( stdout," ", &(ext), &(lp->projection), &(lp->metadata), &(map->web.metadata), "MO", nVersion ); } else { if (nVersion >= OWS_1_3_0) msOWSPrintEX_GeographicBoundingBox(stdout, " ", &(ext), &(map->projection)); else msOWSPrintLatLonBoundingBox(stdout, " ", &(ext), &(map->projection), NULL, OWS_WMS); msOWSPrintBoundingBox(stdout," ", &(ext), &(map->projection), &(lp->metadata), &(map->web.metadata), "MO", nVersion ); } } else { if (nVersion >= OWS_1_3_0) msIO_printf(" \n"); else msIO_printf(" \n"); } /* time support */ pszWmsTimeExtent = msOWSLookupMetadata(&(lp->metadata), "MO", "timeextent"); if (pszWmsTimeExtent) { pszWmsTimeDefault = msOWSLookupMetadata(&(lp->metadata), "MO", "timedefault"); if (nVersion >= OWS_1_3_0) { if (pszWmsTimeDefault) msIO_fprintf(stdout, " %s\n",pszWmsTimeDefault, pszWmsTimeExtent); else msIO_fprintf(stdout, " %s\n",pszWmsTimeExtent); } else { msIO_fprintf(stdout, " \n"); if (pszWmsTimeDefault) msIO_fprintf(stdout, " %s\n",pszWmsTimeDefault, pszWmsTimeExtent); else msIO_fprintf(stdout, " %s\n",pszWmsTimeExtent); } } /*dimensions support: elevation + other user defined dimensions*/ pszDimensionlist = msOWSLookupMetadata(&(lp->metadata), "M", "dimensionlist"); if (pszDimensionlist) { char **tokens = NULL; int ntokens = 0; char *pszDimension=NULL, *pszDimensionItemName=NULL, *pszDimensionExtentName=NULL, *pszDimensionUnitName=NULL, *pszDimensionDefaultName=NULL; const char *pszDimensionItem=NULL, *pszDimensionExtent=NULL, *pszDimensionUnit=NULL, *pszDimensionDefault=NULL; int i; tokens = msStringSplit(pszDimensionlist, ',', &ntokens); if (tokens && ntokens > 0) { for (i=0; imetadata), "M", pszDimensionItemName); pszDimensionExtentName = msStrdup(pszDimension); pszDimensionExtentName = msStringConcatenate(pszDimensionExtentName, "_extent"); pszDimensionExtent = msOWSLookupMetadata(&(lp->metadata), "M", pszDimensionExtentName); pszDimensionUnitName = msStrdup(pszDimension); pszDimensionUnitName = msStringConcatenate(pszDimensionUnitName, "_units"); pszDimensionUnit = msOWSLookupMetadata(&(lp->metadata), "M", pszDimensionUnitName); pszDimensionDefaultName = msStrdup(pszDimension); pszDimensionDefaultName = msStringConcatenate(pszDimensionDefaultName, "_default"); pszDimensionDefault = msOWSLookupMetadata(&(lp->metadata), "M", pszDimensionDefaultName); if (pszDimensionItem && pszDimensionExtent && pszDimensionUnit) { if (nVersion >= OWS_1_3_0) { if(pszDimensionDefault && strlen(pszDimensionDefault) > 0) msIO_fprintf(stdout, " %s\n", pszDimension, pszDimensionUnit, pszDimensionDefault, pszDimensionExtent); else msIO_fprintf(stdout, " %s\n", pszDimension, pszDimensionUnit, pszDimensionExtent); } else { msIO_fprintf(stdout, " \n", pszDimension, pszDimensionUnit); if(pszDimensionDefault && strlen(pszDimensionDefault) > 0) msIO_fprintf(stdout, " %s\n", pszDimension, pszDimensionDefault, pszDimensionExtent); else msIO_fprintf(stdout, " %s\n", pszDimension, pszDimensionExtent); } } msFree(pszDimension); msFree(pszDimensionItemName); msFree(pszDimensionUnitName); msFree(pszDimensionExtentName); msFree(pszDimensionDefaultName); } msFreeCharArray(tokens, ntokens); } } if (nVersion >= OWS_1_0_7) { msWMSPrintAttribution(stdout, " ", &(lp->metadata), "MO"); } /* AuthorityURL support and Identifier support, only available >= WMS 1.1.0 */ if(nVersion >= OWS_1_1_0) { msWMSPrintAuthorityURL(stdout, " ", &(lp->metadata), "MO"); msWMSPrintIdentifier(stdout, " ", &(lp->metadata), "MO"); } if(nVersion >= OWS_1_1_0) msOWSPrintURLType(stdout, &(lp->metadata), "MO", "metadataurl", OWS_NOERR, NULL, "MetadataURL", " type=\"%s\"", NULL, NULL, ">\n %s\n ", MS_TRUE, MS_FALSE, MS_FALSE, MS_TRUE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); if(nVersion < OWS_1_1_0) msOWSPrintEncodeMetadata(stdout, &(lp->metadata), "MO", "dataurl_href", OWS_NOERR, " %s\n", NULL); else msOWSPrintURLType(stdout, &(lp->metadata), "MO", "dataurl", OWS_NOERR, NULL, "DataURL", NULL, NULL, NULL, ">\n %s\n ", MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); /* The LegendURL reside in a style. The Web Map Context spec already */ /* included the support on this in mapserver. However, it is not in the */ /* wms_legendurl_... metadatas it's in the styles metadata, */ /* In wms_style__lengendurl_... metadata. So we have to detect */ /* the current style before reading it. Also in the Style block, we need */ /* a Title and a name. Title is derived from wms_style_\n"); } else if(nVersion >= OWS_1_1_0) { if (pszLegendURL) { /* First, print the style block */ msIO_fprintf(stdout, " \n"); } else { if (script_url_encoded) { if (lp->connectiontype != MS_WMS && lp->connectiontype != MS_WFS && lp->connectiontype != MS_UNUSED_1 && lp->numclasses > 0) { char width[10], height[10]; char *legendurl = NULL; size_t bufferSize = 0; int classnameset = 0, i=0; for (i=0; inumclasses; i++) { if (lp->class[i]->name && strlen(lp->class[i]->name) > 0) { classnameset = 1; break; } } if (classnameset) { int j=0, k=0, l=0, size_x=0, size_y=0, num_layers=0; int *group_layers = (int *)msSmallMalloc(sizeof(int)*map->numlayers); char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); num_layers = 1; group_layers[0] = lp->index; if (isUsedInNestedGroup[lp->index]) { for (j=0; j < map->numlayers; j++) { if (j == lp->index) continue; for(k = 0; k < numNestedGroups[j]; k++) { if (strcasecmp(lp->name, nestedGroups[j][k]) == 0) { group_layers[num_layers++] = j; break; } } } } group_layers =(int *)msSmallRealloc(group_layers, sizeof(int)*num_layers); if (msLegendCalcSize(map, 1, &size_x, &size_y, group_layers, num_layers, NULL, 1) == MS_SUCCESS) { const char *styleName = NULL; char *pszEncodedStyleName = NULL; layerObj *lp2 = NULL; snprintf(width, sizeof(width), "%d", size_x); snprintf(height, sizeof(height), "%d", size_y); bufferSize = strlen(script_url_encoded)+300; legendurl = (char*)msSmallMalloc(bufferSize); #if defined USE_GD_PNG || defined USE_PNG mimetype = msEncodeHTMLEntities("image/png"); #endif #if defined USE_GD_GIF if (!mimetype) mimetype = msEncodeHTMLEntities("image/gif"); #endif #if defined USE_GD_JPEG || defined USE_JPEG if (!mimetype) mimetype = msEncodeHTMLEntities("image/jpeg"); #endif if (!mimetype) mimetype = msEncodeHTMLEntities(MS_IMAGE_MIME_TYPE(map->outputformat)); /* -------------------------------------------------------------------- */ /* check if the group parameters for the classes are set. We */ /* should then publish the different class groups as different styles.*/ /* -------------------------------------------------------------------- */ iclassgroups = 0; classgroups = NULL; styleName = msOWSLookupMetadata(&(map->web.metadata), "MO", "style_name"); if (styleName == NULL) styleName = "default"; pszEncodedStyleName = msEncodeHTMLEntities(styleName); for (i=0; inumclasses; i++) { if (lp->class[i]->name && lp->class[i]->group) { /* Check that style is not inherited from root layer (#4442). */ if (strcasecmp(pszEncodedStyleName, lp->class[i]->group) == 0) continue; /* Check that style is not inherited from group layer(s) (#4442). */ if (numNestedGroups[lp->index] > 0) { for (j=0; jindex]; j++) { for (k=0; k < map->numlayers; k++) { if (GET_LAYER(map, k)->name && strcasecmp(GET_LAYER(map, k)->name, nestedGroups[lp->index][j]) == 0) { lp2 = (GET_LAYER(map, k)); for (l=0; l < lp2->numclasses; l++) { if (strcasecmp(lp2->class[l]->group, lp->class[i]->group) == 0) break; } break; } } if (lp2 && l < lp2->numclasses) break; } if (j < numNestedGroups[lp->index]) continue; } if (!classgroups) { classgroups = (char **)msSmallMalloc(sizeof(char *)); classgroups[iclassgroups++]= msStrdup(lp->class[i]->group); } else { /* Output style only once. */ for (j=0; jclass[i]->group) == 0) break; } if (j == iclassgroups) { iclassgroups++; classgroups = (char **)msSmallRealloc(classgroups, sizeof(char *)*iclassgroups); classgroups[iclassgroups-1]= msStrdup(lp->class[i]->group); } } } } msFree(pszEncodedStyleName); if (classgroups == NULL) { classgroups = (char **)msSmallMalloc(sizeof(char *)); classgroups[0]= msStrdup("default"); iclassgroups = 1; } for (i=0; iname); char *classgroup_encoded = msEncodeHTMLEntities(classgroups[i]); if (nVersion >= OWS_1_3_0) snprintf(legendurl, bufferSize, "%sversion=%s&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=%s&format=%s&STYLE=%s", script_url_encoded,msOWSGetVersionString(nVersion, szVersionBuf),name_encoded, mimetype, classgroup_encoded); else snprintf(legendurl, bufferSize, "%sversion=%s&service=WMS&request=GetLegendGraphic&layer=%s&format=%s&STYLE=%s", script_url_encoded,msOWSGetVersionString(nVersion, szVersionBuf),name_encoded, mimetype, classgroup_encoded); msFree(name_encoded); msFree(classgroup_encoded); msIO_fprintf(stdout, " \n"); } msFree(legendurl); msFreeCharArray(classgroups, iclassgroups); msFree(mimetype); } /* free the stuff used for nested layers */ for (i = 0; i < map->numlayers; i++) { if (numNestedGroups[i] > 0) { msFreeCharArray(nestedGroups[i], numNestedGroups[i]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); free(group_layers); } } } } } msFree(pszMetadataName); /* print Min/Max ScaleDenominator */ if (nVersion < OWS_1_3_0) msWMSPrintScaleHint(" ", lp->minscaledenom, lp->maxscaledenom, map->resolution); else msWMSPrintScaleDenominator(" ", lp->minscaledenom, lp->maxscaledenom); if ( grouplayer == MS_FALSE ) msIO_printf("%s \n", indent); return MS_SUCCESS; } /* * msWMSIsSubGroup */ int msWMSIsSubGroup(char** currentGroups, int currentLevel, char** otherGroups, int numOtherGroups) { int i; /* no match if otherGroups[] has less levels than currentLevel */ if (numOtherGroups <= currentLevel) { return MS_FALSE; } /* compare all groups below the current level */ for (i = 0; i <= currentLevel; i++) { if (strcmp(currentGroups[i], otherGroups[i]) != 0) { return MS_FALSE; /* if one of these is not equal it is not a sub group */ } } return MS_TRUE; } /*********************************************************************************** * msWMSPrintNestedGroups() * * * * purpose: Writes the layers to the capabilities that have the * * "WMS_LAYER_GROUP" metadata set. * * * * params: * * -map: The main map object * * -nVersion: OGC WMS version * * -pabLayerProcessed: boolean array indicating which layers have been dealt with. * * -index: the index of the current layer. * * -level: the level of depth in the group tree (root = 0) * * -nestedGroups: This array holds the arrays of groups that have * * been set through the WMS_LAYER_GROUP metadata * * -numNestedGroups: This array holds the number of nested groups for each layer * ***********************************************************************************/ void msWMSPrintNestedGroups(mapObj* map, int nVersion, char* pabLayerProcessed, int index, int level, char*** nestedGroups, int* numNestedGroups, int* isUsedInNestedGroup, const char *script_url_encoded, const char *validated_language) { int i, j; int groupAdded = 0; char *indent = NULL; indent = msStrdup(""); for (i = 0; i < level; i++) { indent = msStringConcatenate(indent, " "); } if (numNestedGroups[index] <= level) { /* no more subgroups */ if ((!pabLayerProcessed[index]) && (!isUsedInNestedGroup[index])) { /* we are at the deepest level of the group branchings, so add layer now. */ msDumpLayer(map, GET_LAYER(map, index), nVersion, script_url_encoded, indent, validated_language, MS_FALSE); pabLayerProcessed[index] = 1; /* done */ } } else { /* not yet there, we have to deal with this group and possible subgroups and layers. */ for (j = 0; j < map->numlayers; j++) { if ( GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, nestedGroups[index][level]) == 0 ) { break; } } /* Beginning of a new group... enclose the group in a layer block */ if ( j < map->numlayers ) { if (!pabLayerProcessed[j]) { msDumpLayer(map, GET_LAYER(map, j), nVersion, script_url_encoded, indent, validated_language, MS_TRUE); pabLayerProcessed[j] = 1; /* done */ groupAdded = 1; } } else { msIO_printf("%s \n", indent); msIO_printf("%s %s\n", indent, nestedGroups[index][level]); groupAdded = 1; } /* Look for one group deeper in the current layer */ if (!pabLayerProcessed[index]) { msWMSPrintNestedGroups(map, nVersion, pabLayerProcessed, index, level + 1, nestedGroups, numNestedGroups, isUsedInNestedGroup, script_url_encoded, validated_language); } /* look for subgroups in other layers. */ for (j = index + 1; j < map->numlayers; j++) { if (msWMSIsSubGroup(nestedGroups[index], level, nestedGroups[j], numNestedGroups[j])) { if (!pabLayerProcessed[j]) { msWMSPrintNestedGroups(map, nVersion, pabLayerProcessed, j, level + 1, nestedGroups, numNestedGroups, isUsedInNestedGroup, script_url_encoded, validated_language); } } else { /* TODO: if we would sort all layers on "WMS_LAYER_GROUP" beforehand */ /* we could break out of this loop at this point, which would increase */ /* performance. */ } } /* Close group layer block */ if (groupAdded) msIO_printf("%s \n", indent); } msFree(indent); } /* msWMSPrintNestedGroups */ /* ** msWMSGetCapabilities() */ int msWMSGetCapabilities(mapObj *map, int nVersion, cgiRequestObj *req, owsRequestObj *ows_request, const char *requested_updatesequence, char *wms_exception_format, const char *requested_language) { char *dtd_url = NULL; char *script_url=NULL, *script_url_encoded=NULL; char szVersionBuf[OWS_VERSION_MAXLEN]; char *schemalocation = NULL; const char *updatesequence=NULL; const char *sldenabled=NULL; const char *encoding; const char *layerlimit=NULL; char *pszTmp=NULL; int i; const char *format_list=NULL; char **tokens = NULL; int numtokens = 0; char *validated_language = NULL; updatesequence = msOWSLookupMetadata(&(map->web.metadata), "MO", "updatesequence"); sldenabled = msOWSLookupMetadata(&(map->web.metadata), "MO", "sld_enabled"); encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); if (sldenabled == NULL) sldenabled = "true"; if (requested_updatesequence != NULL) { i = msOWSNegotiateUpdateSequence(requested_updatesequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_WMSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWMSGetCapabilities()", requested_updatesequence, updatesequence); return msWMSException(map, nVersion, "CurrentUpdateSequence", wms_exception_format); } if (i > 0) { /* invalid */ msSetError(MS_WMSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWMSGetCapabilities()", requested_updatesequence, updatesequence); return msWMSException(map, nVersion, "InvalidUpdateSequence", wms_exception_format); } } schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); if (nVersion < 0) nVersion = OWS_1_3_0; /* Default to 1.3.0 */ /* Decide which version we're going to return. */ if (nVersion < OWS_1_0_7) { nVersion = OWS_1_0_0; dtd_url = msStrdup(schemalocation); dtd_url = msStringConcatenate(dtd_url, "/wms/1.0.0/capabilities_1_0_0.dtd"); } else if (nVersion < OWS_1_1_0) { nVersion = OWS_1_0_7; dtd_url = msStrdup(schemalocation); dtd_url = msStringConcatenate(dtd_url, "/wms/1.0.7/capabilities_1_0_7.dtd"); } else if (nVersion < OWS_1_1_1) { nVersion = OWS_1_1_0; dtd_url = msStrdup(schemalocation); dtd_url = msStringConcatenate(dtd_url, "/wms/1.1.0/capabilities_1_1_0.dtd"); } else if (nVersion < OWS_1_3_0) { nVersion = OWS_1_1_1; dtd_url = msStrdup(schemalocation); /* this exception was added to accomadote the OGC test suite (Bug 1576)*/ if (strcasecmp(schemalocation, OWS_DEFAULT_SCHEMAS_LOCATION) == 0) dtd_url = msStringConcatenate(dtd_url, "/wms/1.1.1/WMS_MS_Capabilities.dtd"); else dtd_url = msStringConcatenate(dtd_url, "/wms/1.1.1/capabilities_1_1_1.dtd"); } else nVersion = OWS_1_3_0; /* This function owns validated_language, so remember to free it later*/ validated_language = msOWSGetLanguageFromList(map, "MO", requested_language); if (validated_language != NULL) { for(i=0; inumlayers; i++) { layerObj *layer = GET_LAYER(map, i); if(layer->data) layer->data = msCaseReplaceSubstring(layer->data, "%language%", validated_language); if(layer->connection) layer->connection = msCaseReplaceSubstring(layer->connection, "%language%", validated_language); } } /* We need this server's onlineresource. */ /* Default to use the value of the "onlineresource" metadata, and if not */ /* set then build it: "http://$(SERVER_NAME):$(SERVER_PORT)$(SCRIPT_NAME)?" */ /* the returned string should be freed once we're done with it. */ if ((script_url=msOWSGetOnlineResource2(map, "MO", "onlineresource", req, validated_language)) == NULL || (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL) { msFree(validated_language); return msWMSException(map, nVersion, NULL, wms_exception_format); } if (nVersion <= OWS_1_0_7 || nVersion >= OWS_1_3_0) /* 1.0.0 to 1.0.7 and >=1.3.0*/ if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); else /* 1.1.0 and later */ if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.wms_xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.wms_xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); /*TODO review wms1.3.0*/ if ( nVersion < OWS_1_3_0) { msIO_printf("web.metadata), "MO", "inspire_capabilities") ) { msIO_printf("" " " "" "" "\n"); } else { /* some mapserver specific declarations will go here */ msIO_printf(" \n"); } msIO_printf(" ]> \n\n"); } updatesequence = msOWSLookupMetadata(&(map->web.metadata), "MO", "updatesequence"); if ( nVersion >= OWS_1_3_0) msIO_printf("web.metadata), "MO", "inspire_capabilities") ) { msIO_printf(" xmlns:inspire_common=\"http://inspire.ec.europa.eu/schemas/common/1.0\"" " xmlns:inspire_vs=\"http://inspire.ec.europa.eu/schemas/inspire_vs/1.0\"" ); } msIO_printf(" xsi:schemaLocation=\"http://www.opengis.net/wms %s/wms/%s/capabilities_1_3_0.xsd " " http://www.opengis.net/sld %s/sld/1.1.0/sld_capabilities.xsd ", msOWSGetSchemasLocation(map), msOWSGetVersionString(nVersion, szVersionBuf), msOWSGetSchemasLocation(map)); if ( msOWSLookupMetadata(&(map->web.metadata), "MO", "inspire_capabilities") ) { msIO_printf(" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0 " " http://inspire.ec.europa.eu/schemas/inspire_vs/1.0/inspire_vs.xsd"); } msIO_printf(" http://mapserver.gis.umn.edu/mapserver %sservice=WMS&version=1.3.0&request=GetSchemaExtension\"", script_url_encoded); } msIO_printf(">\n"); /* Report MapServer Version Information */ msIO_printf("\n\n\n", msGetVersion()); /* WMS definition */ msIO_printf("\n"); /* Service name is defined by the spec and changed at v1.0.0 */ if (nVersion <= OWS_1_0_7) msIO_printf(" GetMap\n"); /* v 1.0.0 to 1.0.7 */ else if (nVersion > OWS_1_0_7 && nVersion < OWS_1_3_0) msIO_printf(" OGC:WMS\n"); /* v 1.1.0 to 1.1.1*/ else msIO_printf(" WMS\n"); /* v 1.3.0+ */ /* the majority of this section is dependent on appropriately named metadata in the WEB object */ msOWSPrintEncodeMetadata2(stdout, &(map->web.metadata), "MO", "title", OWS_WARN, " %s\n", map->name, validated_language); msOWSPrintEncodeMetadata2(stdout, &(map->web.metadata), "MO", "abstract", OWS_NOERR, " %s\n", NULL, validated_language); msWMSPrintKeywordlist(stdout, " ", "keywordlist", &(map->web.metadata), "MO", nVersion); /* Service/onlineresource */ /* Defaults to same as request onlineresource if wms_service_onlineresource */ /* is not set. */ if (nVersion== OWS_1_0_0) msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "service_onlineresource", OWS_NOERR, " %s\n", script_url_encoded); else msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "service_onlineresource", OWS_NOERR, " \n", script_url_encoded); /* contact information is a required element in 1.0.7 but the */ /* sub-elements such as ContactPersonPrimary, etc. are not! */ /* In 1.1.0, ContactInformation becomes optional. */ msOWSPrintContactInfo(stdout, " ", nVersion, &(map->web.metadata), "MO"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "fees", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "accessconstraints", OWS_NOERR, " %s\n", NULL); if (nVersion >= OWS_1_3_0) { layerlimit = msOWSLookupMetadata(&(map->web.metadata), "MO", "layerlimit"); if (layerlimit) { msIO_printf(" %s\n", layerlimit); } msIO_printf(" %d\n", map->maxsize); msIO_printf(" %d\n", map->maxsize); } msIO_printf("\n\n"); /* WMS capabilities definitions */ msIO_printf("\n"); msIO_printf(" \n"); if (nVersion <= OWS_1_0_7) { /* WMS 1.0.0 to 1.0.7 - We don't try to use outputformats list here for now */ if (msOWSRequestIsEnabled(map, NULL, "M", "GetMap", MS_FALSE)) msWMSPrintRequestCap(nVersion, "Map", script_url_encoded, "" #ifdef USE_GD_GIF "" #endif #if defined USE_GD_PNG || defined USE_PNG "" #endif #if defined USE_GD_JPEG || defined USE_JPEG "" #endif "" , NULL); if (msOWSRequestIsEnabled(map, NULL, "M", "GetCapabilities", MS_TRUE)) msWMSPrintRequestCap(nVersion, "Capabilities", script_url_encoded, "", NULL); if (msOWSRequestIsEnabled(map, NULL, "M", "GetFeatureInfo", MS_FALSE)) msWMSPrintRequestCap(nVersion, "FeatureInfo", script_url_encoded, "", NULL); } else { char *mime_list[20]; int mime_count = 0; int max_mime = 20; /* WMS 1.1.0 and later */ /* Note changes to the request names, their ordering, and to the formats */ if (msOWSRequestIsEnabled(map, NULL, "M", "GetCapabilities", MS_TRUE)) { if (nVersion >= OWS_1_3_0) msWMSPrintRequestCap(nVersion, "GetCapabilities", script_url_encoded, "text/xml", NULL); else msWMSPrintRequestCap(nVersion, "GetCapabilities", script_url_encoded, "application/vnd.ogc.wms_xml", NULL); } msGetOutputFormatMimeListWMS(map,mime_list,sizeof(mime_list)/sizeof(char*)); if (msOWSRequestIsEnabled(map, NULL, "M", "GetMap", MS_FALSE)) msWMSPrintRequestCap(nVersion, "GetMap", script_url_encoded, mime_list[0], mime_list[1], mime_list[2], mime_list[3], mime_list[4], mime_list[5], mime_list[6], mime_list[7], mime_list[8], mime_list[9], mime_list[10], mime_list[11], mime_list[12], mime_list[13], mime_list[14], mime_list[15], mime_list[16], mime_list[17], mime_list[18], mime_list[19], NULL ); format_list = msOWSLookupMetadata(&(map->web.metadata), "M", "getfeatureinfo_formatlist"); /*feature_info_mime_type depricated for MapServer 6.0*/ if (!format_list) format_list = msOWSLookupMetadata(&(map->web.metadata), "MO", "feature_info_mime_type"); if (format_list && strlen(format_list) > 0) { tokens = msStringSplit(format_list, ',', &numtokens); if (tokens && numtokens > 0) { mime_count = 0; for(i=0; i < numtokens; i++ ) { msStringTrim(tokens[i]); /*text plain and gml do not need to be a format and accepted by default*/ /*can not really validate since the old way of using template with wei->header, layer->template ... should be kept*/ if (strlen(tokens[i]) > 0 && mime_count0) { if (mime_count0) msFreeCharArray(tokens, numtokens); } else { if (msOWSRequestIsEnabled(map, NULL, "M", "GetFeatureInfo", MS_FALSE)) msWMSPrintRequestCap(nVersion, "GetFeatureInfo", script_url_encoded, "text/plain", "application/vnd.ogc.gml", NULL); } if (strcasecmp(sldenabled, "true") == 0) { if (msOWSRequestIsEnabled(map, NULL, "M", "DescribeLayer", MS_FALSE)) { if (nVersion == OWS_1_3_0) msWMSPrintRequestCap(nVersion, "sld:DescribeLayer", script_url_encoded, "text/xml", NULL); else msWMSPrintRequestCap(nVersion, "DescribeLayer", script_url_encoded, "text/xml", NULL); } msGetOutputFormatMimeListImg(map,mime_list,sizeof(mime_list)/sizeof(char*)); if (nVersion >= OWS_1_1_1) { if (nVersion == OWS_1_3_0) { if (msOWSRequestIsEnabled(map, NULL, "M", "GetLegendGraphic", MS_FALSE)) msWMSPrintRequestCap(nVersion, "sld:GetLegendGraphic", script_url_encoded, mime_list[0], mime_list[1], mime_list[2], mime_list[3], mime_list[4], mime_list[5], mime_list[6], mime_list[7], mime_list[8], mime_list[9], mime_list[10], mime_list[11], mime_list[12], mime_list[13], mime_list[14], mime_list[15], mime_list[16], mime_list[17], mime_list[18], mime_list[19], NULL ); if (msOWSRequestIsEnabled(map, NULL, "M", "GetStyles", MS_FALSE)) msWMSPrintRequestCap(nVersion, "ms:GetStyles", script_url_encoded, "text/xml", NULL); } else { if (msOWSRequestIsEnabled(map, NULL, "M", "GetLegendGraphic", MS_FALSE)) msWMSPrintRequestCap(nVersion, "GetLegendGraphic", script_url_encoded, mime_list[0], mime_list[1], mime_list[2], mime_list[3], mime_list[4], mime_list[5], mime_list[6], mime_list[7], mime_list[8], mime_list[9], mime_list[10], mime_list[11], mime_list[12], mime_list[13], mime_list[14], mime_list[15], mime_list[16], mime_list[17], mime_list[18], mime_list[19], NULL ); if (msOWSRequestIsEnabled(map, NULL, "M", "GetStyles", MS_FALSE)) msWMSPrintRequestCap(nVersion, "GetStyles", script_url_encoded, "text/xml", NULL); } } } } msIO_printf(" \n"); msIO_printf(" \n"); if (nVersion <= OWS_1_0_7) msIO_printf(" \n"); else if (nVersion <= OWS_1_1_1) { msIO_printf(" application/vnd.ogc.se_xml\n"); msIO_printf(" application/vnd.ogc.se_inimage\n"); msIO_printf(" application/vnd.ogc.se_blank\n"); } else { /*>=1.3.0*/ msIO_printf(" XML\n"); msIO_printf(" INIMAGE\n"); msIO_printf(" BLANK\n"); } msIO_printf(" \n"); if (nVersion != OWS_1_3_0) { /* INSPIRE extended capabilities for WMS 1.1.1 */ if (nVersion == OWS_1_1_1 && msOWSLookupMetadata(&(map->web.metadata), "MO", "inspire_capabilities") ) { msIO_printf(" \n"); msOWSPrintInspireCommonExtendedCapabilities(stdout, map, "MO", OWS_WARN, "inspire_vs:ExtendedCapabilities", validated_language, OWS_WMS); msIO_printf(" \n"); } else { msIO_printf(" \n"); /* nothing yet */ } } /* SLD support */ if (strcasecmp(sldenabled, "true") == 0) { if (nVersion >= OWS_1_0_7) { if (nVersion >= OWS_1_3_0) msIO_printf(" \n"); else msIO_printf(" \n"); } } /* INSPIRE extended capabilities for WMS 1.3.0 */ if (nVersion >= OWS_1_3_0 && msOWSLookupMetadata(&(map->web.metadata), "MO", "inspire_capabilities") ) { msOWSPrintInspireCommonExtendedCapabilities(stdout, map, "MO", OWS_WARN, "inspire_vs:ExtendedCapabilities", validated_language, OWS_WMS); } /* Top-level layer with map extents and SRS, encloses all map layers */ /* Output only if at least one layers is enabled. */ if (ows_request->numlayers == 0) { msIO_fprintf(stdout, " \n"); } else { msIO_printf(" \n"); /* Layer Name is optional but title is mandatory. */ if (map->name && strlen(map->name) > 0 && (msIsXMLTagValid(map->name) == MS_FALSE || isdigit(map->name[0]))) msIO_fprintf(stdout, "\n", map->name); msOWSPrintEncodeParam(stdout, "MAP.NAME", map->name, OWS_NOERR, " %s\n", NULL); if (msOWSLookupMetadataWithLanguage(&(map->web.metadata), "MO", "rootlayer_title", validated_language)) msOWSPrintEncodeMetadata2(stdout, &(map->web.metadata), "MO", "rootlayer_title", OWS_WARN, " %s\n", map->name, validated_language); else msOWSPrintEncodeMetadata2(stdout, &(map->web.metadata), "MO", "title", OWS_WARN, " %s\n", map->name, validated_language); if (msOWSLookupMetadataWithLanguage(&(map->web.metadata), "MO", "rootlayer_abstract", validated_language)) msOWSPrintEncodeMetadata2(stdout, &(map->web.metadata), "MO", "rootlayer_abstract", OWS_NOERR, " %s\n", map->name, validated_language); else msOWSPrintEncodeMetadata2(stdout, &(map->web.metadata), "MO", "abstract", OWS_NOERR, " %s\n", map->name, validated_language); if (msOWSLookupMetadata(&(map->web.metadata), "MO", "rootlayer_keywordlist") || msOWSLookupMetadata(&(map->web.metadata), "MO", "rootlayer_keywordlist_vocabulary")) pszTmp = msStrdup("rootlayer_keywordlist"); else pszTmp = msStrdup("keywordlist"); msWMSPrintKeywordlist(stdout, " ", pszTmp, &(map->web.metadata), "MO", nVersion); msFree(pszTmp); /* According to normative comments in the 1.0.7 DTD, the root layer's SRS tag */ /* is REQUIRED. It also suggests that we use an empty SRS element if there */ /* is no common SRS. */ if (nVersion > OWS_1_1_0) { /* starting 1.1.1 SRS are given in individual tags */ if (nVersion >= OWS_1_3_0) msOWSPrintEncodeParamList(stdout, "(at least one of) " "MAP.PROJECTION, LAYER.PROJECTION " "or wms_srs metadata", msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_FALSE), OWS_WARN, ' ', NULL, NULL, " %s\n", ""); else msOWSPrintEncodeParamList(stdout, "(at least one of) " "MAP.PROJECTION, LAYER.PROJECTION " "or wms_srs metadata", msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_FALSE), OWS_WARN, ' ', NULL, NULL, " %s\n", ""); } else /* If map has no proj then every layer MUST have one or produce a warning */ msOWSPrintEncodeParam(stdout, "MAP.PROJECTION (or wms_srs metadata)", msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_FALSE), OWS_WARN, " %s\n", ""); if (nVersion >= OWS_1_3_0) msOWSPrintEX_GeographicBoundingBox(stdout, " ", &(map->extent), &(map->projection)); else msOWSPrintLatLonBoundingBox(stdout, " ", &(map->extent), &(map->projection), NULL, OWS_WMS); msOWSPrintBoundingBox( stdout, " ", &(map->extent), &(map->projection), NULL, &(map->web.metadata), "MO", nVersion); if (nVersion >= OWS_1_0_7) { msWMSPrintAttribution(stdout, " ", &(map->web.metadata), "MO"); } /* AuthorityURL support and Identifier support, only available >= WMS 1.1.0 */ if(nVersion >= OWS_1_1_0) { msWMSPrintAuthorityURL(stdout, " ", &(map->web.metadata), "MO"); msWMSPrintIdentifier(stdout, " ", &(map->web.metadata), "MO"); } /* MetadataURL */ if(nVersion >= OWS_1_1_0) msOWSPrintURLType(stdout, &(map->web.metadata), "MO", "metadataurl", OWS_NOERR, NULL, "MetadataURL", " type=\"%s\"", NULL, NULL, ">\n %s\n ", MS_TRUE, MS_FALSE, MS_FALSE, MS_TRUE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); /* DataURL */ if(nVersion < OWS_1_1_0) msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "dataurl_href", OWS_NOERR, " %s\n", NULL); else msOWSPrintURLType(stdout, &(map->web.metadata), "MO", "dataurl", OWS_NOERR, NULL, "DataURL", NULL, NULL, NULL, ">\n %s\n ", MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); if (map->name && strlen(map->name) > 0 && msOWSLookupMetadata(&(map->web.metadata), "MO", "inspire_capabilities") ) { char *pszEncodedName = NULL; const char *styleName = NULL; char *pszEncodedStyleName = NULL; const char *legendURL = NULL; pszEncodedName = msEncodeHTMLEntities(map->name); styleName = msOWSLookupMetadata(&(map->web.metadata), "MO", "style_name"); if (styleName == NULL) styleName = "default"; pszEncodedStyleName = msEncodeHTMLEntities(styleName); msIO_fprintf(stdout, " \n"); msFree(pszEncodedName); msFree(pszEncodedStyleName); } if (nVersion < OWS_1_3_0) msWMSPrintScaleHint(" ", map->web.minscaledenom, map->web.maxscaledenom, map->resolution); else msWMSPrintScaleDenominator(" ", map->web.minscaledenom, map->web.maxscaledenom); /* */ /* Dump list of layers organized by groups. Layers with no group are listed */ /* individually, at the same level as the groups in the layer hierarchy */ /* */ if (map->numlayers) { int i, j; char *pabLayerProcessed = NULL; char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; /* We'll use this array of booleans to track which layer/group have been */ /* processed already */ pabLayerProcessed = (char *)msSmallCalloc(map->numlayers, sizeof(char*)); /* Mark disabled layers as processed to prevent from being displayed in nested groups (#4533)*/ for(i=0; inumlayers; i++) { if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) pabLayerProcessed[i] = 1; } nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); for(i=0; inumlayers; i++) { layerObj *lp; lp = (GET_LAYER(map, i)); if (pabLayerProcessed[i] || (lp->status == MS_DELETE)) continue; /* Layer is hidden or has already been handled */ if (numNestedGroups[i] > 0) { /* Has nested groups. */ msWMSPrintNestedGroups(map, nVersion, pabLayerProcessed, i, 0, nestedGroups, numNestedGroups, isUsedInNestedGroup, script_url_encoded, validated_language); } else if (lp->group == NULL || strlen(lp->group) == 0) { /* Don't dump layer if it is used in wms_group_layer. */ if (!isUsedInNestedGroup[i]) { /* This layer is not part of a group... dump it directly */ msDumpLayer(map, lp, nVersion, script_url_encoded, "", validated_language, MS_FALSE); pabLayerProcessed[i] = 1; } } else { /* Beginning of a new group... enclose the group in a layer block */ msIO_printf(" \n"); /* Layer Name is optional but title is mandatory. */ if (lp->group && strlen(lp->group) > 0 && (msIsXMLTagValid(lp->group) == MS_FALSE || isdigit(lp->group[0]))) msIO_fprintf(stdout, "\n", lp->group); msOWSPrintEncodeParam(stdout, "GROUP.NAME", lp->group, OWS_NOERR, " %s\n", NULL); msOWSPrintGroupMetadata2(stdout, map, lp->group, "MO", "GROUP_TITLE", OWS_WARN, " %s\n", lp->group, validated_language); msOWSPrintGroupMetadata2(stdout, map, lp->group, "MO", "GROUP_ABSTRACT", OWS_NOERR, " %s\n", lp->group, validated_language); /*build a getlegendgraphicurl*/ if( script_url_encoded) { if (lp->group && strlen(lp->group) > 0) { char *pszEncodedName = NULL; const char *styleName = NULL; char *pszEncodedStyleName = NULL; const char *legendURL = NULL; pszEncodedName = msEncodeHTMLEntities(lp->group); styleName = msOWSLookupMetadata(&(lp->metadata), "MO", "group_style_name"); if (styleName == NULL) styleName = "default"; pszEncodedStyleName = msEncodeHTMLEntities(styleName); msIO_fprintf(stdout, " \n"); msFree(pszEncodedName); msFree(pszEncodedStyleName); } } /* Dump all layers for this group */ for(j=i; jnumlayers; j++) { if (!pabLayerProcessed[j] && GET_LAYER(map, j)->group && strcmp(lp->group, GET_LAYER(map, j)->group) == 0 && msIntegerInArray(GET_LAYER(map, j)->index, ows_request->enabled_layers, ows_request->numlayers)) { msDumpLayer(map, (GET_LAYER(map, j)), nVersion, script_url_encoded, " ", validated_language, MS_FALSE); pabLayerProcessed[j] = 1; } } /* Close group layer block */ msIO_printf(" \n"); } } free(pabLayerProcessed); /* free the stuff used for nested layers */ for (i = 0; i < map->numlayers; i++) { if (numNestedGroups[i] > 0) { msFreeCharArray(nestedGroups[i], numNestedGroups[i]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); } msIO_printf(" \n"); } msIO_printf("\n"); if ( nVersion >= OWS_1_3_0) msIO_printf("\n"); else msIO_printf("\n"); msFree(validated_language); free(script_url); free(script_url_encoded); free(dtd_url); free(schemalocation); return(MS_SUCCESS); } /* * This function look for params that can be used * by mapserv when generating template. */ int msTranslateWMS2Mapserv(const char **names, const char **values, int numentries, char ***translated_names, char ***translated_values, int *translated_numentries) { int i=0, num_allocated = numentries; *translated_names = (char**)msSmallMalloc(num_allocated * sizeof(char*)); *translated_values = (char**)msSmallMalloc(num_allocated * sizeof(char*)); *translated_numentries = 0; for (i=0; i 0) || (strcasecmp(names[i], "SLD_BODY") == 0 && values[i] && strlen(values[i]) > 0)) { sldrequested = MS_TRUE; break; } } if (sldrequested) { for (i=0; inumlayers; i++) { if (msLookupHashTable(&(GET_LAYER(map, i)->metadata), "tmp_wms_sld_query")) { sldspatialfilter = MS_TRUE; break; } } } /* turn off layer if WMS GetMap is not enabled */ for (i=0; inumlayers; i++) if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) GET_LAYER(map, i)->status = MS_OFF; if (sldrequested && sldspatialfilter) { /* set the quermap style so that only selected features will be retruned */ map->querymap.status = MS_ON; map->querymap.style = MS_SELECTED; img = msPrepareImage(map, MS_TRUE); /* compute layer scale factors now */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->sizeunits != MS_PIXELS) GET_LAYER(map, i)->scalefactor = (msInchesPerUnit(GET_LAYER(map, i)->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize; else if(GET_LAYER(map, i)->symbolscaledenom > 0 && map->scaledenom > 0) GET_LAYER(map, i)->scalefactor = GET_LAYER(map, i)->symbolscaledenom/map->scaledenom; else GET_LAYER(map, i)->scalefactor = 1; } for (i=0; inumlayers; i++) { if (msLookupHashTable(&(GET_LAYER(map, i)->metadata), "tmp_wms_sld_query") && (GET_LAYER(map, i)->type == MS_LAYER_POINT || GET_LAYER(map, i)->type == MS_LAYER_LINE || GET_LAYER(map, i)->type == MS_LAYER_POLYGON || GET_LAYER(map, i)->type == MS_LAYER_ANNOTATION || GET_LAYER(map, i)->type == MS_LAYER_TILEINDEX)) { /* make sure that there is a resultcache. If not just ignore */ /* the layer */ if (GET_LAYER(map, i)->resultcache) msDrawQueryLayer(map, GET_LAYER(map, i), img); } else msDrawLayer(map, GET_LAYER(map, i), img); } } else img = msDrawMap(map, MS_FALSE); if (img == NULL) return msWMSException(map, nVersion, NULL, wms_exception_format); /* Set the HTTP Cache-control headers if they are defined in the map object */ if( (http_max_age = msOWSLookupMetadata(&(map->web.metadata), "MO", "http_max_age")) ) { msIO_setHeader("Cache-Control","max-age=%s", http_max_age); } if (strcasecmp(map->imagetype, "application/openlayers")!=0) { msIO_setHeader("Content-Type", "%s", MS_IMAGE_MIME_TYPE(map->outputformat)); msIO_sendHeaders(); if (msSaveImage(map, img, NULL) != MS_SUCCESS) { msFreeImage(img); return msWMSException(map, nVersion, NULL, wms_exception_format); } } msFreeImage(img); return(MS_SUCCESS); } int msDumpResult(mapObj *map, int bFormatHtml, int nVersion, char *wms_exception_format) { int numresults=0; int i; for(i=0; inumlayers; i++) { int j, k, *itemvisible; char **incitems=NULL; int numincitems=0; char **excitems=NULL; int numexcitems=0; const char *value; size_t bufferSize=0; size_t reqBuffSize; char *tag=NULL; const char *lineTemplate=" %s = '%s'\n"; layerObj *lp; lp = (GET_LAYER(map, i)); if(lp->status != MS_ON || lp->resultcache==NULL || lp->resultcache->numresults == 0) continue; /* if(msLayerOpen(lp) != MS_SUCCESS || msLayerGetItems(lp) != MS_SUCCESS) return msWMSException(map, nVersion, NULL); */ /* Use metadata to control which fields to output. We use the same * metadata names as for GML: * wms/ows_include_items: comma delimited list or keyword 'all' * wms/ows_exclude_items: comma delimited list (all items are excluded by default) */ /* get a list of items that should be excluded in output */ if((value = msOWSLookupMetadata(&(lp->metadata), "MO", "include_items")) != NULL) incitems = msStringSplit(value, ',', &numincitems); /* get a list of items that should be excluded in output */ if((value = msOWSLookupMetadata(&(lp->metadata), "MO", "exclude_items")) != NULL) excitems = msStringSplit(value, ',', &numexcitems); itemvisible = (int*)msSmallMalloc(lp->numitems*sizeof(int)); for(k=0; knumitems; k++) { int l; itemvisible[k] = MS_FALSE; /* check visibility, included items first... */ if(numincitems == 1 && strcasecmp("all", incitems[0]) == 0) { itemvisible[k] = MS_TRUE; } else { for(l=0; litems[k], incitems[l]) == 0) itemvisible[k] = MS_TRUE; } } /* ...and now excluded items */ for(l=0; litems[k], excitems[l]) == 0) itemvisible[k] = MS_FALSE; } } msFreeCharArray(incitems, numincitems); msFreeCharArray(excitems, numexcitems); /* Output selected shapes for this layer */ msIO_printf("\nLayer '%s'\n", lp->name); for(j=0; jresultcache->numresults; j++) { shapeObj shape; msInitShape(&shape); if (msLayerGetShape(lp, &shape, &(lp->resultcache->results[j])) != MS_SUCCESS) { if (tag != NULL) msFree(tag); msFree(itemvisible); return msWMSException(map, nVersion, NULL, wms_exception_format); } msIO_printf(" Feature %ld: \n", lp->resultcache->results[j].shapeindex); for(k=0; knumitems; k++) { if (itemvisible[k]) { reqBuffSize = strlen(lp->items[k]) + 7; if (reqBuffSize > bufferSize) { if (tag != NULL) msFree(tag); /* allocate more buffer than we need to try and avoid need for repeated reallocation */ bufferSize = reqBuffSize * 2; tag = (char*)msSmallMalloc(bufferSize); } snprintf(tag, reqBuffSize, "%s_alias", lp->items[k]); if((value = msOWSLookupMetadata(&(lp->metadata), "MO", tag)) != NULL) msIO_printf(lineTemplate, value, shape.values[k]); else msIO_printf(lineTemplate, lp->items[k], shape.values[k]); } } msFreeShape(&shape); numresults++; } if (tag != NULL) msFree(tag); msFree(itemvisible); /* msLayerClose(lp); */ } return numresults; } /* ** msWMSFeatureInfo() */ int msWMSFeatureInfo(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format, owsRequestObj *ows_request) { int i, feature_count=1, numlayers_found=0; pointObj point = {-1.0, -1.0}; const char *info_format="MIME"; double cellx, celly; errorObj *ms_error = msGetErrorObj(); int query_status=MS_NOERR; const char *encoding; int query_layer = 0; const char *format_list=NULL; int valid_format=MS_FALSE; int format_found = MS_FALSE; int use_bbox = MS_FALSE; int wms_layer = MS_FALSE; const char *wms_connection = NULL; int numOWSLayers = 0; char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); for(i=0; map && inumlayers; j++) { /* Force all layers OFF by default */ GET_LAYER(map, j)->status = MS_OFF; for(k=0; kname && strcasecmp(GET_LAYER(map, j)->name, layers[k]) == 0) || (map->name && strcasecmp(map->name, layers[k]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[k]) == 0) || ((numNestedGroups[j] >0) && msStringInArray(layers[k], nestedGroups[j], numNestedGroups[j]))) && (msIntegerInArray(GET_LAYER(map, j)->index, ows_request->enabled_layers, ows_request->numlayers)) ) { if (GET_LAYER(map, j)->connectiontype == MS_WMS) { wms_layer = MS_TRUE; wms_connection = GET_LAYER(map, j)->connection; } /* Don't turn on layers that are not queryable but have sublayers. */ if ((msIsLayerQueryable(GET_LAYER(map, j))) || isUsedInNestedGroup[j] == 0) { numlayers_found++; GET_LAYER(map, j)->status = MS_ON; } } } } msFreeCharArray(layers, numlayers); } else if (strcasecmp(names[i], "INFO_FORMAT") == 0) { if (values[i] && strlen(values[i]) > 0) { info_format = values[i]; format_found = MS_TRUE; } } else if (strcasecmp(names[i], "FEATURE_COUNT") == 0) feature_count = atoi(values[i]); else if(strcasecmp(names[i], "X") == 0 || strcasecmp(names[i], "I") == 0) point.x = atof(values[i]); else if (strcasecmp(names[i], "Y") == 0 || strcasecmp(names[i], "J") == 0) point.y = atof(values[i]); else if (strcasecmp(names[i], "RADIUS") == 0) { /* RADIUS in pixels. */ /* This is not part of the spec, but some servers such as cubeserv */ /* support it as a vendor-specific feature. */ /* It's easy for MapServer to handle this so let's do it! */ /* Special RADIUS value that changes the query into a bbox query */ /* based on the bbox in the request parameters. */ if( strcasecmp(values[i], "BBOX") == 0) { use_bbox = MS_TRUE; } else { int j; for(j=0; jnumlayers; j++) { GET_LAYER(map, j)->tolerance = atoi(values[i]); GET_LAYER(map, j)->toleranceunits = MS_PIXELS; } } } } /* free the stuff used for nested layers */ for (i = 0; i < map->numlayers; i++) { if (numNestedGroups[i] > 0) { msFreeCharArray(nestedGroups[i], numNestedGroups[i]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); if(numlayers_found == 0) { if (query_layer) { msSetError(MS_WMSERR, "Layer(s) specified in QUERY_LAYERS parameter is not offered by the service instance.", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } else { msSetError(MS_WMSERR, "Required QUERY_LAYERS parameter missing for getFeatureInfo.", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } } /*make sure to initialize the map scale so that layers that are scale dependent are resepected for the query*/ msCalculateScale(map->extent,map->units,map->width,map->height, map->resolution, &map->scaledenom); /* -------------------------------------------------------------------- */ /* check if all layers selected are queryable. If not send an */ /* exception. */ /* -------------------------------------------------------------------- */ /* If a layer of type WMS was found... all layers have to be of that type and with the same connection */ for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->status == MS_ON) { if (!msIsLayerQueryable(GET_LAYER(map, i))) { msSetError(MS_WMSERR, "Requested layer(s) are not queryable.", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, "LayerNotQueryable", wms_exception_format); } else if (wms_layer == MS_TRUE) { if ( (GET_LAYER(map, i)->connectiontype != MS_WMS) || (strcasecmp(wms_connection, GET_LAYER(map, i)->connection) != 0) ) { msSetError(MS_WMSERR, "Requested WMS layer(s) are not queryable: type or connection differ", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, "LayerNotQueryable", wms_exception_format); } ++numOWSLayers; } } } /* It's a valid Cascading WMS GetFeatureInfo request */ if (wms_layer) return msWMSLayerExecuteRequest(map, numOWSLayers, point.x, point.y, feature_count, info_format, WMS_GETFEATUREINFO); if( use_bbox == MS_FALSE ) { if(point.x == -1.0 || point.y == -1.0) { if (nVersion >= OWS_1_3_0) msSetError(MS_WMSERR, "Required I/J parameters missing for getFeatureInfo.", "msWMSFeatureInfo()"); else msSetError(MS_WMSERR, "Required X/Y parameters missing for getFeatureInfo.", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } /*wms1.3.0: check if the points are valid*/ if (nVersion >= OWS_1_3_0) { if (point.x > map->width || point.y > map->height) { msSetError(MS_WMSERR, "Invalid I/J values", "msWMSFeatureInfo()"); return msWMSException(map, nVersion, "InvalidPoint", wms_exception_format); } } /* Perform the actual query */ cellx = MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width); /* note: don't adjust extent, WMS assumes incoming extent is correct */ celly = MS_CELLSIZE(map->extent.miny, map->extent.maxy, map->height); point.x = MS_IMAGE2MAP_X(point.x, map->extent.minx, cellx); point.y = MS_IMAGE2MAP_Y(point.y, map->extent.maxy, celly); /* WMS 1.3.0 states that feature_count is *per layer*. * Its value is a positive integer, if omitted then the default is 1 */ if (feature_count < 1) feature_count = 1; map->query.type = MS_QUERY_BY_POINT; map->query.mode = (feature_count==1?MS_QUERY_SINGLE:MS_QUERY_MULTIPLE); map->query.layer = -1; map->query.point = point; map->query.buffer = 0; map->query.maxresults = feature_count; if(msQueryByPoint(map) != MS_SUCCESS) if((query_status=ms_error->code) != MS_NOTFOUND) return msWMSException(map, nVersion, NULL, wms_exception_format); } else { /* use_bbox == MS_TRUE */ map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = -1; map->query.rect = map->extent; map->query.buffer = 0; map->query.maxresults = feature_count; if(msQueryByRect(map) != MS_SUCCESS) if((query_status=ms_error->code) != MS_NOTFOUND) return msWMSException(map, nVersion, NULL, wms_exception_format); } /*validate the INFO_FORMAT*/ valid_format = MS_FALSE; format_list = msOWSLookupMetadata(&(map->web.metadata), "M", "getfeatureinfo_formatlist"); /*feature_info_mime_type depricated for MapServer 6.0*/ if (!format_list) format_list = msOWSLookupMetadata(&(map->web.metadata), "MO", "feature_info_mime_type"); if (format_list) { /*can not really validate if it is a valid output format since old way of using template with web->header/footer and layer templates need to still be supported. We can only validate if it was part of the format list*/ if (strcasestr(format_list, info_format)) valid_format = MS_TRUE; } /*check to see if the format passed is text/plain or GML and if is defined in the formatlist. If that is the case, It is a valid format*/ if (strcasecmp(info_format, "MIME") == 0 || strcasecmp(info_format, "text/plain") == 0 || strncasecmp(info_format, "GML", 3) == 0 || strcasecmp(info_format, "application/vnd.ogc.gml") == 0) valid_format = MS_TRUE; /*last case: if the info_format is not part of the request, it defaults to MIME*/ if (!valid_format && format_found == MS_FALSE) valid_format =MS_TRUE; if (!valid_format) { msSetError(MS_WMSERR, "Unsupported INFO_FORMAT value (%s).", "msWMSFeatureInfo()", info_format); if (nVersion >= OWS_1_3_0) return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); else return msWMSException(map, nVersion, NULL, wms_exception_format); } /* Generate response */ if (strcasecmp(info_format, "MIME") == 0 || strcasecmp(info_format, "text/plain") == 0) { /* MIME response... we're free to use any valid MIME type */ int numresults = 0; if (encoding) msIO_setHeader("Content-Type","text/plain; charset=%s", encoding); else msIO_setHeader("Content-Type","text/plain"); msIO_sendHeaders(); msIO_printf("GetFeatureInfo results:\n"); numresults = msDumpResult(map, 0, nVersion, wms_exception_format); if (numresults == 0) msIO_printf("\n Search returned no results.\n"); } else if (strncasecmp(info_format, "GML", 3) == 0 || /* accept GML.1 or GML */ strcasecmp(info_format, "application/vnd.ogc.gml") == 0) { if (nVersion <= OWS_1_0_7) /* 1.0.0 to 1.0.7 */ if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); else /* 1.1.0 and later */ if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.gml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.gml"); msIO_sendHeaders(); msGMLWriteQuery(map, NULL, "MGO"); /* default is stdout */ } else { mapservObj *msObj; char **translated_names, **translated_values; int translated_numentries; msObj = msAllocMapServObj(); /* Translate some vars from WMS to mapserv */ msTranslateWMS2Mapserv((const char**)names, (const char**)values, numentries, &translated_names, &translated_values, &translated_numentries); msObj->map = map; msFreeCharArray(msObj->request->ParamNames, msObj->request->NumParams); msFreeCharArray(msObj->request->ParamValues, msObj->request->NumParams); msObj->request->ParamNames = translated_names; msObj->request->ParamValues = translated_values; msObj->Mode = QUERY; msObj->request->NumParams = translated_numentries; msObj->mappnt.x = point.x; msObj->mappnt.y = point.y; if (query_status == MS_NOTFOUND && msObj->map->web.empty) { if(msReturnURL(msObj, msObj->map->web.empty, BROWSE) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); } else if (msReturnTemplateQuery(msObj, (char *)info_format, NULL) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); /* We don't want to free the map since it */ /* belongs to the caller, set it to NULL before freeing the mapservObj */ msObj->map = NULL; msFreeMapServObj(msObj); } return(MS_SUCCESS); } /* ** msWMSDescribeLayer() */ int msWMSDescribeLayer(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format) { int i = 0; char **layers = NULL; int numlayers = 0; int j, k; layerObj *lp = NULL; const char *pszOnlineResMapWFS = NULL, *pszOnlineResLyrWFS = NULL; const char *pszOnlineResMapWCS = NULL, *pszOnlineResLyrWCS = NULL; char *pszOnlineResEncoded=NULL, *pszLayerName=NULL; char *schemalocation = NULL; char *version = NULL; char *sld_version = NULL; const char *encoding; char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); for(i=0; map && i= OWS_1_3_0 && sld_version == NULL) { msSetError(MS_WMSERR, "Missing required parameter SLD_VERSION", "DescribeLayer()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } if (nVersion >= OWS_1_3_0 && strcasecmp(sld_version, "1.1.0") != 0) { msSetError(MS_WMSERR, "SLD_VERSION must be 1.1.0", "DescribeLayer()"); return msWMSException(map, nVersion, "InvalidParameterValue", wms_exception_format); } if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if (nVersion < OWS_1_3_0) { msIO_printf("\n", schemalocation); msIO_printf("\n", version); } else { msIO_printf("\n", schemalocation); msIO_printf("%s\n",sld_version); } free(schemalocation); /* check if map-level metadata wfs(wcs)_onlineresource is available */ pszOnlineResMapWFS = msOWSLookupMetadata(&(map->web.metadata), "FO", "onlineresource"); if (pszOnlineResMapWFS && strlen(pszOnlineResMapWFS) == 0) pszOnlineResMapWFS = NULL; pszOnlineResMapWCS = msOWSLookupMetadata(&(map->web.metadata), "CO", "onlineresource"); if (pszOnlineResMapWCS && strlen(pszOnlineResMapWCS) == 0) pszOnlineResMapWCS = NULL; nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); for(j=0; jnumlayers; k++) { lp = GET_LAYER(map, k); if ((map->name && strcasecmp(map->name, layers[j]) == 0) || (lp->name && strcasecmp(lp->name, layers[j]) == 0) || (lp->group && strcasecmp(lp->group, layers[j]) == 0) || ((numNestedGroups[k] >0) && msStringInArray(layers[j], nestedGroups[k], numNestedGroups[k]))) { /* Look for a WFS onlineresouce at the layer level and then at * the map level. */ pszOnlineResLyrWFS = msOWSLookupMetadata(&(lp->metadata), "FO", "onlineresource"); pszOnlineResLyrWCS = msOWSLookupMetadata(&(lp->metadata), "CO", "onlineresource"); if (pszOnlineResLyrWFS == NULL || strlen(pszOnlineResLyrWFS) == 0) pszOnlineResLyrWFS = pszOnlineResMapWFS; if (pszOnlineResLyrWCS == NULL || strlen(pszOnlineResLyrWCS) == 0) pszOnlineResLyrWCS = pszOnlineResMapWCS; if (pszOnlineResLyrWFS && (lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE || lp->type == MS_LAYER_POLYGON) ) { pszOnlineResEncoded = msEncodeHTMLEntities(pszOnlineResLyrWFS); pszLayerName = msEncodeHTMLEntities(lp->name); if (nVersion < OWS_1_3_0) { msIO_printf("\n", pszLayerName, pszOnlineResEncoded, pszOnlineResEncoded); msIO_printf("\n", pszLayerName); msIO_printf("\n"); } else { /*wms 1.3.0*/ msIO_printf(" \n"); msIO_printf(" wfs\n"); msIO_printf(" \n", pszOnlineResEncoded); msIO_printf(" \n"); msIO_printf(" %s\n",pszLayerName); msIO_printf(" \n"); msIO_printf(" \n"); } msFree(pszOnlineResEncoded); msFree(pszLayerName); } else if (pszOnlineResLyrWCS && lp->type == MS_LAYER_RASTER && lp->connectiontype != MS_WMS) { pszOnlineResEncoded = msEncodeHTMLEntities(pszOnlineResLyrWCS); pszLayerName = msEncodeHTMLEntities(lp->name); if (nVersion < OWS_1_3_0) { msIO_printf("\n", pszLayerName, pszOnlineResEncoded); msIO_printf("\n", pszLayerName); msIO_printf("\n"); msFree(pszOnlineResEncoded); msFree(pszLayerName); } else { msIO_printf(" \n"); msIO_printf(" wcs\n"); msIO_printf(" \n", pszOnlineResEncoded); msIO_printf(" \n"); msIO_printf(" %s\n",pszLayerName); msIO_printf(" \n"); msIO_printf(" \n"); } } else { char *pszLayerName; pszLayerName = msEncodeHTMLEntities(lp->name); if (nVersion < OWS_1_3_0) msIO_printf("\n", pszLayerName); else { /*wms 1.3.0*/ msIO_printf(" \n"); /*need to have a owstype for the DescribeLayer to be valid*/ if (lp->type == MS_LAYER_RASTER && lp->connectiontype != MS_WMS) msIO_printf(" wcs\n"); else msIO_printf(" wfs\n"); msIO_printf(" \n"); msIO_printf(" \n"); if (lp->type == MS_LAYER_RASTER && lp->connectiontype != MS_WMS) msIO_printf(" %s\n",pszLayerName); else msIO_printf(" %s\n",pszLayerName); msIO_printf(" \n"); msIO_printf(" \n"); } msFree(pszLayerName); } /* break; */ } } } if (nVersion < OWS_1_3_0) msIO_printf("\n"); else msIO_printf("\n"); if (layers) msFreeCharArray(layers, numlayers); /* free the stuff used for nested layers */ for (i = 0; i < map->numlayers; i++) { if (numNestedGroups[i] > 0) { msFreeCharArray(nestedGroups[i], numNestedGroups[i]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); return(MS_SUCCESS); } /* ** msWMSGetLegendGraphic() */ int msWMSLegendGraphic(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format, owsRequestObj *ows_request, map_hittest *hittest) { char *pszLayer = NULL; char *pszFormat = NULL; char *psRule = NULL; char *psScale = NULL; int iLayerIndex = -1; outputFormatObj *psFormat = NULL; imageObj *img=NULL; int j, i = 0; int nWidth = -1, nHeight =-1; char *pszStyle = NULL; char *sld_version = NULL; int wms_layer = MS_FALSE; const char *sldenabled = NULL; const char *format_list = NULL; layerObj *lp; int nLayers =0; char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; if(!hittest) { /* we can skip alot of testing if we already have a hittest, as it has already been done in the hittesting phase */ sldenabled = msOWSLookupMetadata(&(map->web.metadata), "MO", "sld_enabled"); if (sldenabled == NULL) sldenabled = "true"; for(i=0; map && i 0 && strcasecmp(sldenabled, "true") == 0) msSLDApplySLDURL(map, values[i], -1, NULL, NULL); else if (strcasecmp(names[i], "SLD_BODY") == 0 && values[i] && strlen(values[i]) > 0 && strcasecmp(sldenabled, "true") == 0) msSLDApplySLD(map, values[i], -1, NULL, NULL); else if (strcasecmp(names[i], "RULE") == 0) psRule = values[i]; else if (strcasecmp(names[i], "STYLE") == 0) pszStyle = values[i]; #endif /* -------------------------------------------------------------------- */ /* SLD support: */ /* - because the request parameter "sld_version" is required in */ /* in WMS 1.3.0, it will be set regardless of OGR support. */ /* -------------------------------------------------------------------- */ else if(strcasecmp(names[i], "SLD_VERSION") == 0) sld_version = values[i]; } if (!pszLayer) { msSetError(MS_WMSERR, "Mandatory LAYER parameter missing in GetLegendGraphic request.", "msWMSGetLegendGraphic()"); return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } if (!pszFormat) { msSetError(MS_WMSERR, "Mandatory FORMAT parameter missing in GetLegendGraphic request.", "msWMSGetLegendGraphic()"); return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); } if (nVersion >= OWS_1_3_0 && sld_version == NULL) { msSetError(MS_WMSERR, "Missing required parameter SLD_VERSION", "GetLegendGraphic()"); return msWMSException(map, nVersion, "MissingParameterValue", wms_exception_format); } if (nVersion >= OWS_1_3_0 && strcasecmp(sld_version, "1.1.0") != 0) { msSetError(MS_WMSERR, "SLD_VERSION must be 1.1.0", "GetLegendGraphic()"); return msWMSException(map, nVersion, "InvalidParameterValue", wms_exception_format); } nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); /* check if layer name is valid. we check for layer's and group's name */ /* as well as wms_layer_group names */ for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if ( ((map->name && strcasecmp(map->name, pszLayer) == 0) || (lp->name && strcasecmp(lp->name, pszLayer) == 0) || (lp->group && strcasecmp(lp->group, pszLayer) == 0) || ((numNestedGroups[i] >0) && (msStringInArray(pszLayer, nestedGroups[i], numNestedGroups[i]))) ) && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) ) { nLayers++; lp->status = MS_ON; iLayerIndex = i; if (GET_LAYER(map, i)->connectiontype == MS_WMS) { /* we do not cascade a wms layer if it contains at least * one class with the property name set */ wms_layer = MS_TRUE; for (j=0; jnumclasses; j++) { if (lp->class[j]->name != NULL && strlen(lp->class[j]->name)>0) { wms_layer = MS_FALSE; break; } } } } else lp->status = MS_OFF; } /* free the stuff used for nested layers */ for (i = 0; i < map->numlayers; i++) { if (numNestedGroups[i] > 0) { msFreeCharArray(nestedGroups[i], numNestedGroups[i]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); if (nLayers == 0) { msSetError(MS_WMSERR, "Invalid layer given in the LAYER parameter. A layer might be disabled for \ this request. Check wms/ows_enable_request settings.", "msWMSGetLegendGraphic()"); return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } /* if SCALE was provided in request, calculate an extent and use a default width and height */ if ( psScale != NULL ) { double scale, cellsize; scale = atof(psScale); map->width = 600; map->height = 600; cellsize = (scale/map->resolution)/msInchesPerUnit(map->units, 0.0); map->extent.maxx = cellsize*map->width/2.0; map->extent.maxy = cellsize*map->height/2.0; map->extent.minx = -map->extent.maxx; map->extent.miny = -map->extent.maxy; } /* It's a valid Cascading WMS GetLegendGraphic request */ if (wms_layer) return msWMSLayerExecuteRequest(map, 1, 0, 0, 0, NULL, WMS_GETLEGENDGRAPHIC); /*if STYLE is set, check if it is a valid style (valid = at least one of the classes have a the group value equals to the style */ /*style is only validated when there is only one layer #3411*/ if (nLayers == 1 && pszStyle && strlen(pszStyle) > 0 && strcasecmp(pszStyle, "default") != 0) { for (i=0; inumclasses; i++) { if (GET_LAYER(map, iLayerIndex)->class[i]->group && strcasecmp(GET_LAYER(map, iLayerIndex)->class[i]->group, pszStyle) == 0) break; } if (i == GET_LAYER(map, iLayerIndex)->numclasses) { msSetError(MS_WMSERR, "style used in the STYLE parameter is not defined on the layer.", "msWMSGetLegendGraphic()"); return msWMSException(map, nVersion, "StyleNotDefined", wms_exception_format); } else { msFree(GET_LAYER(map, iLayerIndex)->classgroup); GET_LAYER(map, iLayerIndex)->classgroup = msStrdup(pszStyle); } } } else { /* extract the parameters we need */ for(i=0; map && iweb.metadata), "M","getlegendgraphic_formatlist"); if (format_list) { psFormat = msOwsIsOutputFormatValid(map, pszFormat, &(map->web.metadata), "M", "getlegendgraphic_formatlist"); if (psFormat == NULL) { msSetError(MS_IMGERR, "Unsupported output format (%s).", "msWMSGetLegendGraphic()", pszFormat); return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); } } else { psFormat = msSelectOutputFormat( map, pszFormat); if( psFormat == NULL || ! MS_RENDERER_PLUGIN(psFormat) ) /* msDrawLegend and msCreateLegendIcon both switch the alpha channel to gd ** after creation, so they can be called here without going through ** the msAlphaGD2AGG functions */ { msSetError(MS_IMGERR, "Unsupported output format (%s).", "msWMSGetLegendGraphic()", pszFormat); return msWMSException(map, nVersion, "InvalidFormat", wms_exception_format); } } msApplyOutputFormat(&(map->outputformat), psFormat, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); if ( psRule == NULL || nLayers > 1) { if ( psScale != NULL ) { /* Scale-dependent legend. map->scaledenom will be calculated in msDrawLegend */ img = msDrawLegend(map, MS_FALSE, NULL); } else { /* Scale-independent legend */ img = msDrawLegend(map, MS_TRUE, hittest); } } else { /* RULE was specified. Get the class corresponding to the RULE */ /* (RULE = class->name) */ /* TBT FIXME? also check the map->scaledenom if multiple scale-dependant classes with same name */ for (i=0; inumclasses; i++) { if (GET_LAYER(map, iLayerIndex)->classgroup && (GET_LAYER(map, iLayerIndex)->class[i]->group == NULL || strcasecmp(GET_LAYER(map, iLayerIndex)->class[i]->group, GET_LAYER(map, iLayerIndex)->classgroup) != 0)) continue; if (GET_LAYER(map, iLayerIndex)->class[i]->name && strlen(GET_LAYER(map, iLayerIndex)->class[i]->name) > 0 && strcasecmp(GET_LAYER(map, iLayerIndex)->class[i]->name,psRule) == 0) break; } if (i < GET_LAYER(map, iLayerIndex)->numclasses) { /* set the map legend parameters */ if (nWidth < 0) { if (map->legend.keysizex > 0) nWidth = map->legend.keysizex; else nWidth = 20; /* default values : this in not defined in the specs */ } if (nHeight < 0) { if (map->legend.keysizey > 0) nHeight = map->legend.keysizey; else nHeight = 20; } if ( psScale != NULL ) { /* Scale-dependent legend. calculate map->scaledenom */ map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); img = msCreateLegendIcon(map, GET_LAYER(map, iLayerIndex), GET_LAYER(map, iLayerIndex)->class[i], nWidth, nHeight, MS_FALSE); } else { /* Scale-independent legend */ img = msCreateLegendIcon(map, GET_LAYER(map, iLayerIndex), GET_LAYER(map, iLayerIndex)->class[i], nWidth, nHeight, MS_TRUE); } } if (img == NULL) { msSetError(MS_IMGERR, "Unavailable RULE (%s).", "msWMSGetLegendGraphic()", psRule); return msWMSException(map, nVersion, "InvalidRule", wms_exception_format); } } if (img == NULL) return msWMSException(map, nVersion, NULL, wms_exception_format); msIO_setHeader("Content-Type", "%s", MS_IMAGE_MIME_TYPE(map->outputformat)); msIO_sendHeaders(); if (msSaveImage(map, img, NULL) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); msFreeImage(img); return(MS_SUCCESS); } /* ** msWMSGetContentDependantLegend() */ int msWMSGetContentDependantLegend(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format, owsRequestObj *ows_request) { int i,status; map_hittest hittest; /* turn off layer if WMS GetMap is not enabled */ for (i=0; inumlayers; i++) if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) GET_LAYER(map, i)->status = MS_OFF; initMapHitTests(map,&hittest); status = msHitTestMap(map,&hittest); if(status == MS_SUCCESS) { status = msWMSLegendGraphic(map,nVersion,names,values,numentries,wms_exception_format,ows_request,&hittest); } freeMapHitTests(map,&hittest); if(status != MS_SUCCESS) { return msWMSException(map, nVersion, NULL, wms_exception_format); } else { return MS_SUCCESS; } } /* ** msWMSGetStyles() : return an SLD document for all layers that ** have a status set to on or default. */ int msWMSGetStyles(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format) { int i,j,k; int validlayer = 0; int numlayers = 0; char **layers = NULL; char *sld = NULL; const char *encoding; char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); nestedGroups = (char***)msSmallCalloc(map->numlayers, sizeof(char**)); numNestedGroups = (int*)msSmallCalloc(map->numlayers, sizeof(int)); isUsedInNestedGroup = (int*)msSmallCalloc(map->numlayers, sizeof(int)); msWMSPrepareNestedGroups(map, nVersion, nestedGroups, numNestedGroups, isUsedInNestedGroup); for(i=0; map && inumlayers; j++) GET_LAYER(map, j)->status = MS_OFF; for (k=0; knumlayers; j++) { if ((map->name && strcasecmp(map->name, layers[k]) == 0) || (GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, layers[k]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[k]) == 0) || ((numNestedGroups[j] >0) && msStringInArray(layers[k], nestedGroups[j], numNestedGroups[j])) ) { GET_LAYER(map, j)->status = MS_ON; validlayer =1; } } } msFreeCharArray(layers, numlayers); } } /* free the stuff used for nested layers */ for (i = 0; i < map->numlayers; i++) { if (numNestedGroups[i] > 0) { msFreeCharArray(nestedGroups[i], numNestedGroups[i]); } } free(nestedGroups); free(numNestedGroups); free(isUsedInNestedGroup); /* validate all layers given. If an invalid layer is sent, return an exception. */ if (validlayer == 0) { msSetError(MS_WMSERR, "Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for \ this request. Check wms/ows_enable_request settings.", "msWMSGetStyles()"); return msWMSException(map, nVersion, "LayerNotDefined", wms_exception_format); } if (nVersion <= OWS_1_1_1) { if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.sld+xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.sld+xml"); msIO_sendHeaders(); sld = msSLDGenerateSLD(map, -1, "1.0.0"); } else { /*for wms 1.3.0 generate a 1.1 sld*/ if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); sld = msSLDGenerateSLD(map, -1, "1.1.0"); } if (sld) { msIO_printf("%s\n", sld); free(sld); } return(MS_SUCCESS); } int msWMSGetSchemaExtension(mapObj *map) { char *schemalocation = NULL; const char *encoding; schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "MO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n"); msIO_printf(" \n", schemalocation); msIO_printf(" \n"); msIO_printf(""); free(schemalocation); return(MS_SUCCESS); } #endif /* USE_WMS_SVR */ /* ** msWMSDispatch() is the entry point for WMS requests. ** - If this is a valid request then it is processed and MS_SUCCESS is returned ** on success, or MS_FAILURE on failure. ** - If this does not appear to be a valid WMS request then MS_DONE ** is returned and MapServer is expected to process this as a regular ** MapServer request. */ int msWMSDispatch(mapObj *map, cgiRequestObj *req, owsRequestObj *ows_request, int force_wms_mode) { #ifdef USE_WMS_SVR int i, status, nVersion=OWS_VERSION_NOTSET, isContentDependantLegend = 0; const char *version=NULL, *request=NULL, *service=NULL, *format=NULL, *updatesequence=NULL, *language=NULL; const char * encoding; char *wms_exception_format = NULL; char *validated_language = NULL; encoding = msOWSLookupMetadata(&(map->web.metadata), "MO", "encoding"); /* ** Process Params common to all requests */ /* VERSION (WMTVER in 1.0.0) and REQUEST must be present in a valid request */ for(i=0; iNumParams; i++) { if(strcasecmp(req->ParamNames[i], "VERSION") == 0) version = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "WMTVER") == 0 && version == NULL) version = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "UPDATESEQUENCE") == 0) updatesequence = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "REQUEST") == 0) request = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "EXCEPTIONS") == 0) wms_exception_format = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "SERVICE") == 0) service = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "FORMAT") == 0) format = req->ParamValues[i]; else if (strcasecmp(req->ParamNames[i], "LANGUAGE") == 0 && msOWSLookupMetadata(&(map->web.metadata), "MO", "inspire_capabilities")) language = req->ParamValues[i]; } /* If SERVICE is specified then it MUST be "WMS" */ if (service != NULL && strcasecmp(service, "WMS") != 0) return MS_DONE; /* Not a WMS request */ nVersion = msOWSParseVersionString(version); if (nVersion == OWS_VERSION_BADFORMAT) { /* Invalid version format. msSetError() has been called by * msOWSParseVersionString() and we return the error as an exception */ return msWMSException(map, OWS_VERSION_NOTSET, NULL, wms_exception_format); } /* ** GetCapbilities request needs the service parametr defined as WMS: see section 7.1.3.2 wms 1.1.1 specs for decsription. */ if (request && service == NULL && (strcasecmp(request, "capabilities") == 0 || strcasecmp(request, "GetCapabilities") == 0) && (nVersion >= OWS_1_0_7 || nVersion == OWS_VERSION_NOTSET)) { if (force_wms_mode) { msSetError(MS_WMSERR, "Required SERVICE parameter missing.", "msWMSDispatch"); return msWMSException(map, nVersion, "ServiceNotDefined", wms_exception_format); } else return MS_DONE; } /* ** Dispatch request... we should probably do some validation on VERSION here ** vs the versions we actually support. */ if (request && (strcasecmp(request, "capabilities") == 0 || strcasecmp(request, "GetCapabilities") == 0) ) { const char *enable_request; int globally_enabled, disabled = MS_FALSE; if (nVersion == OWS_VERSION_NOTSET) { version = msOWSLookupMetadata(&(map->web.metadata), "M", "getcapabilities_version"); if (version) nVersion = msOWSParseVersionString(version); else nVersion = OWS_1_3_0;/* VERSION is optional with getCapabilities only */ } if ((status = msOWSMakeAllLayersUnique(map)) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); msOWSRequestLayersEnabled(map, "M", "GetCapabilities", ows_request); enable_request = msOWSLookupMetadata(&map->web.metadata, "OM", "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, "GetCapabilities", &disabled); if (ows_request->numlayers == 0 && !globally_enabled) { msSetError(MS_WMSERR, "WMS request not enabled. Check wms/ows_enable_request settings.", "msWMSGetCapabilities()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } msAcquireLock(TLOCK_WxS); status=msWMSGetCapabilities(map, nVersion, req, ows_request, updatesequence, wms_exception_format, language); msReleaseLock(TLOCK_WxS); return status; } else if (request && (strcasecmp(request, "context") == 0 || strcasecmp(request, "GetContext") == 0) ) { /* Return a context document with all layers in this mapfile * This is not a standard WMS request. * __TODO__ The real implementation should actually return only context * info for selected layers in the LAYERS parameter. */ const char *getcontext_enabled; getcontext_enabled = msOWSLookupMetadata(&(map->web.metadata), "MO", "getcontext_enabled"); if (nVersion != OWS_VERSION_NOTSET) { /* VERSION, if specified, is Map Context version, not WMS version */ /* Pass it via wms_context_version metadata */ char szVersion[OWS_VERSION_MAXLEN]; msInsertHashTable(&(map->web.metadata), "wms_context_version", msOWSGetVersionString(nVersion, szVersion)); } /* Now set version to 1.1.1 for error handling purposes */ nVersion = OWS_1_1_1; if (getcontext_enabled==NULL || atoi(getcontext_enabled) == 0) { msSetError(MS_WMSERR, "GetContext not enabled on this server.", "msWMSDispatch()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } if ((status = msOWSMakeAllLayersUnique(map)) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); if ( msWriteMapContext(map, stdout) != MS_SUCCESS ) return msWMSException(map, nVersion, NULL, wms_exception_format); /* Request completed */ return MS_SUCCESS; } else if (request && strcasecmp(request, "GetMap") == 0 && format && strcasecmp(format, "image/txt") == 0) { /* Until someone adds full support for ASCII graphics this should do. ;) */ if (encoding) msIO_setHeader("Content-Type","text/plain; charset=%s", encoding); else msIO_setHeader("Content-Type","text/plain"); msIO_sendHeaders(); msIO_printf(".\n ,,ggddY\"\"\"Ybbgg,,\n ,agd888b,_ " "\"Y8, ___'\"\"Ybga,\n ,gdP\"\"88888888baa,.\"\"8b \"" "888g,\n ,dP\" ]888888888P' \"Y '888Yb,\n ,dP\"" " ,88888888P\" db, \"8P\"\"Yb,\n ,8\" ,8888" "88888b, d8888a \"8,\n ,8' d88888888888,88P\"" "' a, '8,\n,8' 88888888888888PP\" \"\" " " '8,\nd' I88888888888P\" 'b\n8" " '8\"88P\"\"Y8P' 8\n8 " " Y 8[ _ \" 8\n8 \"Y8d8" "b \"Y a 8\n8 '\"\"8d, __" " 8\nY, '\"8bd888b, " " ,P\n'8, ,d8888888baaa ,8'\n '8" ", 888888888888' ,8'\n '8a " " \"8888888888I a8'\n 'Yba 'Y88" "88888P' adP'\n \"Yba '888888P' adY\"" "\n '\"Yba, d8888P\" ,adP\"' \n '\"" "Y8baa, ,d888P,ad8P\"' \n ''\"\"YYba8888P\"" "\"''\n"); return MS_SUCCESS; } /* If SERVICE, VERSION and REQUEST not included than this isn't a WMS req*/ if (service == NULL && nVersion == OWS_VERSION_NOTSET && request==NULL) return MS_DONE; /* Not a WMS request */ /* VERSION *and* REQUEST required by both getMap and getFeatureInfo */ if (nVersion == OWS_VERSION_NOTSET) { msSetError(MS_WMSERR, "Incomplete WMS request: VERSION parameter missing", "msWMSDispatch()"); return msWMSException(map, OWS_VERSION_NOTSET, NULL, wms_exception_format); } /*check if the version is one of the supported vcersions*/ if (nVersion != OWS_1_0_0 && nVersion != OWS_1_0_6 && nVersion != OWS_1_0_7 && nVersion != OWS_1_1_0 && nVersion != OWS_1_1_1 && nVersion != OWS_1_3_0) { msSetError(MS_WMSERR, "Invalid WMS version: VERSION %s is not supported. Supported versions are 1.0.0, 1.0.6, 1.0.7, 1.1.0, 1.1.1, 1.3.0", "msWMSDispatch()", version); return msWMSException(map, OWS_VERSION_NOTSET, NULL, wms_exception_format); } if (request==NULL) { msSetError(MS_WMSERR, "Incomplete WMS request: REQUEST parameter missing", "msWMSDispatch()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } /* hack !? The function can return MS_DONE ... be sure it's a wms request * before checking the enabled layers */ if ( (strcasecmp(request, "GetStyles") == 0) || (strcasecmp(request, "GetLegendGraphic") == 0) || (strcasecmp(request, "GetSchemaExtension") == 0) || (strcasecmp(request, "map") == 0 || strcasecmp(request, "GetMap") == 0) || (strcasecmp(request, "feature_info") == 0 || strcasecmp(request, "GetFeatureInfo") == 0) || (strcasecmp(request, "DescribeLayer") == 0) ) { char request_tmp[32]; if (strcasecmp(request, "map") == 0) strlcpy(request_tmp, "GetMap", sizeof(request_tmp)); else if (strcasecmp(request, "feature_info") == 0) strlcpy(request_tmp, "GetFeatureInfo", sizeof(request_tmp)); else strlcpy(request_tmp, request, sizeof(request_tmp)); msOWSRequestLayersEnabled(map, "M", request_tmp, ows_request); if (ows_request->numlayers == 0) { msSetError(MS_WMSERR, "WMS request not enabled. Check wms/ows_enable_request settings.", "msWMSDispatch()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } } if ((status = msOWSMakeAllLayersUnique(map)) != MS_SUCCESS) return msWMSException(map, nVersion, NULL, wms_exception_format); if (strcasecmp(request, "GetLegendGraphic") == 0) { /* * check for a BBOX in the request, in that case we have a content-dependant legend request, * and should be following the GetMap path a bit more */ for(i=0; iNumParams; i++) { if(strcasecmp(req->ParamNames[i], "BBOX") == 0) { if(req->ParamValues[i] && *req->ParamValues[i]) { break; } } } if(i != req->NumParams) { isContentDependantLegend = 1; /* getLegendGraphic uses LAYER= , we need to create a LAYERS= value that is identical * we'll suppose that the client is conformat and hasn't included a LAYERS= parameter * in its request */ for(i=0; iNumParams; i++) { if(strcasecmp(req->ParamNames[i], "LAYER") == 0) { req->ParamNames[req->NumParams] = msStrdup("LAYERS"); req->ParamValues[req->NumParams] = msStrdup(req->ParamValues[i]); req->NumParams++; } } } else { return msWMSLegendGraphic(map, nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format, ows_request, NULL); } } if (strcasecmp(request, "GetStyles") == 0) return msWMSGetStyles(map, nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format); else if (request && strcasecmp(request, "GetSchemaExtension") == 0) return msWMSGetSchemaExtension(map); /* getMap parameters are used by both getMap, getFeatureInfo, and content dependant legendgraphics */ if (strcasecmp(request, "map") == 0 || strcasecmp(request, "GetMap") == 0 || strcasecmp(request, "feature_info") == 0 || strcasecmp(request, "GetFeatureInfo") == 0 || strcasecmp(request, "DescribeLayer") == 0 || isContentDependantLegend) { status = msWMSLoadGetMapParams(map, nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format, request, ows_request); if (status != MS_SUCCESS) return status; } /* This function owns validated_language, so remember to free it later*/ validated_language = msOWSGetLanguageFromList(map, "MO", language); if (validated_language != NULL) { for(i=0; inumlayers; i++) { layerObj *layer = GET_LAYER(map, i); if(layer->data) layer->data = msCaseReplaceSubstring(layer->data, "%language%", validated_language); if(layer->connection) layer->connection = msCaseReplaceSubstring(layer->connection, "%language%", validated_language); } } msFree(validated_language); if (strcasecmp(request, "map") == 0 || strcasecmp(request, "GetMap") == 0) return msWMSGetMap(map, nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format, ows_request); else if (strcasecmp(request, "feature_info") == 0 || strcasecmp(request, "GetFeatureInfo") == 0) return msWMSFeatureInfo(map, nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format, ows_request); else if (strcasecmp(request, "DescribeLayer") == 0) { return msWMSDescribeLayer(map, nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format); } else if (isContentDependantLegend) { return msWMSGetContentDependantLegend(map,nVersion, req->ParamNames, req->ParamValues, req->NumParams, wms_exception_format, ows_request); } /* Hummmm... incomplete or unsupported WMS request */ if (service != NULL && strcasecmp(service, "WMS") == 0) { msSetError(MS_WMSERR, "Incomplete or unsupported WMS request", "msWMSDispatch()"); return msWMSException(map, nVersion, NULL, wms_exception_format); } else return MS_DONE; /* Not a WMS request */ #else msSetError(MS_WMSERR, "WMS server support is not available.", "msWMSDispatch()"); return(MS_FAILURE); #endif } mapserver-6.4.1/mapprojhack.c0000644002461700001440000001161012261257215015756 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of utility functions related to the PROJ4 library * Author: DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2001, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #include #include "mapserver.h" /************************************************************************/ /* ConvertProjUnitStringToMS */ /* */ /* Returns mapserver's unit code corresponding to the proj */ /* unit passed as argument. */ /* Please refer to ./src/pj_units.c file in the Proj.4 module. */ /************************************************************************/ #ifdef USE_PROJ static int ConvertProjUnitStringToMS(const char *pszProjUnit) { if (strcmp(pszProjUnit, "m") ==0) { return MS_METERS; } else if (strcmp(pszProjUnit, "km") ==0) { return MS_KILOMETERS; } else if (strcmp(pszProjUnit, "mi") ==0 || strcmp(pszProjUnit, "us-mi") ==0) { return MS_MILES; } else if (strcmp(pszProjUnit, "in") ==0 || strcmp(pszProjUnit, "us-in") ==0 ) { return MS_INCHES; } else if (strcmp(pszProjUnit, "ft") ==0 || strcmp(pszProjUnit, "us-ft") ==0) { return MS_FEET; } else if (strcmp(pszProjUnit, "kmi") == 0) { return MS_NAUTICALMILES; } return -1; } #endif /* def USE_PROJ */ /************************************************************************/ /* int GetMapserverUnitUsingProj(projectionObj *psProj) */ /* */ /* Return a mapserver unit corresponding to the projection */ /* passed. Retunr -1 on failure */ /************************************************************************/ int GetMapserverUnitUsingProj(projectionObj *psProj) { #ifdef USE_PROJ char *proj_str; if( pj_is_latlong( psProj->proj ) ) return MS_DD; proj_str = pj_get_def( psProj->proj, 0 ); /* -------------------------------------------------------------------- */ /* Handle case of named units. */ /* -------------------------------------------------------------------- */ if( strstr(proj_str,"units=") != NULL ) { char units[32]; char *blank; strlcpy( units, (strstr(proj_str,"units=")+6), sizeof(units) ); pj_dalloc( proj_str ); blank = strchr(units, ' '); if( blank != NULL ) *blank = '\0'; return ConvertProjUnitStringToMS( units ); } /* -------------------------------------------------------------------- */ /* Handle case of to_meter value. */ /* -------------------------------------------------------------------- */ if( strstr(proj_str,"to_meter=") != NULL ) { char to_meter_str[32]; char *blank; double to_meter; strlcpy(to_meter_str,(strstr(proj_str,"to_meter=")+9), sizeof(to_meter_str)); pj_dalloc( proj_str ); blank = strchr(to_meter_str, ' '); if( blank != NULL ) *blank = '\0'; to_meter = atof(to_meter_str); if( fabs(to_meter-1.0) < 0.0000001 ) return MS_METERS; else if( fabs(to_meter-1000.0) < 0.00001 ) return MS_KILOMETERS; else if( fabs(to_meter-0.3048) < 0.0001 ) return MS_FEET; else if( fabs(to_meter-0.0254) < 0.0001 ) return MS_INCHES; else if( fabs(to_meter-1609.344) < 0.001 ) return MS_MILES; else if( fabs(to_meter-1852.0) < 0.1 ) return MS_NAUTICALMILES; else return -1; } pj_dalloc( proj_str ); #endif return -1; } mapserver-6.4.1/print-test-results.sh0000755002461700001440000000310312261257215017460 0ustar tbonfortusers#!/bin/bash ret=0 tests=( query misc gdal wxs renderers ) command_exists () { type "$1" &> /dev/null ; } DIFF=diff COMPARE= if command_exists colordiff ; then DIFF="colordiff" fi if command_exists compare ; then COMPARE="compare" fi #leftover .aux.xml files are valid for some gdal tests rm -f msautotest/*/result/*.aux.xml for testcase in "${tests[@]}"; do cd msautotest/$testcase if [ ! -d result ]; then #"result" directory does not exist, all tests passed cd ../.. continue fi cd result failedtests=`find . -type f -printf "%f\n" ` if [ -z "$failedtests" ]; then cd ../../.. continue fi #we have some failing tests ret=1 for failedtest in $failedtests; do echo "" echo "######################################" echo "# $testcase => $failedtest" echo "######################################" #for txt, gml and xml files, print a diff if echo "$failedtest" | egrep -q "(txt|xml|gml)$"; then $DIFF -u "../expected/$failedtest" "$failedtest" fi if echo "$failedtest" | egrep -q "(png|gif|tif)$"; then if echo "$failedtest" | egrep -v -q "\\.diff\\.png$"; then if [ -n "$COMPARE" ]; then $COMPARE ../expected/$failedtest $failedtest -compose Src $failedtest.diff.png fi fi fi done cd ../../.. done if test "$ret" -eq "0"; then echo "" echo "######################################" echo "# All tests passed #" echo "######################################" echo "" fi exit $ret mapserver-6.4.1/mapgdal.c0000644002461700001440000006035212261257215015073 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of support for output using GDAL. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * 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. ****************************************************************************/ #include "mapserver.h" #include "mapthread.h" #include #if defined(USE_GDAL) || defined(USE_OGR) #include "cpl_conv.h" #include "cpl_string.h" #include "ogr_srs_api.h" #endif #ifdef USE_GDAL #include "gdal.h" static int bGDALInitialized = 0; /************************************************************************/ /* msGDALInitialize() */ /************************************************************************/ void msGDALInitialize( void ) { if( !bGDALInitialized ) { msAcquireLock( TLOCK_GDAL ); GDALAllRegister(); CPLPushErrorHandler( CPLQuietErrorHandler ); msReleaseLock( TLOCK_GDAL ); bGDALInitialized = 1; } } /************************************************************************/ /* msGDALCleanup() */ /************************************************************************/ void msGDALCleanup( void ) { if( bGDALInitialized ) { int iRepeat = 5; msAcquireLock( TLOCK_GDAL ); #if GDAL_RELEASE_DATE > 20101207 { /* ** Cleanup any unreferenced but open datasets as will tend ** to exist due to deferred close requests. We are careful ** to only close one file at a time before refecting the ** list as closing some datasets may cause others to be ** closed (subdatasets in a VRT for instance). */ GDALDatasetH *pahDSList = NULL; int nDSCount = 0; int bDidSomething; do { int i; GDALGetOpenDatasets( &pahDSList, &nDSCount ); bDidSomething = FALSE; for( i = 0; i < nDSCount && !bDidSomething; i++ ) { if( GDALReferenceDataset( pahDSList[i] ) == 1 ) { GDALClose( pahDSList[i] ); bDidSomething = TRUE; } else GDALDereferenceDataset( pahDSList[i] ); } } while( bDidSomething ); } #endif while( iRepeat-- ) CPLPopErrorHandler(); #if GDAL_RELEASE_DATE > 20021001 GDALDestroyDriverManager(); #endif msReleaseLock( TLOCK_GDAL ); bGDALInitialized = 0; } } /************************************************************************/ /* CleanVSIDir() */ /* */ /* For the temporary /vsimem/msout directory we need to be sure */ /* things are clean before we start, and after we are done. */ /************************************************************************/ void CleanVSIDir( const char *pszDir ) { char **papszFiles = CPLReadDir( pszDir ); int i, nFileCount = CSLCount( papszFiles ); for( i = 0; i < nFileCount; i++ ) { if( strcasecmp(papszFiles[i],".") == 0 || strcasecmp(papszFiles[i],"..") == 0 ) continue; VSIUnlink( papszFiles[i] ); } CSLDestroy( papszFiles ); } /************************************************************************/ /* msSaveImageGDAL() */ /************************************************************************/ int msSaveImageGDAL( mapObj *map, imageObj *image, char *filename ) { int bFileIsTemporary = MS_FALSE; GDALDatasetH hMemDS, hOutputDS; GDALDriverH hMemDriver, hOutputDriver; int nBands = 1; int iLine; GByte *pabyAlphaLine = NULL; char **papszOptions = NULL; outputFormatObj *format = image->format; rasterBufferObj rb; GDALDataType eDataType = GDT_Byte; int bUseXmp = MS_FALSE; msGDALInitialize(); memset(&rb,0,sizeof(rasterBufferObj)); #ifdef USE_EXEMPI if( map != NULL ) { bUseXmp = msXmpPresent(map); } #endif /* -------------------------------------------------------------------- */ /* Identify the proposed output driver. */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_GDAL ); hOutputDriver = GDALGetDriverByName( format->driver+5 ); if( hOutputDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find %s driver.", "msSaveImageGDAL()", format->driver+5 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* We will need to write the output to a temporary file and */ /* then stream to stdout if no filename is passed. If the */ /* driver supports virtualio then we hold the temporary file in */ /* memory, otherwise we try to put it in a reasonable temporary */ /* file location. */ /* -------------------------------------------------------------------- */ if( filename == NULL ) { const char *pszExtension = format->extension; if( pszExtension == NULL ) pszExtension = "img.tmp"; if( bUseXmp == MS_FALSE && GDALGetMetadataItem( hOutputDriver, GDAL_DCAP_VIRTUALIO, NULL ) != NULL ) { CleanVSIDir( "/vsimem/msout" ); filename = msTmpFile(map, NULL, "/vsimem/msout/", pszExtension ); } if( filename == NULL && map != NULL) filename = msTmpFile(map, map->mappath,NULL,pszExtension); else if( filename == NULL ) { filename = msTmpFile(map, NULL, NULL, pszExtension ); } bFileIsTemporary = MS_TRUE; } /* -------------------------------------------------------------------- */ /* Establish the characteristics of our memory, and final */ /* dataset. */ /* -------------------------------------------------------------------- */ if( format->imagemode == MS_IMAGEMODE_RGB ) { nBands = 3; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); format->vtable->getRasterBufferHandle(image,&rb); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { pabyAlphaLine = (GByte *) calloc(image->width,1); if (pabyAlphaLine == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", image->width); return MS_FAILURE; } nBands = 4; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); format->vtable->getRasterBufferHandle(image,&rb); } else if( format->imagemode == MS_IMAGEMODE_INT16 ) { nBands = format->bands; eDataType = GDT_Int16; } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { nBands = format->bands; eDataType = GDT_Float32; } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { nBands = format->bands; eDataType = GDT_Byte; } else { #ifdef USE_GD assert( format->imagemode == MS_IMAGEMODE_PC256 && format->renderer == MS_RENDER_WITH_GD ); #else { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "GD not compiled in. This is a bug.", "msSaveImageGDAL()"); return MS_FAILURE; } #endif } /* -------------------------------------------------------------------- */ /* Create a memory dataset which we can use as a source for a */ /* CreateCopy(). */ /* -------------------------------------------------------------------- */ hMemDriver = GDALGetDriverByName( "MEM" ); if( hMemDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find MEM driver.", "msSaveImageGDAL()" ); return MS_FAILURE; } hMemDS = GDALCreate( hMemDriver, "msSaveImageGDAL_temp", image->width, image->height, nBands, eDataType, NULL ); if( hMemDS == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create MEM dataset.", "msSaveImageGDAL()" ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy the gd image into the memory dataset. */ /* -------------------------------------------------------------------- */ for( iLine = 0; iLine < image->height; iLine++ ) { int iBand; for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); if( format->imagemode == MS_IMAGEMODE_INT16 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_16bit + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Int16, 2, 0 ); } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_float + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Float32, 4, 0 ); } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_byte + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Byte, 1, 0 ); } #ifdef USE_GD else if(format->renderer == MS_RENDER_WITH_GD) { gdImagePtr img = (gdImagePtr)image->img.plugin; GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, img->pixels[iLine], image->width, 1, GDT_Byte, 0, 0 ); } #endif else { GByte *pabyData; unsigned char *pixptr = NULL; assert( rb.type == MS_BUFFER_BYTE_RGBA ); switch(iBand) { case 0: pixptr = rb.data.rgba.r; break; case 1: pixptr = rb.data.rgba.g; break; case 2: pixptr = rb.data.rgba.b; break; case 3: pixptr = rb.data.rgba.a; break; } assert(pixptr); if( pixptr == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Missing RGB or A buffer.\n", "msSaveImageGDAL()" ); return MS_FAILURE; } pabyData = (GByte *)(pixptr + iLine*rb.data.rgba.row_step); if( rb.data.rgba.a == NULL || iBand == 3 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyData, image->width, 1, GDT_Byte, rb.data.rgba.pixel_step, 0 ); } else { /* We need to un-pre-multiple RGB by alpha. */ GByte *pabyUPM = (GByte*) malloc(image->width); GByte *pabyAlpha= (GByte *)(rb.data.rgba.a + iLine*rb.data.rgba.row_step); int i; for( i = 0; i < image->width; i++ ) { int alpha = pabyAlpha[i*rb.data.rgba.pixel_step]; if( alpha == 0 ) pabyUPM[i] = 0; else { int result = (pabyData[i*rb.data.rgba.pixel_step] * 255) / alpha; if( result > 255 ) result = 255; pabyUPM[i] = result; } } GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyUPM, image->width, 1, GDT_Byte, 1, 0 ); free( pabyUPM ); } } } } if( pabyAlphaLine != NULL ) free( pabyAlphaLine ); /* -------------------------------------------------------------------- */ /* Attach the palette if appropriate. */ /* -------------------------------------------------------------------- */ #ifdef USE_GD if( format->renderer == MS_RENDER_WITH_GD ) { GDALColorEntry sEntry; int iColor; GDALColorTableH hCT; gdImagePtr img = (gdImagePtr)image->img.plugin; hCT = GDALCreateColorTable( GPI_RGB ); for( iColor = 0; iColor < img->colorsTotal; iColor++ ) { sEntry.c1 = img->red[iColor]; sEntry.c2 = img->green[iColor]; sEntry.c3 = img->blue[iColor]; if( iColor == gdImageGetTransparent( img ) ) sEntry.c4 = 0; else if( iColor == 0 && gdImageGetTransparent( img ) == -1 && format->transparent ) sEntry.c4 = 0; else sEntry.c4 = 255; GDALSetColorEntry( hCT, iColor, &sEntry ); } GDALSetRasterColorTable( GDALGetRasterBand( hMemDS, 1 ), hCT ); GDALDestroyColorTable( hCT ); } else #endif if( format->imagemode == MS_IMAGEMODE_RGB ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 4 ), GCI_AlphaBand ); } /* -------------------------------------------------------------------- */ /* Assign the projection and coordinate system to the memory */ /* dataset. */ /* -------------------------------------------------------------------- */ if( map != NULL ) { char *pszWKT; GDALSetGeoTransform( hMemDS, map->gt.geotransform ); pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { GDALSetProjection( hMemDS, pszWKT ); msFree( pszWKT ); } } /* -------------------------------------------------------------------- */ /* Possibly assign a nodata value. */ /* -------------------------------------------------------------------- */ if( msGetOutputFormatOption(format,"NULLVALUE",NULL) != NULL ) { int iBand; const char *nullvalue = msGetOutputFormatOption(format, "NULLVALUE",NULL); for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); GDALSetRasterNoDataValue( hBand, atof(nullvalue) ); } } /* -------------------------------------------------------------------- */ /* Try to save resolution in the output file. */ /* -------------------------------------------------------------------- */ if( image->resolution > 0 ) { char res[30]; sprintf( res, "%lf", image->resolution ); GDALSetMetadataItem( hMemDS, "TIFFTAG_XRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_YRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_RESOLUTIONUNIT", "2", NULL ); } /* -------------------------------------------------------------------- */ /* Create a disk image in the selected output format from the */ /* memory image. */ /* -------------------------------------------------------------------- */ papszOptions = (char**)calloc(sizeof(char *),(format->numformatoptions+1)); if (papszOptions == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", (unsigned int)(sizeof(char *)*(format->numformatoptions+1))); return MS_FAILURE; } memcpy( papszOptions, format->formatoptions, sizeof(char *) * format->numformatoptions ); hOutputDS = GDALCreateCopy( hOutputDriver, filename, hMemDS, FALSE, papszOptions, NULL, NULL ); free( papszOptions ); if( hOutputDS == NULL ) { GDALClose( hMemDS ); msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create output %s file.\n%s", "msSaveImageGDAL()", format->driver+5, CPLGetLastErrorMsg() ); return MS_FAILURE; } /* closing the memory DS also frees all associated resources. */ GDALClose( hMemDS ); GDALClose( hOutputDS ); msReleaseLock( TLOCK_GDAL ); /* -------------------------------------------------------------------- */ /* Are we writing license info into the image? */ /* If so, add it to the temp file on disk now. */ /* -------------------------------------------------------------------- */ #ifdef USE_EXEMPI if ( bUseXmp == MS_TRUE ) { if( msXmpWrite(map, filename) == MS_FAILURE ) { /* Something bad happened. */ msSetError( MS_MISCERR, "XMP write to %s failed.\n", "msSaveImageGDAL()", filename); return MS_FAILURE; } } #endif /* -------------------------------------------------------------------- */ /* Is this supposed to be a temporary file? If so, stream to */ /* stdout and delete the file. */ /* -------------------------------------------------------------------- */ if( bFileIsTemporary ) { FILE *fp; unsigned char block[4000]; int bytes_read; if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; /* We aren't sure how far back GDAL exports the VSI*L API, so we only use it if we suspect we need it. But we do need it if holding temporary file in memory. */ fp = VSIFOpenL( filename, "rb" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open %s for streaming to stdout.", "msSaveImageGDAL()", filename ); return MS_FAILURE; } while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 ) msIO_fwrite( block, 1, bytes_read, stdout ); VSIFCloseL( fp ); VSIUnlink( filename ); CleanVSIDir( "/vsimem/msout" ); free( filename ); } return MS_SUCCESS; } /************************************************************************/ /* msInitGDALOutputFormat() */ /************************************************************************/ int msInitDefaultGDALOutputFormat( outputFormatObj *format ) { GDALDriverH hDriver; msGDALInitialize(); /* -------------------------------------------------------------------- */ /* check that this driver exists. Note visiting drivers should */ /* be pretty threadsafe so don't bother acquiring the GDAL */ /* lock. */ /* -------------------------------------------------------------------- */ hDriver = GDALGetDriverByName( format->driver+5 ); if( hDriver == NULL ) { msSetError( MS_MISCERR, "No GDAL driver named `%s' available.", "msInitGDALOutputFormat()", format->driver+5 ); return MS_FAILURE; } if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL && GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL ) { msSetError( MS_MISCERR, "GDAL `%s' driver does not support output.", "msInitGDALOutputFormat()", format->driver+5 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Initialize the object. */ /* -------------------------------------------------------------------- */ format->imagemode = MS_IMAGEMODE_RGB; format->renderer = MS_RENDER_WITH_AGG; if( GDALGetMetadataItem( hDriver, GDAL_DMD_MIMETYPE, NULL ) != NULL ) format->mimetype = msStrdup(GDALGetMetadataItem(hDriver,GDAL_DMD_MIMETYPE,NULL)); if( GDALGetMetadataItem( hDriver, GDAL_DMD_EXTENSION, NULL ) != NULL ) format->extension = msStrdup(GDALGetMetadataItem(hDriver,GDAL_DMD_EXTENSION,NULL)); return MS_SUCCESS; } #else void msGDALInitialize( void ) {} void msGDALCleanup(void) {} #endif /* def USE_GDAL */ /************************************************************************/ /* msProjectionObj2OGCWKT() */ /* */ /* We stick to the C API for OGRSpatialReference object access */ /* to allow MapServer+GDAL to be built without C++ */ /* complications. */ /* */ /* Note that this function will return NULL on failure, and the */ /* returned string should be freed with msFree(). */ /************************************************************************/ char *msProjectionObj2OGCWKT( projectionObj *projection ) { #if !defined(USE_GDAL) && !defined(USE_OGR) msSetError(MS_OGRERR, "Not implemented since neither OGR nor GDAL is enabled.", "msProjectionObj2OGCWKT()"); return NULL; #else /* defined USE_GDAL or USE_OGR */ OGRSpatialReferenceH hSRS; char *pszWKT=NULL, *pszProj4, *pszInitEpsg=NULL; int nLength = 0, i; OGRErr eErr; if( projection->proj == NULL ) return NULL; hSRS = OSRNewSpatialReference( NULL ); /* -------------------------------------------------------------------- */ /* Look for an EPSG-like projection argument */ /* -------------------------------------------------------------------- */ if( projection->numargs == 1 && (pszInitEpsg = strcasestr(projection->args[0],"init=epsg:"))) { int nEpsgCode = atoi(pszInitEpsg + strlen("init=epsg:")); eErr = OSRImportFromEPSG(hSRS, nEpsgCode); } else { /* -------------------------------------------------------------------- */ /* Form arguments into a full Proj.4 definition string. */ /* -------------------------------------------------------------------- */ for( i = 0; i < projection->numargs; i++ ) nLength += strlen(projection->args[i]) + 2; pszProj4 = (char *) CPLMalloc(nLength+2); pszProj4[0] = '\0'; for( i = 0; i < projection->numargs; i++ ) { strcat( pszProj4, "+" ); strcat( pszProj4, projection->args[i] ); strcat( pszProj4, " " ); } /* -------------------------------------------------------------------- */ /* Ingest the string into OGRSpatialReference. */ /* -------------------------------------------------------------------- */ eErr = OSRImportFromProj4( hSRS, pszProj4 ); CPLFree( pszProj4 ); } /* -------------------------------------------------------------------- */ /* Export as a WKT string. */ /* -------------------------------------------------------------------- */ if( eErr == OGRERR_NONE ) eErr = OSRExportToWkt( hSRS, &pszWKT ); OSRDestroySpatialReference( hSRS ); if( pszWKT ) { char *pszWKT2 = msStrdup(pszWKT); CPLFree( pszWKT ); return pszWKT2; } else return NULL; #endif /* defined USE_GDAL or USE_OGR */ } mapserver-6.4.1/mapdraw.c0000644002461700001440000040423312261257215015121 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: High level msDrawMap() implementation and related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include #include #include "mapserver.h" #include "maptime.h" #include "mapcopy.h" #ifdef USE_GD /* * Functions to reset any pen (color index) values previously set. Used primarily to reset things when * using MapScript to create multiple images. How the pen values are set is irrelevant (definitely output * format type specific) which is why this function is here instead of the GD, PDF or SWF source files. */ void msClearLayerPenValues(layerObj *layer) { int i, j, k; for(i=0; inumclasses; i++) { for(j=0; jclass[i]->numlabels; j++) { layer->class[i]->labels[j]->color.pen = MS_PEN_UNSET; /* set in MSXXDrawText function */ layer->class[i]->labels[j]->outlinecolor.pen = MS_PEN_UNSET; layer->class[i]->labels[j]->shadowcolor.pen = MS_PEN_UNSET; for(k=0; kclass[i]->labels[j]->numstyles; k++) { layer->class[i]->labels[j]->styles[k]->backgroundcolor.pen = MS_PEN_UNSET; /* set in various symbol drawing functions */ layer->class[i]->labels[j]->styles[k]->color.pen = MS_PEN_UNSET; layer->class[i]->labels[j]->styles[k]->outlinecolor.pen = MS_PEN_UNSET; } } for(j=0; jclass[i]->numstyles; j++) { layer->class[i]->styles[j]->backgroundcolor.pen = MS_PEN_UNSET; /* set in various symbol drawing functions */ layer->class[i]->styles[j]->color.pen = MS_PEN_UNSET; layer->class[i]->styles[j]->outlinecolor.pen = MS_PEN_UNSET; } } } void msClearScalebarPenValues(scalebarObj *scalebar) { if (scalebar) { scalebar->color.pen = MS_PEN_UNSET; scalebar->backgroundcolor.pen = MS_PEN_UNSET; scalebar->outlinecolor.pen = MS_PEN_UNSET; scalebar->imagecolor.pen = MS_PEN_UNSET; scalebar->label.color.pen = MS_PEN_UNSET; scalebar->label.outlinecolor.pen = MS_PEN_UNSET; scalebar->label.shadowcolor.pen = MS_PEN_UNSET; /* TODO: deal with label styles here */ } } void msClearLegendPenValues(legendObj *legend) { if (legend) { legend->outlinecolor.pen = MS_PEN_UNSET; legend->imagecolor.pen = MS_PEN_UNSET; legend->label.color.pen = MS_PEN_UNSET; legend->label.outlinecolor.pen = MS_PEN_UNSET; legend->label.shadowcolor.pen = MS_PEN_UNSET; /* TODO: deal with label styles here */ } } void msClearReferenceMapPenValues(referenceMapObj *referencemap) { if (referencemap) { referencemap->outlinecolor.pen = MS_PEN_UNSET; referencemap->color.pen = MS_PEN_UNSET; } } void msClearQueryMapPenValues(queryMapObj *querymap) { if (querymap) querymap->color.pen = MS_PEN_UNSET; } void msClearPenValues(mapObj *map) { int i; for(i=0; inumlayers; i++) msClearLayerPenValues((GET_LAYER(map, i))); msClearLegendPenValues(&(map->legend)); msClearScalebarPenValues(&(map->scalebar)); msClearReferenceMapPenValues(&(map->reference)); msClearQueryMapPenValues(&(map->querymap)); } #endif /* msPrepareImage() * * Returns a new imageObj ready for rendering the current map. * * If allow_nonsquare is set to MS_TRUE then the caller should call * msMapRestoreRealExtent() once they are done with the image. * This should be set to MS_TRUE only when called from msDrawMap(), see bug 945. */ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare) { int i, status; imageObj *image=NULL; double geo_cellsize; if(map->width == -1 || map->height == -1) { msSetError(MS_MISCERR, "Image dimensions not specified.", "msPrepareImage()"); return(NULL); } msInitLabelCache(&(map->labelcache)); /* this clears any previously allocated cache */ /* clear any previously created mask layer images */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->maskimage) { msFreeImage(GET_LAYER(map, i)->maskimage); GET_LAYER(map, i)->maskimage = NULL; } } status = msValidateContexts(map); /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */ if(status != MS_SUCCESS) return NULL; if(!map->outputformat) { msSetError(MS_GDERR, "Map outputformat not set!", "msPrepareImage()"); return(NULL); } else if (MS_RENDERER_PLUGIN(map->outputformat)) { rendererVTableObj *renderer = map->outputformat->vtable; colorObj *bg = &map->imagecolor; map->imagecolor.alpha=255; if(map->transparent == MS_TRUE) { /* don't set the image color */ bg = NULL; } image = renderer->createImage(map->width, map->height, map->outputformat,bg); if (image == NULL) return(NULL); image->format = map->outputformat; image->format->refcount++; image->width = map->width; image->height = map->height; image->resolution = map->resolution; image->resolutionfactor = map->resolution/map->defresolution; if (map->web.imagepath) image->imagepath = msStrdup(map->web.imagepath); if (map->web.imageurl) image->imageurl = msStrdup(map->web.imageurl); } else if( MS_RENDERER_IMAGEMAP(map->outputformat) ) { image = msImageCreateIM(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution); } else if( MS_RENDERER_RAWDATA(map->outputformat) ) { image = msImageCreate(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->imagecolor); } else { image = NULL; } if(!image) { msSetError(MS_GDERR, "Unable to initialize image.", "msPrepareImage()"); return(NULL); } /* * If we want to support nonsquare pixels, note that now, otherwise * adjust the extent size to have square pixels. * * If allow_nonsquare is set to MS_TRUE then the caller should call * msMapRestoreRealExtent() once they are done with the image. * This should be set to MS_TRUE only when called from msDrawMap(), see bug 945. */ if( allow_nonsquare && msTestConfigOption( map, "MS_NONSQUARE", MS_FALSE ) ) { double cellsize_x = (map->extent.maxx - map->extent.minx)/map->width; double cellsize_y = (map->extent.maxy - map->extent.miny)/map->height; if( cellsize_y != 0.0 && (fabs(cellsize_x/cellsize_y) > 1.00001 || fabs(cellsize_x/cellsize_y) < 0.99999) ) { map->gt.need_geotransform = MS_TRUE; if (map->debug) msDebug( "msDrawMap(): kicking into non-square pixel preserving mode.\n" ); } map->cellsize = (cellsize_x*0.5 + cellsize_y*0.5); } else map->cellsize = msAdjustExtent(&(map->extent),map->width,map->height); status = msCalculateScale(map->extent,map->units,map->width,map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { msFreeImage(image); return(NULL); } /* update geotransform based on adjusted extent. */ msMapComputeGeotransform( map ); /* Do we need to fake out stuff for rotated support? */ if( map->gt.need_geotransform ) msMapSetFakedExtent( map ); /* We will need a cellsize that represents a real georeferenced */ /* coordinate cellsize here, so compute it from saved extents. */ geo_cellsize = map->cellsize; if( map->gt.need_geotransform == MS_TRUE ) { double cellsize_x = (map->saved_extent.maxx - map->saved_extent.minx) / map->width; double cellsize_y = (map->saved_extent.maxy - map->saved_extent.miny) / map->height; geo_cellsize = sqrt(cellsize_x*cellsize_x + cellsize_y*cellsize_y) / sqrt(2.0); } /* compute layer scale factors now */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->sizeunits != MS_PIXELS) GET_LAYER(map, i)->scalefactor = (msInchesPerUnit(GET_LAYER(map, i)->sizeunits,0)/msInchesPerUnit(map->units,0)) / geo_cellsize; else if(GET_LAYER(map, i)->symbolscaledenom > 0 && map->scaledenom > 0) GET_LAYER(map, i)->scalefactor = GET_LAYER(map, i)->symbolscaledenom/map->scaledenom*map->resolution/map->defresolution; else GET_LAYER(map, i)->scalefactor = map->resolution/map->defresolution; } image->refpt.x = MS_MAP2IMAGE_X_IC_DBL(0, map->extent.minx, 1.0/map->cellsize); image->refpt.y = MS_MAP2IMAGE_Y_IC_DBL(0, map->extent.maxy, 1.0/map->cellsize); return image; } /* * Generic function to render the map file. * The type of the image created is based on the imagetype parameter in the map file. * * mapObj *map - map object loaded in MapScript or via a mapfile to use * int querymap - is this map the result of a query operation, MS_TRUE|MS_FALSE */ imageObj *msDrawMap(mapObj *map, int querymap) { int i; layerObj *lp=NULL; int status = MS_FAILURE; imageObj *image = NULL; struct mstimeval mapstarttime, mapendtime; struct mstimeval starttime, endtime; #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) enum MS_CONNECTION_TYPE lastconnectiontype; httpRequestObj *pasOWSReqInfo=NULL; int numOWSLayers=0, numOWSRequests=0; wmsParamsObj sLastWMSParams; #endif if(map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&mapstarttime, NULL); if(querymap) { /* use queryMapObj image dimensions */ if(map->querymap.width != -1) map->width = map->querymap.width; if(map->querymap.height != -1) map->height = map->querymap.height; } msApplyMapConfigOptions(map); image = msPrepareImage(map, MS_TRUE); if(!image) { msSetError(MS_IMGERR, "Unable to initialize image.", "msDrawMap()"); return(NULL); } if( map->debug >= MS_DEBUGLEVEL_DEBUG ) msDebug( "msDrawMap(): rendering using outputformat named %s (%s).\n", map->outputformat->name, map->outputformat->driver ); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Time the OWS query phase */ if(map->debug >= MS_DEBUGLEVEL_TUNING ) msGettimeofday(&starttime, NULL); /* How many OWS (WMS/WFS) layers do we have to draw? * Note: numOWSLayers is the number of actual layers and numOWSRequests is * the number of HTTP requests which could be lower if multiple layers * are merged into the same request. */ numOWSLayers=0; for(i=0; inumlayers; i++) { if(map->layerorder[i] != -1 && msLayerIsVisible(map, GET_LAYER(map,map->layerorder[i]))) numOWSLayers++; } if (numOWSLayers > 0) { /* Alloc and init pasOWSReqInfo... */ pasOWSReqInfo = (httpRequestObj *)malloc((numOWSLayers+1)*sizeof(httpRequestObj)); if (pasOWSReqInfo == NULL) { msSetError(MS_MEMERR, "Allocation of httpRequestObj failed.", "msDrawMap()"); return NULL; } msHTTPInitRequestObj(pasOWSReqInfo, numOWSLayers+1); msInitWmsParamsObj(&sLastWMSParams); /* Pre-download all WMS/WFS layers in parallel before starting to draw map */ lastconnectiontype = MS_SHAPEFILE; for(i=0; numOWSLayers && inumlayers; i++) { if(map->layerorder[i] == -1 || !msLayerIsVisible(map, GET_LAYER(map,map->layerorder[i]))) continue; lp = GET_LAYER(map,map->layerorder[i]); #ifdef USE_WMS_LYR if(lp->connectiontype == MS_WMS) { if(msPrepareWMSLayerRequest(map->layerorder[i], map, lp, 1, lastconnectiontype, &sLastWMSParams, 0, 0, 0, NULL, pasOWSReqInfo, &numOWSRequests) == MS_FAILURE) { msFreeWmsParamsObj(&sLastWMSParams); msFreeImage(image); msFree(pasOWSReqInfo); return NULL; } } #endif #ifdef USE_WFS_LYR if(lp->connectiontype == MS_WFS) { if(msPrepareWFSLayerRequest(map->layerorder[i], map, lp, pasOWSReqInfo, &numOWSRequests) == MS_FAILURE) { msFreeWmsParamsObj(&sLastWMSParams); msFreeImage(image); msFree(pasOWSReqInfo); return NULL; } } #endif lastconnectiontype = lp->connectiontype; } #ifdef USE_WMS_LYR msFreeWmsParamsObj(&sLastWMSParams); #endif } /* if numOWSLayers > 0 */ if(numOWSRequests && msOWSExecuteRequests(pasOWSReqInfo, numOWSRequests, map, MS_TRUE) == MS_FAILURE) { msFreeImage(image); msFree(pasOWSReqInfo); return NULL; } if(map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): WMS/WFS set-up and query, %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ /* OK, now we can start drawing */ for(i=0; inumlayers; i++) { if(map->layerorder[i] != -1) { lp = (GET_LAYER(map, map->layerorder[i])); if(lp->postlabelcache) /* wait to draw */ continue; if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING ) msGettimeofday(&starttime, NULL); if(!msLayerIsVisible(map, lp)) continue; if(lp->connectiontype == MS_WMS) { #ifdef USE_WMS_LYR if(MS_RENDERER_PLUGIN(image->format) || MS_RENDERER_RAWDATA(image->format)) status = msDrawWMSLayerLow(map->layerorder[i], pasOWSReqInfo, numOWSRequests, map, lp, image); else { msSetError(MS_WMSCONNERR, "Output format '%s' doesn't support WMS layers.", "msDrawMap()", image->format->name); status = MS_FAILURE; } if(status == MS_FAILURE) { msSetError(MS_WMSCONNERR, "Failed to draw WMS layer named '%s'. This most likely happened because " "the remote WMS server returned an invalid image, and XML exception " "or another unexpected result in response to the GetMap request. Also check " "and make sure that the layer's connection URL is valid.", "msDrawMap()", lp->name); msFreeImage(image); msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); return(NULL); } #else /* ndef USE_WMS_LYR */ msSetError(MS_WMSCONNERR, "MapServer not built with WMS Client support, unable to render layer '%s'.", "msDrawMap()", lp->name); msFreeImage(image); return(NULL); #endif } else { /* Default case: anything but WMS layers */ if(querymap) status = msDrawQueryLayer(map, lp, image); else status = msDrawLayer(map, lp, image); if(status == MS_FAILURE) { msSetError(MS_IMGERR, "Failed to draw layer named '%s'.", "msDrawMap()", lp->name); msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } } } if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): Layer %d (%s), %.3fs\n", map->layerorder[i], lp->name?lp->name:"(null)", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } } if(map->scalebar.status == MS_EMBED && !map->scalebar.postlabelcache) { /* We need to temporarily restore the original extent for drawing */ /* the scalebar as it uses the extent to recompute cellsize. */ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); if(MS_SUCCESS != msEmbedScalebar(map, image)) { msFreeImage( image ); return NULL; } if(map->gt.need_geotransform) msMapSetFakedExtent(map); } if(map->legend.status == MS_EMBED && !map->legend.postlabelcache) { if( msEmbedLegend(map, image) != MS_SUCCESS ) { msFreeImage( image ); return NULL; } } if(map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&starttime, NULL); if(msDrawLabelCache(image, map) != MS_SUCCESS) { msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } if(map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): Drawing Label Cache, %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } for(i=0; inumlayers; i++) { /* for each layer, check for postlabelcache layers */ lp = (GET_LAYER(map, map->layerorder[i])); if(!lp->postlabelcache) continue; if(!msLayerIsVisible(map, lp)) continue; if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&starttime, NULL); if(lp->connectiontype == MS_WMS) { #ifdef USE_WMS_LYR if(MS_RENDERER_PLUGIN(image->format) || MS_RENDERER_RAWDATA(image->format)) status = msDrawWMSLayerLow(map->layerorder[i], pasOWSReqInfo, numOWSRequests, map, lp, image); #else status = MS_FAILURE; #endif } else { if(querymap) status = msDrawQueryLayer(map, lp, image); else status = msDrawLayer(map, lp, image); } if(status == MS_FAILURE) { msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): Layer %d (%s), %.3fs\n", map->layerorder[i], lp->name?lp->name:"(null)", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } } /* Do we need to fake out stuff for rotated support? */ /* This really needs to be done on every preceeding exit point too... */ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); if(map->legend.status == MS_EMBED && map->legend.postlabelcache) msEmbedLegend(map, image); /* TODO */ if(map->scalebar.status == MS_EMBED && map->scalebar.postlabelcache) { /* We need to temporarily restore the original extent for drawing */ /* the scalebar as it uses the extent to recompute cellsize. */ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); if(MS_SUCCESS != msEmbedScalebar(map, image)) { msFreeImage( image ); return NULL; } if(map->gt.need_geotransform) msMapSetFakedExtent(map); } #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Cleanup WMS/WFS Request stuff */ if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif if(map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&mapendtime, NULL); msDebug("msDrawMap() total time: %.3fs\n", (mapendtime.tv_sec+mapendtime.tv_usec/1.0e6)- (mapstarttime.tv_sec+mapstarttime.tv_usec/1.0e6) ); } return(image); } /* * Test whether a layer should be drawn or not in the current map view and * at the current scale. * Returns TRUE if layer is visible, FALSE if not. */ int msLayerIsVisible(mapObj *map, layerObj *layer) { int i; if(!layer->data && !layer->tileindex && !layer->connection && !layer->features && !layer->layerinfo) return(MS_FALSE); /* no data associated with this layer, not an error since layer may be used as a template from MapScript */ if(layer->type == MS_LAYER_QUERY || layer->type == MS_LAYER_TILEINDEX) return(MS_FALSE); if((layer->status != MS_ON) && (layer->status != MS_DEFAULT)) return(MS_FALSE); /* Only return MS_FALSE if it is definitely false. Sometimes it will return MS_UNKNOWN, which we ** consider true, for this use case (it might be visible, try and draw it, see what happens). */ if ( msExtentsOverlap(map, layer) == MS_FALSE ) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.EXTENT does not intersect MAP.EXTENT\n", layer->name); } return(MS_FALSE); } if(msEvalContext(map, layer, layer->requires) == MS_FALSE) return(MS_FALSE); if(map->scaledenom > 0) { /* layer scale boundaries should be checked first */ if((layer->maxscaledenom > 0) && (map->scaledenom > layer->maxscaledenom)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.MAXSCALE is too small for this MAP scale\n", layer->name); } return(MS_FALSE); } if((layer->minscaledenom > 0) && (map->scaledenom <= layer->minscaledenom)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.MINSCALE is too large for this MAP scale\n", layer->name); } return(MS_FALSE); } /* now check class scale boundaries (all layers *must* pass these tests) */ if(layer->numclasses > 0) { for(i=0; inumclasses; i++) { if((layer->class[i]->maxscaledenom > 0) && (map->scaledenom > layer->class[i]->maxscaledenom)) continue; /* can skip this one, next class */ if((layer->class[i]->minscaledenom > 0) && (map->scaledenom <= layer->class[i]->minscaledenom)) continue; /* can skip this one, next class */ break; /* can't skip this class (or layer for that matter) */ } if(i == layer->numclasses) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because no CLASS in the layer is in-scale for this MAP scale\n", layer->name); } return(MS_FALSE); } } } if (layer->maxscaledenom <= 0 && layer->minscaledenom <= 0) { if((layer->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > layer->maxgeowidth)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER width is much smaller than map width\n", layer->name); } return(MS_FALSE); } if((layer->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < layer->mingeowidth)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER width is much larger than map width\n", layer->name); } return(MS_FALSE); } } return MS_TRUE; /* All tests passed. Layer is visible. */ } /* * Generic function to render a layer object. */ int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image) { imageObj *image_draw = image; outputFormatObj *altFormat=NULL; int retcode=MS_SUCCESS; int originalopacity = layer->opacity; const char *alternativeFomatString = NULL; layerObj *maskLayer = NULL; if(!msLayerIsVisible(map, layer)) return MS_SUCCESS; if(layer->opacity == 0) return MS_SUCCESS; /* layer is completely transparent, skip it */ /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ layer->project = MS_TRUE; if(layer->mask) { int maskLayerIdx; /* render the mask layer in its own imageObj */ if(!MS_IMAGE_RENDERER(image)->supports_pixel_buffer) { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msDrawLayer()", layer->name); return (MS_FAILURE); } maskLayerIdx = msGetLayerIndex(map,layer->mask); if(maskLayerIdx == -1) { msSetError(MS_MISCERR, "Layer (%s) references unknown mask layer (%s)", "msDrawLayer()", layer->name,layer->mask); return (MS_FAILURE); } maskLayer = GET_LAYER(map, maskLayerIdx); if(!maskLayer->maskimage) { int i; int origstatus, origlabelcache; altFormat = msSelectOutputFormat(map, "png24"); msInitializeRendererVTable(altFormat); /* TODO: check the png24 format hasn't been tampered with, i.e. it's agg */ maskLayer->maskimage= msImageCreate(image->width, image->height,altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!maskLayer->maskimage) { msSetError(MS_MISCERR, "Unable to initialize mask image.", "msDrawLayer()"); return (MS_FAILURE); } /* * force the masked layer to status on, and turn off the labelcache so that * eventual labels are added to the temporary image instead of being added * to the labelcache */ origstatus = maskLayer->status; origlabelcache = maskLayer->labelcache; maskLayer->status = MS_ON; maskLayer->labelcache = MS_OFF; /* draw the mask layer in the temporary image */ retcode = msDrawLayer(map, maskLayer, maskLayer->maskimage); maskLayer->status = origstatus; maskLayer->labelcache = origlabelcache; if(retcode != MS_SUCCESS) { return MS_FAILURE; } /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == MS_IMAGE_RENDERER(maskLayer->maskimage)) { MS_IMAGE_RENDERER(maskLayer->maskimage)->freeSymbol(s); s->renderer = NULL; } } } /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */ msFree(map->imagetype); map->imagetype = msStrdup(image->format->name); } } altFormat = NULL; /* inform the rendering device that layer draw is starting. */ msImageStartLayer(map, layer, image); /*check if an alternative renderer should be used for this layer*/ alternativeFomatString = msLayerGetProcessingKey( layer, "RENDERER"); if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFomatString!=NULL && (altFormat= msSelectOutputFormat(map, alternativeFomatString))) { rendererVTableObj *renderer=NULL; msInitializeRendererVTable(altFormat); image_draw = msImageCreate(image->width, image->height, altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor); renderer = MS_IMAGE_RENDERER(image_draw); renderer->startLayer(image_draw,map,layer); } else if (MS_RENDERER_PLUGIN(image_draw->format)) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); if ((layer->mask && layer->connectiontype!=MS_WMS && layer->type != MS_LAYER_RASTER) || (layer->opacity > 0 && layer->opacity < 100)) { /* masking occurs at the pixel/layer level for raster images, so we don't need to create a temporary image in these cases */ if (layer->mask || !renderer->supports_transparent_layers) { image_draw = msImageCreate(image->width, image->height, image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!image_draw) { msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.", "msDrawLayer()"); return (MS_FAILURE); } /* set opacity to full, as the renderer should be rendering a fully opaque image */ layer->opacity=100; renderer->startLayer(image_draw,map,layer); } } } /* ** redirect procesing of some layer types. */ if(layer->connectiontype == MS_WMS) { #ifdef USE_WMS_LYR retcode = msDrawWMSLayer(map, layer, image_draw); #else retcode = MS_FAILURE; #endif } else if(layer->type == MS_LAYER_RASTER) { retcode = msDrawRasterLayer(map, layer, image_draw); } else if(layer->type == MS_LAYER_CHART) { retcode = msDrawChartLayer(map, layer, image_draw); } else { /* must be a Vector layer */ retcode = msDrawVectorLayer(map, layer, image_draw); } if (altFormat) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rendererVTableObj *altrenderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; int i; memset(&rb,0,sizeof(rasterBufferObj)); altrenderer->endLayer(image_draw,map,layer); altrenderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,layer->opacity*0.01,0,0,0,0,rb.width,rb.height); /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == altrenderer) { altrenderer->freeSymbol(s); s->renderer = NULL; } } } msFreeImage(image_draw); /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */ msFree(map->imagetype); map->imagetype = msStrdup(image->format->name); } else if( image != image_draw) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); renderer->endLayer(image_draw,map,layer); layer->opacity = originalopacity; renderer->getRasterBufferHandle(image_draw,&rb); if(maskLayer && maskLayer->maskimage) { rasterBufferObj mask; unsigned int row,col; memset(&mask,0,sizeof(rasterBufferObj)); MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,&mask); /* modify the pixels of the overlay */ if(rb.type == MS_BUFFER_BYTE_RGBA) { for(row=0; rowmergeRasterBuffer(image,&rb,layer->opacity*0.01,0,0,0,0,rb.width,rb.height); msFreeImage(image_draw); } msImageEndLayer(map,layer,image); return(retcode); } int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image) { int status, retcode=MS_SUCCESS; int drawmode=MS_DRAWMODE_FEATURES; char annotate=MS_TRUE; shapeObj shape; rectObj searchrect; char cache=MS_FALSE; int maxnumstyles=1; featureListNodeObjPtr shpcache=NULL, current=NULL; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; int maxfeatures=-1; int featuresdrawn=0; if (image) maxfeatures=msLayerGetMaxFeaturesToDraw(layer, image->format); /* TODO TBT: draw as raster layer in vector renderers */ annotate = msEvalContext(map, layer, layer->labelrequires); if(map->scaledenom > 0) { if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE; if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE; } #ifdef USE_GD /* reset layer pen values just in case the map has been previously processed */ msClearLayerPenValues(layer); #endif /* open this layer */ status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; /* build item list */ status = msLayerWhichItems(layer, MS_FALSE, NULL); if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) { searchrect = map->extent; #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif } else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); return MS_SUCCESS; } else if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* step through the target shapes */ msInitShape(&shape); nclasses = 0; classgroup = NULL; if(layer->classgroup && layer->numclasses > 0) classgroup = msAllocateValidClassGroups(layer, &nclasses); if(layer->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, layer, layer->minfeaturesize); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { /* Check if the shape size is ok to be drawn */ if((shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) && (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE)) { if(layer->debug >= MS_DEBUGLEVEL_V) msDebug("msDrawVectorLayer(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } shape.classindex = msShapeGetClass(layer, map, &shape, classgroup, nclasses); if((shape.classindex == -1) || (layer->class[shape.classindex]->status == MS_OFF)) { msFreeShape(&shape); continue; } if(maxfeatures >=0 && featuresdrawn >= maxfeatures) { status = MS_DONE; break; } featuresdrawn++; cache = MS_FALSE; if(layer->type == MS_LAYER_LINE && (layer->class[shape.classindex]->numstyles > 1 || (layer->class[shape.classindex]->numstyles == 1 && layer->class[shape.classindex]->styles[0]->outlinewidth > 0))) { int i; cache = MS_TRUE; /* only line layers with multiple styles need be cached (I don't think POLYLINE layers need caching - SDL) */ /* we can't handle caching with attribute binding other than for the first style (#3976) */ for(i=1; iclass[shape.classindex]->numstyles; i++) { if(layer->class[shape.classindex]->styles[i]->numbindings > 0) cache = MS_FALSE; } } /* With 'STYLEITEM AUTO', we will have the datasource fill the class' */ /* style parameters for this shape. */ if(layer->styleitem) { if(strcasecmp(layer->styleitem, "AUTO") == 0) { if(msLayerGetAutoStyle(map, layer, layer->class[shape.classindex], &shape) != MS_SUCCESS) { retcode = MS_FAILURE; break; } } else { /* Generic feature style handling as per RFC-61 */ if(msLayerGetFeatureStyle(map, layer, layer->class[shape.classindex], &shape) != MS_SUCCESS) { retcode = MS_FAILURE; break; } } /* __TODO__ For now, we can't cache features with 'AUTO' style */ cache = MS_FALSE; } /* RFC77 TODO: check return value, may need a more sophisticated if-then test. */ if(annotate && layer->class[shape.classindex]->numlabels > 0) { msShapeGetAnnotation(layer, &shape); drawmode |= MS_DRAWMODE_LABELS; if (msLayerGetProcessingKey(layer, "LABEL_NO_CLIP")) { drawmode |= MS_DRAWMODE_UNCLIPPEDLABELS; } } if (layer->type == MS_LAYER_LINE && msLayerGetProcessingKey(layer, "POLYLINE_NO_CLIP")) { drawmode |= MS_DRAWMODE_UNCLIPPEDLINES; } if (cache) { styleObj *pStyle = layer->class[shape.classindex]->styles[0]; colorObj tmp; if (pStyle->outlinewidth > 0) { /* * RFC 49 implementation * if an outlinewidth is used: * - augment the style's width to account for the outline width * - swap the style color and outlinecolor * - draw the shape (the outline) in the first pass of the * caching mechanism */ /* adapt width (must take scalefactor into account) */ pStyle->width += (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2; pStyle->minwidth += pStyle->outlinewidth * 2; pStyle->maxwidth += pStyle->outlinewidth * 2; pStyle->size += (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution)); /*swap color and outlinecolor*/ tmp = pStyle->color; pStyle->color = pStyle->outlinecolor; pStyle->outlinecolor = tmp; } status = msDrawShape(map, layer, &shape, image, 0, drawmode|MS_DRAWMODE_SINGLESTYLE); /* draw a single style */ if (pStyle->outlinewidth > 0) { /* * RFC 49 implementation: switch back the styleobj to its * original state, so the line fill will be drawn in the * second pass of the caching mechanism */ /* reset widths to original state */ pStyle->width -= (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2; pStyle->minwidth -= pStyle->outlinewidth * 2; pStyle->maxwidth -= pStyle->outlinewidth * 2; pStyle->size -= (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution)); /*reswap colors to original state*/ tmp = pStyle->color; pStyle->color = pStyle->outlinecolor; pStyle->outlinecolor = tmp; } } else status = msDrawShape(map, layer, &shape, image, -1, drawmode); /* all styles */ if(status != MS_SUCCESS) { msFreeShape(&shape); retcode = MS_FAILURE; break; } if(shape.numlines == 0) { /* once clipped the shape didn't need to be drawn */ msFreeShape(&shape); continue; } if(cache) { if(insertFeatureList(&shpcache, &shape) == NULL) { retcode = MS_FAILURE; /* problem adding to the cache */ break; } } maxnumstyles = MS_MAX(maxnumstyles, layer->class[shape.classindex]->numstyles); msFreeShape(&shape); } if (classgroup) msFree(classgroup); if(status != MS_DONE || retcode == MS_FAILURE) { msLayerClose(layer); if(shpcache) { freeFeatureList(shpcache); shpcache = NULL; } return MS_FAILURE; } if(shpcache && MS_DRAW_FEATURES(drawmode)) { int s; for(s=0; snext) { if(layer->class[current->shape.classindex]->numstyles > s) { styleObj *pStyle = layer->class[current->shape.classindex]->styles[s]; if(pStyle->_geomtransform.type != MS_GEOMTRANSFORM_NONE) continue; /*skip this as it has already been rendered*/ if(map->scaledenom > 0) { if((pStyle->maxscaledenom != -1) && (map->scaledenom >= pStyle->maxscaledenom)) continue; if((pStyle->minscaledenom != -1) && (map->scaledenom < pStyle->minscaledenom)) continue; } if(s==0 && pStyle->outlinewidth>0 && MS_VALID_COLOR(pStyle->color)) { msDrawLineSymbol(&map->symbolset, image, ¤t->shape, pStyle, layer->scalefactor); } else if(s>0) { if (pStyle->outlinewidth > 0 && MS_VALID_COLOR(pStyle->outlinecolor)) { colorObj tmp; /* * RFC 49 implementation * if an outlinewidth is used: * - augment the style's width to account for the outline width * - swap the style color and outlinecolor * - draw the shape (the outline) in the first pass of the * caching mechanism */ /* adapt width (must take scalefactor into account) */ pStyle->width += (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2; pStyle->minwidth += pStyle->outlinewidth * 2; pStyle->maxwidth += pStyle->outlinewidth * 2; pStyle->size += (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution)); /*swap color and outlinecolor*/ tmp = pStyle->color; pStyle->color = pStyle->outlinecolor; pStyle->outlinecolor = tmp; msDrawLineSymbol(&map->symbolset, image, ¤t->shape, pStyle, layer->scalefactor); /* * RFC 49 implementation: switch back the styleobj to its * original state, so the line fill will be drawn in the * second pass of the caching mechanism */ /* reset widths to original state */ pStyle->width -= (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2; pStyle->minwidth -= pStyle->outlinewidth * 2; pStyle->maxwidth -= pStyle->outlinewidth * 2; pStyle->size -= (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution)); /*reswap colors to original state*/ tmp = pStyle->color; pStyle->color = pStyle->outlinecolor; pStyle->outlinecolor = tmp; } /* draw a valid line, i.e. one with a color defined or of type pixmap*/ if(MS_VALID_COLOR(pStyle->color) || ( pStyle->symbolsymbolset.numsymbols && ( map->symbolset.symbol[pStyle->symbol]->type == MS_SYMBOL_PIXMAP || map->symbolset.symbol[pStyle->symbol]->type == MS_SYMBOL_SVG ) ) ) { msDrawLineSymbol(&map->symbolset, image, ¤t->shape, pStyle, layer->scalefactor); } } } } } freeFeatureList(shpcache); shpcache = NULL; } msLayerClose(layer); return MS_SUCCESS; } /* ** Function to draw a layer IF it already has a result cache associated with it. Called by msDrawMap and via MapScript. */ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image) { int i, status; char annotate=MS_TRUE, cache=MS_FALSE; int drawmode = MS_DRAWMODE_FEATURES|MS_DRAWMODE_QUERY; shapeObj shape; int maxnumstyles=1; featureListNodeObjPtr shpcache=NULL, current=NULL; colorObj *colorbuffer = NULL; int *mindistancebuffer = NULL; if(!layer->resultcache) return(msDrawLayer(map, layer, image)); if(!msLayerIsVisible(map, layer)) return(MS_SUCCESS); /* not an error, just nothing to do */ /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ layer->project = MS_TRUE; /* set annotation status */ annotate = msEvalContext(map, layer, layer->labelrequires); if(map->scaledenom > 0) { if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE; if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE; } /* ** Certain query map styles require us to render all features only (MS_NORMAL) or first (MS_HILITE). With ** single-pass queries we have to make a copy of the layer and work from it instead. */ if(map->querymap.style == MS_NORMAL || map->querymap.style == MS_HILITE) { layerObj tmp_layer; if(initLayer(&tmp_layer, map) == -1) return(MS_FAILURE); if (msCopyLayer(&tmp_layer, layer) != MS_SUCCESS) return(MS_FAILURE); /* disable the connection pool for this layer */ msLayerSetProcessingKey(&tmp_layer, "CLOSE_CONNECTION", "ALWAYS"); status = msDrawLayer(map, &tmp_layer, image); freeLayer(&tmp_layer); if(map->querymap.style == MS_NORMAL || status != MS_SUCCESS) return(status); } #ifdef USE_GD /* reset layer pen values just in case the map has been previously processed */ msClearLayerPenValues(layer); #endif /* if MS_HILITE, alter the one style (always at least 1 style), and set a MINDISTANCE for the labelObj to avoid duplicates */ if(map->querymap.style == MS_HILITE) { if (layer->numclasses > 0) { colorbuffer = (colorObj*)malloc(layer->numclasses*sizeof(colorObj)); mindistancebuffer = (int*)malloc(layer->numclasses*sizeof(int)); if (colorbuffer == NULL || mindistancebuffer == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for colorbuffer/mindistancebuffer", "msDrawQueryLayer()"); return MS_FAILURE; } } for(i=0; inumclasses; i++) { if(layer->type == MS_LAYER_POLYGON) { /* alter BOTTOM style since that's almost always the fill */ if (layer->class[i]->styles == NULL) { msSetError(MS_MISCERR, "Don't know how to draw class %s of layer %s without a style definition.", "msDrawQueryLayer()", layer->class[i]->name, layer->name); return(MS_FAILURE); } if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) { colorbuffer[i] = layer->class[i]->styles[0]->color; /* save the color from the BOTTOM style */ layer->class[i]->styles[0]->color = map->querymap.color; } else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) { colorbuffer[i] = layer->class[i]->styles[0]->outlinecolor; /* if no color, save the outlinecolor from the BOTTOM style */ layer->class[i]->styles[0]->outlinecolor = map->querymap.color; } } else { if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) { colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->color; /* save the color from the TOP style */ layer->class[i]->styles[layer->class[i]->numstyles-1]->color = map->querymap.color; } else if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor)) { colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor; /* if no color, save the outlinecolor from the TOP style */ layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = map->querymap.color; } } mindistancebuffer[i] = -1; /* RFC77 TODO: only using the first label, is that cool? */ if(layer->class[i]->numlabels > 0) { mindistancebuffer[i] = layer->class[i]->labels[0]->mindistance; layer->class[i]->labels[0]->mindistance = MS_MAX(0, layer->class[i]->labels[0]->mindistance); } } } /* ** Layer was opened as part of the query process, msLayerWhichItems() has also been run, shapes have been classified - start processing! */ msInitShape(&shape); for(i=0; iresultcache->numresults; i++) { status = msLayerGetShape(layer, &shape, &(layer->resultcache->results[i])); if(status != MS_SUCCESS) { msFree(colorbuffer); msFree(mindistancebuffer); return(MS_FAILURE); } shape.classindex = layer->resultcache->results[i].classindex; /* classindex may be -1 here if there was a template at the top level * in this layer and the current shape selected even if it didn't * match any class * * FrankW: classindex is also sometimes 0 even if there are no classes, so * we are careful not to use out of range class values as an index. */ if(shape.classindex==-1 || shape.classindex >= layer->numclasses || layer->class[shape.classindex]->status == MS_OFF) { msFreeShape(&shape); continue; } cache = MS_FALSE; if(layer->type == MS_LAYER_LINE && layer->class[shape.classindex]->numstyles > 1) cache = MS_TRUE; /* only line layers with multiple styles need be cached (I don't think POLYLINE layers need caching - SDL) */ /* RFC 77 TODO: check return value for msShapeGetAnnotation() */ if(annotate && layer->class[shape.classindex]->numlabels > 0) { msShapeGetAnnotation(layer, &shape); drawmode |= MS_DRAWMODE_LABELS; } if(cache) { drawmode |= MS_DRAWMODE_SINGLESTYLE; status = msDrawShape(map, layer, &shape, image, 0, drawmode); /* draw only the first style */ } else status = msDrawShape(map, layer, &shape, image, -1, drawmode); /* all styles */ if(status != MS_SUCCESS) { msLayerClose(layer); msFree(colorbuffer); msFree(mindistancebuffer); return(MS_FAILURE); } if(shape.numlines == 0) { /* once clipped the shape didn't need to be drawn */ msFreeShape(&shape); continue; } if(cache) { if(insertFeatureList(&shpcache, &shape) == NULL) return(MS_FAILURE); /* problem adding to the cache */ } maxnumstyles = MS_MAX(maxnumstyles, layer->class[shape.classindex]->numstyles); msFreeShape(&shape); } if(shpcache) { int s; for(s=1; snext) { if(layer->class[current->shape.classindex]->numstyles > s) { styleObj *curStyle = layer->class[current->shape.classindex]->styles[s]; if(map->scaledenom > 0) { if((curStyle->maxscaledenom != -1) && (map->scaledenom >= curStyle->maxscaledenom)) continue; if((curStyle->minscaledenom != -1) && (map->scaledenom < curStyle->minscaledenom)) continue; } msDrawLineSymbol(&map->symbolset, image, ¤t->shape, (layer->class[current->shape.classindex]->styles[s]), layer->scalefactor); } } } freeFeatureList(shpcache); shpcache = NULL; } /* if MS_HILITE, restore color and mindistance values */ if(map->querymap.style == MS_HILITE) { for(i=0; inumclasses; i++) { if(layer->type == MS_LAYER_POLYGON) { if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) layer->class[i]->styles[0]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) layer->class[i]->styles[0]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the BOTTOM style */ } else { if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) layer->class[i]->styles[layer->class[i]->numstyles-1]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor)) layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the TOP style */ } if(layer->class[i]->numlabels > 0) layer->class[i]->labels[0]->mindistance = mindistancebuffer[i]; /* RFC77 TODO: again, only using the first label, is that cool? */ } msFree(colorbuffer); msFree(mindistancebuffer); } return(MS_SUCCESS); } /** * msDrawRasterLayerPlugin() */ static int msDrawRasterLayerPlugin( mapObj *map, layerObj *layer, imageObj *image) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rasterBufferObj *rb = msSmallCalloc(1,sizeof(rasterBufferObj)); int ret; if( renderer->supports_pixel_buffer ) { if (MS_SUCCESS != renderer->getRasterBufferHandle( image, rb )) { msSetError(MS_MISCERR,"renderer failed to extract raster buffer","msDrawRasterLayer()"); return MS_FAILURE; } ret = msDrawRasterLayerLow( map, layer, image, rb ); } else { if (MS_SUCCESS != renderer->initializeRasterBuffer( rb, image->width, image->height, MS_IMAGEMODE_RGBA )) { msSetError(MS_MISCERR,"renderer failed to create raster buffer","msDrawRasterLayer()"); return MS_FAILURE; } ret = msDrawRasterLayerLow( map, layer, image, rb ); if( ret == 0 ) { renderer->mergeRasterBuffer( image, rb, 1.0, 0, 0, 0, 0, rb->width, rb->height ); } msFreeRasterBuffer(rb); } #define RB_GET_R(rb,x,y) *((rb)->data.rgba.r + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) #define RB_GET_G(rb,x,y) *((rb)->data.rgba.g + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) #define RB_GET_B(rb,x,y) *((rb)->data.rgba.b + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) #define RB_GET_A(rb,x,y) *((rb)->data.rgba.a + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) free(rb); return ret; } /** * Generic function to render raster layers. */ int msDrawRasterLayer(mapObj *map, layerObj *layer, imageObj *image) { int rv = MS_FAILURE; if (!image || !map || !layer) { return rv; } /* RFC-86 Scale dependant token replacements*/ rv = msLayerApplyScaletokens(layer,(layer->map)?layer->map->scaledenom:-1); if (rv != MS_SUCCESS) return rv; if( MS_RENDERER_PLUGIN(image->format) ) rv = msDrawRasterLayerPlugin(map, layer, image); else if( MS_RENDERER_RAWDATA(image->format) ) rv = msDrawRasterLayerLow(map, layer, image, NULL); msLayerRestoreFromScaletokens(layer); return rv; } /** * msDrawWMSLayer() * * Draw a single WMS layer. * Multiple WMS layers in a map are preloaded and then drawn using * msDrawWMSLayerLow() */ #ifdef USE_WMS_LYR int msDrawWMSLayer(mapObj *map, layerObj *layer, imageObj *image) { int nStatus = MS_FAILURE; if (image && map && layer) { /* ------------------------------------------------------------------ * Start by downloading the layer * ------------------------------------------------------------------ */ httpRequestObj asReqInfo[2]; int numReq = 0; msHTTPInitRequestObj(asReqInfo, 2); if ( msPrepareWMSLayerRequest(1, map, layer, 1, 0, NULL, 0, 0, 0, NULL, asReqInfo, &numReq) == MS_FAILURE || msOWSExecuteRequests(asReqInfo, numReq, map, MS_TRUE) == MS_FAILURE ) { return MS_FAILURE; } /* ------------------------------------------------------------------ * Then draw layer based on output format * ------------------------------------------------------------------ */ if( MS_RENDERER_PLUGIN(image->format) ) nStatus = msDrawWMSLayerLow(1, asReqInfo, numReq, map, layer, image) ; else if( MS_RENDERER_RAWDATA(image->format) ) nStatus = msDrawWMSLayerLow(1, asReqInfo, numReq, map, layer, image) ; else { msSetError(MS_WMSCONNERR, "Output format '%s' doesn't support WMS layers.", "msDrawWMSLayer()", image->format->name); nStatus = MS_SUCCESS; /* Should we fail if output doesn't support WMS? */ } /* Cleanup */ msHTTPFreeRequestObj(asReqInfo, numReq); } return nStatus; } #endif int circleLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape) { pointObj center; double r; int s; int c = shape->classindex; if (shape->numlines != 1) return (MS_SUCCESS); /* invalid shape */ if (shape->line[0].numpoints != 2) return (MS_SUCCESS); /* invalid shape */ center.x = (shape->line[0].point[0].x + shape->line[0].point[1].x) / 2.0; center.y = (shape->line[0].point[0].y + shape->line[0].point[1].y) / 2.0; r = MS_ABS(center.x - shape->line[0].point[0].x); if (r == 0) r = MS_ABS(center.y - shape->line[0].point[0].y); if (r == 0) return (MS_SUCCESS); if (layer->transform == MS_TRUE) { #ifdef USE_PROJ if (layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection))) msProjectPoint(&layer->projection, &map->projection, ¢er); else layer->project = MS_FALSE; #endif center.x = MS_MAP2IMAGE_X(center.x, map->extent.minx, map->cellsize); center.y = MS_MAP2IMAGE_Y(center.y, map->extent.maxy, map->cellsize); r /= map->cellsize; } else msOffsetPointRelativeTo(¢er, layer); for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) msCircleDrawShadeSymbol(&map->symbolset, image, ¢er, r, layer->class[c]->styles[s], layer->scalefactor); } return MS_SUCCESS; /* TODO: need to handle circle annotation */ } int annotationLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape) { int c = shape->classindex; rectObj cliprect; labelObj *label; double minfeaturesize; labelPathObj **annopaths = NULL; /* Curved label path. Bug #1620 implementation */ pointObj **annopoints = NULL; pointObj annopnt; pointObj *point; int *regularLines = NULL; double** angles = NULL, **lengths = NULL; int ret = MS_SUCCESS; int numpaths = 1, numpoints = 1, numRegularLines = 0, i,j,s; if (layer->class[c]->numlabels == 0) return (MS_SUCCESS); /* nothing to draw (RFC77 TDOO: could expand this test) */ if (layer->class[c]->numlabels > 1) { msSetError(MS_MISCERR, "Multiple labels not supported on annotation layers.", "annotationLayerDrawShape()"); return MS_FAILURE; } cliprect.minx = cliprect.miny = 0; cliprect.maxx = image->width; cliprect.maxy = image->height; /* annotation layers can only have one layer, don't treat the multi layer case */ label = layer->class[c]->labels[0]; /* for brevity */ minfeaturesize = label->minfeaturesize * image->resolutionfactor; switch (shape->type) { case(MS_SHAPE_LINE): if (label->anglemode == MS_FOLLOW) { /* bug #1620 implementation */ #ifndef NDEBUG /* this test should already occur at the parser level in loadLabel() */ if (label->type != MS_TRUETYPE) { msSetError(MS_MISCERR, "Angle mode 'FOLLOW' is supported only with truetype fonts.", "annotationLayerDrawShape()"); return (MS_FAILURE); } #endif if(!layer->labelcache) { msSetError(MS_MISCERR, "Angle mode 'FOLLOW' is supported only with LABELCACHE ON", "annotationLayerDrawShape()"); return (MS_FAILURE); } annopaths = msPolylineLabelPath(map, image, shape, minfeaturesize, &(map->fontset), label->annotext, label, layer->scalefactor, &numpaths, ®ularLines, &numRegularLines); for (i = 0; i < numpaths; i++) { label->position = MS_CC; /* force label position to MS_CC regardless if a path is computed (WHY HERE?) */ if (annopaths[i]) { if (msAddLabel(map, label, layer->index, c, shape, NULL, annopaths[i], -1) != MS_SUCCESS) { ret = MS_FAILURE; goto anno_cleanup_line; } } } /* handle regular lines that have to be drawn with the regular algorithm */ if (numRegularLines > 0) { annopoints = msPolylineLabelPointExtended(shape, minfeaturesize, label->repeatdistance, &angles, &lengths, &numpoints, regularLines, numRegularLines, MS_FALSE); for (i = 0; i < numpoints; i++) { label->angle = *angles[i]; if (msAddLabel(map, label, layer->index, c, shape, annopoints[i], NULL, *lengths[i]) != MS_SUCCESS) { ret = MS_FAILURE; goto anno_cleanup_line; } } } } else { int s; annopoints = msPolylineLabelPoint(shape, minfeaturesize, label->repeatdistance, &angles, &lengths, &numpoints, label->anglemode); if (label->angle != 0) label->angle -= map->gt.rotation_angle; /* apply rotation angle */ for (i = 0; i < numpoints; i++) { if (label->anglemode != MS_NONE) label->angle = *angles[i]; /* angle derived from line overrides even the rotation value. */ if (layer->labelcache) { if (msAddLabel(map, label, layer->index, c, shape, annopoints[i], NULL, *lengths[i]) != MS_SUCCESS) return (MS_FAILURE); } else { if (layer->class[c]->numstyles > 0 && MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) msDrawMarkerSymbol(&map->symbolset, image, annopoints[i], layer->class[c]->styles[s], layer->scalefactor); } } msDrawLabel(map, image, *annopoints[i], label->annotext, label, layer->scalefactor); } } } anno_cleanup_line: msFree(annopaths); msFree(regularLines); if (annopoints) { for (i = 0; i < numpoints; i++) { if (annopoints[i]) free(annopoints[i]); if (angles[i]) free(angles[i]); if (lengths[i]) free(lengths[i]); } free(angles); free(annopoints); free(lengths); } return ret; case(MS_SHAPE_POLYGON): if (msPolygonLabelPoint(shape, &annopnt, minfeaturesize) == MS_SUCCESS) { if(annopnt.x>0 && annopnt.y >0 && annopnt.x <= image->width && annopnt.y<=image->height) { if (label->angle != 0) label->angle -= map->gt.rotation_angle; /* TODO: isn't this a bug, the label angle will be changed at each feature ? */ if(layer->labelcache) { if (msAddLabel(map, label, layer->index, c, shape, &annopnt, NULL, MS_MIN(shape->bounds.maxx - shape->bounds.minx, shape->bounds.maxy - shape->bounds.miny)) != MS_SUCCESS) { return (MS_FAILURE); } } else { if (layer->class[c]->numstyles > 0 && MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { for (i = 0; i < layer->class[c]->numstyles; i++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[i]->minscaledenom, layer->class[c]->styles[i]->maxscaledenom)) msDrawMarkerSymbol(&map->symbolset, image, &annopnt, layer->class[c]->styles[i], layer->scalefactor); } } msDrawLabel(map, image, annopnt, label->annotext, label, layer->scalefactor); } } } break; default: /* points and anything with out a proper type */ if (label->angle != 0) label->angle -= map->gt.rotation_angle; for (j = 0; j < shape->numlines; j++) { for (i = 0; i < shape->line[j].numpoints; i++) { point = &(shape->line[j].point[i]); if (!msPointInRect(point, &cliprect)) continue; if (layer->labelcache) { if (msAddLabel(map, label, layer->index, c, shape, point, NULL, -1) != MS_SUCCESS) return (MS_FAILURE); } else { if (layer->class[c]->numstyles > 0 && MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) msDrawMarkerSymbol(&map->symbolset, image, point, layer->class[c]->styles[s], layer->scalefactor); } } msDrawLabel(map, image, *point, label->annotext, label, layer->scalefactor); } } } } return MS_SUCCESS; } int pointLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape, int drawmode) { int l, c = shape->classindex, j, i, s; pointObj *point; #ifdef USE_PROJ if (layer->project && layer->transform == MS_TRUE && msProjectionsDiffer(&(layer->projection), &(map->projection))) msProjectShape(&layer->projection, &map->projection, shape); else layer->project = MS_FALSE; #endif for (l = 0; l < layer->class[c]->numlabels; l++) if (layer->class[c]->labels[l]->angle != 0) layer->class[c]->labels[l]->angle -= map->gt.rotation_angle; /* TODO: is this right???? */ for (j = 0; j < shape->numlines; j++) { for (i = 0; i < shape->line[j].numpoints; i++) { point = &(shape->line[j].point[i]); if (layer->transform == MS_TRUE) { if (!msPointInRect(point, &map->extent)) continue; /* next point */ msTransformPoint(point, &map->extent, map->cellsize, image); } else msOffsetPointRelativeTo(point, layer); if(MS_DRAW_FEATURES(drawmode)) { for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) msDrawMarkerSymbol(&map->symbolset, image, point, layer->class[c]->styles[s], layer->scalefactor); } } if(MS_DRAW_LABELS(drawmode)) { if (layer->labelcache) { if (msAddLabelGroup(map, layer->index, c, shape, point, -1) != MS_SUCCESS) return (MS_FAILURE); } else { for (l = 0; l < layer->class[c]->numlabels; l++) msDrawLabel(map, image, *point, layer->class[c]->labels[l]->annotext, layer->class[c]->labels[l], layer->scalefactor); } } } } return MS_SUCCESS; } int lineLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape, shapeObj *anno_shape, shapeObj *unclipped_shape, int style, int drawmode) { int c = shape->classindex; double minfeaturesize; labelPathObj **annopaths = NULL; /* Curved label path. Bug #1620 implementation */ pointObj **annopoints = NULL; int *regularLines = NULL; double** angles = NULL, **lengths = NULL; int ret = MS_SUCCESS; int numpaths = 1, numpoints = 1, numRegularLines = 0, i, j, s, l = 0; /* RFC48: loop through the styles, and pass off to the type-specific function if the style has an appropriate type */ if(MS_DRAW_FEATURES(drawmode)) { for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) { if (layer->class[c]->styles[s]->_geomtransform.type != MS_GEOMTRANSFORM_NONE) msDrawTransformedShape(map, &map->symbolset, image, unclipped_shape, layer->class[c]->styles[s], layer->scalefactor); else if (!MS_DRAW_SINGLESTYLE(drawmode) || s == style) msDrawLineSymbol(&map->symbolset, image, shape, layer->class[c]->styles[s], layer->scalefactor); } } } if(MS_DRAW_LABELS(drawmode)) { for (l = 0; l < layer->class[c]->numlabels; l++) { labelObj *label = layer->class[c]->labels[l]; minfeaturesize = label->minfeaturesize * image->resolutionfactor; if (label->anglemode == MS_FOLLOW) { /* bug #1620 implementation */ if (label->type != MS_TRUETYPE) { msSetError(MS_MISCERR, "Angle mode 'FOLLOW' is supported only with truetype fonts.", "msDrawShape()"); ret = MS_FAILURE; goto line_cleanup; } annopaths = msPolylineLabelPath(map, image, anno_shape, minfeaturesize, &(map->fontset), label->annotext, label, layer->scalefactor, &numpaths, ®ularLines, &numRegularLines); for (i = 0; i < numpaths; i++) { label->position = MS_CC; /* force all label positions to MS_CC regardless if a path is computed */ if (annopaths[i]) { if (layer->labelcache) { if (msAddLabel(map, label, layer->index, c, anno_shape, NULL, annopaths[i], -1) != MS_SUCCESS) { ret = MS_FAILURE; goto line_cleanup; } } else { /* TODO: handle drawing curved labels outside the cache */ msFreeLabelPathObj(annopaths[i]); annopaths[i] = NULL; } } } /* handle regular lines that have to be drawn with the regular algorithm */ if (numRegularLines > 0) { annopoints = msPolylineLabelPointExtended(anno_shape, minfeaturesize, label->repeatdistance, &angles, &lengths, &numpoints, regularLines, numRegularLines, MS_FALSE); for (i = 0; i < numpoints; i++) { label->angle = *angles[i]; if (layer->labelcache) { if (msAddLabel(map, label, layer->index, c, anno_shape, annopoints[i], NULL, *lengths[i]) != MS_SUCCESS) { ret = MS_FAILURE; goto line_cleanup; } } else { msDrawLabel(map, image, *annopoints[i], label->annotext, label, layer->scalefactor); } } } } else { annopoints = msPolylineLabelPoint(anno_shape, minfeaturesize, label->repeatdistance, &angles, &lengths, &numpoints, label->anglemode); if (label->angle != 0) label->angle -= map->gt.rotation_angle; /* apply rotation angle */ for (i = 0; i < numpoints; i++) { if (label->anglemode != MS_NONE) label->angle = *angles[i]; /* angle derived from line overrides even the rotation value. */ if (layer->labelcache) { if (msAddLabel(map, label, layer->index, c, anno_shape, annopoints[i], NULL, *lengths[i]) != MS_SUCCESS) { ret = MS_FAILURE; goto line_cleanup; } } else { msDrawLabel(map, image, *annopoints[i], label->annotext, label, layer->scalefactor); } } } line_cleanup: /* clean up and reset */ if (annopaths) { free(annopaths); annopaths = NULL; } if (regularLines) { free(regularLines); regularLines = NULL; } if (annopoints) { for (j = 0; j < numpoints; j++) { if (annopoints[j]) free(annopoints[j]); if (angles[j]) free(angles[j]); if (lengths[j]) free(lengths[j]); } free(angles); free(annopoints); free(lengths); annopoints = NULL; angles = NULL; lengths = NULL; } if (ret == MS_FAILURE) { break; /* from the label looping */ } } /* next label */ } return ret; } int polygonLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape, shapeObj *anno_shape, shapeObj *unclipped_shape, int drawmode) { int c = shape->classindex; pointObj annopnt; int i; if(MS_DRAW_FEATURES(drawmode)) { for (i = 0; i < layer->class[c]->numstyles; i++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[i]->minscaledenom, layer->class[c]->styles[i]->maxscaledenom)) { if (layer->class[c]->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE) msDrawShadeSymbol(&map->symbolset, image, shape, layer->class[c]->styles[i], layer->scalefactor); else msDrawTransformedShape(map, &map->symbolset, image, unclipped_shape, layer->class[c]->styles[i], layer->scalefactor); } } } if(MS_DRAW_LABELS(drawmode)) { if (layer->class[c]->numlabels > 0) { double minfeaturesize = layer->class[c]->labels[0]->minfeaturesize * image->resolutionfactor; if (msPolygonLabelPoint(anno_shape, &annopnt, minfeaturesize) == MS_SUCCESS) { for (i = 0; i < layer->class[c]->numlabels; i++) if (layer->class[c]->labels[i]->angle != 0) layer->class[c]->labels[i]->angle -= map->gt.rotation_angle; /* TODO: is this correct ??? */ if (layer->labelcache) { if (msAddLabelGroup(map, layer->index, c, anno_shape, &annopnt, MS_MIN(shape->bounds.maxx - shape->bounds.minx, shape->bounds.maxy - shape->bounds.miny)) != MS_SUCCESS) { return MS_FAILURE; } } else { for (i = 0; i < layer->class[c]->numlabels; i++) msDrawLabel(map, image, annopnt, layer->class[c]->labels[i]->annotext, layer->class[c]->labels[i], layer->scalefactor); } } } } return MS_SUCCESS; } /* ** Function to render an individual shape, the style variable enables/disables the drawing of a single style ** versus a single style. This is necessary when drawing entire layers as proper overlay can only be achived ** through caching. "querymapMode" parameter is used to tell msBindLayerToShape to not override the ** QUERYMAP HILITE color. */ int msDrawShape(mapObj *map, layerObj *layer, shapeObj *shape, imageObj *image, int style, int drawmode) { int c,s,ret=MS_SUCCESS; shapeObj *anno_shape, *unclipped_shape = shape; int bNeedUnclippedShape = MS_FALSE; int bNeedUnclippedAnnoShape = MS_FALSE; int bShapeNeedsClipping = MS_TRUE; if(shape->numlines == 0 || shape->type == MS_SHAPE_NULL) return MS_SUCCESS; msDrawStartShape(map, layer, image, shape); c = shape->classindex; /* Before we do anything else, we will check for a rangeitem. If its there, we need to change the style's color to map the range to the shape */ for(s=0; sclass[c]->numstyles; s++) { styleObj *style = layer->class[c]->styles[s]; if(style->rangeitem != NULL) msShapeToRange((layer->class[c]->styles[s]), shape); } /* circle and point layers go through their own treatment */ if(layer->type == MS_LAYER_CIRCLE) { if(msBindLayerToShape(layer, shape, drawmode) != MS_SUCCESS) return MS_FAILURE; ret = circleLayerDrawShape(map,image,layer,shape); msDrawEndShape(map,layer,image,shape); return ret; } else if(layer->type == MS_LAYER_POINT || layer->type == MS_LAYER_RASTER) { if(msBindLayerToShape(layer, shape, drawmode) != MS_SUCCESS) return MS_FAILURE; ret = pointLayerDrawShape(map,image,layer,shape,drawmode); msDrawEndShape(map,layer,image,shape); return ret; } if (layer->type == MS_LAYER_POLYGON && shape->type != MS_SHAPE_POLYGON) { msSetError(MS_MISCERR, "Only polygon shapes can be drawn using a polygon layer definition.", "polygonLayerDrawShape()"); return (MS_FAILURE); } if (layer->type == MS_LAYER_LINE && shape->type != MS_SHAPE_POLYGON && shape->type != MS_SHAPE_LINE) { msSetError(MS_MISCERR, "Only polygon or line shapes can be drawn using a line layer definition.", "msDrawShape()"); return (MS_FAILURE); } #ifdef USE_PROJ if (layer->project && layer->transform == MS_TRUE && msProjectionsDiffer(&(layer->projection), &(map->projection))) msProjectShape(&layer->projection, &map->projection, shape); else layer->project = MS_FALSE; #endif /* check if we'll need the unclipped shape */ if (shape->type != MS_SHAPE_POINT) { if(MS_DRAW_FEATURES(drawmode)) { for (s = 0; s < layer->class[c]->numstyles; s++) { styleObj *style = layer->class[c]->styles[s]; if (style->_geomtransform.type != MS_GEOMTRANSFORM_NONE) bNeedUnclippedShape = MS_TRUE; } } /* check if we need to clip the shape */ if (shape->bounds.minx < map->extent.minx || shape->bounds.miny < map->extent.miny || shape->bounds.maxx > map->extent.maxx || shape->bounds.maxy > map->extent.maxy) { bShapeNeedsClipping = MS_TRUE; } if(MS_DRAW_LABELS(drawmode) && MS_DRAW_UNCLIPPED_LABELS(drawmode)) { bNeedUnclippedAnnoShape = MS_TRUE; bNeedUnclippedShape = MS_TRUE; } if(MS_DRAW_UNCLIPPED_LINES(drawmode)) { bShapeNeedsClipping = MS_FALSE; } } else { bShapeNeedsClipping = MS_FALSE; } if(layer->transform == MS_TRUE && bShapeNeedsClipping) { /* compute the size of the clipping buffer, in pixels. This buffer must account for the size of symbols drawn to avoid artifacts around the image edges */ int clip_buf = 0; int s; rectObj cliprect; for (s=0;sclass[c]->numstyles;s++) { double maxsize, maxunscaledsize; symbolObj *symbol; styleObj *style = layer->class[c]->styles[s]; if (!MS_IS_VALID_ARRAY_INDEX(style->symbol, map->symbolset.numsymbols)) { msSetError(MS_SYMERR, "Invalid symbol index: %d", "msDrawShape()", style->symbol); return MS_FAILURE; } symbol = map->symbolset.symbol[style->symbol]; if (symbol->type == MS_SYMBOL_PIXMAP) { if (MS_SUCCESS != msPreloadImageSymbol(MS_MAP_RENDERER(map), symbol)) return MS_FAILURE; } else if (symbol->type == MS_SYMBOL_SVG) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msDrawShape()"); return MS_FAILURE; #endif } maxsize = MS_MAX(msSymbolGetDefaultSize(symbol), MS_MAX(style->size, style->width)); maxunscaledsize = MS_MAX(style->minsize*image->resolutionfactor, style->minwidth*image->resolutionfactor); if(shape->type == MS_SHAPE_POLYGON && !IS_PARALLEL_OFFSET(style->offsety)) { maxsize += MS_MAX(fabs(style->offsety),fabs(style->offsetx)); } clip_buf = MS_MAX(clip_buf,MS_NINT(MS_MAX(maxsize * layer->scalefactor, maxunscaledsize) + 1)); } /* if we need a copy of the unclipped shape, transform first, then clip to avoid transforming twice */ if(bNeedUnclippedShape) { msTransformShape(shape, map->extent, map->cellsize, image); if(shape->numlines == 0) return MS_SUCCESS; msComputeBounds(shape); /* TODO: there's an optimization here that can be implemented: - no need to allocate unclipped_shape for each call to this function - the calls to msClipXXXRect will discard the original lineObjs, whereas we have just copied them because they where needed. These two functions could be changed so they are instructed not to free the original lineObjs. */ unclipped_shape = (shapeObj *) msSmallMalloc(sizeof (shapeObj)); msInitShape(unclipped_shape); msCopyShape(shape, unclipped_shape); if(shape->type == MS_SHAPE_POLYGON) { /* #179: additional buffer for polygons */ clip_buf += 2; } cliprect.minx = cliprect.miny = -clip_buf; cliprect.maxx = image->width + clip_buf; cliprect.maxy = image->height + clip_buf; if(shape->type == MS_SHAPE_POLYGON) { msClipPolygonRect(shape, cliprect); } else { assert(shape->type == MS_SHAPE_LINE); msClipPolylineRect(shape, cliprect); } if(bNeedUnclippedAnnoShape) { anno_shape = unclipped_shape; } else { anno_shape = shape; } } else { /* clip first, then transform. This means we are clipping in geographical space */ double clip_buf_d; if(shape->type == MS_SHAPE_POLYGON) { /* * add a small buffer around the cliping rectangle to * avoid lines around the edges : #179 */ clip_buf += 2; } clip_buf_d = clip_buf * map->cellsize; cliprect.minx = map->extent.minx - clip_buf_d; cliprect.miny = map->extent.miny - clip_buf_d; cliprect.maxx = map->extent.maxx + clip_buf_d; cliprect.maxy = map->extent.maxy + clip_buf_d; if(shape->type == MS_SHAPE_POLYGON) { msClipPolygonRect(shape, cliprect); } else { assert(shape->type == MS_SHAPE_LINE); msClipPolylineRect(shape, cliprect); } msTransformShape(shape, map->extent, map->cellsize, image); msComputeBounds(shape); anno_shape = shape; } } else { /* the shape is fully in the map extent, * or is a point type layer where out of bounds points are treated differently*/ if (layer->transform == MS_TRUE) { msTransformShape(shape, map->extent, map->cellsize, image); msComputeBounds(shape); } else { msOffsetShapeRelativeTo(shape, layer); } anno_shape = shape; } if(shape->numlines == 0) { ret = MS_SUCCESS; /* error message is set in msBindLayerToShape() */ goto draw_shape_cleanup; } if(msBindLayerToShape(layer, shape, drawmode) != MS_SUCCESS) { ret = MS_FAILURE; /* error message is set in msBindLayerToShape() */ goto draw_shape_cleanup; } switch(layer->type) { case MS_LAYER_ANNOTATION: if(MS_DRAW_LABELS(drawmode)) ret = annotationLayerDrawShape(map, image, layer, anno_shape); else ret = MS_SUCCESS; break; case MS_LAYER_LINE: ret = lineLayerDrawShape(map, image, layer, shape, anno_shape, unclipped_shape, style, drawmode); break; case MS_LAYER_POLYGON: ret = polygonLayerDrawShape(map, image, layer, shape, anno_shape, unclipped_shape, drawmode); break; case MS_LAYER_POINT: case MS_LAYER_RASTER: assert(0); //bug ! default: msSetError(MS_MISCERR, "Unknown layer type.", "msDrawShape()"); ret = MS_FAILURE; } draw_shape_cleanup: msDrawEndShape(map,layer,image,shape); if(unclipped_shape != shape) { msFreeShape(unclipped_shape); msFree(unclipped_shape); } return ret; } /* ** Function to render an individual point, used as a helper function for mapscript only. Since a point ** can't carry attributes you can't do attribute based font size or angle. */ int msDrawPoint(mapObj *map, layerObj *layer, pointObj *point, imageObj *image, int classindex, char *labeltext) { int s; classObj *theclass=layer->class[classindex]; labelObj *label=NULL; #ifdef USE_PROJ if(layer->transform == MS_TRUE && layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection))) msProjectPoint(&layer->projection, &map->projection, point); else layer->project = MS_FALSE; #endif if(labeltext && theclass->numlabels > 0) { label = theclass->labels[0]; msFree(label->annotext); /* free any previously allocated annotation text */ if(labeltext && (label->encoding || label->wrap || label->maxlength)) label->annotext = msTransformLabelText(map,label,labeltext); /* apply wrap character and encoding to the label text */ else label->annotext = msStrdup(labeltext); } switch(layer->type) { case MS_LAYER_ANNOTATION: if(layer->transform == MS_TRUE) { if(!msPointInRect(point, &map->extent)) return(0); point->x = MS_MAP2IMAGE_X(point->x, map->extent.minx, map->cellsize); point->y = MS_MAP2IMAGE_Y(point->y, map->extent.maxy, map->cellsize); } else msOffsetPointRelativeTo(point, layer); if(labeltext) { if(layer->labelcache) { if(msAddLabel(map, label, layer->index, classindex, NULL, point, NULL, -1) != MS_SUCCESS) return(MS_FAILURE); } else { if(theclass->numstyles > 0 && MS_VALID_COLOR(theclass->styles[0]->color)) { for(s=0; snumstyles; s++) { if(msScaleInBounds(map->scaledenom, theclass->styles[s]->minscaledenom, theclass->styles[s]->maxscaledenom)) msDrawMarkerSymbol(&map->symbolset, image, point, theclass->styles[s], layer->scalefactor); } } msDrawLabel(map, image, *point, label->annotext, label, layer->scalefactor); } } break; case MS_LAYER_POINT: if(layer->transform == MS_TRUE) { if(!msPointInRect(point, &map->extent)) return(0); point->x = MS_MAP2IMAGE_X(point->x, map->extent.minx, map->cellsize); point->y = MS_MAP2IMAGE_Y(point->y, map->extent.maxy, map->cellsize); } else msOffsetPointRelativeTo(point, layer); for(s=0; snumstyles; s++) { if(msScaleInBounds(map->scaledenom, theclass->styles[s]->minscaledenom, theclass->styles[s]->maxscaledenom)) msDrawMarkerSymbol(&map->symbolset, image, point, theclass->styles[s], layer->scalefactor); } if(labeltext) { if(layer->labelcache) { if(msAddLabel(map, label, layer->index, classindex, NULL, point, NULL, -1) != MS_SUCCESS) return(MS_FAILURE); } else msDrawLabel(map, image, *point, label->annotext, label, layer->scalefactor); } break; default: break; /* don't do anything with layer of other types */ } return(MS_SUCCESS); /* all done, no cleanup */ } /* ** Draws a single label independently of the label cache. No collision avoidance is performed. */ int msDrawLabel(mapObj *map, imageObj *image, pointObj labelPnt, char *string, labelObj *label, double scalefactor) { shapeObj labelPoly; lineObj labelPolyLine; pointObj labelPolyPoints[5]; int needLabelPoly=MS_TRUE; int needLabelPoint=MS_TRUE; int label_offset_x, label_offset_y; double size; rectObj r; if(!string) return MS_SUCCESS; /* not an error, just don't need to do anything more */ if(strlen(string) == 0) return MS_SUCCESS; /* not an error, just don't need to do anything more */ if(label->status == MS_OFF) return(MS_SUCCESS); /* not an error */ if(label->type == MS_TRUETYPE) { size = label->size * scalefactor; size = MS_MAX(size, label->minsize*image->resolutionfactor); size = MS_MIN(size, label->maxsize*image->resolutionfactor); } else { size = label->size; } if(msGetLabelSize(map, label, string, size, &r, NULL)!= MS_SUCCESS) return MS_FAILURE; label_offset_x = label->offsetx*scalefactor; label_offset_y = label->offsety*scalefactor; if(label->position != MS_XY) { pointObj p; if(label->numstyles > 0) { int i; for(i=0; inumstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { msDrawMarkerSymbol(&map->symbolset, image, &labelPnt, label->styles[i], scalefactor); } else if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if(needLabelPoly) { labelPoly.line = &labelPolyLine; /* setup the label polygon structure */ labelPoly.numlines = 1; labelPoly.line->point = labelPolyPoints; labelPoly.line->numpoints = 5; p = get_metrics_line(&labelPnt, label->position, r, label_offset_x, label_offset_y, label->angle, 1, labelPoly.line); needLabelPoint = MS_FALSE; /* don't re-compute */ needLabelPoly = MS_FALSE; } msDrawShadeSymbol(&map->symbolset, image, &labelPoly, label->styles[i], scalefactor); } else { /* TODO: need error msg about unsupported geomtransform */ return MS_FAILURE; } } } if(needLabelPoint) p = get_metrics_line(&labelPnt, label->position, r, label_offset_x, label_offset_y, label->angle, 0, NULL); /* draw the label text */ msDrawText(image, p, string, label, &(map->fontset), scalefactor); /* actually draw the label */ } else { labelPnt.x += label_offset_x; labelPnt.y += label_offset_y; if(label->numstyles > 0) { int i; for(i=0; inumstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) msDrawMarkerSymbol(&map->symbolset, image, &labelPnt, label->styles[i], scalefactor); else if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if(needLabelPoly) { labelPoly.line = &labelPolyLine; /* setup the label polygon structure */ labelPoly.numlines = 1; labelPoly.line->point = labelPolyPoints; labelPoly.line->numpoints = 5; get_metrics_line(&labelPnt, label->position, r, label_offset_x, label_offset_y, label->angle, 1, labelPoly.line); needLabelPoly = MS_FALSE; /* don't re-compute */ } msDrawShadeSymbol(&map->symbolset, image, &labelPoly, label->styles[i], scalefactor); } else { /* TODO: need error msg about unsupported geomtransform */ return MS_FAILURE; } } } /* draw the label text */ msDrawText(image, labelPnt, string, label, &(map->fontset), scalefactor); /* actually draw the label */ } return MS_SUCCESS; } /* private shortcut function to try a leader offsetted label */ void offsetAndTest(imageObj*image, mapObj *map, labelCacheMemberObj *cachePtr, double ox, double oy, int priority, int label_idx, shapeObj *unoffsetedpoly) { /* offset cachePtr->poly and cachePtr->point */ int i,j; for(i=cachePtr->poly->numlines-1; i>=0; i--) { for(j=cachePtr->poly->line[i].numpoints-1; j>=0; j--) { cachePtr->poly->line[i].point[j].x = unoffsetedpoly->line[i].point[j].x + ox; cachePtr->poly->line[i].point[j].y = unoffsetedpoly->line[i].point[j].y + oy; } } cachePtr->poly->bounds.minx = unoffsetedpoly->bounds.minx + ox; cachePtr->poly->bounds.miny = unoffsetedpoly->bounds.miny + oy; cachePtr->poly->bounds.maxx = unoffsetedpoly->bounds.maxx + ox; cachePtr->poly->bounds.maxy = unoffsetedpoly->bounds.maxy + oy; cachePtr->point.x = cachePtr->leaderline->point[0].x + ox; cachePtr->point.y = cachePtr->leaderline->point[0].y + oy; /* set the second point of the leader line */ cachePtr->leaderline->point[1].x = cachePtr->point.x; cachePtr->leaderline->point[1].y = cachePtr->point.y; /* compute leader line bbox */ if(ox>0) { cachePtr->leaderbbox->minx = cachePtr->leaderline->point[0].x; cachePtr->leaderbbox->maxx = cachePtr->point.x; } else { cachePtr->leaderbbox->maxx = cachePtr->leaderline->point[0].x; cachePtr->leaderbbox->minx = cachePtr->point.x; } if(oy>0) { cachePtr->leaderbbox->miny = cachePtr->leaderline->point[0].y; cachePtr->leaderbbox->maxy = cachePtr->point.y; } else { cachePtr->leaderbbox->maxy = cachePtr->leaderline->point[0].y; cachePtr->leaderbbox->miny = cachePtr->point.y; } cachePtr->status = msTestLabelCacheCollisions(map, cachePtr, cachePtr->poly, cachePtr->labels[0].mindistance,priority,-label_idx); if(cachePtr->status) { int ll; for(ll=0; llnumlabels; ll++) { cachePtr->labels[ll].annopoint.x += ox; cachePtr->labels[ll].annopoint.y += oy; if(cachePtr->labels[ll].annopoly) { for(i=0; i<5; i++) { cachePtr->labels[ll].annopoly->line[0].point[i].x += ox; cachePtr->labels[ll].annopoly->line[0].point[i].y += oy; } } } } } int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority) { int retval = MS_SUCCESS; int l; labelCacheObj *labelcache = &(map->labelcache); labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr; assert(MS_RENDERER_PLUGIN(image->format)); cacheslot = &(labelcache->slots[priority]); for(l=cacheslot->numlabels-1; l>=0; l--) { cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */ if(cachePtr->status == MS_FALSE && !cachePtr->labelpath && cachePtr->poly) { /* only test regular labels that have had their bounding box computed and that haven't been rendered */ classObj *classPtr = (GET_CLASS(map,cachePtr->layerindex,cachePtr->classindex)); layerObj *layerPtr = (GET_LAYER(map,cachePtr->layerindex)); if(classPtr->leader.maxdistance) { /* only test labels that can be offsetted */ shapeObj origPoly; int steps,i; if(cachePtr->point.x < labelcache->gutter || cachePtr->point.y < labelcache->gutter || cachePtr->point.x >= image->width - labelcache->gutter || cachePtr->point.y >= image->height - labelcache->gutter) { /* don't look for leaders if point is in edge buffer as the leader line would end up chopped off */ continue; } /* TODO: check the cachePtr->point doesn't intersect a rendered label before event trying to offset ?*/ /* TODO: if the entry has a single label and it has position != CC, * recompute the cachePtr->poly and labelPtr->annopoint using POSITION CC */ msInitShape(&origPoly); msCopyShape(cachePtr->poly,&origPoly); cachePtr->leaderline = msSmallMalloc(sizeof(lineObj)); cachePtr->leaderline->numpoints = 2; cachePtr->leaderline->point = msSmallMalloc(2*sizeof(pointObj)); cachePtr->leaderline->point[0] = cachePtr->point; cachePtr->leaderbbox = msSmallMalloc(sizeof(rectObj)); steps = classPtr->leader.maxdistance / classPtr->leader.gridstep; #define x0 (cachePtr->leaderline->point[0].x) #define y0 (cachePtr->leaderline->point[0].y) #define gridstepsc (classPtr->leader.gridstep) #define otest(ox,oy) if((x0+(ox)) >= labelcache->gutter &&\ (y0+(oy)) >= labelcache->gutter &&\ (x0+(ox)) < image->width + labelcache->gutter &&\ (y0+(oy)) < image->height + labelcache->gutter) {\ offsetAndTest(image,map,cachePtr,(ox),(oy),priority,l,&origPoly); \ if(cachePtr->status) break;\ } /* loop through possible offsetted positions */ for(i=1; i<=steps; i++) { /* test the intermediate points on the ring */ /* (points marked "0" are the ones being tested) X00X00X 0XXXXX0 0XXXXX0 XXX.XXX 0XXXXX0 0XXXXX0 X00X00X */ int j; for(j=1; jstatus) { int ll; shapeObj labelLeader; /* label polygon (bounding box, possibly rotated) */ labelLeader.line = cachePtr->leaderline; /* setup the label polygon structure */ labelLeader.numlines = 1; for(ll=0; llleader.numstyles; ll++) { msDrawLineSymbol(&map->symbolset, image,&labelLeader , classPtr->leader.styles[ll], layerPtr->scalefactor); } for(ll=0; llnumlabels; ll++) { labelObj *labelPtr = &(cachePtr->labels[ll]); /* here's where we draw the label styles */ if(labelPtr->numstyles > 0) { for(i=0; inumstyles; i++) { if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) msDrawMarkerSymbol(&map->symbolset, image, &(cachePtr->point), labelPtr->styles[i], layerPtr->scalefactor); else if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { msDrawShadeSymbol(&map->symbolset, image, labelPtr->annopoly, labelPtr->styles[i], layerPtr->scalefactor); } else { msSetError(MS_MISCERR,"Labels only support LABELPNT and LABELPOLY GEOMTRANSFORMS", "msDrawOffsettedLabels()"); return MS_FAILURE; } } } if(labelPtr->annotext) msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */ } /* TODO: draw cachePtr->marker, but where ? */ /* styleObj tstyle; static int foo =0; if(!foo) { srand(time(NULL)); foo = 1; initStyle(&tstyle); tstyle.width = 1; tstyle.color.alpha = 255; } tstyle.color.red = random()%255; tstyle.color.green = random()%255; tstyle.color.blue =random()%255; msDrawLineSymbol(&map->symbolset, image, cachePtr->poly, &tstyle, layerPtr->scalefactor); */ } else { msFree(cachePtr->leaderline->point); msFree(cachePtr->leaderline); msFree(cachePtr->leaderbbox); cachePtr->leaderline = NULL; } msFreeShape(&origPoly); } } } return retval; } int computeMarkerPoly(mapObj *map, imageObj *image, labelCacheMemberObj *cachePtr, labelCacheSlotObj *cacheslot, shapeObj *markerPoly) { layerObj *layerPtr = (GET_LAYER(map, cachePtr->layerindex)); if(layerPtr->type == MS_LAYER_ANNOTATION && cachePtr->numstyles > 0) { /* TODO: at the moment only checks the bottom (first) marker style since it *should* be the largest, perhaps we should check all of them and build a composite size */ double marker_width,marker_height; pointObj *point = markerPoly->line[0].point; if(msGetMarkerSize(&map->symbolset, &(cachePtr->styles[0]), &marker_width, &marker_height, layerPtr->scalefactor) != MS_SUCCESS) return MS_FAILURE; markerPoly->numlines = 1; markerPoly->bounds.minx = cachePtr->point.x - .5 * marker_width; markerPoly->bounds.miny = cachePtr->point.y - .5 * marker_height; markerPoly->bounds.maxx = markerPoly->bounds.minx + marker_width; markerPoly->bounds.maxy = markerPoly->bounds.miny + marker_height; point[0].x = markerPoly->bounds.minx; point[0].y = markerPoly->bounds.miny; point[1].x = markerPoly->bounds.minx; point[1].y = markerPoly->bounds.maxy; point[2].x = markerPoly->bounds.maxx; point[2].y = markerPoly->bounds.maxy; point[3].x = markerPoly->bounds.maxx; point[3].y = markerPoly->bounds.miny; point[4].x = markerPoly->bounds.minx; point[4].y = markerPoly->bounds.miny; } return MS_SUCCESS; } void fastComputeBounds(shapeObj *shape) { int i,j; shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { shape->bounds.minx = MS_MIN(shape->bounds.minx, shape->line[i].point[j].x); shape->bounds.maxx = MS_MAX(shape->bounds.maxx, shape->line[i].point[j].x); shape->bounds.miny = MS_MIN(shape->bounds.miny, shape->line[i].point[j].y); shape->bounds.maxy = MS_MAX(shape->bounds.maxy, shape->line[i].point[j].y); } } } int computeLabelMarkerPoly(mapObj *map, imageObj *img, labelCacheMemberObj *cachePtr, labelObj *label, shapeObj *markerPoly) { int i; layerObj *layerPtr = (GET_LAYER(map, cachePtr->layerindex)); markerPoly->numlines = 0; for (i=0; inumstyles; i++) { styleObj *style = label->styles[i]; if(style->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT && style->symbol < map->symbolset.numsymbols && style->symbol > 0) { double sx,sy; pointObj *point; int p; double aox,aoy; symbolObj *symbol = map->symbolset.symbol[style->symbol]; if(msGetMarkerSize(&map->symbolset, style, &sx, &sy, layerPtr->scalefactor) != MS_SUCCESS) return MS_FAILURE; point = markerPoly->line[0].point; point[0].x = sx / 2.0; point[0].y = sy / 2.0; point[1].x = point[0].x; point[1].y = -point[0].y; point[2].x = -point[0].x; point[2].y = -point[0].y; point[3].x = -point[0].x; point[3].y = point[0].y; point[4].x = point[0].x; point[4].y = point[0].y; if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) { aox = (0.5 - symbol->anchorpoint_x) * sx; aoy = (0.5 - symbol->anchorpoint_y) * sy; for(p=0; p<5; p++) { point[p].x += aox; point[p].y += aoy; } } if(style->angle) { double rot = -style->angle * MS_DEG_TO_RAD; double sina = sin(rot); double cosa = cos(rot); for(p=0; p<5; p++) { double tmpx = point[p].x; point[p].x = point[p].x * cosa - point[p].y * sina; point[p].y = tmpx * sina + point[p].y * cosa; } } aox = cachePtr->point.x + style->offsetx * layerPtr->scalefactor; aoy = cachePtr->point.y + style->offsety * layerPtr->scalefactor; for(p=0; p<5; p++) { point[p].x += aox; point[p].y += aoy; } markerPoly->numlines = 1; fastComputeBounds(markerPoly); break; } } return MS_SUCCESS; } int msDrawLabelCache(imageObj *image, mapObj *map) { int nReturnVal = MS_SUCCESS; if(image) { if(MS_RENDERER_PLUGIN(image->format)) { int i, l, ll, priority; rectObj r; shapeObj marker_poly; lineObj marker_line; pointObj marker_points[5]; shapeObj label_marker_poly; lineObj label_marker_line; pointObj label_marker_points[5]; shapeObj metrics_poly; lineObj metrics_line; pointObj metrics_points[5]; double marker_offset_x, marker_offset_y; int label_offset_x, label_offset_y; int label_mindistance=-1, label_buffer=0; const char *value; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; labelObj *labelPtr=NULL; /* holds the contour of the label styles that correspond to markers */ marker_line.point = marker_points; marker_line.numpoints = 5; msInitShape(&marker_poly); marker_poly.line = &marker_line; marker_poly.numlines = 0; marker_poly.type = MS_SHAPE_POLYGON; label_marker_line.point = label_marker_points; label_marker_line.numpoints = 5; msInitShape(&label_marker_poly); label_marker_poly.line = &label_marker_line; label_marker_poly.numlines = 0; label_marker_poly.type = MS_SHAPE_POLYGON; metrics_line.point = metrics_points; metrics_line.numpoints = 5; msInitShape(&metrics_poly); metrics_poly.line = &metrics_line; metrics_poly.numlines = 1; metrics_poly.type = MS_SHAPE_POLYGON; /* Look for labelcache_map_edge_buffer map metadata * If set then the value defines a buffer (in pixels) along the edge of the * map image where labels can't fall */ if((value = msLookupHashTable(&(map->web.metadata), "labelcache_map_edge_buffer")) != NULL) { map->labelcache.gutter = MS_ABS(atoi(value)); if(map->debug) msDebug("msDrawLabelCache(): labelcache_map_edge_buffer = %d\n", map->labelcache.gutter); } for(priority=MS_MAX_LABEL_PRIORITY-1; priority>=0; priority--) { labelCacheSlotObj *cacheslot; cacheslot = &(map->labelcache.slots[priority]); for(l=cacheslot->numlabels-1; l>=0; l--) { double scalefactor,size; cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */ layerPtr = (GET_LAYER(map, cachePtr->layerindex)); /* set a couple of other pointers, avoids nasty references */ classPtr = (GET_CLASS(map, cachePtr->layerindex, cachePtr->classindex)); if (layerPtr->type == MS_LAYER_ANNOTATION && (cachePtr->numlabels > 1 || classPtr->leader.maxdistance)) { msSetError(MS_MISCERR, "Multiple Labels and/or LEADERs are not supported with annotation layers", "msDrawLabelCache()"); return MS_FAILURE; } /* TODO: classes with a labelpath do not respect multi label rendering */ if(cachePtr->labelpath) { /* path-based label */ labelPtr = &(cachePtr->labels[0]); if(labelPtr->status != MS_ON) continue; /* skip this label */ if(!labelPtr->annotext) continue; /* skip this label, nothing to with curved labels when there is nothing to draw */ /* path-following labels *must* be TRUETYPE */ size = labelPtr->size * layerPtr->scalefactor; size = MS_MAX(size, labelPtr->minsize*image->resolutionfactor); size = MS_MIN(size, labelPtr->maxsize*image->resolutionfactor); scalefactor = size / labelPtr->size; label_buffer = (labelPtr->buffer*image->resolutionfactor); label_mindistance = (labelPtr->mindistance*image->resolutionfactor); /* compare against image bounds, rendered labels and markers (sets cachePtr->status), if FORCE=TRUE then skip it */ cachePtr->status = MS_TRUE; assert(cachePtr->poly == NULL); if(!labelPtr->force) cachePtr->status = msTestLabelCacheCollisions(map,cachePtr,&cachePtr->labelpath->bounds,label_mindistance,priority,l); if(!cachePtr->status) { msFreeShape(&cachePtr->labelpath->bounds); continue; } else { /* take ownership of cachePtr->poly*/ cachePtr->poly = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(cachePtr->poly); cachePtr->poly->type = MS_SHAPE_POLYGON; cachePtr->poly->numlines = cachePtr->labelpath->bounds.numlines; cachePtr->poly->line = cachePtr->labelpath->bounds.line; cachePtr->labelpath->bounds.numlines = 0; cachePtr->labelpath->bounds.line = NULL; cachePtr->poly->bounds.minx = cachePtr->labelpath->bounds.bounds.minx; cachePtr->poly->bounds.miny = cachePtr->labelpath->bounds.bounds.miny; cachePtr->poly->bounds.maxx = cachePtr->labelpath->bounds.bounds.maxx; cachePtr->poly->bounds.maxy = cachePtr->labelpath->bounds.bounds.maxy; msFreeShape(&cachePtr->labelpath->bounds); } msDrawTextLine(image, labelPtr->annotext, labelPtr, cachePtr->labelpath, &(map->fontset), layerPtr->scalefactor); /* Draw the curved label */ } else { /* point-based label */ scalefactor = layerPtr->scalefactor; /* FIXME avoid compiler warning, see also #4408 */ marker_offset_x = marker_offset_y = 0; /* assume no marker */ /* compute label bbox of a marker used in an annotation layer and/or * the offset needed for point layer with markerPtr */ marker_poly.numlines = 0; if(layerPtr->type == MS_LAYER_ANNOTATION) { if(computeMarkerPoly(map,image,cachePtr,cacheslot,&marker_poly)!=MS_SUCCESS) return MS_FAILURE; if(marker_poly.numlines) { marker_offset_x = (marker_poly.bounds.maxx-marker_poly.bounds.minx)/2.0; marker_offset_y = (marker_poly.bounds.maxy-marker_poly.bounds.miny)/2.0; /* if this is an annotation layer, transfer the markerPoly */ if( MS_OFF == msTestLabelCacheCollisions(map, cachePtr, &marker_poly, 0,priority, l)) { continue; /* the marker collided, no point continuing */ } } } else if (layerPtr->type == MS_LAYER_POINT && cachePtr->markerid!=-1) { /* there is a marker already in the image that we need to account for */ markerCacheMemberObj *markerPtr = &(cacheslot->markers[cachePtr->markerid]); /* point to the right spot in the marker cache*/ marker_offset_x = (markerPtr->poly->bounds.maxx-markerPtr->poly->bounds.minx)/2.0; marker_offset_y = (markerPtr->poly->bounds.maxy-markerPtr->poly->bounds.miny)/2.0; } /* ** all other cases *could* have multiple labels defined */ cachePtr->status = MS_OFF; /* assume this cache element *can't* be placed */ for(ll=0; llnumlabels; ll++) { /* RFC 77 TODO: Still may want to step through backwards... */ int label_marker_status = MS_ON; labelPtr = &(cachePtr->labels[ll]); labelPtr->status = MS_OFF; /* first check if there's anything to do with this label */ if(!labelPtr->annotext) { int s; for(s=0; snumstyles; s++) { if(labelPtr->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) break; } if(s == labelPtr->numstyles) { /* no label text, and no markers to render, skip this label */ labelPtr->status = MS_ON; continue; } } /* compute the poly of the label styles */ if(computeLabelMarkerPoly(map,image,cachePtr,labelPtr,&label_marker_poly)!=MS_SUCCESS) return MS_FAILURE; if(label_marker_poly.numlines) { if(cachePtr->numlabels > 1) { /* FIXME this test doesn't seem right, should probably check if we have an annotation layer with a regular style defined */ marker_offset_x = (label_marker_poly.bounds.maxx-label_marker_poly.bounds.minx)/2.0; marker_offset_y = (label_marker_poly.bounds.maxy-label_marker_poly.bounds.miny)/2.0; } else { /* we might be using an old style behavior with a markerPtr */ marker_offset_x = MS_MAX(marker_offset_x,(label_marker_poly.bounds.maxx-label_marker_poly.bounds.minx)/2.0); marker_offset_y = MS_MAX(marker_offset_y,(label_marker_poly.bounds.maxy-label_marker_poly.bounds.miny)/2.0); } /* add marker to cachePtr->poly */ if(labelPtr->force != MS_TRUE) { label_marker_status = msTestLabelCacheCollisions(map, cachePtr,&label_marker_poly, 0,priority, l); } if(label_marker_status == MS_OFF && !(labelPtr->force || classPtr->leader.maxdistance)) break; /* the marker collided, break from multi-label loop */ } if(labelPtr->annotext) { /* compute label size */ if(labelPtr->type == MS_TRUETYPE) { size = labelPtr->size * layerPtr->scalefactor; size = MS_MAX(size, labelPtr->minsize*image->resolutionfactor); size = MS_MIN(size, labelPtr->maxsize*image->resolutionfactor); scalefactor = size / labelPtr->size; } else { size = labelPtr->size; scalefactor = 1; } if(msGetLabelSize(map, labelPtr, labelPtr->annotext, size, &r, NULL) != MS_SUCCESS) return MS_FAILURE; /* if our label has an outline, adjust the marker offset so the outlinecolor does * not bleed into the marker */ if(marker_offset_x && MS_VALID_COLOR(labelPtr->outlinecolor)) { marker_offset_x += labelPtr->outlinewidth/2.0; marker_offset_y += labelPtr->outlinewidth/2.0; } if(labelPtr->autominfeaturesize && (cachePtr->featuresize != -1) && ((r.maxx-r.minx) > cachePtr->featuresize)) { /* label too large relative to the feature */ /* this label cannot be rendered, go on to next cachePtr */ break; /* TODO: treat the case with multiple labels and/or leader lines */ } /* apply offset and buffer settings */ if(labelPtr->anglemode != MS_FOLLOW) { label_offset_x = labelPtr->offsetx*scalefactor; label_offset_y = labelPtr->offsety*scalefactor; } else { label_offset_x = 0; label_offset_y = 0; } label_buffer = (labelPtr->buffer*image->resolutionfactor); label_mindistance = (labelPtr->mindistance*image->resolutionfactor); #ifdef oldcode /* adjust the baseline (see #1449) */ if(labelPtr->type == MS_TRUETYPE) { char *lastline = strrchr(labelPtr->annotext,'\n'); if(!lastline || !*(++lastline)) { label_offset_y += ((r.miny + r.maxy) + size) / 2.0; } else { rectObj rect2; /* bbox of first line only */ msGetLabelSize(map, labelPtr, lastline, size, &rect2, NULL); label_offset_y += ((rect2.miny+rect2.maxy) + size) / 2.0; } } #endif /* compute the label annopoly if we need to render the background billboard */ if(labelPtr->numstyles > 0) { for(i=0; inumstyles; i++) { if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { /* initialize the annotation polygon */ labelPtr->annopoly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(labelPtr->annopoly); labelPtr->annopoly->line = (lineObj *) malloc(sizeof(lineObj)); labelPtr->annopoly->numlines = 1; labelPtr->annopoly->line->point = (pointObj *) malloc(5*sizeof(pointObj)); labelPtr->annopoly->line->numpoints = 5; break; } } } } /* TODO: no point in using auto positionning if the marker cannot be placed? */ if(labelPtr->annotext && labelPtr->position == MS_AUTO) { /* no point in using auto positionning if the marker cannot be placed */ int positions[MS_POSITIONS_LENGTH], npositions=0; /* ** If the ANNOTATION has an associated marker then the position is handled like a point regardless of underlying shape type. (#2993) ** (Note: might be able to re-order this for more speed.) */ if((layerPtr->type == MS_LAYER_POLYGON && marker_offset_x==0 )|| (layerPtr->type == MS_LAYER_ANNOTATION && cachePtr->shapetype == MS_SHAPE_POLYGON && cachePtr->numstyles == 0)) { positions[0]=MS_CC; positions[1]=MS_UC; positions[2]=MS_LC; positions[3]=MS_CL; positions[4]=MS_CR; npositions = 5; } else if((layerPtr->type == MS_LAYER_LINE && marker_offset_x == 0) || (layerPtr->type == MS_LAYER_ANNOTATION && cachePtr->shapetype == MS_SHAPE_LINE && cachePtr->numstyles == 0)) { positions[0]=MS_UC; positions[1]=MS_LC; positions[2]=MS_CC; npositions = 3; } else { positions[0]=MS_UL; positions[1]=MS_LR; positions[2]=MS_UR; positions[3]=MS_LL; positions[4]=MS_CR; positions[5]=MS_CL; positions[6]=MS_UC; positions[7]=MS_LC; npositions = 8; } for(i=0; iannopoint = get_metrics_line(&(cachePtr->point), positions[i], r, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, labelPtr->angle, label_buffer, &metrics_line); fastComputeBounds(&metrics_poly); if(labelPtr->force == MS_OFF) { /* check for collisions inside the label group */ if(cachePtr->poly && cachePtr->poly->numlines && intersectLabelPolygons(&metrics_poly, cachePtr->poly) == MS_TRUE) { /* there was a self intersection */ continue; /* next position, labelPtr->status is left to MS_OFF */ } } labelPtr->status = msTestLabelCacheCollisions(map, cachePtr,&metrics_poly, label_mindistance,priority, l); /* found a suitable place for this label */ if(labelPtr->status == MS_TRUE || (i==(npositions-1) && labelPtr->force == MS_ON)) { labelPtr->status = MS_TRUE; /* set to true in case we are forcing it */ if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), positions[i], r, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, labelPtr->angle, 1, labelPtr->annopoly->line); break; /* ...out of position loop */ } } /* next position */ /* if position auto didn't manage to find a position, but we have leader configured * for the class, then we want to compute the label poly anyways */ if(classPtr->leader.maxdistance && labelPtr->status == MS_FALSE) { labelPtr->annopoint = get_metrics_line(&(cachePtr->point), MS_CC, r, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, labelPtr->angle, label_buffer, &metrics_line); if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), MS_CC, r, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, labelPtr->angle, 1, labelPtr->annopoly->line); fastComputeBounds(&metrics_poly); } } else { /* explicit position */ if(labelPtr->annotext) { if(labelPtr->position == MS_CC) { /* don't need the marker_offset */ labelPtr->annopoint = get_metrics_line(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, label_buffer, &metrics_line); if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, 1, labelPtr->annopoly->line); } else { labelPtr->annopoint = get_metrics_line(&(cachePtr->point), labelPtr->position, r, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, labelPtr->angle, label_buffer, &metrics_line); if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), labelPtr->position, r, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, labelPtr->angle, 1, labelPtr->annopoly->line); } fastComputeBounds(&metrics_poly); if(labelPtr->force == MS_ON) { labelPtr->status = MS_ON; } else { if(labelPtr->force == MS_OFF) { /* check for collisions inside the label group unless the label is FORCE GROUP */ if(cachePtr->poly && cachePtr->poly->numlines && intersectLabelPolygons(&metrics_poly, cachePtr->poly) == MS_TRUE) { break; /* collision within the group */ } } /* TODO: in case we have leader lines and multiple labels, there's no use in testing for labelcache collisions * once a first collision has been found. we only need to know that the label group has collided, and the * poly of the whole label group: if(label_group) testLabelCacheCollisions */ labelPtr->status = msTestLabelCacheCollisions(map, cachePtr,&metrics_poly, label_mindistance, priority, l); } } else { labelPtr->status = MS_ON; } } /* end POSITION AUTO vs Fixed POSITION */ if((!labelPtr->status || !label_marker_status) && classPtr->leader.maxdistance == 0) { labelPtr->status = MS_OFF; break; /* no point looking at more labels, unless their is a leader defined, in which case we still want to compute the full cachePtr->poly to be used for offset tests */ } else { if(!cachePtr->poly) { cachePtr->poly = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(cachePtr->poly); } if(labelPtr->annotext) { msAddLine(cachePtr->poly, metrics_poly.line); } if(label_marker_poly.numlines) { msAddLine(cachePtr->poly, label_marker_poly.line); } if(!label_marker_status) labelPtr->status = MS_OFF; } } /* next label in the group */ /* * cachePtr->status can be set to ON only if all it's labels didn't collide */ cachePtr->status = MS_ON; for(ll=0; llnumlabels; ll++) { if(cachePtr->labels[ll].status == MS_OFF) { cachePtr->status = MS_OFF; break; } } if(cachePtr->status == MS_ON || classPtr->leader.maxdistance) { /* add the marker polygon if we have one */ if(marker_poly.numlines) { if(!cachePtr->poly) { cachePtr->poly = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(cachePtr->poly); } msAddLine(cachePtr->poly, marker_poly.line); } if(cachePtr->poly) msComputeBounds(cachePtr->poly); } if(cachePtr->status == MS_OFF) continue; /* next label, as we had a collision */ if(layerPtr->type == MS_LAYER_ANNOTATION && cachePtr->numstyles > 0) { /* need to draw a marker */ for(i=0; inumstyles; i++) msDrawMarkerSymbol(&map->symbolset, image, &(cachePtr->point), &(cachePtr->styles[i]), layerPtr->scalefactor); } for(ll=0; llnumlabels; ll++) { labelPtr = &(cachePtr->labels[ll]); /* here's where we draw the label styles */ if(labelPtr->numstyles > 0) { for(i=0; inumstyles; i++) { if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) msDrawMarkerSymbol(&map->symbolset, image, &(cachePtr->point), labelPtr->styles[i], layerPtr->scalefactor); else if(labelPtr->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY && labelPtr->annotext) { msDrawShadeSymbol(&map->symbolset, image, labelPtr->annopoly, labelPtr->styles[i], scalefactor); /* FIXME: scalefactor here should be adjusted by the label minsize/maxsize adjustments of each label, not only the last one. see #4408 */ } else { msSetError(MS_MISCERR,"Labels only support LABELPNT and LABELPOLY GEOMTRANSFORMS", "msDrawLabelCAche()"); return MS_FAILURE; } } } if(labelPtr->annotext) msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */ } } /* end else */ } /* next label(group) from cacheslot */ msDrawOffsettedLabels(image, map, priority); } /* next priority */ #ifdef TBDEBUG styleObj tstyle; initStyle(&tstyle); tstyle.width = 1; tstyle.color.alpha = 255; tstyle.color.red = 255; tstyle.color.green = 0; tstyle.color.blue = 0; for(priority=MS_MAX_LABEL_PRIORITY-1; priority>=0; priority--) { labelCacheSlotObj *cacheslot; cacheslot = &(map->labelcache.slots[priority]); for(l=cacheslot->numlabels-1; l>=0; l--) { cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */ /* assert((cachePtr->poly == NULL && cachePtr->status == MS_OFF) || (cachePtr->poly && (cachePtr->status == MS_ON)); */ if(cachePtr->status) { msDrawLineSymbol(&map->symbolset, image, cachePtr->poly, &tstyle, layerPtr->scalefactor); } } } #endif return MS_SUCCESS; /* necessary? */ } } return nReturnVal; } /** * Generic function to tell the underline device that layer * drawing is stating */ void msImageStartLayer(mapObj *map, layerObj *layer, imageObj *image) { if (image) { if( MS_RENDERER_PLUGIN(image->format) ) { char *approximation_scale = msLayerGetProcessingKey( layer, "APPROXIMATION_SCALE" ); if(approximation_scale) { if(!strncasecmp(approximation_scale,"ROUND",5)) { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_ROUND; } else if(!strncasecmp(approximation_scale,"FULL",4)) { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_FULLRESOLUTION; } else if(!strncasecmp(approximation_scale,"SIMPLIFY",8)) { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_SIMPLIFY; } else { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_SNAPTOGRID; MS_IMAGE_RENDERER(image)->approximation_scale = atof(approximation_scale); } } else { MS_IMAGE_RENDERER(image)->transform_mode = MS_IMAGE_RENDERER(image)->default_transform_mode; MS_IMAGE_RENDERER(image)->approximation_scale = MS_IMAGE_RENDERER(image)->default_approximation_scale; } MS_IMAGE_RENDERER(image)->startLayer(image, map, layer); } else if( MS_RENDERER_IMAGEMAP(image->format) ) msImageStartLayerIM(map, layer, image); } } /** * Generic function to tell the underline device that layer * drawing is ending */ void msImageEndLayer(mapObj *map, layerObj *layer, imageObj *image) { if(image) { if( MS_RENDERER_PLUGIN(image->format) ) { MS_IMAGE_RENDERER(image)->endLayer(image,map,layer); } } } /** * Generic function to tell the underline device that shape * drawing is stating */ void msDrawStartShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape) { if (image) { if(MS_RENDERER_PLUGIN(image->format)) { if (image->format->vtable->startShape) image->format->vtable->startShape(image, shape); } } } /** * Generic function to tell the underline device that shape * drawing is ending */ void msDrawEndShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape) { if(MS_RENDERER_PLUGIN(image->format)) { if (image->format->vtable->endShape) image->format->vtable->endShape(image, shape); } } /** * take the value from the shape and use it to change the * color in the style to match the range map */ int msShapeToRange(styleObj *style, shapeObj *shape) { double fieldVal; char* fieldStr; /*first, get the value of the rangeitem, which should*/ /*evaluate to a double*/ fieldStr = shape->values[style->rangeitemindex]; if (fieldStr == NULL) { /*if there's not value, bail*/ return MS_FAILURE; } fieldVal = 0.0; fieldVal = atof(fieldStr); /*faith that it's ok -- */ /*should switch to strtod*/ return msValueToRange(style, fieldVal); } /** * Allow direct mapping of a value so that mapscript can use the * Ranges. The styls passed in is updated to reflect the right color * based on the fieldVal */ int msValueToRange(styleObj *style, double fieldVal) { double range; double scaledVal; range = style->maxvalue - style->minvalue; scaledVal = (fieldVal - style->minvalue)/range; /*At this point, we know where on the range we need to be*/ /*However, we don't know how to map it yet, since RGB(A) can */ /*Go up or down*/ style->color.red = (int)(MS_MAX(0,(MS_MIN(255, (style->mincolor.red + ((style->maxcolor.red - style->mincolor.red) * scaledVal)))))); style->color.green = (int)(MS_MAX(0,(MS_MIN(255,(style->mincolor.green + ((style->maxcolor.green - style->mincolor.green) * scaledVal)))))); style->color.blue = (int)(MS_MAX(0,(MS_MIN(255,(style->mincolor.blue + ((style->maxcolor.blue - style->mincolor.blue) * scaledVal)))))); #ifdef USE_GD style->color.pen = MS_PEN_UNSET; /*so it will recalculate pen*/ #endif /*( "msMapRange(): %i %i %i", style->color.red , style->color.green, style->color.blue);*/ #if ALPHACOLOR_ENABLED /*NO ALPHA RANGE YET style->color.alpha = style->mincolor.alpha + ((style->maxcolor.alpha - style->mincolor.alpha) * scaledVal);*/ #endif return MS_SUCCESS; } mapserver-6.4.1/maptclutf.c0000644002461700001440000002773112261257215015471 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of msUTF8ToUniChar() * Author: Daniel Morissette, Thomas Bonfort * * Note: * The source code of Tcl_UtfToUniChar() was borrowed from tclUtf.c * from the Tcl/Tk project. * * Website: http://www.tcl.tk/software/tcltk/ * Source download: http://prdownloads.sourceforge.net/tcl/tcl8.4.15-src.tar.gz * * See copyright and license terms below the standard MapServer license. * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * 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. ****************************************************************************/ /* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * This software is copyrighted by the Regents of the University of * California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState * Corporation and other parties. The following terms apply to all files * associated with the software unless explicitly disclaimed in * individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. * * GOVERNMENT USE: If you are acquiring this software on behalf of the * U.S. government, the Government shall have only "Restricted Rights" * in the software and related documentation as defined in the Federal * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you * are acquiring the software on behalf of the Department of Defense, the * software shall be classified as "Commercial Computer Software" and the * Government shall have only "Restricted Rights" as defined in Clause * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the * authors grant the U.S. Government and others acting in its behalf * permission to use and distribute the software in accordance with the * terms specified in this license. */ #include "mapserver.h" /* The source code of Tcl_UtfToUniChar() was borrowed from tclUtf.c * from the Tcl/Tk project: * Website: * http://www.tcl.tk/software/tcltk/ * Source download: * http://prdownloads.sourceforge.net/tcl/tcl8.4.15-src.tar.gz * Original License info follows below. */ /* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Id: tclUtf.c,v 1.30.2.3 2005/09/07 14:35:56 dgp Exp */ /******************* Tcl license.terms ********************* This software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. ***********************************************************/ #define TCL_UTF_MAX 6 #define Tcl_UniChar int /* * The following structures are used when mapping between Unicode (UCS-2) * and UTF-8. */ static const unsigned char totalBytes[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, #if TCL_UTF_MAX > 3 4,4,4,4,4,4,4,4, #else 1,1,1,1,1,1,1,1, #endif #if TCL_UTF_MAX > 4 5,5,5,5, #else 1,1,1,1, #endif #if TCL_UTF_MAX > 5 6,6,6,6 #else 1,1,1,1 #endif }; /* *--------------------------------------------------------------------------- * * Tcl_UtfToUniChar -- * * Extract the Tcl_UniChar represented by the UTF-8 string. Bad * UTF-8 sequences are converted to valid Tcl_UniChars and processing * continues. Equivalent to Plan 9 chartorune(). * * The caller must ensure that the source buffer is long enough that * this routine does not run off the end and dereference non-existent * memory looking for trail bytes. If the source buffer is known to * be '\0' terminated, this cannot happen. Otherwise, the caller * should call Tcl_UtfCharComplete() before calling this routine to * ensure that enough bytes remain in the string. * * Results: * *chPtr is filled with the Tcl_UniChar, and the return value is the * number of bytes from the UTF-8 string that were consumed. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static int ms_Tcl_UtfToUniChar(str, chPtr) register const char *str; /* The UTF-8 string. */ register Tcl_UniChar *chPtr; /* Filled with the Tcl_UniChar represented * by the UTF-8 string. */ { register int byte; int entitylgth; /*check if the string is an html entity (eg { or Ī)*/ if((entitylgth=msGetUnicodeEntity(str, chPtr))>0) return entitylgth; /* * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. */ byte = *((unsigned char *) str); if (byte < 0xC0) { /* * Handles properly formed UTF-8 characters between 0x01 and 0x7F. * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid * characters representing themselves. */ *chPtr = (Tcl_UniChar) byte; return 1; } else if (byte < 0xE0) { if ((str[1] & 0xC0) == 0x80) { /* * Two-byte-character lead-byte followed by a trail-byte. */ *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[1] & 0x3F)); return 2; } /* * A two-byte-character lead-byte not followed by trail-byte * represents itself. */ *chPtr = (Tcl_UniChar) byte; return 1; } else if (byte < 0xF0) { if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) { /* * Three-byte-character lead byte followed by two trail bytes. */ *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F)); return 3; } /* * A three-byte-character lead-byte not followed by two trail-bytes * represents itself. */ *chPtr = (Tcl_UniChar) byte; return 1; } #if TCL_UTF_MAX > 3 else { int ch, total, trail; total = totalBytes[byte]; trail = total - 1; if (trail > 0) { ch = byte & (0x3F >> trail); do { str++; if ((*str & 0xC0) != 0x80) { *chPtr = byte; return 1; } ch <<= 6; ch |= (*str & 0x3F); trail--; } while (trail > 0); *chPtr = ch; return total; } } #endif *chPtr = (Tcl_UniChar) byte; return 1; } /* msUTF8ToUniChar() * * Extract the Unicode Char represented by the UTF-8 string. Bad * UTF-8 sequences are converted to valid Unicode Chars and processing * continues. * * The caller must ensure that the source buffer is long enough that * this routine does not run off the end and dereference non-existent * memory looking for trail bytes. If the source buffer is known to * be '\0' terminated, this cannot happen. * * Results: * *chPtr is filled with the Unicode Char value, and the return value * is the number of bytes from the UTF-8 string that were consumed. ** **/ int msUTF8ToUniChar(const char *str, /* The UTF-8 string. */ int *chPtr) /* Filled with the Unicode Char represented * by the UTF-8 string. */ { return ms_Tcl_UtfToUniChar(str, chPtr); } mapserver-6.4.1/mapwfs11.c0000644002461700001440000005120412261257215015121 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC WFS 1.1.0 implementation. This file holds some WFS 1.1.0 * specific functions but other parts are still implemented in mapwfs.c. * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2008, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #include "mapserver.h" #include "mapows.h" #if defined(USE_WFS_SVR) && defined(USE_LIBXML2) #include "maplibxml2.h" #include "mapowscommon.h" #include "mapogcfilter.h" /************************************************************************/ /* msWFSException11() */ /************************************************************************/ int msWFSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version) { int size = 0; char *errorString = NULL; char *errorMessage = NULL; char *schemasLocation = NULL; const char *encoding; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode = NULL; xmlNsPtr psNsOws = NULL; xmlChar *buffer = NULL; if (version == NULL) version = "1.1.0"; psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows"); encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); errorString = msGetErrorString("\n"); errorMessage = msEncodeHTMLEntities(errorString); schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_0_0, schemasLocation, version, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage); xmlDocSetRootElement(psDoc, psRootNode); xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows"); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_printf("%s", buffer); /*free buffer and the document */ free(errorString); free(errorMessage); free(schemasLocation); xmlFree(buffer); xmlFreeDoc(psDoc); xmlFreeNs(psNsOws); /* clear error since we have already reported it */ msResetErrorList(); return MS_FAILURE; } /************************************************************************/ /* msWFSDumpLayer11 */ /************************************************************************/ static xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws) { rectObj ext; xmlNodePtr psRootNode, psNode; const char *value = NULL; const char *encoding = NULL; char *encoded=NULL; char *valueToFree; char **tokens; int n=0,i=0; encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (!encoding) encoding = "ISO-8859-1"; psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType"); /* add namespace to layer name */ value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix"); if(value) { n = strlen(value)+strlen(lp->name)+1+1; valueToFree = (char *) msSmallMalloc(sizeof(char*)*n); snprintf(valueToFree, n, "%s%s%s", (value ? value : ""), (value ? ":" : ""), lp->name); /*if there is an encoding using it on some of the items*/ psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", valueToFree, encoding); msFree(valueToFree); } else { psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", lp->name, encoding); } if (lp->name && strlen(lp->name) > 0 && (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0]))) xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: The layer name '%s' might contain spaces or " "invalid characters or may start with a number. This could lead to potential problems")); value = msOWSLookupMetadata(&(lp->metadata), "FO", "title"); if (!value) value =(const char*)lp->name; psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Title", value, encoding); value = msOWSLookupMetadata(&(lp->metadata), "FO", "abstract"); if (value) psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Abstract", value, encoding); value = msOWSLookupMetadata(&(lp->metadata), "FO", "keywordlist"); if (value) { if (encoding) encoded = msGetEncodedString(value, encoding); else encoded = msGetEncodedString(value, "ISO-8859-1"); msLibXml2GenerateList( xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL), NULL, "Keyword", encoded, ',' ); msFree(encoded); } /*support DefaultSRS and OtherSRS*/ valueToFree = msOWSGetProjURN(&(map->projection),&(map->web.metadata),"FO",MS_FALSE); if (!valueToFree) valueToFree = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE); if (valueToFree) { tokens = msStringSplit(valueToFree, ' ', &n); if (tokens && n > 0) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]); for (i=1; iprojection.numargs > 0) msOWSProjectToWGS84(&lp->projection, &ext); else msOWSProjectToWGS84(&map->projection, &ext); xmlAddChild(psRootNode, msOWSCommonWGS84BoundingBox( psNsOws, 2, ext.minx, ext.miny, ext.maxx, ext.maxy)); } else { xmlNewChild(psRootNode, psNsOws, BAD_CAST "WGS84BoundingBox", NULL); xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional WGS84BoundingBox could not be established for this layer. Consider setting the EXTENT in the LAYER object, or wfs_extent metadata. Also check that your data exists in the DATA statement")); } value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href"); if (value) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format"); if (!value) value = msStrdup("text/html"); /* default */ xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_type"); if (!value) value = msStrdup("FGDC"); /* default */ xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value); } return psRootNode; } /************************************************************************/ /* msWFSGetCapabilities11 */ /* */ /* Return the capabilities document for wfs 1.1.0 */ /************************************************************************/ int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode, psMainNode, psNode, psFtNode; const char *updatesequence=NULL; xmlNsPtr psNsOws, psNsXLink, psNsOgc; char *schemalocation = NULL; char *xsi_schemaLocation = NULL; const char *user_namespace_prefix = NULL; const char *user_namespace_uri = NULL; gmlNamespaceListObj *namespaceList=NULL; /* for external application schema support */ char *script_url=NULL, *formats_list; const char *value = NULL; const char *encoding; xmlChar *buffer = NULL; int size = 0, i; msIOContext *context = NULL; int ows_version = OWS_1_0_0; /* -------------------------------------------------------------------- */ /* Handle updatesequence */ /* -------------------------------------------------------------------- */ updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence"); encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (params->pszUpdateSequence != NULL) { i = msOWSNegotiateUpdateSequence(params->pszUpdateSequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWFSGetCapabilities11()", params->pszUpdateSequence, updatesequence); return msWFSException11(map, "updatesequence", "CurrentUpdateSequence", params->pszVersion); } if (i > 0) { /* invalid */ msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWFSGetCapabilities11()", params->pszUpdateSequence, updatesequence); return msWFSException11(map, "updatesequence", "InvalidUpdateSequence", params->pszVersion); } } /* -------------------------------------------------------------------- */ /* Create document. */ /* -------------------------------------------------------------------- */ psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "WFS_Capabilities"); xmlDocSetRootElement(psDoc, psRootNode); /* -------------------------------------------------------------------- */ /* Name spaces */ /* -------------------------------------------------------------------- */ /*default name space*/ xmlNewProp(psRootNode, BAD_CAST "xmlns", BAD_CAST "http://www.opengis.net/wfs"); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wfs", BAD_CAST "wfs")); psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psNsXLink = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX ); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_uri"); if(value) user_namespace_uri = value; value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix"); if(value) user_namespace_prefix = value; if(user_namespace_prefix != NULL && msIsXMLTagValid(user_namespace_prefix) == MS_FALSE) msIO_printf("\n", user_namespace_prefix); else xmlNewNs(psRootNode, BAD_CAST user_namespace_uri, BAD_CAST user_namespace_prefix); /* any additional namespaces */ namespaceList = msGMLGetNamespaces(&(map->web), "G"); for(i=0; inumnamespaces; i++) { if(namespaceList->namespaces[i].uri) { xmlNewNs(psRootNode, BAD_CAST namespaceList->namespaces[i].uri, BAD_CAST namespaceList->namespaces[i].prefix); } } msGMLFreeNamespaces(namespaceList); xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->pszVersion ); updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence"); if (updatesequence) xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence); /*schema*/ schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); xsi_schemaLocation = msStrdup("http://www.opengis.net/wfs"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/wfs/1.1.0/wfs.xsd"); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); /* -------------------------------------------------------------------- */ /* Service metadata. */ /* -------------------------------------------------------------------- */ xmlAddChild(psRootNode, msOWSCommonServiceIdentification(psNsOws, map, "OGC WFS", params->pszVersion, "FO")); /*service provider*/ xmlAddChild(psRootNode, msOWSCommonServiceProvider( psNsOws, psNsXLink, map, "FO")); /*operation metadata */ if ((script_url=msOWSGetOnlineResource(map, "FO", "onlineresource", req)) == NULL) { msSetError(MS_WFSERR, "Server URL not found", "msWFSGetCapabilities11()"); return msWFSException11(map, "mapserv", "NoApplicableCode", params->pszVersion); } /* -------------------------------------------------------------------- */ /* Operations metadata. */ /* -------------------------------------------------------------------- */ psMainNode= xmlAddChild(psRootNode,msOWSCommonOperationsMetadata(psNsOws)); /* -------------------------------------------------------------------- */ /* GetCapabilities */ /* -------------------------------------------------------------------- */ psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetCapabilities", OWS_METHOD_GETPOST, script_url)); xmlAddChild(psMainNode, psNode); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psNsOws, "Parameter", "service", "WFS")); /*accept version*/ xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws, "Parameter", "AcceptVersions", "1.0.0,1.1.0")); /*format*/ xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws, "Parameter", "AcceptFormats", "text/xml")); /* -------------------------------------------------------------------- */ /* DescribeFeatureType */ /* -------------------------------------------------------------------- */ if (msOWSRequestIsEnabled(map, NULL, "F", "DescribeFeatureType", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeFeatureType", OWS_METHOD_GETPOST, script_url)); xmlAddChild(psMainNode, psNode); /*output format*/ xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws, "Parameter", "outputFormat", "XMLSCHEMA,text/xml; subtype=gml/2.1.2,text/xml; subtype=gml/3.1.1")); } /* -------------------------------------------------------------------- */ /* GetFeature */ /* -------------------------------------------------------------------- */ if (msOWSRequestIsEnabled(map, NULL, "F", "GetFeature", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetFeature", OWS_METHOD_GETPOST, script_url)); xmlAddChild(psMainNode, psNode); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws, "Parameter", "resultType", "results,hits")); formats_list = msWFSGetOutputFormatList( map, NULL, "1.1.0" ); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws, "Parameter", "outputFormat", formats_list)); msFree( formats_list ); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "maxfeatures"); if (value) { xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws, "Constraint", "DefaultMaxFeatures", (char *)value)); } } /* -------------------------------------------------------------------- */ /* FeatureTypeList */ /* -------------------------------------------------------------------- */ psFtNode = xmlNewNode(NULL, BAD_CAST "FeatureTypeList"); xmlAddChild(psRootNode, psFtNode); psNode = xmlNewChild(psFtNode, NULL, BAD_CAST "Operations", NULL); xmlNewChild(psNode, NULL, BAD_CAST "Operation", BAD_CAST "Query"); for(i=0; inumlayers; i++) { layerObj *lp; lp = GET_LAYER(map, i); if (!msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) continue; /* List only vector layers in which DUMP=TRUE */ if (msWFSIsLayerSupported(lp)) xmlAddChild(psFtNode, msWFSDumpLayer11(map, lp, psNsOws)); } /* -------------------------------------------------------------------- */ /* Filter capabilities. */ /* -------------------------------------------------------------------- */ psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX); xmlAddChild(psRootNode, FLTGetCapabilities(psNsOgc, psNsOgc, MS_FALSE)); /* -------------------------------------------------------------------- */ /* Write out the document. */ /* -------------------------------------------------------------------- */ if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); context = msIO_getHandler(stdout); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_contextWrite(context, buffer, size); xmlFree(buffer); /*free buffer and the document */ /*xmlFree(buffer);*/ xmlFreeDoc(psDoc); xmlFreeNs(psNsOgc); free(script_url); free(xsi_schemaLocation); free(schemalocation); xmlCleanupParser(); return(MS_SUCCESS); } #endif /*defined(USE_WFS_SVR) && defined(USE_LIBXML2)*/ #if defined(USE_WFS_SVR) && !defined(USE_LIBXML2) int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request) { msSetError( MS_WFSERR, "WFS 1.1 request made, but mapserver requires libxml2 for WFS 1.1 services and this is not configured.", "msWFSGetCapabilities11()", "NoApplicableCode" ); return msWFSException11(map, "mapserv", "NoApplicableCode", params->pszVersion); } int msWFSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version) { /* fallback to reporting using 1.0 style exceptions. */ return msWFSException( map, locator, exceptionCode, "1.0.0" ); } #endif /* defined(USE_WFS_SVR) && !defined(USE_LIBXML2) */ mapserver-6.4.1/mapcopy.c0000644002461700001440000011156312261257215015137 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions to allow copying/cloning of maps * Author: Sean Gillies, sgillies@frii.com * * Notes: * These functions are not in mapfile.c because that file is * cumbersome enough as it is. There is agreement that this code and * that in mapfile.c should eventually be split up by object into * mapobj.c, layerobj.c, etc. Or something like that. * * Unit tests are written in Python using PyUnit and are in * mapscript/python/tests/testCopyMap.py. The tests can be * executed from the python directory as * * python2 tests/testCopyMap.py * * I just find Python to be very handy for unit testing, that's all. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include "mapserver.h" #include "mapsymbol.h" #include "mapcopy.h" /*********************************************************************** * msCopyProjection() * * * * Copy a projectionObj * **********************************************************************/ int msCopyProjection(projectionObj *dst, projectionObj *src) { #ifdef USE_PROJ int i; MS_COPYSTELEM(numargs); for (i = 0; i < dst->numargs; i++) { /* Our destination consists of unallocated pointers */ dst->args[i] = msStrdup(src->args[i]); } if (dst->numargs != 0) { if (msProcessProjection(dst) != MS_SUCCESS) return MS_FAILURE; } #endif MS_COPYSTELEM(wellknownprojection); return MS_SUCCESS; } /*********************************************************************** * msCopyLine() * * * * Copy a lineObj, using msCopyPoint() * **********************************************************************/ int msCopyLine(lineObj *dst, lineObj *src) { int i; dst->numpoints = src->numpoints; for (i = 0; i < dst->numpoints; i++) { MS_COPYPOINT(&(dst->point[i]), &(src->point[i])); } return MS_SUCCESS; } /*********************************************************************** * msCopyShape() * * * * Copy a shapeObj, using msCopyLine(), msCopyRect() * * Not completely implemented or tested. * **********************************************************************/ /* int msCopyShapeObj(shapeObj *dst, shapeObj *src) { int i; copyProperty(&(dst->numlines), &(src->numlines), sizeof(int)); for (i = 0; i < dst->numlines; i++) { msCopyLine(&(dst->line[i]), &(src->line[i])); } msCopyRect(&(dst->bounds), &(src->bounds)); copyProperty(&(dst->type), &(src->type), sizeof(int)); copyProperty(&(dst->index), &(src->index), sizeof(long)); copyProperty(&(dst->tileindex), &(src->tileindex), sizeof(int)); copyProperty(&(dst->classindex), &(src->classindex), sizeof(int)); copyStringPropertyRealloc(&(dst->text), src->text); copyProperty(&(dst->numvalues), &(src->numvalues), sizeof(int)); for (i = 0; i < dst->numvalues; i++) { copyStringPropertyRealloc(&(dst->values[i]), src->values[i]); } return(0); } */ /********************************************************************** * msCopyItem() * * * * Copy an itemObj * **********************************************************************/ int msCopyItem(itemObj *dst, itemObj *src) { MS_COPYSTRING(dst->name, src->name); MS_COPYSTELEM(type); MS_COPYSTELEM(index); MS_COPYSTELEM(size); MS_COPYSTELEM(numdecimals); return MS_SUCCESS; } /*********************************************************************** * msCopyHashTable() * * * * Copy a hashTableObj, using msInsertHashTable() * **********************************************************************/ int msCopyHashTable(hashTableObj *dst, hashTableObj *src) { const char *key=NULL; while (1) { key = msNextKeyFromHashTable(src, key); if (!key) break; else msInsertHashTable(dst, key, msLookupHashTable(src, key)); } return MS_SUCCESS; } /*********************************************************************** * msCopyFontSet() * * * * Copy a fontSetObj, using msCreateHashTable() and msCopyHashTable() * **********************************************************************/ int msCopyFontSet(fontSetObj *dst, fontSetObj *src, mapObj *map) { MS_COPYSTRING(dst->filename, src->filename); MS_COPYSTELEM(numfonts); if (&(src->fonts)) { /* if (!dst->fonts) */ /* dst->fonts = msCreateHashTable(); */ if (msCopyHashTable(&(dst->fonts), &(src->fonts)) != MS_SUCCESS) return MS_FAILURE; } dst->map = map; return MS_SUCCESS; } /*********************************************************************** * msCopyExpression( * * * * Copy an expressionObj, but only its string and type * **********************************************************************/ int msCopyExpression(expressionObj *dst, expressionObj *src) { MS_COPYSTRING(dst->string, src->string); MS_COPYSTELEM(type); dst->compiled = MS_FALSE; return MS_SUCCESS; } /*********************************************************************** * msCopyJoin() * * * * Copy a joinObj * **********************************************************************/ int msCopyJoin(joinObj *dst, joinObj *src) { MS_COPYSTRING(dst->name, src->name); /* makes no sense to copy the items or values since they are runtime additions to the mapfile */ MS_COPYSTRING(dst->table, src->table); MS_COPYSTRING(dst->from, src->from); MS_COPYSTRING(dst->to, src->to); MS_COPYSTRING(dst->header, src->header); #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTRING(dst->footer, src->footer); dst->type = src->type; MS_COPYSTRING(dst->connection, src->connection); MS_COPYSTELEM(connectiontype); /* TODO: need to handle joininfo (probably should be just set to NULL) */ dst->joininfo = NULL; return MS_SUCCESS; } /*********************************************************************** * msCopyQueryMap() * * * * Copy a queryMapObj, using msCopyColor() * **********************************************************************/ int msCopyQueryMap(queryMapObj *dst, queryMapObj *src) { MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(status); MS_COPYSTELEM(style); MS_COPYCOLOR(&(dst->color), &(src->color)); return MS_SUCCESS; } /*********************************************************************** * msCopyLeader() * * * * Copy a labelLeaderObj, using msCopyStyle() * **********************************************************************/ int msCopyLeader(labelLeaderObj *dst, labelLeaderObj *src) { int i; MS_COPYSTELEM(gridstep); MS_COPYSTELEM(maxdistance); /* ** now the styles */ /* free any previous styles on the dst label */ for(i=0; inumstyles; i++) { /* each style */ if (dst->styles[i]!=NULL) { if( freeStyle(dst->styles[i]) == MS_SUCCESS ) msFree(dst->styles[i]); } } msFree(dst->styles); dst->numstyles = 0; for (i = 0; i < src->numstyles; i++) { if (msGrowLeaderStyles(dst) == NULL) return MS_FAILURE; if (initStyle(dst->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to init style.", "msCopyLabel()"); return MS_FAILURE; } if (msCopyStyle(dst->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msCopyLabel()"); return MS_FAILURE; } dst->numstyles++; } return MS_SUCCESS; } /*********************************************************************** * msCopyLabel() * * * * Copy a labelObj, using msCopyColor() and msCopyStyle() * **********************************************************************/ int msCopyLabel(labelObj *dst, labelObj *src) { int i; for(i=0; ibindings[i].item, src->bindings[i].item); dst->bindings[i].index = src->bindings[i].index; /* no way to use the macros */ } MS_COPYSTELEM(numbindings); MS_COPYSTRING(dst->font, src->font); MS_COPYSTELEM(type); MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->outlinecolor), &(src->outlinecolor)); MS_COPYCOLOR(&(dst->shadowcolor), &(src->shadowcolor)); MS_COPYSTELEM(shadowsizex); MS_COPYSTELEM(shadowsizey); MS_COPYSTELEM(size); MS_COPYSTELEM(minsize); MS_COPYSTELEM(maxsize); MS_COPYSTELEM(position); MS_COPYSTELEM(offsetx); MS_COPYSTELEM(offsety); MS_COPYSTELEM(angle); MS_COPYSTELEM(anglemode); MS_COPYSTELEM(buffer); MS_COPYSTELEM(antialias); MS_COPYSTELEM(wrap); MS_COPYSTELEM(align); MS_COPYSTELEM(maxlength); MS_COPYSTELEM(minfeaturesize); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTELEM(autominfeaturesize); MS_COPYSTELEM(mindistance); MS_COPYSTELEM(partials); MS_COPYSTELEM(force); MS_COPYSTELEM(priority); MS_COPYSTRING(dst->encoding, src->encoding); MS_COPYSTELEM(outlinewidth); MS_COPYSTELEM(space_size_10); if (msCopyExpression(&(dst->expression), &(src->expression)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy expression.", "msCopyLabel()"); return MS_FAILURE; } if (msCopyExpression(&(dst->text), &(src->text)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy text.", "msCopyLabel()"); return MS_FAILURE; } /* ** now the styles */ /* free any previous styles on the dst label */ for(i=0; inumstyles; i++) { /* each style */ if (dst->styles[i]!=NULL) { if( freeStyle(dst->styles[i]) == MS_SUCCESS ) msFree(dst->styles[i]); } } msFree(dst->styles); dst->numstyles = 0; for (i = 0; i < src->numstyles; i++) { if (msGrowLabelStyles(dst) == NULL) return MS_FAILURE; if (initStyle(dst->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to init style.", "msCopyLabel()"); return MS_FAILURE; } if (msCopyStyle(dst->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msCopyLabel()"); return MS_FAILURE; } dst->numstyles++; } /* ** other book keeping information (RFC77 TODO) */ MS_COPYSTELEM(status); MS_COPYSTRING(dst->annotext, src->annotext); msCopyLeader(&(dst->leader),&(src->leader)); return MS_SUCCESS; } /*********************************************************************** * msCopyWeb() * * * * Copy webObj, using msCopyRect(), msCreateHashTable(), and * * msCopyHashTable() * **********************************************************************/ int msCopyWeb(webObj *dst, webObj *src, mapObj *map) { MS_COPYSTRING(dst->log, src->log); MS_COPYSTRING(dst->imagepath, src->imagepath); MS_COPYSTRING(dst->imageurl, src->imageurl); dst->map = map; #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTRING(dst->header, src->header); MS_COPYSTRING(dst->footer, src->footer); MS_COPYSTRING(dst->empty, src->empty); MS_COPYSTRING(dst->error, src->error); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTRING(dst->mintemplate, src->mintemplate); MS_COPYSTRING(dst->maxtemplate, src->maxtemplate); if (&(src->metadata)) { /* dst->metadata = msCreateHashTable(); */ if (msCopyHashTable(&(dst->metadata), &(src->metadata)) != MS_SUCCESS) return MS_FAILURE; } msCopyHashTable(&dst->validation,&src->validation); MS_COPYSTRING(dst->queryformat, src->queryformat); MS_COPYSTRING(dst->legendformat, src->legendformat); MS_COPYSTRING(dst->browseformat, src->browseformat); return MS_SUCCESS ; } /*********************************************************************** * msCopyStyle() * * * * Copy a styleObj, using msCopyColor() * **********************************************************************/ int msCopyStyle(styleObj *dst, styleObj *src) { int i; for(i=0; ibindings[i].item, src->bindings[i].item); dst->bindings[i].index = src->bindings[i].index; /* no way to use the macros */ } MS_COPYSTELEM(numbindings); MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->outlinecolor),&(src->outlinecolor)); MS_COPYCOLOR(&(dst->backgroundcolor), &(src->backgroundcolor)); MS_COPYCOLOR(&(dst->mincolor), &(src->mincolor)); MS_COPYCOLOR(&(dst->maxcolor), &(src->maxcolor)); MS_COPYSTRING(dst->symbolname, src->symbolname); MS_COPYSTELEM(patternlength); for(i=0; ipatternlength; i++) dst->pattern[i]=src->pattern[i]; MS_COPYSTELEM(initialgap); MS_COPYSTELEM(gap); MS_COPYSTELEM(linejoin); MS_COPYSTELEM(linejoinmaxsize); MS_COPYSTELEM(linecap); MS_COPYSTELEM(symbol); MS_COPYSTELEM(size); MS_COPYSTELEM(minsize); MS_COPYSTELEM(maxsize); MS_COPYSTELEM(width); MS_COPYSTELEM(minwidth); MS_COPYSTELEM(maxwidth); MS_COPYSTELEM(offsetx); MS_COPYSTELEM(offsety); MS_COPYSTELEM(antialias); MS_COPYSTELEM(angle); MS_COPYSTELEM(minvalue); MS_COPYSTELEM(maxvalue); MS_COPYSTELEM(opacity); MS_COPYSTRING(dst->_geomtransform.string, src->_geomtransform.string); MS_COPYSTELEM(_geomtransform.type); MS_COPYSTRING(dst->rangeitem, src->rangeitem); MS_COPYSTELEM(rangeitemindex); MS_COPYSTELEM(outlinewidth); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); /* TODO: add copy for bindings */ return MS_SUCCESS; } /*********************************************************************** * msCopyClass() * * * * Copy a classObj, using msCopyExpression(), msCopyStyle(), * * msCopyLabel(), msCreateHashTable(), msCopyHashTable() * **********************************************************************/ int msCopyClass(classObj *dst, classObj *src, layerObj *layer) { int i, return_value; return_value = msCopyExpression(&(dst->expression),&(src->expression)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy expression.", "msCopyClass()"); return MS_FAILURE; } MS_COPYSTELEM(status); /* free any previous styles on the dst layer */ for(i=0; inumstyles; i++) { /* each style */ if (dst->styles[i]!=NULL) { if( freeStyle(dst->styles[i]) == MS_SUCCESS ) { msFree(dst->styles[i]); } } } msFree(dst->styles); dst->numstyles = 0; for (i = 0; i < src->numstyles; i++) { if (msGrowClassStyles(dst) == NULL) return MS_FAILURE; if (initStyle(dst->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to init style.", "msCopyClass()"); return MS_FAILURE; } if (msCopyStyle(dst->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msCopyClass()"); return MS_FAILURE; } dst->numstyles++; } for (i=0; inumlabels; i++) { if (msGrowClassLabels(dst) == NULL) return MS_FAILURE; initLabel(dst->labels[i]); if (msCopyLabel(dst->labels[i], src->labels[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.", "msCopyClass()"); return MS_FAILURE; } dst->numlabels++; } MS_COPYSTELEM(numlabels); msCopyLeader(&(dst->leader),&(src->leader)); MS_COPYSTRING(dst->keyimage, src->keyimage); MS_COPYSTRING(dst->name, src->name); MS_COPYSTRING(dst->title, src->title); MS_COPYSTRING(dst->group, src->group); if (msCopyExpression(&(dst->text), &(src->text)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy text.", "msCopyClass()"); return MS_FAILURE; } #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTELEM(type); if (&(src->metadata) != NULL) { /* dst->metadata = msCreateHashTable(); */ msCopyHashTable(&(dst->metadata), &(src->metadata)); } msCopyHashTable(&dst->validation,&src->validation); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTELEM(layer); MS_COPYSTELEM(debug); return MS_SUCCESS; } int msCopyCluster(clusterObj *dst, clusterObj *src) { int return_value; MS_COPYSTELEM(maxdistance); MS_COPYSTELEM(buffer); MS_COPYSTRING(dst->region, src->region); return_value = msCopyExpression(&(dst->group),&(src->group)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy cluster group.", "msCopyCluster()"); return MS_FAILURE; } return_value = msCopyExpression(&(dst->filter),&(src->filter)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy cluster filter.", "msCopyCluster()"); return MS_FAILURE; } return MS_SUCCESS; } #ifdef why_on_earth_would_you_copy_a_labelcache /*********************************************************************** * msCopyLabelCacheMember() * * * * Copy a labelCacheMemberObj using msCopyStyle(), msCopyPoint() * * * * Note: since it seems most users will want to clone maps rather than * * make exact copies, this method might not get much use. * **********************************************************************/ int msCopyLabelCacheMember(labelCacheMemberObj *dst, labelCacheMemberObj *src) { int i; MS_COPYSTELEM(featuresize); MS_COPYSTELEM(numstyles); for (i = 0; i < dst->numstyles; i++) { msCopyStyle(&(dst->styles[i]), &(src->styles[i])); } MS_COPYSTELEM(numlabels); dst->labels = (labelObj *) msSmallMalloc(sizeof(labelObj)*dst->numlabels); for (i = 0; i < dst->numlabels; i++) { msCopyLabel(&(dst->labels[i]), &(src->labels[i])); } MS_COPYSTELEM(layerindex); MS_COPYSTELEM(classindex); MS_COPYSTELEM(tileindex); MS_COPYSTELEM(shapeindex); MS_COPYPOINT(&(dst->point), &(src->point)); /* msCopyShape(&(dst->poly), &(src->poly)); */ MS_COPYSTELEM(status); return MS_SUCCESS; } /*********************************************************************** * msCopyMarkerCacheMember() * * * * Copy a markerCacheMemberObj * **********************************************************************/ int msCopyMarkerCacheMember(markerCacheMemberObj *dst, markerCacheMemberObj *src) { MS_COPYSTELEM(id); /* msCopyShape(&(dst->poly), &(src->poly)); */ return MS_SUCCESS; } /*********************************************************************** * msCopyLabelCacheSlot() * **********************************************************************/ int msCopyLabelCacheSlot(labelCacheSlotObj *dst, labelCacheSlotObj *src) { int i; for (i = 0; i < dst->numlabels; i++) { msCopyLabelCacheMember(&(dst->labels[i]), &(src->labels[i])); } MS_COPYSTELEM(cachesize); MS_COPYSTELEM(nummarkers); for (i = 0; i < dst->nummarkers; i++) { msCopyMarkerCacheMember(&(dst->markers[i]), &(src->markers[i])); } MS_COPYSTELEM(markercachesize); return MS_SUCCESS; } /*********************************************************************** * msCopyLabelCache() * **********************************************************************/ int msCopyLabelCache(labelCacheObj *dst, labelCacheObj *src) { int p; MS_COPYSTELEM(numlabels); for (p=0; pslots[p]), &(src->slots[p])); } return MS_SUCCESS; } #endif /*********************************************************************** * msCopyResult() * **********************************************************************/ int msCopyResult(resultObj *dst, resultObj *src) { MS_COPYSTELEM(shapeindex); MS_COPYSTELEM(tileindex); MS_COPYSTELEM(classindex); MS_COPYSTELEM(resultindex); return MS_SUCCESS; } /*********************************************************************** * msCopyResultCache() * **********************************************************************/ int msCopyResultCache(resultCacheObj *dst, resultCacheObj *src) { int i; MS_COPYSTELEM(cachesize); MS_COPYSTELEM(numresults); for (i = 0; i < dst->numresults; i++) { msCopyResult(&(dst->results[i]), &(src->results[i])); } MS_COPYRECT(&(dst->bounds), &(src->bounds)); return MS_SUCCESS; } /*********************************************************************** * msCopyReferenceMap() * * * * Copy a referenceMapObj using mapfile.c:initReferenceMap(), * * msCopyRect(), msCopyColor() * **********************************************************************/ int msCopyReferenceMap(referenceMapObj *dst, referenceMapObj *src, mapObj *map) { initReferenceMap(dst); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->outlinecolor),&(src->outlinecolor)); MS_COPYSTRING(dst->image, src->image); MS_COPYSTELEM(status); MS_COPYSTELEM(marker); MS_COPYSTRING(dst->markername, src->markername); MS_COPYSTELEM(markersize); MS_COPYSTELEM(minboxsize); MS_COPYSTELEM(maxboxsize); dst->map = map; return MS_SUCCESS; } /*********************************************************************** * msCopyScalebar() * * * * Copy a scalebarObj, using initScalebar(), msCopyColor(), * * and msCopyLabel() * **********************************************************************/ int msCopyScalebar(scalebarObj *dst, scalebarObj *src) { initScalebar(dst); MS_COPYCOLOR(&(dst->imagecolor), &(src->imagecolor)); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(style); MS_COPYSTELEM(intervals); if (msCopyLabel(&(dst->label), &(src->label)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.","msCopyScalebar()"); return MS_FAILURE; } MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->backgroundcolor), &(src->backgroundcolor)); MS_COPYCOLOR(&(dst->outlinecolor), &(src->outlinecolor)); MS_COPYSTELEM(units); MS_COPYSTELEM(status); MS_COPYSTELEM(position); MS_COPYSTELEM(transparent); MS_COPYSTELEM(interlace); MS_COPYSTELEM(postlabelcache); MS_COPYSTELEM(align); return MS_SUCCESS; } /*********************************************************************** * msCopyLegend() * * * * Copy a legendObj, using msCopyColor() * **********************************************************************/ int msCopyLegend(legendObj *dst, legendObj *src, mapObj *map) { int return_value; MS_COPYCOLOR(&(dst->imagecolor), &(src->imagecolor)); return_value = msCopyLabel(&(dst->label), &(src->label)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.", "msCopyLegend()"); return MS_FAILURE; } MS_COPYSTELEM(keysizex); MS_COPYSTELEM(keysizey); MS_COPYSTELEM(keyspacingx); MS_COPYSTELEM(keyspacingy); MS_COPYCOLOR(&(dst->outlinecolor),&(src->outlinecolor)); MS_COPYSTELEM(status); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(position); MS_COPYSTELEM(transparent); MS_COPYSTELEM(interlace); MS_COPYSTELEM(postlabelcache); #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif dst->map = map; return MS_SUCCESS; } int msCopyScaleTokenEntry(scaleTokenEntryObj *src, scaleTokenEntryObj *dst) { MS_COPYSTRING(dst->value,src->value); MS_COPYSTELEM(minscale); MS_COPYSTELEM(maxscale); return MS_SUCCESS; } int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst) { int i; MS_COPYSTRING(dst->name,src->name); MS_COPYSTELEM(n_entries); dst->tokens = (scaleTokenEntryObj*)msSmallCalloc(src->n_entries,sizeof(scaleTokenEntryObj)); for(i=0;in_entries;i++) { msCopyScaleTokenEntry(&src->tokens[i],&dst->tokens[i]); } return MS_SUCCESS; } /*********************************************************************** * msCopyLayer() * * * * Copy a layerObj, using mapfile.c:initClass(), msCopyClass(), * * msCopyColor(), msCopyProjection(), msShapefileOpen(), * * msCreateHashTable(), msCopyHashTable(), msCopyExpression() * * * * As it stands, we are not copying a layer's resultcache * **********************************************************************/ int msCopyLayer(layerObj *dst, layerObj *src) { int i, return_value; featureListNodeObjPtr current; MS_COPYSTELEM(index); MS_COPYSTRING(dst->classitem, src->classitem); MS_COPYSTELEM(classitemindex); for(i = 0; i < src->numscaletokens; i++) { if(msGrowLayerScaletokens(dst) == NULL) return MS_FAILURE; initScaleToken(&dst->scaletokens[i]); msCopyScaleToken(&src->scaletokens[i],&dst->scaletokens[i]); dst->numscaletokens++; } for (i = 0; i < src->numclasses; i++) { if (msGrowLayerClasses(dst) == NULL) return MS_FAILURE; #ifndef __cplusplus initClass(dst->class[i]); return_value = msCopyClass(dst->class[i], src->class[i], dst); #else initClass(dst->_class[i]); return_value = msCopyClass(dst->_class[i], src->_class[i], dst); #endif if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy class.", "msCopyLayer()"); return MS_FAILURE; } dst->numclasses++; } MS_COPYSTRING(dst->header, src->header); MS_COPYSTRING(dst->footer, src->footer); #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTRING(dst->name, src->name); MS_COPYSTRING(dst->group, src->group); MS_COPYSTRING(dst->data, src->data); MS_COPYSTELEM(status); MS_COPYSTELEM(type); MS_COPYSTELEM(annotate); MS_COPYSTELEM(tolerance); MS_COPYSTELEM(toleranceunits); MS_COPYSTELEM(symbolscaledenom); MS_COPYSTELEM(scalefactor); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTELEM(labelminscaledenom); MS_COPYSTELEM(labelmaxscaledenom); MS_COPYSTELEM(mingeowidth); MS_COPYSTELEM(maxgeowidth); MS_COPYSTELEM(sizeunits); MS_COPYSTELEM(maxfeatures); MS_COPYCOLOR(&(dst->offsite), &(src->offsite)); MS_COPYSTELEM(transform); MS_COPYSTELEM(labelcache); MS_COPYSTELEM(postlabelcache); MS_COPYSTRING(dst->labelitem, src->labelitem); MS_COPYSTELEM(labelitemindex); MS_COPYSTRING(dst->tileitem, src->tileitem); MS_COPYSTELEM(tileitemindex); MS_COPYSTRING(dst->tilesrs, src->tilesrs); MS_COPYSTRING(dst->tileindex, src->tileindex); return_value = msCopyProjection(&(dst->projection),&(src->projection)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy projection.", "msCopyLayer()"); return MS_FAILURE; } return_value = msCopyCluster(&(dst->cluster),&(src->cluster)); if (return_value != MS_SUCCESS) { return MS_FAILURE; } MS_COPYSTELEM(project); MS_COPYSTELEM(units); current = src->features; while(current != NULL) { insertFeatureList(&(dst->features), &(current->shape)); current = current->next; } MS_COPYSTRING(dst->connection, src->connection); MS_COPYSTELEM(connectiontype); MS_COPYSTRING(dst->plugin_library, src->plugin_library); MS_COPYSTRING(dst->plugin_library_original, src->plugin_library_original); /* Do not copy *layerinfo, items, or iteminfo. these are all initialized when the copied layer is opened */ return_value = msCopyExpression(&(dst->filter), &(src->filter)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy filter.", "msCopyLayer()"); return MS_FAILURE; } MS_COPYSTRING(dst->filteritem, src->filteritem); MS_COPYSTELEM(filteritemindex); MS_COPYSTRING(dst->styleitem, src->styleitem); MS_COPYSTELEM(styleitemindex); MS_COPYSTRING(dst->requires, src->requires); MS_COPYSTRING(dst->labelrequires, src->labelrequires); if (&(src->metadata)) { msCopyHashTable(&(dst->metadata), &(src->metadata)); } msCopyHashTable(&dst->validation,&src->validation); MS_COPYSTELEM(opacity); MS_COPYSTELEM(dump); MS_COPYSTELEM(debug); /* No need to copy the numprocessing member, as it is incremented by msLayerAddProcessing */ for (i = 0; i < src->numprocessing; i++) { msLayerAddProcessing(dst, msLayerGetProcessing(src, i)); } MS_COPYSTELEM(numjoins); for (i = 0; i < dst->numjoins; i++) { initJoin(&(dst->joins[i])); return_value = msCopyJoin(&(dst->joins[i]), &(src->joins[i])); if (return_value != MS_SUCCESS) return MS_FAILURE; } MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTRING(dst->classgroup, src->classgroup); MS_COPYSTRING(dst->mask, src->mask); return MS_SUCCESS; } /*********************************************************************** * msCopyMap() * * * * Copy a mapObj, using mapfile.c:initLayer(), msCopyLayer(), * * msCopyLegend(), msCopyScalebar(), msCopyProjection() * * msCopyOutputFormat(), msCopyWeb(), msCopyReferenceMap() * **********************************************************************/ int msCopyMap(mapObj *dst, mapObj *src) { int i, return_value; outputFormatObj *format; MS_COPYSTRING(dst->name, src->name); MS_COPYSTELEM(status); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(maxsize); for (i = 0; i < src->numlayers; i++) { if (msGrowMapLayers(dst) == NULL) return MS_FAILURE; initLayer((GET_LAYER(dst, i)), dst); return_value = msCopyLayer((GET_LAYER(dst, i)), (GET_LAYER(src, i))); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy layer.", "msCopyMap()"); return MS_FAILURE; } dst->numlayers++; } return_value = msCopyFontSet(&(dst->fontset), &(src->fontset), dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy fontset.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopySymbolSet(&(dst->symbolset), &(src->symbolset), dst); if(return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy symbolset.", "msCopyMap()"); return MS_FAILURE; } /* msCopyLabelCache(&(dst->labelcache), &(src->labelcache)); */ MS_COPYSTELEM(transparent); MS_COPYSTELEM(interlace); MS_COPYSTELEM(imagequality); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTELEM(cellsize); MS_COPYSTELEM(units); MS_COPYSTELEM(scaledenom); MS_COPYSTELEM(defresolution); MS_COPYSTELEM(resolution); MS_COPYSTRING(dst->shapepath, src->shapepath); MS_COPYSTRING(dst->mappath, src->mappath); MS_COPYCOLOR(&(dst->imagecolor), &(src->imagecolor)); /* clear existing destination format list */ if( dst->outputformat && --dst->outputformat->refcount < 1 ) { msFreeOutputFormat( dst->outputformat ); dst->outputformat = NULL; } for(i=0; i < dst->numoutputformats; i++ ) { if( --dst->outputformatlist[i]->refcount < 1 ) msFreeOutputFormat( dst->outputformatlist[i] ); } if( dst->outputformatlist != NULL ) msFree( dst->outputformatlist ); dst->outputformatlist = NULL; dst->outputformat = NULL; dst->numoutputformats = 0; for (i = 0; i < src->numoutputformats; i++) msAppendOutputFormat( dst, msCloneOutputFormat( src->outputformatlist[i]) ); /* set the active output format */ MS_COPYSTRING(dst->imagetype, src->imagetype); format = msSelectOutputFormat( dst, dst->imagetype ); msApplyOutputFormat(&(dst->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); return_value = msCopyProjection(&(dst->projection),&(src->projection)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy projection.", "msCopyMap()"); return MS_FAILURE; } /* No need to copy latlon projection */ return_value = msCopyReferenceMap(&(dst->reference),&(src->reference), dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy reference.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyScalebar(&(dst->scalebar), &(src->scalebar)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy scalebar.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyLegend(&(dst->legend), &(src->legend),dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy legend.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyQueryMap(&(dst->querymap), &(src->querymap)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy querymap.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyWeb(&(dst->web), &(src->web), dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy web.", "msCopyMap()"); return MS_FAILURE; } for (i = 0; i < dst->numlayers; i++) { MS_COPYSTELEM(layerorder[i]); } MS_COPYSTELEM(debug); MS_COPYSTRING(dst->datapattern, src->datapattern); MS_COPYSTRING(dst->templatepattern, src->templatepattern); if( msCopyHashTable( &(dst->configoptions), &(src->configoptions) ) != MS_SUCCESS ) return MS_FAILURE; return MS_SUCCESS; } mapserver-6.4.1/mapscale.c0000644002461700001440000005003712261257215015252 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Scale object rendering. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #define VMARGIN 3 /* buffer around the scalebar */ #define HMARGIN 3 #define VSPACING .8 /* spacing (% of font height) between scalebar and text */ #define VSLOP 5 /* makes things fit a bit better vertically */ /* ** Match this with with unit enumerations is mapserver.h */ static char *unitText[9]= {"in", "ft", "mi", "m", "km", "dd", "??", "??", "NM"}; /* MS_PIXEL and MS_PERCENTAGE not used */ double inchesPerUnit[9]= {1, 12, 63360.0, 39.3701, 39370.1, 4374754, 1, 1, 72913.3858 }; static double roundInterval(double d) { if(d<.001) return(MS_NINT(d*10000)/10000.0); if(d<.01) return(MS_NINT(d*1000)/1000.0); if(d<.1) return(MS_NINT(d*100)/100.0); if(d<1) return(MS_NINT(d*10)/10.0); if(d<100) return(MS_NINT(d)); if(d<1000) return(MS_NINT(d/10) * 10); if(d<10000) return(MS_NINT(d/100) * 100); if(d<100000) return(MS_NINT(d/1000) * 1000); if(d<1000000) return(MS_NINT(d/10000) * 10000); if(d<10000000) return(MS_NINT(d/100000) * 100000); if(d<100000000) return(MS_NINT(d/1000000) * 1000000); return(-1); } /* ** Calculate the approximate scale based on a few parameters. Note that this assumes the scale is ** the same in the x direction as in the y direction, so run msAdjustExtent(...) first. */ int msCalculateScale(rectObj extent, int units, int width, int height, double resolution, double *scale) { double md, gd, center_y; /* if((extent.maxx == extent.minx) || (extent.maxy == extent.miny)) */ if(!MS_VALID_EXTENT(extent)) { msSetError(MS_MISCERR, "Invalid image extent, minx=%lf, miny=%lf, maxx=%lf, maxy=%lf.", "msCalculateScale()", extent.minx, extent.miny, extent.maxx, extent.maxy); return(MS_FAILURE); } if((width <= 0) || (height <= 0)) { msSetError(MS_MISCERR, "Invalid image width or height.", "msCalculateScale()"); return(MS_FAILURE); } switch (units) { case(MS_DD): case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): center_y = (extent.miny+extent.maxy)/2.0; md = (width-1)/(resolution*msInchesPerUnit(units, center_y)); /* remember, we use a pixel-center to pixel-center extent, hence the width-1 */ gd = extent.maxx - extent.minx; *scale = gd/md; break; default: *scale = -1; /* this is not an error */ break; } return(MS_SUCCESS); } double msInchesPerUnit(int units, double center_lat) { double lat_adj = 1.0, ipu = 1.0; switch (units) { case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): ipu = inchesPerUnit[units]; break; case(MS_DD): /* With geographical (DD) coordinates, we adjust the inchesPerUnit * based on the latitude of the center of the view. For this we assume * we have a perfect sphere and just use cos(lat) in our calculation. */ #ifdef ENABLE_VARIABLE_INCHES_PER_DEGREE if (center_lat != 0.0) { double cos_lat; cos_lat = cos(MS_PI*center_lat/180.0); lat_adj = sqrt(1+cos_lat*cos_lat)/sqrt(2.0); } #endif ipu = inchesPerUnit[units]*lat_adj; break; default: break; } return ipu; } #define X_STEP_SIZE 5 /* TODO : the will be msDrawScalebarGD */ imageObj *msDrawScalebar(mapObj *map) { int status; char label[32]; double i, msx; int j; int isx, sx, sy, ox, oy, state, dsx; pointObj p; rectObj r; imageObj *image = NULL; double fontWidth, fontHeight; outputFormatObj *format = NULL; strokeStyleObj strokeStyle; shapeObj shape; lineObj line; pointObj points[5]; rendererVTableObj *renderer; strokeStyle.patternlength=0; if(map->units == -1) { msSetError(MS_MISCERR, "Map units not set.", "msDrawScalebar()"); return(NULL); } renderer = MS_MAP_RENDERER(map); if(!renderer || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { msSetError(MS_MISCERR, "Outputformat not supported for scalebar", "msDrawScalebar()"); return(NULL); } /* * A string containing the ten decimal digits is rendered to compute an average cell size * for each number, which is used later to place labels on the scalebar. */ if(msGetLabelSize(map,&map->scalebar.label,"0123456789",map->scalebar.label.size,&r,NULL) != MS_SUCCESS) { return NULL; } fontWidth = (r.maxx-r.minx)/10.0; fontHeight = r.maxy -r.miny; map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { return(NULL); } dsx = map->scalebar.width - 2*HMARGIN; do { msx = (map->cellsize * dsx)/(msInchesPerUnit(map->scalebar.units,0)/msInchesPerUnit(map->units,0)); i = roundInterval(msx/map->scalebar.intervals); snprintf(label, sizeof(label), "%g", map->scalebar.intervals*i); /* last label */ isx = MS_NINT((i/(msInchesPerUnit(map->units,0)/msInchesPerUnit(map->scalebar.units,0)))/map->cellsize); sx = (map->scalebar.intervals*isx) + MS_NINT((1.5 + strlen(label)/2.0 + strlen(unitText[map->scalebar.units]))*fontWidth); if(sx <= (map->scalebar.width - 2*HMARGIN)) break; /* it will fit */ dsx -= X_STEP_SIZE; /* change the desired size in hopes that it will fit in user supplied width */ } while(1); sy = (2*VMARGIN) + MS_NINT(VSPACING*fontHeight) + fontHeight + map->scalebar.height - VSLOP; /*Ensure we have an image format representing the options for the scalebar.*/ msApplyOutputFormat( &format, map->outputformat, map->scalebar.transparent, map->scalebar.interlace, MS_NOOVERRIDE ); if(map->scalebar.transparent == MS_OFF) { if(!MS_VALID_COLOR(map->scalebar.imagecolor)) MS_INIT_COLOR(map->scalebar.imagecolor,255,255,255,255); } image = msImageCreate(map->scalebar.width, sy, format, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->scalebar.imagecolor); /* drop this reference to output format */ msApplyOutputFormat( &format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); /* did we succeed in creating the image? */ if(!image) { msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawScalebar()"); return NULL; } switch(map->scalebar.align) { case(MS_ALIGN_LEFT): ox = HMARGIN; break; case(MS_ALIGN_RIGHT): ox = MS_NINT((map->scalebar.width - sx) + fontWidth); break; default: ox = MS_NINT((map->scalebar.width - sx)/2.0 + fontWidth/2.0); /* center the computed scalebar */ } oy = VMARGIN; switch(map->scalebar.style) { case(0): { line.numpoints = 5; line.point = points; shape.line = &line; shape.numlines = 1; if(MS_VALID_COLOR(map->scalebar.color)) { INIT_STROKE_STYLE(strokeStyle); strokeStyle.color = &map->scalebar.outlinecolor; strokeStyle.color->alpha = 255; strokeStyle.width = 1; } map->scalebar.backgroundcolor.alpha = 255; map->scalebar.color.alpha = 255; state = 1; /* 1 means filled */ for(j=0; jscalebar.intervals; j++) { points[0].x = points[4].x = points[3].x = ox + j*isx + 0.5; points[0].y = points[4].y = points[1].y = oy + 0.5; points[1].x = points[2].x = ox + (j+1)*isx + 0.5; points[2].y = points[3].y = oy + map->scalebar.height + 0.5; if(state == 1 && MS_VALID_COLOR(map->scalebar.color)) renderer->renderPolygon(image,&shape,&map->scalebar.color); else if(MS_VALID_COLOR(map->scalebar.backgroundcolor)) renderer->renderPolygon(image,&shape,&map->scalebar.backgroundcolor); if(strokeStyle.color) renderer->renderLine(image,&shape,&strokeStyle); sprintf(label, "%g", j*i); map->scalebar.label.position = MS_CC; p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */ p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); msDrawLabel(map,image,p,label,&map->scalebar.label,1.0); state = -state; } sprintf(label, "%g", j*i); ox = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0); sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]); map->scalebar.label.position = MS_CR; p.x = ox; /* + MS_NINT(fontPtr->w/2); */ p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); msDrawLabel(map,image,p,label,&map->scalebar.label,1.0); break; } case(1): { line.numpoints = 2; line.point = points; shape.line = &line; shape.numlines = 1; if(MS_VALID_COLOR(map->scalebar.color)) { strokeStyle.width = 1; strokeStyle.color = &map->scalebar.color; } points[0].y = points[1].y = oy; points[0].x = ox; points[1].x = ox + isx*map->scalebar.intervals; renderer->renderLine(image,&shape,&strokeStyle); points[0].y = oy; points[1].y = oy + map->scalebar.height; p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); for(j=0; j<=map->scalebar.intervals; j++) { points[0].x = points[1].x = ox + j*isx; renderer->renderLine(image,&shape,&strokeStyle); sprintf(label, "%g", j*i); if(j!=map->scalebar.intervals) { map->scalebar.label.position = MS_CC; p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */ } else { sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]); map->scalebar.label.position = MS_CR; p.x = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0); } msDrawLabel(map,image,p,label,&map->scalebar.label,1.0); } break; } default: msSetError(MS_MISCERR, "Unsupported scalebar style.", "msDrawScalebar()"); return(NULL); } return(image); } int msEmbedScalebar(mapObj *map, imageObj *img) { int l,index,s; pointObj point; imageObj *image = NULL; rendererVTableObj *renderer; symbolObj *embededSymbol; char* imageType = NULL; index = msGetSymbolIndex(&(map->symbolset), "scalebar", MS_FALSE); if(index != -1) msRemoveSymbol(&(map->symbolset), index); /* remove cached symbol in case the function is called multiple times with different zoom levels */ if((embededSymbol=msGrowSymbolSet(&map->symbolset)) == NULL) return MS_FAILURE; s = map->symbolset.numsymbols; map->symbolset.numsymbols++; if(!MS_RENDERER_PLUGIN(map->outputformat) || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { imageType = msStrdup(map->imagetype); /* save format */ if MS_DRIVER_CAIRO(map->outputformat) map->outputformat = msSelectOutputFormat( map, "cairopng" ); else map->outputformat = msSelectOutputFormat( map, "png" ); msInitializeRendererVTable(map->outputformat); } renderer = MS_MAP_RENDERER(map); image = msDrawScalebar(map); if (imageType) { map->outputformat = msSelectOutputFormat( map, imageType ); /* restore format */ msFree(imageType); } if(!image) { return MS_FAILURE; } embededSymbol->pixmap_buffer = calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(embededSymbol->pixmap_buffer, sizeof(rasterBufferObj), MS_FAILURE); if(MS_SUCCESS != renderer->getRasterBufferCopy(image,embededSymbol->pixmap_buffer)) { return MS_FAILURE; } embededSymbol->type = MS_SYMBOL_PIXMAP; /* intialize a few things */ embededSymbol->name = msStrdup("scalebar"); embededSymbol->sizex = embededSymbol->pixmap_buffer->width; embededSymbol->sizey = embededSymbol->pixmap_buffer->height; if(map->scalebar.transparent) { embededSymbol->transparent = MS_TRUE; embededSymbol->transparentcolor = 0; } switch(map->scalebar.position) { case(MS_LL): point.x = MS_NINT(embededSymbol->pixmap_buffer->width/2.0); point.y = map->height - MS_NINT(embededSymbol->pixmap_buffer->height/2.0); break; case(MS_LR): point.x = map->width - MS_NINT(embededSymbol->pixmap_buffer->width/2.0); point.y = map->height - MS_NINT(embededSymbol->pixmap_buffer->height/2.0); break; case(MS_LC): point.x = MS_NINT(map->width/2.0); point.y = map->height - MS_NINT(embededSymbol->pixmap_buffer->height/2.0); break; case(MS_UR): point.x = map->width - MS_NINT(embededSymbol->pixmap_buffer->width/2.0); point.y = MS_NINT(embededSymbol->pixmap_buffer->height/2.0); break; case(MS_UL): point.x = MS_NINT(embededSymbol->pixmap_buffer->width/2.0); point.y = MS_NINT(embededSymbol->pixmap_buffer->height/2.0); break; case(MS_UC): point.x = MS_NINT(map->width/2.0); point.y = MS_NINT(embededSymbol->pixmap_buffer->height/2.0); break; } l = msGetLayerIndex(map, "__embed__scalebar"); if(l == -1) { if (msGrowMapLayers(map) == NULL) return(-1); l = map->numlayers; map->numlayers++; if(initLayer((GET_LAYER(map, l)), map) == -1) return(-1); GET_LAYER(map, l)->name = msStrdup("__embed__scalebar"); GET_LAYER(map, l)->type = MS_LAYER_POINT; if (msGrowLayerClasses( GET_LAYER(map, l) ) == NULL) return(-1); if(initClass(GET_LAYER(map, l)->class[0]) == -1) return(-1); GET_LAYER(map, l)->numclasses = 1; /* so we make sure to free it */ /* update the layer order list with the layer's index. */ map->layerorder[l] = l; } GET_LAYER(map, l)->status = MS_ON; if(map->scalebar.postlabelcache) { /* add it directly to the image */ if(msMaybeAllocateClassStyle(GET_LAYER(map, l)->class[0], 0)==MS_FAILURE) return MS_FAILURE; GET_LAYER(map, l)->class[0]->styles[0]->symbol = s; msDrawMarkerSymbol(&map->symbolset, img, &point, GET_LAYER(map, l)->class[0]->styles[0], 1.0); } else { if(!GET_LAYER(map, l)->class[0]->labels) { if(msGrowClassLabels(GET_LAYER(map, l)->class[0]) == NULL) return MS_FAILURE; initLabel(GET_LAYER(map, l)->class[0]->labels[0]); GET_LAYER(map, l)->class[0]->numlabels = 1; GET_LAYER(map, l)->class[0]->labels[0]->force = MS_TRUE; GET_LAYER(map, l)->class[0]->labels[0]->size = MS_MEDIUM; /* must set a size to have a valid label definition */ GET_LAYER(map, l)->class[0]->labels[0]->priority = MS_MAX_LABEL_PRIORITY; GET_LAYER(map, l)->class[0]->labels[0]->annotext = NULL; } if(GET_LAYER(map, l)->class[0]->labels[0]->numstyles == 0) { if(msGrowLabelStyles(GET_LAYER(map,l)->class[0]->labels[0]) == NULL) return(MS_FAILURE); GET_LAYER(map,l)->class[0]->labels[0]->numstyles = 1; initStyle(GET_LAYER(map,l)->class[0]->labels[0]->styles[0]); GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; } GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->symbol = s; msAddLabel(map, GET_LAYER(map, l)->class[0]->labels[0], l, 0, NULL, &point, NULL, -1); } /* Mark layer as deleted so that it doesn't interfere with html legends or with saving maps */ GET_LAYER(map, l)->status = MS_DELETE; msFreeImage( image ); return(0); } /************************************************************************/ /* These two functions are used in PHP/Mapscript and Swig/Mapscript */ /************************************************************************/ /************************************************************************/ /* double GetDeltaExtentsUsingScale(double scale, int units, */ /* double centerLat, int width, */ /* double resolution) */ /* */ /* Utility function to return the maximum extent using the */ /* scale and the width of the image. */ /* */ /* Base on the function msCalculateScale (mapscale.c) */ /************************************************************************/ double GetDeltaExtentsUsingScale(double scale, int units, double centerLat, int width, double resolution) { double md = 0.0; double dfDelta = -1.0; if (scale <= 0 || width <=0) return -1; switch (units) { case(MS_DD): case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): /* remember, we use a pixel-center to pixel-center extent, hence the width-1 */ md = (width-1)/(resolution*msInchesPerUnit(units,centerLat)); dfDelta = md * scale; break; default: break; } return dfDelta; } /************************************************************************/ /* static double Pix2Georef(int nPixPos, int nPixMin, double nPixMax,*/ /* double dfGeoMin, double dfGeoMax, */ /* bool bULisYOrig) */ /* */ /* Utility function to convert a pixel pos to georef pos. If */ /* bULisYOrig parameter is set to true then the upper left is */ /* considered to be the Y origin. */ /* */ /************************************************************************/ double Pix2Georef(int nPixPos, int nPixMin, int nPixMax, double dfGeoMin, double dfGeoMax, int bULisYOrig) { double dfWidthGeo = 0.0; int nWidthPix = 0; double dfPixToGeo = 0.0; double dfPosGeo = 0.0; double dfDeltaGeo = 0.0; int nDeltaPix = 0; dfWidthGeo = dfGeoMax - dfGeoMin; nWidthPix = nPixMax - nPixMin; if (dfWidthGeo > 0.0 && nWidthPix > 0) { dfPixToGeo = dfWidthGeo / (double)nWidthPix; if (!bULisYOrig) nDeltaPix = nPixPos - nPixMin; else nDeltaPix = nPixMax - nPixPos; dfDeltaGeo = nDeltaPix * dfPixToGeo; dfPosGeo = dfGeoMin + dfDeltaGeo; } return (dfPosGeo); } /* This function converts a pixel value in geo ref. The return value is in * layer units. This function has been added for the purpose of the ticket #1340 */ double Pix2LayerGeoref(mapObj *map, layerObj *layer, int value) { double cellsize = MS_MAX(MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width), MS_CELLSIZE(map->extent.miny, map->extent.maxy, map->height)); double resolutionFactor = map->resolution/map->defresolution; double unitsFactor = 1; if (layer->sizeunits != MS_PIXELS) unitsFactor = msInchesPerUnit(map->units,0)/msInchesPerUnit(layer->sizeunits,0); return value*cellsize*resolutionFactor*unitsFactor; } mapserver-6.4.1/Makefile0000644002461700001440000000451712261257215014763 0ustar tbonfortusersAUTOTEST_OPTS=-strict -q PHP_MAPSCRIPT=build/mapscript/php/php_mapscript.so PYTHON_MAPSCRIPT_PATH=build/mapscript/python JAVA_MAPSCRIPT_PATH=build/mapscript/java BUILDPATH=../../build FLEX=flex YACC=yacc CMAKEFLAGS=-DCMAKE_C_FLAGS="--coverage" -DCMAKE_CXX_FLAGS="--coverage" \ -DCMAKE_SHARED_LINKER_FLAGS="-lgcov" -DWITH_GD=1 -DWITH_CLIENT_WMS=1 \ -DWITH_CLIENT_WFS=1 -DWITH_KML=1 -DWITH_SOS=1 -DWITH_PHP=1 \ -DWITH_PYTHON=1 -DWITH_JAVA=1 -DWITH_THREAD_SAFETY=1 -DWITH_FRIBIDI=0 -DWITH_FCGI=0 -DWITH_EXEMPI=1 \ -DCMAKE_BUILD_TYPE=Release -DWITH_RSVG=1 -DWITH_CURL=1 all: cmakebuild cmakebuild: lexer parser if test ! -s build/Makefile; then mkdir -p build ; cd build ; cmake .. $(CMAKEFLAGS); fi cd build && $(MAKE) $(MFLAGS) warning: $(error "This Makefile is used to run the \"test\" target") wxs-testcase: cd msautotest/wxs && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) renderers-testcase: cd msautotest/renderers && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) misc-testcase: cd msautotest/misc && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) gdal-testcase: cd msautotest/gdal && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) query-testcase: cd msautotest/query && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) autotest-install: test -d "msautotest/wxs" || ( git submodule init && git submodule update ) mspython-testcase: test -f "$(PYTHON_MAPSCRIPT_PATH)/_mapscript.so" && (export PYTHONPATH="../../$(PYTHON_MAPSCRIPT_PATH)" && cd msautotest/mspython && python run_all_tests.py) php-testcase: test -f "$(PHP_MAPSCRIPT)" && (export PHP_MAPSCRIPT_SO="../../$(PHP_MAPSCRIPT)" && cd msautotest/php && ./run_test.sh) java-testcase: test -d "$(JAVA_MAPSCRIPT_PATH)" && (export JAVA_MAPSCRIPT_SO="../../$(JAVA_MAPSCRIPT_PATH)" && cd mapscript/java && ./run_test.sh) test: autotest-install cmakebuild @$(MAKE) $(MFLAGS) wxs-testcase renderers-testcase misc-testcase gdal-testcase query-testcase mspython-testcase @./print-test-results.sh @$(MAKE) $(MFLAGS) php-testcase @$(MAKE) $(MFLAGS) java-testcase lexer: maplexer.c parser: mapparser.c maplexer.c: maplexer.l $(FLEX) --nounistd -Pmsyy -i -o$(CURDIR)/maplexer.c $(CURDIR)/maplexer.l mapparser.c: mapparser.y $(YACC) -d -o$(CURDIR)/mapparser.c $(CURDIR)/mapparser.y mapserver-6.4.1/mapquery.c0000644002461700001440000021367312261257215015337 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: layer query support. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" int msInitQuery(queryObj *query) { if(!query) return MS_FAILURE; msFreeQuery(query); /* clean up anything previously allocated */ query->type = MS_QUERY_IS_NULL; /* nothing defined */ query->mode = MS_QUERY_SINGLE; query->layer = query->slayer = -1; query->point.x = query->point.y = -1; query->buffer = 0.0; query->maxresults = 0; query->rect.minx = query->rect.miny = query->rect.maxx = query->rect.maxy = -1; query->shape = NULL; query->shapeindex = query->tileindex = -1; query->clear_resultcache = MS_TRUE; /* index queries allow the old results to persist */ query->maxfeatures = -1; query->startindex = -1; query->item = query->str = NULL; query->filter = NULL; return MS_SUCCESS; } void msFreeQuery(queryObj *query) { if(query->shape) { msFreeShape(query->shape); free(query->shape); } if(query->item) free(query->item); if(query->str) free(query->str); if(query->filter) { freeExpression(query->filter); free(query->filter); } } /* ** Wrapper for all query functions, just feed is a mapObj with a populated queryObj... */ int msExecuteQuery(mapObj *map) { int tmp=-1, status; /* handle slayer/qlayer management for feature queries */ if(map->query.slayer >= 0) { tmp = map->query.layer; map->query.layer = map->query.slayer; } switch(map->query.type) { case MS_QUERY_BY_POINT: status = msQueryByPoint(map); break; case MS_QUERY_BY_RECT: status = msQueryByRect(map); break; case MS_QUERY_BY_ATTRIBUTE: status = msQueryByAttributes(map); break; case MS_QUERY_BY_FILTER: status = msQueryByFilter(map); break; case MS_QUERY_BY_SHAPE: status = msQueryByShape(map); break; case MS_QUERY_BY_INDEX: status = msQueryByIndex(map); break; default: msSetError(MS_QUERYERR, "Malformed queryObj.", "msExecuteQuery()"); return(MS_FAILURE); } if(map->query.slayer >= 0) { map->query.layer = tmp; /* restore layer */ if(status == MS_SUCCESS) status = msQueryByFeatures(map); } return status; } /* ** msIsLayerQueryable() returns MS_TRUE/MS_FALSE */ int msIsLayerQueryable(layerObj *lp) { int i; if ( lp->type == MS_LAYER_TILEINDEX ) return MS_FALSE; if(lp->template && strlen(lp->template) > 0) return MS_TRUE; for(i=0; inumclasses; i++) { if(lp->class[i]->template && strlen(lp->class[i]->template) > 0) return MS_TRUE; } return MS_FALSE; } static int addResult(resultCacheObj *cache, shapeObj *shape) { int i; if(cache->numresults == cache->cachesize) { /* just add it to the end */ if(cache->cachesize == 0) cache->results = (resultObj *) malloc(sizeof(resultObj)*MS_RESULTCACHEINCREMENT); else cache->results = (resultObj *) realloc(cache->results, sizeof(resultObj)*(cache->cachesize+MS_RESULTCACHEINCREMENT)); if(!cache->results) { msSetError(MS_MEMERR, "Realloc() error.", "addResult()"); return(MS_FAILURE); } cache->cachesize += MS_RESULTCACHEINCREMENT; } i = cache->numresults; cache->results[i].classindex = shape->classindex; cache->results[i].tileindex = shape->tileindex; cache->results[i].shapeindex = shape->index; cache->results[i].resultindex = shape->resultindex; cache->numresults++; if(cache->numresults == 1) cache->bounds = shape->bounds; else msMergeRect(&(cache->bounds), &(shape->bounds)); return(MS_SUCCESS); } /* ** Serialize a query result set to disk. */ static int saveQueryResults(mapObj *map, char *filename) { FILE *stream; int i, j, n=0; if(!filename) { msSetError(MS_MISCERR, "No filename provided to save query results to.", "saveQueryResults()"); return MS_FAILURE; } stream = fopen(filename, "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "saveQueryResults()", filename); return MS_FAILURE; } fprintf(stream, "%s - Generated by msSaveQuery()\n", MS_QUERY_RESULTS_MAGIC_STRING); /* count the number of layers with results */ for(i=0; inumlayers; i++) if(GET_LAYER(map, i)->resultcache) n++; fwrite(&n, sizeof(int), 1, stream); /* now write the result set for each layer */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->resultcache) { fwrite(&i, sizeof(int), 1, stream); /* layer index */ fwrite(&(GET_LAYER(map, i)->resultcache->numresults), sizeof(int), 1, stream); /* number of results */ fwrite(&(GET_LAYER(map, i)->resultcache->bounds), sizeof(rectObj), 1, stream); /* bounding box */ for(j=0; jresultcache->numresults; j++) fwrite(&(GET_LAYER(map, i)->resultcache->results[j]), sizeof(resultObj), 1, stream); /* each result */ } } fclose(stream); return MS_SUCCESS; } static int loadQueryResults(mapObj *map, FILE *stream) { int i, j, k, n=0; if(1 != fread(&n, sizeof(int), 1, stream)) { msSetError(MS_MISCERR,"failed to read query count from query file stream", "loadQueryResults()"); return MS_FAILURE; } /* now load the result set for each layer found in the query file */ for(i=0; imap->numlayers) { msSetError(MS_MISCERR, "Invalid layer index loaded from query file.", "loadQueryResults()"); return MS_FAILURE; } /* inialize the results for this layer */ GET_LAYER(map, j)->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(GET_LAYER(map, j)->resultcache, sizeof(resultCacheObj), MS_FAILURE); if(1 != fread(&(GET_LAYER(map, j)->resultcache->numresults), sizeof(int), 1, stream)) { /* number of results */ msSetError(MS_MISCERR,"failed to read number of results from query file stream", "loadQueryResults()"); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } GET_LAYER(map, j)->resultcache->cachesize = GET_LAYER(map, j)->resultcache->numresults; if(1 != fread(&(GET_LAYER(map, j)->resultcache->bounds), sizeof(rectObj), 1, stream)) { /* bounding box */ msSetError(MS_MISCERR,"failed to read bounds from query file stream", "loadQueryResults()"); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } GET_LAYER(map, j)->resultcache->results = (resultObj *) malloc(sizeof(resultObj)*GET_LAYER(map, j)->resultcache->numresults); if (GET_LAYER(map, j)->resultcache->results == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "loadQueryResults()", __FILE__, __LINE__, (unsigned int)(sizeof(resultObj)*GET_LAYER(map, j)->resultcache->numresults)); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } for(k=0; kresultcache->numresults; k++) { if(1 != fread(&(GET_LAYER(map, j)->resultcache->results[k]), sizeof(resultObj), 1, stream)) { /* each result */ msSetError(MS_MISCERR,"failed to read result %d from query file stream", "loadQueryResults()", k); free(GET_LAYER(map, j)->resultcache->results); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } if(!GET_LAYER(map, j)->tileindex) GET_LAYER(map, j)->resultcache->results[k].tileindex = -1; /* reset the tile index for non-tiled layers */ GET_LAYER(map, j)->resultcache->results[k].resultindex = -1; /* all results loaded this way have a -1 result (set) index */ } } return MS_SUCCESS; } /* ** Serialize the parameters necessary to duplicate a query to disk. (TODO: add filter query...) */ static int saveQueryParams(mapObj *map, char *filename) { FILE *stream; if(!filename) { msSetError(MS_MISCERR, "No filename provided to save query to.", "saveQueryParams()"); return MS_FAILURE; } stream = fopen(filename, "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "saveQueryParams()", filename); return MS_FAILURE; } fprintf(stream, "%s - Generated by msSaveQuery()\n", MS_QUERY_PARAMS_MAGIC_STRING); fprintf(stream, "%d %d %d %d\n", map->query.mode, map->query.type, map->query.layer, map->query.slayer); /* all queries */ fprintf(stream, "%.15g %.15g %g %d\n", map->query.point.x, map->query.point.y, map->query.buffer, map->query.maxresults); /* by point */ fprintf(stream, "%.15g %.15g %.15g %.15g\n", map->query.rect.minx, map->query.rect.miny, map->query.rect.maxx, map->query.rect.maxy); /* by rect */ fprintf(stream, "%ld %ld %d\n", map->query.shapeindex, map->query.tileindex, map->query.clear_resultcache); /* by index */ fprintf(stream, "%s\n", (map->query.item)?map->query.item:"NULL"); /* by attribute */ fprintf(stream, "%s\n", (map->query.str)?map->query.str:"NULL"); if(map->query.shape) { /* by shape */ int i, j; shapeObj *s = map->query.shape; fprintf(stream, "%d\n", s->type); fprintf(stream, "%d\n", s->numlines); for(i=0; inumlines; i++) { fprintf(stream, "%d\n", s->line[i].numpoints); for(j=0; jline[i].numpoints; j++) fprintf(stream, "%.15g %.15g\n", s->line[i].point[j].x, s->line[i].point[j].y); } } else { fprintf(stream, "%d\n", MS_SHAPE_NULL); /* NULL shape */ } fclose(stream); return MS_SUCCESS; } static int loadQueryParams(mapObj *map, FILE *stream) { char buffer[MS_BUFFER_LENGTH]; int lineno; int shapetype, numlines, numpoints; msInitQuery(&(map->query)); /* this will free any previous query as well */ lineno = 2; /* line 1 is the magic string */ while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { switch(lineno) { case 2: if(sscanf(buffer, "%d %d %d %d\n", &(map->query.mode), &(map->query.type), &(map->query.layer), &(map->query.slayer)) != 4) goto parse_error; break; case 3: if(sscanf(buffer, "%lf %lf %lf %d\n", &map->query.point.x, &map->query.point.y, &map->query.buffer, &map->query.maxresults) != 4) goto parse_error; break; case 4: if(sscanf(buffer, "%lf %lf %lf %lf\n", &map->query.rect.minx, &map->query.rect.miny, &map->query.rect.maxx, &map->query.rect.maxy) != 4) goto parse_error; break; case 5: if(sscanf(buffer, "%ld %ld %d\n", &map->query.shapeindex, &map->query.tileindex, &map->query.clear_resultcache) != 3) goto parse_error; break; case 6: if(strncmp(buffer, "NULL", 4) != 0) { map->query.item = msStrdup(buffer); msStringChop(map->query.item); } break; case 7: if(strncmp(buffer, "NULL", 4) != 0) { map->query.str = msStrdup(buffer); msStringChop(map->query.str); } break; case 8: if(sscanf(buffer, "%d\n", &shapetype) != 1) goto parse_error; if(shapetype != MS_SHAPE_NULL) { /* load the rest of the shape */ int i, j; lineObj line; map->query.shape = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(map->query.shape); map->query.shape->type = shapetype; if(fscanf(stream, "%d\n", &numlines) != 1) goto parse_error; for(i=0; iquery.shape, &line); free(line.point); } } break; default: break; } lineno++; } /* TODO: should we throw an error if lineno != 10? */ /* force layer and slayer on */ if(map->query.layer >= 0 && map->query.layer < map->numlayers) GET_LAYER(map, map->query.layer)->status = MS_ON; if(map->query.slayer >= 0 && map->query.slayer < map->numlayers) GET_LAYER(map, map->query.slayer)->status = MS_ON; /* now execute the query */ return msExecuteQuery(map); parse_error: msSetError(MS_MISCERR, "Parse error line %d.", "loadQueryParameters()", lineno); return MS_FAILURE; } /* ** Save (serialize) a query to disk. There are two methods, one saves the query parameters and the other saves ** all the shape indexes. Note the latter can be very slow against certain data sources but has a certain usefulness ** on occation. */ int msSaveQuery(mapObj *map, char *filename, int results) { if(results) return saveQueryResults(map, filename); else return saveQueryParams(map, filename); } /* ** Loads a query file contained either serialized 1) query parameters or 2) query results (e.g. indexes). */ int msLoadQuery(mapObj *map, char *filename) { FILE *stream; char buffer[MS_BUFFER_LENGTH]; int retval=MS_FAILURE; if(!filename) { msSetError(MS_MISCERR, "No filename provided to load query from.", "msLoadQuery()"); return MS_FAILURE; } /* ** Make sure the file at least has the right extension. */ if(msEvalRegex("\\.qy$", filename) != MS_TRUE) { msSetError(MS_MISCERR, "Queryfile %s has incorrect file extension.", "msLoadQuery()", filename); return MS_FAILURE; } /* ** Open the file and inspect the first line. */ stream = fopen(filename, "r"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msLoadQuery()", filename); return MS_FAILURE; } if(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { /* ** Call correct reader based on the magic string. */ if(strncasecmp(buffer, MS_QUERY_RESULTS_MAGIC_STRING, strlen(MS_QUERY_RESULTS_MAGIC_STRING)) == 0) { retval = loadQueryResults(map, stream); } else if(strncasecmp(buffer, MS_QUERY_PARAMS_MAGIC_STRING, strlen(MS_QUERY_PARAMS_MAGIC_STRING)) == 0) { retval = loadQueryParams(map, stream); } else { msSetError(MS_WEBERR, "Missing magic string, %s doesn't look like a MapServer query file.", "msLoadQuery()", filename); retval = MS_FAILURE; } } else { msSetError(MS_WEBERR, "Empty file or failed read for %s.", "msLoadQuery()", filename); retval = MS_FAILURE; } fclose(stream); return retval; } int msQueryByIndex(mapObj *map) { layerObj *lp; int status; resultObj record; shapeObj shape; double minfeaturesize = -1; if(map->query.type != MS_QUERY_BY_INDEX) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByIndex()"); return(MS_FAILURE); } if(map->query.layer < 0 || map->query.layer >= map->numlayers) { msSetError(MS_QUERYERR, "No query layer defined.", "msQueryByIndex()"); return(MS_FAILURE); } lp = (GET_LAYER(map, map->query.layer)); if(!msIsLayerQueryable(lp)) { msSetError(MS_QUERYERR, "Requested layer has no templates defined.", "msQueryByIndex()"); return(MS_FAILURE); } if(map->query.clear_resultcache) { if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } } msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); /* disable driver paging */ msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); if(map->query.clear_resultcache || lp->resultcache == NULL) { lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); } msInitShape(&shape); record.resultindex = -1; record.shapeindex = map->query.shapeindex; record.tileindex = map->query.tileindex; status = msLayerGetShape(lp, &shape, &record); if(status != MS_SUCCESS) { msSetError(MS_NOTFOUND, "Not valid record request.", "msQueryByIndex()"); return(MS_FAILURE); } if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { msSetError(MS_NOTFOUND, "Requested shape not valid against layer minfeaturesize.", "msQueryByIndex()"); msFreeShape(&shape); msLayerClose(lp); return(MS_FAILURE); } } shape.classindex = msShapeGetClass(lp, map, &shape, NULL, 0); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msSetError(MS_NOTFOUND, "Requested shape not valid against layer classification scheme.", "msQueryByIndex()"); msFreeShape(&shape); msLayerClose(lp); return(MS_FAILURE); } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msSetError(MS_NOTFOUND, "Requested shape does not have a valid template, no way to present results.", "msQueryByIndex()"); msFreeShape(&shape); msLayerClose(lp); return(MS_FAILURE); } addResult(lp->resultcache, &shape); msFreeShape(&shape); /* msLayerClose(lp); */ return(MS_SUCCESS); } void msRestoreOldFilter(layerObj *lp, int old_filtertype, char *old_filteritem, char *old_filterstring) { freeExpression(&(lp->filter)); if(lp->filteritem) { free(lp->filteritem); lp->filteritem = NULL; lp->filteritemindex = -1; } /* restore any previously defined filter */ if(old_filterstring) { lp->filter.type = old_filtertype; lp->filter.string = old_filterstring; if(old_filteritem) { lp->filteritem = old_filteritem; } } } int msQueryByAttributes(mapObj *map) { layerObj *lp; int status; int old_filtertype=-1; char *old_filterstring=NULL, *old_filteritem=NULL; rectObj searchrect; shapeObj shape; int paging; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; if(map->query.type != MS_QUERY_BY_ATTRIBUTE) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByAttribute()"); return(MS_FAILURE); } if(map->query.layer < 0 || map->query.layer >= map->numlayers) { msSetError(MS_MISCERR, "No query layer defined.", "msQueryByAttributes()"); return(MS_FAILURE); } lp = (GET_LAYER(map, map->query.layer)); /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do now in case one of the following tests fails */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) { msSetError(MS_QUERYERR, "Requested layer has no templates defined so is not queryable.", "msQueryByAttributes()"); return(MS_FAILURE); } if(!map->query.str) { msSetError(MS_QUERYERR, "No query expression defined.", "msQueryByAttributes()"); return(MS_FAILURE); } /* save any previously defined filter */ if(lp->filter.string) { old_filtertype = lp->filter.type; old_filterstring = msStrdup(lp->filter.string); if(lp->filteritem) old_filteritem = msStrdup(lp->filteritem); } /* apply the passed query parameters */ if(map->query.item && map->query.item[0] != '\0') lp->filteritem = msStrdup(map->query.item); else lp->filteritem = NULL; msLoadExpressionString(&(lp->filter), map->query.str); msInitShape(&shape); /* Paging could have been disabled before */ paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) { msRestoreOldFilter(lp, old_filtertype, old_filteritem, old_filterstring); /* manually reset the filter */ return(MS_FAILURE); } msLayerEnablePaging(lp, paging); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) { msRestoreOldFilter(lp, old_filtertype, old_filteritem, old_filterstring); /* manually reset the filter */ return(MS_FAILURE); } /* identify candidate shapes */ searchrect = map->query.rect; #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ else lp->project = MS_FALSE; #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msRestoreOldFilter(lp, old_filtertype, old_filteritem, old_filterstring); /* manually reset the filter */ msLayerClose(lp); msSetError(MS_NOTFOUND, "No matching record(s) found, layer and area of interest do not overlap.", "msQueryByAttributes()"); return(MS_FAILURE); } else if(status != MS_SUCCESS) { msRestoreOldFilter(lp, old_filtertype, old_filteritem, old_filterstring); /* manually reset the filter */ msLayerClose(lp); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByAttributes(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&(lp->projection), &(map->projection), &shape); else lp->project = MS_FALSE; #endif /* Should we skip this feature? */ if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(lp->resultcache, &shape); msFreeShape(&shape); if(map->query.mode == MS_QUERY_SINGLE) { /* no need to look any further */ status = MS_DONE; break; } /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } if (classgroup) msFree(classgroup); msRestoreOldFilter(lp, old_filtertype, old_filteritem, old_filterstring); /* manually reset the filter */ if(status != MS_DONE) { msLayerClose(lp); return(MS_FAILURE); } /* was anything found? (if yes, don't close the layer) */ if(lp->resultcache && lp->resultcache->numresults > 0) return(MS_SUCCESS); msLayerClose(lp); msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByAttributes()"); return(MS_FAILURE); } /* ** Query using common expression syntax. */ int msQueryByFilter(mapObj *map) { int l; int start, stop=0; layerObj *lp; char status; expressionObj old_filter; rectObj search_rect; shapeObj shape; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; if(map->query.type != MS_QUERY_BY_FILTER) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByFilter()"); return(MS_FAILURE); } if(!map->query.filter) { /* TODO: check filter type too */ msSetError(MS_QUERYERR, "Filter is not set.", "msQueryByFilter()"); return(MS_FAILURE); } msInitShape(&shape); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(lp->type == MS_LAYER_RASTER) continue; /* ok to skip? */ if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } initExpression(&old_filter); msCopyExpression(&old_filter, &lp->filter); /* save existing filter */ if(msLayerSupportsCommonFilters(lp)) { msCopyExpression(&lp->filter, map->query.filter); /* apply new filter */ } msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) goto query_error; /* disable driver paging */ msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) goto query_error; if(!msLayerSupportsCommonFilters(lp)) { freeExpression(&lp->filter); /* clear existing filter */ status = msTokenizeExpression(map->query.filter, lp->items, &(lp->numitems)); if(status != MS_SUCCESS) goto query_error; } search_rect = map->query.rect; #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectRect(&(map->projection), &(lp->projection), &search_rect); /* project the searchrect to source coords */ else lp->project = MS_FALSE; #endif status = msLayerWhichShapes(lp, search_rect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) goto query_error; lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ if(!msLayerSupportsCommonFilters(lp)) { /* we have to apply the filter here instead of within the driver */ if(msEvalExpression(lp, &shape, map->query.filter, -1) != MS_TRUE) { /* next shape */ msFreeShape(&shape); continue; } } /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByFilter(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&(lp->projection), &(map->projection), &shape); else lp->project = MS_FALSE; #endif /* Should we skip this feature? */ if (!msLayerGetPaging(lp) && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(lp->resultcache, &shape); msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if(classgroup) msFree(classgroup); msCopyExpression(&lp->filter, &old_filter); /* restore old filter */ freeExpression(&old_filter); if(status != MS_DONE) goto query_error; if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return MS_SUCCESS; } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByFilter()"); return MS_FAILURE; query_error: msCopyExpression(&lp->filter, &old_filter); /* restore old filter */ freeExpression(&old_filter); msLayerClose(lp); return MS_FAILURE; } int msQueryByRect(mapObj *map) { int l; /* counters */ int start, stop=0; layerObj *lp; char status; shapeObj shape, searchshape; rectObj searchrect; double layer_tolerance = 0, tolerance = 0; int paging; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; if(map->query.type != MS_QUERY_BY_RECT) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByRect()"); return(MS_FAILURE); } msInitShape(&shape); msInitShape(&searchshape); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); /* Set the global maxfeatures */ if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } searchrect = map->query.rect; if(lp->tolerance > 0) { layer_tolerance = lp->tolerance; if(lp->toleranceunits == MS_PIXELS) tolerance = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); searchrect.minx -= tolerance; searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; } msRectToPolygon(searchrect, &searchshape); /* Raster layers are handled specially. */ if( lp->type == MS_LAYER_RASTER ) { if( msRasterQueryByRect( map, lp, searchrect ) == MS_FAILURE) return MS_FAILURE; continue; } /* Paging could have been disabled before */ paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); msLayerEnablePaging(lp, paging); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ else lp->project = MS_FALSE; #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) { msLayerClose(lp); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByRect(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&(lp->projection), &(map->projection), &shape); else lp->project = MS_FALSE; #endif if(msRectContained(&shape.bounds, &searchrect) == MS_TRUE) { /* if the whole shape is in, don't intersect */ status = MS_TRUE; } else { switch(shape.type) { /* make sure shape actually intersects the qrect (ADD FUNCTIONS SPECIFIC TO RECTOBJ) */ case MS_SHAPE_POINT: status = msIntersectMultipointPolygon(&shape, &searchshape); break; case MS_SHAPE_LINE: status = msIntersectPolylinePolygon(&shape, &searchshape); break; case MS_SHAPE_POLYGON: status = msIntersectPolygons(&shape, &searchshape); break; default: break; } } if(status == MS_TRUE) { /* Should we skip this feature? */ if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(lp->resultcache, &shape); --map->query.maxfeatures; } msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if (classgroup) msFree(classgroup); if(status != MS_DONE) return(MS_FAILURE); if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ msFreeShape(&searchshape); /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByRect()"); return(MS_FAILURE); } static int is_duplicate(resultCacheObj *resultcache, int shapeindex, int tileindex) { int i; for(i=0; inumresults; i++) if(resultcache->results[i].shapeindex == shapeindex && resultcache->results[i].tileindex == tileindex) return(MS_TRUE); return(MS_FALSE); } int msQueryByFeatures(mapObj *map) { int i, l; int start, stop=0; layerObj *lp, *slp; char status; double distance, tolerance, layer_tolerance; rectObj searchrect; shapeObj shape, selectshape; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; if(map->debug) msDebug("in msQueryByFeatures()\n"); /* is the selection layer valid and has it been queried */ if(map->query.slayer < 0 || map->query.slayer >= map->numlayers) { msSetError(MS_QUERYERR, "Invalid selection layer index.", "msQueryByFeatures()"); return(MS_FAILURE); } slp = (GET_LAYER(map, map->query.slayer)); if(!slp->resultcache) { msSetError(MS_QUERYERR, "Selection layer has not been queried.", "msQueryByFeatures()"); return(MS_FAILURE); } /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ slp->project = MS_TRUE; if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; /* selection layers should already be open */ /* status = msLayerOpen(slp); if(status != MS_SUCCESS) return(MS_FAILURE); */ msInitShape(&shape); /* initialize a few things */ msInitShape(&selectshape); for(l=start; l>=stop; l--) { if(l == map->query.slayer) continue; /* skip the selection layer */ lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* Get the layer tolerance default is 3 for point and line layers, 0 for others */ if(lp->tolerance == -1) { if(lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE) layer_tolerance = 3; else layer_tolerance = 0; } else layer_tolerance = lp->tolerance; if(lp->toleranceunits == MS_PIXELS) tolerance = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); /* for each selection shape */ for(i=0; iresultcache->numresults; i++) { status = msLayerGetShape(slp, &selectshape, &(slp->resultcache->results[i])); if(status != MS_SUCCESS) { msLayerClose(lp); msLayerClose(slp); return(MS_FAILURE); } if(selectshape.type != MS_SHAPE_POLYGON && selectshape.type != MS_SHAPE_LINE) { msLayerClose(lp); msLayerClose(slp); msSetError(MS_QUERYERR, "Selection features MUST be polygons or lines.", "msQueryByFeatures()"); return(MS_FAILURE); } #ifdef USE_PROJ if(slp->project && msProjectionsDiffer(&(slp->projection), &(map->projection))) { msProjectShape(&(slp->projection), &(map->projection), &selectshape); msComputeBounds(&selectshape); /* recompute the bounding box AFTER projection */ } else slp->project = MS_FALSE; #endif /* identify target shapes */ searchrect = selectshape.bounds; searchrect.minx -= tolerance; /* expand the search box to account for layer tolerances (e.g. buffered searches) */ searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ else lp->project = MS_FALSE; #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); break; /* next layer */ } else if(status != MS_SUCCESS) { msLayerClose(lp); msLayerClose(slp); return(MS_FAILURE); } if(i == 0) { lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); } nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* check for dups when there are multiple selection shapes */ if(i > 0 && is_duplicate(lp->resultcache, shape.index, shape.tileindex)) continue; /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByFeature(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&(lp->projection), &(map->projection), &shape); else lp->project = MS_FALSE; #endif switch(selectshape.type) { /* may eventually support types other than polygon on line */ case MS_SHAPE_POLYGON: switch(shape.type) { /* make sure shape actually intersects the selectshape */ case MS_SHAPE_POINT: if(tolerance == 0) /* just test for intersection */ status = msIntersectMultipointPolygon(&shape, &selectshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylinePolygon(&shape, &selectshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolygons(&shape, &selectshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: status = MS_FALSE; break; } break; case MS_SHAPE_LINE: switch(shape.type) { /* make sure shape actually intersects the selectshape */ case MS_SHAPE_POINT: if(tolerance == 0) { /* just test for intersection */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance == 0) status = MS_TRUE; } else { distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylines(&shape, &selectshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolylinePolygon(&selectshape, &shape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: status = MS_FALSE; break; } break; default: break; /* should never get here as we test for selection shape type explicitly earlier */ } if(status == MS_TRUE) { /* Should we skip this feature? */ if (!msLayerGetPaging(lp) && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(lp->resultcache, &shape); } msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if (classgroup) msFree(classgroup); if(status != MS_DONE) return(MS_FAILURE); msFreeShape(&selectshape); } /* next selection shape */ if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(l == map->query.slayer) continue; /* skip the selection layer */ if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByFeatures()"); return(MS_FAILURE); } /* msQueryByPoint() * * With mode=MS_QUERY_SINGLE: * Set maxresults = 0 to have a single result across all layers (the closest * shape from the first layer that finds a match). * Set maxresults = 1 to have up to one result per layer (the closest shape * from each layer). * * With mode=MS_QUERY_MULTIPLE: * Set maxresults = 0 to have an unlimited number of results. * Set maxresults > 0 to limit the number of results per layer (the shapes * returned are the first ones found in each layer and are not necessarily * the closest ones). */ int msQueryByPoint(mapObj *map) { int l; int start, stop=0; double d, t; double layer_tolerance; layerObj *lp; int paging; char status; rectObj rect, searchrect; shapeObj shape; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; if(map->query.type != MS_QUERY_BY_POINT) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByPoint()"); return(MS_FAILURE); } msInitShape(&shape); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* Raster layers are handled specially. */ if( lp->type == MS_LAYER_RASTER ) { if( msRasterQueryByPoint( map, lp, map->query.mode, map->query.point, map->query.buffer, map->query.maxresults ) == MS_FAILURE ) return MS_FAILURE; continue; } /* Get the layer tolerance default is 3 for point and line layers, 0 for others */ if(lp->tolerance == -1) { if(lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE) layer_tolerance = 3; else layer_tolerance = 0; } else layer_tolerance = lp->tolerance; if(map->query.buffer <= 0) { /* use layer tolerance */ if(lp->toleranceunits == MS_PIXELS) t = layer_tolerance * MS_MAX(MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width), MS_CELLSIZE(map->extent.miny, map->extent.maxy, map->height)); else t = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); } else /* use buffer distance */ t = map->query.buffer; rect.minx = map->query.point.x - t; rect.maxx = map->query.point.x + t; rect.miny = map->query.point.y - t; rect.maxy = map->query.point.y + t; /* Paging could have been disabled before */ paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); msLayerEnablePaging(lp, paging); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); /* identify target shapes */ searchrect = rect; #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ else lp->project = MS_FALSE; #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) { msLayerClose(lp); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByPoint(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&(lp->projection), &(map->projection), &shape); else lp->project = MS_FALSE; #endif d = msDistancePointToShape(&(map->query.point), &shape); if( d <= t ) { /* found one */ /* Should we skip this feature? */ if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } if(map->query.mode == MS_QUERY_SINGLE) { lp->resultcache->numresults = 0; addResult(lp->resultcache, &shape); t = d; /* next one must be closer */ } else { addResult(lp->resultcache, &shape); } } msFreeShape(&shape); if(map->query.mode == MS_QUERY_MULTIPLE && map->query.maxresults > 0 && lp->resultcache->numresults == map->query.maxresults) { status = MS_DONE; /* got enough results for this layer */ break; } /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if (classgroup) msFree(classgroup); if(status != MS_DONE) return(MS_FAILURE); if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ if((lp->resultcache->numresults > 0) && (map->query.mode == MS_QUERY_SINGLE) && (map->query.maxresults == 0)) break; /* no need to search any further */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByPoint()"); return(MS_FAILURE); } int msQueryByShape(mapObj *map) { int start, stop=0, l; shapeObj shape, *qshape=NULL; layerObj *lp; char status; double distance, tolerance, layer_tolerance; rectObj searchrect; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; if(map->query.type != MS_QUERY_BY_SHAPE) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByShape()"); return(MS_FAILURE); } if(!(map->query.shape)) { msSetError(MS_QUERYERR, "Query shape is not defined.", "msQueryByShape()"); return(MS_FAILURE); } if(map->query.shape->type != MS_SHAPE_POLYGON && map->query.shape->type != MS_SHAPE_LINE && map->query.shape->type != MS_SHAPE_POINT) { msSetError(MS_QUERYERR, "Query shape MUST be a polygon, line or point.", "msQueryByShape()"); return(MS_FAILURE); } msInitShape(&shape); qshape = map->query.shape; /* for brevity */ if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; msComputeBounds(qshape); /* make sure an accurate extent exists */ for(l=start; l>=stop; l--) { /* each layer */ lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* Raster layers are handled specially. */ if( lp->type == MS_LAYER_RASTER ) { if( msRasterQueryByShape(map, lp, qshape) == MS_FAILURE ) return MS_FAILURE; continue; } /* Get the layer tolerance default is 3 for point and line layers, 0 for others */ if(lp->tolerance == -1) { if(lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE) layer_tolerance = 3; else layer_tolerance = 0; } else layer_tolerance = lp->tolerance; if(lp->toleranceunits == MS_PIXELS) tolerance = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); /* disable driver paging */ msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); /* identify target shapes */ searchrect = qshape->bounds; searchrect.minx -= tolerance; /* expand the search box to account for layer tolerances (e.g. buffered searches) */ searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ else lp->project = MS_FALSE; #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) { msLayerClose(lp); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByShape(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&(lp->projection), &(map->projection), &shape); else lp->project = MS_FALSE; #endif switch(qshape->type) { /* may eventually support types other than polygon or line */ case MS_SHAPE_POLYGON: switch(shape.type) { /* make sure shape actually intersects the shape */ case MS_SHAPE_POINT: if(tolerance == 0) /* just test for intersection */ status = msIntersectMultipointPolygon(&shape, qshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylinePolygon(&shape, qshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolygons(&shape, qshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: break; } break; case MS_SHAPE_LINE: switch(shape.type) { /* make sure shape actually intersects the selectshape */ case MS_SHAPE_POINT: if(tolerance == 0) { /* just test for intersection */ distance = msDistanceShapeToShape(qshape, &shape); if(distance == 0) status = MS_TRUE; } else { distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylines(&shape, qshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolylinePolygon(qshape, &shape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: status = MS_FALSE; break; } break; case MS_SHAPE_POINT: distance = msDistanceShapeToShape(qshape, &shape); status = MS_FALSE; if(tolerance == 0 && distance == 0) status = MS_TRUE; /* shapes intersect */ else if(distance < tolerance) status = MS_TRUE; /* shapes are close enough */ break; default: break; /* should never get here as we test for selection shape type explicitly earlier */ } if(status == MS_TRUE) { /* Should we skip this feature? */ if (!msLayerGetPaging(lp) && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(lp->resultcache, &shape); } msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if(status != MS_DONE) return(MS_FAILURE); if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByShape()"); return(MS_FAILURE); } /* msGetQueryResultBounds() * * Compute the BBOX of all query results, returns the number of layers found * that contained query results and were included in the BBOX. * i.e. if we return 0 then the value in bounds is invalid. */ int msGetQueryResultBounds(mapObj *map, rectObj *bounds) { int i, found=0; rectObj tmpBounds; for(i=0; inumlayers; i++) { layerObj *lp; lp = (GET_LAYER(map, i)); if(!lp->resultcache) continue; if(lp->resultcache->numresults <= 0) continue; tmpBounds = lp->resultcache->bounds; if(found == 0) { *bounds = tmpBounds; } else { msMergeRect(bounds, &tmpBounds); } found++; } return found; } /* TODO: Rename this msFreeResultSet() or something along those lines... */ /* msQueryFree() * * Free layer's query results. If qlayer == -1, all layers will be treated. */ void msQueryFree(mapObj *map, int qlayer) { int l; /* counters */ int start, stop=0; layerObj *lp; if(qlayer < 0 || qlayer >= map->numlayers) start = map->numlayers-1; else start = stop = qlayer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } } } mapserver-6.4.1/maptime.c0000644002461700001440000003460512261257215015124 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Date/Time utility functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #define _GNU_SOURCE /* glibc2 needs this for strptime() */ #include #include #include #include "mapserver.h" #include "maptime.h" #include "maperror.h" #include "mapthread.h" typedef struct { char pattern[64]; ms_regex_t *regex; char format[32]; char userformat[32]; MS_TIME_RESOLUTION resolution; } timeFormatObj; #define MS_NUMTIMEFORMATS 13 timeFormatObj ms_timeFormats[MS_NUMTIMEFORMATS] = { {"^[0-9]{8}", NULL, "%Y%m%d","YYYYMMDD",TIME_RESOLUTION_DAY}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z", NULL, "%Y-%m-%dT%H:%M:%SZ","YYYY-MM-DDTHH:MM:SSZ",TIME_RESOLUTION_SECOND}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%dT%H:%M:%S", "YYYY-MM-DDTHH:MM:SS",TIME_RESOLUTION_SECOND}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%d %H:%M:%S", "YYYY-MM-DD HH:MM:SS", TIME_RESOLUTION_SECOND}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%dT%H:%M", "YYYY-MM-DDTHH:MM",TIME_RESOLUTION_MINUTE}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%d %H:%M", "YYYY-MM-DD HH:MM",TIME_RESOLUTION_MINUTE}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}", NULL, "%Y-%m-%dT%H", "YYYY-MM-DDTHH",TIME_RESOLUTION_HOUR}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}", NULL, "%Y-%m-%d %H", "YYYY-MM-DD HH",TIME_RESOLUTION_HOUR}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}", NULL, "%Y-%m-%d", "YYYY-MM-DD", TIME_RESOLUTION_DAY}, {"^[0-9]{4}-[0-9]{2}", NULL, "%Y-%m", "YYYY-MM",TIME_RESOLUTION_MONTH}, {"^[0-9]{4}", NULL, "%Y", "YYYY",TIME_RESOLUTION_YEAR}, {"^T[0-9]{2}:[0-9]{2}:[0-9]{2}Z", NULL, "T%H:%M:%SZ", "THH:MM:SSZ",TIME_RESOLUTION_SECOND}, {"^T[0-9]{2}:[0-9]{2}:[0-9]{2}", NULL, "T%H:%M:%S", "THH:MM:SS", TIME_RESOLUTION_SECOND}, }; int *ms_limited_pattern = NULL; int ms_num_limited_pattern; int ms_time_inited = 0; int msTimeSetup() { if(!ms_time_inited) { msAcquireLock(TLOCK_TIME); if(!ms_time_inited) { int i; for(i=0;itm_sec = 0; time->tm_min = 0; time->tm_hour = 0; time->tm_mday = 0; time->tm_mon = 0; time->tm_year = 0; time->tm_wday = 0; time->tm_yday = 0; time->tm_isdst = 0; return; } static int compareIntVals(int a, int b) { if(ab) return 1; else return 0; } int msDateCompare(struct tm *time1, struct tm *time2) { int result; if((result = compareIntVals(time1->tm_year, time2->tm_year)) != 0) return result; /* not equal based on year */ else if((result = compareIntVals(time1->tm_mon, time2->tm_mon)) != 0) return result; /* not equal based on month */ else if((result = compareIntVals(time1->tm_mday, time2->tm_mday)) != 0) return result; /* not equal based on day of month */ return(0); /* must be equal */ } int msTimeCompare(struct tm *time1, struct tm *time2) { int result; if((result = compareIntVals(time1->tm_year, time2->tm_year)) != 0) return result; /* not equal based on year */ else if((result = compareIntVals(time1->tm_mon, time2->tm_mon)) != 0) return result; /* not equal based on month */ else if((result = compareIntVals(time1->tm_mday, time2->tm_mday)) != 0) return result; /* not equal based on day of month */ else if((result = compareIntVals(time1->tm_hour, time2->tm_hour)) != 0) return result; /* not equal based on hour */ else if((result = compareIntVals(time1->tm_min, time2->tm_min)) != 0) return result; /* not equal based on minute */ else if((result = compareIntVals(time1->tm_sec, time2->tm_sec)) != 0) return result; /* not equal based on second */ return(0); /* must be equal */ } #if defined(_WIN32) && !defined(__CYGWIN__) #include void msGettimeofday(struct mstimeval* tp, void* tzp) { struct _timeb theTime; _ftime(&theTime); tp->tv_sec = theTime.time; tp->tv_usec = theTime.millitm * 1000; } #endif #if defined(_WIN32) && !defined(__CYGWIN__) /* we need to provide our own prototype on windows. */ char *strptime( const char *buf, const char *format, struct tm *timeptr ); #endif char *msStrptime(const char *s, const char *format, struct tm *tm) { return strptime(s, format, tm); } /** return MS_TRUE if the time string matchs the timeformat. else return MS_FALSE. */ int msTimeMatchPattern(char *timestring, char *timeformat) { int i =-1; if(msTimeSetup() != MS_SUCCESS) { return MS_FALSE; } /* match the pattern format first and then check if the time string */ /* matchs the pattern. If it is the case retrurn the MS_TRUE */ for (i=0; i= 0 && i < MS_NUMTIMEFORMATS) { int match = ms_regexec(ms_timeFormats[i].regex, timestring, 0,NULL, 0); if(match == 0) return MS_TRUE; } return MS_FALSE; } void msUnsetLimitedPatternToUse() { msTimeSetup(); ms_num_limited_pattern = 0; } void msSetLimitedPattersToUse(char *patternstring) { int *limitedpatternindice = NULL; int numpatterns=0, i=0, j=0, ntmp=0; char **patterns = NULL; msTimeSetup(); limitedpatternindice = (int *)msSmallMalloc(sizeof(int)*MS_NUMTIMEFORMATS); /* free previous setting */ msUnsetLimitedPatternToUse(); if (patternstring) { patterns = msStringSplit(patternstring, ',', &ntmp); if (patterns && ntmp >= 1) { for (i=0; i 0) { for (i=0; i 0) num_patterns = ms_num_limited_pattern; else num_patterns = MS_NUMTIMEFORMATS; for(i=0; i 0) indice = ms_limited_pattern[i]; else indice = i; match = ms_regexec(ms_timeFormats[indice].regex, string, 0,NULL, 0); /* test the expression against the string */ if(match == 0) { /* match */ msStrptime(string, ms_timeFormats[indice].format, tm); return(MS_TRUE); } } msSetError(MS_REGEXERR, "Unrecognized date or time format (%s).", "msParseTime()", string); return(MS_FALSE); } /** * Parse the time string and return the reslution */ int msTimeGetResolution(const char *timestring) { int i=0; if (!timestring) return -1; for(i=0; i=2) { /*range */ if (msParseTime(atimeelements[0], &tmtimestart) != MS_TRUE) { msFreeCharArray(atimeelements, numelements); return MS_FALSE; } if (msParseTime(atimeelements[1], &tmtimeend) != MS_TRUE) { msFreeCharArray(atimeelements, numelements); return MS_FALSE; } } msFreeCharArray(atimeelements, numelements); /* Now parse the time extent. Extents can be - one range (2004-09-21/2004-09-25/resolution) - multiple rages 2004-09-21/2004-09-25/res1,2004-09-21/2004-09-25/res2 - one value 2004-09-21 - mutiple values 2004-09-21,2004-09-22,2004-09-23 */ numextents = 0; atimeextents = msStringSplit (timeextent, ',', &numextents); if (atimeextents == NULL || numextents <= 0) return MS_FALSE; /*the time timestring should at be valid in one of the extents defined */ for (i=0; i= 0) { msFreeCharArray(atimerange, numranges); msFreeCharArray(atimeextents, numextents); return MS_TRUE; } } /*2004-09-21/2004-09-25/res1*/ else if (numranges >= 2) { if (msParseTime(atimerange[0], &tmstart) == MS_TRUE && msParseTime(atimerange[1], &tmend) == MS_TRUE && msTimeCompare(&tmstart, &tmtimestart) <= 0 && msTimeCompare(&tmend, &tmtimeend) >= 0) { msFreeCharArray(atimerange, numranges); msFreeCharArray(atimeextents, numextents); return MS_TRUE; } } msFreeCharArray(atimerange, numranges); } msFreeCharArray(atimeextents, numextents); return MS_FALSE; } int msValidateTimeValue(char *timestring, const char *timeextent) { char **atimes = NULL; int i, numtimes=0; /* we need to validate the time passsed in the request */ /* against the time extent defined */ if (!timestring || !timeextent) return MS_FALSE; /* parse the time string. We support descrete times (eg 2004-09-21), */ /* multiple times (2004-09-21, 2004-09-22, ...) */ /* and range(s) (2004-09-21/2004-09-25, 2004-09-27/2004-09-29) */ if (strstr(timestring, ",") == NULL && strstr(timestring, "/") == NULL) { /* discrete time */ return _msValidateTime(timestring, timeextent); } else { atimes = msStringSplit (timestring, ',', &numtimes); if (numtimes >=1) { /* multiple times */ if (strstr(atimes[0], "/") == NULL) { /* multiple descrete times */ for (i=0; i1) break; y=__sync_fetch_and_add(&x,1); } }" HAVE_SYNC_FETCH_AND_ADD) include_directories(${CMAKE_CURRENT_BINARY_DIR}) #options suported by the cmake builder option(WITH_PROJ "Choose if reprojection support should be built in" ON) option(WITH_KML "Enable native KML output support (requires libxml2 support)" OFF) option(WITH_SOS "Enable SOS Server support (requires PROJ and libxml2 support)" OFF) option(WITH_WMS "Enable WMS Server support (requires proj support)" ON) option(WITH_GD "Choose if (old) GD support should be built in" OFF) option(WITH_FRIBIDI "Choose if FriBidi glyph shaping support should be built in (usefull for left-to-right languages)" ON) option(WITH_ICONV "Choose if Iconv Internationalization support should be built in" ON) option(WITH_CAIRO "Choose if CAIRO rendering support should be built in (required for SVG and PDF output)" ON) option(WITH_SVGCAIRO "Choose if SVG symbology support (via libsvgcairo) should be built in (requires cairo, libsvg, libsvg-cairo. Incompatible with librsvg)" OFF) option(WITH_RSVG "Choose if SVG symbology support (via librsvg) should be built in (requires cairo, librsvg. Incompatible with libsvg-cairo)" OFF) option(WITH_MYSQL "Choose if MYSQL joining support should be built in" OFF) option(WITH_FCGI "Choose if FastCGI support should be built in" ON) option(WITH_GEOS "Choose if GEOS geometry operations support should be built in" ON) option(WITH_POSTGIS "Choose if Postgis input support should be built in" ON) option(WITH_GDAL "Choose if GDAL input raster support should be built in" ON) option(WITH_OGR "Choose if OGR/GDAL input vector support should be built in" ON) option(WITH_CLIENT_WMS "Enable Client WMS Layer support (requires CURL and GDAL support)" OFF) option(WITH_CLIENT_WFS "Enable Client WMS Layer support (requires CURL and OGR support)" OFF) option(WITH_CURL "Enable Curl HTTP support (required for wms/wfs client, and remote SLD)" OFF) option(WITH_WFS "Enable WFS Server support (requires PROJ and OGR support)" ON) option(WITH_WCS "Enable WCS Server support (requires PROJ and GDAL support)" ON) option(WITH_LIBXML2 "Choose if libxml2 support should be built in (used for sos, wcs 1.1,2.0 and wfs 1.1)" ON) option(WITH_THREAD_SAFETY "Choose if a thread-safe version of libmapserver should be built (only recommended for some mapscripts)" OFF) option(WITH_GIF "Enable GIF support (for PIXMAP loading)" ON) option(WITH_PYTHON "Enable Python mapscript support" OFF) option(WITH_PHP "Enable Python mapscript support" OFF) option(WITH_PERL "Enable Perl mapscript support" OFF) option(WITH_RUBY "Enable Ruby mapscript support" OFF) option(WITH_JAVA "Enable Java mapscript support" OFF) option(WITH_CSHARP "Enable C# mapscript support" OFF) option(WITH_POINT_Z_M "include Z and M coordinates in point structure (advanced, not recommended)" OFF) option(WITH_ORACLESPATIAL "include oracle spatial database input support" OFF) option(WITH_ORACLE_PLUGIN "include oracle spatial database input support as plugin" OFF) option(WITH_MSSQL2008 "include mssql 2008 database input support as plugin" OFF) option(WITH_SDE_PLUGIN "include ArcSDE support as a plugin (must specify SDE_INCLUDE_DIR and SDE_LIBRARY_DIR)." OFF) option(WITH_SDE "include ArcSDE support. Add -DSDE_VERSION=91 to use 9.1 arcSDE version" OFF) option(WITH_EXEMPI "include xmp output metadata support" OFF) option(WITH_XMLMAPFILE "include native xml mapfile support (requires libxslt/libexslt)" OFF) option(BUILD_STATIC "Also build a static version of mapserver" OFF) option(LINK_STATIC_LIBMAPSERVER "Link to static version of libmapserver (also for mapscripts)" OFF) option(WITH_APACHE_MODULE "include (experimental) support for apache module" OFF) option(WITH_GENERIC_NINT "generic rounding" OFF) #TODO: USE_OGL? , USE_SDE, USE_CLUSTER_EXTERNAL USE_CLUSTER_PLUGIN, USE_MSSQL2008, USE_MSSQL2008_PLUGIN # SIGNORE_MISSING_DATA, CGI_CL_DEBUG_ARGS, EXTRA DEBUG FLAGS?, # PERLV_ld_DETECT? # Add compiler flags for warnings if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wdeclaration-after-statement") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") endif() if(NOT DEFINED CMAKE_INSTALL_LIBDIR) set(_LIBDIR_DEFAULT "lib") # Override this default 'lib' with 'lib64' iff: # - we are on Linux system but NOT cross-compiling # - we are NOT on debian # - we are on a 64 bits system # reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf # Note that the future of multi-arch handling may be even # more complicated than that: http://wiki.debian.org/Multiarch if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT CMAKE_CROSSCOMPILING AND NOT EXISTS "/etc/debian_version") if(NOT DEFINED CMAKE_SIZEOF_VOID_P) message(AUTHOR_WARNING "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. " "Please enable at least one language before including GNUInstallDirs.") else() if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(_LIBDIR_DEFAULT "lib64") endif() endif() endif() set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})") endif() SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) SET(CMAKE_MACOSX_RPATH ON) if(LINK_STATIC_LIBMAPSERVER) set(BUILD_STATIC 1) set(MAPSERVER_LIBMAPSERVER mapserver_static) else(LINK_STATIC_LIBMAPSERVER) set(MAPSERVER_LIBMAPSERVER mapserver) endif(LINK_STATIC_LIBMAPSERVER) set(agg_SOURCES renderers/agg/src/agg_arc.cpp renderers/agg/src/agg_vcgen_dash.cpp renderers/agg/src/agg_vcgen_contour.cpp renderers/agg/src/agg_curves.cpp renderers/agg/src/agg_embedded_raster_fonts.cpp renderers/agg/src/agg_trans_affine.cpp renderers/agg/src/agg_vcgen_stroke.cpp renderers/agg/src/agg_font_freetype.cpp renderers/agg/src/agg_line_aa_basics.cpp renderers/agg/src/clipper.cpp ) include_directories(renderers/agg/include) if(WIN32) set(REGEX_SOURCES ${REGEX_DIR}/regex.c) include_directories(${REGEX_DIR}) add_definitions(-DREGEX_MALLOC -DUSE_GENERIC_MS_NINT -DHAVE_STRING_H) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) set(REGEX_MALLOC 1) set(USE_GENERIC_MS_NINT 1) set(HAVE_STRING_H 0) else(WIN32) set(REGEX_SOURCES "") endif(WIN32) set(mapserver_SOURCES cgiutil.c mapgeos.c maporaclespatial.c mapsearch.c mapwms.c classobject.c mapgml.c mapoutput.c mapwmslayer.c layerobject.c mapgraticule.c mapows.c mapservutil.c mapxbase.c maphash.c mapowscommon.c mapshape.c mapxml.c mapbits.c maphttp.c mapparser.c mapstring.c mapxmp.c mapcairo.c mapimageio.c mappluginlayer.c mapsymbol.c mapchart.c mapimagemap.c mappool.c maptclutf.c mapcluster.c mapio.c mappostgis.c maptemplate.c mapcontext.c mapjoin.c mappostgresql.c mapthread.c mapcopy.c maplabel.c mapprimitive.c maptile.c mapcpl.c maplayer.c mapproject.c maptime.c mapcrypto.c maplegend.c hittest.c mapprojhack.c maptree.c mapdebug.c maplexer.c mapquantization.c mapunion.c mapdraw.c maplibxml2.c mapquery.c maputil.c strptime.c mapdrawgdal.c mapraster.c mapuvraster.c mapdummyrenderer.c mapobject.c maprasterquery.c mapwcs.c maperror.c mapogcfilter.c mapregex.c mapwcs11.c mapfile.c mapogcfiltercommon.c maprendering.c mapwcs20.c mapgd.c mapogcsld.c mapresample.c mapwfs.c mapgdal.c mapogcsos.c mapscale.c mapwfs11.c mapgeomtransform.c mapogroutput.c mapsde.c mapwfslayer.c mapagg.cpp mapkml.cpp mapgeomutil.cpp mapkmlrenderer.cpp mapogr.cpp mapcontour.c mapsmoothing.c ${REGEX_SOURCES}) add_library(mapserver SHARED ${mapserver_SOURCES} ${agg_SOURCES}) set_target_properties( mapserver PROPERTIES VERSION ${MapServer_VERSION_STRING} SOVERSION 1 ) if(BUILD_STATIC) add_library(mapserver_static STATIC ${mapserver_SOURCES} ${agg_SOURCES}) set_target_properties( mapserver_static PROPERTIES VERSION ${MapServer_VERSION_STRING} SOVERSION 1 ) endif(BUILD_STATIC) #SOVERSION is not necessarily the same as the #major version. The rule is that any breakage of the ABI must be #indicated by incrementing the SOVERSION. So, adding e.g. functions is no #problem, modifying argument lists or removing functions would required #the SOVERSION to be incremented. Similar rules hold of course for #non-opaque data-structures. add_executable(mapserv mapserv.c) target_link_libraries(mapserv ${MAPSERVER_LIBMAPSERVER}) add_executable(shp2img shp2img.c) target_link_libraries(shp2img ${MAPSERVER_LIBMAPSERVER}) add_executable(shptree shptree.c) target_link_libraries(shptree ${MAPSERVER_LIBMAPSERVER}) add_executable(shptreevis shptreevis.c) target_link_libraries(shptreevis ${MAPSERVER_LIBMAPSERVER}) add_executable(sortshp sortshp.c) target_link_libraries(sortshp ${MAPSERVER_LIBMAPSERVER}) add_executable(legend legend.c) target_link_libraries(legend ${MAPSERVER_LIBMAPSERVER}) add_executable(scalebar scalebar.c) target_link_libraries(scalebar ${MAPSERVER_LIBMAPSERVER}) add_executable(msencrypt msencrypt.c) target_link_libraries(msencrypt ${MAPSERVER_LIBMAPSERVER}) add_executable(tile4ms tile4ms.c) target_link_libraries(tile4ms ${MAPSERVER_LIBMAPSERVER}) add_executable(shptreetst shptreetst.c) target_link_libraries(shptreetst ${MAPSERVER_LIBMAPSERVER}) find_package(PNG) if(PNG_FOUND) include_directories(${PNG_INCLUDE_DIR}) ms_link_libraries( ${PNG_LIBRARIES}) set(USE_PNG 1) else(PNG_FOUND) report_mandatory_not_found(PNG) endif(PNG_FOUND) find_package(JPEG) if(JPEG_FOUND) include_directories(${JPEG_INCLUDE_DIR}) ms_link_libraries( ${JPEG_LIBRARY}) set(USE_JPEG 1) else(JPEG_FOUND) report_mandatory_not_found(JPEG) endif(JPEG_FOUND) find_package(Freetype) if(NOT FREETYPE_FOUND) report_mandatory_not_found(FREETYPE) endif(NOT FREETYPE_FOUND) include_directories(${FREETYPE_INCLUDE_DIR}) ms_link_libraries( ${FREETYPE_LIBRARY}) if(WITH_PROJ) find_package(Proj) if(NOT PROJ_FOUND) report_optional_not_found(PROJ) else(NOT PROJ_FOUND) include_directories(${PROJ_INCLUDE_DIR}) ms_link_libraries( ${PROJ_LIBRARY}) set (USE_PROJ 1) endif(NOT PROJ_FOUND) endif (WITH_PROJ) if(WITH_WMS) if(USE_PROJ) set(USE_WMS_SVR 1) else(USE_PROJ) report_dependency_error(WMS PROJ) endif(USE_PROJ) endif(WITH_WMS) if(WITH_GD) find_package(GD) if(NOT GD_FOUND) report_optional_not_found(GD) else(NOT GD_FOUND) include_directories(${GD_INCLUDE_DIR}) ms_link_libraries( ${GD_LIBRARY}) set (USE_GD 1) if(GD_SUPPORTS_PNG) set(USE_GD_PNG 1) endif(GD_SUPPORTS_PNG) if(GD_SUPPORTS_GIF) set(USE_GD_GIF 1) endif(GD_SUPPORTS_GIF) if(GD_SUPPORTS_JPEG) set(USE_GD_JPEG 1) endif(GD_SUPPORTS_JPEG) if(GD_SUPPORTS_FREETYPE) set(USE_GD_FREETYPE 1) endif(GD_SUPPORTS_FREETYPE) endif(NOT GD_FOUND) endif (WITH_GD) if(WITH_FRIBIDI) find_package(FriBiDi) if(NOT FRIBIDI_FOUND) report_optional_not_found(FRIBIDI) else(NOT FRIBIDI_FOUND) include_directories(${FRIBIDI_INCLUDE_DIR}) ms_link_libraries( ${FRIBIDI_LIBRARY}) set (USE_FRIBIDI 1) if(FRIBIDI_LEGACY) message(WARNING "Old Fribidi found, upgrade recommended") endif(FRIBIDI_LEGACY) endif(NOT FRIBIDI_FOUND) endif (WITH_FRIBIDI) if(WITH_ICONV) find_package(ICONV) if(ICONV_FOUND) include_directories(${ICONV_INCLUDE_DIR}) ms_link_libraries( ${ICONV_LIBRARY}) set (USE_ICONV 1) else(ICONV_FOUND) report_optional_not_found(ICONV) endif(ICONV_FOUND) endif (WITH_ICONV) if(WITH_GENERIC_NINT) set(USE_GENERIC_MS_NINT 1) endif(WITH_GENERIC_NINT) if(WITH_CAIRO) find_package(Cairo) if(CAIRO_FOUND) include_directories(${CAIRO_INCLUDE_DIRS}) ms_link_libraries( ${CAIRO_LIBRARY}) set (USE_CAIRO 1) else(CAIRO_FOUND) report_optional_not_found(CAIRO) endif(CAIRO_FOUND) endif (WITH_CAIRO) if(WITH_MYSQL) find_package(MySQL) if(MYSQL_FOUND) include_directories(${MYSQL_INCLUDE_DIR}) ms_link_libraries( ${MYSQL_LIBRARY}) set (USE_MYSQL 1) else(MYSQL_FOUND) report_optional_not_found(MYSQL) endif(MYSQL_FOUND) endif (WITH_MYSQL) if(WITH_ORACLE_PLUGIN AND WITH_ORACLESPATIAL) message(SEND_ERROR "WITH_ORACLESPATIAL and WITH_ORACLE_PLUGIN cannot be used simultaneously") endif(WITH_ORACLE_PLUGIN AND WITH_ORACLESPATIAL) if(WITH_ORACLESPATIAL OR WITH_ORACLE_PLUGIN) if(NOT DEFINED ENV{ORACLE_HOME}) MESSAGE( SEND_ERROR "ORACLE_HOME environment variable not set, needed for detection") endif() find_package(Oracle) if(ORACLE_FOUND) include_directories(${ORACLE_INCLUDE_DIR}) else(ORACLE_FOUND) report_optional_not_found(ORACLESPATIAL) #FIXME: error message here could be misleading, only states ORACLESPATIAL whereas #the request could have been for ORACLE_PLUGIN endif(ORACLE_FOUND) endif(WITH_ORACLESPATIAL OR WITH_ORACLE_PLUGIN) if(ORACLE_FOUND AND WITH_ORACLESPATIAL) ms_link_libraries( ${ORACLE_LIBRARY}) set (USE_ORACLESPATIAL 1) endif(ORACLE_FOUND AND WITH_ORACLESPATIAL) if(ORACLE_FOUND AND WITH_ORACLE_PLUGIN) add_library(msplugin_oracle MODULE maporaclespatial.c) target_link_libraries(msplugin_oracle ${ORACLE_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_oracle PROPERTIES COMPILE_FLAGS -DUSE_ORACLE_PLUGIN) set (USE_ORACLE_PLUGIN 1) endif(ORACLE_FOUND AND WITH_ORACLE_PLUGIN) if(WITH_MSSQL2008) find_package(ODBC) if(ODBC_FOUND) include_directories(${ODBC_INCLUDE_DIR}) add_library(msplugin_mssql2008 MODULE mapmssql2008.c) target_link_libraries(msplugin_mssql2008 ${ODBC_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_mssql2008 PROPERTIES COMPILE_FLAGS "-DUSE_MSSQL2008_PLUGIN -DUSE_MSSQL2008") set (USE_MSSQL2008 1) else(ODBC_FOUND) report_optional_not_found(ODBC) endif(ODBC_FOUND) endif(WITH_MSSQL2008) if(WITH_SDE_PLUGIN) if(WITH_SDE) MESSAGE( SEND_ERROR "WITH_SDE and WITH_SDE_PLUGIN cannot be used simultaneously") endif(WITH_SDE) if(SDE_INCLUDE_DIR AND SDE_LIBRARY_DIR) include_directories(${SDE_INCLUDE_DIR}) if(SDE_VERSION STREQUAL "91") add_library(msplugin_sde91 MODULE mapsde.c mapthread.c) target_link_libraries(msplugin_sde91 ${SDE_LIBRARY_DIR}/pe91.lib ${SDE_LIBRARY_DIR}/sg91.lib ${SDE_LIBRARY_DIR}/sde91.lib ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_sde91 PROPERTIES COMPILE_FLAGS "-DUSE_SDE") else(SDE_VERSION STREQUAL "91") add_library(msplugin_sde92 MODULE mapsde.c mapthread.c) target_link_libraries(msplugin_sde92 ${SDE_LIBRARY_DIR}/pe.lib ${SDE_LIBRARY_DIR}/sg.lib ${SDE_LIBRARY_DIR}/sde.lib ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_sde92 PROPERTIES COMPILE_FLAGS "-DUSE_SDE") endif(SDE_VERSION STREQUAL "91") set(USE_SDE_PLUGIN 1) else(SDE_INCLUDE_DIR AND SDE_LIBRARY_DIR) MESSAGE( SEND_ERROR "Must specify SDE_INCLUDE_DIR and SDE_LIBRARY_DIR for WITH_SDE_PLUGIN") endif(SDE_INCLUDE_DIR AND SDE_LIBRARY_DIR) endif(WITH_SDE_PLUGIN) if(WITH_SDE) find_package(SDE) if(SDE_FOUND) include_directories(${SDE_INCLUDE_DIRS}) ms_link_libraries(${SDE_LIBRARIES}) set (USE_SDE 1) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(SDE64 1) endif(CMAKE_SIZEOF_VOID_P EQUAL 8) else(SDE_FOUND) MESSAGE(WARNING "Could not find (all?) sde files. Try setting -DSDE_DIR=/path/to/sde and/or -DSDE_VERSION=91|92|100") report_optional_not_found(SDE) endif(SDE_FOUND) endif(WITH_SDE) if(WITH_FCGI) find_package(FCGI) if(FCGI_FOUND) include_directories(${FCGI_INCLUDE_DIR}) target_link_libraries(mapserv ${FCGI_LIBRARY}) set (USE_FASTCGI 1) else(FCGI_FOUND) report_optional_not_found(FCGI) endif(FCGI_FOUND) endif (WITH_FCGI) if(WITH_GEOS) find_package(GEOS) if(GEOS_FOUND) include_directories(${GEOS_INCLUDE_DIR}) ms_link_libraries( ${GEOS_LIBRARY}) set (USE_GEOS 1) else(GEOS_FOUND) report_optional_not_found(GEOS) endif(GEOS_FOUND) endif (WITH_GEOS) if(WITH_POSTGIS) find_package(PostgreSQL) if(POSTGRESQL_FOUND) #uppercase our variables if ( NOT DEFINED POSTGRESQL_LIBRARY ) set( POSTGRESQL_LIBRARY ${PostgreSQL_LIBRARY}) endif() if ( NOT DEFINED POSTGRESQL_INCLUDE_DIR ) set( POSTGRESQL_INCLUDE_DIR ${PostgreSQL_INCLUDE_DIR}) endif() include_directories(${POSTGRESQL_INCLUDE_DIR}) ms_link_libraries( ${POSTGRESQL_LIBRARY}) CHECK_LIBRARY_EXISTS(pq "PQserverVersion" POSTGRESQL_LIBRARY POSTGIS_HAS_SERVER_VERSION) set (USE_POSTGIS 1) else(POSTGRESQL_FOUND) report_optional_not_found(POSTGIS) endif(POSTGRESQL_FOUND) endif (WITH_POSTGIS) if(WITH_GDAL) find_package(GDAL) if(GDAL_FOUND) include_directories(${GDAL_INCLUDE_DIR}) ms_link_libraries( ${GDAL_LIBRARY}) set (USE_GDAL 1) else(GDAL_FOUND) report_optional_not_found(GDAL) endif(GDAL_FOUND) endif (WITH_GDAL) if(WITH_SVGCAIRO) if(WITH_RSVG) message(SEND_ERROR "WITH_SVGCAIRO cannot be enabled with WITH_RSVG") endif(WITH_RSVG) find_package(SVGCairo) if(SVGCAIRO_FOUND) include_directories(${SVGCAIRO_INCLUDE_DIR}) ms_link_libraries( ${SVG_LIBRARY} ${SVGCAIRO_LIBRARY}) set (USE_SVG_CAIRO 1) else(SVGCAIRO_FOUND) report_optional_not_found(SVGCAIRO) endif(SVGCAIRO_FOUND) endif (WITH_SVGCAIRO) if(WITH_RSVG) if(WITH_SVGCAIRO) message(SEND_ERROR "WITH_RSVG cannot be enabled with WITH_CAIROSVG") endif(WITH_SVGCAIRO) find_package(RSVG) if(RSVG_FOUND AND GOBJECT_FOUND) include_directories(${RSVG_INCLUDE_DIRS}) ms_link_libraries( ${RSVG_LIBRARY} ) include_directories(${GOBJECT_INCLUDE_DIRS}) ms_link_libraries( ${GOBJECT_LIBRARY} ) set (USE_RSVG 1) else(RSVG_FOUND AND GOBJECT_FOUND) report_optional_not_found(RSVG) endif(RSVG_FOUND AND GOBJECT_FOUND) endif (WITH_RSVG) if(WITH_OGR) if(GDAL_FOUND) set (USE_OGR 1) else(GDAL_FOUND) find_package(GDAL) if(GDAL_FOUND) include_directories(${GDAL_INCLUDE_DIR}) ms_link_libraries( ${GDAL_LIBRARY}) set (USE_OGR 1) else(GDAL_FOUND) message(SEND_ERROR "GDAL library could not be found and is needed for OGR support. HINTS: - disable OGR support by adding -DWITH_OGR=0 - add the GDAL install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/${component}-install-dir;/path/to/other/dirs\"") endif(GDAL_FOUND) endif(GDAL_FOUND) endif(WITH_OGR) if(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) set(WITH_CURL ON) endif(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(WITH_CURL) find_package(CURL) if(CURL_FOUND) include_directories(${CURL_INCLUDE_DIR}) ms_link_libraries( ${CURL_LIBRARY}) set(USE_CURL 1) else(CURL_FOUND) report_optional_not_found(CURL) endif(CURL_FOUND) endif(WITH_CURL) if(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(NOT USE_CURL) if(WITH_CLIENT_WFS) report_dependency_error(CLIENT_WFS CURL) endif(WITH_CLIENT_WFS) if(WITH_CLIENT_WMS) report_dependency_error(CLIENT_WMS CURL) endif(WITH_CLIENT_WMS) endif(NOT USE_CURL) endif(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(WITH_CLIENT_WMS) if(USE_GDAL AND USE_PROJ) set(USE_WMS_LYR 1) else(USE_GDAL AND USE_PROJ) if(NOT USE_GDAL) report_dependency_error(CLIENT_WMS GDAL) endif(NOT USE_GDAL) if( NOT USE_PROJ) report_dependency_error(CLIENT_WMS PROJ) endif(NOT USE_PROJ) endif(USE_GDAL AND USE_PROJ) endif(WITH_CLIENT_WMS) if(WITH_CLIENT_WFS) if(USE_OGR AND USE_PROJ) set(USE_WFS_LYR 1) else(USE_OGR AND USE_PROJ) if(NOT USE_OGR) report_dependency_error(CLIENT_WFS OGR) endif(NOT USE_OGR) if( NOT USE_PROJ) report_dependency_error(CLIENT_WFS PROJ) endif(NOT USE_PROJ) endif(USE_OGR AND USE_PROJ) endif(WITH_CLIENT_WFS) if(WITH_WFS) if(USE_PROJ AND USE_OGR) set(USE_WFS_SVR 1) #TODO: set WFS_USE_LIBXML2 ? else(USE_PROJ AND USE_OGR) if( NOT USE_OGR) report_dependency_error(WFS OGR) endif( NOT USE_OGR) if( NOT USE_PROJ) report_dependency_error(WFS PROJ) endif( NOT USE_PROJ) endif(USE_PROJ AND USE_OGR) endif(WITH_WFS) if(WITH_WCS) if(USE_PROJ AND USE_GDAL) set(USE_WCS_SVR 1) else(USE_PROJ AND USE_GDAL) if(NOT USE_GDAL) report_dependency_error(WCS GDAL) endif(NOT USE_GDAL) if(NOT USE_PROJ) report_dependency_error(WCS PROJ) endif(NOT USE_PROJ) endif(USE_PROJ AND USE_GDAL) endif(WITH_WCS) if(WITH_LIBXML2) find_package(LibXml2) if(LIBXML2_FOUND) include_directories(${LIBXML2_INCLUDE_DIR}) if(NOT DEFINED LIBXML2_LIBRARY) set(LIBXML2_LIBRARY ${LIBXML2_LIBRARIES}) endif() ms_link_libraries( ${LIBXML2_LIBRARY}) set (USE_LIBXML2 1) else(LIBXML2_FOUND) report_optional_not_found(LIBXML2) endif(LIBXML2_FOUND) endif (WITH_LIBXML2) if( USE_WCS_SVR AND NOT USE_LIBXML2 ) message(WARNING "WCS 1.1 and 2.0 require libxml2 support but it was not found. WCS 1.1 and 2.0 will not be supported by this build") endif( USE_WCS_SVR AND NOT USE_LIBXML2 ) if( USE_WFS_SVR AND NOT USE_LIBXML2 ) message(WARNING "WFS 1.1 requires libxml2 support but it was not found. WFS 1.1 will not be supported by this build") endif( USE_WFS_SVR AND NOT USE_LIBXML2 ) if(WITH_SOS) if(USE_PROJ AND USE_LIBXML2) set(USE_SOS_SVR 1) else(USE_PROJ AND USE_LIBXML2) if(NOT USE_LIBXML2) report_dependency_error(SOS LIBXML2) endif(NOT USE_LIBXML2) if(NOT USE_PROJ) report_dependency_error(SOS PROJ) endif(NOT USE_PROJ) endif(USE_PROJ AND USE_LIBXML2) endif(WITH_SOS) if(WITH_POINT_Z_M) set(USE_POINT_Z_M 1) endif(WITH_POINT_Z_M) if(WITH_KML) if(USE_LIBXML2) set(USE_KML 1) else(USE_LIBXML2) report_dependency_error(KML LIBXML2) endif(USE_LIBXML2) endif(WITH_KML) if(WITH_THREAD_SAFETY) set( CMAKE_THREAD_PREFER_PTHREAD 1 ) find_package(Threads) if (THREADS_FOUND) ms_link_libraries( ${CMAKE_THREAD_LIBS_INIT}) set(USE_THREAD 1) endif (THREADS_FOUND) endif(WITH_THREAD_SAFETY) if(WITH_XMLMAPFILE) if(NOT USE_LIBXML2) report_dependency_error(KML LIBXML2) endif(NOT USE_LIBXML2) #check for xslt and exslt find_package(LibXslt) if(LIBXSLT_FOUND) if(NOT DEFINED LIBXSLT_LIBRARY) set(LIBXSLT_LIBRARY ${LIBXSLT_LIBRARIES}) endif() include_directories(${LIBXSLT_INCLUDE_DIR}) ms_link_libraries( ${LIBXSLT_LIBRARY} ${LIBXSLT_EXSLT_LIBRARY}) set(USE_XMLMAPFILE 1) else(LIBXSLT_FOUND) message(SEND_ERROR "Xml Mapfile support requires XSLT support which was not found. HINTS: - add the libxslt install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/libxslt-install-dir;/path/to/other/dirs\" - disable Xml Mapfile support by adding -DWITH_XMLMAPFILE=0" ) endif(LIBXSLT_FOUND) endif(WITH_XMLMAPFILE) if(WITH_GIF) find_package(GIF) if(GIF_FOUND) include_directories(${GIF_INCLUDE_DIR}) ms_link_libraries( ${GIF_LIBRARY}) set(USE_GIF 1) else(GIF_FOUND) report_optional_not_found(GIF) endif(GIF_FOUND) endif(WITH_GIF) if(WITH_EXEMPI) find_package(Exempi) if(LIBEXEMPI_FOUND) include_directories(${LIBEXEMPI_INCLUDE_DIR}) ms_link_libraries( ${LIBEXEMPI_LIBRARY}) set(USE_EXEMPI 1) else(LIBEXEMPI_FOUND) report_optional_not_found(EXEMPI) endif(LIBEXEMPI_FOUND) endif(WITH_EXEMPI) if(WITH_PYTHON) add_subdirectory("mapscript/python") set(USE_PYTHON_MAPSCRIPT 1) endif(WITH_PYTHON) if(WITH_PHP) add_subdirectory("mapscript/php") set(USE_PHP_MAPSCRIPT 1) endif(WITH_PHP) if(WITH_APACHE_MODULE) add_subdirectory("apache") set(USE_APACHE_MODULE 1) endif(WITH_APACHE_MODULE) if(WITH_PERL) add_subdirectory("mapscript/perl") set(USE_PERL_MAPSCRIPT 1) endif(WITH_PERL) if(WITH_RUBY) add_subdirectory("mapscript/ruby") set(USE_RUBY_MAPSCRIPT 1) endif(WITH_RUBY) if(WITH_JAVA) add_subdirectory("mapscript/java") set(USE_JAVA_MAPSCRIPT 1) endif(WITH_JAVA) if(WITH_CSHARP) add_subdirectory("mapscript/csharp") set(USE_CSHARP_MAPSCRIPT 1) endif(WITH_CSHARP) if(UNIX) ms_link_libraries( ${CMAKE_DL_LIBS} m ) endif(UNIX) if (WIN32) ms_link_libraries( ${MS_EXTERNAL_LIBS}) endif (WIN32) configure_file ( "${PROJECT_SOURCE_DIR}/mapserver-config.h.in" "${PROJECT_BINARY_DIR}/mapserver-config.h" ) configure_file ( "${PROJECT_SOURCE_DIR}/mapserver-version.h.in" "${PROJECT_BINARY_DIR}/mapserver-version.h" ) macro(status_optional_component component enabled libpath) if("${enabled}" EQUAL "1") message(STATUS " * ${component}: ${libpath}") else() message(STATUS " * ${component}: disabled") endif() endmacro() macro(status_optional_feature feature enabled) if("${enabled}" EQUAL "1") message(STATUS " * ${feature}: ENABLED") else() message(STATUS " * ${feature}: disabled") endif() endmacro() message(STATUS "* Summary of configured options for this build") message(STATUS " * Mandatory components") message(STATUS " * png: ${PNG_LIBRARY}") message(STATUS " * jpeg: ${JPEG_LIBRARY}") message(STATUS " * freetype: ${FREETYPE_LIBRARY}") message(STATUS " * Optional components") status_optional_component("GDAL" "${USE_GDAL}" "${GDAL_LIBRARY}") status_optional_component("OGR" "${USE_OGR}" "${GDAL_LIBRARY}") status_optional_component("GD" "${USE_GD}" "${GD_LIBRARY}") status_optional_component("GIF" "${USE_GIF}" "${GIF_LIBRARY}") status_optional_component("MYSQL" "${USE_MYSQL}" "${MYSQL_LIBRARY}") status_optional_component("FRIBIDI" "${USE_FRIBIDI}" "${FRIBIDI_LIBRARY}") status_optional_component("GIF" "${USE_GIF}" "${GIF_LIBRARY}") status_optional_component("CAIRO" "${USE_CAIRO}" "${CAIRO_LIBRARY}") status_optional_component("SVGCAIRO" "${USE_SVG_CAIRO}" "${SVGCAIRO_LIBRARY}") status_optional_component("RSVG" "${USE_RSVG}" "${RSVG_LIBRARY}") status_optional_component("CURL" "${USE_CURL}" "${CURL_LIBRARY}") status_optional_component("PROJ" "${USE_PROJ}" "${PROJ_LIBRARY}") status_optional_component("LIBXML2" "${USE_LIBXML2}" "${LIBXML2_LIBRARY}") status_optional_component("POSTGIS" "${USE_POSTGIS}" "${POSTGRESQL_LIBRARY}") status_optional_component("GEOS" "${USE_GEOS}" "${GEOS_LIBRARY}") status_optional_component("FastCGI" "${USE_FASTCGI}" "${FCGI_LIBRARY}") if(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) if(USE_ORACLESPATIAL) status_optional_component("Oracle Spatial" "${USE_ORACLESPATIAL}" "${ORACLE_LIBRARY}") else(USE_ORACLESPATIAL) status_optional_component("Oracle Spatial (Built as plugin)" "${USE_ORACLE_PLUGIN}" "${ORACLE_LIBRARY}") endif(USE_ORACLESPATIAL) else(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) status_optional_component("Oracle Spatial" "" "${ORACLE_LIBRARY}") endif(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) if(USE_MSSQL2008) status_optional_component("MSSQL 2008 (Built as plugin)" "${USE_MSSQL2008}" "${ODBC_LIBRARY}") endif(USE_MSSQL2008) if(USE_SDE_PLUGIN) if(SDE_VERSION STREQUAL "91") status_optional_component("SDE 9.1 (Built as plugin)" "${USE_SDE_PLUGIN}" "${SDE_LIBRARY_DIR}") else(SDE_VERSION STREQUAL "91") status_optional_component("SDE 9.2 (Built as plugin)" "${USE_SDE_PLUGIN}" "${SDE_LIBRARY_DIR}") endif(SDE_VERSION STREQUAL "91") else(USE_SDE_PLUGIN) status_optional_component("SDE" "${USE_SDE}" "${SDE_LIBRARIES}") endif(USE_SDE_PLUGIN) status_optional_component("Exempi XMP" "${USE_EXEMPI}" "${LIBEXEMPI_LIBRARY}") message(STATUS " * Optional features") status_optional_feature("WMS SERVER" "${USE_WMS_SVR}") status_optional_feature("WFS SERVER" "${USE_WFS_SVR}") status_optional_feature("WCS SERVER" "${USE_WCS_SVR}") status_optional_feature("SOS SERVER" "${USE_SOS_SVR}") status_optional_feature("WMS CLIENT" "${USE_WMS_LYR}") status_optional_feature("WFS CLIENT" "${USE_WFS_LYR}") status_optional_feature("ICONV" "${USE_ICONV}") status_optional_feature("Thread-safety support" "${USE_THREAD}") status_optional_feature("KML output" "${USE_KML}") status_optional_feature("Z+M point coordinate support" "${USE_POINT_Z_M}") status_optional_feature("XML Mapfile support" "${USE_XMLMAPFILE}") message(STATUS " * Mapscripts") status_optional_feature("Python" "${USE_PYTHON_MAPSCRIPT}") status_optional_feature("PHP" "${USE_PHP_MAPSCRIPT}") status_optional_feature("PERL" "${USE_PERL_MAPSCRIPT}") status_optional_feature("RUBY" "${USE_RUBY_MAPSCRIPT}") status_optional_feature("JAVA" "${USE_JAVA_MAPSCRIPT}") status_optional_feature("C#" "${USE_CSHARP_MAPSCRIPT}") status_optional_feature("Apache Module (Experimental)" "${USE_APACHE_MODULE}") message(STATUS "") message(STATUS "Will install files to ${CMAKE_INSTALL_PREFIX}") message(STATUS "Will install libraries to ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") include_directories("${PROJECT_BINARY_DIR}") if(WIN32) set(REGEX_MALLOC 1) set(USE_GENERIC_MS_NINT 1) endif(WIN32) #INSTALL(FILES mapserver-api.h ${PROJECT_BINARY_DIR}/mapserver-version.h DESTINATION include) if(USE_ORACLE_PLUGIN) INSTALL(TARGETS msplugin_oracle DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(USE_ORACLE_PLUGIN) if(USE_MSSQL2008) INSTALL(TARGETS msplugin_mssql2008 DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(USE_MSSQL2008) if(USE_SDE91) INSTALL(TARGETS msplugin_sde91 DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(USE_SDE91) if(USE_SDE92) INSTALL(TARGETS msplugin_sde92 DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(USE_SDE92) INSTALL(TARGETS sortshp shptree shptreevis msencrypt legend scalebar tile4ms shptreetst shp2img mapserv mapserver RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) if(BUILD_STATIC) INSTALL(TARGETS mapserver_static DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif(BUILD_STATIC) mapserver-6.4.1/.gitattributes0000644002461700001440000000006612261257215016211 0ustar tbonfortusers.gitattributes export-ignore .gitignore export-ignore mapserver-6.4.1/MIGRATION_GUIDE.txt0000644002461700001440000000105212261257215016321 0ustar tbonfortusers***************************************************************************** MapServer Migration Guide ***************************************************************************** The current version of the MapServer Migration Guide is available online at http://www.mapserver.org/MIGRATION_GUIDE.html. For developers: The master copy of the MIGRATION_GUIDE is now located in the root of the mapserver/docs source tree (https://github.com/mapserver/docs). Developers are welcome and encouraged to edit/update the guide in the docs tree directly. mapserver-6.4.1/mapwcs.c0000644002461700001440000033473512261257215014771 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OpenGIS Web Coverage Server (WCS) Implementation. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include #if defined(USE_WCS_SVR) #include "mapwcs.h" #include "maptime.h" #include #include "gdal.h" #include "cpl_string.h" /* GDAL string handling */ /************************************************************************/ /* msWCSValidateRangeSetParam() */ /************************************************************************/ static int msWCSValidateRangeSetParam(layerObj *lp, char *name, const char *value) { char **allowed_ri_values; char **client_ri_values; int allowed_count, client_count; int i_client, i, all_match = 1; char *tmpname = NULL; const char *ri_values_list; if( name == NULL ) return MS_FAILURE; /* Fetch the available values list for the rangeset item and tokenize */ tmpname = (char *)msSmallMalloc(sizeof(char)*strlen(name) + 10); sprintf(tmpname,"%s_values", name); ri_values_list = msOWSLookupMetadata(&(lp->metadata), "CO", tmpname); msFree( tmpname ); if (ri_values_list == NULL) return MS_FAILURE; allowed_ri_values = msStringSplit( ri_values_list, ',', &allowed_count); /* Parse the client value list into tokens. */ client_ri_values = msStringSplit( value, ',', &client_count ); /* test each client value against the allowed list. */ for( i_client = 0; all_match && i_client < client_count; i_client++ ) { for( i = 0; i < allowed_count && strcasecmp(client_ri_values[i_client], allowed_ri_values[i]) != 0; i++ ) {} if( i == allowed_count ) all_match = 0; } msFreeCharArray(allowed_ri_values, allowed_count ); msFreeCharArray(client_ri_values, client_count ); if (all_match == 0) return MS_FAILURE; else return MS_SUCCESS; } /************************************************************************/ /* msWCSConvertRangeSetToString() */ /************************************************************************/ static char *msWCSConvertRangeSetToString(const char *value) { char **tokens; int numtokens; double min, max, res; double val; char buf1[128], *buf2=NULL; if(strchr(value, '/')) { /* value is min/max/res */ tokens = msStringSplit(value, '/', &numtokens); if(tokens==NULL || numtokens != 3) { msFreeCharArray(tokens, numtokens); return NULL; /* not a set of equally spaced intervals */ } min = atof(tokens[0]); max = atof(tokens[1]); res = atof(tokens[2]); msFreeCharArray(tokens, numtokens); for(val=min; val<=max; val+=res) { if(val == min) snprintf(buf1, sizeof(buf1), "%g", val); else snprintf(buf1, sizeof(buf1), ",%g", val); buf2 = msStringConcatenate(buf2, buf1); } return buf2; } else return msStrdup(value); } /************************************************************************/ /* msWCSException() */ /************************************************************************/ int msWCSException(mapObj *map, const char *code, const char *locator, const char *version ) { char *pszEncodedVal = NULL; const char *encoding; char version_string[OWS_VERSION_MAXLEN]; if( version == NULL ) version = "1.0.0"; #if defined(USE_LIBXML2) if( msOWSParseVersionString(version) >= OWS_2_0_0 ) return msWCSException20( map, code, locator, msOWSGetVersionString(msOWSParseVersionString(version), version_string) ); #endif if( msOWSParseVersionString(version) >= OWS_1_1_0 ) return msWCSException11( map, code, locator, msOWSGetVersionString(msOWSParseVersionString(version), version_string) ); encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.se_xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.se_xml"); msIO_sendHeaders(); /* msIO_printf("Content-Type: text/xml%c%c",10,10); */ msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), NULL, "wcs_encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n", pszEncodedVal); msFree(pszEncodedVal); msIO_printf(" "); msWriteErrorXML(stdout); msIO_printf(" \n"); msIO_printf("\n"); msResetErrorList(); return MS_FAILURE; } /************************************************************************/ /* msWCSPrintRequestCapability() */ /************************************************************************/ static void msWCSPrintRequestCapability(const char *version, const char *request_tag, const char *script_url) { msIO_printf(" <%s>\n", request_tag); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", script_url); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", script_url); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", request_tag); } /************************************************************************/ /* msWCSCreateParams() */ /************************************************************************/ static wcsParamsObj *msWCSCreateParams() { wcsParamsObj *params; params = (wcsParamsObj *) calloc(1, sizeof(wcsParamsObj)); MS_CHECK_ALLOC(params, sizeof(wcsParamsObj), NULL); return params; } /************************************************************************/ /* msWCSFreeParams() */ /************************************************************************/ void msWCSFreeParams(wcsParamsObj *params) { if(params) { /* TODO */ if(params->version) free(params->version); if(params->updatesequence) free(params->updatesequence); if(params->request) free(params->request); if(params->service) free(params->service); if(params->section) free(params->section); if(params->crs) free(params->crs); if(params->response_crs) free(params->response_crs); if(params->format) free(params->format); if(params->exceptions) free(params->exceptions); if(params->time) free(params->time); if(params->interpolation) free(params->interpolation); CSLDestroy( params->coverages ); } } /************************************************************************/ /* msWCSIsLayerSupported() */ /************************************************************************/ int msWCSIsLayerSupported(layerObj *layer) { /* only raster layers, are elligible to be served via WCS, WMS rasters are not ok */ if((layer->type == MS_LAYER_RASTER) && layer->connectiontype != MS_WMS && layer->name != NULL) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* msWCSGetRequestParameter() */ /* */ /************************************************************************/ const char *msWCSGetRequestParameter(cgiRequestObj *request, char *name) { int i; if(!request || !name) /* nothing to do */ return NULL; if(request->NumParams > 0) { for(i=0; iNumParams; i++) { if(strcasecmp(request->ParamNames[i], name) == 0) return request->ParamValues[i]; } } return NULL; } /************************************************************************/ /* msWCSSetDefaultBandsRangeSetInfo() */ /************************************************************************/ void msWCSSetDefaultBandsRangeSetInfo( wcsParamsObj *params, coverageMetadataObj *cm, layerObj *lp ) { /* This function will provide default rangeset information for the "special" */ /* "bands" rangeset if it appears in the axes list but has no specifics provided */ /* in the metadata. */ const char *value; char *bandlist; size_t bufferSize = 0; int i; /* Does this item exist in the axes list? */ value = msOWSLookupMetadata(&(lp->metadata), "CO", "rangeset_axes"); if( value == NULL ) return; value = strstr(value,"bands"); if( value == NULL || (value[5] != '\0' && value[5] != ' ') ) return; /* Are there any w*s_bands_ metadata already? If so, skip out. */ if( msOWSLookupMetadata(&(lp->metadata), "CO", "bands_description") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_name") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_label") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_values") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_values_semantic") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_values_type") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_rangeitem") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_semantic") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_refsys") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_refsyslabel") != NULL || msOWSLookupMetadata(&(lp->metadata), "CO", "bands_interval") != NULL ) return; /* OK, we have decided to fill in the information. */ msInsertHashTable( &(lp->metadata), "wcs_bands_name", "bands" ); msInsertHashTable( &(lp->metadata), "wcs_bands_label", "Bands/Channels/Samples" ); msInsertHashTable( &(lp->metadata), "wcs_bands_rangeitem", "_bands" ); /* ? */ bufferSize = cm->bandcount*30+30; bandlist = (char *) msSmallMalloc(bufferSize); strcpy( bandlist, "1" ); for( i = 1; i < cm->bandcount; i++ ) snprintf( bandlist+strlen(bandlist), bufferSize-strlen(bandlist), ",%d", i+1 ); msInsertHashTable( &(lp->metadata), "wcs_bands_values", bandlist ); free( bandlist ); } /************************************************************************/ /* msWCSParseRequest() */ /************************************************************************/ static int msWCSParseRequest(cgiRequestObj *request, wcsParamsObj *params, mapObj *map) { int i, n; char **tokens; if(!request || !params) /* nothing to do */ return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Check if this appears to be an XML POST WCS request. */ /* -------------------------------------------------------------------- */ msDebug("msWCSParseRequest(): request is %s.\n", (request->type == MS_POST_REQUEST)?"POST":"KVP"); if( request->type == MS_POST_REQUEST && request->postrequest ) { #if defined(USE_LIBXML2) xmlDocPtr doc = NULL; xmlNodePtr root = NULL, child = NULL; char *tmp = NULL; /* parse to DOM-Structure and get root element */ if((doc = xmlParseMemory(request->postrequest, strlen(request->postrequest))) == NULL) { xmlErrorPtr error = xmlGetLastError(); msSetError(MS_WCSERR, "XML parsing error: %s", "msWCSParseRequest()", error->message); return MS_FAILURE; } root = xmlDocGetRootElement(doc); /* Get service, version and request from root */ params->request = strdup((char *) root->name); if ((tmp = (char *) xmlGetProp(root, BAD_CAST "service")) != NULL) params->service = tmp; if ((tmp = (char *) xmlGetProp(root, BAD_CAST "version")) != NULL) params->version = tmp; /* search first level children, either CoverageID, */ for (child = root->children; child != NULL; child = child->next) { if (EQUAL((char *)child->name, "AcceptVersions")) { /* will be overridden to 1.1.1 anyway */ } else if (EQUAL((char *) child->name, "UpdateSequence")) { params->updatesequence = (char *)xmlNodeGetContent(child); } else if (EQUAL((char *) child->name, "Sections")) { xmlNodePtr sectionNode = NULL; /* concatenate all sections by ',' */ for(sectionNode = child->children; sectionNode != NULL; sectionNode = sectionNode->next) { char *content; if(!EQUAL((char *)sectionNode->name, "Section")) continue; content = (char *)xmlNodeGetContent(sectionNode); if(!params->section) { params->section = content; } else { params->section = msStringConcatenate(params->section, ","); params->section = msStringConcatenate(params->section, content); xmlFree(content); } } } else if(EQUAL((char *) child->name, "AcceptFormats")) { /* TODO: implement */ } else if(EQUAL((char *) child->name, "Identifier")) { char *content = (char *)xmlNodeGetContent(child); params->coverages = CSLAddString(params->coverages, content); xmlFree(content); } else if(EQUAL((char *) child->name, "DomainSubset")) { xmlNodePtr tmpNode = NULL; for(tmpNode = child->children; tmpNode != NULL; tmpNode = tmpNode->next) { if(EQUAL((char *) tmpNode->name, "BoundingBox")) { xmlNodePtr cornerNode = NULL; params->crs = (char *)xmlGetProp(tmpNode, BAD_CAST "crs"); if( strncasecmp(params->crs,"urn:ogc:def:crs:",16) == 0 && strncasecmp(params->crs+strlen(params->crs)-8,"imageCRS",8)==0) strcpy( params->crs, "imageCRS" ); for(cornerNode = tmpNode->children; cornerNode != NULL; cornerNode = cornerNode->next) { if(EQUAL((char *) cornerNode->name, "LowerCorner")) { char *value = (char *)xmlNodeGetContent(cornerNode); tokens = msStringSplit(value, ' ', &n); if(tokens==NULL || n < 2) { msSetError(MS_WCSERR, "Wrong number of arguments for LowerCorner", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "LowerCorner", params->version ); } params->bbox.minx = atof(tokens[0]); params->bbox.miny = atof(tokens[1]); msFreeCharArray(tokens, n); xmlFree(value); } if(EQUAL((char *) cornerNode->name, "UpperCorner")) { char *value = (char *)xmlNodeGetContent(cornerNode); tokens = msStringSplit(value, ' ', &n); if(tokens==NULL || n < 2) { msSetError(MS_WCSERR, "Wrong number of arguments for UpperCorner", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "UpperCorner", params->version ); } params->bbox.maxx = atof(tokens[0]); params->bbox.maxy = atof(tokens[1]); msFreeCharArray(tokens, n); xmlFree(value); } } } } } else if(EQUAL((char *) child->name, "RangeSubset")) { /* TODO: not implemented in mapserver WCS 1.1? */ } else if(EQUAL((char *) child->name, "Output")) { xmlNodePtr tmpNode = NULL; params->format = (char *)xmlGetProp(child, BAD_CAST "format"); for(tmpNode = child->children; tmpNode != NULL; tmpNode = tmpNode->next) { if(EQUAL((char *) tmpNode->name, "GridCRS")) { xmlNodePtr crsNode = NULL; for(crsNode = tmpNode->children; crsNode != NULL; crsNode = crsNode->next) { if(EQUAL((char *) crsNode->name, "GridBaseCRS")) { params->response_crs = (char *) xmlNodeGetContent(crsNode); } else if (EQUAL((char *) crsNode->name, "GridOrigin")) { char *value = (char *)xmlNodeGetContent(crsNode); tokens = msStringSplit(value, ' ', &n); if(tokens==NULL || n < 2) { msSetError(MS_WCSERR, "Wrong number of arguments for GridOrigin", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "GridOffsets", params->version ); } params->originx = atof(tokens[0]); params->originy = atof(tokens[1]); msFreeCharArray(tokens, n); xmlFree(value); } else if (EQUAL((char *) crsNode->name, "GridOffsets")) { char *value = (char *)xmlNodeGetContent(crsNode); tokens = msStringSplit(value, ' ', &n); if(tokens==NULL || n < 2) { msSetError(MS_WCSERR, "Wrong number of arguments for GridOffsets", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "GridOffsets", params->version ); } /* take absolute values to convert to positive RESX/RESY style WCS 1.0 behavior. *but* this does break some possibilities! */ params->resx = fabs(atof(tokens[0])); params->resy = fabs(atof(tokens[1])); msFreeCharArray(tokens, n); xmlFree(value); } } } } } } xmlFreeDoc(doc); xmlCleanupParser(); return MS_SUCCESS; #else /* defined(USE_LIBXML2) */ msSetError(MS_WCSERR, "To enable POST requests, MapServer has to " "be compiled with libxml2.", "msWCSParseRequest()"); return MS_FAILURE; #endif /* defined(USE_LIBXML2) */ } /* -------------------------------------------------------------------- */ /* Extract WCS KVP Parameters. */ /* -------------------------------------------------------------------- */ if(request->NumParams > 0) { for(i=0; iNumParams; i++) { if(strcasecmp(request->ParamNames[i], "VERSION") == 0) params->version = msStrdup(request->ParamValues[i]); if(strcasecmp(request->ParamNames[i], "UPDATESEQUENCE") == 0) params->updatesequence = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "REQUEST") == 0) params->request = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "INTERPOLATION") == 0) params->interpolation = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "SERVICE") == 0) params->service = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "SECTION") == 0) /* 1.0 */ params->section = msStrdup(request->ParamValues[i]); /* TODO: validate value here */ else if(strcasecmp(request->ParamNames[i], "SECTIONS") == 0) /* 1.1 */ params->section = msStrdup(request->ParamValues[i]); /* TODO: validate value here */ /* GetCoverage parameters. */ else if(strcasecmp(request->ParamNames[i], "BBOX") == 0) { tokens = msStringSplit(request->ParamValues[i], ',', &n); if(tokens==NULL || n != 4) { msSetError(MS_WCSERR, "Wrong number of arguments for BBOX.", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "bbox", params->version ); } params->bbox.minx = atof(tokens[0]); params->bbox.miny = atof(tokens[1]); params->bbox.maxx = atof(tokens[2]); params->bbox.maxy = atof(tokens[3]); msFreeCharArray(tokens, n); } else if(strcasecmp(request->ParamNames[i], "RESX") == 0) params->resx = atof(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "RESY") == 0) params->resy = atof(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "WIDTH") == 0) params->width = atoi(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "HEIGHT") == 0) params->height = atoi(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "COVERAGE") == 0) params->coverages = CSLAddString(params->coverages, request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "TIME") == 0) params->time = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "FORMAT") == 0) params->format = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "CRS") == 0) params->crs = msStrdup(request->ParamValues[i]); else if(strcasecmp(request->ParamNames[i], "RESPONSE_CRS") == 0) params->response_crs = msStrdup(request->ParamValues[i]); /* WCS 1.1 DescribeCoverage and GetCoverage ... */ else if(strcasecmp(request->ParamNames[i], "IDENTIFIER") == 0 || strcasecmp(request->ParamNames[i], "IDENTIFIERS") == 0 ) { msDebug("msWCSParseRequest(): Whole String: %s\n", request->ParamValues[i]); params->coverages = CSLAddString(params->coverages, request->ParamValues[i]); } /* WCS 1.1 style BOUNDINGBOX */ else if(strcasecmp(request->ParamNames[i], "BOUNDINGBOX") == 0) { tokens = msStringSplit(request->ParamValues[i], ',', &n); if(tokens==NULL || n < 5) { msSetError(MS_WCSERR, "Wrong number of arguments for BOUNDINGBOX.", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "boundingbox", params->version ); } /* NOTE: WCS 1.1 boundingbox is center of pixel oriented, not edge like in WCS 1.0. So bbox semantics are wonky till this is fixed later in the GetCoverage processing. */ params->bbox.minx = atof(tokens[0]); params->bbox.miny = atof(tokens[1]); params->bbox.maxx = atof(tokens[2]); params->bbox.maxy = atof(tokens[3]); params->crs = msStrdup(tokens[4]); msFreeCharArray(tokens, n); /* normalize imageCRS urns to simply "imageCRS" */ if( strncasecmp(params->crs,"urn:ogc:def:crs:",16) == 0 && strncasecmp(params->crs+strlen(params->crs)-8,"imageCRS",8)==0) strcpy( params->crs, "imageCRS" ); } else if(strcasecmp(request->ParamNames[i], "GridOffsets") == 0) { tokens = msStringSplit(request->ParamValues[i], ',', &n); if(tokens==NULL || n < 2) { msSetError(MS_WCSERR, "Wrong number of arguments for GridOffsets", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "GridOffsets", params->version ); } /* take absolute values to convert to positive RESX/RESY style WCS 1.0 behavior. *but* this does break some possibilities! */ params->resx = fabs(atof(tokens[0])); params->resy = fabs(atof(tokens[1])); msFreeCharArray(tokens, n); } else if(strcasecmp(request->ParamNames[i], "GridOrigin") == 0) { tokens = msStringSplit(request->ParamValues[i], ',', &n); if(tokens==NULL || n < 2) { msSetError(MS_WCSERR, "Wrong number of arguments for GridOrigin", "msWCSParseRequest()"); return msWCSException(map, "InvalidParameterValue", "GridOffsets", params->version ); } params->originx = atof(tokens[0]); params->originy = atof(tokens[1]); msFreeCharArray(tokens, n); } /* and so on... */ } } /* we are not dealing with an XML encoded request at this point */ return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities_Service_ResponsibleParty() */ /************************************************************************/ static void msWCSGetCapabilities_Service_ResponsibleParty(mapObj *map) { int bEnableTelephone=MS_FALSE, bEnableAddress=MS_FALSE, bEnableOnlineResource=MS_FALSE; /* the WCS-specific way */ if(msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_individualname") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_organizationname")) { msIO_printf("\n"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_individualname", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_organizationname", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_positionname", OWS_NOERR, " %s\n", NULL); if(msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_phone_voice") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_phone_facsimile")) bEnableTelephone = MS_TRUE; if(msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_address_deliverypoint") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_address_city") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_address_administrativearea") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_address_postalcode") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_address_country") || msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_address_electronicmailaddress")) bEnableAddress = MS_TRUE; if(msOWSLookupMetadata(&(map->web.metadata), "CO", "responsibleparty_onlineresource")) bEnableOnlineResource = MS_TRUE; if(bEnableTelephone || bEnableAddress || bEnableOnlineResource) { msIO_printf(" \n"); if(bEnableTelephone) { msIO_printf(" \n"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_phone_voice", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_phone_facsimile", OWS_NOERR, " %s\n", NULL); msIO_printf(" \n"); } if(bEnableAddress) { msIO_printf("
\n"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_address_deliverypoint", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_address_city", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_address_administrativearea", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_address_postalcode", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_address_country", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_address_electronicmailaddress", OWS_NOERR, " %s\n", NULL); msIO_printf("
\n"); } msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "responsibleparty_onlineresource", OWS_NOERR, " \n", NULL); msIO_printf("
\n"); } msIO_printf("
\n"); } else if(msOWSLookupMetadata(&(map->web.metadata), "CO", "contactperson") || msOWSLookupMetadata(&(map->web.metadata), "CO", "contactorganization")) { /* leverage WMS contact information */ msIO_printf("\n"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "contactperson", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "contactorganization", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "contactposition", OWS_NOERR, " %s\n", NULL); if(msOWSLookupMetadata(&(map->web.metadata), "CO", "contactvoicetelephone") || msOWSLookupMetadata(&(map->web.metadata), "CO", "contactfacsimiletelephone")) bEnableTelephone = MS_TRUE; if(msOWSLookupMetadata(&(map->web.metadata), "CO", "address") || msOWSLookupMetadata(&(map->web.metadata), "CO", "city") || msOWSLookupMetadata(&(map->web.metadata), "CO", "stateorprovince") || msOWSLookupMetadata(&(map->web.metadata), "CO", "postcode") || msOWSLookupMetadata(&(map->web.metadata), "CO", "country") || msOWSLookupMetadata(&(map->web.metadata), "CO", "contactelectronicmailaddress")) bEnableAddress = MS_TRUE; if(msOWSLookupMetadata(&(map->web.metadata), "CO", "service_onlineresource")) bEnableOnlineResource = MS_TRUE; if(bEnableTelephone || bEnableAddress || bEnableOnlineResource) { msIO_printf(" \n"); if(bEnableTelephone) { msIO_printf(" \n"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "contactvoicetelephone", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "contactfacsimiletelephone", OWS_NOERR, " %s\n", NULL); msIO_printf(" \n"); } if(bEnableAddress) { msIO_printf("
\n"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "address", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "city", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "stateorprovince", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "postcode", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "country", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "contactelectronicmailaddress", OWS_NOERR, " %s\n", NULL); msIO_printf("
\n"); } msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "service_onlineresource", OWS_NOERR, " \n", NULL); msIO_printf("
\n"); } msIO_printf("
\n"); } return; } /************************************************************************/ /* msWCSGetCapabilities_Service() */ /************************************************************************/ static int msWCSGetCapabilities_Service(mapObj *map, wcsParamsObj *params) { /* start the Service section, only need the full start tag if this is the only section requested */ if(!params->section || (params->section && strcasecmp(params->section, "/") == 0)) msIO_printf("\n"); else msIO_printf("\n", params->version, params->updatesequence, msOWSGetSchemasLocation(map), params->version); /* optional metadataLink */ msOWSPrintURLType(stdout, &(map->web.metadata), "CO", "metadatalink", OWS_NOERR, " ", NULL, " metadataType=\"%s\"", NULL, NULL, NULL, " xlink:href=\"%s\"", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, "other", NULL, NULL, NULL, NULL, NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "description", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "name", OWS_NOERR, " %s\n", "MapServer WCS"); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "label", OWS_WARN, " \n", NULL); /* we are not supporting the optional keyword type, at least not yet */ msOWSPrintEncodeMetadataList(stdout, &(map->web.metadata), "CO", "keywordlist", " \n", " \n", " %s\n", NULL); msWCSGetCapabilities_Service_ResponsibleParty(map); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "CO", "fees", OWS_NOERR, " %s\n", "NONE"); msOWSPrintEncodeMetadataList(stdout, &(map->web.metadata), "CO", "accessconstraints", " \n", " \n", " %s\n", "NONE"); /* done */ msIO_printf("\n"); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities_Capability() */ /************************************************************************/ static int msWCSGetCapabilities_Capability(mapObj *map, wcsParamsObj *params, cgiRequestObj *req) { char *script_url=NULL, *script_url_encoded=NULL; /* we need this server's onlineresource for the request section */ if((script_url=msOWSGetOnlineResource(map, "CO", "onlineresource", req)) == NULL || (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL) { free(script_url); free(script_url_encoded); return msWCSException(map, NULL, NULL, params->version ); } /* start the Capabilty section, only need the full start tag if this is the only section requested */ if(!params->section || (params->section && strcasecmp(params->section, "/") == 0)) msIO_printf("\n"); else msIO_printf("\n", params->version, params->updatesequence, msOWSGetSchemasLocation(map), params->version); /* describe the types of requests the server can handle */ msIO_printf(" \n"); msWCSPrintRequestCapability(params->version, "GetCapabilities", script_url_encoded); if (msOWSRequestIsEnabled(map, NULL, "C", "DescribeCoverage", MS_FALSE)) msWCSPrintRequestCapability(params->version, "DescribeCoverage", script_url_encoded); if (msOWSRequestIsEnabled(map, NULL, "C", "GetCoverage", MS_FALSE)) msWCSPrintRequestCapability(params->version, "GetCoverage", script_url_encoded); msIO_printf(" \n"); /* describe the exception formats the server can produce */ msIO_printf(" \n"); msIO_printf(" application/vnd.ogc.se_xml\n"); msIO_printf(" \n"); /* describe any vendor specific capabilities */ /* msIO_printf(" \n"); */ /* none yet */ /* done */ msIO_printf("\n"); free(script_url); free(script_url_encoded); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities_CoverageOfferingBrief() */ /************************************************************************/ static int msWCSGetCapabilities_CoverageOfferingBrief(layerObj *layer, wcsParamsObj *params) { coverageMetadataObj cm; int status; if((layer->status == MS_DELETE) || !msWCSIsLayerSupported(layer)) return MS_SUCCESS; /* not an error, this layer cannot be served via WCS */ status = msWCSGetCoverageMetadata(layer, &cm); if(status != MS_SUCCESS) return MS_FAILURE; /* start the CoverageOfferingBrief section */ msIO_printf(" \n"); /* is this tag right? (I hate schemas without ANY examples) */ /* optional metadataLink */ msOWSPrintURLType(stdout, &(layer->metadata), "CO", "metadatalink", OWS_NOERR, " ", NULL, " metadataType=\"%s\"", NULL, NULL, NULL, " xlink:href=\"%s\"", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, "other", NULL, NULL, NULL, NULL, NULL); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "description", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "name", OWS_NOERR, " %s\n", layer->name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "label", OWS_WARN, " \n", NULL); /* TODO: add elevation ranges to lonLatEnvelope (optional) */ msIO_printf(" \n"); msIO_printf(" %.15g %.15g\n", cm.llextent.minx, cm.llextent.miny); /* TODO: don't know if this is right */ msIO_printf(" %.15g %.15g\n", cm.llextent.maxx, cm.llextent.maxy); msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", "timeposition", NULL, NULL, " %s\n", NULL); msIO_printf(" \n"); /* we are not supporting the optional keyword type, at least not yet */ msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", "keywordlist", " \n", " \n", " %s\n", NULL); /* done */ msIO_printf(" \n"); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities_ContentMetadata() */ /************************************************************************/ static int msWCSGetCapabilities_ContentMetadata(mapObj *map, wcsParamsObj *params, owsRequestObj *ows_request) { int i; /* start the ContentMetadata section, only need the full start tag if this is the only section requested */ /* TODO: add Xlink attributes for other sources of this information */ if(!params->section || (params->section && strcasecmp(params->section, "/") == 0)) msIO_printf("\n"); else msIO_printf("\n", params->version, params->updatesequence, msOWSGetSchemasLocation(map), params->version); if(ows_request->numlayers == 0) { msIO_printf(" \n"); } else { for(i=0; inumlayers; i++) { if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) continue; if( msWCSGetCapabilities_CoverageOfferingBrief((GET_LAYER(map, i)), params) != MS_SUCCESS ) { msIO_printf("\n"); return MS_FAILURE; } } } /* done */ msIO_printf("\n"); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities() */ /************************************************************************/ static int msWCSGetCapabilities(mapObj *map, wcsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request) { char tmpString[OWS_VERSION_MAXLEN]; int i, tmpInt = 0; int wcsSupportedVersions[] = {OWS_1_1_2, OWS_1_1_1, OWS_1_1_0, OWS_1_0_0}; int wcsNumSupportedVersions = 4; const char *updatesequence=NULL; const char *encoding; encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); /* check version is valid */ tmpInt = msOWSParseVersionString(params->version); if (tmpInt == OWS_VERSION_BADFORMAT) { return msWCSException(map, "InvalidParameterValue", "version", "1.0.0 "); } /* negotiate version */ tmpInt = msOWSNegotiateVersion(tmpInt, wcsSupportedVersions, wcsNumSupportedVersions); /* set result as string and carry on */ free(params->version); params->version = msStrdup(msOWSGetVersionString(tmpInt, tmpString)); /* -------------------------------------------------------------------- */ /* 1.1.x is sufficiently different we have a whole case for */ /* it. The remainder of this function is for 1.0.0. */ /* -------------------------------------------------------------------- */ if( strncmp(params->version,"1.1",3) == 0 ) return msWCSGetCapabilities11( map, params, req, ows_request); updatesequence = msOWSLookupMetadata(&(map->web.metadata), "CO", "updatesequence"); if (params->updatesequence != NULL) { i = msOWSNegotiateUpdateSequence(params->updatesequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_WCSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWCSGetCapabilities()", params->updatesequence, updatesequence); return msWCSException(map, "CurrentUpdateSequence", "updatesequence", params->version ); } if (i > 0) { /* invalid */ msSetError(MS_WCSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWCSGetCapabilities()", params->updatesequence, updatesequence); return msWCSException(map, "InvalidUpdateSequence", "updatesequence", params->version ); } } else { /* set default updatesequence */ if(!updatesequence) updatesequence = "0"; params->updatesequence = msStrdup(updatesequence); } /* if a bum section param is passed, throw exception */ if (params->section && strcasecmp(params->section, "/WCS_Capabilities/Service") != 0 && strcasecmp(params->section, "/WCS_Capabilities/Capability") != 0 && strcasecmp(params->section, "/WCS_Capabilities/ContentMetadata") != 0 && strcasecmp(params->section, "/") != 0) { if (encoding) msIO_setHeader("Content-Type","application/vnd.ogc.se_xml; charset=%s", encoding); else msIO_setHeader("Content-Type","application/vnd.ogc.se_xml"); msIO_sendHeaders(); msSetError( MS_WCSERR, "Invalid SECTION parameter \"%s\"", "msWCSGetCapabilities()", params->section); return msWCSException(map, "InvalidParameterValue", "section", params->version ); } else { if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); /* print common capability elements */ /* TODO: DocType? */ if (!updatesequence) updatesequence = "0"; msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), NULL, "wcs_encoding", OWS_NOERR, "\n", "ISO-8859-1"); if(!params->section || (params->section && strcasecmp(params->section, "/") == 0)) msIO_printf("\n", params->version, updatesequence, msOWSGetSchemasLocation(map), params->version); /* print the various capability sections */ if(!params->section || strcasecmp(params->section, "/WCS_Capabilities/Service") == 0) msWCSGetCapabilities_Service(map, params); if(!params->section || strcasecmp(params->section, "/WCS_Capabilities/Capability") == 0) msWCSGetCapabilities_Capability(map, params, req); if(!params->section || strcasecmp(params->section, "/WCS_Capabilities/ContentMetadata") == 0) msWCSGetCapabilities_ContentMetadata(map, params, ows_request); if(params->section && strcasecmp(params->section, "/") == 0) { msWCSGetCapabilities_Service(map, params); msWCSGetCapabilities_Capability(map, params, req); msWCSGetCapabilities_ContentMetadata(map, params, ows_request); } /* done */ if(!params->section || (params->section && strcasecmp(params->section, "/") == 0)) msIO_printf("\n"); } return MS_SUCCESS; } /************************************************************************/ /* msWCSDescribeCoverage_AxisDescription() */ /************************************************************************/ static int msWCSDescribeCoverage_AxisDescription(layerObj *layer, char *name) { const char *value; char tag[100]; /* should be plenty of space */ msIO_printf(" \n"); msIO_printf(" metadata), "CO", tag, OWS_NOERR, " semantic=\"%s\"", NULL); snprintf(tag, sizeof(tag), "%s_refsys", name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", tag, OWS_NOERR, " refSys=\"%s\"", NULL); snprintf(tag, sizeof(tag), "%s_refsyslabel", name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", tag, OWS_NOERR, " refSysLabel=\"%s\"", NULL); msIO_printf(">\n"); /* TODO: add metadataLink (optional) */ snprintf(tag, sizeof(tag), "%s_description", name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", tag, OWS_NOERR, " %s\n", NULL); /* snprintf(tag, sizeof(tag), "%s_name", name); */ /* msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", tag, OWS_WARN, " %s\n", NULL); */ msIO_printf(" %s\n", name); snprintf(tag, sizeof(tag), "%s_label", name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", tag, OWS_WARN, " \n", NULL); /* Values */ msIO_printf(" metadata), "CO", tag, OWS_NOERR, " semantic=\"%s\"", NULL); snprintf(tag, sizeof(tag), "%s_values_type", name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", tag, OWS_NOERR, " type=\"%s\"", NULL); msIO_printf(">\n"); /* single values, we do not support optional type and semantic attributes */ snprintf(tag, sizeof(tag), "%s_values", name); if(msOWSLookupMetadata(&(layer->metadata), "CO", tag)) msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", tag, NULL, NULL, " %s\n", NULL); /* intervals, only one per axis for now, we do not support optional type, atomic and semantic attributes */ snprintf(tag, sizeof(tag), "%s_interval", name); if((value = msOWSLookupMetadata(&(layer->metadata), "CO", tag)) != NULL) { char **tokens; int numtokens; tokens = msStringSplit(value, '/', &numtokens); if(tokens && numtokens > 0) { msIO_printf(" \n"); if(numtokens >= 1) msIO_printf(" %s\n", tokens[0]); /* TODO: handle closure */ if(numtokens >= 2) msIO_printf(" %s\n", tokens[1]); if(numtokens >= 3) msIO_printf(" %s\n", tokens[2]); msIO_printf(" \n"); } } /* TODO: add default (optional) */ msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); return MS_SUCCESS; } /************************************************************************/ /* msWCSDescribeCoverage_CoverageOffering() */ /************************************************************************/ static int msWCSDescribeCoverage_CoverageOffering(layerObj *layer, wcsParamsObj *params) { char **tokens; int numtokens; const char *value; coverageMetadataObj cm; int i, status; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; if(!msWCSIsLayerSupported(layer)) return MS_SUCCESS; /* not an error, this layer cannot be served via WCS */ status = msWCSGetCoverageMetadata(layer, &cm); if(status != MS_SUCCESS) return MS_FAILURE; /* fill in bands rangeset info, if required. */ msWCSSetDefaultBandsRangeSetInfo( params, &cm, layer ); /* start the Coverage section */ msIO_printf(" \n"); /* optional metadataLink */ msOWSPrintURLType(stdout, &(layer->metadata), "CO", "metadatalink", OWS_NOERR, " ", NULL, " metadataType=\"%s\"", NULL, NULL, NULL, " xlink:href=\"%s\"", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, "other", NULL, NULL, NULL, NULL, NULL); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "description", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "name", OWS_NOERR, " %s\n", layer->name); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "label", OWS_WARN, " \n", NULL); /* TODO: add elevation ranges to lonLatEnvelope (optional) */ msIO_printf(" \n"); msIO_printf(" %.15g %.15g\n", cm.llextent.minx, cm.llextent.miny); msIO_printf(" %.15g %.15g\n", cm.llextent.maxx, cm.llextent.maxy); msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", "timeposition", NULL, NULL, " %s\n", NULL); msIO_printf(" \n"); /* we are not supporting the optional keyword type, at least not yet */ msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", "keywordlist", " \n", " \n", " %s\n", NULL); /* DomainSet: starting simple, just a spatial domain (gml:envelope) and optionally a temporal domain */ msIO_printf(" \n"); /* SpatialDomain */ msIO_printf(" \n"); /* envelope in lat/lon */ msIO_printf(" \n"); msIO_printf(" %.15g %.15g\n", cm.llextent.minx, cm.llextent.miny); msIO_printf(" %.15g %.15g\n", cm.llextent.maxx, cm.llextent.maxy); msIO_printf(" \n"); /* envelope in the native srs */ if((value = msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "CO", MS_TRUE)) != NULL) msIO_printf(" \n", value); else if((value = msOWSGetEPSGProj(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_TRUE)) != NULL) msIO_printf(" \n", value); else msIO_printf(" \n"); msIO_printf(" %.15g %.15g\n", cm.extent.minx, cm.extent.miny); msIO_printf(" %.15g %.15g\n", cm.extent.maxx, cm.extent.maxy); msIO_printf(" \n"); /* gml:rectifiedGrid */ msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" 0 0\n"); msIO_printf(" %d %d\n", cm.xsize-1, cm.ysize-1); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" x\n"); msIO_printf(" y\n"); msIO_printf(" \n"); msIO_printf(" %.15g %.15g\n", cm.geotransform[0], cm.geotransform[3]); msIO_printf(" \n"); msIO_printf(" %.15g %.15g\n", cm.geotransform[1], cm.geotransform[2]); /* offset vector in X direction */ msIO_printf(" %.15g %.15g\n", cm.geotransform[4], cm.geotransform[5]); /* offset vector in Y direction */ msIO_printf(" \n"); msIO_printf(" \n"); /* TemporalDomain */ /* TODO: figure out when a temporal domain is valid, for example only tiled rasters support time as a domain, plus we need a timeitem */ if(msOWSLookupMetadata(&(layer->metadata), "CO", "timeposition") || msOWSLookupMetadata(&(layer->metadata), "CO", "timeperiod")) { msIO_printf(" \n"); /* TimePosition (should support a value AUTO, then we could mine positions from the timeitem) */ msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", "timeposition", NULL, NULL, " %s\n", NULL); /* TODO: add TimePeriod (only one per layer) */ msIO_printf(" \n"); } msIO_printf(" \n"); /* rangeSet */ msIO_printf(" \n"); msIO_printf(" \n"); /* TODO: there are some optional attributes */ /* TODO: add metadataLink (optional) */ msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "rangeset_description", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "rangeset_name", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(layer->metadata), "CO", "rangeset_label", OWS_WARN, " \n", NULL); /* compound range sets */ if((value = msOWSLookupMetadata(&(layer->metadata), "CO", "rangeset_axes")) != NULL) { tokens = msStringSplit(value, ',', &numtokens); if(tokens && numtokens > 0) { for(i=0; imetadata), "CO", "rangeset_nullvalue")) != NULL) { msIO_printf(" \n"); msIO_printf(" %s\n", value); msIO_printf(" \n"); } msIO_printf(" \n"); msIO_printf(" \n"); /* supportedCRSs */ msIO_printf(" \n"); /* requestResposeCRSs: check the layer metadata/projection, and then the map metadata/projection if necessary (should never get to the error message) */ if((value = msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "CO", MS_FALSE)) != NULL) { tokens = msStringSplit(value, ' ', &numtokens); if(tokens && numtokens > 0) { for(i=0; i%s\n", tokens[i]); msFreeCharArray(tokens, numtokens); } } else if((value = msOWSGetEPSGProj(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_FALSE)) != NULL) { tokens = msStringSplit(value, ' ', &numtokens); if(tokens && numtokens > 0) { for(i=0; i%s\n", tokens[i]); msFreeCharArray(tokens, numtokens); } } else msIO_printf(" \n"); /* nativeCRSs (only one in our case) */ if((value = msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "CO", MS_TRUE)) != NULL) msIO_printf(" %s\n", value); else if((value = msOWSGetEPSGProj(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_TRUE)) != NULL) msIO_printf(" %s\n", value); else msIO_printf(" \n"); msIO_printf(" \n"); /* supportedFormats */ msIO_printf(" metadata), "CO", "nativeformat", OWS_NOERR, " nativeFormat=\"%s\"", NULL); msIO_printf(">\n"); if( (value = msOWSGetEncodeMetadata( &(layer->metadata), "CO", "formats", "GTiff" )) != NULL ) { tokens = msStringSplit(value, ' ', &numtokens); if(tokens && numtokens > 0) { for(i=0; i%s
\n", tokens[i]); msFreeCharArray(tokens, numtokens); } msFree((char*)value); } msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" nearest neighbor\n" ); msIO_printf(" bilinear\n" ); /* msIO_printf(" bicubic\n" ); */ msIO_printf(" \n"); /* done */ msIO_printf(" \n"); return MS_SUCCESS; } /************************************************************************/ /* msWCSDescribeCoverage() */ /************************************************************************/ static int msWCSDescribeCoverage(mapObj *map, wcsParamsObj *params, owsRequestObj *ows_request) { int i = 0,j = 0, k = 0; const char *updatesequence=NULL; char **coverages=NULL; int numcoverages=0; const char *encoding; char *coverageName=NULL; encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); /* -------------------------------------------------------------------- */ /* 1.1.x is sufficiently different we have a whole case for */ /* it. The remainder of this function is for 1.0.0. */ /* -------------------------------------------------------------------- */ if( strncmp(params->version,"1.1",3) == 0 ) return msWCSDescribeCoverage11( map, params, ows_request); /* -------------------------------------------------------------------- */ /* Process 1.0.0... */ /* -------------------------------------------------------------------- */ if(params->coverages) { /* use the list, but validate it first */ for(j=0; params->coverages[j]; j++) { coverages = msStringSplit(params->coverages[j], ',', &numcoverages); for(k=0; knumlayers; i++) { coverageName = msOWSGetEncodeMetadata(&(GET_LAYER(map, i)->metadata), "CO", "name", GET_LAYER(map, i)->name); if( coverageName != NULL && EQUAL(coverageName, coverages[k]) && (msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) ) { msFree(coverageName); break; } msFree(coverageName); } /* i = msGetLayerIndex(map, coverages[k]); */ if(i == map->numlayers) { /* coverage not found */ msSetError( MS_WCSERR, "COVERAGE %s cannot be opened / does not exist. A layer might be disabled for \ this request. Check wcs/ows_enable_request settings.", "msWCSDescribeCoverage()", coverages[k]); return msWCSException(map, "CoverageNotDefined", "coverage", params->version ); } } /* next coverage */ msFreeCharArray(coverages,numcoverages); } } updatesequence = msOWSLookupMetadata(&(map->web.metadata), "CO", "updatesequence"); if (!updatesequence) updatesequence = "0"; /* printf("Content-Type: application/vnd.ogc.se_xml%c%c",10,10); */ if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); /* print common capability elements */ msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), NULL, "wcs_encoding", OWS_NOERR, "\n", "ISO-8859-1"); /* start the DescribeCoverage section */ msIO_printf("\n", params->version, updatesequence, msOWSGetSchemasLocation(map), params->version); if(params->coverages) { /* use the list */ for( j = 0; params->coverages[j]; j++ ) { coverages = msStringSplit(params->coverages[j], ',', &numcoverages); for(k=0; knumlayers; i++) { coverageName = msOWSGetEncodeMetadata(&(GET_LAYER(map, i)->metadata), "CO", "name", GET_LAYER(map, i)->name); if( coverageName != NULL && EQUAL(coverageName, coverages[k]) ) { msFree(coverageName); break; } msFree(coverageName); } msWCSDescribeCoverage_CoverageOffering((GET_LAYER(map, i)), params); } msFreeCharArray(coverages,numcoverages); } } else { /* return all layers */ for(i=0; inumlayers; i++) { if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) continue; msWCSDescribeCoverage_CoverageOffering((GET_LAYER(map, i)), params); } } /* done */ msIO_printf("\n"); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCoverageBands10() */ /************************************************************************/ static int msWCSGetCoverageBands10( mapObj *map, cgiRequestObj *request, wcsParamsObj *params, layerObj *lp, char **p_bandlist ) { const char *value = NULL; int i; /* Are there any non-spatio/temporal ranges to do subsetting on (e.g. bands) */ value = msOWSLookupMetadata(&(lp->metadata), "CO", "rangeset_axes"); /* this will get all the compound range sets */ if(value) { char **tokens; int numtokens; char tag[100]; const char *rangeitem; tokens = msStringSplit(value, ',', &numtokens); for(i=0; iversion ); msFreeCharArray(tokens, numtokens); return ret; } /* xxxxx_rangeitem tells us how to subset */ snprintf(tag, sizeof(tag), "%s_rangeitem", tokens[i]); if((rangeitem = msOWSLookupMetadata(&(lp->metadata), "CO", tag)) == NULL) { msSetError( MS_WCSERR, "Missing required metadata element \"%s\", unable to process %s=%s.", "msWCSGetCoverage()", tag, tokens[i], value); msFreeCharArray(tokens, numtokens); return msWCSException(map, NULL, NULL, params->version); } if(strcasecmp(rangeitem, "_bands") == 0) { /* special case, subset bands */ *p_bandlist = msWCSConvertRangeSetToString(value); if(!*p_bandlist) { msSetError( MS_WCSERR, "Error specifying \"%s\" parameter value(s).", "msWCSGetCoverage()", tokens[i]); msFreeCharArray(tokens, numtokens); return msWCSException(map, NULL, NULL, params->version ); } } else if(strcasecmp(rangeitem, "_pixels") == 0) { /* special case, subset pixels */ msFreeCharArray(tokens, numtokens); msSetError( MS_WCSERR, "Arbitrary range sets based on pixel values are not yet supported.", "msWCSGetCoverage()" ); return msWCSException(map, NULL, NULL, params->version); } else { msFreeCharArray(tokens, numtokens); msSetError( MS_WCSERR, "Arbitrary range sets based on tile (i.e. image) attributes are not yet supported.", "msWCSGetCoverage()" ); return msWCSException(map, NULL, NULL, params->version ); } } /* clean-up */ msFreeCharArray(tokens, numtokens); } return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCoverage_ImageCRSSetup() */ /* */ /* The request was in imageCRS - update the map projection to */ /* map the native projection of the layer, and reset the */ /* bounding box to match the projected bounds corresponding to */ /* the imageCRS request. */ /************************************************************************/ static int msWCSGetCoverage_ImageCRSSetup( mapObj *map, cgiRequestObj *request, wcsParamsObj *params, coverageMetadataObj *cm, layerObj *layer ) { /* -------------------------------------------------------------------- */ /* Load map with the layer (coverage) coordinate system. We */ /* really need a set projectionObj from projectionObj function! */ /* -------------------------------------------------------------------- */ char *layer_proj = msGetProjectionString( &(layer->projection) ); if (msLoadProjectionString(&(map->projection), layer_proj) != 0) return msWCSException( map, NULL, NULL, params->version ); free( layer_proj ); layer_proj = NULL; /* -------------------------------------------------------------------- */ /* Reset bounding box. */ /* -------------------------------------------------------------------- */ if( params->bbox.maxx != params->bbox.minx ) { rectObj orig_bbox = params->bbox; params->bbox.minx = cm->geotransform[0] + orig_bbox.minx * cm->geotransform[1] + orig_bbox.miny * cm->geotransform[2]; params->bbox.maxy = cm->geotransform[3] + orig_bbox.minx * cm->geotransform[4] + orig_bbox.miny * cm->geotransform[5]; params->bbox.maxx = cm->geotransform[0] + (orig_bbox.maxx+1) * cm->geotransform[1] + (orig_bbox.maxy+1) * cm->geotransform[2]; params->bbox.miny = cm->geotransform[3] + (orig_bbox.maxx+1) * cm->geotransform[4] + (orig_bbox.maxy+1) * cm->geotransform[5]; /* WCS 1.1 boundbox is center of pixel oriented. */ if( strncasecmp(params->version,"1.1",3) == 0 ) { params->bbox.minx += cm->geotransform[1]/2 + cm->geotransform[2]/2; params->bbox.maxx -= cm->geotransform[1]/2 + cm->geotransform[2]/2; params->bbox.maxy += cm->geotransform[4]/2 + cm->geotransform[5]/2; params->bbox.miny -= cm->geotransform[4]/2 + cm->geotransform[5]/2; } } /* -------------------------------------------------------------------- */ /* Reset resolution. */ /* -------------------------------------------------------------------- */ if( params->resx != 0.0 ) { params->resx = cm->geotransform[1] * params->resx; params->resy = fabs(cm->geotransform[5] * params->resy); } return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCoverage() */ /************************************************************************/ static int msWCSGetCoverage(mapObj *map, cgiRequestObj *request, wcsParamsObj *params, owsRequestObj *ows_request) { imageObj *image; layerObj *lp; int status, i; const char *value; outputFormatObj *format; char *bandlist=NULL; size_t bufferSize = 0; char numbands[8]; /* should be large enough to hold the number of bands in the bandlist */ coverageMetadataObj cm; rectObj reqextent; rectObj covextent; rasterBufferObj rb; char *coverageName; /* make sure all required parameters are available (at least the easy ones) */ if(!params->crs) { msSetError( MS_WCSERR, "Required parameter CRS was not supplied.", "msWCSGetCoverage()"); return msWCSException(map, "MissingParameterValue", "crs", params->version); } if(!params->time && !params->bbox.minx && !params->bbox.miny && !params->bbox.maxx && !params->bbox.maxy) { msSetError(MS_WCSERR, "One of BBOX or TIME is required", "msWCSGetCoverage()"); return msWCSException(map, "MissingParameterValue", "bbox/time", params->version); } if( params->coverages == NULL || params->coverages[0] == NULL ) { msSetError( MS_WCSERR, "Required parameter COVERAGE was not supplied.", "msWCSGetCoverage()"); return msWCSException(map, "MissingParameterValue", "coverage", params->version); } /* For WCS 1.1, we need to normalize the axis order of the BBOX and resolution values some coordinate systems (eg. EPSG geographic) */ if( strncasecmp(params->version,"1.0",3) != 0 && params->crs != NULL && strncasecmp(params->crs,"urn:",4) == 0 ) { projectionObj proj; msInitProjection( &proj ); if( msLoadProjectionString( &proj, (char *) params->crs ) == 0 ) { msAxisNormalizePoints( &proj, 1, &(params->bbox.minx), &(params->bbox.miny) ); msAxisNormalizePoints( &proj, 1, &(params->bbox.maxx), &(params->bbox.maxy) ); msAxisNormalizePoints( &proj, 1, &(params->resx), &(params->resy) ); msAxisNormalizePoints( &proj, 1, &(params->originx), &(params->originy) ); } else msResetErrorList(); msFreeProjection( &proj ); } /* find the layer we are working with */ lp = NULL; for(i=0; inumlayers; i++) { coverageName = msOWSGetEncodeMetadata(&(GET_LAYER(map, i)->metadata), "CO", "name", GET_LAYER(map, i)->name); if( coverageName != NULL && EQUAL(coverageName, params->coverages[0]) && (msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) ) { lp = GET_LAYER(map, i); free( coverageName ); break; } free( coverageName ); } if(lp == NULL) { msSetError( MS_WCSERR, "COVERAGE=%s not found, not in supported layer list. A layer might be disabled for \ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage()", params->coverages[0] ); return msWCSException(map, "InvalidParameterValue", "coverage", params->version); } /* make sure the layer is on */ lp->status = MS_ON; /* If the layer has no projection set, set it to the map's projection (#4079) */ if(lp->projection.numargs <=0) { char *map_original_srs = msGetProjectionString(&(map->projection)); if (msLoadProjectionString(&(lp->projection), map_original_srs) != 0) { msSetError( MS_WCSERR, "Error when setting map projection to a layer with no projection", "msWCSGetCoverage()" ); return msWCSException(map, NULL, NULL, params->version); } } /* we need the coverage metadata, since things like numbands may not be available otherwise */ status = msWCSGetCoverageMetadata(lp, &cm); if(status != MS_SUCCESS) return MS_FAILURE; /* fill in bands rangeset info, if required. */ msWCSSetDefaultBandsRangeSetInfo(params, &cm, lp); /* handle the response CRS, that is, set the map object projection */ if(params->response_crs || params->crs ) { int iUnits; const char *crs_to_use = params->response_crs; if( crs_to_use == NULL ) crs_to_use = params->crs; if (strncasecmp(crs_to_use, "EPSG:", 5) == 0 || strncasecmp(crs_to_use,"urn:ogc:def:crs:",16) == 0 ) { if (msLoadProjectionString(&(map->projection), (char *) crs_to_use) != 0) return msWCSException( map, NULL, NULL,params->version); } else if( strcasecmp(crs_to_use,"imageCRS") == 0 ) { /* use layer native CRS, and rework bounding box accordingly */ if( msWCSGetCoverage_ImageCRSSetup( map, request, params, &cm, lp ) != MS_SUCCESS ) return MS_FAILURE; } else { /* should we support WMS style AUTO: projections? (not for now) */ msSetError(MS_WCSERR, "Unsupported SRS namespace (only EPSG currently supported).", "msWCSGetCoverage()"); return msWCSException(map, "InvalidParameterValue", "srs", params->version); } iUnits = GetMapserverUnitUsingProj(&(map->projection)); if (iUnits != -1) map->units = iUnits; } /* did we get a TIME value (support only a single value for now) */ if(params->time) { int tli; layerObj *tlp=NULL; /* need to handle NOW case */ /* check format of TIME parameter */ if(strchr(params->time, ',')) { msSetError( MS_WCSERR, "Temporal lists are not supported, only individual values.", "msWCSGetCoverage()" ); return msWCSException(map, "InvalidParameterValue", "time", params->version); } if(strchr(params->time, '/')) { msSetError( MS_WCSERR, "Temporal ranges are not supported, only individual values.", "msWCSGetCoverage()" ); return msWCSException(map, "InvalidParameterValue", "time", params->version); } /* TODO: will need to expand this check if a time period is supported */ value = msOWSLookupMetadata(&(lp->metadata), "CO", "timeposition"); if(!value) { msSetError( MS_WCSERR, "The coverage does not support temporal subsetting.", "msWCSGetCoverage()" ); return msWCSException(map, "InvalidParameterValue", "time", params->version ); } /* check if timestamp is covered by the wcs_timeposition definition */ if (msValidateTimeValue(params->time, value) == MS_FALSE) { msSetError( MS_WCSERR, "The coverage does not have a time position of %s.", "msWCSGetCoverage()", params->time ); return msWCSException(map, "InvalidParameterValue", "time", params->version); } /* make sure layer is tiled appropriately */ if(!lp->tileindex) { msSetError( MS_WCSERR, "Underlying layer is not tiled, unable to do temporal subsetting.", "msWCSGetCoverage()" ); return msWCSException(map, NULL, NULL, params->version); } tli = msGetLayerIndex(map, lp->tileindex); if(tli == -1) { msSetError( MS_WCSERR, "Underlying layer does not use appropriate tiling mechanism.", "msWCSGetCoverage()" ); return msWCSException(map, NULL, NULL, params->version); } tlp = (GET_LAYER(map, tli)); /* make sure there is enough information to filter */ value = msOWSLookupMetadata(&(lp->metadata), "CO", "timeitem"); if(!tlp->filteritem && !value) { msSetError( MS_WCSERR, "Not enough information available to filter.", "msWCSGetCoverage()" ); return msWCSException(map, NULL, NULL, params->version); } /* override filteritem if specified in metadata */ if(value) { if(tlp->filteritem) free(tlp->filteritem); tlp->filteritem = msStrdup(value); } /* finally set the filter */ freeExpression(&tlp->filter); msLayerSetTimeFilter(tlp, params->time, value); } if( strncasecmp(params->version,"1.0",3) == 0 ) status = msWCSGetCoverageBands10( map, request, params, lp, &bandlist ); else status = msWCSGetCoverageBands11( map, request, params, lp, &bandlist ); if( status != MS_SUCCESS ) return status; /* did we get BBOX values? if not use the exent stored in the coverageMetadataObj */ if( fabs((params->bbox.maxx - params->bbox.minx)) < 0.000000000001 || fabs(params->bbox.maxy - params->bbox.miny) < 0.000000000001 ) { params->bbox = cm.extent; /* WCS 1.1 boundbox is center of pixel oriented. */ if( strncasecmp(params->version,"1.1",3) == 0 ) { params->bbox.minx += cm.geotransform[1]/2 + cm.geotransform[2]/2; params->bbox.maxx -= cm.geotransform[1]/2 + cm.geotransform[2]/2; params->bbox.maxy += cm.geotransform[4]/2 + cm.geotransform[5]/2; params->bbox.miny -= cm.geotransform[4]/2 + cm.geotransform[5]/2; } } /* WCS 1.1+ GridOrigin is effectively resetting the minx/maxy BOUNDINGBOX values, so apply that here */ if( params->originx != 0.0 || params->originy != 0.0 ) { assert( strncasecmp(params->version,"1.0",3) != 0 ); /* should always be 1.0 in this logic. */ params->bbox.minx = params->originx; params->bbox.maxy = params->originy; } /* if necessary, project the BBOX to the map->projection */ if(params->response_crs && params->crs) { projectionObj tmp_proj; msInitProjection(&tmp_proj); if (msLoadProjectionString(&tmp_proj, (char *) params->crs) != 0) return msWCSException( map, NULL, NULL, params->version); msProjectRect(&tmp_proj, &map->projection, &(params->bbox)); msFreeProjection(&tmp_proj); } /* in WCS 1.1 the default is full resolution */ if( strncasecmp(params->version,"1.1",3) == 0 && params->resx == 0.0 && params->resy == 0.0 ) { params->resx = cm.geotransform[1]; params->resy = fabs(cm.geotransform[5]); } /* compute width/height from BBOX and cellsize. */ if( (params->resx == 0.0 || params->resy == 0.0) && params->width != 0 && params->height != 0 ) { assert( strncasecmp(params->version,"1.0",3) == 0 ); /* should always be 1.0 in this logic. */ params->resx = (params->bbox.maxx -params->bbox.minx) / params->width; params->resy = (params->bbox.maxy -params->bbox.miny) / params->height; } /* compute cellsize/res from bbox and raster size. */ if( (params->width == 0 || params->height == 0) && params->resx != 0 && params->resy != 0 ) { /* WCS 1.0 boundbox is edge of pixel oriented. */ if( strncasecmp(params->version,"1.0",3) == 0 ) { params->width = (int) ((params->bbox.maxx - params->bbox.minx) / params->resx + 0.5); params->height = (int) ((params->bbox.maxy - params->bbox.miny) / params->resy + 0.5); } else { params->width = (int) ((params->bbox.maxx - params->bbox.minx) / params->resx + 1.000001); params->height = (int) ((params->bbox.maxy - params->bbox.miny) / params->resy + 1.000001); /* recompute bounding box so we get exactly the origin and resolution requested. */ params->bbox.maxx = params->bbox.minx + (params->width-1) * params->resx; params->bbox.miny = params->bbox.maxy - (params->height-1) * params->resy; } } /* are we still underspecified? */ if( (params->width == 0 || params->height == 0) && (params->resx == 0.0 || params->resy == 0.0 )) { msSetError( MS_WCSERR, "A non-zero RESX/RESY or WIDTH/HEIGHT is required but neither was provided.", "msWCSGetCoverage()" ); return msWCSException(map, "MissingParameterValue", "width/height/resx/resy", params->version); } map->cellsize = params->resx; /* Do we need to force special handling? */ if( fabs(params->resx/params->resy - 1.0) > 0.001 ) { map->gt.need_geotransform = MS_TRUE; if( map->debug ) msDebug( "RESX and RESY don't match. Using geotransform/resample.\n"); } /* Do we have a specified interpolation method */ if( params->interpolation != NULL ) { if( strncasecmp(params->interpolation,"NEAREST",7) == 0 ) msLayerSetProcessingKey(lp, "RESAMPLE", "NEAREST"); else if( strcasecmp(params->interpolation,"BILINEAR") == 0 ) msLayerSetProcessingKey(lp, "RESAMPLE", "BILINEAR"); else if( strcasecmp(params->interpolation,"AVERAGE") == 0 ) msLayerSetProcessingKey(lp, "RESAMPLE", "AVERAGE"); else { msSetError( MS_WCSERR, "INTERPOLATION=%s specifies an unsupported interpolation method.", "msWCSGetCoverage()", params->interpolation ); return msWCSException(map, "InvalidParameterValue", "interpolation", params->version); } } /* apply region and size to map object. */ map->width = params->width; map->height = params->height; /* Are we exceeding the MAXSIZE limit on result size? */ if(map->width > map->maxsize || map->height > map->maxsize ) { msSetError(MS_WCSERR, "Raster size out of range, width and height of resulting coverage must be no more than MAXSIZE=%d.", "msWCSGetCoverage()", map->maxsize); return msWCSException(map, "InvalidParameterValue", "width/height", params->version); } /* adjust OWS BBOX to MapServer's pixel model */ if( strncasecmp(params->version,"1.0",3) == 0 ) { params->bbox.minx += params->resx*0.5; params->bbox.miny += params->resy*0.5; params->bbox.maxx -= params->resx*0.5; params->bbox.maxy -= params->resy*0.5; } map->extent = params->bbox; map->cellsize = params->resx; /* pick one, MapServer only supports square cells (what about msAdjustExtent here!) */ msMapComputeGeotransform(map); /* Do we need to fake out stuff for rotated support? */ if( map->gt.need_geotransform ) msMapSetFakedExtent( map ); map->projection.gt = map->gt; /* check for overlap */ /* get extent of bbox passed, and reproject */ reqextent.minx = map->extent.minx; reqextent.miny = map->extent.miny; reqextent.maxx = map->extent.maxx; reqextent.maxy = map->extent.maxy; /* reproject incoming bbox */ msProjectRect(&map->projection, &lp->projection, &(reqextent)); /* get extent of layer */ covextent.minx = cm.extent.minx; covextent.miny = cm.extent.miny; covextent.maxx = cm.extent.maxx; covextent.maxy = cm.extent.maxy; if(msRectOverlap(&reqextent, &covextent) == MS_FALSE) { msSetError(MS_WCSERR, "Requested BBOX (%.15g,%.15g,%.15g,%.15g) is outside requested coverage BBOX (%.15g,%.15g,%.15g,%.15g)", "msWCSGetCoverage()", reqextent.minx, reqextent.miny, reqextent.maxx, reqextent.maxy, covextent.minx, covextent.miny, covextent.maxx, covextent.maxy); return msWCSException(map, "NoApplicableCode", "bbox", params->version); } /* check and make sure there is a format, and that it's valid (TODO: make sure in the layer metadata) */ if(!params->format) { msSetError( MS_WCSERR, "Missing required FORMAT parameter.", "msWCSGetCoverage()" ); return msWCSException(map, "MissingParameterValue", "format", params->version); } msApplyDefaultOutputFormats(map); if(msGetOutputFormatIndex(map,params->format) == -1) { msSetError( MS_WCSERR, "Unrecognized value for the FORMAT parameter.", "msWCSGetCoverage()" ); return msWCSException(map, "InvalidParameterValue", "format", params->version ); } /* create a temporary outputformat (we likely will need to tweak parts) */ format = msCloneOutputFormat(msSelectOutputFormat(map,params->format)); msApplyOutputFormat(&(map->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); if(!bandlist) { /* build a bandlist (default is ALL bands) */ bufferSize = cm.bandcount*30+30; bandlist = (char *) msSmallMalloc(bufferSize); strcpy(bandlist, "1"); for(i = 1; i < cm.bandcount; i++) snprintf(bandlist+strlen(bandlist), bufferSize-strlen(bandlist), ",%d", i+1); } /* apply nullvalue to the output format object if we have it */ if((value = msOWSLookupMetadata(&(lp->metadata), "CO", "rangeset_nullvalue")) != NULL) { msSetOutputFormatOption( map->outputformat, "NULLVALUE", value ); } msLayerSetProcessingKey(lp, "BANDS", bandlist); snprintf(numbands, sizeof(numbands), "%d", msCountChars(bandlist, ',')+1); msSetOutputFormatOption(map->outputformat, "BAND_COUNT", numbands); free( bandlist ); /* create the image object */ if(!map->outputformat) { msSetError(MS_WCSERR, "The map outputformat is missing!", "msWCSGetCoverage()"); return msWCSException(map, NULL, NULL, params->version ); } else if( MS_RENDERER_RAWDATA(map->outputformat) || MS_RENDERER_PLUGIN(map->outputformat) ) { image = msImageCreate(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, NULL); } else { msSetError(MS_WCSERR, "Map outputformat not supported for WCS!", "msWCSGetCoverage()"); return msWCSException(map, NULL, NULL, params->version ); } if(lp->mask) { int maskLayerIdx = msGetLayerIndex(map,lp->mask); layerObj *maskLayer; outputFormatObj *altFormat; if(maskLayerIdx == -1) { msSetError(MS_MISCERR, "Layer (%s) references unknown mask layer (%s)", "msDrawLayer()", lp->name,lp->mask); return (MS_FAILURE); } maskLayer = GET_LAYER(map, maskLayerIdx); if(!maskLayer->maskimage) { int i,retcode; int origstatus, origlabelcache; char *origImageType = msStrdup(map->imagetype); altFormat = msSelectOutputFormat(map, "png24"); msInitializeRendererVTable(altFormat); /* TODO: check the png24 format hasn't been tampered with, i.e. it's agg */ maskLayer->maskimage= msImageCreate(image->width, image->height,altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!maskLayer->maskimage) { msSetError(MS_MISCERR, "Unable to initialize mask image.", "msDrawLayer()"); return (MS_FAILURE); } /* * force the masked layer to status on, and turn off the labelcache so that * eventual labels are added to the temporary image instead of being added * to the labelcache */ origstatus = maskLayer->status; origlabelcache = maskLayer->labelcache; maskLayer->status = MS_ON; maskLayer->labelcache = MS_OFF; /* draw the mask layer in the temporary image */ retcode = msDrawLayer(map, maskLayer, maskLayer->maskimage); maskLayer->status = origstatus; maskLayer->labelcache = origlabelcache; if(retcode != MS_SUCCESS) { return MS_FAILURE; } /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == MS_IMAGE_RENDERER(maskLayer->maskimage)) { MS_IMAGE_RENDERER(maskLayer->maskimage)->freeSymbol(s); s->renderer = NULL; } } } /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */ msFree(map->imagetype); map->imagetype = origImageType; } } if( image == NULL ) return msWCSException(map, NULL, NULL, params->version ); if( MS_RENDERER_RAWDATA(map->outputformat) ) { status = msDrawRasterLayerLow( map, lp, image, NULL ); } else { MS_IMAGE_RENDERER(image)->getRasterBufferHandle(image,&rb); /* Actually produce the "grid". */ status = msDrawRasterLayerLow( map, lp, image, &rb ); } if( status != MS_SUCCESS ) { return msWCSException(map, NULL, NULL, params->version ); } if( strncmp(params->version, "1.1",3) == 0 ) { msWCSReturnCoverage11( params, map, image ); } else { /* WCS 1.0.0 - just return the binary data with a content type */ const char *fo_filename; /* Do we have a predefined filename? */ fo_filename = msGetOutputFormatOption( format, "FILENAME", NULL ); if( fo_filename ) msIO_setHeader("Content-Disposition","attachment; filename=%s", fo_filename ); /* Emit back to client. */ msIO_setHeader("Content-Type","%s",MS_IMAGE_MIME_TYPE(map->outputformat)); msIO_sendHeaders(); status = msSaveImage(map, image, NULL); if( status != MS_SUCCESS ) { /* unfortunately, the image content type will have already been sent but that is hard for us to avoid. The main error that could happen here is a misconfigured tmp directory or running out of space. */ return msWCSException(map, NULL, NULL, params->version ); } } /* Cleanup */ msFreeImage(image); msApplyOutputFormat(&(map->outputformat), NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); /* msFreeOutputFormat(format); */ return status; } #endif /* def USE_WCS_SVR */ /************************************************************************/ /* msWCSDispatch() */ /* */ /* Entry point for WCS requests */ /************************************************************************/ int msWCSDispatch(mapObj *map, cgiRequestObj *request, owsRequestObj *ows_request) { #if defined(USE_WCS_SVR) void *params = NULL; /* either wcsParamsObj* or wcs20ParamsObj* */ int status, retVal, operation; /* If SERVICE is not set or not WCS exit gracefully. */ if (ows_request->service == NULL || !EQUAL(ows_request->service, "WCS")) { return MS_DONE; } /* If no REQUEST is set, exit with an error */ if (ows_request->request == NULL) { /* The request has to be set. */ msSetError(MS_WCSERR, "Missing REQUEST parameter", "msWCSDispatch()"); return msWCSException(map, "MissingParameterValue", "request", ows_request->version ); } if (EQUAL(ows_request->request, "GetCapabilities")) { operation = MS_WCS_GET_CAPABILITIES; } else if (EQUAL(ows_request->request, "DescribeCoverage")) { operation = MS_WCS_DESCRIBE_COVERAGE; } else if (EQUAL(ows_request->request, "GetCoverage")) { operation = MS_WCS_GET_COVERAGE; } else { msSetError(MS_WCSERR, "Invalid REQUEST parameter \"%s\"", "msWCSDispatch()", ows_request->request); return msWCSException(map, "InvalidParameterValue", "request", ows_request->version); } /* Check the number of enabled layers for the REQUEST */ msOWSRequestLayersEnabled(map, "C", ows_request->request, ows_request); if (ows_request->numlayers == 0) { int caps_globally_enabled = MS_FALSE, disabled = MS_FALSE; const char *enable_request; if(operation == MS_WCS_GET_CAPABILITIES) { enable_request = msOWSLookupMetadata(&map->web.metadata, "OC", "enable_request"); caps_globally_enabled = msOWSParseRequestMetadata(enable_request, "GetCapabilities", &disabled); } if(caps_globally_enabled == MS_FALSE) { msSetError(MS_WCSERR, "WCS request not enabled. Check " "wcs/ows_enable_request settings.", "msWCSDispatch()"); return msWCSException(map, "InvalidParameterValue", "request", ows_request->version ); } } /* Check the VERSION parameter */ if (ows_request->version == NULL) { /* If the VERSION parameter is not set, it is either */ /* an error (Describe and GetCoverage), or it has to */ /* be determined (GetCapabilities). To determine the */ /* version, the request has to be fully parsed to */ /* obtain the ACCEPTVERSIONS parameter. If this is */ /* present also, set version to "2.0.1". */ if (operation == MS_WCS_GET_CAPABILITIES) { /* Parse it as if it was a WCS 2.0 request */ wcs20ParamsObjPtr params_tmp = msWCSCreateParamsObj20(); status = msWCSParseRequest20(map, request, ows_request, params_tmp); if (status == MS_FAILURE) { msWCSFreeParamsObj20(params); return msWCSException(map, "InvalidParameterValue", "request", "2.0.1"); } /* VERSION negotiation */ if (params_tmp->accept_versions != NULL) { /* choose highest acceptable */ int i, highest_version = 0; char version_string[OWS_VERSION_MAXLEN]; for(i = 0; params_tmp->accept_versions[i] != NULL; ++i) { int version = msOWSParseVersionString(params_tmp->accept_versions[i]); if (version == OWS_VERSION_BADFORMAT) { msWCSFreeParamsObj20(params_tmp); return msWCSException(map, "InvalidParameterValue", "version", NULL ); } if(version > highest_version) { highest_version = version; } } msOWSGetVersionString(highest_version, version_string); params_tmp->version = msStrdup(version_string); ows_request->version = msStrdup(version_string); } else { /* set to highest acceptable */ params_tmp->version = msStrdup("2.0.1"); ows_request->version = msStrdup("2.0.1"); } /* check if we can keep the params object */ if (EQUAL(params_tmp->version, "2.0.1")) { params = params_tmp; } else { msWCSFreeParamsObj20(params_tmp); } } else { /* operation != GetCapabilities */ /* VERSION is mandatory in other requests */ msSetError(MS_WCSERR, "VERSION parameter not set.", "msWCSDispatch()"); return msWCSException(map, "InvalidParameterValue", "version", NULL ); } } else { /* Parse the VERSION parameter */ int requested_version = msOWSParseVersionString(ows_request->version); if (requested_version == OWS_VERSION_BADFORMAT) { /* Return an error if the VERSION is */ /* in an unsupported format. */ return msWCSException(map, "InvalidParameterValue", "version", NULL ); } if (operation == MS_WCS_GET_CAPABILITIES) { /* In case of GetCapabilities, make */ char version_string[OWS_VERSION_MAXLEN]; int version, supported_versions[] = {OWS_2_0_1, OWS_2_0_0, OWS_1_1_2, OWS_1_1_1, OWS_1_1_0, OWS_1_0_0}; version = msOWSNegotiateVersion(requested_version, supported_versions, sizeof(supported_versions)/sizeof(int)); msOWSGetVersionString(version, version_string); msFree(ows_request->version); ows_request->version = msStrdup(version_string); } } /* VERSION specific request handler */ if (strcmp(ows_request->version, "1.0.0") == 0 || strcmp(ows_request->version, "1.1.0") == 0 || strcmp(ows_request->version, "1.1.1") == 0 || strcmp(ows_request->version, "1.1.2") == 0) { params = msWCSCreateParams(); status = msWCSParseRequest(request, params, map); if (status == MS_FAILURE) { msWCSFreeParams(params); free(params); return msWCSException(map, "InvalidParameterValue", "request", "2.0"); } if (operation == MS_WCS_GET_CAPABILITIES) { retVal = msWCSGetCapabilities(map, params, request, ows_request); } else if (operation == MS_WCS_DESCRIBE_COVERAGE) { retVal = msWCSDescribeCoverage(map, params, ows_request); } else if (operation == MS_WCS_GET_COVERAGE) { retVal = msWCSGetCoverage(map, request, params, ows_request); } msWCSFreeParams(params); free(params); return retVal; } else if (strcmp(ows_request->version, "2.0.0") == 0 || strcmp(ows_request->version, "2.0.1") == 0) { #if defined(USE_LIBXML2) int i; if (params == NULL) { params = msWCSCreateParamsObj20(); status = msWCSParseRequest20(map, request, ows_request, params); if (status == MS_FAILURE) { msWCSFreeParamsObj20(params); return msWCSException(map, "InvalidParameterValue", "request", "2.0.1"); } else if (status == MS_DONE) { /* MS_DONE means, that the exception has already been written to the IO buffer. */ msWCSFreeParamsObj20(params); return MS_FAILURE; } } /* check if all layer names are valid NCNames */ for(i = 0; i < map->numlayers; ++i) { if(!msWCSIsLayerSupported(map->layers[i])) continue; /* Check if each layers name is a valid NCName. */ if (msEvalRegex("^[a-zA-z_][a-zA-Z0-9_.-]*$" , map->layers[i]->name) == MS_FALSE) { msSetError(MS_WCSERR, "Layer name '%s' is not a valid NCName.", "msWCSDispatch()", map->layers[i]->name); msWCSFreeParamsObj20(params); return msWCSException(map, "mapserv", "Internal", "2.0.1"); } } /* Call operation specific functions */ if (operation == MS_WCS_GET_CAPABILITIES) { retVal = msWCSGetCapabilities20(map, request, params, ows_request); } else if (operation == MS_WCS_DESCRIBE_COVERAGE) { retVal = msWCSDescribeCoverage20(map, params, ows_request); } else if (operation == MS_WCS_GET_COVERAGE) { retVal = msWCSGetCoverage20(map, request, params, ows_request); } else { msSetError(MS_WCSERR, "Invalid request '%s'.", "msWCSDispatch20()", ows_request->request); retVal = msWCSException20(map, "InvalidParameterValue", "request", "2.0.1"); } /* clean up */ msWCSFreeParamsObj20(params); return retVal; #else /* def USE_LIBXML2 */ msSetError(MS_WCSERR, "WCS 2.0 needs mapserver to be compiled with libxml2.", "msWCSDispatch()"); return msWCSException(map, "mapserv", "NoApplicableCode", "2.0.1"); #endif /* def USE_LIBXML2 */ } else { /* unsupported version */ msSetError(MS_WCSERR, "WCS Server does not support VERSION %s.", "msWCSDispatch()", ows_request->version); return msWCSException(map, "InvalidParameterValue", "version", ows_request->version); } #else msSetError(MS_WCSERR, "WCS server support is not available.", "msWCSDispatch()"); return MS_FAILURE; #endif } /************************************************************************/ /* msWCSGetCoverageMetadata() */ /************************************************************************/ #ifdef USE_WCS_SVR int msWCSGetCoverageMetadata( layerObj *layer, coverageMetadataObj *cm ) { char *srs_urn = NULL; int i = 0; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* Get the SRS in WCS 1.0 format (eg. EPSG:n) */ /* -------------------------------------------------------------------- */ if((cm->srs = msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "CO", MS_TRUE)) == NULL) { if((cm->srs = msOWSGetEPSGProj(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_TRUE)) == NULL) { msSetError(MS_WCSERR, "Unable to determine the SRS for this layer, no projection defined and no metadata available.", "msWCSGetCoverageMetadata()"); return MS_FAILURE; } } /* -------------------------------------------------------------------- */ /* Get the SRS in urn format. */ /* -------------------------------------------------------------------- */ if((srs_urn = msOWSGetProjURN(&(layer->projection), &(layer->metadata), "CO", MS_TRUE)) == NULL) { srs_urn = msOWSGetProjURN(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_TRUE); } if( srs_urn != NULL ) { if( strlen(srs_urn) > sizeof(cm->srs_urn) - 1 ) { msSetError(MS_WCSERR, "SRS URN too long!", "msWCSGetCoverageMetadata()"); return MS_FAILURE; } strcpy( cm->srs_urn, srs_urn ); msFree( srs_urn ); } else cm->srs_urn[0] = '\0'; /* -------------------------------------------------------------------- */ /* If we have "virtual dataset" metadata on the layer, then use */ /* that in preference to inspecting the file(s). */ /* We require extent and either size or resolution. */ /* -------------------------------------------------------------------- */ if( msOWSLookupMetadata(&(layer->metadata), "CO", "extent") != NULL && (msOWSLookupMetadata(&(layer->metadata), "CO", "resolution") != NULL || msOWSLookupMetadata(&(layer->metadata), "CO", "size") != NULL) ) { const char *value; /* get extent */ cm->extent.minx = 0.0; cm->extent.maxx = 0.0; cm->extent.miny = 0.0; cm->extent.maxy = 0.0; if( msOWSGetLayerExtent( layer->map, layer, "CO", &cm->extent ) == MS_FAILURE ) return MS_FAILURE; /* get resolution */ cm->xresolution = 0.0; cm->yresolution = 0.0; if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "resolution")) != NULL ) { char **tokens; int n; tokens = msStringSplit(value, ' ', &n); if( tokens == NULL || n != 2 ) { msSetError( MS_WCSERR, "Wrong number of arguments for wcs|ows_resolution metadata.", "msWCSGetCoverageMetadata()"); msFreeCharArray( tokens, n ); return MS_FAILURE; } cm->xresolution = atof(tokens[0]); cm->yresolution = atof(tokens[1]); msFreeCharArray( tokens, n ); } /* get Size (in pixels and lines) */ cm->xsize = 0; cm->ysize = 0; if( (value=msOWSLookupMetadata(&(layer->metadata), "CO", "size")) != NULL ) { char **tokens; int n; tokens = msStringSplit(value, ' ', &n); if( tokens == NULL || n != 2 ) { msSetError( MS_WCSERR, "Wrong number of arguments for wcs|ows_size metadata.", "msWCSGetCoverageDomain()"); msFreeCharArray( tokens, n ); return MS_FAILURE; } cm->xsize = atoi(tokens[0]); cm->ysize = atoi(tokens[1]); msFreeCharArray( tokens, n ); } /* try to compute raster size */ if( cm->xsize == 0 && cm->ysize == 0 && cm->xresolution != 0.0 && cm->yresolution != 0.0 && cm->extent.minx != cm->extent.maxx && cm->extent.miny != cm->extent.maxy ) { cm->xsize = (int) ((cm->extent.maxx - cm->extent.minx) / cm->xresolution + 0.5); cm->ysize = (int) fabs((cm->extent.maxy - cm->extent.miny) / cm->yresolution + 0.5); } /* try to compute raster resolution */ if( (cm->xresolution == 0.0 || cm->yresolution == 0.0) && cm->xsize != 0 && cm->ysize != 0 ) { cm->xresolution = (cm->extent.maxx - cm->extent.minx) / cm->xsize; cm->yresolution = (cm->extent.maxy - cm->extent.miny) / cm->ysize; } /* do we have information to do anything */ if( cm->xresolution == 0.0 || cm->yresolution == 0.0 || cm->xsize == 0 || cm->ysize == 0 ) { msSetError( MS_WCSERR, "Failed to collect extent and resolution for WCS coverage from metadata for layer '%s'. Need value wcs|ows_resolution or wcs|ows_size values.", "msWCSGetCoverageMetadata()", layer->name ); return MS_FAILURE; } /* compute geotransform */ cm->geotransform[0] = cm->extent.minx; cm->geotransform[1] = cm->xresolution; cm->geotransform[2] = 0.0; cm->geotransform[3] = cm->extent.maxy; cm->geotransform[4] = 0.0; cm->geotransform[5] = -fabs(cm->yresolution); /* get bands count, or assume 1 if not found */ cm->bandcount = 1; if( (value=msOWSLookupMetadata(&(layer->metadata), "CO", "bandcount")) != NULL) { cm->bandcount = atoi(value); } /* get bands type, or assume float if not found */ cm->imagemode = MS_IMAGEMODE_FLOAT32; if( (value=msOWSLookupMetadata(&(layer->metadata), "CO", "imagemode")) != NULL ) { if( EQUAL(value,"INT16") ) cm->imagemode = MS_IMAGEMODE_INT16; else if( EQUAL(value,"FLOAT32") ) cm->imagemode = MS_IMAGEMODE_FLOAT32; else if( EQUAL(value,"BYTE") ) cm->imagemode = MS_IMAGEMODE_BYTE; else { msSetError( MS_WCSERR, "Content of wcs|ows_imagemode (%s) not recognised. Should be one of BYTE, INT16 or FLOAT32.", "msWCSGetCoverageMetadata()", value ); return MS_FAILURE; } } /* set color interpretation to undefined */ /* TODO: find better solution */ for(i = 0; i < 10; ++i) { cm->bandinterpretation[i] = GDALGetColorInterpretationName(GCI_Undefined); } } else if( layer->data == NULL ) { /* no virtual metadata, not ok unless we're talking 1 image, hopefully we can fix that */ msSetError( MS_WCSERR, "RASTER Layer with no DATA statement and no WCS virtual dataset metadata. Tileindexed raster layers not supported for WCS without virtual dataset metadata (cm->extent, wcs_res, wcs_size).", "msWCSGetCoverageDomain()" ); return MS_FAILURE; } else { /* work from the file (e.g. DATA) */ GDALDatasetH hDS; GDALRasterBandH hBand; char szPath[MS_MAXPATHLEN]; char *decrypted_path; msGDALInitialize(); msTryBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( layer->map, szPath ); if( !decrypted_path ) return MS_FAILURE; msAcquireLock( TLOCK_GDAL ); hDS = GDALOpen( decrypted_path, GA_ReadOnly ); if( hDS == NULL ) { const char *cpl_error_msg = CPLGetLastErrorMsg(); /* we wish to avoid reporting decrypted paths */ if( cpl_error_msg != NULL && strstr(cpl_error_msg,decrypted_path) != NULL && strcmp(decrypted_path,szPath) != 0 ) cpl_error_msg = NULL; if( cpl_error_msg == NULL ) cpl_error_msg = ""; msReleaseLock( TLOCK_GDAL ); msSetError( MS_IOERR, "%s", "msWCSGetCoverageMetadata()", cpl_error_msg ); msFree( decrypted_path ); return MS_FAILURE; } msFree( decrypted_path ); msGetGDALGeoTransform( hDS, layer->map, layer, cm->geotransform ); cm->xsize = GDALGetRasterXSize( hDS ); cm->ysize = GDALGetRasterYSize( hDS ); cm->extent.minx = cm->geotransform[0]; cm->extent.maxx = cm->geotransform[0] + cm->geotransform[1] * cm->xsize + cm->geotransform[2] * cm->ysize; cm->extent.miny = cm->geotransform[3] + cm->geotransform[4] * cm->xsize + cm->geotransform[5] * cm->ysize; cm->extent.maxy = cm->geotransform[3]; cm->xresolution = cm->geotransform[1]; cm->yresolution = cm->geotransform[5]; /* TODO: need to set resolution */ cm->bandcount = GDALGetRasterCount( hDS ); if( cm->bandcount == 0 ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_WCSERR, "Raster file %s has no raster bands. This cannot be used in a layer.", "msWCSGetCoverageMetadata()", layer->data ); return MS_FAILURE; } hBand = GDALGetRasterBand( hDS, 1 ); switch( GDALGetRasterDataType( hBand ) ) { case GDT_Byte: cm->imagemode = MS_IMAGEMODE_BYTE; break; case GDT_Int16: cm->imagemode = MS_IMAGEMODE_INT16; break; default: cm->imagemode = MS_IMAGEMODE_FLOAT32; break; } /* color interpretation */ for(i = 1; i <= 10 && i <= cm->bandcount; ++i) { GDALColorInterp colorInterp; hBand = GDALGetRasterBand( hDS, i ); colorInterp = GDALGetRasterColorInterpretation(hBand); cm->bandinterpretation[i-1] = GDALGetColorInterpretationName(colorInterp); } GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } /* we must have the bounding box in lat/lon [WGS84(DD)/EPSG:4326] */ cm->llextent = cm->extent; /* Already in latlong .. use directly. */ if( layer->projection.proj != NULL && pj_is_latlong(layer->projection.proj)) { /* no change */ } else if (layer->projection.numargs > 0 && !pj_is_latlong(layer->projection.proj)) /* check the layer projection */ msProjectRect(&(layer->projection), NULL, &(cm->llextent)); else if (layer->map->projection.numargs > 0 && !pj_is_latlong(layer->map->projection.proj)) /* check the map projection */ msProjectRect(&(layer->map->projection), NULL, &(cm->llextent)); else { /* projection was specified in the metadata only (EPSG:... only at the moment) */ projectionObj proj; char projstring[32]; msInitProjection(&proj); /* or bad things happen */ snprintf(projstring, sizeof(projstring), "init=epsg:%.20s", cm->srs+5); if (msLoadProjectionString(&proj, projstring) != 0) return MS_FAILURE; msProjectRect(&proj, NULL, &(cm->llextent)); } return MS_SUCCESS; } #endif /* def USE_WCS_SVR */ mapserver-6.4.1/mapowscommon.c0000644002461700001440000006007412261257215016206 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC OWS Common Implementation for use by MapServer OGC code * versions: * 1.0.0 (OGC Document 05-008c1) * 1.1.0 (OGC document 06-121r3) * * Author: Tom Kralidis (tomkralidis@hotmail.com) * ****************************************************************************** * Copyright (c) 2006, Tom Kralidis * * 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. ****************************************************************************/ #include "mapserver.h" #include "mapows.h" #ifdef USE_LIBXML2 #include #include #include "mapowscommon.h" #include "maplibxml2.h" /** * msOWSCommonServiceIdentification() * * returns an object of ServiceIdentification as per: * * 1.0.0 subclause 7.4.3 * 1.1.1 subclause 7.4.4 * * @param map mapObj used to fetch WEB/METADATA * @param servicetype the OWS type * @param version the version of the OWS * * @return psRootNode xmlNodePtr of XML construct * */ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, const char *servicetype, const char *version, const char *namespaces) { const char *value = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); /* create element name */ psRootNode = xmlNewNode(psNsOws, BAD_CAST "ServiceIdentification"); /* add child elements */ value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "title"); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_title\" missing for ows:Title")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "abstract"); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_abstract\" was missing for ows:Abstract")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "keywordlist"); if (value) { psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL); msLibXml2GenerateList(psNode, psNsOws, "Keyword", value, ','); } else { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_keywordlist\" was missing for ows:KeywordList")); } psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceType", BAD_CAST servicetype); xmlNewProp(psNode, BAD_CAST "codeSpace", BAD_CAST MS_OWSCOMMON_OGC_CODESPACE); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceTypeVersion", BAD_CAST version); value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "fees"); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_fees\" was missing for ows:Fees")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "accessconstraints"); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_accessconstraints\" was missing for ows:AccessConstraints")); } return psRootNode; } /** * msOWSCommonServiceProvider() * * returns an object of ServiceProvider as per: * * * 1.0.0 subclause 7.4.4 * 1.1.0 subclause 7.4.5 * * @param map mapObj to fetch MAP/WEB/METADATA * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, mapObj *map, const char *namespaces) { const char *value = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psSubNode = NULL; xmlNodePtr psSubSubNode = NULL; xmlNodePtr psSubSubSubNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST "ServiceProvider"); /* add child elements */ value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactorganization"); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ProviderName", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Mandatory metadata \"ows_contactorganization\" was missing for ows:ProviderName")); } psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple"); value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "service_onlineresource"); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_service_onlineresource\" was missing for ows:ProviderSite/@xlink:href")); } psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL); value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactperson"); psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "IndividualName", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactperson\" was missing for ows:IndividualName")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactposition"); psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactposition\" was missing for ows:PositionName")); } psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL); value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactvoicetelephone"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactvoicetelephone\" was missing for ows:Voice")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactfacsimiletelephone"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactfacsimiletelephone\" was missing for ows:Facsimile")); } psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Address", NULL); value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "address"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "DeliveryPoint", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_address\" was missing for ows:DeliveryPoint")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "city"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_city\" was missing for ows:City")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "stateorprovince"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_stateorprovince\" was missing for ows:AdministrativeArea")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "postcode"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "PostalCode", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_postcode\" was missing for ows:PostalCode")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "country"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Country", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_country\" was missing for ows:Country")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactelectronicmailaddress"); psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactelectronicmailaddress\" was missing for ows:ElectronicMailAddress")); } psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL); xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple"); value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "service_onlineresource"); xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "href", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_service_onlineresource\" was missing for ows:OnlineResource/@xlink:href")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "hoursofservice"); psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "HoursOfService", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_hoursofservice\" was missing for ows:HoursOfService")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "contactinstructions"); psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactinstructions\" was missing for ows:ContactInstructions")); } value = msOWSLookupMetadata(&(map->web.metadata), namespaces, "role"); psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_role\" was missing for ows:Role")); } return psRootNode; } /** * msOWSCommonOperationsMetadata() * * returns the root element of OperationsMetadata as per: * * 1.0.0 subclause 7.4.5 * 1.1.0 subclause 7.4.6 * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonOperationsMetadata(xmlNsPtr psNsOws) { xmlNodePtr psRootNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST "OperationsMetadata"); return psRootNode; } /** * msOWSCommonOperationsMetadataOperation() * * returns an Operation element of OperationsMetadata as per: * * 1.0.0 subclause 7.4.5 * 1.1.0 subclause 7.4.6 * * @param name name of the Operation * @param method HTTP method: OWS_METHOD_GET, OWS_METHOD_POST or OWS_METHOD_GETPOST) * @param url online resource URL * * @return psRootNode xmlNodePtr pointer of XML construct */ xmlNodePtr msOWSCommonOperationsMetadataOperation(xmlNsPtr psNsOws, xmlNsPtr psXLinkNs, char *name, int method, char *url) { xmlNodePtr psRootNode = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psSubNode = NULL; xmlNodePtr psSubSubNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST "Operation"); xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "DCP", NULL); psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "HTTP", NULL); if (method == OWS_METHOD_GET || method == OWS_METHOD_GETPOST ) { psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Get", NULL); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "type", BAD_CAST "simple"); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "href", BAD_CAST url); } if (method == OWS_METHOD_POST || method == OWS_METHOD_GETPOST ) { psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Post", NULL); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "type", BAD_CAST "simple"); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "href", BAD_CAST url); } return psRootNode; } /** * msOWSCommonOperationsMetadataDomainType() * * returns a Parameter or Constraint element (which are of type ows:DomainType) * of OperationsMetadata as per: * * 1.0.0 subclause 7.4.5 * 1.1.0 subclause 7.4.6 * * @param version the integerized x.y.z version of OWS Common to use * @param elname name of the element (Parameter | Constraint) * @param name name of the Parameter * @param values list of values (comma separated list) or NULL if none * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonOperationsMetadataDomainType(int version, xmlNsPtr psNsOws, char *elname, char *name, char *values) { xmlNodePtr psRootNode = NULL; xmlNodePtr psNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST elname); xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name); if (version == OWS_1_0_0) { msLibXml2GenerateList(psRootNode, psNsOws, "Value", values, ','); } if (version == OWS_1_1_0 || version == OWS_2_0_0) { psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "AllowedValues", NULL); msLibXml2GenerateList(psNode, psNsOws, "Value", values, ','); } return psRootNode; } /** * msOWSCommonExceptionReport() * * returns an object of ExceptionReport as per clause 8 * * @param ows_version the version of OWS Common to use * @param schemas_location URL to OGC Schemas Location base * @param version the version of the calling specification * @param language ISO3166 code of language * @param exceptionCode a code from the calling specification's list of exceptions, or from OWS Common * @param locator where the exception was encountered (i.e. "layers" keyword) * @param ExceptionText the actual error message * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const char *schemas_location, const char *version, const char *language, const char *exceptionCode, const char *locator, const char *ExceptionText) { char *xsi_schemaLocation = NULL; char szVersionBuf[OWS_VERSION_MAXLEN]; xmlNsPtr psNsXsi = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psMainNode = NULL; psRootNode = xmlNewNode(psNsOws, BAD_CAST "ExceptionReport"); psNsXsi = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); /* add attributes to root element */ xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST version); if (ows_version == OWS_1_0_0) { xmlNewProp(psRootNode, BAD_CAST "language", BAD_CAST language); } if (ows_version == OWS_1_1_0) { xmlNewProp(psRootNode, BAD_CAST "xml:lang", BAD_CAST language); } xsi_schemaLocation = msStrdup((char *)psNsOws->href); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)schemas_location); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/ows/"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)msOWSGetVersionString(ows_version, szVersionBuf)); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/owsExceptionReport.xsd"); /* add namespace'd attributes to root element */ xmlNewNsProp(psRootNode, psNsXsi, BAD_CAST "schemaLocation", BAD_CAST xsi_schemaLocation); /* add child element */ psMainNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Exception", NULL); /* add attributes to child */ xmlNewProp(psMainNode, BAD_CAST "exceptionCode", BAD_CAST exceptionCode); if (locator != NULL) { xmlNewProp(psMainNode, BAD_CAST "locator", BAD_CAST locator); } if (ExceptionText != NULL) { xmlNewChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST ExceptionText); } free(xsi_schemaLocation); return psRootNode; } /** * msOWSCommonBoundingBox() * * returns an object of BoundingBox as per subclause 10.2.1 * * If necessary (ie. an EPSG URN GCS such as 4326) the tuple axes will be * reoriented to match the EPSG coordinate system expectations. * * @param psNsOws OWS namespace object * @param crs the CRS / EPSG code * @param dimensions number of dimensions of the coordinates * @param minx minx * @param miny miny * @param maxx maxx * @param maxy maxy * * @return psRootNode xmlNodePtr pointer of XML construct */ xmlNodePtr msOWSCommonBoundingBox(xmlNsPtr psNsOws, const char *crs, int dimensions, double minx, double miny, double maxx, double maxy) { char LowerCorner[100]; char UpperCorner[100]; char dim_string[100]; xmlNodePtr psRootNode = NULL; /* Do we need to reorient tuple axes? */ if(crs && strstr(crs, "imageCRS") == NULL) { projectionObj proj; msInitProjection( &proj ); if( msLoadProjectionString( &proj, (char *) crs ) == 0 ) { msAxisNormalizePoints( &proj, 1, &minx, &miny ); msAxisNormalizePoints( &proj, 1, &maxx, &maxy ); } msFreeProjection( &proj ); } if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); /* create element name */ psRootNode = xmlNewNode(psNsOws, BAD_CAST "BoundingBox"); /* add attributes to the root element */ xmlNewProp(psRootNode, BAD_CAST "crs", BAD_CAST crs); snprintf( dim_string, sizeof(dim_string), "%d", dimensions ); xmlNewProp(psRootNode, BAD_CAST "dimensions", BAD_CAST dim_string); snprintf(LowerCorner, sizeof(LowerCorner), "%.15g %.15g", minx, miny); snprintf(UpperCorner, sizeof(UpperCorner), "%.15g %.15g", maxx, maxy); /* add child elements */ xmlNewChild(psRootNode, psNsOws,BAD_CAST "LowerCorner",BAD_CAST LowerCorner); xmlNewChild(psRootNode, psNsOws,BAD_CAST "UpperCorner",BAD_CAST UpperCorner); return psRootNode; } /** * msOWSCommonWGS84BoundingBox() * * returns an object of WGS84BoundingBox as per subclause 10.2.2 * * @param psNsOws OWS namespace object * @param dimensions number of dimensions of the coordinates * @param minx minx * @param miny miny * @param maxx maxx * @param maxy maxy * * @return psRootNode xmlNodePtr pointer of XML construct */ xmlNodePtr msOWSCommonWGS84BoundingBox(xmlNsPtr psNsOws, int dimensions, double minx, double miny, double maxx, double maxy) { char LowerCorner[100]; char UpperCorner[100]; char dim_string[100]; xmlNodePtr psRootNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); /* create element name */ psRootNode = xmlNewNode(psNsOws, BAD_CAST "WGS84BoundingBox"); snprintf( dim_string, sizeof(dim_string), "%d", dimensions ); xmlNewProp(psRootNode, BAD_CAST "dimensions", BAD_CAST dim_string); snprintf(LowerCorner, sizeof(LowerCorner), "%.15g %.15g", minx, miny); snprintf(UpperCorner, sizeof(UpperCorner), "%.15g %.15g", maxx, maxy); /* add child elements */ xmlNewChild(psRootNode, psNsOws,BAD_CAST "LowerCorner",BAD_CAST LowerCorner); xmlNewChild(psRootNode, psNsOws,BAD_CAST "UpperCorner",BAD_CAST UpperCorner); return psRootNode; } /** * _validateNamespace() * * validates the namespace passed to this module's functions * * @param psNsOws namespace object * * @return MS_SUCCESS or MS_FAILURE * */ int _validateNamespace(xmlNsPtr psNsOws) { char namespace_prefix[10]; snprintf(namespace_prefix, sizeof(namespace_prefix), "%s", psNsOws->prefix); if (strcmp(namespace_prefix, MS_OWSCOMMON_OWS_NAMESPACE_PREFIX) == 0) return MS_SUCCESS; else return MS_FAILURE; } xmlNodePtr msOWSCommonxmlNewChildEncoded( xmlNodePtr psParent, xmlNsPtr psNs, const char* name, const char *content, const char *encoding) { char *encoded = NULL; xmlNodePtr psNode; if (encoding && content) { encoded = msGetEncodedString(content, encoding); psNode = xmlNewChild(psParent, psNs, BAD_CAST name, BAD_CAST encoded); msFree(encoded); return psNode; } else return xmlNewChild(psParent, psNs, BAD_CAST name, BAD_CAST content); } /* * Valid an xml string against an XML schema * Inpired from: http://xml.developpez.com/sources/?page=validation#validate_XSD_CppCLI_2 * taken from tinyows.org */ int msOWSSchemaValidation(const char* xml_schema, const char* xml) { xmlSchemaPtr schema; xmlSchemaParserCtxtPtr ctxt; xmlSchemaValidCtxtPtr validctxt; int ret; xmlDocPtr doc; if (!xml_schema || !xml) return MS_FAILURE; xmlInitParser(); schema = NULL; ret = -1; /* Open XML Schema File */ ctxt = xmlSchemaNewParserCtxt(xml_schema); /* else ctxt = xmlSchemaNewMemParserCtxt(xml_schema); */ /* xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc) libxml2_callback, (xmlSchemaValidityWarningFunc) libxml2_callback, stderr); */ schema = xmlSchemaParse(ctxt); xmlSchemaFreeParserCtxt(ctxt); /* If XML Schema hasn't been rightly loaded */ if (schema == NULL) { xmlSchemaCleanupTypes(); xmlMemoryDump(); xmlCleanupParser(); return ret; } doc = xmlParseDoc((xmlChar *)xml); if (doc != NULL) { /* Loading XML Schema content */ validctxt = xmlSchemaNewValidCtxt(schema); /* xmlSchemaSetValidErrors(validctxt, (xmlSchemaValidityErrorFunc) libxml2_callback, (xmlSchemaValidityWarningFunc) libxml2_callback, stderr); */ /* validation */ ret = xmlSchemaValidateDoc(validctxt, doc); xmlSchemaFreeValidCtxt(validctxt); } xmlSchemaFree(schema); xmlFreeDoc(doc); xmlCleanupParser(); return ret; } #endif /* defined(USE_LIBXML2) */ /** * msOWSCommonNegotiateVersion() * * returns a supported version as per subclause 7.3.2 * * @param requested_version the version passed by the client * @param supported_versions an array of supported versions * @param num_supported_versions size of supported_versions * * @return supported version integer, or -1 on error * */ int msOWSCommonNegotiateVersion(int requested_version, int supported_versions[], int num_supported_versions) { int i; /* if version is not set return error */ if (! requested_version) return -1; /* return the first entry that's equal to the requested version */ for (i = 0; i < num_supported_versions; i++) { if (supported_versions[i] == requested_version) return supported_versions[i]; } /* no match; calling code should throw an exception */ return -1; } mapserver-6.4.1/mapregex.c0000644002461700001440000000564012261257215015275 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Regex wrapper * Author: Bill Binko * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* we can't include mapserver.h, so we need our own basics */ #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #else #include #endif /*Need to specify this so that mapregex.h doesn't defined constants and doesn't #define away our ms_*/ #if defined(_WIN32) && !defined(__CYGWIN__) #define off_t long #endif #include "mapserver.h" #include "mapregex.h" #include MS_API_EXPORT(int) ms_regcomp(ms_regex_t *regex, const char *expr, int cflags) { /* Must free in regfree() */ regex_t* sys_regex = (regex_t*) msSmallMalloc(sizeof(regex_t)); regex->sys_regex = (void*) sys_regex; return regcomp(sys_regex, expr, cflags); } MS_API_EXPORT(size_t) ms_regerror(int errcode, const ms_regex_t *regex, char *errbuf, size_t errbuf_size) { return regerror(errcode, (regex_t*)(regex->sys_regex), errbuf, errbuf_size); } MS_API_EXPORT(int) ms_regexec(const ms_regex_t *regex, const char *string, size_t nmatch, ms_regmatch_t pmatch[], int eflags) { /*This next line only works because we know that regmatch_t and ms_regmatch_t are exactly alike (POSIX STANDARD)*/ return regexec((const regex_t*)(regex->sys_regex), string, nmatch, (regmatch_t*) pmatch, eflags); } MS_API_EXPORT(void) ms_regfree(ms_regex_t *regex) { regfree((regex_t*)(regex->sys_regex)); free(regex->sys_regex); return; } mapserver-6.4.1/strptime.c0000644002461700001440000002423712261257215015337 0ustar tbonfortusers/* * Copyright (c) 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of KTH nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #include #include #include #include "mapserver.h" static const char *abb_weekdays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL }; static const char *full_weekdays[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL }; static const char *abb_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL }; static const char *full_month[] = { "January", "February", "Mars", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL, }; static const char *ampm[] = { "am", "pm", NULL }; /* * tm_year is relative this year */ const int tm_year_base = 1900; /* * Return TRUE iff `year' was a leap year. * Needed for strptime. */ static int is_leap_year (int year) { return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); } /* Needed for strptime. */ static int match_string (const char **buf, const char **strs) { int i = 0; for (i = 0; strs[i] != NULL; ++i) { int len = strlen (strs[i]); if (strncasecmp (*buf, strs[i], len) == 0) { *buf += len; return i; } } return -1; } /* Needed for strptime. */ static int first_day (int year) { int ret = 4; for (; year > 1970; --year) ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7; return ret; } /* * Set `timeptr' given `wnum' (week number [0, 53]) * Needed for strptime */ static void set_week_number_sun (struct tm *timeptr, int wnum) { int fday = first_day (timeptr->tm_year + tm_year_base); timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday; if (timeptr->tm_yday < 0) { timeptr->tm_wday = fday; timeptr->tm_yday = 0; } } /* * Set `timeptr' given `wnum' (week number [0, 53]) * Needed for strptime */ static void set_week_number_mon (struct tm *timeptr, int wnum) { int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7; timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday; if (timeptr->tm_yday < 0) { timeptr->tm_wday = (fday + 1) % 7; timeptr->tm_yday = 0; } } /* * Set `timeptr' given `wnum' (week number [0, 53]) * Needed for strptime */ static void set_week_number_mon4 (struct tm *timeptr, int wnum) { int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7; int offset = 0; if (fday < 4) offset += 7; timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday; if (timeptr->tm_yday < 0) { timeptr->tm_wday = fday; timeptr->tm_yday = 0; } } /* strptime: roken */ /* extern "C" */ char * /* strptime (const char *buf, const char *format, struct tm *timeptr) */ strptime (const char *buf, const char *format, struct tm *timeptr) { char c; for (; (c = *format) != '\0'; ++format) { char *s; int ret; if (isspace (c)) { while (isspace (*buf)) ++buf; } else if (c == '%' && format[1] != '\0') { c = *++format; if (c == 'E' || c == 'O') c = *++format; switch (c) { case 'A' : ret = match_string (&buf, full_weekdays); if (ret < 0) return NULL; timeptr->tm_wday = ret; break; case 'a' : ret = match_string (&buf, abb_weekdays); if (ret < 0) return NULL; timeptr->tm_wday = ret; break; case 'B' : ret = match_string (&buf, full_month); if (ret < 0) return NULL; timeptr->tm_mon = ret; break; case 'b' : case 'h' : ret = match_string (&buf, abb_month); if (ret < 0) return NULL; timeptr->tm_mon = ret; break; case 'C' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_year = (ret * 100) - tm_year_base; buf = s; break; case 'c' : abort (); case 'D' : /* %m/%d/%y */ s = strptime (buf, "%m/%d/%y", timeptr); if (s == NULL) return NULL; buf = s; break; case 'd' : case 'e' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_mday = ret; buf = s; break; case 'H' : case 'k' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_hour = ret; buf = s; break; case 'I' : case 'l' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; if (ret == 12) timeptr->tm_hour = 0; else timeptr->tm_hour = ret; buf = s; break; case 'j' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_yday = ret - 1; buf = s; break; case 'm' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_mon = ret - 1; buf = s; break; case 'M' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_min = ret; buf = s; break; case 'n' : if (*buf == '\n') ++buf; else return NULL; break; case 'p' : ret = match_string (&buf, ampm); if (ret < 0) return NULL; if (timeptr->tm_hour == 0) { if (ret == 1) timeptr->tm_hour = 12; } else timeptr->tm_hour += 12; break; case 'r' : /* %I:%M:%S %p */ s = strptime (buf, "%I:%M:%S %p", timeptr); if (s == NULL) return NULL; buf = s; break; case 'R' : /* %H:%M */ s = strptime (buf, "%H:%M", timeptr); if (s == NULL) return NULL; buf = s; break; case 'S' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_sec = ret; buf = s; break; case 't' : if (*buf == '\t') ++buf; else return NULL; break; case 'T' : /* %H:%M:%S */ case 'X' : s = strptime (buf, "%H:%M:%S", timeptr); if (s == NULL) return NULL; buf = s; break; case 'u' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_wday = ret - 1; buf = s; break; case 'w' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_wday = ret; buf = s; break; case 'U' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; set_week_number_sun (timeptr, ret); buf = s; break; case 'V' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; set_week_number_mon4 (timeptr, ret); buf = s; break; case 'W' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; set_week_number_mon (timeptr, ret); buf = s; break; case 'x' : s = strptime (buf, "%Y:%m:%d", timeptr); if (s == NULL) return NULL; buf = s; break; case 'y' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; if (ret < 70) timeptr->tm_year = 100 + ret; else timeptr->tm_year = ret; buf = s; break; case 'Y' : ret = strtol (buf, &s, 10); if (s == buf) return NULL; timeptr->tm_year = ret - tm_year_base; buf = s; break; case 'Z' : abort (); case '\0' : --format; /* FALLTHROUGH */ case '%' : if (*buf == '%') ++buf; else return NULL; break; default : if (*buf == '%' || *++buf == c) ++buf; else return NULL; break; } } else { if (*buf == c) ++buf; else return NULL; } } return (char *)buf; } #endif mapserver-6.4.1/mapio.h0000644002461700001440000001110112261257215014564 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Definitions for MapServer IO redirection capability. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * 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 MAPIO_H #define MAPIO_H /* ** We deliberately emulate stdio functions in the msIO cover functions. ** This makes it easy for folks to understand the semantics, and means we ** can just #define things to use stdio in the simplest case. */ #include #ifdef __cplusplus extern "C" { #endif #ifndef MS_PRINT_FUNC_FORMAT #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP) #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) __attribute__((__format__ (__printf__, format_idx, arg_idx))) #else #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) #endif #endif /* stdio analogs */ int MS_DLL_EXPORT msIO_printf( const char *format, ... ) MS_PRINT_FUNC_FORMAT(1,2); int MS_DLL_EXPORT msIO_fprintf( FILE *stream, const char *format, ... ) MS_PRINT_FUNC_FORMAT(2,3); int MS_DLL_EXPORT msIO_fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream ); int MS_DLL_EXPORT msIO_fread( void *ptr, size_t size, size_t nmemb, FILE *stream ); int MS_DLL_EXPORT msIO_vfprintf( FILE *fp, const char *format, va_list ap ); #ifdef USE_GD gdIOCtx MS_DLL_EXPORT *msIO_getGDIOCtx( FILE *fp ); #endif /* ** Definitions for the callback function and the details of the IO ** channel contexts. */ typedef int (*msIO_llReadWriteFunc)( void *cbData, void *data, int byteCount ); typedef struct msIOContext_t { const char *label; int write_channel; /* 1 for stdout/stderr, 0 for stdin */ msIO_llReadWriteFunc readWriteFunc; void *cbData; } msIOContext; int MS_DLL_EXPORT msIO_installHandlers( msIOContext *stdin_context, msIOContext *stdout_context, msIOContext *stderr_context ); msIOContext MS_DLL_EXPORT *msIO_getHandler( FILE * ); void msIO_setHeader (const char *header, const char* value, ...) MS_PRINT_FUNC_FORMAT(2,3); void msIO_sendHeaders(void); /* ** These can be used instead of the stdio style functions if you have ** msIOContext's for the channel in question. */ int msIO_contextRead( msIOContext *context, void *data, int byteCount ); int msIO_contextWrite( msIOContext *context, const void *data, int byteCount ); /* ** For redirecting IO to a memory buffer. */ typedef struct { unsigned char *data; int data_len; /* really buffer length */ int data_offset; /* really buffer used */ } msIOBuffer; int MS_DLL_EXPORT msIO_bufferRead( void *, void *, int ); int MS_DLL_EXPORT msIO_bufferWrite( void *, void *, int ); void MS_DLL_EXPORT msIO_resetHandlers(void); void MS_DLL_EXPORT msIO_installStdoutToBuffer(void); void MS_DLL_EXPORT msIO_installStdinFromBuffer(void); void MS_DLL_EXPORT msIO_Cleanup(void); char MS_DLL_EXPORT *msIO_stripStdoutBufferContentType(void); void MS_DLL_EXPORT msIO_stripStdoutBufferContentHeaders(void); /* this is just for setting normal stdout's to binary mode on windows */ int msIO_needBinaryStdout( void ); int msIO_needBinaryStdin( void ); #ifdef __cplusplus } #endif #endif /* nef MAPIO_H */ mapserver-6.4.1/mapogcsos.c0000644002461700001440000037110612261257215015463 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC SOS implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2006, Y. Assefa, DM Solutions Group Inc * * 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. **********************************************************************/ #define _GNU_SOURCE #include "mapserver.h" #if defined(USE_SOS_SVR) && defined(USE_LIBXML2) #include "maperror.h" #include "mapthread.h" #include "mapows.h" #include "maptime.h" #include "mapgml.h" #include "mapogcfilter.h" #include "mapowscommon.h" #include "maplibxml2.h" #include "libxml/parser.h" #include "libxml/tree.h" #include "libxml/xpath.h" #include "libxml/xpathInternals.h" const char *pszSOSVersion = "1.0.0"; const char *pszSOSNamespaceUri = "http://www.opengis.net/sos/1.0"; const char *pszSOSNamespacePrefix = "sos"; const char *pszOMNamespaceUri = "http://www.opengis.net/om/1.0"; const char *pszOMNamespacePrefix = "om"; const char *pszSOSDescribeSensorMimeType = "text/xml; subtype=\"sensorML/1.0.0\""; const char *pszSOSGetObservationMimeType = "text/xml; subtype=\"om/1.0.0\""; typedef struct { char *pszProcedure; xmlNodePtr psResultNode; } SOSProcedureNode; int msSOSParseRequest(mapObj *map, cgiRequestObj *request, sosParamsObj *sosparams); void msSOSFreeParamsObj(sosParamsObj *sosparams); /* ** msSOSException() ** ** Report current MapServer error in XML exception format. ** Wrapper function around msOWSCommonExceptionReport. Merely ** passes SOS specific info. ** */ static int msSOSException(mapObj *map, char *locator, char *exceptionCode) { int size = 0; char *errorString = NULL; char *errorMessage = NULL; char *schemasLocation = NULL; const char *encoding; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode = NULL; xmlNsPtr psNsOws = NULL; xmlChar *buffer = NULL; psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); encoding = msOWSLookupMetadata(&(map->web.metadata), "SO", "encoding"); errorString = msGetErrorString("\n"); errorMessage = msEncodeHTMLEntities(errorString); schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_1_0, schemasLocation, pszSOSVersion, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage); xmlDocSetRootElement(psDoc, psRootNode); xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_printf("%s", buffer); /*free buffer and the document */ free(errorString); free(errorMessage); free(schemasLocation); xmlFree(buffer); xmlFreeDoc(psDoc); xmlFreeNs(psNsOws); /* ** The typical pattern is to call msSOSException() right after ** msSetError(). In order to prevent mapserv.c from re-reporting this ** error at a higher level, we mark it as reported here. #3571 */ { errorObj *err = msGetErrorObj(); if( err != NULL && err->code != MS_NOERR ) err->isreported = MS_TRUE; } return MS_FAILURE; } static int _IsInList(char **papsProcedures, int nDistinctProcedures, char *pszProcedure) { int i = 0; if (papsProcedures && nDistinctProcedures > 0 && pszProcedure) { for (i=0; ieType == FILTER_NODE_TYPE_PROPERTYNAME) { for (i=0; inumitems; i++) { if (strcasecmp(lp->items[i], psFilterNode->pszValue) == 0) { bFound = 1; break; } } if (!bFound) return MS_FALSE; } if (psFilterNode->psLeftNode && psFilterNode->eType != FILTER_NODE_TYPE_SPATIAL) { if (msSOSValidateFilter(psFilterNode->psLeftNode, lp) == MS_FALSE) return MS_FALSE; } if (psFilterNode->psRightNode && psFilterNode->eType != FILTER_NODE_TYPE_SPATIAL) { if (msSOSValidateFilter(psFilterNode->psRightNode, lp) == MS_FALSE) return MS_FALSE; } } return MS_TRUE; } /************************************************************************/ /* msSOSAddMetadataChildNode */ /* */ /* Utility function to add a metadata node. */ /************************************************************************/ void msSOSAddMetadataChildNode(xmlNodePtr psParent, const char *psNodeName, xmlNsPtr psNs, hashTableObj *metadata, const char *psNamespaces, const char *psMetadataName, const char *psDefaultValue) { xmlNodePtr psNode = NULL; char *psValue = NULL; if (psParent && psNodeName) { psValue = msOWSGetEncodeMetadata(metadata, psNamespaces, psMetadataName, psDefaultValue); if (psValue) { psNode = xmlNewChild(psParent, NULL, BAD_CAST psNodeName, BAD_CAST psValue); if (psNs) xmlSetNs(psNode, psNs); free(psValue); } } } /************************************************************************/ /* msSOSGetFirstLayerForOffering */ /* */ /* return the first layer for the offering. */ /************************************************************************/ layerObj *msSOSGetFirstLayerForOffering(mapObj *map, const char *pszOffering, const char *pszProperty) { layerObj *lp = NULL; const char *pszTmp = NULL; int i = 0; if (pszOffering && map) { for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); if (pszTmp && (strcasecmp(pszTmp, pszOffering) == 0)) { if (pszProperty) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "observedproperty_id"); if (pszTmp && (strcasecmp(pszTmp, pszProperty) == 0)) { lp = (GET_LAYER(map, i)); break; } } else { lp = (GET_LAYER(map, i)); break; } } } } return lp; } xmlNodePtr msSOSAddTimeNode(xmlNsPtr psNs, xmlNsPtr psNsGml, char *pszStart, char *pszEnd) { xmlNodePtr psNode=NULL; char *timeel= NULL; if (strcmp((char *)psNs->prefix,"sos") == 0) timeel = "time"; if (strcmp((char *)psNs->prefix,"om") == 0) timeel = "samplingTime"; else timeel = "time"; psNode = xmlNewNode(psNs, BAD_CAST timeel); xmlAddChild(psNode, msGML3TimePeriod(psNsGml, pszStart, pszEnd)); return psNode; } void msSOSAddPropertyNode(xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNodePtr psParent, layerObj *lp, xmlNsPtr psNsGml, char *pszCompositePhenomenonId) { const char *pszValue = NULL; char *pszTmpVal = NULL, *pszFullName = NULL; xmlNodePtr psCompNode, psNode; int i, j=0; char szTmp[256]; const char *pszComponentBase = "urn:ogc:def:property:"; if (psParent && lp) { psNode = xmlNewChild(psParent, NULL, BAD_CAST "observedProperty", NULL); psCompNode = xmlNewChild(psNode, psNsSwe, BAD_CAST "CompositePhenomenon", NULL); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id"); pszTmpVal = msStrdup(pszValue); if (pszCompositePhenomenonId != NULL) { /* unique value needs to be constructed */ pszTmpVal = msStringConcatenate(pszTmpVal, "_"); pszTmpVal = msStringConcatenate(pszTmpVal, pszCompositePhenomenonId); } if (pszTmpVal) { /*should always be true */ xmlNewNsProp(psCompNode, psNsGml, BAD_CAST "id", BAD_CAST pszTmpVal); msFree(pszTmpVal); } pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_name"); if (pszValue) psNode = xmlNewChild(psCompNode, psNsGml, BAD_CAST "name", BAD_CAST pszValue); /* add components */ /*assuming that the layer is opened and msLayerGetItems called*/ for(i=0; inumitems; i++) { pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_authority"); if (pszValue) pszTmpVal = msStrdup(pszValue); else pszTmpVal = msStrdup("OGC-SWE"); pszFullName = msStrdup(pszComponentBase); pszFullName = msStringConcatenate(pszFullName, pszTmpVal); free(pszTmpVal); pszFullName = msStringConcatenate(pszFullName, ":"); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_version"); if (pszValue) pszTmpVal = msStrdup(pszValue); else pszTmpVal = msStrdup("1"); pszFullName = msStringConcatenate(pszFullName, pszTmpVal); free(pszTmpVal); pszFullName = msStringConcatenate(pszFullName, ":"); snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszValue) pszTmpVal = msStrdup(pszValue); else pszTmpVal = msStrdup(lp->items[i]); pszFullName = msStringConcatenate(pszFullName, pszTmpVal); psNode = xmlNewChild(psCompNode, psNsSwe, BAD_CAST "component", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszFullName); free(pszFullName); free(pszTmpVal); j++; } pszTmpVal = msIntToString(j); xmlNewNsProp(psCompNode, NULL, BAD_CAST "dimension", BAD_CAST pszTmpVal); free(pszTmpVal); } } /************************************************************************/ /* msSOSAddGeometryNode */ /* */ /* Outout gml 2 gemptry nodes based on a shape. All logic comes */ /* from gmlWriteGeometry_GML2. Should be merged at one point if */ /* possible. */ /************************************************************************/ void msSOSAddGeometryNode(xmlNsPtr psNsGml, xmlNsPtr psNsMs, xmlNodePtr psParent, mapObj *map, layerObj *lp, shapeObj *psShape, const char *pszEpsg) { char *pszTmp = NULL; int i,j = 0; xmlNodePtr psPointNode, psNode, psLineNode, psPolygonNode; int *panOuterList = NULL, *panInnerList = NULL; if (psParent && psShape) { if (msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) { msProjectShape(&lp->projection, &map->projection, psShape); pszEpsg = msOWSGetEPSGProj(&(map->projection), &(lp->metadata), "SO", MS_TRUE); } switch(psShape->type) { case(MS_SHAPE_POINT): psNode = xmlNewChild(psParent, NULL, BAD_CAST "msGeometry", NULL); xmlSetNs(psNode, psNsMs); if (psShape->line[0].numpoints > 1) { psPointNode = xmlNewChild(psNode, NULL, BAD_CAST "MultiPoint", NULL); xmlSetNs(psPointNode, psNsGml); if (pszEpsg) xmlNewProp(psPointNode, BAD_CAST "srsName", BAD_CAST pszEpsg); } else psPointNode= psNode; /*add all points */ for(i=0; iline[0].numpoints; i++) { psNode = xmlAddChild(psPointNode, msGML3Point(psNsGml, pszEpsg, NULL, psShape->line[0].point[i].x, psShape->line[0].point[i].y)); } break; case(MS_SHAPE_LINE): psNode = xmlNewChild(psParent, NULL, BAD_CAST "msGeometry", NULL); xmlSetNs(psNode,xmlNewNs(psNode, NULL, NULL)); if (psShape->numlines > 1) { psLineNode = xmlNewChild(psNode, NULL, BAD_CAST "MultiLineString", NULL); xmlSetNs(psLineNode,xmlNewNs(psLineNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); if (pszEpsg) xmlNewProp(psLineNode, BAD_CAST "srsName", BAD_CAST pszEpsg); } else psLineNode= psNode; for(i=0; inumlines; i++) { if (psShape->numlines > 1) { psNode = xmlNewChild(psLineNode, NULL, BAD_CAST "lineStringMember", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); psNode = xmlNewChild(psNode, NULL, BAD_CAST "LineString", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } else { psNode = xmlNewChild(psLineNode, NULL, BAD_CAST "LineString", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } if (pszEpsg) xmlNewProp(psNode, BAD_CAST "srsName", BAD_CAST pszEpsg); pszTmp = NULL; for(j=0; jline[i].numpoints; j++) { pszTmp = msStringConcatenate(pszTmp, msDoubleToString(psShape->line[i].point[j].x, MS_TRUE)); pszTmp = msStringConcatenate(pszTmp, ","); pszTmp = msStringConcatenate(pszTmp, msDoubleToString(psShape->line[i].point[j].y, MS_TRUE)); pszTmp = msStringConcatenate(pszTmp, " "); } psNode = xmlNewChild(psNode, NULL, BAD_CAST "coordinates", BAD_CAST pszTmp); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); free(pszTmp); } break; case(MS_SHAPE_POLYGON): psNode = xmlNewChild(psParent, NULL, BAD_CAST "msGeometry", NULL); xmlSetNs(psNode,xmlNewNs(psNode, NULL, NULL)); if (psShape->numlines > 1) { psPolygonNode = xmlNewChild(psNode, NULL, BAD_CAST "MultiPolygon", NULL); xmlSetNs(psPolygonNode, xmlNewNs(psPolygonNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); if (pszEpsg) xmlNewProp(psPolygonNode, BAD_CAST "srsName", BAD_CAST pszEpsg); } else psPolygonNode= psNode; panOuterList = msGetOuterList(psShape); for(i=0; inumlines; i++) { if(panOuterList[i] != MS_TRUE) continue; panInnerList = msGetInnerList(psShape, i, panOuterList); if (psShape->numlines > 1) { psNode = xmlNewChild(psPolygonNode, NULL, BAD_CAST "polygonMember", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); psNode = xmlNewChild(psNode, NULL, BAD_CAST "Polygon", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } else { psNode = xmlNewChild(psPolygonNode, NULL, BAD_CAST "Polygon", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } if (pszEpsg) xmlNewProp(psNode, BAD_CAST "srsName", BAD_CAST pszEpsg); psNode = xmlNewChild(psNode, NULL, BAD_CAST "outerBoundaryIs", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); psNode = xmlNewChild(psNode, NULL, BAD_CAST "LinearRing", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); pszTmp = NULL; for(j=0; jline[i].numpoints; j++) { pszTmp = msStringConcatenate(pszTmp, msDoubleToString(psShape->line[i].point[j].x, MS_TRUE)); pszTmp = msStringConcatenate(pszTmp, ","); pszTmp = msStringConcatenate(pszTmp, msDoubleToString(psShape->line[i].point[j].y, MS_TRUE)); pszTmp = msStringConcatenate(pszTmp, " "); } psNode = xmlNewChild(psNode, NULL, BAD_CAST "coordinates", BAD_CAST pszTmp); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); free(pszTmp); if (panInnerList) free(panInnerList); } if (panOuterList) free(panOuterList); break; default: break; } } } /************************************************************************/ /* void msSOSAddDataBlockDefinition(xmlNodePtr psParent, */ /* layerObj *lp) */ /* */ /* Add a databalock used for GetObservation request. */ /************************************************************************/ void msSOSAddDataBlockDefinition(xmlNsPtr psNsSwe, xmlNodePtr psParent, layerObj *lp) { xmlNodePtr psNode, psRecordNode, psCompNode, psSubNode, psEncNode; const char *pszDefinition = NULL, *pszUom=NULL, *pszValue=NULL, *pszName=NULL; char szTmp[100]; int i=0; char *pszTokenValue = NULL; char *pszBlockValue = NULL; const char *pszBlockSep=NULL, *pszTokenSep=NULL; if (psParent) { psNode = xmlNewChild(psParent, NULL, BAD_CAST "DataBlockDefinition", NULL); xmlSetNs(psNode, psNsSwe); /* -------------------------------------------------------------------- */ /* Add components. */ /* -------------------------------------------------------------------- */ psCompNode = xmlNewChild(psNode, NULL, BAD_CAST "components", NULL); psEncNode = xmlNewChild(psNode, NULL, BAD_CAST "encoding", NULL); psRecordNode = xmlNewChild(psCompNode, NULL, BAD_CAST "DataRecord", NULL); /*always add a time field if timeitem is defined*/ if (msOWSLookupMetadata(&(lp->metadata), "SO", "timeitem")) { psNode = xmlNewChild(psRecordNode, NULL, BAD_CAST "field", NULL); xmlNewNsProp(psNode, NULL, BAD_CAST "name", BAD_CAST "time"); psNode = xmlNewChild(psNode, NULL, BAD_CAST "Time", NULL); xmlNewNsProp(psNode, NULL, BAD_CAST "definition", BAD_CAST "urn:ogc:phenomenon:time:iso8601"); } /*add all other fields*/ /*assuming that the layer is open */ for(i=0; inumitems; i++) { snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszValue) { psNode = xmlNewChild(psRecordNode, NULL, BAD_CAST "field", NULL); /* check if there is an alias/full name used */ snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszName = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (!pszName) pszName = lp->items[i]; xmlNewNsProp(psNode, NULL, BAD_CAST "name", BAD_CAST pszName); psNode = xmlNewChild(psNode, NULL, BAD_CAST "Quantity", NULL); /* get definition and uom */ snprintf(szTmp, sizeof(szTmp), "%s_definition", lp->items[i]); pszDefinition = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszDefinition == NULL) pszDefinition = "urn:ogc:object:definition"; xmlNewNsProp(psNode, NULL, BAD_CAST "definition", BAD_CAST pszDefinition); snprintf(szTmp, sizeof(szTmp), "%s_uom", lp->items[i]); pszUom = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszUom == NULL) pszUom = "urn:ogc:object:uom"; psNode = xmlNewChild(psNode, NULL, BAD_CAST "uom", NULL); xmlNewNsProp(psNode, NULL, BAD_CAST "code", BAD_CAST pszUom); } } /* -------------------------------------------------------------------- */ /* Add encoding block. */ /* -------------------------------------------------------------------- */ pszBlockSep = msOWSLookupMetadata(&(lp->map->web.metadata), "S", "encoding_blockSeparator"); pszTokenSep = msOWSLookupMetadata(&(lp->map->web.metadata), "S", "encoding_tokenSeparator"); psSubNode = xmlNewChild(psEncNode, NULL, BAD_CAST "TextBlock", NULL); if (pszTokenSep) pszTokenValue = msStringConcatenate(pszTokenValue, (char *)pszTokenSep); else pszTokenValue = msStringConcatenate(pszTokenValue, ","); xmlNewNsProp(psSubNode, NULL, BAD_CAST "tokenSeparator", BAD_CAST pszTokenValue); if (pszBlockSep) pszBlockValue = msStringConcatenate(pszBlockValue, (char *)pszBlockSep); else pszBlockValue = msStringConcatenate(pszBlockValue, "\n"); xmlNewNsProp(psSubNode, NULL, BAD_CAST "blockSeparator", BAD_CAST pszBlockValue); xmlNewNsProp(psSubNode, NULL, BAD_CAST "decimalSeparator", BAD_CAST "."); msFree(pszTokenValue); msFree(pszBlockValue); } } /************************************************************************/ /* msSOSAddMemberNode */ /* */ /* Add a memeber node corresponding to a feature. */ /* Assuming that the layer is opened and msLayerGetItems is */ /* called on it. */ /************************************************************************/ void msSOSAddMemberNode(xmlNsPtr psNsGml, xmlNsPtr psNsOm, xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNsPtr psNsMs, xmlNodePtr psParent, mapObj *map, layerObj *lp, int iFeatureId, const char *script_url, const char *opLayerName) { xmlNodePtr psObsNode, psNode, psLayerNode = NULL; const char *pszEpsg = NULL, *pszValue = NULL; int status,i,j; shapeObj sShape; char szTmp[256]; layerObj *lpfirst = NULL; const char *pszTimeField = NULL; char *pszTmp = NULL; char *pszOid = NULL; char *pszTime = NULL; char *pszValueShape = NULL; const char *pszFeatureId = NULL; if (psParent) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[iFeatureId])); if(status != MS_SUCCESS) { xmlFreeNs(psNsOm); return; } psNode = xmlNewChild(psParent, NULL, BAD_CAST "member", NULL); psObsNode = xmlNewChild(psNode, NULL, BAD_CAST "Observation", BAD_CAST pszValue); pszFeatureId = msOWSLookupMetadata(&(lp->metadata), "OSG", "featureid"); if(pszFeatureId && msLayerGetItems(lp) == MS_SUCCESS) { /* find the featureid amongst the items for this layer */ for(j=0; jnumitems; j++) { if(strcasecmp(lp->items[j], pszFeatureId) == 0) { /* found it */ break; } } if (jnumitems) { pszOid = msStringConcatenate(pszOid, "o_"); pszOid = msStringConcatenate(pszOid, sShape.values[j]); xmlNewNsProp(psObsNode, psNsGml, BAD_CAST "id", BAD_CAST pszOid); } } /* order of elements is time, location, procedure, observedproperty featureofinterest, result */ /* time*/ pszTimeField = msOWSLookupMetadata(&(lp->metadata), "SO", "timeitem"); if (pszTimeField && sShape.values) { for(i=0; inumitems; i++) { if (strcasecmp(lp->items[i], pszTimeField) == 0) { if (sShape.values[i] && strlen(sShape.values[i]) > 0) { pszTime = msStringConcatenate(pszTime, sShape.values[i]); psNode = xmlNewChild(psObsNode, psNsOm, BAD_CAST "samplingTime", NULL); xmlAddChild(psNode, msGML3TimeInstant(psNsGml, pszTime)); msFree(pszTime); } break; } } } /*TODO add location*/ /*procedure*/ /* if a procedure_item is defined, we should extract the value for the attributes. If not dump what is found in the procedure metadata bug 2054*/ if ((pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item"))) { lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (lp != lpfirst) status = msLayerOpen(lpfirst); if (status == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS) { for(i=0; inumitems; i++) { if (strcasecmp(lpfirst->items[i], pszValue) == 0) { break; } } if (i < lpfirst->numitems) { snprintf(szTmp, sizeof(szTmp), "%s", "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, szTmp); pszValueShape = msEncodeHTMLEntities(sShape.values[i]); pszTmp = msStringConcatenate(pszTmp, pszValueShape); psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "procedure", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; msFree(pszValueShape); } /*else should we generate a warning !*/ if (lp != lpfirst) msLayerClose(lpfirst); } } else if ((pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "procedure"))) { if (! msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item")) xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_procedure_item\" missing for sos:procedure. If you have more than 1 procedures, sos:procedure will output them incorrectly.")); snprintf(szTmp, sizeof(szTmp), "%s", "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, szTmp); pszTmp = msStringConcatenate(pszTmp, (char *)pszValue); psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "procedure", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; } /*observed property*/ pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id"); if (pszValue) msSOSAddPropertyNode(psNsSwe, psNsXLink, psObsNode, lp, psNsGml, pszOid); msFree(pszOid); pszOid = NULL; /*TODO add featureofinterest*/ pszTmp = msStringConcatenate(pszTmp, (char *) script_url); pszTmp = msStringConcatenate(pszTmp, "service=WFS&version=1.1.0&request=DescribeFeatureType&typename="); pszTmp = msStringConcatenate(pszTmp, (char *) opLayerName); psNode = xmlNewChild(psObsNode, psNsOm, BAD_CAST "featureOfInterest", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp=NULL; /* add result : gml:featureMember of all selected elements */ psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "result", NULL); /*TODO should we add soemwhere the units of the value : 29.00 */ #ifdef USE_PROJ if(msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&lp->projection, &lp->projection, &sShape); #endif psNode = xmlNewChild(psNode, psNsGml, BAD_CAST "featureMember", NULL); /* xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); */ /*TODO : add namespaces like wfs " ms and a url to mapserve ? */ psLayerNode = xmlNewChild(psNode, psNsMs, BAD_CAST lp->name, NULL); /* fetch gml:id */ pszFeatureId = msOWSLookupMetadata(&(lp->metadata), "OSG", "featureid"); if(pszFeatureId && msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) xmlSetNs(psLayerNode,psNsMs); /*bbox*/ #ifdef USE_PROJ pszEpsg = msOWSGetEPSGProj(&(map->projection), &(lp->metadata), "SO", MS_TRUE); if (!pszEpsg) pszEpsg = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "SO", MS_TRUE); if (msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) msProjectRect(&lp->projection, &map->projection, &sShape.bounds); #endif psNode = xmlAddChild(psLayerNode, msGML3BoundedBy(psNsGml, sShape.bounds.minx, sShape.bounds.miny, sShape.bounds.maxx, sShape.bounds.maxy, pszEpsg)); /*geometry*/ msSOSAddGeometryNode(psNsGml, psNsMs, psLayerNode, map, lp, &sShape, pszEpsg); /*attributes */ /* TODO only output attributes where there is a sos_%s_alias (to be discussed)*/ /* the first layer is the one that has to have all the metadata defined */ lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (lpfirst && msLayerOpen(lpfirst) == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS) { for(i=0; inumitems; i++) { snprintf(szTmp, sizeof(szTmp), "%s_alias", lpfirst->items[i]); pszValue = msOWSLookupMetadata(&(lpfirst->metadata), "S", szTmp); if (pszValue) { for (j=0; jnumitems; j++) { if (strcasecmp(lpfirst->items[i], lpfirst->items[j]) == 0) { /*if there is an alias used, use it to output the parameter name : eg "sos_AMMON_DIS_alias" "Amonia" */ snprintf(szTmp, sizeof(szTmp), "%s_alias", lpfirst->items[i]); pszValue = msOWSLookupMetadata(&(lpfirst->metadata), "S", szTmp); pszValueShape = msEncodeHTMLEntities(sShape.values[j]); if (pszValue) { pszTmp = msEncodeHTMLEntities(pszValue); psNode = xmlNewChild(psLayerNode, psNsMs, BAD_CAST pszValue, BAD_CAST pszValueShape); free(pszTmp); } else { pszTmp = msEncodeHTMLEntities(lpfirst->items[i]); psNode = xmlNewChild(psLayerNode, psNsMs, BAD_CAST lpfirst->items[i], BAD_CAST pszValueShape); free(pszTmp); } free(pszValueShape); xmlSetNs(psNode,psNsMs); break; } } } } if (lp->index != lpfirst->index) msLayerClose(lpfirst); } } msFreeShape(&sShape); } /************************************************************************/ /* msSOSReturnMemberResult */ /* */ /* Add a result string to the result node (used for */ /* GetObservation using "observation" as the response output. */ /* Assuming here that the layer is already opened. */ /************************************************************************/ char* msSOSReturnMemberResult(layerObj *lp, int iFeatureId, char **ppszProcedure) { char *pszFinalValue = NULL; shapeObj sShape; int i, j, status; layerObj *lpfirst; const char *pszTimeField = NULL, *pszValue=NULL, *pszProcedureField=NULL; char *pszValueShape = NULL; char szTmp[100]; const char *pszSep=NULL; msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[iFeatureId])); if(status != MS_SUCCESS) return NULL; pszTimeField = msOWSLookupMetadata(&(lp->metadata), "SO", "timeitem"); if (pszTimeField && sShape.values) { for(i=0; inumitems; i++) { if (strcasecmp(lp->items[i], pszTimeField) == 0) { pszFinalValue = msStringConcatenate(pszFinalValue, sShape.values[i]); break; } } } if (ppszProcedure) { pszProcedureField = msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item"); for(i=0; inumitems; i++) { if (strcasecmp(lp->items[i], pszProcedureField) == 0) { (*ppszProcedure) = msStrdup( sShape.values[i]); break; } } } /* the first layer is the one that has to have all the metadata defined */ lpfirst = msSOSGetFirstLayerForOffering(lp->map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (lp == lpfirst || (lpfirst && msLayerOpen(lpfirst) == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS)) { pszSep = msOWSLookupMetadata(&(lp->map->web.metadata), "S", "encoding_tokenSeparator"); for(i=0; inumitems; i++) { snprintf(szTmp, sizeof(szTmp), "%s_alias", lpfirst->items[i]); pszValue = msOWSLookupMetadata(&(lpfirst->metadata), "S", szTmp); if (pszValue) { for (j=0; jnumitems; j++) { if (strcasecmp(lpfirst->items[i], lpfirst->items[j]) == 0) { pszValueShape = msEncodeHTMLEntities(sShape.values[j]); if (pszFinalValue) { if (pszSep) pszFinalValue = msStringConcatenate(pszFinalValue, (char *)pszSep); else pszFinalValue = msStringConcatenate(pszFinalValue, ","); } pszFinalValue = msStringConcatenate(pszFinalValue, pszValueShape); msFree(pszValueShape); } } } } } msFreeShape(&sShape); return pszFinalValue; } /************************************************************************/ /* msSOSAddMemberNodeObservation */ /* */ /* Add a member node used for getObservation request using */ /* Observation as the result format. */ /************************************************************************/ xmlNodePtr msSOSAddMemberNodeObservation(xmlNsPtr psNsGml, xmlNsPtr psNsSos, xmlNsPtr psNsOm, xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNodePtr psParent, mapObj *map, layerObj *lp, const char *pszProcedure) { char *pszTmp = NULL; xmlNodePtr psNode=NULL, psObsNode=NULL, psMemberNode=NULL; layerObj *lpfirst; const char *value = NULL; /*always featch the first layer that has the same offering id and observered propery. This allows to only define all the attributes and components on the first layer if the user wants to present several mapserver layers as the same offering.*/ lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (psParent) { psMemberNode = xmlNewChild(psParent, NULL, BAD_CAST "member", NULL); psObsNode = xmlNewChild(psMemberNode, NULL, BAD_CAST "Observation", NULL); /*time*/ /* ??TODO : sampling time is a manadatory element but uses a non mandatory metadata sos_offering_timeextent */ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_timeextent"); if (value) { char **tokens; int n; char *pszEndTime = NULL; tokens = msStringSplit(value, '/', &n); if (tokens==NULL || (n != 1 && n!=2)) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_timeextent.", "msSOSGetObservation()"); msSOSException(map, "sos_offering_timeextent", "InvalidParameterValue"); return NULL; } if (n == 2) /* end time is empty. It is going to be set as "now*/ pszEndTime = tokens[1]; psNode = xmlAddChild(psObsNode, msSOSAddTimeNode(psNsOm, psNsGml, tokens[0], pszEndTime)); msFreeCharArray(tokens, n); } /* procedure */ if (pszProcedure) { /*this should always be true since procedure is a manadtory element*/ if (! msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item") && msOWSLookupMetadata(&(lp->metadata), "S", "procedure")) xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_procedure_item\" missing for sos:procedure. If you have more than 1 procedures, sos:procedure will output them incorrectly.")); pszTmp = msStringConcatenate(pszTmp, "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, (char *)pszProcedure); psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "procedure", NULL); /* xmlNewNsProp(psNode, xmlNewNs(NULL, BAD_CAST "http://www.w3.org/1999/xlink", BAD_CAST "xlink"), BAD_CAST "href", BAD_CAST pszTmp); */ xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; } /*observed propery and components*/ if (lp != lpfirst && msLayerOpen(lpfirst) == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS) { msSOSAddPropertyNode(psNsSwe, psNsXLink, psObsNode, lpfirst, psNsGml, NULL); msLayerClose(lpfirst); } else msSOSAddPropertyNode(psNsSwe, psNsXLink, psObsNode, lpfirst, psNsGml, NULL); /* result definition*/ psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "resultDefinition", NULL); msSOSAddDataBlockDefinition(psNsSwe, psNode, lpfirst); } return psObsNode; } /************************************************************************/ /* msSOSParseTimeGML */ /* */ /* Utility function to convert a gml time value to a */ /* string. Supported gml times are : */ /* */ /* - */ /* 2005-09-01T11:54:32 */ /* 2005-09-02T14:54:32 */ /* */ /* This will be converted to startime/endtime */ /* */ /* - */ /* 2003-02-13T12:28-08:00*/ /* */ /* This will retunr the timevalue as a string. */ /* */ /* The caller of the function should free the return value. */ /************************************************************************/ char *msSOSParseTimeGML(char *pszGmlTime) { char *pszReturn = NULL, *pszBegin = NULL, *pszEnd = NULL; CPLXMLNode *psRoot=NULL, *psChild=NULL; CPLXMLNode *psTime=NULL, *psBegin=NULL, *psEnd=NULL; struct tm tm_struct; if (pszGmlTime) { psRoot = CPLParseXMLString(pszGmlTime); if(!psRoot) return NULL; CPLStripXMLNamespace(psRoot, "gml", 1); if (psRoot->eType == CXT_Element && (EQUAL(psRoot->pszValue,"TimePeriod") || EQUAL(psRoot->pszValue,"TimeInstant"))) { if (EQUAL(psRoot->pszValue,"TimeInstant")) { psChild = psRoot->psChild; if (psChild && EQUAL(psChild->pszValue,"timePosition")) { psTime = psChild->psNext; if (psTime && psTime->pszValue && psTime->eType == CXT_Text) { if (msParseTime(psTime->pszValue, &tm_struct) == MS_TRUE) pszReturn = msStrdup(psTime->pszValue); } } } else { psBegin = psRoot->psChild; if (psBegin) psEnd = psBegin->psNext; if (psBegin && EQUAL(psBegin->pszValue, "beginPosition") && psEnd && EQUAL(psEnd->pszValue, "endPosition")) { if (psBegin->psChild && psBegin->psChild->pszValue && psBegin->psChild->eType == CXT_Text) pszBegin = msStrdup( psBegin->psChild->pszValue); if (psEnd->psChild && psEnd->psChild->pszValue && psEnd->psChild->eType == CXT_Text) pszEnd = msStrdup(psEnd->psChild->pszValue); if (pszBegin && pszEnd) { if (msParseTime(pszBegin, &tm_struct) == MS_TRUE && msParseTime(pszEnd, &tm_struct) == MS_TRUE) { pszReturn = msStrdup(pszBegin); pszReturn = msStringConcatenate(pszReturn, "/"); pszReturn = msStringConcatenate(pszReturn, pszEnd); } } msFree(pszBegin); msFree(pszEnd); } } } } CPLDestroyXMLNode(psRoot); return pszReturn; } /************************************************************************/ /* msSOSGetCapabilities */ /* */ /* getCapabilities request handler. */ /************************************************************************/ int msSOSGetCapabilities(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *req, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode, psMainNode, psNode; xmlNodePtr psOfferingNode; char *schemalocation = NULL; char *xsi_schemaLocation = NULL; char *script_url=NULL; const char *updatesequence=NULL; const char *encoding; int i,j,k; layerObj *lp = NULL, *lpTmp = NULL; const char *value = NULL; char *pszTmp = NULL; char *pszProcedure = NULL; char szTmp[256]; /* array of offering */ char **papsOfferings = NULL; int nOfferings =0, nCurrentOff = -1; int nProperties = 0; char **papszProperties = NULL; int iItemPosition = -1; shapeObj sShape; int status; /* for each layer it indicates the indice to be used in papsOfferings (to associate it with the offering) */ int *panOfferingLayers = NULL; char **papsProcedures = NULL; int nDistinctProcedures =0; xmlNsPtr psNsGml = NULL; xmlNsPtr psNsSos = NULL; xmlNsPtr psNsOws = NULL; xmlNsPtr psNsOgc = NULL; xmlNsPtr psNsXLink = NULL; xmlNsPtr psNsSwe = NULL; xmlChar *buffer = NULL; int size = 0; msIOContext *context = NULL; int ows_version = OWS_1_1_0; int sosSupportedVersions[] = {OWS_1_0_0}; int sosNumSupportedVersions = 1; /* acceptversions: do OWS Common style of version negotiation */ if (sosparams->pszAcceptVersions) { char **tokens; int i, j, k=-1; tokens = msStringSplit(sosparams->pszAcceptVersions, ',', &j); for (i=0; ipszAcceptVersions, pszSOSVersion); return msSOSException(map, "acceptversions", "VersionNegotiationFailed"); } } /* updateSequence */ updatesequence = msOWSLookupMetadata(&(map->web.metadata), "SO", "updatesequence"); encoding = msOWSLookupMetadata(&(map->web.metadata), "SO", "encoding"); if (sosparams->pszUpdateSequence != NULL) { i = msOWSNegotiateUpdateSequence(sosparams->pszUpdateSequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_SOSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msSOSGetCapabilities()", sosparams->pszUpdateSequence, updatesequence); return msSOSException(map, "updatesequence", "CurrentUpdateSequence"); } if (i > 0) { /* invalid */ msSetError(MS_SOSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msSOSGetCapabilities()", sosparams->pszUpdateSequence, updatesequence); return msSOSException(map, "updatesequence", "InvalidUpdateSequence"); } } psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "Capabilities"); xmlDocSetRootElement(psDoc, psRootNode); psNsGml = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"); psNsSos = xmlNewNs(NULL, BAD_CAST pszSOSNamespaceUri, BAD_CAST pszSOSNamespacePrefix); psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX); psNsSwe = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe"); /* name spaces */ xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/om/1.0", BAD_CAST "om")); psNsOws = xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); xmlSetNs(psRootNode, psNsOws ); xmlSetNs(psRootNode,xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe")); psNsXLink = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlSetNs(psRootNode, psNsXLink ); xmlSetNs(psRootNode,xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST pszSOSNamespaceUri, BAD_CAST pszSOSNamespacePrefix)); /*version fixed for now*/ xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST pszSOSVersion); value = msOWSLookupMetadata(&(map->web.metadata), "SO", "updatesequence"); if (value) xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST value); /*schema fixed*/ schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); xsi_schemaLocation = msStrdup(pszSOSNamespaceUri); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/sos/"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)pszSOSVersion); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/sosGetCapabilities.xsd"); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); xmlAddChild(psRootNode, xmlNewComment(BAD_CAST msGetVersion())); /*service identification*/ xmlAddChild(psRootNode, msOWSCommonServiceIdentification(psNsOws, map, "SOS", pszSOSVersion, "SO")); /*service provider*/ xmlAddChild(psRootNode, msOWSCommonServiceProvider(psNsOws, psNsXLink, map, "SO")); /*operation metadata */ if ((script_url=msOWSGetOnlineResource(map, "SO", "onlineresource", req)) == NULL) return msSOSException(map, "NoApplicableCode", "NoApplicableCode"); psMainNode = xmlAddChild(psRootNode, msOWSCommonOperationsMetadata(psNsOws)); psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetCapabilities", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); if (msOWSRequestIsEnabled(map, NULL, "S", "DescribeSensor", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeSensor", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "sensorid", "urn:ogc:object:procedure")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "outputFormat", (char *)pszSOSDescribeSensorMimeType)); } if (msOWSRequestIsEnabled(map, NULL, "S", "DescribeObservationType", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeObservationType", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "observedproperty", "urn:ogc:object:observedproperty")); } if (msOWSRequestIsEnabled(map, NULL, "S", "GetObservation", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetObservation", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "offering", "urn:ogc:object:offering")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "observedproperty", "urn:ogc:object:observedproperty")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "eventtime", "sos:time")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "procedure", "urn:ogc:object:sensor")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "featureofinterest", "gml:location")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "result", "ogc:Filter")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "responseFormat", (char *)pszSOSGetObservationMimeType)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "resultModel", "Observation,Measurement")); } value = msOWSLookupMetadata(&(map->web.metadata), "SO", "maxfeatures"); if (value) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Constraint", "DefaultMaxFeatures", (char *)value)); } /* */ xmlAddChild(psRootNode, FLTGetCapabilities(psNsSos, psNsOgc, MS_TRUE)); /*Offerings */ psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Contents", NULL); psMainNode = xmlNewChild(psNode, NULL, BAD_CAST "ObservationOfferingList", NULL); /*go through the layers and check for metadata sos_offering_id. One or more layers could have the same offering id. In that case they are adverized as the same offering. The first layer that has*/ if (map->numlayers) { papsOfferings = (char **)malloc(sizeof(char *)*map->numlayers); panOfferingLayers = (int *)malloc(sizeof(int)*map->numlayers); for (i=0; inumlayers; i++) panOfferingLayers[i] = -1; for (i=0; inumlayers; i++) { lp = (GET_LAYER(map, i)); if (lp->status == MS_DELETE) continue; value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"); if (value && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers))) { nCurrentOff = -1; for (j=0; j= 0) /* existing offering */ panOfferingLayers[i] = nCurrentOff; else { /*new offering */ papsOfferings[nOfferings] = msStrdup(value); panOfferingLayers[i] = nOfferings; nOfferings++; } } } if (nOfferings > 0) { for (i=0; inumlayers; j++) { if (panOfferingLayers[j] == i) /*first layer of the offering */ break; } /*description*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_description"); if (value) psNode = xmlNewChild(psOfferingNode, psNsGml, BAD_CAST "description", BAD_CAST value); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_description\" missing for gml:description")); /*name*/ lp = (GET_LAYER(map, j)); /*first layer*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_name"); if (value) psNode = xmlNewChild(psOfferingNode, psNsGml, BAD_CAST "name", BAD_CAST value); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_name\" missing for gml:name")); /* srsName */ value = msOWSLookupMetadata(&(map->web.metadata), "SO", "srs"); if (value) msLibXml2GenerateList(psOfferingNode, psNsGml, "srsName", value, ' '); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Required metadata \"sos_srs\" missing for gml:srsName")); /*bounding box */ /*TODO : if sos_offering_extent does not exist compute extents Check also what happen if epsg not present */ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_extent"); if (value) { char **tokens; int n; tokens = msStringSplit(value, ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_extent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_extent", "InvalidParameterValue"); } value = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "SO", MS_TRUE); if (value) psNode = xmlAddChild(psOfferingNode, msGML3BoundedBy(psNsGml, atof(tokens[0]), atof(tokens[1]), atof(tokens[2]), atof(tokens[3]), value)); msFreeCharArray(tokens, n); } /* intended application */ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_intendedapplication"); if (value) psNode = xmlNewChild(psOfferingNode, psNsSos, BAD_CAST "intendedApplication", BAD_CAST value); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_intendedapplication\" missing for sos:intendedApplication")); /*time*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_timeextent"); if (value) { char **tokens; int n; char *pszEndTime = NULL; tokens = msStringSplit(value, '/', &n); if (tokens==NULL || (n != 1 && n!=2)) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_timeextent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_timeextent", "InvalidParameterValue"); } if (n == 2) /* end time is empty. It is going to be set as "now*/ pszEndTime = tokens[1]; psNode = xmlAddChild(psOfferingNode, msSOSAddTimeNode(psNsSos, psNsGml, tokens[0], pszEndTime)); msFreeCharArray(tokens, n); } /*procedure : output all procedure links for the offering */ for (j=0; jnumlayers; j++) { if (panOfferingLayers[j] == i) { value = msOWSLookupMetadata(&(GET_LAYER(map, j)->metadata), "S", "procedure"); if (value && strlen(value) > 0) { /*value could be a list of procedure*/ char **tokens; int n = 0; tokens = msStringSplit(value, ' ', &n); for (k=0; kmetadata), "S", "procedure_item"))) { /* if a procedure_item is used, it means that the procedure (or sensor) need to be extracted from the data. Thus we need to query the layer and get the values from each feature */ lpTmp = GET_LAYER(map,j); if (lpTmp->template == NULL) lpTmp->template = msStrdup("ttt"); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = j; map->query.rect = map->extent; msQueryByRect(map); /*check if the attribute specified in the procedure_item is available on the layer*/ iItemPosition = -1; if (msLayerGetItems(lpTmp) == MS_SUCCESS && lpTmp->resultcache && lpTmp->resultcache->numresults > 0) { for(k=0; knumitems; k++) { if (strcasecmp(lpTmp->items[k], value) == 0) { iItemPosition = k; break; } } if (iItemPosition == -1) { msSetError(MS_SOSERR, "procedure_item %s could not be found on the layer %s", "msSOSGetCapabilities()", value, lpTmp->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } /*for each selected feature, grab the value of the prodedire_item*/ /* do not duplicate sensor ids if they are the same */ /*keep list of distinct procedures*/ papsProcedures = (char **)malloc(sizeof(char *) * lpTmp->resultcache->numresults); nDistinctProcedures = 0; for(k=0; kresultcache->numresults; k++) papsProcedures[k] = NULL; for(k=0; kresultcache->numresults; k++) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lpTmp->resultcache->results[k])); if(status != MS_SUCCESS) continue; if (sShape.values[iItemPosition]) { pszProcedure = msStringConcatenate(pszProcedure, sShape.values[iItemPosition]); if (!_IsInList(papsProcedures, nDistinctProcedures, pszProcedure)) { papsProcedures[nDistinctProcedures] = msStrdup(pszProcedure); nDistinctProcedures++; snprintf(szTmp, sizeof(szTmp), "%s", "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, szTmp); pszTmp = msStringConcatenate(pszTmp, pszProcedure); psNode = xmlNewChild(psOfferingNode, NULL, BAD_CAST "procedure", NULL); xmlNewNsProp(psNode, xmlNewNs(NULL, BAD_CAST "http://www.w3.org/1999/xlink", BAD_CAST "xlink"), BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; } msFree(pszProcedure); pszProcedure = NULL; } } for(k=0; kresultcache->numresults; k++) if (papsProcedures[k] != NULL) msFree(papsProcedures[k]); msFree(papsProcedures); } else { msSetError(MS_SOSERR, "Invalid procedure %s", "msSOSGetCapabilities()", value); return msSOSException(map, "procedure", "InvalidParameterValue"); } } else { msSetError(MS_SOSERR, "Mandatory metadata procedure_item could not be found on the layer %s", "msSOSGetCapabilities()", GET_LAYER(map,j)->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } } } /*observed property */ /* observed property are equivalent to layers. We can group sevaral layers using the same sos_observedproperty_id. The components are the attributes. Components are exposed using the metadata sos_%s_aliasl */ nProperties = 0; papszProperties = (char **)malloc(sizeof(char *)*map->numlayers); for (j=0; jnumlayers; j++) { if (panOfferingLayers[j] == i) { if ((value = msOWSLookupMetadata(&(GET_LAYER(map, j)->metadata), "S", "observedproperty_id"))) { for (k=0; k 0) { for (i=0; iweb.metadata), "SO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); */ /*xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);*/ /* xmlDocDump crashs withe the prebuild windows binaries distibutes at the libxml site???. It works with locally build binaries*/ context = msIO_getHandler(stdout); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_contextWrite(context, buffer, size); xmlFree(buffer); /*free buffer and the document */ /*xmlFree(buffer);*/ xmlFreeDoc(psDoc); xmlFreeNs(psNsGml); xmlFreeNs(psNsSos); xmlFreeNs(psNsOgc); xmlFreeNs(psNsSwe); free(xsi_schemaLocation); free(schemalocation); msFree(script_url); /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser(); return(MS_SUCCESS); /* nSize = sizeof(workbuffer); nSize = nSize-1;*/ /* the last character for the '\0' */ /* if (size > nSize) { iIndice = 0; while ((iIndice + nSize) <= size) { snprintf(workbuffer, (sizeof(workbuffer)-1), "%s", buffer+iIndice ); workbuffer[sizeof(workbuffer)-1] = '\0'; msIO_printf("%s", workbuffer); iIndice +=nSize; } if (iIndice < size) { sprintf(workbuffer, "%s", buffer+iIndice ); msIO_printf("%s", workbuffer); } } else { msIO_printf("%s", buffer); } */ } /************************************************************************/ /* msSOSGetObservation */ /* */ /* GetObservation request handler */ /************************************************************************/ int msSOSGetObservation(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *req, owsRequestObj *ows_request) { char *schemalocation = NULL; char *xsi_schemaLocation = NULL; const char *pszTmp = NULL, *pszTmp2 = NULL; const char *user_namespace_uri = "http://mapserver.gis.umn.edu/mapserver"; const char *user_namespace_prefix = "ms"; char *script_url=NULL; int i, j, k, bLayerFound = 0; layerObj *lp = NULL, *lpfirst = NULL; const char *pszTimeExtent=NULL, *pszTimeField=NULL, *pszValue=NULL; FilterEncodingNode *psFilterNode = NULL; rectObj sBbox; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode, psNode; char **tokens=NULL, **tokens1; int n=0, n1=0; xmlNsPtr psNsGml = NULL; xmlNsPtr psNsOm = NULL; xmlNsPtr psNsSwe = NULL; xmlNsPtr psNsXLink = NULL; xmlNsPtr psNsSos = NULL; xmlNsPtr psNsMs = NULL; const char *opLayerName = NULL; char *pszBuffer = NULL; const char *pszProcedureItem = NULL; int bSpatialDB = 0; xmlChar *buffer = NULL; int size = 0; msIOContext *context = NULL; xmlNodePtr psObservationNode = NULL, psResultNode=NULL; const char *pszProcedure = NULL; const char *pszBlockSep=NULL; const char *encoding; char *pszResult=NULL; int nDiffrentProc = 0; SOSProcedureNode *paDiffrentProc = NULL; char *pszProcedureValue = NULL; int iItemPosition, status; shapeObj sShape; char* pszEscapedStr = NULL; sBbox = map->extent; /* establish local namespace */ pszTmp = msOWSLookupMetadata(&(map->web.metadata), "SFO", "namespace_uri"); encoding = msOWSLookupMetadata(&(map->web.metadata), "SO", "encoding"); if(pszTmp) user_namespace_uri = pszTmp; pszTmp = msOWSLookupMetadata(&(map->web.metadata), "SFO", "namespace_prefix"); if(pszTmp) user_namespace_prefix = pszTmp; /* validates mandatory request elements */ if (!sosparams->pszOffering) { msSetError(MS_SOSERR, "Missing OFFERING parameter.", "msSOSGetObservation()"); return msSOSException(map, "offering", "MissingParameterValue"); } if (!sosparams->pszObservedProperty) { msSetError(MS_SOSERR, "Missing OBSERVEDPROPERTY parameter.", "msSOSGetObservation()"); return msSOSException(map, "observedproperty", "MissingParameterValue"); } if (!sosparams->pszResponseFormat) { msSetError(MS_SOSERR, "Missing RESPONSEFORMAT parameter.", "msSOSGetObservation()"); return msSOSException(map, "responseformat", "MissingParameterValue"); } if (strcasecmp(sosparams->pszResponseFormat, pszSOSGetObservationMimeType) != 0) { msSetError(MS_SOSERR, "Invalid RESPONSEFORMAT parameter %s. Allowable values are: %s", "msSOSGetObservation()", sosparams->pszResponseFormat, pszSOSGetObservationMimeType); return msSOSException(map, "responseformat", "InvalidParameterValue"); } if (sosparams->pszResponseMode && strcasecmp(sosparams->pszResponseMode, "inline") != 0) { msSetError(MS_SOSERR, "Invalid RESPONSEMODE parameter %s. Allowable values are: \"inline\"", "msSOSGetObservation()", sosparams->pszResponseMode); return msSOSException(map, "responsemode", "InvalidParameterValue"); } /*validate if offering exists*/ for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); if (pszTmp && (strcasecmp(pszTmp, sosparams->pszOffering) == 0) && (msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers))) break; } if (i==map->numlayers) { msSetError(MS_SOSERR, "Offering %s not found. A layer might be disabled for \ this request. Check sos/ows_enable_request settings.", "msSOSGetObservation()", sosparams->pszOffering); return msSOSException(map, "offering", "InvalidParameterValue"); } /*validate if observed property exist*/ /* Allow more the 1 oberved property comma separated (specs is unclear on it). If we do it, we need to see if other parameters like result (filter encoding) should be given for each property too) */ bLayerFound = 0; tokens = msStringSplit(sosparams->pszObservedProperty, ',', &n); for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); pszTmp2 = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "observedproperty_id"); GET_LAYER(map, i)->status = MS_OFF; if (pszTmp && pszTmp2) { if (strcasecmp(pszTmp, sosparams->pszOffering) == 0) { if (tokens && n > 0) { for (j=0; jstatus = MS_ON; /* opLayerName = msStrdup(GET_LAYER(map, i)->name); */ opLayerName = GET_LAYER(map, i)->name; /* Force setting a template to enable query. */ if (!GET_LAYER(map, i)->template) GET_LAYER(map, i)->template = msStrdup("ttt.html"); bLayerFound = 1; break; } } } } } } if (tokens && n > 0) msFreeCharArray(tokens, n); if (bLayerFound == 0) { msSetError(MS_SOSERR, "ObservedProperty %s not found.", "msSOSGetObservation()", sosparams->pszObservedProperty); return msSOSException(map, "observedproperty", "InvalidParameterValue"); } /* apply procedure : could be a comma separated list. set status to on those layers that have the sos_procedure metadata equals to this parameter. Note that the layer should already have it's status at ON by the offering,observedproperty filter done above */ if (sosparams->pszProcedure) { bLayerFound = 0; tokens = msStringSplit(sosparams->pszProcedure, ',', &n); if (tokens && n > 0) { for (i=0; inumlayers; i++) { if(GET_LAYER(map, i)->status == MS_ON) { pszValue = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "procedure"); if (pszValue) { /* the procedure metadata can be a list "sensor1 sensor2..."*/ tokens1 = msStringSplit(pszValue, ' ', &n1); for (j=0; jstatus = MS_OFF; if (tokens1) msFreeCharArray(tokens1, n1); if (bLayerFound == 0) { msSetError(MS_SOSERR, "Procedure %s not found.", "msSOSGetObservation()", sosparams->pszProcedure); msFreeCharArray(tokens, n); return msSOSException(map, "procedure", "InvalidParameterValue"); } } /* if there is a procedure_item defined on the layer, we will */ /* use it to set the filter parameter of the layer */ if ((GET_LAYER(map, i)->status == MS_ON) && (pszProcedureItem = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "procedure_item"))) { lp = GET_LAYER(map, i); /* HACK BEGIN */ if (msOWSLookupMetadata(&(GET_LAYER(map,i)->metadata), "S", "procedure") == NULL) { /* if sos_procedure_item is used, and sos_procedure is not, it means that */ /* the procedure or sensor) need to be extracted from the data. Thus we */ /* need to query the layer and get the values from each feature */ if (lp->template == NULL) lp->template = msStrdup("ttt"); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = i; map->query.rect = map->extent; msQueryByRect(map); /*check if the attribute specified in the procedure_item is available */ /*on the layer*/ iItemPosition = -1; if (msLayerGetItems(lp) == MS_SUCCESS && lp->resultcache && lp->resultcache->numresults > 0) { for(k=0; knumitems; k++) { if (strcasecmp(lp->items[k], pszProcedureItem) == 0) { iItemPosition = k; break; } } if (iItemPosition == -1) { msSetError(MS_SOSERR, "sos_procedure_item %s could not be found on the layer %s", "msSOSGetCapabilities()", pszProcedureItem, lp->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } /*for each selected feature, grab the value of the procedure_item*/ bLayerFound = 0; for(k=0; kresultcache->numresults; k++) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[k])); if(status != MS_SUCCESS) continue; if (sShape.values[iItemPosition]) { tokens = msStringSplit(sosparams->pszProcedure, ',', &n); for (j=0; jpszProcedure); return msSOSException(map, "procedure", "InvalidParameterValue"); } } } /* HACK END */ pszBuffer = NULL; if (&lp->filter) { if (lp->filter.string && strlen(lp->filter.string) > 0) freeExpression(&lp->filter); } /*The filter should reflect the underlying db*/ /*for ogr add a where clause */ bSpatialDB = 0; if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_SDE || lp->connectiontype == MS_OGR) bSpatialDB = 1; if (bSpatialDB) { if (lp->connectiontype != MS_OGR) pszBuffer = msStringConcatenate(pszBuffer, "("); else pszBuffer = msStringConcatenate(pszBuffer, "WHERE "); } else pszBuffer = msStringConcatenate(pszBuffer, "("); for (j=0; j 0) pszBuffer = msStringConcatenate(pszBuffer, " OR "); pszBuffer = msStringConcatenate(pszBuffer, "("); if (!bSpatialDB) { pszBuffer = msStringConcatenate(pszBuffer, "'["); pszBuffer = msStringConcatenate(pszBuffer, (char *)pszProcedureItem); } else { pszEscapedStr = msLayerEscapePropertyName(lp, (char *)pszProcedureItem); pszBuffer = msStringConcatenate(pszBuffer, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr = NULL; } if (!bSpatialDB) pszBuffer = msStringConcatenate(pszBuffer, "]'"); pszBuffer = msStringConcatenate(pszBuffer, " = '"); pszEscapedStr = msLayerEscapeSQLParam(lp, tokens[j]); pszBuffer = msStringConcatenate(pszBuffer, pszEscapedStr); msFree(pszEscapedStr); pszBuffer = msStringConcatenate(pszBuffer, "')"); } if (!bSpatialDB || lp->connectiontype != MS_OGR) pszBuffer = msStringConcatenate(pszBuffer, ")"); loadExpressionString(&lp->filter, pszBuffer); if (pszBuffer) msFree(pszBuffer); } } } msFreeCharArray(tokens, n); } } /* -------------------------------------------------------------------- */ /* supports 2 types of gml:Time : TimePeriod and TimeInstant : */ /* - */ /* 2005-09-01T11:54:32 */ /* 2005-09-02T14:54:32 */ /* */ /* */ /* - */ /* 2003-02-13T12:28-08:00*/ /* */ /* */ /* The user can specify mutilple times separated by commas. */ /* */ /* The gml will be parsed and trasformed into a sting tah */ /* looks like timestart/timeend,... */ /* -------------------------------------------------------------------- */ /*apply time filter if available */ if (sosparams->pszEventTime) { char **apszTimes = NULL; int numtimes = 0; char *pszTimeString = NULL, *pszTmp = NULL; /* Because SOS has specific TemporalOperator which extends FES 1.1, the time filter */ /* passed is different than what mapogcfilter (per 1.0.0) supports. */ /* */ /* Because, in XML POST mode, we traverse directly to gml:TimePeriod|gml:TimeInstant */ /* this is passed directly to mapogcfilter. */ /* for GET requests, we strip the parent element before passing */ pszTmp = msStrdup(sosparams->pszEventTime); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); apszTimes = msStringSplit (pszTmp, ',', &numtimes); msFree(pszTmp); if (numtimes >=1) { for (i=0; ipszEventTime); return msSOSException(map, "eventtime", "InvalidParameterValue"); } for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->status == MS_ON) { /* the sos_offering_timeextent should be used for time validation*/ /*TODO : too documented ?*/ lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"), NULL); if (lpfirst) pszTimeExtent = msOWSLookupMetadata(&lpfirst->metadata, "S", "offering_timeextent"); pszTimeField = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "SO", "timeitem"); if (pszTimeField) { /*validate only if time extent is set.*/ if (pszTimeExtent) { if (msValidateTimeValue(pszTimeString, pszTimeExtent) == MS_TRUE) msLayerSetTimeFilter((GET_LAYER(map, i)), pszTimeString, pszTimeField); else { /*we should turn the layer off since the eventTime is not in the time extent*/ GET_LAYER(map, i)->status = MS_OFF; } } else msLayerSetTimeFilter((GET_LAYER(map, i)), pszTimeString, pszTimeField); } } } if (pszTimeString) msFree(pszTimeString); } /*bbox*/ /* this is a gml feature -66 43 -62 45 */ if (sosparams->pszFeatureOfInterest) { int bValid = 0; CPLXMLNode *psRoot=NULL; char *pszSRS = NULL; psRoot = CPLParseXMLString(sosparams->pszFeatureOfInterest); if(!psRoot) { msSetError(MS_SOSERR, "Invalid gml:Envelope value given for featureOfInterest.", "msSOSGetObservation()"); return msSOSException(map, "featureofinterest", "InvalidParameterValue"); } CPLStripXMLNamespace(psRoot, "gml", 1); bValid = FLTParseGMLEnvelope(psRoot, &sBbox, &pszSRS); /* TODO we should reproject the bbox to the map projection if there is an srs defined */ if (!bValid) { msSetError(MS_SOSERR, "Invalid gml:Envelope value given for featureOfInterest %s.", "msSOSGetObservation()", sosparams->pszEventTime); return msSOSException(map, "featureofinterest", "InvalidParameterValue"); } map->extent.minx = sBbox.minx; map->extent.miny = sBbox.miny; map->extent.maxx = sBbox.maxx; map->extent.maxy = sBbox.maxy; CPLDestroyXMLNode(psRoot); msFree(pszSRS); } if (sosparams->pszSrsName) { /* validate against MAP.WEB.METADATA.sos_srs */ int iUnits = -1; char **tokens = NULL; const char *pszSRSList = NULL; int n = 0; int bFound = 0; int k; char srsbuffer[100]; projectionObj po; pszSRSList = msOWSLookupMetadata(&(map->web.metadata), "SO", "srs"); if (pszSRSList) { tokens = msStringSplit(pszSRSList, ' ', &n); if (tokens && n > 0) { for (k=0; kpszSrsName, tokens[k]) == 0) { /* match */ bFound = 1; /* project MAP.EXTENT to this SRS */ msInitProjection(&po); snprintf(srsbuffer, sizeof(srsbuffer), "+init=epsg:%.20s", sosparams->pszSrsName+strlen("EPSG:")); if (msLoadProjectionString(&po, srsbuffer) != 0) { msSetError(MS_SOSERR, "Could not set output projection to \"%s\"", "msSOSGetObservation()", sosparams->pszSrsName); return msSOSException(map, "mapserv", "NoApplicableCode"); } if (msProjectionsDiffer(&map->projection, &po) == MS_TRUE) { msProjectRect(&map->projection, &po, &map->extent); sBbox = map->extent; } /* set map->projection to this SRS */ if (msLoadProjectionString(&(map->projection), srsbuffer) != 0) { msSetError(MS_SOSERR, "Could not set output projection to \"%s\"", "msSOSGetObservation()", sosparams->pszSrsName); return msSOSException(map, "mapserv", "NoApplicableCode"); } iUnits = GetMapserverUnitUsingProj(&(map->projection)); if (iUnits != -1) map->units = iUnits; msFreeProjection(&po); break; } } msFreeCharArray(tokens, n); } if (bFound == 0) { msSetError(MS_SOSERR, "srsName value \"%s\" unsupported / invalid", "msSOSGetObservation()", sosparams->pszSrsName); return msSOSException(map, "srsName", "InvalidParameterValue"); } } else { msSetError(MS_SOSERR, "MAP.WEB.METADATA.sos_srs not set", "msSOSGetObservation()"); return msSOSException(map, "mapserv", "NoApplicableCode"); } } /* apply filter */ if (sosparams->pszResult) { psFilterNode = FLTParseFilterEncoding(sosparams->pszResult); if (!psFilterNode) { msSetError(MS_SOSERR, "Invalid or Unsupported RESULT in GetObservation: %s", "msSOSGetObservation()", sosparams->pszResult); return msSOSException(map, "result", "InvalidParameterValue"); } /* apply the filter to all layers that are on */ for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if (lp->status == MS_ON) { /* preparse parser so that alias for fields can be used */ FLTPreParseFilterForAlias(psFilterNode, map, i, "S"); /* validate that the property names used are valid (there is a corresponding layer attribute) */ if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { if (msSOSValidateFilter(psFilterNode, lp)== MS_FALSE) { msSetError(MS_SOSERR, "Invalid component name in RESULT statement", "msSOSGetObservation()"); return msSOSException(map, "result", "InvalidParameterValue"); } msLayerClose(lp); } FLTApplyFilterToLayer(psFilterNode, map, i); } } FLTFreeFilterEncodingNode(psFilterNode); } /* this is just a fall back if bbox is enetered. The bbox parameter is not supported by the sos specs */ if (sosparams->pszBBox && !sosparams->pszFeatureOfInterest) { char **tokens; int n; tokens = msStringSplit(sosparams->pszBBox, ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_SOSERR, "Wrong number of arguments for bounding box.", "msSOSGetObservation()"); return msSOSException(map, "bbox", "InvalidParameterValue"); } sBbox.minx = atof(tokens[0]); sBbox.miny = atof(tokens[1]); sBbox.maxx = atof(tokens[2]); sBbox.maxy = atof(tokens[3]); msFreeCharArray(tokens, n); } /* do the query if the filter encoding (pszResult) is not part of the request. If pszResult is available, the query on the layers will be done when the filter is parsed*/ if (!sosparams->pszResult) { map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = -1; map->query.rect = sBbox; msQueryByRect(map); } /*get the first layers of the offering*/ for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); if (pszTmp && (strcasecmp(pszTmp, sosparams->pszOffering) == 0)) { lp = (GET_LAYER(map, i)); break; } } /* build xml return tree*/ psNsSos = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/sos/1.0", BAD_CAST "sos"); psNsGml = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"); psNsOm = xmlNewNs(NULL, BAD_CAST pszOMNamespaceUri, BAD_CAST pszOMNamespacePrefix); psNsSwe = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe"); psNsXLink = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); psNsMs = xmlNewNs(NULL, BAD_CAST user_namespace_uri, BAD_CAST user_namespace_prefix); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "ObservationCollection"); xmlDocSetRootElement(psDoc, psRootNode); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST pszSOSNamespaceUri, BAD_CAST pszSOSNamespacePrefix)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST user_namespace_uri, BAD_CAST user_namespace_prefix)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/om/1.0", BAD_CAST "om")); xmlNewNsProp(psRootNode, psNsGml, BAD_CAST "id", BAD_CAST sosparams->pszOffering); schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if ((script_url=msOWSGetOnlineResource(map, "SO", "onlineresource", req)) == NULL) return msSOSException(map, "NoApplicableCode", "NoApplicableCode"); xsi_schemaLocation = msStrdup("http://www.opengis.net/om/1.0 "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/om/1.0.0/om.xsd "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *) user_namespace_uri); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *) script_url); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "service=WFS&version=1.1.0&request=DescribeFeatureType&typename="); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *) opLayerName); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); /* description */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "S", "offering_description"); if (pszTmp) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "description", BAD_CAST pszTmp); xmlSetNs(psNode, xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } /* name */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "S", "offering_name"); if (pszTmp) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "name", BAD_CAST pszTmp); xmlSetNs(psNode, xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } /* extent */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "S", "offering_extent"); if (pszTmp) { char **tokens; int n; rectObj envelope; pszTmp2 = msOWSGetEPSGProj(&(map->projection), &(lp->metadata), "SO", MS_TRUE); tokens = msStringSplit(pszTmp, ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_extent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_extent", "InvalidParameterValue"); } envelope.minx = atof(tokens[0]); envelope.miny = atof(tokens[1]); envelope.maxx = atof(tokens[2]); envelope.maxy = atof(tokens[3]); if (map && msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) { if (msProjectRect(&lp->projection, &map->projection, &envelope) == MS_FAILURE) { msSetError(MS_SOSERR, "Coordinates transformation failed. Raised in msProjectRect() of file %s line %d", "msSOSGetCapabilities()", __FILE__, __LINE__); return msSOSException(map, "sos_offering_extent", "InvalidParameterValue"); } } psNode = xmlAddChild(psRootNode, msGML3BoundedBy(psNsGml, envelope.minx, envelope.miny, envelope.maxx, envelope.maxy, pszTmp2)); msFreeCharArray(tokens, n); } /* time pszTmp = msOWSLookupMetadata(&(lp->metadata), "S","offering_timeextent"); if (pszTmp) { char **tokens; int n; char *pszEndTime = NULL; tokens = msStringSplit(pszTmp, '/', &n); if (tokens==NULL || (n != 1 && n!=2)) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_timeextent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_timeextent", "InvalidParameterValue"); } */ /* if (n == 2) */ /* end time is empty. It is going to be set as "now" */ /* pszEndTime = tokens[1]; psNode = xmlAddChild(psRootNode, msSOSAddTimeNode(xmlNewNs(NULL, BAD_CAST pszOMNamespaceUri, BAD_CAST pszOMNamespacePrefix), tokens[0], pszEndTime)); psNode = xmlAddChild(psRootNode, msSOSAddTimeNode(psNsOm, psNsGml, tokens[0], pszEndTime)); msFreeCharArray(tokens, n); } */ if (sosparams->pszResultModel && strcasecmp(sosparams->pszResultModel, "om:Measurement") != 0 && strcasecmp(sosparams->pszResultModel, "om:Observation") != 0) { msSetError(MS_SOSERR, "resultModel should be om:Measurement or om:Observation", "msSOSGetObservation()"); free(xsi_schemaLocation); free(schemalocation); return msSOSException(map, "resultModel", "InvalidParameterValue"); } else { /* output result members */ for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->resultcache && GET_LAYER(map, i)->resultcache->numresults > 0) { msLayerGetItems((GET_LAYER(map, i))); pszTmp = msOWSLookupMetadata(&(map->web.metadata), "SO", "maxfeatures"); if (pszTmp != NULL) n1 = atoi(pszTmp); else n1 = 0; if (sosparams->pszResultModel == NULL || strcasecmp(sosparams->pszResultModel, "om:Measurement") == 0) { for(j=0; jresultcache->numresults; j++) { msSOSAddMemberNode(psNsGml, psNsOm, psNsSwe, psNsXLink, psNsMs, psRootNode, map, (GET_LAYER(map, i)), j, script_url, opLayerName); if (j == n1-1) break; } } else { /*assuming here that pszResultModel = observation */ /*layer does not define a procedure_item: this means one procedure per layer defined using sos_procedure)*/ if (msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "procedure_item") == NULL) { pszProcedure = msOWSLookupMetadata(&(lp->metadata), "S", "procedure"); psObservationNode = msSOSAddMemberNodeObservation(psNsGml, psNsSos, psNsOm, psNsSwe, psNsXLink, psRootNode, map, (GET_LAYER(map, i)), pszProcedure); /*add a result node*/ psResultNode = xmlNewChild(psObservationNode, NULL, BAD_CAST "result", NULL); for(j=0; jresultcache->numresults; j++) { /*add a block separator*/ if (j > 0) { pszBlockSep = msOWSLookupMetadata(&(map->web.metadata), "S", "encoding_blockSeparator"); if (pszBlockSep) xmlNodeAddContent(psResultNode, BAD_CAST pszBlockSep); else xmlNodeAddContent(psResultNode, BAD_CAST "\n"); } pszResult = msSOSReturnMemberResult((GET_LAYER(map, i)), j, NULL); if (pszResult) { xmlNodeAddContent(psResultNode, BAD_CAST pszResult); msFree(pszResult); } } } /*this is the case where procedure_item is used. Needs more management since the same data on a layer contains different procedures (procedures are one of the fields of the record)*/ else { for(j=0; jresultcache->numresults; j++) { pszResult = msSOSReturnMemberResult((GET_LAYER(map, i)), j, &pszProcedureValue); if (!pszProcedureValue || !pszResult) continue; for (k=0; kweb.metadata), "S", "encoding_blockSeparator"); if (pszBlockSep) xmlNodeAddContent(paDiffrentProc[k].psResultNode, BAD_CAST pszBlockSep); else xmlNodeAddContent(paDiffrentProc[k].psResultNode, BAD_CAST "\n"); xmlNodeAddContent(paDiffrentProc[k].psResultNode, BAD_CAST pszResult); break; } } if (k == nDiffrentProc) { /*a new procedure*/ nDiffrentProc++; if (paDiffrentProc == NULL) paDiffrentProc = (SOSProcedureNode *)malloc(sizeof(SOSProcedureNode)); else paDiffrentProc = (SOSProcedureNode *)realloc(paDiffrentProc, sizeof(SOSProcedureNode) *nDiffrentProc); paDiffrentProc[nDiffrentProc-1].pszProcedure = msStrdup(pszProcedureValue); psObservationNode = msSOSAddMemberNodeObservation(psNsGml, psNsSos, psNsOm, psNsSwe, psNsXLink, psRootNode, map, (GET_LAYER(map, i)), pszProcedureValue); msFree(pszProcedureValue); paDiffrentProc[nDiffrentProc-1].psResultNode = xmlNewChild(psObservationNode, NULL, BAD_CAST "result", NULL); xmlNodeAddContent(paDiffrentProc[nDiffrentProc-1].psResultNode, BAD_CAST pszResult); msFree(pszResult); } } if (paDiffrentProc) { for (k=0; kpszOutputFormat) { msSetError(MS_SOSERR, "Missing mandatory parameter outputFormat.", "msSOSDescribeSensor()"); return msSOSException(map, "outputformat", "MissingParameterValue"); } if (strcasecmp(sosparams->pszOutputFormat, pszSOSDescribeSensorMimeType) != 0) { msSetError(MS_SOSERR, "Invalid outputformat parameter %s. Allowable values are: %s", "msSOSDescribeSensor()", sosparams->pszOutputFormat, pszSOSDescribeSensorMimeType); return msSOSException(map, "outputformat", "InvalidParameterValue"); } if (!sosparams->pszProcedure) { msSetError(MS_SOSERR, "Missing mandatory parameter procedure", "msSOSDescribeSensor()"); return msSOSException(map, "procedure", "MissingParameterValue"); } for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); pszId = msOWSLookupMetadata(&(lp->metadata), "S", "procedure"); if (pszId && strlen(pszId) > 0) { /*procedure could be a list*/ char **tokens = NULL; int n=0; int bFound = 0; tokens = msStringSplit(pszId, ' ', &n); for (k=0; k 0) { pszProcedureURI = msStrdup("urn:ogc:def:procedure:"); pszProcedureURI = msStringConcatenate(pszProcedureURI, tokens[k]); if ( (pszProcedureURI && strcasecmp(pszProcedureURI, sosparams->pszProcedure) == 0) && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) ) { bFound = 1; pszProcedureId = msStrdup(tokens[k]); msFree(pszProcedureURI); break; } msFree(pszProcedureURI); } } msFreeCharArray(tokens, n); if (bFound) { pszUrl = msOWSLookupMetadata(&(lp->metadata), "S", "describesensor_url"); if (pszUrl) { pszTmp = msStrdup(pszUrl); /* %procedure% is the hardcoded variable name to use within sos_describesensor_url */ tmpstr = (char *)malloc(sizeof(char)*strlen("procedure") + 3); sprintf(tmpstr,"%%%s%%", "procedure"); if (strcasestr(pszUrl, tmpstr) != NULL) pszTmp = msCaseReplaceSubstring(pszTmp, tmpstr, pszProcedureId); msFree(tmpstr); pszEncodedUrl = msEncodeHTMLEntities(pszTmp); msIO_printf("Location: %s\n\n", pszEncodedUrl); msFree(pszTmp); msFree(pszEncodedUrl); msFree(pszProcedureId); return(MS_SUCCESS); } else { msSetError(MS_SOSERR, "Missing mandatory metadata sos_describesensor_url on layer %s", "msSOSDescribeSensor()", lp->name); return msSOSException(map, "sos_describesensor_url", "MissingParameterValue"); } } } else if ((pszId = msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item"))) { iItemPosition = -1; if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { for(j=0; jnumitems; j++) { if (strcasecmp(lp->items[j], pszId) == 0) { iItemPosition = j; break; } } msLayerClose(lp); } if (iItemPosition >=0) { if (lp->template == NULL) lp->template = msStrdup("ttt"); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = i; map->query.rect = map->extent; msQueryByRect(map); msLayerGetItems(lp); if (lp->resultcache && lp->resultcache->numresults > 0) { for(j=0; jresultcache->numresults; j++) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) continue; if (sShape.values[iItemPosition]) { pszProcedureURI = msStrdup("urn:ogc:def:procedure:"); pszProcedureURI = msStringConcatenate(pszProcedureURI, sShape.values[iItemPosition]); if (strcasecmp(pszProcedureURI, sosparams->pszProcedure) == 0) { pszUrl = msOWSLookupMetadata(&(lp->metadata), "S", "describesensor_url"); pszProcedureId = msStrdup(sShape.values[iItemPosition]); if (pszUrl) { pszTmp = msStrdup(pszUrl); /* %procedure% is the hardcoded variable names to use within sos_describesensor_url */ tmpstr = (char *)malloc(sizeof(char)*strlen("procedure") + 3); sprintf(tmpstr,"%%%s%%", "procedure"); if (strcasestr(pszUrl, tmpstr) != NULL) pszTmp = msCaseReplaceSubstring(pszTmp, tmpstr, pszProcedureId); msFree(tmpstr); pszEncodedUrl = msEncodeHTMLEntities(pszTmp); msIO_printf("Location: %s\n\n", pszEncodedUrl); msFree(pszTmp); return(MS_SUCCESS); } else { msSetError(MS_SOSERR, "Missing mandatory metadata sos_describesensor_url on layer %s", "msSOSDescribeSensor()", lp->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } } } } } } } } msSetError(MS_SOSERR, "procedure %s not found.", "msSOSDescribeSensor()", sosparams->pszProcedure); return msSOSException(map, "procedure", "InvalidParameterValue"); } /************************************************************************/ /* msSOSDescribeObservationType */ /* */ /* DescribeObserrvationType request handler */ /************************************************************************/ int msSOSDescribeObservationType(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *req, owsRequestObj *ows_request) { int i, j, n = 0, bLayerFound = 0; char **tokens = NULL; char *script_url=NULL; const char *pszTmp = NULL; char *pszTmp2=NULL; const char *opLayerName = NULL; if (!sosparams->pszObservedProperty) { msSetError(MS_SOSERR, "Missing mandatory parameter observedproperty", "msSOSDescribeObservationType()"); return msSOSException(map, "observedproperty", "MissingParameterValue"); } tokens = msStringSplit(sosparams->pszObservedProperty, ',', &n); for (i=0; inumlayers; i++) { if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) continue; pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "observedproperty_id"); if (pszTmp) { if (strcasecmp(pszTmp, sosparams->pszObservedProperty) == 0) { if (tokens && n > 0) { for (j=0; jname; bLayerFound = 1; break; } } } } } } if (tokens && n > 0) msFreeCharArray(tokens, n); if (bLayerFound == 0) { msSetError(MS_SOSERR, "ObservedProperty %s not found.", "msSOSGetObservation()", sosparams->pszObservedProperty); return msSOSException(map, "observedproperty", "InvalidParameterValue"); } if ((script_url=msOWSGetOnlineResource(map, "SO", "onlineresource", req)) == NULL) return msSOSException(map, "NoApplicableCode", "NoApplicableCode"); pszTmp2 = msStringConcatenate(pszTmp2, (char *) script_url); pszTmp2 = msStringConcatenate(pszTmp2, "service=WFS&version=1.1.0&request=DescribeFeatureType&typename="); pszTmp2 = msStringConcatenate(pszTmp2, (char *) opLayerName); msIO_printf("Location: %s\n\n", pszTmp2); msFree(pszTmp2); msFree(script_url); return(MS_SUCCESS); } #endif /* defined(USE_WCS_SVR) && defined(USE_LIBXML2) */ /* ** msSOSDispatch() is the entry point for SOS requests. ** - If this is a valid request then it is processed and MS_SUCCESS is returned ** on success, or MS_FAILURE on failure. */ int msSOSDispatch(mapObj *map, cgiRequestObj *req, owsRequestObj *ows_request) { #if defined(USE_SOS_SVR) && defined(USE_LIBXML2) int returnvalue = MS_DONE; sosParamsObj *paramsObj = (sosParamsObj *)calloc(1, sizeof(sosParamsObj)); if (msSOSParseRequest(map, req, paramsObj) == MS_FAILURE) return MS_FAILURE; /* SERVICE must be specified and be SOS */ if (paramsObj->pszService && strcasecmp(paramsObj->pszService, "SOS") == 0) { /* this is an SOS request */ if (!paramsObj->pszRequest) { msSetError(MS_SOSERR, "Missing REQUEST Parameter", "msSOSDispatch()"); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "request", "MissingParameterValue"); } msOWSRequestLayersEnabled(map, "S", paramsObj->pszRequest, ows_request); if (ows_request->numlayers == 0) { msSetError(MS_SOSERR, "SOS request not enabled. Check sos/ows_enable_request settings.", "msSOSDispatch()"); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "request", "InvalidParameterValue"); } if (strcasecmp(paramsObj->pszRequest, "GetCapabilities") == 0) { returnvalue = msSOSGetCapabilities(map, paramsObj, req, ows_request); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } else if (strcasecmp(paramsObj->pszRequest, "DescribeSensor") == 0 || strcasecmp(paramsObj->pszRequest, "GetObservation") == 0 || strcasecmp(paramsObj->pszRequest, "DescribeObservationType") == 0 ) { /* check version */ if (!paramsObj->pszVersion) { msSetError(MS_SOSERR, "Missing VERSION parameter", "msSOSDispatch()"); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "version", "MissingParameterValue"); } if (msOWSParseVersionString(paramsObj->pszVersion) != OWS_1_0_0) { msSetError(MS_SOSERR, "VERSION %s not supported. Supported versions are: %s.", "msSOSDispatch()", paramsObj->pszVersion, pszSOSVersion); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "version", "InvalidParameterValue"); } if (strcasecmp(paramsObj->pszRequest, "DescribeSensor") == 0) returnvalue = msSOSDescribeSensor(map, paramsObj, ows_request); else if (strcasecmp(paramsObj->pszRequest, "GetObservation") == 0) returnvalue = msSOSGetObservation(map, paramsObj, req, ows_request); else if (strcasecmp(paramsObj->pszRequest, "DescribeObservationType") == 0) returnvalue = msSOSDescribeObservationType(map, paramsObj, req, ows_request); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } else { msSetError(MS_SOSERR, "Invalid REQUEST parameter: %s", "msSOSDispatch()", paramsObj->pszRequest); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "request", "InvalidParameterValue"); } } else return MS_DONE; /* Not an SOS request */ #else msSetError(MS_SOSERR, "SOS support is not available.", "msSOSDispatch()"); return(MS_FAILURE); #endif } #if defined(USE_SOS_SVR) && defined(USE_LIBXML2) int msSOSParseRequest(mapObj *map, cgiRequestObj *request, sosParamsObj *sosparams) { int i; xmlDocPtr doc; xmlXPathContextPtr context; xmlNodeSetPtr nodeset; xmlXPathObjectPtr psXPathTmp; char *pszTmp = NULL; if (request->NumParams) { /* this is a GET request */ for(i=0; iNumParams; i++) { if (strcasecmp(request->ParamNames[i], "SERVICE") == 0) sosparams->pszService = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "VERSION") == 0) sosparams->pszVersion = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "ACCEPTVERSIONS") == 0) sosparams->pszAcceptVersions = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "REQUEST") == 0) sosparams->pszRequest = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "UPDATESEQUENCE") == 0) sosparams->pszUpdateSequence = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "SENSORID") == 0) sosparams->pszSensorId = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "PROCEDURE") == 0) sosparams->pszProcedure = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OUTPUTFORMAT") == 0) sosparams->pszOutputFormat = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OFFERING") == 0) sosparams->pszOffering = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OBSERVEDPROPERTY") == 0) sosparams->pszObservedProperty = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "EVENTTIME") == 0) sosparams->pszEventTime = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESULT") == 0) sosparams->pszResult = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESULTMODEL") == 0) sosparams->pszResultModel = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESPONSEFORMAT") == 0) sosparams->pszResponseFormat = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESPONSEMODE") == 0) sosparams->pszResponseMode = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "BBOX") == 0) sosparams->pszBBox = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "SRSNAME") == 0) sosparams->pszSrsName = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "FEATUREOFINTEREST") == 0) sosparams->pszFeatureOfInterest = msStrdup(request->ParamValues[i]); } } if (request->postrequest) { /* this a POST request */ /* load document */ doc = xmlParseDoc((xmlChar *)request->postrequest); if (doc == NULL ) { msSetError(MS_SOSERR, "Invalid POST request. XML is not well-formed", "msSOSParseRequest()"); return msSOSException(map, "request", "InvalidRequest"); } /* load context */ context = xmlXPathNewContext(doc); if (context == NULL) { msSetError(MS_SOSERR, "Could not create context (xmlXPathNewContext)", "msSOSParseRequest()"); return msSOSException(map, "request", "NoApplicableCode"); } /* register namespaces */ if(xmlXPathRegisterNs(context, (xmlChar *)"sos", (xmlChar *)"http://www.opengis.net/sos/1.0") != 0 || xmlXPathRegisterNs(context, (xmlChar *)"ows", (xmlChar *)"http://www.opengis.net/ows/1.1") != 0 || xmlXPathRegisterNs(context, (xmlChar *)"ogc", (xmlChar *)"http://www.opengis.net/ogc") != 0 || xmlXPathRegisterNs(context, (xmlChar *)"gml", (xmlChar *)"http://www.opengis.net/gml") != 0) { msSetError(MS_SOSERR, "Could not register namespaces (xmlXPathRegisterNs)", "msSOSParseRequest()"); return msSOSException(map, "request", "NoApplicableCode"); } /* check for service */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/*/@service"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszService = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for updateSequence*/ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/*/@updateSequence"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszUpdateSequence = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for version */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/*/ows:AcceptVersions/ows:Version|/*/@version"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszVersion = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for request */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetCapabilities"); if (psXPathTmp) sosparams->pszRequest = msStrdup("GetCapabilities"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor"); if (psXPathTmp) sosparams->pszRequest = msStrdup("DescribeSensor"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation"); if (psXPathTmp) sosparams->pszRequest = msStrdup("GetObservation"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeObservationType"); if (psXPathTmp) sosparams->pszRequest = msStrdup("DescribeObservationType"); xmlXPathFreeObject(psXPathTmp); /* check for outputformat */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor/@outputFormat"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszOutputFormat = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for Procedure */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor/sos:procedure"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszProcedure = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for offering */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:offering"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszOffering = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for observedproperty */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:observedProperty"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszObservedProperty = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for procedure */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:procedure"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszProcedure = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for responseFormat */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:responseFormat"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszResponseFormat = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for resultModel */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:resultModel"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszResultModel = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for responseMode */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:responseMode"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszResponseMode = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for srsName */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/@srsName"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszSrsName = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for result (chunk of XML) */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:result/child::*"); if (psXPathTmp) { sosparams->pszResult = msStrdup(msLibXml2GetXPathTree(doc, psXPathTmp)); pszTmp = msStringConcatenate(pszTmp, ""); pszTmp = msStringConcatenate(pszTmp, sosparams->pszResult); pszTmp = msStringConcatenate(pszTmp, ""); msFree(sosparams->pszResult); sosparams->pszResult = msStrdup(pszTmp); msFree(pszTmp); } xmlXPathFreeObject(psXPathTmp); /* check for featureOfInterest (chunk of XML) */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:featureOfInterest/ogc:BBOX/gml:Envelope"); if (psXPathTmp) { sosparams->pszFeatureOfInterest = (char *)msLibXml2GetXPathTree(doc, psXPathTmp); } xmlXPathFreeObject(psXPathTmp); /* check for eventTime (chunk of XML) */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:eventTime/*/gml:TimeInstant|/sos:GetObservation/sos:eventTime/*/gml:TimePeriod"); if (psXPathTmp) { sosparams->pszEventTime = (char *)msLibXml2GetXPathTree(doc, psXPathTmp); } xmlXPathFreeObject(psXPathTmp); xmlXPathFreeContext(context); xmlFreeDoc(doc); xmlCleanupParser(); } return MS_SUCCESS; } void msSOSFreeParamsObj(sosParamsObj *sosparams) { if (sosparams) { if (sosparams->pszService) free(sosparams->pszService); if (sosparams->pszVersion) free(sosparams->pszVersion); if (sosparams->pszAcceptVersions) free(sosparams->pszAcceptVersions); if (sosparams->pszUpdateSequence) free(sosparams->pszUpdateSequence); if (sosparams->pszRequest) free(sosparams->pszRequest); if (sosparams->pszOutputFormat) free(sosparams->pszOutputFormat); if (sosparams->pszSensorId) free(sosparams->pszSensorId); if (sosparams->pszProcedure) free(sosparams->pszProcedure); if (sosparams->pszOffering) free(sosparams->pszOffering); if (sosparams->pszObservedProperty) free(sosparams->pszObservedProperty); if (sosparams->pszEventTime) free(sosparams->pszEventTime); if (sosparams->pszResult) free(sosparams->pszResult); if (sosparams->pszResponseFormat) free(sosparams->pszResponseFormat); if (sosparams->pszResultModel) free(sosparams->pszResultModel); if (sosparams->pszResponseMode) free(sosparams->pszResponseMode); if (sosparams->pszSrsName) free(sosparams->pszSrsName); if (sosparams->pszFeatureOfInterest) free(sosparams->pszFeatureOfInterest); } } #endif /* defined(USE_SOS_SVR) && defined(USE_LIBXML2) */ mapserver-6.4.1/mappostgresql.c0000644002461700001440000003447612261257215016377 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Postgres CONNECTIONTYPE support. * Author: Mark Leslie, Refractions Research * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* $Id$ */ #include #include "mapserver.h" #include "maptime.h" #ifndef FLT_MAX #define FLT_MAX 25000000.0 #endif #ifdef USE_POSTGIS #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN 1 #endif #ifndef BIG_ENDIAN #define BIG_ENDIAN 2 #endif #include "libpq-fe.h" #include #include /* tolower() */ typedef struct { PGconn *conn; /* connection to db */ long row_num; /* what row is the NEXT to be read (for random access) */ PGresult *query_result; /* for fetching rows from the db */ int from_index; char *to_column; char *from_value; int layer_debug; /* there's no debug on the join, so use the layer */ } msPOSTGRESQLJoinInfo; /************************************************************************/ /* msPOSTGRESQLJoinConnect() */ /* */ /* Creates and populates the joininfo struct, including establishing */ /* a connection to the database. Since the join and layer won't always */ /* share connection details, there is currently no mechanism to use */ /* pooled connections with joins. */ /************************************************************************/ int msPOSTGRESQLJoinConnect(layerObj *layer, joinObj *join) { char *maskeddata, *temp, *sql, *column; char *conn_decrypted; int i, count, test; PGresult *query_result; msPOSTGRESQLJoinInfo *joininfo; if(join->joininfo) return MS_SUCCESS; joininfo = (msPOSTGRESQLJoinInfo *)malloc(sizeof(msPOSTGRESQLJoinInfo)); if(!joininfo) { msSetError(MS_MEMERR, "Error allocating join info struct.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } joininfo->conn = NULL; joininfo->row_num = 0; joininfo->query_result = NULL; joininfo->from_index = 0; joininfo->to_column = join->to; joininfo->from_value = NULL; joininfo->layer_debug = layer->debug; join->joininfo = joininfo; /* * We need three things at a minimum, the connection string, a table * name, and a column to join on. */ if(!join->connection) { msSetError(MS_QUERYERR, "No connection information provided.", "MSPOSTGRESQLJoinConnect()"); return MS_FAILURE; } if(!join->table) { msSetError(MS_QUERYERR, "No join table name found.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } if(!joininfo->to_column) { msSetError(MS_QUERYERR, "No join to column name found.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } /* Establish database connection */ conn_decrypted = msDecryptStringTokens(layer->map, join->connection); if (conn_decrypted != NULL) { joininfo->conn = PQconnectdb(conn_decrypted); free(conn_decrypted); } if(!joininfo->conn || PQstatus(joininfo->conn) == CONNECTION_BAD) { maskeddata = (char *)malloc(strlen(layer->connection) + 1); strcpy(maskeddata, join->connection); temp = strstr(maskeddata, "password="); if(!temp) { temp = (char *)(temp + 9); count = (int)(strstr(temp, " ") - temp); for(i = 0; i < count; i++) { strlcpy(temp, "*", (int)1); temp++; } } msSetError(MS_QUERYERR, "Unable to connect to PostgreSQL using the string %s.\n Error reported: %s\n", "msPOSTGRESQLJoinConnect()", maskeddata, PQerrorMessage(joininfo->conn)); free(maskeddata); if(!joininfo->conn) { free(joininfo->conn); } free(joininfo); join->joininfo = NULL; return MS_FAILURE; } /* Determine the number and names of columns in the join table. */ sql = (char *)malloc(36 + strlen(join->table) + 1); sprintf(sql, "SELECT * FROM %s WHERE false LIMIT 0", join->table); if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinConnect(): executing %s.\n", sql); } query_result = PQexec(joininfo->conn, sql); if(!query_result || PQresultStatus(query_result) != PGRES_TUPLES_OK) { msSetError(MS_QUERYERR, "Error determining join items: %s.", "msPOSTGRESQLJoinConnect()", PQerrorMessage(joininfo->conn)); if(query_result) { PQclear(query_result); query_result = NULL; } free(sql); return MS_FAILURE; } free(sql); join->numitems = PQnfields(query_result); join->items = malloc(sizeof(char *) * (join->numitems)); /* We want the join-to column to be first in the list. */ test = 1; for(i = 0; i < join->numitems; i++) { column = PQfname(query_result, i); if(strcmp(column, joininfo->to_column) != 0) { join->items[i + test] = (char *)malloc(strlen(column) + 1); strcpy(join->items[i + test], column); } else { test = 0; join->items[0] = (char *)malloc(strlen(column) + 1); strcpy(join->items[0], column); } } PQclear(query_result); query_result = NULL; if(test == 1) { msSetError(MS_QUERYERR, "Unable to find join to column: %s", "msPOSTGRESQLJoinConnect()", joininfo->to_column); return MS_FAILURE; } if(joininfo->layer_debug) { for(i = 0; i < join->numitems; i++) { msDebug("msPOSTGRESQLJoinConnect(): Column %d named %s\n", i, join->items[i]); } } /* Determine the index of the join from column. */ for(i = 0; i < layer->numitems; i++) { if(strcasecmp(layer->items[i], join->from) == 0) { joininfo->from_index = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msPOSTGRESQLJoinConnect()", join->from, layer->name); return MS_FAILURE; } return MS_SUCCESS; } /************************************************************************/ /* */ /* msPOSTGRESQLJoinPrepare() */ /* Sets up the joininfo to be ready to join against the given shape. */ /* There's not much involved here, just freeing previous results and */ /* resources, and setting the next value to join to. */ /************************************************************************/ int msPOSTGRESQLJoinPrepare(joinObj *join, shapeObj *shape) { /* We need a connection, and a shape with values to join to. */ msPOSTGRESQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join has not been connected.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } if(!shape) { msSetError(MS_JOINERR, "Null shape provided for join.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } if(!shape->values) { msSetError(MS_JOINERR, "Shape has no attributes. Kinda hard to join against.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } joininfo->row_num = 0; /* Free the previous join value, if any. */ if(joininfo->from_value) { free(joininfo->from_value); } /* Free the previous results, if any. */ if(joininfo->query_result) { PQclear(joininfo->query_result); joininfo->query_result = NULL; } /* Copy the next join value from the shape. */ joininfo->from_value = msStrdup(shape->values[joininfo->from_index]); if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinPrepare() preping for value %s.\n", joininfo->from_value); } return MS_SUCCESS; } /************************************************************************/ /* msPOSTGRESQLJoinNext() */ /* */ /* The goal here is to populate join->values with the detail of the */ /* join against the previously prepared shapeObj. This will be called */ /* only once for a one-to-one join, with msPOSTGRESQLJoinPrepare() */ /* being called before each. It will be called repeatedly for */ /* one-to-many joins, until in returns MS_DONE. To accomodate this, */ /* we store the next row number and query results in the joininfo and */ /* process the next tuple on each call. */ /************************************************************************/ int msPOSTGRESQLJoinNext(joinObj *join) { msPOSTGRESQLJoinInfo *joininfo = join->joininfo; int i, length, row_count; char *sql, *columns; /* We need a connection, and a join value. */ if(!joininfo || !joininfo->conn) { msSetError(MS_JOINERR, "Join has not been connected.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } if(!joininfo->from_value) { msSetError(MS_JOINERR, "Join has not been prepared.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } /* Free the previous results. */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } /* We only need to execute the query if no results exist. */ if(!joininfo->query_result) { /* Write the list of column names. */ length = 0; for(i = 0; i < join->numitems; i++) { length += 8 + strlen(join->items[i]) + 2; } columns = (char *)malloc(length); if(!columns) { msSetError(MS_MEMERR, "Failure to malloc.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } strcpy(columns, ""); for(i = 0; i < join->numitems; i++) { strcat(columns, "\""); strcat(columns, join->items[i]); strcat(columns, "\"::text"); if(i != join->numitems - 1) { strcat(columns, ", "); } } /* Create the query string. */ sql = (char *)malloc(26 + strlen(columns) + strlen(join->table) + strlen(join->to) + strlen(joininfo->from_value)); if(!sql) { msSetError(MS_MEMERR, "Failure to malloc.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } sprintf(sql, "SELECT %s FROM %s WHERE %s = '%s'", columns, join->table, join->to, joininfo->from_value); if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinNext(): executing %s.\n", sql); } free(columns); joininfo->query_result = PQexec(joininfo->conn, sql); if(!joininfo->query_result || PQresultStatus(joininfo->query_result) != PGRES_TUPLES_OK) { msSetError(MS_QUERYERR, "Error executing queri %s: %s\n", "msPOSTGRESQLJoinNext()", sql, PQerrorMessage(joininfo->conn)); if(joininfo->query_result) { PQclear(joininfo->query_result); joininfo->query_result = NULL; } free(sql); return MS_FAILURE; } free(sql); } row_count = PQntuples(joininfo->query_result); /* see if we're done processing this set */ if(joininfo->row_num >= row_count) { return(MS_DONE); } if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinNext(): fetching row %ld.\n", joininfo->row_num); } /* Copy the resulting values into the joinObj. */ join->values = (char **)malloc(sizeof(char *) * join->numitems); for(i = 0; i < join->numitems; i++) { join->values[i] = msStrdup(PQgetvalue( joininfo->query_result, joininfo->row_num, i)); } joininfo->row_num++; return MS_SUCCESS; } /************************************************************************/ /* msPOSTGRESQLJoinClose() */ /* */ /* Closes the connection and frees the resources used by the joininfo. */ /************************************************************************/ int msPOSTGRESQLJoinClose(joinObj *join) { msPOSTGRESQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msDebug("msPOSTGRESQLJoinClose() already close or never opened.\n"); return MS_SUCCESS; } if(joininfo->query_result) { msDebug("msPOSTGRESQLJoinClose(): clearing query_result.\n"); PQclear(joininfo->query_result); joininfo->query_result = NULL; } if(joininfo->conn) { msDebug("msPOSTGRESQLJoinClose(): closing connection.\n"); PQfinish(joininfo->conn); joininfo->conn = NULL; } /* removed free(joininfo->to_column), see bug #2936 */ if(joininfo->from_value) { free(joininfo->from_value); } free(joininfo); join->joininfo = NULL; return MS_SUCCESS; } #else /* not USE_POSTGIS */ int msPOSTGRESQLJoinConnect(layerObj *layer, joinObj *join) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } int msPOSTGRESQLJoinPrepare(joinObj *join, shapeObj *shape) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } int msPOSTGRESQLJoinNext(joinObj *join) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } int msPOSTGRESQLJoinClose(joinObj *join) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinClose()"); return MS_FAILURE; } #endif mapserver-6.4.1/mapstring.c0000644002461700001440000015667712261257215015512 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various string handling functions. * Author: Steve Lime and the MapServer team. * * Notes: A couple of string handling functions (strrstr, strlcat) were taken from * other sources. Copyright notices accompany those functions below. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * Copyright (c) 1998 Todd C. Miller * * 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. ****************************************************************************/ #include "mapserver.h" #include "mapthread.h" #include #include #include /* * Find the first occurrence of find in s, ignore case. */ #ifdef USE_FRIBIDI #if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(HAVE_FRIBIDI2) #include "fribidi.h" #else #include #endif #define MAX_STR_LEN 65000 #endif #ifdef USE_ICONV #include #include #endif #include "mapentities.h" #ifndef HAVE_STRRSTR /* ** Copyright (c) 2000-2004 University of Illinois Board of Trustees ** Copyright (c) 2000-2005 Mark D. Roth ** All rights reserved. ** ** Developed by: Campus Information Technologies and Educational Services, ** University of Illinois at Urbana-Champaign ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the ** ``Software''), to deal with 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: ** ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimers. ** ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimers in the ** documentation and/or other materials provided with the distribution. ** ** * Neither the names of Campus Information Technologies and Educational ** Services, University of Illinois at Urbana-Champaign, nor the names ** of its contributors may be used to endorse or promote products derived ** from this Software without specific prior written permission. ** ** 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 CONTRIBUTORS 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 WITH THE SOFTWARE. */ char *strrstr(char *string, char *find) { size_t stringlen, findlen; char *cp; findlen = strlen(find); stringlen = strlen(string); if (findlen > stringlen) return NULL; for (cp = string + stringlen - findlen; cp >= string; cp--) if (strncmp(cp, find, findlen) == 0) return cp; return NULL; } #endif #ifndef HAVE_STRLCAT /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src));/* count does not include NUL */ } #endif #ifndef HAVE_STRLCPY /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif #ifndef HAVE_STRCASESTR /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ char *strcasestr(const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { c = tolower((unsigned char)c); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while ((char)tolower((unsigned char)sc) != c); } while (strncasecmp(s, find, len) != 0); s--; } return ((char *)s); } #endif #ifndef HAVE_STRDUP char *strdup(char *s) { char *s1; if(!s) return(NULL); s1 = (char *)malloc(strlen(s) + 1); if(!s1) return(NULL); strcpy(s1,s); return(s1); } #endif #ifndef HAVE_STRNCASECMP int strncasecmp(const char *s1, const char *s2, int len) { register const char *cp1, *cp2; int cmp = 0; cp1 = s1; cp2 = s2; if(len == 0) return(0); if (!*cp1) return -1; else if (!*cp2) return 1; while(*cp1 && *cp2 && len) { if((cmp = (toupper(*cp1) - toupper(*cp2))) != 0) return(cmp); cp1++; cp2++; len--; } if(len == 0) { return(0); } if(*cp1 || *cp2) { if (*cp1) return(1); else return (-1); } return(0); } #endif #ifndef HAVE_STRCASECMP int strcasecmp(const char *s1, const char *s2) { register const char *cp1, *cp2; int cmp = 0; cp1 = s1; cp2 = s2; if ((!cp1) || (!cp2 )) { return (0); } while(*cp1 && *cp2) { if((cmp = (toupper(*cp1) - toupper(*cp2))) != 0) return(cmp); cp1++; cp2++; } if(*cp1 || *cp2) { if (*cp1) return(1); else return (-1); } return(0); } #endif char *msLongToString(long value) { size_t bufferSize = 256; char *buffer = (char*)msSmallMalloc(bufferSize); snprintf(buffer, bufferSize, "%ld", value); return(buffer); } char *msDoubleToString(double value, int force_f) { size_t bufferSize = 256; char *buffer = (char*)msSmallMalloc(bufferSize); if (force_f == MS_TRUE) snprintf(buffer, bufferSize, "%f", value); else snprintf(buffer, bufferSize, "%g", value); return(buffer); } char *msIntToString(int value) { size_t bufferSize = 256; char *buffer = (char*)msSmallMalloc(bufferSize); snprintf(buffer, bufferSize, "%i", value); return(buffer); } void msStringToUpper(char *string) { int i; if (string != NULL) { for (i = 0; i < strlen(string); i++) { string[i] = toupper(string[i]); } return; } } void msStringToLower(char *string) { int i; if (string != NULL) { for (i = 0; i < strlen(string); i++) { string[i] = tolower(string[i]); } return; } } char *msStringChop(char *string) { int n; n = strlen(string); if(n>0) string[n-1] = '\0'; return(string); } /* ** Trim leading and trailing white space. */ void msStringTrim(char *str) { int i; /* Send nulls home without supper. */ if( ! str ) return; /* Move non-white string to the front. */ i = strspn(str, " "); if(i) { memmove(str, str + i, strlen(str) - i + 1); } /* Nothing left? Exit. */ if(strlen(str) == 0) { return; } /* Null-terminate end of non-white string. */ for(i=strlen(str)-1; i>=0; i--) { /* step backwards from end */ if(str[i] != ' ') { str[i+1] = '\0'; return; } } return; } /* ** Remove leading white spaces and shift everything to the left. */ char *msStringTrimLeft(char *string) { char *read, *write; int i, length; if (string && strlen(string) > 0) { length = strlen(string); read = string; write = string; for (i=0; i write) { while (*read) { *write = *read; read++; write++; } *write = '\0'; } } return string; } /* ------------------------------------------------------------------------------- */ /* Trims trailing blanks from a string */ /* ------------------------------------------------------------------------------- */ void msStringTrimBlanks(char *string) { int i,n; n = strlen(string); for(i=n-1; i>=0; i--) { /* step backwards through the string */ if(string[i] != ' ') { string[i+1] = '\0'; return; } } } /* ------------------------------------------------------------------------------- */ /* Trims end-of-line marker from a string */ /* Usefull in conjunction with fgets() calls */ /* ------------------------------------------------------------------------------- */ void msStringTrimEOL(char *string) { int i; for(i=0 ; string[i] != '\0'; i++) { if(string[i] == '\n') { string[i] = '\0'; /* Terminate the string at the newline */ return; } } } /* ------------------------------------------------------------------------------- */ /* Replace all occurances of old with new in str. */ /* It is assumed that str was dynamically created using malloc. */ /* ------------------------------------------------------------------------------- */ char *msReplaceSubstring(char *str, const char *old, const char *new) { size_t str_len, old_len, new_len, tmp_offset; char *tmp_ptr; if(new == NULL) new = ""; /* ** If old is not found then leave str alone */ if( (tmp_ptr = strstr(str, old)) == NULL) return(str); /* ** Grab some info about incoming strings */ str_len = strlen(str); old_len = strlen(old); new_len = strlen(new); /* ** Now loop until old is NOT found in new */ while( tmp_ptr != NULL ) { /* ** re-allocate memory for buf assuming 1 replacement of old with new ** don't bother reallocating if old is larger than new) */ if (old_len < new_len) { tmp_offset = tmp_ptr - str; str_len = str_len - old_len + new_len; str = (char *)msSmallRealloc(str, (str_len + 1)); /* make new space for a copy */ tmp_ptr = str + tmp_offset; } /* ** Move the trailing part of str to make some room unless old_len == new_len */ if (old_len != new_len) { memmove(tmp_ptr+new_len, tmp_ptr+old_len, strlen(tmp_ptr)-old_len+1); } /* ** Now copy new over old */ memcpy(tmp_ptr, new, new_len); /* ** And look for more matches in the rest of the string */ tmp_ptr = strstr(tmp_ptr + new_len, old); } return(str); } /* * same goal as msReplaceSubstring, but for the known case * when we won't have to do reallocs etc * used to replace the wrap characetr by a newline for labels */ void msReplaceChar(char *str, char old, char new) { while(*(str++)) if(*str==old) *str=new; } /* ** how many times does ch occur in str */ int msCountChars(char *str, char ch) { int i, l, n=0; l = strlen(str); for(i=0; i=0; i--) { /* step backwards through the string */ if((str[i] == '/') || (str[i] == '\\')) { str[i+1] = '\0'; break; } } if(strcmp(str, fn) == 0) { msFree(str); #if defined(_WIN32) && !defined(__CYGWIN__) str = msStrdup(".\\"); #else str= msStrdup("./"); #endif } return(str); } /* ** Returns a *path* built from abs_path and path. ** The pszReturnPath must be declared by the caller function as an array ** of MS_MAXPATHLEN char */ char *msBuildPath(char *pszReturnPath, const char *abs_path, const char *path) { int abslen = 0; int pathlen = 0; if(path == NULL) { msSetError(MS_IOERR, NULL, "msBuildPath"); return NULL; } pathlen = strlen(path); if (abs_path) abslen = strlen(abs_path); if((pathlen + abslen + 2) > MS_MAXPATHLEN) { msSetError(MS_IOERR, "(%s%s): path is too long", "msBuildPath()", abs_path, path); return NULL; } /* Check if path is absolute */ if((abs_path == NULL) || (abslen == 0) || (path[0] == '\\') || (path[0] == '/') || (pathlen > 1 && (path[1] == ':'))) { strlcpy(pszReturnPath, path, MS_MAXPATHLEN); return(pszReturnPath); } /* else return abs_path/path */ if((abs_path[abslen-1] == '/') || (abs_path[abslen-1] == '\\')) { snprintf(pszReturnPath, MS_MAXPATHLEN, "%s%s", abs_path, path); } else { snprintf(pszReturnPath, MS_MAXPATHLEN, "%s/%s", abs_path, path); } return(pszReturnPath); } /* ** Returns a *path* built from abs_path, path1 and path2. ** abs_path/path1/path2 ** The pszReturnPath must be declared by the caller function as an array ** of MS_MAXPATHLEN char */ char *msBuildPath3(char *pszReturnPath, const char *abs_path, const char *path1,const char *path2) { char szPath[MS_MAXPATHLEN]; return msBuildPath(pszReturnPath, abs_path, msBuildPath(szPath, path1, path2)); } /* ** Similar to msBuildPath(), but the input path is only qualified by the ** absolute path if this will result in it pointing to a readable file. ** ** Returns NULL if the resulting path doesn't point to a readable file. */ char *msTryBuildPath(char *szReturnPath, const char *abs_path, const char *path) { FILE *fp; if( msBuildPath( szReturnPath, abs_path, path ) == NULL ) return NULL; fp = fopen( szReturnPath, "r" ); if( fp == NULL ) { strlcpy( szReturnPath, path, MS_MAXPATHLEN); return NULL; } else fclose( fp ); return szReturnPath; } /* ** Similar to msBuildPath3(), but the input path is only qualified by the ** absolute path if this will result in it pointing to a readable file. ** ** Returns NULL if the resulting path doesn't point to a readable file. */ char *msTryBuildPath3(char *szReturnPath, const char *abs_path, const char *path1, const char *path2) { FILE *fp; if( msBuildPath3( szReturnPath, abs_path, path1, path2 ) == NULL ) return NULL; fp = fopen( szReturnPath, "r" ); if( fp == NULL ) { strlcpy( szReturnPath, path2, MS_MAXPATHLEN); return NULL; } else fclose( fp ); return szReturnPath; } /* ** Splits a string into multiple strings based on ch. Consecutive ch's are ignored. */ char **msStringSplit(const char *string, char ch, int *num_tokens) { int i,j,k; int length,n; char **token; char last_ch='\0'; n = 1; /* always at least 1 token, the string itself */ length = strlen(string); for(i=0; i= nTokenMax-3 ) { nTokenMax = nTokenMax * 2 + 10; pszToken = (char *) msSmallRealloc(pszToken, sizeof(char*)*nTokenMax); } pszToken[nTokenLen] = *pszString; nTokenLen++; } /* * Strip spaces at the token end if requested. */ if ( !bInString && bStripEndSpaces ) { while ( nTokenLen && isspace((unsigned char)pszToken[nTokenLen - 1]) ) nTokenLen--; } pszToken[nTokenLen] = '\0'; /* * Add the token. */ if( pszToken[0] != '\0' || bAllowEmptyTokens ) { if( nRetLen >= nRetMax - 1 ) { nRetMax = nRetMax * 2 + 10; papszRetList = (char **) msSmallRealloc(papszRetList, sizeof(char*)*nRetMax); } papszRetList[nRetLen++] = msStrdup( pszToken ); papszRetList[nRetLen] = NULL; } } /* * If the last token was empty, then we need to capture * it now, as the loop would skip it. */ if( *pszString == '\0' && bAllowEmptyTokens && nRetLen > 0 && strchr(pszDelimiters,*(pszString-1)) != NULL ) { if( nRetLen >= nRetMax - 1 ) { nRetMax = nRetMax * 2 + 10; papszRetList = (char **) msSmallRealloc(papszRetList, sizeof(char*)*nRetMax); } papszRetList[nRetLen++] = msStrdup(""); papszRetList[nRetLen] = NULL; } if( papszRetList == NULL ) papszRetList = (char **) msSmallMalloc(sizeof(char *)*1); *num_tokens = nRetLen; free(pszToken); return papszRetList; } /* This method is similar to msStringSplit but support quoted strings. It also support multi-characters delimiter and allows to preserve quotes */ char **msStringTokenize( const char *pszLine, const char *pszDelim, int *num_tokens, int preserve_quote ) { char **papszResult = NULL; int n = 1, iChar, nLength = strlen(pszLine), iTokenChar = 0, bInQuotes = MS_FALSE; char *pszToken = (char *) msSmallMalloc(sizeof(char*)*(nLength+1)); int nDelimLen = strlen(pszDelim); /* Compute the number of tokens */ for( iChar = 0; pszLine[iChar] != '\0'; iChar++ ) { if( bInQuotes && pszLine[iChar] == '"' && pszLine[iChar+1] == '"' ) { iChar++; } else if( pszLine[iChar] == '"' ) { bInQuotes = !bInQuotes; } else if ( !bInQuotes && strncmp(pszLine+iChar,pszDelim,nDelimLen) == 0 ) { iChar += nDelimLen - 1; n++; } } papszResult = (char **) msSmallMalloc(sizeof(char *)*n); n = iTokenChar = bInQuotes = 0; for( iChar = 0; pszLine[iChar] != '\0'; iChar++ ) { if( bInQuotes && pszLine[iChar] == '"' && pszLine[iChar+1] == '"' ) { if (preserve_quote == MS_TRUE) pszToken[iTokenChar++] = '"'; pszToken[iTokenChar++] = '"'; iChar++; } else if( pszLine[iChar] == '"' ) { if (preserve_quote == MS_TRUE) pszToken[iTokenChar++] = '"'; bInQuotes = !bInQuotes; } else if( !bInQuotes && strncmp(pszLine+iChar,pszDelim,nDelimLen) == 0 ) { pszToken[iTokenChar++] = '\0'; papszResult[n] = pszToken; pszToken = (char *) msSmallMalloc(sizeof(char*)*(nLength+1)); iChar += nDelimLen - 1; iTokenChar = 0; n++; } else { pszToken[iTokenChar++] = pszLine[iChar]; } } pszToken[iTokenChar++] = '\0'; papszResult[n] = pszToken; *num_tokens = n+1; return papszResult; } /********************************************************************** * msEncodeChar() * * Return 1 if the character argument should be encoded for safety * in URL use and 0 otherwise. Specific character map taken from * http://www.ietf.org/rfc/rfc2396.txt * **********************************************************************/ int msEncodeChar(const char c) { if ( (c >= 0x61 && c <= 0x7A ) || /* Letters a-z */ (c >= 0x41 && c <= 0x5A ) || /* Letters A-Z */ (c >= 0x30 && c <= 0x39 ) || /* Numbers 0-9 */ (c >= 0x27 && c <= 0x2A ) || /* * ' ( ) */ (c >= 0x2D && c <= 0x2E ) || /* - . */ (c == 0x5F ) || /* _ */ (c == 0x21 ) || /* ! */ (c == 0x7E ) ) { /* ~ */ return(0); } else { return(1); } } char *msEncodeUrl(const char *data) { /* * Delegate to msEncodeUrlExcept, with a null second argument * to render the except handling moot. */ return(msEncodeUrlExcept(data, '\0')); } /********************************************************************** * msEncodeCharExcept() * * URL encoding, applies RFP2396 encoding to all characters * except the one exception character. An exception character * of '\0' implies no exception handling. * **********************************************************************/ char *msEncodeUrlExcept(const char *data, const char except) { char *hex = "0123456789ABCDEF"; const char *i; char *j, *code; int inc; unsigned char ch; for (inc=0, i=data; *i!='\0'; i++) if (msEncodeChar(*i)) inc += 2; code = (char*)msSmallMalloc(strlen(data)+inc+1); for (j=code, i=data; *i!='\0'; i++, j++) { if (*i == ' ') *j = '+'; else if ( except != '\0' && *i == except ) { *j = except; } else if (msEncodeChar(*i)) { ch = *i; *j++ = '%'; *j++ = hex[ch/16]; *j = hex[ch%16]; } else *j = *i; } *j = '\0'; return code; } /* msEncodeHTMLEntities() ** ** Return a copy of string after replacing some problematic chars with their ** HTML entity equivalents. ** ** The replacements performed are: ** '&' -> "&", '"' -> """, '<' -> "<" and '>' -> ">" **/ char *msEncodeHTMLEntities(const char *string) { int buflen, i; char *newstring; const char *c; if(string == NULL) return NULL; /* Start with 100 extra chars for replacements... */ /* should be good enough for most cases */ buflen = strlen(string) + 100; newstring = (char*)malloc(buflen+1); MS_CHECK_ALLOC(newstring, buflen+1, NULL); for(i=0, c=string; *c != '\0'; c++) { /* Need to realloc buffer? */ if (i+6 > buflen) { /* If we had to realloc then this string must contain several */ /* entities... so let's go with twice the previous buffer size */ buflen *= 2; newstring = (char*)realloc(newstring, buflen+1); MS_CHECK_ALLOC(newstring, buflen+1, NULL); } switch(*c) { case '&': strcpy(newstring+i, "&"); i += 5; break; case '<': strcpy(newstring+i, "<"); i += 4; break; case '>': strcpy(newstring+i, ">"); i += 4; break; case '"': strcpy(newstring+i, """); i += 6; break; case '\'': strcpy(newstring+i, "'"); /* changed from ' and i += 6 (bug 1040) */ i += 5; break; default: newstring[i++] = *c; } } newstring[i++] = '\0'; return newstring; } /* msDecodeHTMLEntities() ** ** Modify the string to replace encoded characters by their true value ** ** The replacements performed are: ** "&" -> '&', """ -> '"', "<" -> '<' and ">" -> '>' **/ void msDecodeHTMLEntities(const char *string) { char *pszAmp=NULL, *pszSemiColon=NULL, *pszReplace=NULL, *pszEnd=NULL; char *pszBuffer=NULL; size_t bufferSize = 0; if(string == NULL) return; else pszBuffer = (char*)string; bufferSize = strlen(pszBuffer); pszReplace = (char*) msSmallMalloc(bufferSize); pszEnd = (char*) msSmallMalloc(bufferSize); while((pszAmp = strchr(pszBuffer, '&')) != NULL) { /* Get the &...; */ strlcpy(pszReplace, pszAmp, bufferSize); pszSemiColon = strchr(pszReplace, ';'); if(pszSemiColon == NULL) break; else pszSemiColon++; /* Get everything after the &...; */ strlcpy(pszEnd, pszSemiColon, bufferSize); pszReplace[pszSemiColon-pszReplace] = '\0'; /* Replace the &...; */ if(strcasecmp(pszReplace, "&") == 0) { pszBuffer[pszAmp - pszBuffer] = '&'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, "<") == 0) { pszBuffer[pszAmp - pszBuffer] = '<'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, ">") == 0) { pszBuffer[pszAmp - pszBuffer] = '>'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, """) == 0) { pszBuffer[pszAmp - pszBuffer] = '"'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, "'") == 0) { pszBuffer[pszAmp - pszBuffer] = '\''; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } pszBuffer = pszAmp + 1; } free(pszReplace); free(pszEnd); return; } /* ** msIsXMLValid ** ** Check if the string is an XML valid string. It should contains only ** A-Z, a-z, 0-9, '_', '-', '.', and ':' ** Return MS_TRUE or MS_FALSE */ int msIsXMLTagValid(const char *string) { int i, nLen; nLen = strlen(string); for(i=0; i= 'A' && string[i] <= 'Z' ) && !( string[i] >= 'a' && string[i] <= 'z' ) && !( string[i] >= '0' && string[i] <= '9' ) && string[i] != '-' && string[i] != '.' && string[i] != ':' && string[i] != '_' ) return MS_FALSE; } return MS_TRUE; } /* * Concatenate pszSrc to pszDest and reallocate memory if necessary. */ char *msStringConcatenate(char *pszDest, const char *pszSrc) { int nLen; if (pszSrc == NULL) return pszDest; /* if destination is null, allocate memory */ if (pszDest == NULL) { pszDest = msStrdup(pszSrc); } else { /* if dest is not null, reallocate memory */ char *pszTemp; nLen = strlen(pszDest) + strlen(pszSrc); pszTemp = (char*)realloc(pszDest, nLen + 1); if (pszTemp) { pszDest = pszTemp; strcat(pszDest, pszSrc); pszDest[nLen] = '\0'; } else { msSetError(MS_MEMERR, "Error while reallocating memory.", "msStringConcatenate()"); return NULL; } } return pszDest; } char *msJoinStrings(char **array, int arrayLength, const char *delimeter) { char *string; int stringLength=0; int delimeterLength; int i; if(!array || arrayLength <= 0 || !delimeter) return NULL; delimeterLength = strlen(delimeter); for(i=0; i 1) return str; old_length = strlen(str); if(num_decimal_points == 0) { num_commas = floor((old_length - 1)/3); add_commas=1; /* add commas right away */ } else { num_commas = floor(((old_length - strlen(strchr(str, decimal_point))) - 1)/3); add_commas=0; /* wait until after the decimal point */ } if(num_commas < 1) return str; /* nothing to add */ new_length = old_length + num_commas; str = (char *) msSmallRealloc(str, new_length+1); str[new_length] = '\0'; j = 0; for(i=new_length-1; i>=0; i--) { /* step backwards through the string */ if(num_decimal_points == 1 && add_commas == 0) { /* to the right of the decimal point, no commas */ str[i] = str[i-num_commas]; if(str[i] == decimal_point) add_commas = 1; } else if(add_commas == 1 && j>2) { /* need a comma */ str[i] = comma; num_commas--; /* need one fewer now */ j = 0; /* reset */ } else { str[i] = str[i-num_commas]; /* shift to the right */ j++; } if(num_commas == 0) break; /* done, rest of string is ok "as is" */ } return str; } /* ------------------------------------------------------------------------------- */ /* Replace all occurances of old with new in str. */ /* It is assumed that str was dynamically created using malloc. */ /* Same function as msReplaceSubstring but this is case incensitive */ /* ------------------------------------------------------------------------------- */ char *msCaseReplaceSubstring(char *str, const char *old, const char *new) { size_t str_len, old_len, new_len, tmp_offset; char *tmp_ptr; if(new == NULL) new = ""; /* ** If old is not found then leave str alone */ if( (tmp_ptr = (char *) strcasestr(str, old)) == NULL) return(str); /* ** Grab some info about incoming strings */ str_len = strlen(str); old_len = strlen(old); new_len = strlen(new); /* ** Now loop until old is NOT found in new */ while( tmp_ptr != NULL ) { /* ** re-allocate memory for buf assuming 1 replacement of old with new ** don't bother reallocating if old is larger than new) */ if (old_len < new_len) { tmp_offset = tmp_ptr - str; str_len = str_len - old_len + new_len; str = (char *)msSmallRealloc(str, (str_len + 1)); /* make new space for a copy */ tmp_ptr = str + tmp_offset; } /* ** Move the trailing part of str to make some room unless old_len == new_len */ if (old_len != new_len) { memmove(tmp_ptr+new_len, tmp_ptr+old_len, strlen(tmp_ptr)-old_len+1); } /* ** Now copy new over old */ memcpy(tmp_ptr, new, new_len); /* ** And look for more matches in the rest of the string */ tmp_ptr = (char *) strcasestr(tmp_ptr + new_len, old); } return(str); } /* ** Converts a 2 character hexidecimal string to an integer. */ int msHexToInt(char *hex) { int number; number = (hex[0] >= 'A' ? ((hex[0] & 0xdf) - 'A')+10 : (hex[0] - '0')); number *= 16; number += (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A')+10 : (hex[1] - '0')); return(number); } /* ** Use FRIBIDI to encode the string. ** The return value must be freed by the caller. */ #ifdef USE_FRIBIDI char *msGetFriBidiEncodedString(const char *string, const char *encoding) { FriBidiChar logical[MAX_STR_LEN]; FriBidiParType base; size_t len; #ifdef FRIBIDI_NO_CHARSETS iconv_t to_ucs4, from_ucs4; #else int to_char_set_num; int from_char_set_num; #endif len = strlen(string); #ifdef FRIBIDI_NO_CHARSETS to_ucs4 = iconv_open ("WCHAR_T", encoding); from_ucs4 = iconv_open ("UTF-8", "WCHAR_T"); #else to_char_set_num = fribidi_parse_charset ((char*)encoding); from_char_set_num = fribidi_parse_charset ("UTF-8"); #endif #ifdef FRIBIDI_NO_CHARSETS if (to_ucs4 == (iconv_t) (-1) || from_ucs4 == (iconv_t) (-1)) #else if (!to_char_set_num || !from_char_set_num) #endif { msSetError(MS_IDENTERR, "Encoding not supported (%s).", "msGetFriBidiEncodedString()", encoding); return NULL; } #ifdef FRIBIDI_NO_CHARSETS { char *st = string, *ust = (char *) logical; int in_len = (int) len; len = sizeof logical; iconv (to_ucs4, &st, &in_len, &ust, (int *) &len); len = (FriBidiChar *) ust - logical; } #else len = fribidi_charset_to_unicode (to_char_set_num, (char*)string, len, logical); #endif { FriBidiChar *visual; char outstring[MAX_STR_LEN]; FriBidiStrIndex *ltov, *vtol; FriBidiLevel *levels; FriBidiStrIndex new_len; fribidi_boolean log2vis; int i, j; visual = (FriBidiChar *) msSmallMalloc (sizeof (FriBidiChar) * (len + 1)); ltov = NULL; vtol = NULL; levels = NULL; /* Create a bidi string. */ log2vis = fribidi_log2vis (logical, len, &base, /* output */ visual, ltov, vtol, levels); if (!log2vis) { msSetError(MS_IDENTERR, "Failed to create bidi string.", "msGetFriBidiEncodedString()"); return NULL; } new_len = len; /* Convert it to utf-8 for display. */ #ifdef FRIBIDI_NO_CHARSETS { char *str = outstring, *ust = (char *) visual; int in_len = len * sizeof visual[0]; new_len = sizeof outstring; iconv (from_ucs4, &ust, &in_len, &str, (int *) &new_len); *str = '\0'; new_len = str - outstring; } #else new_len = fribidi_unicode_to_charset (from_char_set_num, visual, len, outstring); /* scan str and compress out FRIBIDI_CHAR_FILL UTF8 characters */ for (i=0, j=0; i 0) { iconv_status = iconv(cd, (char**)&inp, &len, &outp, &bufleft); if(iconv_status == -1) { msFree(out); iconv_close(cd); return msStrdup(string); } } out[bufsize - bufleft] = '\0'; iconv_close(cd); return out; #else if (*string == '\0' || (encoding && strcasecmp(encoding, "UTF-8")==0)) return msStrdup(string); /* Nothing to do: string already in UTF-8 */ msSetError(MS_MISCERR, "Not implemeted since Iconv is not enabled.", "msGetEncodedString()"); return NULL; #endif } char* msConvertWideStringToUTF8 (const wchar_t* string, const char* encoding) { #ifdef USE_ICONV char* output = NULL; char* errormessage = NULL; iconv_t cd = NULL; size_t nStr; size_t nInSize; size_t nOutSize; size_t iconv_status = -1; size_t nBufferSize; char* pszUTF8 = NULL; const wchar_t* pwszWide = NULL; if (string != NULL) { nStr = wcslen (string); nBufferSize = ((nStr * 6) + 1); output = (char*) msSmallMalloc (nBufferSize); if (nStr == 0) { /* return an empty 8 byte string */ output[0] = '\0'; return output; } cd = iconv_open("UTF-8", encoding); nOutSize = nBufferSize; if ((iconv_t)-1 != cd) { nInSize = sizeof (wchar_t)*nStr; pszUTF8 = output; pwszWide = string; iconv_status = iconv(cd, (char **)&pwszWide, &nInSize, &pszUTF8, &nOutSize); if ((size_t)-1 == iconv_status) { switch (errno) { case E2BIG: errormessage = "There is not sufficient room in buffer"; break; case EILSEQ: errormessage = "An invalid multibyte sequence has been encountered in the input"; break; case EINVAL: errormessage = "An incomplete multibyte sequence has been encountered in the input"; break; default: errormessage = "Unknown"; break; } msSetError(MS_MISCERR, "Unable to convert string in encoding '%s' to UTF8 %s", "msConvertWideStringToUTF8()", encoding,errormessage); iconv_close(cd); msFree(output); return NULL; } iconv_close(cd); } else { msSetError(MS_MISCERR, "Encoding not supported by libiconv (%s).", "msConvertWideStringToUTF8()", encoding); msFree(output); return NULL; } } else { /* we were given a NULL wide string, nothing we can do here */ return NULL; } /* NULL-terminate the output string */ output[nBufferSize - nOutSize] = '\0'; return output; #else msSetError(MS_MISCERR, "Not implemented since Iconv is not enabled.", "msConvertWideStringToUTF8()"); return NULL; #endif } /* ** Returns the next glyph in string and advances *in_ptr to the next ** character. ** ** If out_string is not NULL then the character (bytes) is copied to this ** buffer and null-terminated. out_string must be a pre-allocated buffer of ** at least 11 bytes. ** ** The function returns the number of bytes in this glyph. ** ** This function treats 3 types of glyph encodings: * - as an html entity, for example { , Ư , or é * - as an utf8 encoded character * - if utf8 decoding fails, as a raw character * ** This function mimics the character decoding function used in gdft.c of * libGD. It is necessary to have the same behaviour, as input strings must be * split into the same glyphs as what gd does. ** ** In UTF-8, the number of leading 1 bits in the first byte specifies the ** number of bytes in the entire sequence. ** Source: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 ** ** U-00000000 U-0000007F: 0xxxxxxx ** U-00000080 U-000007FF: 110xxxxx 10xxxxxx ** U-00000800 U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx ** U-00010000 U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ** U-00200000 U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx ** U-04000000 U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ int msGetNextGlyph(const char **in_ptr, char *out_string) { unsigned char in; int numbytes=0,unicode; int i; in = (unsigned char)**in_ptr; if (in == 0) return -1; /* Empty string */ if((numbytes=msGetUnicodeEntity(*in_ptr,&unicode))>0) { if(out_string) { for(i=0; iname, en2->name); } /* * this function tests if the string pointed by inptr represents * an HTML entity, in decimal form ( e.g. Å), in hexadecimal * form ( e.g. 水 ), or from html 4.0 spec ( e.g. é ) * - returns returns 0 if the string doesn't represent such an entity. * - if the string does start with such entity,it returns the number of * bytes occupied by said entity, and stores the unicode value in *unicode */ int msGetUnicodeEntity(const char *inptr, int *unicode) { unsigned char *in = (unsigned char*)inptr; int l,val=0; if(*in=='&') { in++; if(*in=='#') { in++; if(*in=='x'||*in=='X') { in++; for(l=3; l<8; l++) { char byte; if(*in>='0'&&*in<='9') byte = *in - '0'; else if(*in>='a'&&*in<='f') byte = *in - 'a' + 10; else if(*in>='A'&&*in<='F') byte = *in - 'A' + 10; else break; in++; val = (val * 16) + byte; } if(*in==';' && l>3 ) { *unicode=val; return ++l; } } else { for(l=2; l<8; l++) { if(*in>='0'&&*in<='9') { val = val*10+*in-'0'; in++; } else break; } if(*in==';' && l>2 ) { *unicode=val; return ++l; } } } else { char entity_name_buf[MAP_ENTITY_NAME_LENGTH_MAX+1]; char *p; struct mapentities_s key, *res; key.name = p = entity_name_buf; for (l = 1; l <= MAP_ENTITY_NAME_LENGTH_MAX+1; l++) { if (*in == '\0') /*end of string before possible entity: return*/ break; if (*in == ';') { /*possible end of entity: do a lookup*/ *p++ = '\0'; res = bsearch(&key, mapentities, MAP_NR_OF_ENTITIES, sizeof(mapentities[0]), *cmp_entities); if (res) { *unicode = res->value; return ++l; } break; /*the string was of the form of an entity but didn't correspond to an existing one: return*/ } *p++ = *in; in++; } } } return 0; } /** * msStringIsInteger() * * determines whether a given string is an integer * * @param string the string to be tested * * @return MS_SUCCESS or MS_FAILURE */ int msStringIsInteger(const char *string) { int length, i; length = strlen(string); if (length == 0) return MS_FAILURE; for(i=0; i mapscriptvars !IFDEF WIN64 echo $(MS_DEFS) -DWIN32 -D_WIN32 -DUSE_GENERIC_MS_NINT >> mapscriptvars !ELSE echo $(MS_DEFS) -DWIN32 -D_WIN32 >> mapscriptvars !ENDIF echo $(INCLUDES) >> mapscriptvars echo $(LIBS_DLL) >> mapscriptvars echo $(LIBS) >> mapscriptvars findstr MS_VERSION mapserver-version.h | findstr define >> mapscriptvars #install: $(MS_DLL) $(MS_EXE) python csharp java php install: $(MS_DLL) $(MS_EXE) -mkdir $(BINDIR) xcopy /y /r /d /f $(MS_DLL) $(BINDIR) copy *.exe $(BINDIR) !IFDEF PYTHON_HOME -mkdir $(BINDIR)\mapscript\python xcopy /y /r /d /f .\mapscript\python\dist\*.zip $(BINDIR)\mapscript\python !ENDIF !IFDEF DOT_NET -mkdir $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.dll $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.exe $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.manifest $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.config $(BINDIR)\mapscript\csharp !ENDIF !IFDEF JAVA_HOME -mkdir $(BINDIR)\mapscript\java xcopy /y /r /d /f .\mapscript\java\*.dll $(BINDIR)\mapscript\java xcopy /y /r /d /f .\mapscript\java\*.jar $(BINDIR)\mapscript\java !ENDIF !IFDEF PHP_HOME -mkdir $(BINDIR)\mapscript\php xcopy /y /r /d /f .\mapscript\php\*.dll $(BINDIR)\mapscript\php !ENDIF !IFDEF PYTHON_HOME python: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\python $(SWIG) -python -shadow -o mapscript_wrap.c ../mapscript.i $(PYTHON_HOME)\PCBuild\python.exe setup.py bdist cd ..\.. !ELSE python: !ENDIF !IFDEF DOT_NET csharp: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\csharp nmake /f makefile.vc cd ..\.. !ELSE csharp: !ENDIF !IFDEF JAVA_HOME java: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\java nmake /f makefile.vc cd ..\.. !ELSE java: !ENDIF !IFDEF PHP_HOME php: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\php nmake /f makefile.vc cd ..\.. !ELSE php: !ENDIF !IF DEFINED(SDE_OPT) || DEFINED(ORACLE) || DEFINED(MSSQL2008) !IFDEF ORACLE ORACLE_LIB=$(ORACLE_DIR)/lib/msvc/oci.lib !ENDIF !IFDEF SDE_OPT !IF $(SDE_VERSION) >= 92 SDE_LIB = $(SDE_DIR)\lib\pe.lib \ $(SDE_DIR)\lib\sde.lib \ $(SDE_DIR)\lib\sg.lib !ELSE SDE_LIB = $(SDE_DIR)\lib\pe$(SDE_VERSION).lib \ $(SDE_DIR)\lib\sde$(SDE_VERSION).lib \ $(SDE_DIR)\lib\sg$(SDE_VERSION).lib !ENDIF !ENDIF !ENDIF plugins: -del mapsde.obj -del maporaclespatial.obj -del mapmssql2008.obj !IFDEF SDE_OPT $(CC) $(CFLAGS) -DUSE_SDE /c mapsde.c /Fomapsde.obj link /dll $(LDEBUG) /out:msplugin_sde_$(SDE_VERSION).dll mapsde.obj mapthread.obj mapserver_i.lib $(SDE_LIB) if exist msplugin_sde_$(SDE_VERSION).dll.manifest mt -manifest msplugin_sde_$(SDE_VERSION).dll.manifest -outputresource:msplugin_sde_$(SDE_VERSION).dll;2 -del mapsde.obj !ENDIF !IFDEF ORACLE $(CC) $(CFLAGS) -DUSE_ORACLESPATIAL /c maporaclespatial.c /Fomaporaclespatial.obj link /dll $(LDEBUG) /out:msplugin_oracle.dll maporaclespatial.obj $(ORACLE_LIB) mapserver_i.lib if exist msplugin_oracle.dll.manifest mt -manifest msplugin_oracle.dll.manifest -outputresource:msplugin_oracle.dll;2 -del maporaclespatial.obj !ENDIF !IFDEF MSSQL2008 $(CC) $(CFLAGS) $(ODBC_INC) -DUSE_MSSQL2008 -DUSE_MSSQL2008_PLUGIN /c mapmssql2008.c /Fomapmssql2008.obj link /dll $(LDEBUG) /out:msplugin_mssql2008.dll mapmssql2008.obj $(ODBC_LIBS) mapserver_i.lib if exist msplugin_mssql2008.dll.manifest mt -manifest msplugin_mssql2008.dll.manifest -outputresource:msplugin_mssql2008.dll;2 -del mapmssql2008.obj !ENDIF mapserver-6.4.1/maptime.h0000644002461700001440000000601212261257215015120 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Time processing related declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPTIME_H #define MAPTIME_H /* (bug 602) gettimeofday() and struct timeval aren't available on Windows, * so we provide a replacement with msGettimeofday() and struct mstimeval on * Windows. On Unix/Linux they are just #defines to the real things. */ #if defined(_WIN32) && !defined(__CYGWIN__) struct mstimeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ }; MS_DLL_EXPORT void msGettimeofday(struct mstimeval *t, void *__not_used_here__); #else # include /* for gettimeofday() */ # define mstimeval timeval # define msGettimeofday(t,u) gettimeofday(t,u) #endif typedef enum { TIME_RESOLUTION_UNDEFINED = -1, TIME_RESOLUTION_MICROSECOND =0, TIME_RESOLUTION_MILLISECOND =1, TIME_RESOLUTION_SECOND =2, TIME_RESOLUTION_MINUTE =3, TIME_RESOLUTION_HOUR =4, TIME_RESOLUTION_DAY =5, TIME_RESOLUTION_MONTH =6, TIME_RESOLUTION_YEAR =7 } MS_TIME_RESOLUTION; /* function prototypes */ void msTimeInit(struct tm *time); int msDateCompare(struct tm *time1, struct tm *time2); int msTimeCompare(struct tm *time1, struct tm *time2); char *msStrptime(const char *s, const char *format, struct tm *tm); int msParseTime(const char *string, struct tm *tm); int msTimeMatchPattern(char *timestring, char *pattern); void msSetLimitedPattersToUse(char *patternstring); void msUnsetLimitedPatternToUse(void); int msTimeGetResolution(const char *timestring); void msTimeCleanup(); int msValidateTimeValue(char *timestring, const char *timeextent); #endif /* MAPTIME_H */ mapserver-6.4.1/mapfile.dtd0000644002461700001440000001546112261257215015435 0ustar tbonfortusers mapserver-6.4.1/mapoglcontext.cpp0000644002461700001440000003531712261257215016715 0ustar tbonfortusers/****************************************************************************** * $id: mapoglcontext.cpp 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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. ****************************************************************************/ #ifdef USE_OGL #include "mapserver.h" #include "maperror.h" #include "mapoglcontext.h" #define _T(x) __TEXT(x) ms_uint32 OglContext::MAX_MULTISAMPLE_SAMPLES = 16; ms_uint32 OglContext::MAX_ANISOTROPY = 0; ms_uint32 OglContext::MAX_TEXTURE_SIZE = 0; ms_uint32 OglContext::MIN_TEXTURE_SIZE = 0; OglContext* OglContext::current = NULL; OglContext::OglContext(ms_uint32 width, ms_uint32 height) : valid(false) { if (!window && !initWindow()) return; if (!sharingContext && !initSharingContext()) return; if (!(this->width = getTextureSize(GL_TEXTURE_WIDTH, width))) return; if (!(this->height = getTextureSize(GL_TEXTURE_HEIGHT, height))) return; if (!createPBuffer(this->width, this->height)) return; if (!makeCurrent()) return; valid = true; } ms_uint32 OglContext::getTextureSize(GLuint dimension, ms_uint32 value) { glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, value, value, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); GLint check = 0; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, dimension, &check); if (glGetError() != GL_NO_ERROR) { msSetError(MS_OGLERR, "glGetTexLevelParameteriv failed. glError: %d", "OglContext::getTextureSize()", glGetError()); } if (check == 0) { return MS_MAX(MS_MIN(NextPowerOf2(value), OglContext::MAX_TEXTURE_SIZE), OglContext::MIN_TEXTURE_SIZE); } else { msSetError(MS_OGLERR, "Unable to create opengl texture of map size", "OglContext::getTextureSize()"); return value; } } GLuint OglContext::NextPowerOf2(GLuint in) { in -= 1; in |= in >> 16; in |= in >> 8; in |= in >> 4; in |= in >> 2; in |= in >> 1; return in + 1; } #if defined(_WIN32) && !defined(__CYGWIN__) HDC OglContext::window = NULL; HGLRC OglContext::sharingContext = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return(1L); } OglContext::~OglContext() { //TODO } bool OglContext::makeCurrent() { if (current != this) { current = this; if (!wglMakeContextCurrentARB(hPBufferDC, hPBufferDC, hPBufferRC)) { msSetError(MS_OGLERR, "Can't Activate The GL Rendering pbuffer.", "OglContext::makeCurrent()"); return FALSE; } } return true; } bool OglContext::initWindow() { int windowPixelFormat; WNDCLASS wc; DWORD dwExStyle; DWORD dwStyle; RECT WindowRect; HMODULE hInstance = NULL; HWND hWnd = NULL; WindowRect.left=(long)0; WindowRect.right=(long)0; WindowRect.top=(long)0; WindowRect.bottom=(long)0; hInstance = GetModuleHandle(NULL); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.lpfnWndProc = (WNDPROC) WndProc; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = _T("OpenGL"); if (!RegisterClass(&wc)) { msSetError(MS_OGLERR, "Failed To Register The Window Class.", "OglContext::initWindow()"); return FALSE; } dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle=WS_OVERLAPPEDWINDOW; AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); if (!(hWnd=CreateWindowEx( dwExStyle, _T("OpenGL"), _T("temp"), dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, NULL, NULL, hInstance, NULL))) { msSetError(MS_OGLERR, "Window Creation Error.", "OglContext::initWindow()"); return FALSE; } static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 8, // Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; if (!(window=GetDC(hWnd))) { msSetError(MS_OGLERR, "Can't Create A GL Device Context.. Last Error: %d", "OglContext::initWindow()", GetLastError()); return FALSE; } if (!(windowPixelFormat=ChoosePixelFormat(window,&pfd))) { msSetError(MS_OGLERR, "Can't Find A Suitable windowPixelFormat. Last Error: %d", "OglContext::initWindow()", GetLastError()); return FALSE; } if(!SetPixelFormat(window,windowPixelFormat,&pfd)) { msSetError(MS_OGLERR, "Can't Set The windowPixelFormat. Last Error: %d", "OglContext::initWindow()", GetLastError()); return FALSE; } return TRUE; } bool OglContext::initSharingContext() { if (!(sharingContext=wglCreateContext(window))) { msSetError(MS_OGLERR, "Can't Create A GL Rendering Context.", "OglContext::createContext()"); return FALSE; } if(!wglMakeCurrent(window,sharingContext)) { msSetError(MS_OGLERR, "Can't Activate The GL Rendering Context.", "OglContext::createContext()"); return FALSE; } if (!(wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"))) { msSetError(MS_OGLERR, "unable to retreive wglChoosePixelFormatARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"))) { msSetError(MS_OGLERR, "unable to retreive wglCreatePbufferARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB"))) { msSetError(MS_OGLERR, "unable to retreive wglGetPbufferDCARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB"))) { msSetError(MS_OGLERR, "unable to retreive wglReleasePbufferDCARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetProcAddress("wglMakeContextCurrentARB"))) { msSetError(MS_OGLERR, "unable to retreive wglMakeContextCurrentARB method.", "OglContext::createContext()"); return FALSE; } glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*) &MAX_ANISOTROPY); glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&MAX_TEXTURE_SIZE); MIN_TEXTURE_SIZE = 8; return TRUE; } bool OglContext::createPBuffer(ms_uint32 width, ms_uint32 height) { HPBUFFERARB hPBuffer = NULL; hPBufferDC = NULL; hPBufferRC = NULL; int pixelFormat; int valid = false; UINT numFormats = 0; float fAttributes[] = {0,0}; int samples = MAX_MULTISAMPLE_SAMPLES; while ((!valid || numFormats == 0) && samples >= 0) { int iAttributes[] = { WGL_SAMPLES_ARB,samples, WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE, WGL_SUPPORT_OPENGL_ARB,GL_TRUE, WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB,24, WGL_ALPHA_BITS_ARB,8, WGL_DEPTH_BITS_ARB,16, WGL_STENCIL_BITS_ARB,0, WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 0,0 }; valid = wglChoosePixelFormatARB(window,iAttributes,fAttributes,1,&pixelFormat,&numFormats); if (!valid || numFormats == 0) samples -= 2; } if(numFormats == 0) { msSetError(MS_OGLERR, "P-buffer Error: Unable to find an acceptable pixel format.", "OglContext::createPBuffer()"); return FALSE; } if (!(hPBuffer = wglCreatePbufferARB(window, pixelFormat, width, height, 0))) { msSetError(MS_OGLERR, "P-buffer Error: Unable to create P-buffer. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } if (!(hPBufferDC = wglGetPbufferDCARB(hPBuffer))) { msSetError(MS_OGLERR, "P-buffer Error: Unable to get P-buffer DC. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } if (!(hPBufferRC = wglCreateContext(hPBufferDC))) { msSetError(MS_OGLERR, "P-buffer Error: Unable to get P-buffer DC. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } if (wglShareLists(sharingContext,hPBufferRC) == FALSE) { msSetError(MS_OGLERR, "P-buffer Error: Unable to share display lists. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } return TRUE; } PFNWGLCHOOSEPIXELFORMATARBPROC OglContext::wglChoosePixelFormatARB = NULL; PFNWGLCREATEPBUFFERARBPROC OglContext::wglCreatePbufferARB = NULL; PFNWGLGETPBUFFERDCARBPROC OglContext::wglGetPbufferDCARB = NULL; PFNWGLRELEASEPBUFFERDCARBPROC OglContext::wglReleasePbufferDCARB = NULL; PFNWGLMAKECONTEXTCURRENTARBPROC OglContext::wglMakeContextCurrentARB = NULL; #else /* UNIX */ Display* OglContext::window = NULL; GLXContext OglContext::sharingContext = NULL; GLXFBConfig* OglContext::configs = NULL; OglContext::~OglContext() { //TODO } bool OglContext::makeCurrent() { if (current != this) { current = this; if (!glXMakeCurrent(window, pbuffer, sharingContext)) { msSetError(MS_OGLERR, "glXMakeCurrent failed. glError: %d", "OglContext::makeCurrent()", glGetError()); return false; } } return true; } bool OglContext::initSharingContext() { int fb_attributes[] = { GLX_SAMPLES_ARB, MAX_MULTISAMPLE_SAMPLES, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, 0, GLX_SAMPLE_BUFFERS_ARB, 1, 0 }; int num_configs = 0; while (num_configs == 0 && fb_attributes[1] >= 0) { configs = glXChooseFBConfig(window, DefaultScreen(window), fb_attributes, &num_configs); fb_attributes[1] -= 2; } if (configs == NULL || num_configs == 0) { msSetError(MS_OGLERR, "glXChooseFBConfig could not find any configs. Likely your video card or drivers are not supported. glError: %d", "OglContext::init()", glGetError()); return false; } sharingContext = glXCreateNewContext(window, *configs, GLX_RGBA_TYPE, NULL, 1); if (sharingContext == NULL) { msSetError(MS_OGLERR, "glXCreateNewContext failed. glError: %d", "OglContext::initSharingContext()", glGetError()); return false; } return true; } bool OglContext::createPBuffer(ms_uint32 width, ms_uint32 height) { int maxHeight, maxWidth; glXGetFBConfigAttrib(window, *configs, GLX_MAX_PBUFFER_WIDTH, &maxWidth); glXGetFBConfigAttrib(window, *configs, GLX_MAX_PBUFFER_HEIGHT, &maxHeight); ms_uint32 uMaxHeight = maxHeight, uMaxWidth = maxWidth; this->width = MS_MIN(width, uMaxWidth); this->height = MS_MIN(height, uMaxHeight); int iPbufferAttributes[] = { GLX_PBUFFER_WIDTH, this->width, GLX_PBUFFER_HEIGHT, this->height, GLX_LARGEST_PBUFFER, false, 0, 0 }; pbuffer = glXCreatePbuffer(window, *configs, iPbufferAttributes); if (pbuffer == 0) { msSetError(MS_OGLERR, "glXCreatePbuffer failed. glError: %d", "OglContext::init()", glGetError()); return false; } return true; } bool OglContext::initWindow() { const char* const display_name = getenv("DISPLAY"); if (!display_name) { msSetError(MS_OGLERR, "DISPLAY environment variable not set", "OglContext::init()"); return false; } window = XOpenDisplay(display_name); if (!window) { msSetError(MS_OGLERR, "XOpenDisplay() failed.", "OglContext::init()"); return false; } const int fb_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, 0, GLX_SAMPLE_BUFFERS_ARB, 1, 0 }; int num_configs = 0; GLXFBConfig* tempConfigs = glXChooseFBConfig(window, DefaultScreen(window), fb_attributes, &num_configs); if (tempConfigs == NULL || num_configs == 0) { msSetError(MS_OGLERR, "glXChooseFBConfig could not find any configs. Likely your video card or drivers are not supported.", "OglContext::initWindow()"); return false; } GLXContext tempContext = glXCreateNewContext(window, *tempConfigs, GLX_RGBA_TYPE, NULL, 1); if (tempContext == NULL) { msSetError(MS_OGLERR, "glXCreateNewContext failed.", "OglContext::initWindow()"); return false; } int iPbufferAttributes[] = {0, 0}; GLXPbuffer tempBuffer = glXCreatePbuffer(window, *tempConfigs, iPbufferAttributes); if (tempBuffer == 0) { msSetError(MS_OGLERR, "glXCreatePbuffer failed.", "OglContext::initWindow()"); return false; } if (!glXMakeCurrent(window, tempBuffer, tempContext)) { msSetError(MS_OGLERR, "glXMakeCurrent failed.", "OglContext::initWindow()"); return false; } glGetIntegerv(GL_MAX_SAMPLES_EXT, (GLint*)&MAX_MULTISAMPLE_SAMPLES); glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*) &MAX_ANISOTROPY); glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&MAX_TEXTURE_SIZE); MIN_TEXTURE_SIZE = 8; return true; } #endif /* UNIX */ #endif /* USE_OGL */ mapserver-6.4.1/hittest.c0000644002461700001440000002243712261257215015154 0ustar tbonfortusers/***************************************************************************** * * Project: MapServer * Purpose: Content Dependant Legend rendering support * Author: Thomas Bonfort (tbonfort@terriscope.fr) * ****************************************************************************** * Copyright (c) 1996-2013 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. ****************************************************************************/ #include "mapserver.h" void initStyleHitTests(styleObj *s, style_hittest *sh, int default_status) { sh->status = default_status; } void initLabelHitTests(labelObj *l, label_hittest *lh, int default_status) { int i; lh->stylehits = msSmallCalloc(l->numstyles,sizeof(style_hittest)); lh->status = default_status; for(i=0; inumstyles; i++) { initStyleHitTests(l->styles[i],&lh->stylehits[i],default_status); } } void initClassHitTests(classObj *c, class_hittest *ch, int default_status) { int i; ch->stylehits = msSmallCalloc(c->numstyles,sizeof(style_hittest)); ch->labelhits = msSmallCalloc(c->numlabels,sizeof(label_hittest)); ch->status = default_status; for(i=0; inumstyles; i++) { initStyleHitTests(c->styles[i],&ch->stylehits[i],default_status); } for(i=0; inumlabels; i++) { initLabelHitTests(c->labels[i],&ch->labelhits[i],default_status); } } void initLayerHitTests(layerObj *l, layer_hittest *lh) { int i,default_status; lh->classhits = msSmallCalloc(l->numclasses,sizeof(class_hittest)); lh->status = default_status; switch(l->type) { case MS_LAYER_POLYGON: case MS_LAYER_POINT: case MS_LAYER_LINE: case MS_LAYER_ANNOTATION: default_status = 0; /* needs testing */ break; default: default_status = 1; /* no hittesting needed, use traditional mode */ break; } for(i=0; inumclasses; i++) { initClassHitTests(l->class[i],&lh->classhits[i], default_status); } } void initMapHitTests(mapObj *map, map_hittest *mh) { int i; mh->layerhits = msSmallCalloc(map->numlayers,sizeof(layer_hittest)); for(i=0; inumlayers; i++) { initLayerHitTests(GET_LAYER(map,i),&mh->layerhits[i]); } } void freeLabelHitTests(labelObj *l, label_hittest *lh) { free(lh->stylehits); } void freeClassHitTests(classObj *c, class_hittest *ch) { int i; for(i=0; inumlabels; i++) { freeLabelHitTests(c->labels[i],&ch->labelhits[i]); } free(ch->stylehits); free(ch->labelhits); } void freeLayerHitTests(layerObj *l, layer_hittest *lh) { int i; for(i=0; inumclasses; i++) { freeClassHitTests(l->class[i],&lh->classhits[i]); } free(lh->classhits); } void freeMapHitTests(mapObj *map, map_hittest *mh) { int i; for(i=0; inumlayers; i++) { freeLayerHitTests(GET_LAYER(map,i),&mh->layerhits[i]); } free(mh->layerhits); } int msHitTestShape(mapObj *map, layerObj *layer, shapeObj *shape, int drawmode, class_hittest *hittest) { int i; classObj *cp = layer->class[shape->classindex]; if(MS_DRAW_FEATURES(drawmode)) { for(i=0;inumstyles;i++) { styleObj *sp = cp->styles[i]; if(msScaleInBounds(map->scaledenom,sp->minscaledenom,sp->maxscaledenom)) { hittest->stylehits[i].status = 1; } } } if(MS_DRAW_LABELS(drawmode)) { for(i=0;inumlabels;i++) { labelObj *l = cp->labels[i]; if(l->status == MS_ON) { int s; hittest->labelhits[i].status = 1; for(s=0; snumstyles;s++) { hittest->labelhits[i].stylehits[s].status = 1; } } } } return MS_SUCCESS; } int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) { int status; #ifdef USE_GEOS shapeObj searchpoly; #endif if(!msLayerIsVisible(map,layer)) { hittest->status = 0; return MS_SUCCESS; } if(layer->type == MS_LAYER_LINE || layer->type == MS_LAYER_POLYGON || layer->type == MS_LAYER_POINT || layer->type == MS_LAYER_ANNOTATION) { int maxfeatures=msLayerGetMaxFeaturesToDraw(layer, NULL); int annotate = msEvalContext(map, layer, layer->labelrequires); shapeObj shape; int nclasses,featuresdrawn = 0; int *classgroup; rectObj searchrect; int minfeaturesize=-1; if(map->scaledenom > 0) { if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE; if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE; } status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; /* build item list */ status = msLayerWhichItems(layer, MS_FALSE, NULL); if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) { searchrect = map->extent; #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif } else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_GEOS msInitShape(&searchpoly); msRectToPolygon(searchrect,&searchpoly); #endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); hittest->status = 0; return MS_SUCCESS; } else if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* step through the target shapes */ msInitShape(&shape); nclasses = 0; classgroup = NULL; if(layer->classgroup && layer->numclasses > 0) classgroup = msAllocateValidClassGroups(layer, &nclasses); if(layer->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, layer, layer->minfeaturesize); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { int drawmode = MS_DRAWMODE_FEATURES; #ifdef USE_GEOS if(!msGEOSIntersects(&shape,&searchpoly)) { msFreeShape(&shape); continue; } #else if(shape.type == MS_SHAPE_POLYGON) { msClipPolygonRect(&shape, map->extent); } else { msClipPolylineRect(&shape, map->extent); } if(shape.numlines == 0) { msFreeShape(&shape); continue; } #endif /* Check if the shape size is ok to be drawn, we need to clip */ if((shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0)) { msTransformShape(&shape, map->extent, map->cellsize, NULL); msComputeBounds(&shape); if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(layer, map, &shape, classgroup, nclasses); if((shape.classindex == -1) || (layer->class[shape.classindex]->status == MS_OFF)) { msFreeShape(&shape); continue; } hittest->classhits[shape.classindex].status = 1; hittest->status = 1; if(maxfeatures >=0 && featuresdrawn >= maxfeatures) { status = MS_DONE; break; } featuresdrawn++; if(annotate && layer->class[shape.classindex]->numlabels > 0) { msShapeGetAnnotation(layer, &shape); drawmode |= MS_DRAWMODE_LABELS; } status = msHitTestShape(map, layer, &shape, drawmode, &hittest->classhits[shape.classindex]); /* all styles */ msFreeShape(&shape); } if (classgroup) msFree(classgroup); if(status != MS_DONE) { msLayerClose(layer); return MS_FAILURE; } msLayerClose(layer); return MS_SUCCESS; } else { /* we don't hittest these layers, skip as they already have been initialised */ return MS_SUCCESS; } } int msHitTestMap(mapObj *map, map_hittest *hittest) { int i,status; map->cellsize = msAdjustExtent(&(map->extent),map->width,map->height); status = msCalculateScale(map->extent,map->units,map->width,map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { return MS_FAILURE; } for(i=0; inumlayers; i++) { layerObj *lp = map->layers[i]; status = msHitTestLayer(map,lp,&hittest->layerhits[i]); if(status != MS_SUCCESS) { return MS_FAILURE; } } return MS_SUCCESS; } mapserver-6.4.1/mapshape.c0000644002461700001440000030164612261257215015270 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements support for shapefile access. * Authors: Steve Lime and Frank Warmerdam * * Note: * This code is entirely based on the previous work of Frank Warmerdam. It is * essentially shapelib 1.1.5. However, there were enough changes that it was * incorporated into the MapServer source to avoid confusion. Relicensed with * permission of Frank Warmerdam (shapelib author). See the README * for licence details. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include #include "mapserver.h" #if defined(USE_GDAL) || defined(USE_OGR) #include #include #endif /* Only use this macro on 32-bit integers! */ #define SWAP_FOUR_BYTES(data) \ ( ((data >> 24) & 0x000000FF) | ((data >> 8) & 0x0000FF00) | \ ((data << 8) & 0x00FF0000) | ((data << 24) & 0xFF000000) ) #define ByteCopy( a, b, c ) memcpy( b, a, c ) static int bBigEndian; /************************************************************************/ /* SwapWord() */ /* */ /* Swap a 2, 4 or 8 byte word. */ /************************************************************************/ static void SwapWord( int length, void * wordP ) { int i; uchar temp; for( i=0; i < length/2; i++ ) { temp = ((uchar *) wordP)[i]; ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1]; ((uchar *) wordP)[length-i-1] = temp; } } /************************************************************************/ /* SfRealloc() */ /* */ /* A realloc cover function that will access a NULL pointer as */ /* a valid input. */ /************************************************************************/ static void * SfRealloc( void * pMem, int nNewSize ) { if( pMem == NULL ) return( (void *) malloc(nNewSize) ); else return( (void *) realloc(pMem,nNewSize) ); } /************************************************************************/ /* writeHeader() */ /* */ /* Write out a header for the .shp and .shx files as well as the */ /* contents of the index (.shx) file. */ /************************************************************************/ static void writeHeader( SHPHandle psSHP ) { uchar abyHeader[100]; int i; ms_int32 i32; double dValue; ms_int32 *panSHX; /* -------------------------------------------------------------------- */ /* Prepare header block for .shp file. */ /* -------------------------------------------------------------------- */ for( i = 0; i < 100; i++ ) abyHeader[i] = 0; abyHeader[2] = 0x27; /* magic cookie */ abyHeader[3] = 0x0a; i32 = psSHP->nFileSize/2; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); i32 = 1000; /* version */ ByteCopy( &i32, abyHeader+28, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+28 ); i32 = psSHP->nShapeType; /* shape type */ ByteCopy( &i32, abyHeader+32, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+32 ); dValue = psSHP->adBoundsMin[0]; /* set bounds */ ByteCopy( &dValue, abyHeader+36, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+36 ); dValue = psSHP->adBoundsMin[1]; ByteCopy( &dValue, abyHeader+44, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+44 ); dValue = psSHP->adBoundsMax[0]; ByteCopy( &dValue, abyHeader+52, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+52 ); dValue = psSHP->adBoundsMax[1]; ByteCopy( &dValue, abyHeader+60, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+60 ); dValue = psSHP->adBoundsMin[2]; /* z */ ByteCopy( &dValue, abyHeader+68, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+68 ); dValue = psSHP->adBoundsMax[2]; ByteCopy( &dValue, abyHeader+76, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+76 ); dValue = psSHP->adBoundsMin[3]; /* m */ ByteCopy( &dValue, abyHeader+84, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+84 ); dValue = psSHP->adBoundsMax[3]; ByteCopy( &dValue, abyHeader+92, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+92 ); /* -------------------------------------------------------------------- */ /* Write .shp file header. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, 0, 0 ); fwrite( abyHeader, 100, 1, psSHP->fpSHP ); /* -------------------------------------------------------------------- */ /* Prepare, and write .shx file header. */ /* -------------------------------------------------------------------- */ i32 = (psSHP->nRecords * 2 * sizeof(ms_int32) + 100)/2; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); fseek( psSHP->fpSHX, 0, 0 ); fwrite( abyHeader, 100, 1, psSHP->fpSHX ); /* -------------------------------------------------------------------- */ /* Write out the .shx contents. */ /* -------------------------------------------------------------------- */ panSHX = (ms_int32 *) msSmallMalloc(sizeof(ms_int32) * 2 * psSHP->nRecords); for( i = 0; i < psSHP->nRecords; i++ ) { panSHX[i*2 ] = psSHP->panRecOffset[i]/2; panSHX[i*2+1] = psSHP->panRecSize[i]/2; if( !bBigEndian ) { *(panSHX+i*2) = SWAP_FOUR_BYTES(*(panSHX+i*2)); *(panSHX+i*2+1) = SWAP_FOUR_BYTES(*(panSHX+i*2+1)); } } fwrite( panSHX, sizeof(ms_int32) * 2, psSHP->nRecords, psSHP->fpSHX ); free( panSHX ); } /************************************************************************/ /* msSHPOpen() */ /* */ /* Open the .shp and .shx files based on the basename of the */ /* files or either file name. */ /************************************************************************/ SHPHandle msSHPOpen( const char * pszLayer, const char * pszAccess ) { char *pszFullname, *pszBasename; SHPHandle psSHP; uchar *pabyBuf; int i; double dValue; /* -------------------------------------------------------------------- */ /* Ensure the access string is one of the legal ones. We */ /* ensure the result string indicates binary to avoid common */ /* problems on Windows. */ /* -------------------------------------------------------------------- */ if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0 || strcmp(pszAccess,"r+") == 0 ) pszAccess = "r+b"; else pszAccess = "rb"; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Initialize the info structure. */ /* -------------------------------------------------------------------- */ psSHP = (SHPHandle) msSmallMalloc(sizeof(SHPInfo)); psSHP->bUpdated = MS_FALSE; psSHP->pabyRec = NULL; psSHP->panParts = NULL; psSHP->nBufSize = psSHP->nPartMax = 0; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszLayer)+5); strcpy( pszBasename, pszLayer ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s.shp", pszBasename ); psSHP->fpSHP = fopen(pszFullname, pszAccess ); if( psSHP->fpSHP == NULL ) { sprintf( pszFullname, "%s.SHP", pszBasename ); psSHP->fpSHP = fopen(pszFullname, pszAccess ); } if( psSHP->fpSHP == NULL ) { msFree(pszBasename); msFree(pszFullname); msFree(psSHP); return( NULL ); } sprintf( pszFullname, "%s.shx", pszBasename ); psSHP->fpSHX = fopen(pszFullname, pszAccess ); if( psSHP->fpSHX == NULL ) { sprintf( pszFullname, "%s.SHX", pszBasename ); psSHP->fpSHX = fopen(pszFullname, pszAccess ); } if( psSHP->fpSHX == NULL ) { msFree(pszBasename); msFree(pszFullname); msFree(psSHP); return( NULL ); } free( pszFullname ); free( pszBasename ); /* -------------------------------------------------------------------- */ /* Read the file size from the SHP file. */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) msSmallMalloc(100); fread( pabyBuf, 100, 1, psSHP->fpSHP ); psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256 + pabyBuf[25] * 256 * 256 + pabyBuf[26] * 256 + pabyBuf[27]) * 2; /* -------------------------------------------------------------------- */ /* Read SHX file Header info */ /* -------------------------------------------------------------------- */ fread( pabyBuf, 100, 1, psSHP->fpSHX ); if( pabyBuf[0] != 0 || pabyBuf[1] != 0 || pabyBuf[2] != 0x27 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) ) { fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); return( NULL ); } psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256 + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256; if (psSHP->nRecords != 0) psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8; if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 ) { msSetError(MS_SHPERR, "Corrupted .shp file : nRecords = %d.", "msSHPOpen()", psSHP->nRecords); fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); return( NULL ); } psSHP->nShapeType = pabyBuf[32]; if( bBigEndian ) SwapWord( 8, pabyBuf+36 ); memcpy( &dValue, pabyBuf+36, 8 ); psSHP->adBoundsMin[0] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+44 ); memcpy( &dValue, pabyBuf+44, 8 ); psSHP->adBoundsMin[1] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+52 ); memcpy( &dValue, pabyBuf+52, 8 ); psSHP->adBoundsMax[0] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+60 ); memcpy( &dValue, pabyBuf+60, 8 ); psSHP->adBoundsMax[1] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */ memcpy( &dValue, pabyBuf+68, 8 ); psSHP->adBoundsMin[2] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+76 ); memcpy( &dValue, pabyBuf+76, 8 ); psSHP->adBoundsMax[2] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* m */ memcpy( &dValue, pabyBuf+84, 8 ); psSHP->adBoundsMin[3] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+92 ); memcpy( &dValue, pabyBuf+92, 8 ); psSHP->adBoundsMax[3] = dValue; free( pabyBuf ); /* -------------------------------------------------------------------- */ /* Read the .shx file to get the offsets to each record in */ /* the .shp file. */ /* -------------------------------------------------------------------- */ psSHP->nMaxRecords = psSHP->nRecords; /* Our in-memory cache of offset information */ psSHP->panRecOffset = (int *) malloc(sizeof(int) * psSHP->nMaxRecords ); /* Our in-memory cache of size information */ psSHP->panRecSize = (int *) malloc(sizeof(int) * psSHP->nMaxRecords ); /* The completeness information for our in-memory cache */ psSHP->panRecLoaded = msAllocBitArray( 1 + (psSHP->nMaxRecords / SHX_BUFFER_PAGE) ) ; /* Is our in-memory cache completely populated? */ psSHP->panRecAllLoaded = 0; /* malloc failed? clean up and shut down */ if (psSHP->panRecOffset == NULL || psSHP->panRecSize == NULL || psSHP->panRecLoaded == NULL) { free(psSHP->panRecOffset); free(psSHP->panRecSize); free(psSHP->panRecLoaded); fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); msSetError(MS_MEMERR, "Out of memory", "msSHPOpen()"); return( NULL ); } return( psSHP ); } /************************************************************************/ /* msSHPClose() */ /* */ /* Close the .shp and .shx files. */ /************************************************************************/ void msSHPClose(SHPHandle psSHP ) { /* -------------------------------------------------------------------- */ /* Update the header if we have modified anything. */ /* -------------------------------------------------------------------- */ if( psSHP->bUpdated ) writeHeader( psSHP ); /* -------------------------------------------------------------------- */ /* Free all resources, and close files. */ /* -------------------------------------------------------------------- */ free( psSHP->panRecOffset ); free( psSHP->panRecSize ); free( psSHP->panRecLoaded ); if(psSHP->pabyRec) free(psSHP->pabyRec); if(psSHP->panParts) free(psSHP->panParts); fclose( psSHP->fpSHX ); fclose( psSHP->fpSHP ); free( psSHP ); } /************************************************************************/ /* msSHPGetInfo() */ /* */ /* Fetch general information about the shape file. */ /************************************************************************/ void msSHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType ) { if( pnEntities ) *pnEntities = psSHP->nRecords; if( pnShapeType ) *pnShapeType = psSHP->nShapeType; } /************************************************************************/ /* msSHPCreate() */ /* */ /* Create a new shape file and return a handle to the open */ /* shape file with read/write access. */ /************************************************************************/ SHPHandle msSHPCreate( const char * pszLayer, int nShapeType ) { char *pszBasename, *pszFullname; int i; FILE *fpSHP, *fpSHX; uchar abyHeader[100]; ms_int32 i32; double dValue; #ifndef USE_POINT_Z_M if( nShapeType == SHP_POLYGONZ || nShapeType == SHP_POLYGONM || nShapeType == SHP_ARCZ || nShapeType == SHP_ARCM || nShapeType == SHP_POINTZ || nShapeType == SHP_POINTM || nShapeType == SHP_MULTIPOINTZ || nShapeType == SHP_MULTIPOINTM ) { msSetError( MS_SHPERR, "Attempt to create M/Z shapefile but without having enabled Z/M support.", "msSHPCreate()" ); return NULL; } #endif /* -------------------------------------------------------------------- */ /* Establish the byte order on this system. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszLayer)+5); strcpy( pszBasename, pszLayer ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the two files so we can write their headers. */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s.shp", pszBasename ); fpSHP = fopen(pszFullname, "wb" ); if( fpSHP == NULL ) return( NULL ); sprintf( pszFullname, "%s.shx", pszBasename ); fpSHX = fopen(pszFullname, "wb" ); if( fpSHX == NULL ) return( NULL ); free( pszFullname ); /* -------------------------------------------------------------------- */ /* Prepare header block for .shp file. */ /* -------------------------------------------------------------------- */ for( i = 0; i < 100; i++ ) abyHeader[i] = 0; abyHeader[2] = 0x27; /* magic cookie */ abyHeader[3] = 0x0a; i32 = 50; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); i32 = 1000; /* version */ ByteCopy( &i32, abyHeader+28, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+28 ); i32 = nShapeType; /* shape type */ ByteCopy( &i32, abyHeader+32, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+32 ); dValue = 0.0; /* set bounds */ ByteCopy( &dValue, abyHeader+36, 8 ); ByteCopy( &dValue, abyHeader+44, 8 ); ByteCopy( &dValue, abyHeader+52, 8 ); ByteCopy( &dValue, abyHeader+60, 8 ); /* -------------------------------------------------------------------- */ /* Write .shp file header. */ /* -------------------------------------------------------------------- */ fwrite( abyHeader, 100, 1, fpSHP ); /* -------------------------------------------------------------------- */ /* Prepare, and write .shx file header. */ /* -------------------------------------------------------------------- */ i32 = 50; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); fwrite( abyHeader, 100, 1, fpSHX ); /* -------------------------------------------------------------------- */ /* Close the files, and then open them as regular existing files. */ /* -------------------------------------------------------------------- */ fclose( fpSHP ); fclose( fpSHX ); return( msSHPOpen( pszLayer, "rb+" ) ); } /************************************************************************/ /* writeBounds() */ /* */ /* Compute a bounds rectangle for a shape, and set it into the */ /* indicated location in the record. */ /************************************************************************/ static void writeBounds( uchar * pabyRec, shapeObj *shape, int nVCount ) { double dXMin, dXMax, dYMin, dYMax; int i, j; if( nVCount == 0 ) { dXMin = dYMin = dXMax = dYMax = 0.0; } else { dXMin = dXMax = shape->line[0].point[0].x; dYMin = dYMax = shape->line[0].point[0].y; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { dXMin = MS_MIN(dXMin, shape->line[i].point[j].x); dXMax = MS_MAX(dXMax, shape->line[i].point[j].x); dYMin = MS_MIN(dYMin, shape->line[i].point[j].y); dYMax = MS_MAX(dYMax, shape->line[i].point[j].y); } } } if( bBigEndian ) { SwapWord( 8, &dXMin ); SwapWord( 8, &dYMin ); SwapWord( 8, &dXMax ); SwapWord( 8, &dYMax ); } ByteCopy( &dXMin, pabyRec + 0, 8 ); ByteCopy( &dYMin, pabyRec + 8, 8 ); ByteCopy( &dXMax, pabyRec + 16, 8 ); ByteCopy( &dYMax, pabyRec + 24, 8 ); } int msSHPWritePoint(SHPHandle psSHP, pointObj *point ) { int nRecordOffset, nRecordSize=0; uchar *pabyRec; ms_int32 i32, nPoints, nParts; if( psSHP->nShapeType != SHP_POINT) return(-1); psSHP->bUpdated = MS_TRUE; /* Fill the SHX buffer if it is not already full. */ if( ! psSHP->panRecAllLoaded ) msSHXLoadAll( psSHP ); /* -------------------------------------------------------------------- */ /* Add the new entity to the in memory index. */ /* -------------------------------------------------------------------- */ psSHP->nRecords++; if( psSHP->nRecords > psSHP->nMaxRecords ) { psSHP->nMaxRecords = (int) (psSHP->nMaxRecords * 1.3 + 100); psSHP->panRecOffset = (int *) SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords ); psSHP->panRecSize = (int *) SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords ); } /* -------------------------------------------------------------------- */ /* Compute a few things. */ /* -------------------------------------------------------------------- */ nPoints = 1; nParts = 1; /* -------------------------------------------------------------------- */ /* Initialize record. */ /* -------------------------------------------------------------------- */ psSHP->panRecOffset[psSHP->nRecords-1] = nRecordOffset = psSHP->nFileSize; pabyRec = (uchar *) msSmallMalloc(nPoints * 2 * sizeof(double) + nParts * 4 + 128); /* -------------------------------------------------------------------- */ /* Write vertices for a point. */ /* -------------------------------------------------------------------- */ ByteCopy( &(point->x), pabyRec + 12, 8 ); ByteCopy( &(point->y), pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 12 ); SwapWord( 8, pabyRec + 20 ); } nRecordSize = 20; /* -------------------------------------------------------------------- */ /* Set the shape type, record number, and record size. */ /* -------------------------------------------------------------------- */ i32 = psSHP->nRecords-1+1; /* record # */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec, 4 ); i32 = nRecordSize/2; /* record size */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 4, 4 ); i32 = psSHP->nShapeType; /* shape type */ if( bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 8, 4 ); /* -------------------------------------------------------------------- */ /* Write out record. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, nRecordOffset, 0 ); fwrite( pabyRec, nRecordSize+8, 1, psSHP->fpSHP ); free( pabyRec ); psSHP->panRecSize[psSHP->nRecords-1] = nRecordSize; psSHP->nFileSize += nRecordSize + 8; /* -------------------------------------------------------------------- */ /* Expand file wide bounds based on this shape. */ /* -------------------------------------------------------------------- */ if( psSHP->nRecords == 1 ) { psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = point->x; psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = point->y; } else { psSHP->adBoundsMin[0] = MS_MIN(psSHP->adBoundsMin[0], point->x); psSHP->adBoundsMin[1] = MS_MIN(psSHP->adBoundsMin[1], point->y); psSHP->adBoundsMax[0] = MS_MAX(psSHP->adBoundsMax[0], point->x); psSHP->adBoundsMax[1] = MS_MAX(psSHP->adBoundsMax[1], point->y); } return( psSHP->nRecords - 1 ); } int msSHPWriteShape(SHPHandle psSHP, shapeObj *shape ) { int nRecordOffset, i, j, k, nRecordSize=0; uchar *pabyRec; int nShapeType; ms_int32 i32, nPoints, nParts; #ifdef USE_POINT_Z_M double dfMMin, dfMMax = 0; #endif psSHP->bUpdated = MS_TRUE; /* Fill the SHX buffer if it is not already full. */ if( ! psSHP->panRecAllLoaded ) msSHXLoadAll( psSHP ); /* -------------------------------------------------------------------- */ /* Add the new entity to the in memory index. */ /* -------------------------------------------------------------------- */ psSHP->nRecords++; if( psSHP->nRecords > psSHP->nMaxRecords ) { psSHP->nMaxRecords = (int) (psSHP->nMaxRecords * 1.3 + 100); psSHP->panRecOffset = (int *) SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords ); psSHP->panRecSize = (int *) SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords ); } /* -------------------------------------------------------------------- */ /* Compute a few things. */ /* -------------------------------------------------------------------- */ nPoints = 0; for(i=0; inumlines; i++) nPoints += shape->line[i].numpoints; nParts = shape->numlines; /* -------------------------------------------------------------------- */ /* Initialize record. */ /* -------------------------------------------------------------------- */ psSHP->panRecOffset[psSHP->nRecords-1] = nRecordOffset = psSHP->nFileSize; pabyRec = (uchar *) msSmallMalloc(nPoints * 4 * sizeof(double) + nParts * 8 + 128); nShapeType = psSHP->nShapeType; if (shape->type == MS_SHAPE_NULL) { nShapeType = 0; nRecordSize = 12; } /* -------------------------------------------------------------------- */ /* Write vertices for a Polygon or Arc. */ /* -------------------------------------------------------------------- */ else if(psSHP->nShapeType == SHP_POLYGON || psSHP->nShapeType == SHP_ARC || psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM || psSHP->nShapeType == SHP_ARCZ || psSHP->nShapeType == SHP_POLYGONZ) { ms_int32 t_nParts, t_nPoints, partSize; t_nParts = nParts; t_nPoints = nPoints; writeBounds( pabyRec + 12, shape, t_nPoints ); if( bBigEndian ) { nPoints = SWAP_FOUR_BYTES(nPoints); nParts = SWAP_FOUR_BYTES(nParts); } ByteCopy( &nPoints, pabyRec + 40 + 8, 4 ); ByteCopy( &nParts, pabyRec + 36 + 8, 4 ); partSize = 0; /* first part always starts at 0 */ ByteCopy( &partSize, pabyRec + 44 + 8 + 4*0, 4 ); if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*0); for( i = 1; i < t_nParts; i++ ) { partSize += shape->line[i-1].numpoints; ByteCopy( &partSize, pabyRec + 44 + 8 + 4*i, 4 ); if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i); } k = 0; /* overall point counter */ for( i = 0; i < shape->numlines; i++ ) { for( j = 0; j < shape->line[i].numpoints; j++ ) { ByteCopy( &(shape->line[i].point[j].x), pabyRec + 44 + 4*t_nParts + 8 + k * 16, 8 ); ByteCopy( &(shape->line[i].point[j].y), pabyRec + 44 + 4*t_nParts + 8 + k * 16 + 8, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 44+4*t_nParts+8+k*16 ); SwapWord( 8, pabyRec + 44+4*t_nParts+8+k*16+8 ); } k++; } } nRecordSize = 44 + 4*t_nParts + 16 * t_nPoints; #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* measured shape : polygon and arc. */ /* -------------------------------------------------------------------- */ if(psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM) { dfMMin = shape->line[0].point[0].m; dfMMax = shape->line[shape->numlines-1].point[shape->line[shape->numlines-1].numpoints-1].m; nRecordSize = 44 + 4*t_nParts + 8 + (t_nPoints* 16); ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->numlines; i++ ) { for( j = 0; j < shape->line[i].numpoints; j++ ) { ByteCopy( &(shape->line[i].point[j].m), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } } /* -------------------------------------------------------------------- */ /* Polygon. Arc with Z */ /* -------------------------------------------------------------------- */ if (psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_ARCZ || psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM) { dfMMin = shape->line[0].point[0].z; dfMMax = shape->line[shape->numlines-1].point[shape->line[shape->numlines-1].numpoints-1].z; nRecordSize = 44 + 4*t_nParts + 8 + (t_nPoints* 16); ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->numlines; i++ ) { for( j = 0; j < shape->line[i].numpoints; j++ ) { ByteCopy( &(shape->line[i].point[j].z), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } } #endif /* def USE_POINT_Z_M */ } /* -------------------------------------------------------------------- */ /* Write vertices for a MultiPoint. */ /* -------------------------------------------------------------------- */ else if( psSHP->nShapeType == SHP_MULTIPOINT || psSHP->nShapeType == SHP_MULTIPOINTM || psSHP->nShapeType == SHP_MULTIPOINTZ) { ms_int32 t_nPoints; t_nPoints = nPoints; writeBounds( pabyRec + 12, shape, nPoints ); if( bBigEndian ) nPoints = SWAP_FOUR_BYTES(nPoints); ByteCopy( &nPoints, pabyRec + 44, 4 ); for( i = 0; i < shape->line[0].numpoints; i++ ) { ByteCopy( &(shape->line[0].point[i].x), pabyRec + 48 + i*16, 8 ); ByteCopy( &(shape->line[0].point[i].y), pabyRec + 48 + i*16 + 8, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 48 + i*16 ); SwapWord( 8, pabyRec + 48 + i*16 + 8 ); } } nRecordSize = 40 + 16 * t_nPoints; #ifdef USE_POINT_Z_M if (psSHP->nShapeType == SHP_MULTIPOINTM) { dfMMin = shape->line[0].point[0].m; dfMMax = shape->line[0].point[shape->line[0].numpoints-1].m; ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->line[0].numpoints; i++ ) { ByteCopy( &(shape->line[0].point[i].m), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } if (psSHP->nShapeType == SHP_MULTIPOINTZ) { dfMMin = shape->line[0].point[0].z; dfMMax = shape->line[0].point[shape->line[0].numpoints-1].z; ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->line[0].numpoints; i++ ) { ByteCopy( &(shape->line[0].point[i].z), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } #endif /* USE_POINT_Z_M */ } /* -------------------------------------------------------------------- */ /* Write vertices for a point. */ /* -------------------------------------------------------------------- */ else if( psSHP->nShapeType == SHP_POINT || psSHP->nShapeType == SHP_POINTM || psSHP->nShapeType == SHP_POINTZ) { ByteCopy( &(shape->line[0].point[0].x), pabyRec + 12, 8 ); ByteCopy( &(shape->line[0].point[0].y), pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 12 ); SwapWord( 8, pabyRec + 20 ); } nRecordSize = 20; #ifdef USE_POINT_Z_M if (psSHP->nShapeType == SHP_POINTM) { ByteCopy( &(shape->line[0].point[0].m), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } if (psSHP->nShapeType == SHP_POINTZ) { ByteCopy( &(shape->line[0].point[0].z), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } #endif /* USE_POINT_Z_M */ } /* -------------------------------------------------------------------- */ /* Set the shape type, record number, and record size. */ /* -------------------------------------------------------------------- */ i32 = psSHP->nRecords-1+1; /* record # */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec, 4 ); i32 = nRecordSize/2; /* record size */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 4, 4 ); i32 = nShapeType; /* shape type */ if( bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 8, 4 ); /* -------------------------------------------------------------------- */ /* Write out record. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, nRecordOffset, 0 ); fwrite( pabyRec, nRecordSize+8, 1, psSHP->fpSHP ); free( pabyRec ); psSHP->panRecSize[psSHP->nRecords-1] = nRecordSize; psSHP->nFileSize += nRecordSize + 8; /* -------------------------------------------------------------------- */ /* Expand file wide bounds based on this shape. */ /* -------------------------------------------------------------------- */ if( psSHP->nRecords == 1 ) { psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = shape->line[0].point[0].x; psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = shape->line[0].point[0].y; #ifdef USE_POINT_Z_M psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = shape->line[0].point[0].z; psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = shape->line[0].point[0].m; #endif } for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { psSHP->adBoundsMin[0] = MS_MIN(psSHP->adBoundsMin[0], shape->line[i].point[j].x); psSHP->adBoundsMin[1] = MS_MIN(psSHP->adBoundsMin[1], shape->line[i].point[j].y); #ifdef USE_POINT_Z_M psSHP->adBoundsMin[2] = MS_MIN(psSHP->adBoundsMin[2], shape->line[i].point[j].z); psSHP->adBoundsMin[3] = MS_MIN(psSHP->adBoundsMin[3], shape->line[i].point[j].m); #endif psSHP->adBoundsMax[0] = MS_MAX(psSHP->adBoundsMax[0], shape->line[i].point[j].x); psSHP->adBoundsMax[1] = MS_MAX(psSHP->adBoundsMax[1], shape->line[i].point[j].y); #ifdef USE_POINT_Z_M psSHP->adBoundsMax[2] = MS_MAX(psSHP->adBoundsMax[2], shape->line[i].point[j].z); psSHP->adBoundsMax[3] = MS_MAX(psSHP->adBoundsMax[3], shape->line[i].point[j].m); #endif } } return( psSHP->nRecords - 1 ); } /* ** msSHPReadAllocateBuffer() - Ensure our record buffer is large enough. */ static int msSHPReadAllocateBuffer( SHPHandle psSHP, int hEntity, const char* pszCallingFunction) { int nEntitySize = msSHXReadSize(psSHP, hEntity) + 8; /* -------------------------------------------------------------------- */ /* Ensure our record buffer is large enough. */ /* -------------------------------------------------------------------- */ if( nEntitySize > psSHP->nBufSize ) { psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize); if (psSHP->pabyRec == NULL) { /* Reallocate previous successfull size for following features */ psSHP->pabyRec = msSmallMalloc(psSHP->nBufSize); msSetError(MS_MEMERR, "Out of memory. Cannot allocate %d bytes. Probably broken shapefile at feature %d", pszCallingFunction, nEntitySize, hEntity); return(MS_FAILURE); } psSHP->nBufSize = nEntitySize; } if (psSHP->pabyRec == NULL) { msSetError(MS_MEMERR, "Out of memory", pszCallingFunction); return(MS_FAILURE); } return MS_SUCCESS; } /* ** msSHPReadPoint() - Reads a single point from a POINT shape file. */ int msSHPReadPoint( SHPHandle psSHP, int hEntity, pointObj *point ) { int nEntitySize; /* -------------------------------------------------------------------- */ /* Only valid for point shapefiles */ /* -------------------------------------------------------------------- */ if( psSHP->nShapeType != SHP_POINT ) { msSetError(MS_SHPERR, "msSHPReadPoint only operates on point shapefiles.", "msSHPReadPoint()"); return(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ /* -------------------------------------------------------------------- */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) { msSetError(MS_SHPERR, "Record index out of bounds.", "msSHPReadPoint()"); return(MS_FAILURE); } nEntitySize = msSHXReadSize( psSHP, hEntity) + 8; if( msSHXReadSize( psSHP, hEntity) == 4 ) { msSetError(MS_SHPERR, "NULL feature encountered.", "msSHPReadPoint()"); return(MS_FAILURE); } else if ( nEntitySize < 28 ) { msSetError(MS_SHPERR, "Corrupted feature encountered. hEntity=%d, nEntitySize=%d", "msSHPReadPoint()", hEntity, nEntitySize); return(MS_FAILURE); } if (msSHPReadAllocateBuffer(psSHP, hEntity, "msSHPReadPoint()") == MS_FAILURE) { return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Read the record. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, msSHXReadOffset( psSHP, hEntity), 0 ); fread( psSHP->pabyRec, nEntitySize, 1, psSHP->fpSHP ); memcpy( &(point->x), psSHP->pabyRec + 12, 8 ); memcpy( &(point->y), psSHP->pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, &(point->x)); SwapWord( 8, &(point->y)); } return(MS_SUCCESS); } /* ** msSHXLoadPage() ** ** The SHX tells us what the byte offsets of the shapes in the SHP file are. ** We read the SHX file in ~8K pages and store those pages in memory for ** successive accesses during the reading cycle (first bounds are read, ** then entire shapes). Each time we read a page, we mark it as read. */ int msSHXLoadPage( SHPHandle psSHP, int shxBufferPage ) { int i; /* Each SHX record is 8 bytes long (two ints), hence our buffer size. */ char buffer[SHX_BUFFER_PAGE * 8]; /* Validate the page number. */ if( shxBufferPage < 0 ) return(MS_FAILURE); /* The SHX file starts with 100 bytes of header, skip that. */ fseek( psSHP->fpSHX, 100 + shxBufferPage * SHX_BUFFER_PAGE * 8, 0 ); fread( buffer, 8, SHX_BUFFER_PAGE, psSHP->fpSHX ); /* Copy the buffer contents out into the working arrays. */ for( i = 0; i < SHX_BUFFER_PAGE; i++ ) { int tmpOffset, tmpSize; /* Don't write information past the end of the arrays, please. */ if(psSHP->nRecords <= (shxBufferPage * SHX_BUFFER_PAGE + i) ) break; memcpy( &tmpOffset, (buffer + (8*i)), 4); memcpy( &tmpSize, (buffer + (8*i) + 4), 4); /* SHX uses big endian numbers for the offsets, so we have to flip them */ /* if we are a little endian machine. */ if( !bBigEndian ) { tmpOffset = SWAP_FOUR_BYTES(tmpOffset); tmpSize = SWAP_FOUR_BYTES(tmpSize); } /* SHX stores the offsets in 2 byte units, so we double them to get */ /* an offset in bytes. */ tmpOffset = tmpOffset * 2; tmpSize = tmpSize * 2; /* Write the answer into the working arrays on the SHPHandle */ psSHP->panRecOffset[shxBufferPage * SHX_BUFFER_PAGE + i] = tmpOffset; psSHP->panRecSize[shxBufferPage * SHX_BUFFER_PAGE + i] = tmpSize; } msSetBit(psSHP->panRecLoaded, shxBufferPage, 1); return(MS_SUCCESS); } int msSHXLoadAll( SHPHandle psSHP ) { int i; uchar *pabyBuf; pabyBuf = (uchar *) msSmallMalloc(8 * psSHP->nRecords ); fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ); for( i = 0; i < psSHP->nRecords; i++ ) { ms_int32 nOffset, nLength; memcpy( &nOffset, pabyBuf + i * 8, 4 ); memcpy( &nLength, pabyBuf + i * 8 + 4, 4 ); if( !bBigEndian ) { nOffset = SWAP_FOUR_BYTES( nOffset ); nLength = SWAP_FOUR_BYTES( nLength ); } psSHP->panRecOffset[i] = nOffset*2; psSHP->panRecSize[i] = nLength*2; } free(pabyBuf); psSHP->panRecAllLoaded = 1; return(MS_SUCCESS); } int msSHXReadOffset( SHPHandle psSHP, int hEntity ) { int shxBufferPage = hEntity / SHX_BUFFER_PAGE; /* Validate the record/entity number. */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) return(MS_FAILURE); if( ! (psSHP->panRecAllLoaded || msGetBit(psSHP->panRecLoaded, shxBufferPage)) ) { msSHXLoadPage( psSHP, shxBufferPage ); } return psSHP->panRecOffset[hEntity]; } int msSHXReadSize( SHPHandle psSHP, int hEntity ) { int shxBufferPage = hEntity / SHX_BUFFER_PAGE; /* Validate the record/entity number. */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) return(MS_FAILURE); if( ! (psSHP->panRecAllLoaded || msGetBit(psSHP->panRecLoaded, shxBufferPage)) ) { msSHXLoadPage( psSHP, shxBufferPage ); } return psSHP->panRecSize[hEntity]; } /* ** msSHPReadShape() - Reads the vertices for one shape from a shape file. */ void msSHPReadShape( SHPHandle psSHP, int hEntity, shapeObj *shape ) { int i, j, k; #ifdef USE_POINT_Z_M int nOffset = 0; #endif int nEntitySize, nRequiredSize; msInitShape(shape); /* initialize the shape */ /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ /* -------------------------------------------------------------------- */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) return; if( msSHXReadSize(psSHP, hEntity) == 4 ) { shape->type = MS_SHAPE_NULL; return; } nEntitySize = msSHXReadSize(psSHP, hEntity) + 8; if (msSHPReadAllocateBuffer(psSHP, hEntity, "msSHPReadShape()") == MS_FAILURE) { shape->type = MS_SHAPE_NULL; return; } /* -------------------------------------------------------------------- */ /* Read the record. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, msSHXReadOffset(psSHP, hEntity), 0 ); fread( psSHP->pabyRec, nEntitySize, 1, psSHP->fpSHP ); /* -------------------------------------------------------------------- */ /* Extract vertices for a Polygon or Arc. */ /* -------------------------------------------------------------------- */ if( psSHP->nShapeType == SHP_POLYGON || psSHP->nShapeType == SHP_ARC || psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM || psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_ARCZ) { ms_int32 nPoints, nParts; if (nEntitySize < 40 + 8 + 4) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. hEntity = %d, nEntitySize=%d", "msSHPReadShape()", hEntity, nEntitySize); return; } /* copy the bounding box */ memcpy( &shape->bounds.minx, psSHP->pabyRec + 8 + 4, 8 ); memcpy( &shape->bounds.miny, psSHP->pabyRec + 8 + 12, 8 ); memcpy( &shape->bounds.maxx, psSHP->pabyRec + 8 + 20, 8 ); memcpy( &shape->bounds.maxy, psSHP->pabyRec + 8 + 28, 8 ); if( bBigEndian ) { SwapWord( 8, &shape->bounds.minx); SwapWord( 8, &shape->bounds.miny); SwapWord( 8, &shape->bounds.maxx); SwapWord( 8, &shape->bounds.maxy); } memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 ); memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 ); if( bBigEndian ) { nPoints = SWAP_FOUR_BYTES(nPoints); nParts = SWAP_FOUR_BYTES(nParts); } if (nPoints < 0 || nParts < 0 || nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. hEntity = %d, nPoints =%d, nParts = %d", "msSHPReadShape()", hEntity, nPoints, nParts); return; } /* -------------------------------------------------------------------- */ /* Copy out the part array from the record. */ /* -------------------------------------------------------------------- */ if( psSHP->nPartMax < nParts ) { psSHP->panParts = (int *) SfRealloc(psSHP->panParts, nParts * sizeof(int) ); if (psSHP->panParts == NULL) { /* Reallocate previous successfull size for following features */ psSHP->panParts = (int *) msSmallMalloc(psSHP->nPartMax * sizeof(int) ); shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory. Cannot allocate %d bytes. Probably broken shapefile at feature %d", "msSHPReadShape()", (int)(nParts * sizeof(int)), hEntity); return; } psSHP->nPartMax = nParts; } if (psSHP->panParts == NULL) { shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } /* With the previous checks on nPoints and nParts, */ /* we should not overflow here and after */ /* since 50 M * (16 + 8 + 8) = 1 600 MB */ if (44 + 8 + 4 * nParts + 16 * nPoints > nEntitySize) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.", "msSHPReadShape()", hEntity, nPoints, nParts); return; } memcpy( psSHP->panParts, psSHP->pabyRec + 44 + 8, 4 * nParts ); if( bBigEndian ) { for( i = 0; i < nParts; i++ ) { *(psSHP->panParts+i) = SWAP_FOUR_BYTES(*(psSHP->panParts+i)); } } /* -------------------------------------------------------------------- */ /* Fill the shape structure. */ /* -------------------------------------------------------------------- */ shape->line = (lineObj *)malloc(sizeof(lineObj)*nParts); MS_CHECK_ALLOC_NO_RET(shape->line, sizeof(lineObj)*nParts); shape->numlines = nParts; k = 0; /* overall point counter */ for( i = 0; i < nParts; i++) { if( i == nParts-1) shape->line[i].numpoints = nPoints - psSHP->panParts[i]; else shape->line[i].numpoints = psSHP->panParts[i+1] - psSHP->panParts[i]; if (shape->line[i].numpoints <= 0) { msSetError(MS_SHPERR, "Corrupted .shp file : shape %d, shape->line[%d].numpoints=%d", "msSHPReadShape()", hEntity, i, shape->line[i].numpoints); while(--i >= 0) free(shape->line[i].point); free(shape->line); shape->line = NULL; shape->numlines = 0; shape->type = MS_SHAPE_NULL; return; } if( (shape->line[i].point = (pointObj *)malloc(sizeof(pointObj)*shape->line[i].numpoints)) == NULL ) { while(--i >= 0) free(shape->line[i].point); free(shape->line); shape->numlines = 0; shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } /* nOffset = 44 + 8 + 4*nParts; */ for( j = 0; j < shape->line[i].numpoints; j++ ) { memcpy(&(shape->line[i].point[j].x), psSHP->pabyRec + 44 + 4*nParts + 8 + k * 16, 8 ); memcpy(&(shape->line[i].point[j].y), psSHP->pabyRec + 44 + 4*nParts + 8 + k * 16 + 8, 8 ); if( bBigEndian ) { SwapWord( 8, &(shape->line[i].point[j].x) ); SwapWord( 8, &(shape->line[i].point[j].y) ); } #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* Polygon, Arc with Z values. */ /* -------------------------------------------------------------------- */ shape->line[i].point[j].z = 0.0; /* initialize */ if (psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_ARCZ) { nOffset = 44 + 8 + (4*nParts) + (16*nPoints) ; if( nEntitySize >= nOffset + 16 + 8*nPoints ) { memcpy(&(shape->line[i].point[j].z), psSHP->pabyRec + nOffset + 16 + k*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[i].point[j].z) ); } } /* -------------------------------------------------------------------- */ /* Measured arc and polygon support. */ /* -------------------------------------------------------------------- */ shape->line[i].point[j].m = 0; /* initialize */ if (psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM) { nOffset = 44 + 8 + (4*nParts) + (16*nPoints) ; if( nEntitySize >= nOffset + 16 + 8*nPoints ) { memcpy(&(shape->line[i].point[j].m), psSHP->pabyRec + nOffset + 16 + k*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[i].point[j].m) ); } } #endif /* USE_POINT_Z_M */ k++; } } if(psSHP->nShapeType == SHP_POLYGON || psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_POLYGONM) shape->type = MS_SHAPE_POLYGON; else shape->type = MS_SHAPE_LINE; } /* -------------------------------------------------------------------- */ /* Extract a MultiPoint. */ /* -------------------------------------------------------------------- */ else if( psSHP->nShapeType == SHP_MULTIPOINT || psSHP->nShapeType == SHP_MULTIPOINTM || psSHP->nShapeType == SHP_MULTIPOINTZ) { ms_int32 nPoints; if (nEntitySize < 44 + 4) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. recSize of feature %d=%d", "msSHPReadShape()", hEntity, msSHXReadSize(psSHP, hEntity)); return; } /* copy the bounding box */ memcpy( &shape->bounds.minx, psSHP->pabyRec + 8 + 4, 8 ); memcpy( &shape->bounds.miny, psSHP->pabyRec + 8 + 12, 8 ); memcpy( &shape->bounds.maxx, psSHP->pabyRec + 8 + 20, 8 ); memcpy( &shape->bounds.maxy, psSHP->pabyRec + 8 + 28, 8 ); if( bBigEndian ) { SwapWord( 8, &shape->bounds.minx); SwapWord( 8, &shape->bounds.miny); SwapWord( 8, &shape->bounds.maxx); SwapWord( 8, &shape->bounds.maxy); } memcpy( &nPoints, psSHP->pabyRec + 44, 4 ); if( bBigEndian ) nPoints = SWAP_FOUR_BYTES(nPoints); /* -------------------------------------------------------------------- */ /* Fill the shape structure. */ /* -------------------------------------------------------------------- */ if( (shape->line = (lineObj *)malloc(sizeof(lineObj))) == NULL ) { shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } if (nPoints < 0 || nPoints > 50 * 1000 * 1000) { free(shape->line); shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted .shp file : shape %d, nPoints=%d.", "msSHPReadShape()", hEntity, nPoints); return; } nRequiredSize = 48 + nPoints * 16; if (psSHP->nShapeType == SHP_MULTIPOINTZ || psSHP->nShapeType == SHP_MULTIPOINTM) nRequiredSize += 16 + nPoints * 8; if (nRequiredSize > nEntitySize) { free(shape->line); shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d", "msSHPReadShape()", hEntity, nPoints, nEntitySize); return; } shape->numlines = 1; shape->line[0].numpoints = nPoints; shape->line[0].point = (pointObj *) malloc( nPoints * sizeof(pointObj) ); if (shape->line[0].point == NULL) { free(shape->line); shape->numlines = 0; shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } for( i = 0; i < nPoints; i++ ) { memcpy(&(shape->line[0].point[i].x), psSHP->pabyRec + 48 + 16 * i, 8 ); memcpy(&(shape->line[0].point[i].y), psSHP->pabyRec + 48 + 16 * i + 8, 8 ); if( bBigEndian ) { SwapWord( 8, &(shape->line[0].point[i].x) ); SwapWord( 8, &(shape->line[0].point[i].y) ); } #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* MulipointZ */ /* -------------------------------------------------------------------- */ shape->line[0].point[i].z = 0; /* initialize */ if (psSHP->nShapeType == SHP_MULTIPOINTZ) { nOffset = 48 + 16*nPoints; memcpy(&(shape->line[0].point[i].z), psSHP->pabyRec + nOffset + 16 + i*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[i].z)); } /* -------------------------------------------------------------------- */ /* Measured shape : multipont. */ /* -------------------------------------------------------------------- */ shape->line[0].point[i].m = 0; /* initialize */ if (psSHP->nShapeType == SHP_MULTIPOINTM) { nOffset = 48 + 16*nPoints; memcpy(&(shape->line[0].point[i].m), psSHP->pabyRec + nOffset + 16 + i*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[i].m)); } #endif /* USE_POINT_Z_M */ } shape->type = MS_SHAPE_POINT; } /* -------------------------------------------------------------------- */ /* Extract a Point. */ /* -------------------------------------------------------------------- */ else if(psSHP->nShapeType == SHP_POINT || psSHP->nShapeType == SHP_POINTM || psSHP->nShapeType == SHP_POINTZ) { if (nEntitySize < 20 + 8) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. recSize of feature %d=%d", "msSHPReadShape()", hEntity, msSHXReadSize(psSHP, hEntity)); return; } /* -------------------------------------------------------------------- */ /* Fill the shape structure. */ /* -------------------------------------------------------------------- */ shape->line = (lineObj *)malloc(sizeof(lineObj)); MS_CHECK_ALLOC_NO_RET(shape->line, sizeof(lineObj)); shape->numlines = 1; shape->line[0].numpoints = 1; shape->line[0].point = (pointObj *) msSmallMalloc(sizeof(pointObj)); memcpy( &(shape->line[0].point[0].x), psSHP->pabyRec + 12, 8 ); memcpy( &(shape->line[0].point[0].y), psSHP->pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, &(shape->line[0].point[0].x)); SwapWord( 8, &(shape->line[0].point[0].y)); } #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* PointZ */ /* -------------------------------------------------------------------- */ shape->line[0].point[0].z = 0; /* initialize */ if (psSHP->nShapeType == SHP_POINTZ) { nOffset = 20 + 8; if( nEntitySize >= nOffset + 8 ) { memcpy(&(shape->line[0].point[0].z), psSHP->pabyRec + nOffset, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[0].z)); } } /* -------------------------------------------------------------------- */ /* Measured support : point. */ /* -------------------------------------------------------------------- */ shape->line[0].point[0].m = 0; /* initialize */ if (psSHP->nShapeType == SHP_POINTM) { nOffset = 20 + 8; if( nEntitySize >= nOffset + 8 ) { memcpy(&(shape->line[0].point[0].m), psSHP->pabyRec + nOffset, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[0].m)); } } #endif /* USE_POINT_Z_M */ /* set the bounding box to the point */ shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y; shape->type = MS_SHAPE_POINT; } shape->index = hEntity; return; } int msSHPReadBounds( SHPHandle psSHP, int hEntity, rectObj *padBounds) { /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ /* -------------------------------------------------------------------- */ if( psSHP->nRecords <= 0 || hEntity < -1 || hEntity >= psSHP->nRecords ) { padBounds->minx = padBounds->miny = padBounds->maxx = padBounds->maxy = 0.0; return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* If the entity is -1 we fetch the bounds for the whole file. */ /* -------------------------------------------------------------------- */ if( hEntity == -1 ) { padBounds->minx = psSHP->adBoundsMin[0]; padBounds->miny = psSHP->adBoundsMin[1]; padBounds->maxx = psSHP->adBoundsMax[0]; padBounds->maxy = psSHP->adBoundsMax[1]; } else { if( msSHXReadSize(psSHP, hEntity) == 4 ) { /* NULL shape */ padBounds->minx = padBounds->miny = padBounds->maxx = padBounds->maxy = 0.0; return MS_FAILURE; } if( psSHP->nShapeType != SHP_POINT && psSHP->nShapeType != SHP_POINTZ && psSHP->nShapeType != SHP_POINTM) { fseek( psSHP->fpSHP, msSHXReadOffset(psSHP, hEntity) + 12, 0 ); fread( padBounds, sizeof(double)*4, 1, psSHP->fpSHP ); if( bBigEndian ) { SwapWord( 8, &(padBounds->minx) ); SwapWord( 8, &(padBounds->miny) ); SwapWord( 8, &(padBounds->maxx) ); SwapWord( 8, &(padBounds->maxy) ); } if(msIsNan(padBounds->minx)) { /* empty shape */ padBounds->minx = padBounds->miny = padBounds->maxx = padBounds->maxy = 0.0; return MS_FAILURE; } } else { /* -------------------------------------------------------------------- */ /* For points we fetch the point, and duplicate it as the */ /* minimum and maximum bound. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, msSHXReadOffset(psSHP, hEntity) + 12, 0 ); fread( padBounds, sizeof(double)*2, 1, psSHP->fpSHP ); if( bBigEndian ) { SwapWord( 8, &(padBounds->minx) ); SwapWord( 8, &(padBounds->miny) ); } padBounds->maxx = padBounds->minx; padBounds->maxy = padBounds->miny; } } return MS_SUCCESS; } int msShapefileOpen(shapefileObj *shpfile, char *mode, char *filename, int log_failures) { int i; char *dbfFilename; size_t bufferSize = 0; if(!filename) { if( log_failures ) msSetError(MS_IOERR, "No (NULL) filename provided.", "msShapefileOpen()"); return(-1); } /* initialize a few things */ shpfile->status = NULL; shpfile->lastshape = -1; shpfile->isopen = MS_FALSE; /* open the shapefile file (appending ok) and get basic info */ if(!mode) shpfile->hSHP = msSHPOpen( filename, "rb"); else shpfile->hSHP = msSHPOpen( filename, mode); if(!shpfile->hSHP) { if( log_failures ) msSetError(MS_IOERR, "(%s)", "msShapefileOpen()", filename); return(-1); } strlcpy(shpfile->source, filename, sizeof(shpfile->source)); /* load some information about this shapefile */ msSHPGetInfo( shpfile->hSHP, &shpfile->numshapes, &shpfile->type); msSHPReadBounds( shpfile->hSHP, -1, &(shpfile->bounds)); bufferSize = strlen(filename)+5; dbfFilename = (char *)msSmallMalloc(bufferSize); dbfFilename[0] = '\0'; strcpy(dbfFilename, filename); /* clean off any extention the filename might have */ for (i = strlen(dbfFilename) - 1; i > 0 && dbfFilename[i] != '.' && dbfFilename[i] != '/' && dbfFilename[i] != '\\'; i-- ) {} if( dbfFilename[i] == '.' ) dbfFilename[i] = '\0'; strlcat(dbfFilename, ".dbf", bufferSize); shpfile->hDBF = msDBFOpen(dbfFilename, "rb"); if(!shpfile->hDBF) { if( log_failures ) msSetError(MS_IOERR, "(%s)", "msShapefileOpen()", dbfFilename); free(dbfFilename); return(-1); } free(dbfFilename); shpfile->isopen = MS_TRUE; return(0); /* all o.k. */ } /* Creates a new shapefile */ int msShapefileCreate(shapefileObj *shpfile, char *filename, int type) { if(type != SHP_POINT && type != SHP_MULTIPOINT && type != SHP_ARC && type != SHP_POLYGON && type != SHP_POINTM && type != SHP_MULTIPOINTM && type != SHP_ARCM && type != SHP_POLYGONM && type != SHP_POINTZ && type != SHP_MULTIPOINTZ && type != SHP_ARCZ && type != SHP_POLYGONZ) { msSetError(MS_SHPERR, "Invalid shape type.", "msNewSHPFile()"); return(-1); } /* create the spatial portion */ shpfile->hSHP = msSHPCreate(filename, type); if(!shpfile->hSHP) { msSetError(MS_IOERR, "(%s)", "msNewSHPFile()",filename); return(-1); } /* retrieve a few things about this shapefile */ msSHPGetInfo( shpfile->hSHP, &shpfile->numshapes, &shpfile->type); msSHPReadBounds( shpfile->hSHP, -1, &(shpfile->bounds)); /* initialize a few other things */ shpfile->status = NULL; shpfile->lastshape = -1; shpfile->isopen = MS_TRUE; shpfile->hDBF = NULL; /* XBase file is NOT created here... */ return(0); } void msShapefileClose(shapefileObj *shpfile) { if (shpfile && shpfile->isopen == MS_TRUE) { /* Silently return if called with NULL shpfile by freeLayer() */ if(shpfile->hSHP) msSHPClose(shpfile->hSHP); if(shpfile->hDBF) msDBFClose(shpfile->hDBF); if(shpfile->status) free(shpfile->status); shpfile->isopen = MS_FALSE; } } /* status array lives in the shpfile, can return MS_SUCCESS/MS_FAILURE/MS_DONE */ int msShapefileWhichShapes(shapefileObj *shpfile, rectObj rect, int debug) { int i; rectObj shaperect; char *filename; char *sourcename = 0; /* shape file source string from map file */ char *s = 0; /* pointer to start of '.shp' in source string */ if(shpfile->status) { free(shpfile->status); shpfile->status = NULL; } shpfile->statusbounds = rect; /* save the search extent */ /* rect and shapefile DON'T overlap... */ if(msRectOverlap(&shpfile->bounds, &rect) != MS_TRUE) return(MS_DONE); if(msRectContained(&shpfile->bounds, &rect) == MS_TRUE) { shpfile->status = msAllocBitArray(shpfile->numshapes); if(!shpfile->status) { msSetError(MS_MEMERR, NULL, "msShapefileWhichShapes()"); return(MS_FAILURE); } msSetAllBits(shpfile->status, shpfile->numshapes, 1); } else { /* deal with case where sourcename is of the form 'file.shp' */ sourcename = msStrdup(shpfile->source); s = strstr(sourcename, ".shp"); if( s ) *s = '\0'; else { s = strstr(sourcename, ".SHP"); if( s ) *s = '\0'; } filename = (char *)malloc(strlen(sourcename)+strlen(MS_INDEX_EXTENSION)+1); MS_CHECK_ALLOC(filename, strlen(sourcename)+strlen(MS_INDEX_EXTENSION)+1, MS_FAILURE); sprintf(filename, "%s%s", sourcename, MS_INDEX_EXTENSION); shpfile->status = msSearchDiskTree(filename, rect, debug); free(filename); free(sourcename); if(shpfile->status) { /* index */ msFilterTreeSearch(shpfile, shpfile->status, rect); } else { /* no index */ shpfile->status = msAllocBitArray(shpfile->numshapes); if(!shpfile->status) { msSetError(MS_MEMERR, NULL, "msShapefileWhichShapes()"); return(MS_FAILURE); } for(i=0; inumshapes; i++) { if(msSHPReadBounds(shpfile->hSHP, i, &shaperect) == MS_SUCCESS) if(msRectOverlap(&shaperect, &rect) == MS_TRUE) msSetBit(shpfile->status, i, 1); } } } shpfile->lastshape = -1; return(MS_SUCCESS); /* success */ } /* Return the absolute path to the given layer's tileindex file's directory */ void msTileIndexAbsoluteDir(char *tiFileAbsDir, layerObj *layer) { char tiFileAbsPath[MS_MAXPATHLEN]; char *tiFileAbsDirTmp=NULL; msBuildPath(tiFileAbsPath, layer->map->mappath, layer->tileindex); /* absolute path to tileindex file */ tiFileAbsDirTmp = msGetPath(tiFileAbsPath); /* tileindex file's directory */ strlcpy(tiFileAbsDir, tiFileAbsDirTmp, MS_MAXPATHLEN); free(tiFileAbsDirTmp); } /* ** Build possible paths we might find the tile file at: ** map dir + shape path + filename? ** tile dir + shape path + filename? ** map dir + filename? ** ** Returns ** MS_SUCCESS - found a file ** MS_FAILURE - no file, and map is configured to fail on missing ** MS_DONE - no file, and map is configured to continue on missing */ int msTiledSHPTryOpen(shapefileObj *shpfile, layerObj *layer, char *tiFileAbsDir, char *filename) { char szPath[MS_MAXPATHLEN]; int ignore_missing = msMapIgnoreMissingData(layer->map); int log_failures = MS_TRUE; if( ignore_missing == MS_MISSING_DATA_IGNORE ) log_failures = MS_FALSE; if(msShapefileOpen(shpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, filename), log_failures) == -1) { if(msShapefileOpen(shpfile, "rb", msBuildPath3(szPath, tiFileAbsDir, layer->map->shapepath, filename), log_failures) == -1) { if(msShapefileOpen(shpfile, "rb", msBuildPath(szPath, layer->map->mappath, filename), log_failures) == -1) { if(ignore_missing == MS_MISSING_DATA_FAIL) { msSetError(MS_IOERR, "Unable to open shapefile '%s' for layer '%s' ... fatal error.", "msTiledSHPTryOpen()", filename, layer->name); return(MS_FAILURE); } else if( ignore_missing == MS_MISSING_DATA_LOG ) { if( layer->debug || layer->map->debug ) { msDebug( "Unable to open shapefile '%s' for layer '%s' ... ignoring this missing data.\n", szPath, layer->name ); } return(MS_DONE); } else if( ignore_missing == MS_MISSING_DATA_IGNORE ) { return(MS_DONE); } else { /* never get here */ msSetError(MS_IOERR, "msIgnoreMissingData returned unexpected value.", "msTiledSHPTryOpen()"); return(MS_FAILURE); } } } } return(MS_SUCCESS); } int msTiledSHPOpenFile(layerObj *layer) { int i; char *filename, tilename[MS_MAXPATHLEN], szPath[MS_MAXPATHLEN]; char tiFileAbsDir[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate space for a shapefileObj using layer->layerinfo */ tSHP = (msTiledSHPLayerInfo *) malloc(sizeof(msTiledSHPLayerInfo)); MS_CHECK_ALLOC(tSHP, sizeof(msTiledSHPLayerInfo), MS_FAILURE); tSHP->shpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); if (tSHP->shpfile == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msTiledSHPOpenFile()", __FILE__, __LINE__, (unsigned int)sizeof(shapefileObj)); free(tSHP); return MS_FAILURE; } tSHP->shpfile->isopen = MS_FALSE; /* in case of error: do not try to close the shpfile */ tSHP->tileshpfile = NULL; /* may need this if not using a tile layer, look for malloc later */ layer->layerinfo = tSHP; tSHP->tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); if(tSHP->tilelayerindex != -1) { /* does the tileindex reference another layer */ int status; layerObj *tlp; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); if(tlp->connectiontype != MS_SHAPEFILE) { msSetError(MS_SDEERR, "Tileindex layer must be a shapefile.", "msTiledSHPOpenFile()"); return(MS_FAILURE); } status = msLayerOpen(tlp); if(status != MS_SUCCESS) return(MS_FAILURE); /* build item list */ status = msLayerWhichItems(tlp, MS_FALSE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); tSHP->tileshpfile = (shapefileObj *) tlp->layerinfo; /* shapefiles use layerinfo to point to a shapefileObj */ } else { /* or reference a shapefile directly */ /* we need tSHP->tileshpfile if we're not working with a layer */ tSHP->tileshpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); if (tSHP->tileshpfile == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msTiledSHPOpenFile()", __FILE__, __LINE__, (unsigned int)sizeof(shapefileObj)); free(tSHP->shpfile); free(tSHP); layer->layerinfo = NULL; return MS_FAILURE; } if(msShapefileOpen(tSHP->tileshpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->tileindex), MS_TRUE) == -1) if(msShapefileOpen(tSHP->tileshpfile, "rb", msBuildPath(szPath, layer->map->mappath, layer->tileindex), MS_TRUE) == -1) return(MS_FAILURE); } if((layer->tileitemindex = msDBFGetItemIndex(tSHP->tileshpfile->hDBF, layer->tileitem)) == -1) return(MS_FAILURE); if( layer->tilesrs != NULL ) { msSetError(MS_OGRERR, "TILESRS not supported in vector layers.", "msTiledSHPOpenFile()"); return MS_FAILURE; } msTileIndexAbsoluteDir(tiFileAbsDir, layer); /* position the source at the FIRST tile to use as a template, this is so the functions that fill the iteminfo array have something to work from */ for(i=0; itileshpfile->numshapes; i++) { int try_open; if(!layer->data) /* assume whole filename is in attribute field */ filename = (char*) msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex); else { snprintf(tilename, sizeof(tilename), "%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex) , layer->data); filename = tilename; } if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); return(MS_SUCCESS); /* found a template, ok to proceed */ } msSetError(MS_SHPERR, "Unable to open a single tile to use as a template in layer %s.", "msTiledSHPOpenFile()", layer->name?layer->name:"(null)"); return(MS_FAILURE); } int msTiledSHPWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i, status; char *filename, tilename[MS_MAXPATHLEN]; char tiFileAbsDir[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPWhichShapes()"); return(MS_FAILURE); } msShapefileClose(tSHP->shpfile); /* close previously opened files */ if(tSHP->tilelayerindex != -1) { /* does the tileindex reference another layer */ layerObj *tlp; shapeObj tshape; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); status= msLayerWhichShapes(tlp, rect, isQuery); if(status != MS_SUCCESS) return(status); /* could be MS_DONE or MS_FAILURE */ msTileIndexAbsoluteDir(tiFileAbsDir, layer); msInitShape(&tshape); while((status = msLayerNextShape(tlp, &tshape)) == MS_SUCCESS) { int try_open; /* TODO: seems stupid to read the tileitem seperately from the shape, need to fix msTiledSHPOpenFile */ if(!layer->data) /* assume whole filename is in attribute field */ filename = (char *) msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, tshape.index, layer->tileitemindex); else { snprintf(tilename, sizeof(tilename), "%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, tshape.index, layer->tileitemindex) , layer->data); filename = tilename; } if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); status = msShapefileWhichShapes(tSHP->shpfile, rect, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); return(MS_FAILURE); } /* the layer functions keeps track of this */ /* tSHP->tileshpfile->lastshape = tshape.index; */ break; } return(status); /* if we reach here we either 1) ran out of tiles or 2) had an error reading a tile */ } else { /* or reference a shapefile directly */ int try_open; status = msShapefileWhichShapes(tSHP->tileshpfile, rect, layer->debug); if(status != MS_SUCCESS) return(status); /* could be MS_DONE or MS_FAILURE */ msTileIndexAbsoluteDir(tiFileAbsDir, layer); /* position the source at the FIRST shapefile */ for(i=0; itileshpfile->numshapes; i++) { if(msGetBit(tSHP->tileshpfile->status,i)) { if(!layer->data) /* assume whole filename is in attribute field */ filename = (char *) msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex); else { snprintf(tilename, sizeof(tilename), "%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex) , layer->data); filename = tilename; } if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); status = msShapefileWhichShapes(tSHP->shpfile, rect, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); return(MS_FAILURE); } tSHP->tileshpfile->lastshape = i; break; } } if(i == tSHP->tileshpfile->numshapes) return(MS_DONE); /* no more tiles */ else return(MS_SUCCESS); } return(MS_FAILURE); /* should *never* get here */ } int msTiledSHPNextShape(layerObj *layer, shapeObj *shape) { int i, status, filter_passed = MS_FALSE; char *filename, tilename[MS_MAXPATHLEN]; char tiFileAbsDir[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPNextShape()"); return(MS_FAILURE); } msTileIndexAbsoluteDir(tiFileAbsDir, layer); do { i = tSHP->shpfile->lastshape + 1; while(ishpfile->numshapes && !msGetBit(tSHP->shpfile->status,i)) i++; /* next "in" shape */ if(i == tSHP->shpfile->numshapes) { /* done with this tile, need a new one */ msShapefileClose(tSHP->shpfile); /* clean up */ /* position the source to the NEXT shapefile based on the tileindex */ if(tSHP->tilelayerindex != -1) { /* does the tileindex reference another layer */ layerObj *tlp; shapeObj tshape; int try_open; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); msInitShape(&tshape); while((status = msLayerNextShape(tlp, &tshape)) == MS_SUCCESS) { /* TODO: seems stupid to read the tileitem seperately from the shape, need to fix msTiledSHPOpenFile */ if(!layer->data) /* assume whole filename is in attribute field */ filename = (char *) msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, tshape.index, layer->tileitemindex); else { snprintf(tilename, sizeof(tilename),"%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, tshape.index, layer->tileitemindex) , layer->data); filename = tilename; } if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); status = msShapefileWhichShapes(tSHP->shpfile, tSHP->tileshpfile->statusbounds, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); return(MS_FAILURE); } /* the layer functions keeps track of this */ /* tSHP->tileshpfile->lastshape = tshape.index; */ break; } if(status == MS_DONE) return(MS_DONE); /* no more tiles */ else { msFreeShape(&tshape); continue; /* we've got shapes */ } } else { /* or reference a shapefile directly */ for(i=(tSHP->tileshpfile->lastshape + 1); itileshpfile->numshapes; i++) { if(msGetBit(tSHP->tileshpfile->status,i)) { int try_open; if(!layer->data) /* assume whole filename is in attribute field */ filename = (char*)msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex); else { snprintf(tilename, sizeof(tilename),"%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex) , layer->data); filename = tilename; } if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); status = msShapefileWhichShapes(tSHP->shpfile, tSHP->tileshpfile->statusbounds, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); return(MS_FAILURE); } tSHP->tileshpfile->lastshape = i; break; } } /* end for loop */ if(i == tSHP->tileshpfile->numshapes) return(MS_DONE); /* no more tiles */ else continue; /* we've got shapes */ } } tSHP->shpfile->lastshape = i; msSHPReadShape(tSHP->shpfile->hSHP, i, shape); if(shape->type == MS_SHAPE_NULL) { msFreeShape(shape); continue; /* skip NULL shapes */ } shape->tileindex = tSHP->tileshpfile->lastshape; shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(tSHP->shpfile->hDBF, i, layer->iteminfo, layer->numitems); if(!shape->values) shape->numvalues = 0; filter_passed = MS_TRUE; /* By default accept ANY shape */ if(layer->numitems > 0 && layer->iteminfo) { filter_passed = msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex); } if(!filter_passed) msFreeShape(shape); /* free's values as well */ } while(!filter_passed); /* Loop until both spatial and attribute filters match */ return(MS_SUCCESS); } int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { char *filename, tilename[MS_MAXPATHLEN], szPath[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; char tiFileAbsDir[MS_MAXPATHLEN]; long shapeindex = record->shapeindex; int tileindex = record->tileindex; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPGetShape()"); return(MS_FAILURE); } if((tileindex < 0) || (tileindex >= tSHP->tileshpfile->numshapes)) return(MS_FAILURE); /* invalid tile id */ if(tileindex != tSHP->tileshpfile->lastshape) { /* correct tile is not currenly open so open the correct tile */ msShapefileClose(tSHP->shpfile); /* close current tile */ if(!layer->data) /* assume whole filename is in attribute field */ filename = (char*) msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, tileindex, layer->tileitemindex); else { snprintf(tilename, sizeof(tilename), "%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, tileindex, layer->tileitemindex) , layer->data); filename = tilename; } /* open the shapefile, since a specific tile was request an error should be generated if that tile does not exist */ if(strlen(filename) == 0) return(MS_FAILURE); if(msShapefileOpen(tSHP->shpfile, "rb", msBuildPath3(szPath, tiFileAbsDir, layer->map->shapepath, filename), MS_TRUE) == -1) { if(msShapefileOpen(tSHP->shpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, filename), MS_TRUE) == -1) { if(msShapefileOpen(tSHP->shpfile, "rb", msBuildPath(szPath, layer->map->mappath, filename), MS_TRUE) == -1) { return(MS_FAILURE); } } } } if((shapeindex < 0) || (shapeindex >= tSHP->shpfile->numshapes)) return(MS_FAILURE); msSHPReadShape(tSHP->shpfile->hSHP, shapeindex, shape); tSHP->shpfile->lastshape = shapeindex; if(layer->numitems > 0 && layer->iteminfo) { shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(tSHP->shpfile->hDBF, shapeindex, layer->iteminfo, layer->numitems); if(!shape->values) return(MS_FAILURE); } shape->tileindex = tileindex; return(MS_SUCCESS); } void msTiledSHPClose(layerObj *layer) { msTiledSHPLayerInfo *tSHP=NULL; tSHP = layer->layerinfo; if(tSHP) { msShapefileClose(tSHP->shpfile); free(tSHP->shpfile); if(tSHP->tilelayerindex != -1) { layerObj *tlp; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); msLayerClose(tlp); } else { msShapefileClose(tSHP->tileshpfile); free(tSHP->tileshpfile); } free(tSHP); } layer->layerinfo = NULL; } /************************************************************************/ /* msTiledSHPClose() */ /* Overloaded version of msTiledSHPClose for virtual table architecture */ /************************************************************************/ int msTiledSHPCloseVT(layerObj *layer) { msTiledSHPClose(layer); return MS_SUCCESS; } void msTiledSHPLayerFreeItemInfo(layerObj *layer) { if(layer->iteminfo) { free(layer->iteminfo); layer->iteminfo = NULL; } } int msTiledSHPLayerInitItemInfo(layerObj *layer) { msTiledSHPLayerInfo *tSHP=NULL; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPLayerInitItemInfo()"); return MS_FAILURE; } msTiledSHPLayerFreeItemInfo(layer); layer->iteminfo = (int *) msDBFGetItemIndexes(tSHP->shpfile->hDBF, layer->items, layer->numitems); if(!layer->iteminfo) return(MS_FAILURE); return MS_SUCCESS; } static void msSHPPassThroughFieldDefinitions( layerObj *layer, DBFHandle hDBF ) { int numitems, i; numitems = msDBFGetFieldCount( hDBF ); for(i=0; imetadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } } int msTiledSHPLayerGetItems(layerObj *layer) { msTiledSHPLayerInfo *tSHP=NULL; const char *value; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPLayerGetItems()"); return MS_FAILURE; } layer->numitems = msDBFGetFieldCount(tSHP->shpfile->hDBF); layer->items = msDBFGetItems(tSHP->shpfile->hDBF); if(!layer->items) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* consider populating the field definitions in metadata. */ /* -------------------------------------------------------------------- */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msSHPPassThroughFieldDefinitions( layer, tSHP->shpfile->hDBF ); return msTiledSHPLayerInitItemInfo(layer); } int msTiledSHPLayerGetExtent(layerObj *layer, rectObj *extent) { msTiledSHPLayerInfo *tSHP=NULL; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPLayerGetExtent()"); return MS_FAILURE; } *extent = tSHP->tileshpfile->bounds; return MS_SUCCESS; } int msTiledSHPLayerIsOpen(layerObj *layer) { if(layer->layerinfo) return MS_TRUE; else return MS_FALSE; } int msTiledSHPLayerSupportsCommonFilters(layerObj *layer) { return MS_TRUE; } int msTiledSHPLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerSupportsCommonFilters = msTiledSHPLayerSupportsCommonFilters; layer->vtable->LayerInitItemInfo = msTiledSHPLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msTiledSHPLayerFreeItemInfo; layer->vtable->LayerOpen = msTiledSHPOpenFile; layer->vtable->LayerIsOpen = msTiledSHPLayerIsOpen; layer->vtable->LayerWhichShapes = msTiledSHPWhichShapes; layer->vtable->LayerNextShape = msTiledSHPNextShape; /* no special version, use ...GetShape() */ /* layer->vtable->LayerResultsGetShape = msTiledSHPGetShape; */ layer->vtable->LayerGetShape = msTiledSHPGetShape; layer->vtable->LayerClose = msTiledSHPCloseVT; layer->vtable->LayerGetItems = msTiledSHPLayerGetItems; layer->vtable->LayerGetExtent = msTiledSHPLayerGetExtent; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerCloseConnection, use default */; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection, use defaut*/ return MS_SUCCESS; } /* SHAPEFILE Layer virtual table functions */ void msSHPLayerFreeItemInfo(layerObj *layer) { if(layer->iteminfo) { free(layer->iteminfo); layer->iteminfo = NULL; } } int msSHPLayerInitItemInfo(layerObj *layer) { shapefileObj *shpfile = shpfile = layer->layerinfo; if( ! shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerInitItemInfo()"); return MS_FAILURE; } /* iteminfo needs to be a bit more complex, a list of indexes plus the length of the list */ msSHPLayerFreeItemInfo(layer); layer->iteminfo = (int *) msDBFGetItemIndexes(shpfile->hDBF, layer->items, layer->numitems); if( ! layer->iteminfo) { return MS_FAILURE; } return MS_SUCCESS; } int msSHPLayerOpen(layerObj *layer) { char szPath[MS_MAXPATHLEN]; shapefileObj *shpfile; if(layer->layerinfo) return MS_SUCCESS; /* layer already open */ /* allocate space for a shapefileObj using layer->layerinfo */ shpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); MS_CHECK_ALLOC(shpfile, sizeof(shapefileObj), MS_FAILURE); if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; layer->layerinfo = shpfile; if(msShapefileOpen(shpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->data), MS_TRUE) == -1) { if(msShapefileOpen(shpfile, "rb", msBuildPath(szPath, layer->map->mappath, layer->data), MS_TRUE) == -1) { layer->layerinfo = NULL; free(shpfile); return MS_FAILURE; } } if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { #if defined(USE_GDAL) || defined(USE_OGR) const char* pszPRJFilename = CPLResetExtension(szPath, "prj"); int bOK = MS_FALSE; FILE* fp = fopen(pszPRJFilename, "rb"); if( fp != NULL ) { char szPRJ[2048]; OGRSpatialReferenceH hSRS; int nRead; nRead = (int)fread(szPRJ, 1, sizeof(szPRJ) - 1, fp); szPRJ[nRead] = '\0'; hSRS = OSRNewSpatialReference(szPRJ); if( hSRS != NULL ) { if( OSRMorphFromESRI( hSRS ) == OGRERR_NONE ) { char* pszWKT = NULL; if( OSRExportToWkt( hSRS, &pszWKT ) == OGRERR_NONE ) { if( msOGCWKT2ProjectionObj(pszWKT, &(layer->projection), layer->debug ) == MS_SUCCESS ) { bOK = MS_TRUE; } } CPLFree(pszWKT); } OSRDestroySpatialReference(hSRS); } } fclose(fp); if( bOK != MS_TRUE ) { if( layer->debug || (layer->map && layer->map->debug) ) { msDebug( "Unable to get SRS from shapefile '%s' for layer '%s'.\n", szPath, layer->name ); } } #else /* !(defined(USE_GDAL) || defined(USE_OGR)) */ if( layer->debug || (layer->map && layer->map->debug) ) { msDebug( "Unable to get SRS from shapefile '%s' for layer '%s'. GDAL or OGR support needed\n", szPath, layer->name ); } #endif /* defined(USE_GDAL) || defined(USE_OGR) */ } return MS_SUCCESS; } int msSHPLayerIsOpen(layerObj *layer) { if(layer->layerinfo) return MS_TRUE; else return MS_FALSE; } int msSHPLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int status; shapefileObj *shpfile; shpfile = layer->layerinfo; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerWhichShapes()"); return MS_FAILURE; } status = msShapefileWhichShapes(shpfile, rect, layer->debug); if(status != MS_SUCCESS) { return status; } return MS_SUCCESS; } int msSHPLayerNextShape(layerObj *layer, shapeObj *shape) { int i, filter_passed=MS_FALSE; shapefileObj *shpfile; shpfile = layer->layerinfo; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerNextShape()"); return MS_FAILURE; } do { i = msGetNextBit(shpfile->status, shpfile->lastshape + 1, shpfile->numshapes); shpfile->lastshape = i; if(i == -1) return(MS_DONE); /* nothing else to read */ msSHPReadShape(shpfile->hSHP, i, shape); if(shape->type == MS_SHAPE_NULL) { msFreeShape(shape); continue; /* skip NULL shapes */ } shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(shpfile->hDBF, i, layer->iteminfo, layer->numitems); if(!shape->values) { shape->numvalues = 0; } filter_passed = MS_TRUE; /* By default accept ANY shape */ if(layer->numitems > 0 && layer->iteminfo) { filter_passed = msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex); } if(!filter_passed) msFreeShape(shape); } while(!filter_passed); /* Loop until both spatial and attribute filters match */ return MS_SUCCESS; } int msSHPLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { shapefileObj *shpfile; long shapeindex; shpfile = layer->layerinfo; shapeindex = record->shapeindex; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerGetShape()"); return MS_FAILURE; } /* msSHPReadShape *should* return success or failure so we don't have to test here */ if(shapeindex < 0 || shapeindex >= shpfile->numshapes) { msSetError(MS_MISCERR, "Invalid feature id.", "msSHPLayerGetShape()"); return MS_FAILURE; } msSHPReadShape(shpfile->hSHP, shapeindex, shape); if(layer->numitems > 0 && layer->iteminfo) { shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(shpfile->hDBF, shapeindex, layer->iteminfo, layer->numitems); if(!shape->values) return MS_FAILURE; } shpfile->lastshape = shapeindex; return MS_SUCCESS; } int msSHPLayerClose(layerObj *layer) { shapefileObj *shpfile; shpfile = layer->layerinfo; if(!shpfile) return MS_SUCCESS; /* nothing to do */ msShapefileClose(shpfile); free(layer->layerinfo); layer->layerinfo = NULL; return MS_SUCCESS; } int msSHPLayerGetItems(layerObj *layer) { shapefileObj *shpfile; const char *value; shpfile = layer->layerinfo; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerGetItems()"); return MS_FAILURE; } layer->numitems = msDBFGetFieldCount(shpfile->hDBF); layer->items = msDBFGetItems(shpfile->hDBF); if(layer->numitems == 0) return MS_SUCCESS; /* No items is a valid case (#3147) */ if(!layer->items) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* consider populating the field definitions in metadata. */ /* -------------------------------------------------------------------- */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msSHPPassThroughFieldDefinitions( layer, shpfile->hDBF ); return msLayerInitItemInfo(layer); } int msSHPLayerGetExtent(layerObj *layer, rectObj *extent) { *extent = ((shapefileObj*)layer->layerinfo)->bounds; return MS_SUCCESS; } int msSHPLayerSupportsCommonFilters(layerObj *layer) { return MS_TRUE; } int msSHPLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerSupportsCommonFilters = msSHPLayerSupportsCommonFilters; layer->vtable->LayerInitItemInfo = msSHPLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msSHPLayerFreeItemInfo; layer->vtable->LayerOpen = msSHPLayerOpen; layer->vtable->LayerIsOpen = msSHPLayerIsOpen; layer->vtable->LayerWhichShapes = msSHPLayerWhichShapes; layer->vtable->LayerNextShape = msSHPLayerNextShape; layer->vtable->LayerGetShape = msSHPLayerGetShape; layer->vtable->LayerClose = msSHPLayerClose; layer->vtable->LayerGetItems = msSHPLayerGetItems; layer->vtable->LayerGetExtent = msSHPLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } mapserver-6.4.1/mapraster.h0000644002461700001440000000621112261257215015463 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Private include file used by mapraster.c and maprasterquery.c * Author: Even Rouault * ****************************************************************************** * Copyright (c) 2013 Regents of the University of Minnesota. * * 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 MAPRASTER_H #define MAPRASTER_H #if defined(USE_GDAL) int msDrawRasterSetupTileLayer(mapObj *map, layerObj *layer, rectObj* psearchrect, int is_query, int* ptilelayerindex, /* output */ int* ptileitemindex, /* output */ int* ptilesrsindex, /* output */ layerObj **ptlp /* output */ ); void msDrawRasterCleanupTileLayer(layerObj* tlp, int tilelayerindex); int msDrawRasterIterateTileIndex(layerObj *layer, layerObj* tlp, shapeObj* ptshp, /* input-output */ int tileitemindex, int tilesrsindex, char* tilename, /* output */ size_t sizeof_tilename, char* tilesrsname, /* output */ size_t sizeof_tilesrsname); int msDrawRasterBuildRasterPath(mapObj *map, layerObj *layer, const char* filename, char szPath[MS_MAXPATHLEN]); const char* msDrawRasterGetCPLErrorMsg(const char* decrypted_path, const char* szPath); int msDrawRasterLoadProjection(layerObj *layer, GDALDatasetH hDS, const char* filename, int tilesrsindex, const char* tilesrsname); #endif #endif /* MAPRASTER_H */ mapserver-6.4.1/mapowscommon.h0000644002461700001440000001201012261257215016176 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC OWS Common Implementation include file * Author: Tom Kralidis (tomkralidis@hotmail.com) * ****************************************************************************** * Copyright (c) 2006, Tom Kralidis * * 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 MAPOWSCOMMON_H #define MAPOWSCOMMON_H #ifdef USE_LIBXML2 #include #include /* W3C namespaces */ #define MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI "http://www.w3.org/1999/xlink" #define MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX "xlink" #define MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI "http://www.w3.org/2001/XMLSchema-instance" #define MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX "xsi" #define MS_OWSCOMMON_W3C_XS_NAMESPACE_URI "http://www.w3.org/2001/XMLSchema" #define MS_OWSCOMMON_W3C_XS_NAMESPACE_PREFIX "xs" /* OGC namespaces */ #define MS_OWSCOMMON_OGC_NAMESPACE_URI "http://www.opengis.net/ogc" #define MS_OWSCOMMON_OGC_NAMESPACE_PREFIX "ogc" #define MS_OWSCOMMON_OWS_NAMESPACE_URI "http://www.opengis.net/ows" #define MS_OWSCOMMON_OWS_NAMESPACE_PREFIX "ows" #define MS_OWSCOMMON_OWS_110_NAMESPACE_URI "http://www.opengis.net/ows/1.1" #define MS_OWSCOMMON_OWS_20_NAMESPACE_URI "http://www.opengis.net/ows/2.0" #define MS_OWSCOMMON_OWS_20_SCHEMAS_LOCATION "/ows/2.0/owsAll.xsd" /* OGC URNs */ #define MS_OWSCOMMON_URN_OGC_CRS_4326 "urn:opengis:def:crs:OGC:2:84" /* default OGC Schemas Location */ #define MS_OWSCOMMON_SCHEMAS_LOCATION "http://schemas.opengis.net" /* OGC codespace */ #define MS_OWSCOMMON_OGC_CODESPACE "OGC" /* WCS namespaces */ #define MS_OWSCOMMON_WCS_20_NAMESPACE_URI "http://www.opengis.net/wcs/2.0" #define MS_OWSCOMMON_WCS_20_SCHEMAS_LOCATION "/wcs/2.0/wcsAll.xsd" #define MS_OWSCOMMON_WCS_NAMESPACE_PREFIX "wcs" /* GML namespaces */ #define MS_OWSCOMMON_GML_32_NAMESPACE_URI "http://www.opengis.net/gml/3.2" #define MS_OWSCOMMON_GML_NAMESPACE_PREFIX "gml" /* GMLCov namespaces */ #define MS_OWSCOMMON_GMLCOV_10_NAMESPACE_URI "http://www.opengis.net/gmlcov/1.0" #define MS_OWSCOMMON_GMLCOV_NAMESPACE_PREFIX "gmlcov" /* SWE namespaces */ #define MS_OWSCOMMON_SWE_20_NAMESPACE_URI "http://www.opengis.net/swe/2.0" #define MS_OWSCOMMON_SWE_NAMESPACE_PREFIX "swe" /* function prototypes */ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, const char *servicetype, const char *version, const char *namespaces); xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psXLinkNs, mapObj *map, const char *namespaces); xmlNodePtr msOWSCommonOperationsMetadata(xmlNsPtr psNsOws); #define OWS_METHOD_GET 1 #define OWS_METHOD_POST 2 #define OWS_METHOD_GETPOST 3 xmlNodePtr msOWSCommonOperationsMetadataOperation(xmlNsPtr psNsOws, xmlNsPtr psXLinkNs, char *name, int method, char *url); xmlNodePtr msOWSCommonOperationsMetadataDomainType(int version, xmlNsPtr psNsOws, char *elname, char *name, char *values); xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const char *schemas_location, const char *version, const char *language, const char *exceptionCode, const char *locator, const char *ExceptionText); xmlNodePtr msOWSCommonBoundingBox(xmlNsPtr psNsOws, const char *crs, int dimensions, double minx, double miny, double maxx, double maxy); xmlNodePtr msOWSCommonWGS84BoundingBox(xmlNsPtr psNsOws, int dimensions, double minx, double miny, double maxx, double maxy); int _validateNamespace(xmlNsPtr psNsOws); xmlNodePtr msOWSCommonxmlNewChildEncoded( xmlNodePtr psParent, xmlNsPtr psNs, const char* name, const char *content, const char *encoding); int msOWSSchemaValidation(const char* xml_schema, const char* xml); #endif /* defined(USE_LIBXML2) */ int msOWSCommonNegotiateVersion(int requested_version, int supported_versions[], int num_supported_versions); #endif /* MAPOWSCOMMON_H */ mapserver-6.4.1/mapmssql2008.c0000644002461700001440000021617712261257215015645 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MS SQL 2008 (Katmai) Layer Connector * Author: Richard Hillman - based on PostGIS and SpatialDB connectors * ****************************************************************************** * Copyright (c) 2007 IS Consulting (www.mapdotnet.com) * * 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. ****************************************************************************** * * Revision 1.0 2007/7/1 * Created. * */ #define _CRT_SECURE_NO_WARNINGS 1 /* $Id$ */ #include #include "mapserver.h" #include "maptime.h" #ifdef USE_MSSQL2008 #include #include #include #include #include #include /* tolower() */ /* Native geometry parser macros */ /* parser error codes */ #define NOERROR 0 #define NOT_ENOUGH_DATA 1 #define CORRUPT_DATA 2 #define UNSUPPORTED_GEOMETRY_TYPE 3 /* geometry format to transfer geometry column */ #define MSSQLGEOMETRY_NATIVE 0 #define MSSQLGEOMETRY_WKB 1 #define MSSQLGEOMETRY_WKT 2 /* geometry column types */ #define MSSQLCOLTYPE_GEOMETRY 0 #define MSSQLCOLTYPE_GEOGRAPHY 1 #define MSSQLCOLTYPE_BINARY 2 #define MSSQLCOLTYPE_TEXT 3 #define SP_NONE 0 #define SP_HASZVALUES 1 #define SP_HASMVALUES 2 #define SP_ISVALID 4 #define SP_ISSINGLEPOINT 8 #define SP_ISSINGLELINESEGMENT 0x10 #define SP_ISWHOLEGLOBE 0x20 #define ST_UNKNOWN 0 #define ST_POINT 1 #define ST_LINESTRING 2 #define ST_POLYGON 3 #define ST_MULTIPOINT 4 #define ST_MULTILINESTRING 5 #define ST_MULTIPOLYGON 6 #define ST_GEOMETRYCOLLECTION 7 #define ReadInt32(nPos) (*((unsigned int*)(gpi->pszData + (nPos)))) #define ReadByte(nPos) (gpi->pszData[nPos]) #define ReadDouble(nPos) (*((double*)(gpi->pszData + (nPos)))) #define ParentOffset(iShape) (ReadInt32(gpi->nShapePos + (iShape) * 9 )) #define FigureOffset(iShape) (ReadInt32(gpi->nShapePos + (iShape) * 9 + 4)) #define ShapeType(iShape) (ReadByte(gpi->nShapePos + (iShape) * 9 + 8)) #define NextFigureOffset(iShape) (iShape + 1 < gpi->nNumShapes? FigureOffset((iShape) +1) : gpi->nNumFigures) #define FigureAttribute(iFigure) (ReadByte(gpi->nFigurePos + (iFigure) * 5)) #define PointOffset(iFigure) (ReadInt32(gpi->nFigurePos + (iFigure) * 5 + 1)) #define NextPointOffset(iFigure) (iFigure + 1 < gpi->nNumFigures? PointOffset((iFigure) +1) : gpi->nNumPoints) #define ReadX(iPoint) (ReadDouble(gpi->nPointPos + 16 * (iPoint))) #define ReadY(iPoint) (ReadDouble(gpi->nPointPos + 16 * (iPoint) + 8)) #define ReadZ(iPoint) (ReadDouble(gpi->nPointPos + 16 * gpi->nNumPoints + 8 * (iPoint))) #define ReadM(iPoint) (ReadDouble(gpi->nPointPos + 24 * gpi->nNumPoints + 8 * (iPoint))) /* Native geometry parser struct */ typedef struct msGeometryParserInfo_t { unsigned char* pszData; int nLen; /* serialization propeties */ char chProps; /* point array */ int nPointSize; int nPointPos; int nNumPoints; /* figure array */ int nFigurePos; int nNumFigures; /* shape array */ int nShapePos; int nNumShapes; int nSRSId; /* geometry or geography */ int nColType; /* bounds */ double minx; double miny; double maxx; double maxy; } msGeometryParserInfo; /* Structure for connection to an ODBC database (Microsoft preferred way to connect to SQL Server 2005 from c/c++) */ typedef struct msODBCconn_t { SQLHENV henv; /* ODBC HENV */ SQLHDBC hdbc; /* ODBC HDBC */ SQLHSTMT hstmt; /* ODBC HSTMNT */ char errorMessage[1024]; /* Last error message if any */ } msODBCconn; typedef struct ms_MSSQL2008_layer_info_t { char *sql; /* sql query to send to DB */ long row_num; /* what row is the NEXT to be read (for random access) */ char *geom_column; /* name of the actual geometry column parsed from the LAYER's DATA field */ char *geom_column_type; /* the type of the geometry column */ char *geom_table; /* the table name or sub-select decalred in the LAYER's DATA field */ char *urid_name; /* name of user-specified unique identifier or OID */ char *user_srid; /* zero length = calculate, non-zero means using this value! */ char *index_name; /* hopefully this isn't necessary - but if the optimizer ain't cuttin' it... */ msODBCconn * conn; /* Connection to db */ msGeometryParserInfo gpi; /* struct for the geometry parser */ int geometry_format; /* Geometry format to be retrieved from the database */ } msMSSQL2008LayerInfo; #define SQL_COLUMN_NAME_MAX_LENGTH 128 #define SQL_TABLE_NAME_MAX_LENGTH 128 #define DATA_ERROR_MESSAGE \ "%s" \ "Error with MSSQL2008 data variable. You specified '%s'.
\n" \ "Standard ways of specifiying are :
\n(1) 'geometry_column from geometry_table'
\n(2) 'geometry_column from (<sub query>) as foo using unique <column name> using SRID=<srid#>'

\n\n" \ "Make sure you utilize the 'using unique <column name>' and 'using with <index name>' clauses in.\n\n

" \ "For more help, please see http://www.mapdotnet.com \n\n

" \ "mapmssql2008.c - version of 2007/7/1.\n" /* Native geometry parser code */ void ReadPoint(msGeometryParserInfo* gpi, pointObj* p, int iPoint, int iOrder) { if (gpi->nColType == MSSQLCOLTYPE_GEOGRAPHY) { p->x = ReadY(iPoint); p->y = ReadX(iPoint); } else { p->x = ReadX(iPoint); p->y = ReadY(iPoint); } /* calculate bounds */ if (iOrder == 0) { gpi->minx = gpi->maxx = p->x; gpi->miny = gpi->maxy = p->y; } else { if (gpi->minx > p->x) gpi->minx = p->x; else if (gpi->maxx < p->x) gpi->maxx = p->x; if (gpi->miny > p->y) gpi->miny = p->y; else if (gpi->maxy < p->y) gpi->maxy = p->y; } #ifdef USE_POINT_Z_M if ( gpi->chProps & SP_HASZVALUES ) p->z = ReadZ(iPoint); if ( gpi->chProps & SP_HASMVALUES ) p->z = ReadM(iPoint); #endif } int ParseSqlGeometry(msMSSQL2008LayerInfo* layerinfo, shapeObj *shape) { msGeometryParserInfo* gpi = &layerinfo->gpi; if (gpi->nLen < 10) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } /* store the SRS id for further use */ gpi->nSRSId = ReadInt32(0); if ( ReadByte(4) != 1 ) { msDebug("ParseSqlGeometry CORRUPT_DATA\n"); return CORRUPT_DATA; } gpi->chProps = ReadByte(5); if ( gpi->chProps & SP_HASMVALUES ) gpi->nPointSize = 32; else if ( gpi->chProps & SP_HASZVALUES ) gpi->nPointSize = 24; else gpi->nPointSize = 16; if ( gpi->chProps & SP_ISSINGLEPOINT ) { // single point geometry gpi->nNumPoints = 1; if (gpi->nLen < 6 + gpi->nPointSize) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) msSmallMalloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) msSmallMalloc(sizeof(pointObj)); shape->line[0].numpoints = 1; gpi->nPointPos = 6; ReadPoint(gpi, &shape->line[0].point[0], 0, 0); } else if ( gpi->chProps & SP_ISSINGLELINESEGMENT ) { // single line segment with 2 points gpi->nNumPoints = 2; if (gpi->nLen < 6 + 2 * gpi->nPointSize) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) msSmallMalloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) msSmallMalloc(sizeof(pointObj) * 2); shape->line[0].numpoints = 2; gpi->nPointPos = 6; ReadPoint(gpi, &shape->line[0].point[0], 0, 0); ReadPoint(gpi, &shape->line[0].point[1], 1, 1); } else { int iShape, iFigure; // complex geometries gpi->nNumPoints = ReadInt32(6); if ( gpi->nNumPoints <= 0 ) { return NOERROR; } // position of the point array gpi->nPointPos = 10; // position of the figures gpi->nFigurePos = gpi->nPointPos + gpi->nPointSize * gpi->nNumPoints + 4; if (gpi->nLen < gpi->nFigurePos) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } gpi->nNumFigures = ReadInt32(gpi->nFigurePos - 4); if ( gpi->nNumFigures <= 0 ) { return NOERROR; } // position of the shapes gpi->nShapePos = gpi->nFigurePos + 5 * gpi->nNumFigures + 4; if (gpi->nLen < gpi->nShapePos) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } gpi->nNumShapes = ReadInt32(gpi->nShapePos - 4); if (gpi->nLen < gpi->nShapePos + 9 * gpi->nNumShapes) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } if ( gpi->nNumShapes <= 0 ) { return NOERROR; } // pick up the root shape if ( ParentOffset(0) != 0xFFFFFFFF) { msDebug("ParseSqlGeometry CORRUPT_DATA\n"); return CORRUPT_DATA; } // determine the shape type for (iShape = 0; iShape < gpi->nNumShapes; iShape++) { unsigned char shapeType = ShapeType(iShape); if (shapeType == ST_POINT || shapeType == ST_MULTIPOINT) { shape->type = MS_SHAPE_POINT; break; } else if (shapeType == ST_LINESTRING || shapeType == ST_MULTILINESTRING) { shape->type = MS_SHAPE_LINE; break; } else if (shapeType == ST_POLYGON || shapeType == ST_MULTIPOLYGON) { shape->type = MS_SHAPE_POLYGON; break; } } shape->line = (lineObj *) msSmallMalloc(sizeof(lineObj) * gpi->nNumFigures); shape->numlines = gpi->nNumFigures; // read figures for (iFigure = 0; iFigure < gpi->nNumFigures; iFigure++) { int iPoint, iNextPoint, i; iPoint = PointOffset(iFigure); iNextPoint = NextPointOffset(iFigure); shape->line[iFigure].point = (pointObj *) msSmallMalloc(sizeof(pointObj)*(iNextPoint - iPoint)); i = 0; while (iPoint < iNextPoint) { ReadPoint(gpi, &shape->line[iFigure].point[i], iPoint, i); ++iPoint; ++i; } shape->line[iFigure].numpoints = i; } } /* set bounds */ shape->bounds.minx = gpi->minx; shape->bounds.miny = gpi->miny; shape->bounds.maxx = gpi->maxx; shape->bounds.maxy = gpi->maxy; return NOERROR; } /* MS SQL driver code*/ msMSSQL2008LayerInfo *getMSSQL2008LayerInfo(const layerObj *layer) { return layer->layerinfo; } void setMSSQL2008LayerInfo(layerObj *layer, msMSSQL2008LayerInfo *MSSQL2008layerinfo) { layer->layerinfo = (void*) MSSQL2008layerinfo; } void handleSQLError(layerObj *layer) { SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH]; SQLINTEGER NativeError; SQLSMALLINT i, MsgLen; SQLRETURN rc; msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer); if (layerinfo == NULL) return; // Get the status records. i = 1; while ((rc = SQLGetDiagRec(SQL_HANDLE_STMT, layerinfo->conn->hstmt, i, SqlState, &NativeError, Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) { if(layer->debug) { msDebug("SQLError: %s\n", Msg); } i++; } } /* remove white space */ /* dont send in empty strings or strings with just " " in them! */ static char* removeWhite(char *str) { int initial; char *orig, *loc; initial = strspn(str, " "); if(initial) { memmove(str, str + initial, strlen(str) - initial + 1); } /* now final */ if(strlen(str) == 0) { return str; } if(str[strlen(str) - 1] == ' ') { /* have to remove from end */ orig = str; loc = &str[strlen(str) - 1]; while((*loc = ' ') && (loc >orig)) { *loc = 0; loc--; } } return str; } /* TODO Take a look at glibc's strcasestr */ static char *strstrIgnoreCase(const char *haystack, const char *needle) { char *hay_lower; char *needle_lower; int len_hay,len_need; int t; char *loc; int match = -1; len_hay = strlen(haystack); len_need = strlen(needle); hay_lower = (char*) msSmallMalloc(len_hay + 1); needle_lower =(char*) msSmallMalloc(len_need + 1); for(t = 0; t < len_hay; t++) { hay_lower[t] = (char)tolower(haystack[t]); } hay_lower[t] = 0; for(t = 0; t < len_need; t++) { needle_lower[t] = (char)tolower(needle[t]); } needle_lower[t] = 0; loc = strstr(hay_lower, needle_lower); if(loc) { match = loc - hay_lower; } msFree(hay_lower); msFree(needle_lower); return (char *) (match < 0 ? NULL : haystack + match); } static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, char **geom_column_type, char **table_name, char **urid_name, char **user_srid, char **index_name, int debug); /* Close connection and handles */ static void msMSSQL2008CloseConnection(void *conn_handle) { msODBCconn * conn = (msODBCconn *) conn_handle; if (!conn) { return; } if (conn->hstmt) { SQLFreeHandle(SQL_HANDLE_STMT, conn->hstmt); } if (conn->hdbc) { SQLDisconnect(conn->hdbc); SQLFreeHandle(SQL_HANDLE_DBC, conn->hdbc); } if (conn->henv) { SQLFreeHandle(SQL_HANDLE_ENV, conn->henv); } msFree(conn); } /* Set the error string for the connection */ static void setConnError(msODBCconn *conn) { SQLSMALLINT len; SQLGetDiagField(SQL_HANDLE_DBC, conn->hdbc, 1, SQL_DIAG_MESSAGE_TEXT, (SQLPOINTER) conn->errorMessage, sizeof(conn->errorMessage), &len); conn->errorMessage[len] = 0; } /* Connect to db */ static msODBCconn * mssql2008Connect(const char * connString) { SQLCHAR fullConnString[1024]; SQLRETURN rc; msODBCconn * conn = msSmallMalloc(sizeof(msODBCconn)); memset(conn, 0, sizeof(*conn)); SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &conn->henv); SQLSetEnvAttr(conn->henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0); SQLAllocHandle(SQL_HANDLE_DBC, conn->henv, &conn->hdbc); snprintf((char*)fullConnString, sizeof(fullConnString), "DRIVER=SQL Server;%s", connString); { SQLCHAR outConnString[1024]; SQLSMALLINT outConnStringLen; rc = SQLDriverConnect(conn->hdbc, NULL, fullConnString, SQL_NTS, outConnString, 1024, &outConnStringLen, SQL_DRIVER_NOPROMPT); } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { setConnError(conn); return conn; } SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &conn->hstmt); return conn; } /* Set the error string for the statement execution */ static void setStmntError(msODBCconn *conn) { SQLSMALLINT len; SQLGetDiagField(SQL_HANDLE_STMT, conn->hstmt, 1, SQL_DIAG_MESSAGE_TEXT, (SQLPOINTER) conn->errorMessage, sizeof(conn->errorMessage), &len); conn->errorMessage[len] = 0; } /* Execute SQL against connection. Set error string if failed */ static int executeSQL(msODBCconn *conn, const char * sql) { SQLRETURN rc; SQLCloseCursor(conn->hstmt); rc = SQLExecDirect(conn->hstmt, (SQLCHAR *) sql, SQL_NTS); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { return 1; } else { setStmntError(conn); return 0; } } /* Get columns name from query results */ static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLength) { SQLRETURN rc; SQLCHAR columnName[SQL_COLUMN_NAME_MAX_LENGTH + 1]; SQLSMALLINT columnNameLen; SQLSMALLINT dataType; SQLUINTEGER columnSize; SQLSMALLINT decimalDigits; SQLSMALLINT nullable; rc = SQLDescribeCol( conn->hstmt, (SQLUSMALLINT)index, columnName, SQL_COLUMN_NAME_MAX_LENGTH, &columnNameLen, &dataType, &columnSize, &decimalDigits, &nullable); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { if (bufferLength < SQL_COLUMN_NAME_MAX_LENGTH + 1) strlcpy(buffer, (const char *)columnName, bufferLength); else strlcpy(buffer, (const char *)columnName, SQL_COLUMN_NAME_MAX_LENGTH + 1); return 1; } else { setStmntError(conn); return 0; } } /* open up a connection to the MS SQL 2008 database using the connection string in layer->connection */ /* ie. "driver=;server=;database=;integrated security=?;user id=;password=" */ int msMSSQL2008LayerOpen(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; char *index, *maskeddata; int i, count; char *conn_decrypted = NULL; if(layer->debug) { msDebug("msMSSQL2008LayerOpen called datastatement: %s\n", layer->data); } if(getMSSQL2008LayerInfo(layer)) { if(layer->debug) { msDebug("msMSSQL2008LayerOpen :: layer is already open!!\n"); } return MS_SUCCESS; /* already open */ } if(!layer->data) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerOpen()", "", "Error parsing MSSQL2008 data variable: nothing specified in DATA statement.

\n\nMore Help:

\n\n"); return MS_FAILURE; } if(!layer->connection) { msSetError( MS_QUERYERR, "MSSQL connection parameter not specified.", "msMSSQL2008LayerOpen()"); return MS_FAILURE; } /* have to setup a connection to the database */ layerinfo = (msMSSQL2008LayerInfo*) msSmallMalloc(sizeof(msMSSQL2008LayerInfo)); layerinfo->sql = NULL; /* calc later */ layerinfo->row_num = 0; layerinfo->geom_column = NULL; layerinfo->geom_column_type = NULL; layerinfo->geom_table = NULL; layerinfo->urid_name = NULL; layerinfo->user_srid = NULL; layerinfo->index_name = NULL; layerinfo->conn = NULL; layerinfo->conn = (msODBCconn *) msConnPoolRequest(layer); if(!layerinfo->conn) { if(layer->debug) { msDebug("MSMSSQL2008LayerOpen -- shared connection not available.\n"); } /* Decrypt any encrypted token in connection and attempt to connect */ conn_decrypted = msDecryptStringTokens(layer->map, layer->connection); if (conn_decrypted == NULL) { return(MS_FAILURE); /* An error should already have been produced */ } layerinfo->conn = mssql2008Connect(conn_decrypted); msFree(conn_decrypted); conn_decrypted = NULL; if(!layerinfo->conn || layerinfo->conn->errorMessage[0]) { char *errMess = "Out of memory"; msDebug("FAILURE!!!"); maskeddata = (char *)msSmallMalloc(strlen(layer->connection) + 1); strcpy(maskeddata, layer->connection); index = strstr(maskeddata, "password="); if(index != NULL) { index = (char *)(index + 9); count = (int)(strstr(index, " ") - index); for(i = 0; i < count; i++) { strlcpy(index, "*", (int)1); index++; } } if (layerinfo->conn) { errMess = layerinfo->conn->errorMessage; } msSetError(MS_QUERYERR, "Couldnt make connection to MS SQL Server 2008 with connect string '%s'.\n
\n" "Error reported was '%s'.\n
\n\n" "This error occured when trying to make a connection to the specified SQL server. \n" "
\nMost commonly this is caused by
\n" "(1) incorrect connection string
\n" "(2) you didnt specify a 'user id=...' in your connection string
\n" "(3) SQL server isnt running
\n" "(4) TCPIP not enabled for SQL Client or server
\n\n", "msMSSQL2008LayerOpen()", maskeddata, errMess); msFree(maskeddata); msMSSQL2008CloseConnection(layerinfo->conn); msFree(layerinfo); return MS_FAILURE; } msConnPoolRegister(layer, layerinfo->conn, msMSSQL2008CloseConnection); } setMSSQL2008LayerInfo(layer, layerinfo); if (msMSSQL2008LayerParseData(layer, &layerinfo->geom_column, &layerinfo->geom_column_type, &layerinfo->geom_table, &layerinfo->urid_name, &layerinfo->user_srid, &layerinfo->index_name, layer->debug) != MS_SUCCESS) { msSetError( MS_QUERYERR, "Could not parse the layer data", "msMSSQL2008LayerOpen()"); return MS_FAILURE; } /* identify the geometry transfer type */ if (msLayerGetProcessingKey( layer, "MSSQL_READ_WKB" ) != NULL) layerinfo->geometry_format = MSSQLGEOMETRY_WKB; else { layerinfo->geometry_format = MSSQLGEOMETRY_NATIVE; if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) layerinfo->gpi.nColType = MSSQLCOLTYPE_GEOGRAPHY; else layerinfo->gpi.nColType = MSSQLCOLTYPE_GEOMETRY; } return MS_SUCCESS; } /* Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msMSSQL2008LayerIsOpen(layerObj *layer) { return getMSSQL2008LayerInfo(layer) ? MS_TRUE : MS_FALSE; } /* Free the itemindexes array in a layer. */ void msMSSQL2008LayerFreeItemInfo(layerObj *layer) { if(layer->debug) { msDebug("msMSSQL2008LayerFreeItemInfo called\n"); } if(layer->iteminfo) { msFree(layer->iteminfo); } layer->iteminfo = NULL; } /* allocate the iteminfo index array - same order as the item list */ int msMSSQL2008LayerInitItemInfo(layerObj *layer) { int i; int *itemindexes ; if (layer->debug) { msDebug("msMSSQL2008LayerInitItemInfo called\n"); } if(layer->numitems == 0) { return MS_SUCCESS; } msFree(layer->iteminfo); layer->iteminfo = (int *) msSmallMalloc(sizeof(int) * layer->numitems); itemindexes = (int*)layer->iteminfo; for(i = 0; i < layer->numitems; i++) { itemindexes[i] = i; /* last one is always the geometry one - the rest are non-geom */ } return MS_SUCCESS; } /* Prepare and execute the SQL statement for this layer */ static int prepare_database(layerObj *layer, rectObj rect, char **query_string) { msMSSQL2008LayerInfo *layerinfo; char *columns_wanted = 0; char *data_source = 0; char *f_table_name = 0; char *geom_table = 0; /* "Geometry::STGeomFromText('POLYGON(())',)" + terminator = 40 chars Plus 10 formatted doubles (15 digits of precision, a decimal point, a space/comma delimiter each = 17 chars each) Plus SRID + comma - if SRID is a long...we'll be safe with 10 chars */ char box3d[40 + 10 * 22 + 11]; char query_string_temp[10000]; /* Should be big enough */ int t; char *pos_from, *pos_ftab, *pos_space, *pos_paren; rectObj extent; layerinfo = getMSSQL2008LayerInfo(layer); /* Extract the proper f_table_name from the geom_table string. * We are expecting the geom_table to be either a single word * or a sub-select clause that possibly includes a join -- * * (select column[,column[,...]] from ftab[ natural join table2]) as foo * * We are expecting whitespace or a ')' after the ftab name. * */ geom_table = msStrdup(layerinfo->geom_table); pos_from = strstrIgnoreCase(geom_table, " from "); if(!pos_from) { f_table_name = (char *) msSmallMalloc(strlen(geom_table) + 1); strcpy(f_table_name, geom_table); } else { /* geom_table is a sub-select clause */ pos_ftab = pos_from + 6; /* This should be the start of the ftab name */ pos_space = strstr(pos_ftab, " "); /* First space */ /* TODO strrchr is POSIX and C99, rindex is neither */ #if defined(_WIN32) && !defined(__CYGWIN__) pos_paren = strrchr(pos_ftab, ')'); #else pos_paren = rindex(pos_ftab, ')'); #endif if(!pos_space || !pos_paren) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "prepare_database()", geom_table, "Error parsing MSSQL2008 data variable: Something is wrong with your subselect statement.

\n\nMore Help:

\n\n"); return MS_FAILURE; } if (pos_paren < pos_space) { /* closing parenthesis preceeds any space */ f_table_name = (char *) msSmallMalloc(pos_paren - pos_ftab + 1); strlcpy(f_table_name, pos_ftab, pos_paren - pos_ftab + 1); } else { f_table_name = (char *) msSmallMalloc(pos_space - pos_ftab + 1); strlcpy(f_table_name, pos_ftab, pos_space - pos_ftab + 1); } } if(layer->numitems == 0) { char buffer[1000]; if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) snprintf(buffer, sizeof(buffer), "[%s],convert(varchar(36), [%s])", layerinfo->geom_column, layerinfo->urid_name); else snprintf(buffer, sizeof(buffer), "[%s].STAsBinary(),convert(varchar(36), [%s])", layerinfo->geom_column, layerinfo->urid_name); columns_wanted = msStrdup(buffer); } else { char buffer[10000] = ""; for(t = 0; t < layer->numitems; t++) { snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(varchar(max), [%s]),", layer->items[t]); } if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "[%s],convert(varchar(36), [%s])", layerinfo->geom_column, layerinfo->urid_name); else snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "[%s].STAsBinary(),convert(varchar(36), [%s])", layerinfo->geom_column, layerinfo->urid_name); columns_wanted = msStrdup(buffer); } if (rect.minx == rect.maxx || rect.miny == rect.maxy) { /* create point shape for rectangles with zero area */ sprintf(box3d, "%s::STGeomFromText('POINT(%.15g %.15g)',%s)", /* %s.STSrid)", */ layerinfo->geom_column_type, rect.minx, rect.miny, layerinfo->user_srid); } else { sprintf(box3d, "%s::STGeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%s)", /* %s.STSrid)", */ layerinfo->geom_column_type, rect.minx, rect.miny, rect.maxx, rect.miny, rect.maxx, rect.maxy, rect.minx, rect.maxy, rect.minx, rect.miny, layerinfo->user_srid ); } /* substitute token '!BOX!' in geom_table with the box3d - do an unlimited # of subs */ /* to not undo the work here, we need to make sure that data_source is malloc'd here */ if(!strstr(geom_table, "!BOX!")) { data_source = (char *) msSmallMalloc(strlen(geom_table) + 1); strcpy(data_source, geom_table); } else { char* result = NULL; while (strstr(geom_table,"!BOX!")) { /* need to do a substition */ char *start, *end; char *oldresult = result; start = strstr(geom_table,"!BOX!"); end = start+5; result = (char *)msSmallMalloc((start - geom_table) + strlen(box3d) + strlen(end) +1); strlcpy(result, geom_table, start - geom_table + 1); strcpy(result + (start - geom_table), box3d); strcat(result, end); geom_table= result; msFree(oldresult); } /* if we're here, this will be a malloc'd string, so no need to copy it */ data_source = (char *)geom_table; } /* use the index hint if provided */ if ( layerinfo->index_name ) { /* given the template - figure out how much to malloc and malloc it */ char *with_template = "%s WITH (INDEX(%s))"; int need_len = strlen(data_source) + strlen(with_template) + strlen(layerinfo->index_name); char *tmp = (char*) msSmallMalloc( need_len + 1 ); sprintf( tmp, with_template, data_source, layerinfo->index_name ); msFree(data_source); data_source = tmp; } /* test whether we should omit spatial filtering */ msMSSQL2008LayerGetExtent(layer, &extent); if (rect.minx <= extent.minx && rect.miny <= extent.miny && rect.maxx >= extent.maxx && rect.maxy >= extent.maxy) { /* no spatial filter used */ if(!layer->filter.string) { snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s", columns_wanted, data_source ); } else { snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE (%s)", columns_wanted, data_source, layer->filter.string ); } } else { if(!layer->filter.string) { snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE %s.STIntersects(%s) = 1 ", columns_wanted, data_source, layerinfo->geom_column, box3d ); } else { snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE (%s) and %s.STIntersects(%s) = 1 ", columns_wanted, data_source, layer->filter.string, layerinfo->geom_column, box3d ); } } msFree(data_source); msFree(f_table_name); msFree(columns_wanted); if(layer->debug) { msDebug("query_string_temp:%s\n", query_string_temp); } if (executeSQL(layerinfo->conn, query_string_temp)) { *query_string = msStrdup(query_string_temp); return MS_SUCCESS; } else { msSetError(MS_QUERYERR, "Error executing MSSQL2008 SQL statement: %s\n-%s\n", "msMSSQL2008LayerGetShape()", query_string_temp, layerinfo->conn->errorMessage); return MS_FAILURE; } } /* Execute SQL query for this layer */ int msMSSQL2008LayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msMSSQL2008LayerInfo *layerinfo = 0; char *query_str = 0; int set_up_result; if(layer->debug) { msDebug("msMSSQL2008LayerWhichShapes called\n"); } layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { /* layer not opened yet */ msSetError(MS_QUERYERR, "msMSSQL2008LayerWhichShapes called on unopened layer (layerinfo = NULL)", "msMSSQL2008LayerWhichShapes()"); return MS_FAILURE; } if(!layer->data) { msSetError(MS_QUERYERR, "Missing DATA clause in MSSQL2008 Layer definition. DATA statement must contain 'geometry_column from table_name' or 'geometry_column from (sub-query) as foo'.", "msMSSQL2008LayerWhichShapes()"); return MS_FAILURE; } set_up_result = prepare_database(layer, rect, &query_str); if(set_up_result != MS_SUCCESS) { msFree(query_str); return set_up_result; /* relay error */ } msFree(layerinfo->sql); layerinfo->sql = query_str; layerinfo->row_num = 0; return MS_SUCCESS; } /* Close the MSSQL2008 record set and connection */ int msMSSQL2008LayerClose(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; layerinfo = getMSSQL2008LayerInfo(layer); if(layer->debug) { char *data = ""; if (layer->data) { data = layer->data; } msDebug("msMSSQL2008LayerClose datastatement: %s\n", data); } if(layer->debug && !layerinfo) { msDebug("msMSSQL2008LayerClose -- layerinfo is NULL\n"); } if(layerinfo) { msConnPoolRelease(layer, layerinfo->conn); layerinfo->conn = NULL; if(layerinfo->user_srid) { msFree(layerinfo->user_srid); layerinfo->user_srid = NULL; } if(layerinfo->urid_name) { msFree(layerinfo->urid_name); layerinfo->urid_name = NULL; } if(layerinfo->index_name) { msFree(layerinfo->index_name); layerinfo->index_name = NULL; } if(layerinfo->sql) { msFree(layerinfo->sql); layerinfo->sql = NULL; } if(layerinfo->geom_column) { msFree(layerinfo->geom_column); layerinfo->geom_column = NULL; } if(layerinfo->geom_column_type) { msFree(layerinfo->geom_column_type); layerinfo->geom_column_type = NULL; } if(layerinfo->geom_table) { msFree(layerinfo->geom_table); layerinfo->geom_table = NULL; } setMSSQL2008LayerInfo(layer, NULL); msFree(layerinfo); } return MS_SUCCESS; } /* ******************************************************* */ /* wkb is assumed to be 2d (force_2d) */ /* and wkb is a GEOMETRYCOLLECTION (force_collection) */ /* and wkb is in the endian of this computer (asbinary(...,'[XN]DR')) */ /* each of the sub-geom inside the collection are point,linestring, or polygon */ /* */ /* also, int is 32bits long */ /* double is 64bits long */ /* ******************************************************* */ /* convert the wkb into points */ /* points -> pass through */ /* lines-> constituent points */ /* polys-> treat ring like line and pull out the consituent points */ static int force_to_points(char *wkb, shapeObj *shape) { /* we're going to make a 'line' for each entity (point, line or ring) in the geom collection */ int offset = 0; int pt_offset; int ngeoms; int t, u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t=0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if(type == 1) { /* Point */ shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)); memcpy(&line.point[0].x, &wkb[offset + 5], 8); memcpy(&line.point[0].y, &wkb[offset + 5 + 8], 8); offset += 5 + 16; msAddLine(shape, &line); msFree(line.point); } else if(type == 2) { /* Linestring */ shape->type = MS_SHAPE_POINT; memcpy(&line.numpoints, &wkb[offset+5], 4); /* num points */ line.point = (pointObj *) msSmallMalloc(sizeof(pointObj) * line.numpoints); for(u = 0; u < line.numpoints; u++) { memcpy( &line.point[u].x, &wkb[offset+9 + (16 * u)], 8); memcpy( &line.point[u].y, &wkb[offset+9 + (16 * u)+8], 8); } offset += 9 + 16 * line.numpoints; /* length of object */ msAddLine(shape, &line); msFree(line.point); } else if(type == 3) { /* Polygon */ shape->type = MS_SHAPE_POINT; memcpy(&nrings, &wkb[offset+5],4); /* num rings */ /* add a line for each polygon ring */ pt_offset = 0; offset += 9; /* now points at 1st linear ring */ for(u = 0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); /* num points */ line.numpoints = npoints; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)* npoints); /* point struct */ for(v = 0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 *npoints; } } } return MS_SUCCESS; } /* convert the wkb into lines */ /* points-> remove */ /* lines -> pass through */ /* polys -> treat rings as lines */ static int force_to_lines(char *wkb, shapeObj *shape) { int offset = 0; int pt_offset; int ngeoms; int t, u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t=0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ /* cannot do anything with a point */ if(type == 2) { /* Linestring */ shape->type = MS_SHAPE_LINE; memcpy(&line.numpoints, &wkb[offset + 5], 4); line.point = (pointObj*) msSmallMalloc(sizeof(pointObj) * line.numpoints ); for(u=0; u < line.numpoints; u++) { memcpy(&line.point[u].x, &wkb[offset + 9 + (16 * u)], 8); memcpy(&line.point[u].y, &wkb[offset + 9 + (16 * u)+8], 8); } offset += 9 + 16 * line.numpoints; /* length of object */ msAddLine(shape, &line); msFree(line.point); } else if(type == 3) { /* polygon */ shape->type = MS_SHAPE_LINE; memcpy(&nrings, &wkb[offset + 5], 4); /* num rings */ /* add a line for each polygon ring */ pt_offset = 0; offset += 9; /* now points at 1st linear ring */ for(u = 0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); line.numpoints = npoints; line.point = (pointObj*) msSmallMalloc(sizeof(pointObj) * npoints); /* point struct */ for(v = 0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 * npoints; } } } return MS_SUCCESS; } /* point -> reject */ /* line -> reject */ /* polygon -> lines of linear rings */ static int force_to_polygons(char *wkb, shapeObj *shape) { int offset = 0; int pt_offset; int ngeoms; int t, u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t = 0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if(type == 3) { /* polygon */ shape->type = MS_SHAPE_POLYGON; memcpy(&nrings, &wkb[offset + 5], 4); /* num rings */ /* add a line for each polygon ring */ pt_offset = 0; offset += 9; /* now points at 1st linear ring */ for(u=0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); /* num points */ line.numpoints = npoints; line.point = (pointObj*) msSmallMalloc(sizeof(pointObj) * npoints); for(v=0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 * npoints; } } } return MS_SUCCESS; } /* if there is any polygon in wkb, return force_polygon */ /* if there is any line in wkb, return force_line */ /* otherwise return force_point */ static int dont_force(char *wkb, shapeObj *shape) { int offset =0; int ngeoms; int type, t; int best_type; best_type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t = 0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if(type == 3) { best_type = MS_SHAPE_POLYGON; } else if(type ==2 && best_type != MS_SHAPE_POLYGON) { best_type = MS_SHAPE_LINE; } else if(type == 1 && best_type == MS_SHAPE_NULL) { best_type = MS_SHAPE_POINT; } } if(best_type == MS_SHAPE_POINT) { return force_to_points(wkb, shape); } if(best_type == MS_SHAPE_LINE) { return force_to_lines(wkb, shape); } if(best_type == MS_SHAPE_POLYGON) { return force_to_polygons(wkb, shape); } return MS_FAILURE; /* unknown type */ } /* ******************************************************* */ /* wkb assumed to be same endian as this machine. */ /* Should be in little endian (default if created by Microsoft platforms) */ /* ******************************************************* */ /* convert the wkb into points */ /* points -> pass through */ /* lines-> constituent points */ /* polys-> treat ring like line and pull out the consituent points */ static int force_to_shapeType(char *wkb, shapeObj *shape, int msShapeType) { int offset = 0; int ngeoms = 1; int u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ do { ngeoms--; memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if (type == 1) { /* Point */ shape->type = msShapeType; line.numpoints = 1; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)); memcpy(&line.point[0].x, &wkb[offset + 5], 8); memcpy(&line.point[0].y, &wkb[offset + 5 + 8], 8); offset += 5 + 16; if (msShapeType == MS_SHAPE_POINT) { msAddLine(shape, &line); } msFree(line.point); } else if(type == 2) { /* Linestring */ shape->type = msShapeType; memcpy(&line.numpoints, &wkb[offset+5], 4); /* num points */ line.point = (pointObj *) msSmallMalloc(sizeof(pointObj) * line.numpoints); for(u = 0; u < line.numpoints; u++) { memcpy( &line.point[u].x, &wkb[offset+9 + (16 * u)], 8); memcpy( &line.point[u].y, &wkb[offset+9 + (16 * u)+8], 8); } offset += 9 + 16 * line.numpoints; /* length of object */ if ((msShapeType == MS_SHAPE_POINT) || (msShapeType == MS_SHAPE_LINE)) { msAddLine(shape, &line); } msFree(line.point); } else if(type == 3) { /* Polygon */ shape->type = msShapeType; memcpy(&nrings, &wkb[offset+5],4); /* num rings */ /* add a line for each polygon ring */ offset += 9; /* now points at 1st linear ring */ for(u = 0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); /* num points */ line.numpoints = npoints; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)* npoints); /* point struct */ for(v = 0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 *npoints; } } else if(type >= 4 && type <= 7) { int cnt = 0; offset += 5; memcpy(&cnt, &wkb[offset], 4); offset += 4; /* were the first geometry is */ ngeoms += cnt; } } while (ngeoms > 0); return MS_SUCCESS; } ///* if there is any polygon in wkb, return force_polygon */ ///* if there is any line in wkb, return force_line */ ///* otherwise return force_point */ //static int dont_force(char *wkb, shapeObj *shape) //{ // int offset =0; // int ngeoms = 1; // int type; // int best_type; // int u; // int nrings, npoints; // // best_type = MS_SHAPE_NULL; /* nothing in it */ // // do // { // ngeoms--; // // memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ // // if(type == 3) { // best_type = MS_SHAPE_POLYGON; // } else if(type ==2 && best_type != MS_SHAPE_POLYGON) { // best_type = MS_SHAPE_LINE; // } else if(type == 1 && best_type == MS_SHAPE_NULL) { // best_type = MS_SHAPE_POINT; // } // // if (type == 1) // { // /* Point */ // offset += 5 + 16; // } // else if(type == 2) // { // int numPoints; // // memcpy(&numPoints, &wkb[offset+5], 4); /* num points */ // /* Linestring */ // offset += 9 + 16 * numPoints; /* length of object */ // } // else if(type == 3) // { // /* Polygon */ // memcpy(&nrings, &wkb[offset+5],4); /* num rings */ // offset += 9; /* now points at 1st linear ring */ // for(u = 0; u < nrings; u++) { // /* for each ring, make a line */ // memcpy(&npoints, &wkb[offset], 4); /* num points */ // offset += 4 + 16 *npoints; // } // } // else if(type >= 4 && type <= 7) // { // int cnt = 0; // // offset += 5; // // memcpy(&cnt, &wkb[offset], 4); // offset += 4; /* were the first geometry is */ // // ngeoms += cnt; // } // } // while (ngeoms > 0); // // return force_to_shapeType(wkb, shape, best_type); //} // /* find the bounds of the shape */ static void find_bounds(shapeObj *shape) { int t, u; int first_one = 1; for(t = 0; t < shape->numlines; t++) { for(u = 0; u < shape->line[t].numpoints; u++) { if(first_one) { shape->bounds.minx = shape->line[t].point[u].x; shape->bounds.maxx = shape->line[t].point[u].x; shape->bounds.miny = shape->line[t].point[u].y; shape->bounds.maxy = shape->line[t].point[u].y; first_one = 0; } else { if(shape->line[t].point[u].x < shape->bounds.minx) { shape->bounds.minx = shape->line[t].point[u].x; } if(shape->line[t].point[u].x > shape->bounds.maxx) { shape->bounds.maxx = shape->line[t].point[u].x; } if(shape->line[t].point[u].y < shape->bounds.miny) { shape->bounds.miny = shape->line[t].point[u].y; } if(shape->line[t].point[u].y > shape->bounds.maxy) { shape->bounds.maxy = shape->line[t].point[u].y; } } } } } /* Used by NextShape() to access a shape in the query set */ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *record) { msMSSQL2008LayerInfo *layerinfo; int result; SQLINTEGER needLen = 0; SQLINTEGER retLen = 0; char dummyBuffer[1]; char *wkbBuffer; char *valueBuffer; char oidBuffer[ 16 ]; /* assuming the OID will always be a long this should be enough */ long record_oid; int t; /* for coercing single types into geometry collections */ char *wkbTemp; int geomType; layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { msSetError(MS_QUERYERR, "GetShape called with layerinfo = NULL", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } if(!layerinfo->conn) { msSetError(MS_QUERYERR, "NextShape called on MSSQL2008 layer with no connection to DB.", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } shape->type = MS_SHAPE_NULL; while(shape->type == MS_SHAPE_NULL) { /* SQLRETURN rc = SQLFetchScroll(layerinfo->conn->hstmt, SQL_FETCH_ABSOLUTE, (SQLINTEGER) (*record) + 1); */ /* We only do forward fetches. the parameter 'record' is ignored, but is incremented */ SQLRETURN rc = SQLFetch(layerinfo->conn->hstmt); /* Any error assume out of recordset bounds */ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { handleSQLError(layer); return MS_DONE; } /* retreive an item */ { /* have to retrieve shape attributes */ shape->values = (char **) msSmallMalloc(sizeof(char *) * layer->numitems); shape->numvalues = layer->numitems; for(t=0; t < layer->numitems; t++) { /* figure out how big the buffer needs to be */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(t + 1), SQL_C_BINARY, dummyBuffer, 0, &needLen); if (rc == SQL_ERROR) handleSQLError(layer); if (needLen > 0) { /* allocate the buffer - this will be a null-terminated string so alloc for the null too */ valueBuffer = (char*) msSmallMalloc( needLen + 1 ); if ( valueBuffer == NULL ) { msSetError( MS_QUERYERR, "Could not allocate value buffer.", "msMSSQL2008LayerGetShapeRandom()" ); return MS_FAILURE; } /* Now grab the data */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(t + 1), SQL_C_BINARY, valueBuffer, needLen, &retLen); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) handleSQLError(layer); /* Terminate the buffer */ valueBuffer[retLen] = 0; /* null terminate it */ /* Pop the value into the shape's value array */ shape->values[t] = valueBuffer; } else /* Copy empty sting for NULL values */ shape->values[t] = msStrdup(""); } /* Get shape geometry */ { /* Set up to request the size of the buffer needed */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(layer->numitems + 1), SQL_C_BINARY, dummyBuffer, 0, &needLen); if (rc == SQL_ERROR) handleSQLError(layer); /* allow space for coercion to geometry collection if needed*/ wkbTemp = (char*)msSmallMalloc(needLen+9); /* write data above space allocated for geometry collection coercion */ wkbBuffer = wkbTemp + 9; if ( wkbBuffer == NULL ) { msSetError( MS_QUERYERR, "Could not allocate value buffer.", "msMSSQL2008LayerGetShapeRandom()" ); return MS_FAILURE; } /* Grab the WKB */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(layer->numitems + 1), SQL_C_BINARY, wkbBuffer, needLen, &retLen); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) handleSQLError(layer); if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) { layerinfo->gpi.pszData = (unsigned char*)wkbBuffer; layerinfo->gpi.nLen = retLen; if (!ParseSqlGeometry(layerinfo, shape)) { switch(layer->type) { case MS_LAYER_POINT: shape->type = MS_SHAPE_POINT; break; case MS_LAYER_LINE: shape->type = MS_SHAPE_LINE; break; case MS_LAYER_POLYGON: shape->type = MS_SHAPE_POLYGON; break; } } } else { memcpy(&geomType, wkbBuffer + 1, 4); /* is this a single type? */ if (geomType < 4) { /* copy byte order marker (although we don't check it) */ wkbTemp[0] = wkbBuffer[0]; wkbBuffer = wkbTemp; /* indicate type is geometry collection (although geomType + 3 would also work) */ wkbBuffer[1] = (char)7; wkbBuffer[2] = (char)0; wkbBuffer[3] = (char)0; wkbBuffer[4] = (char)0; /* indicate 1 shape */ wkbBuffer[5] = (char)1; wkbBuffer[6] = (char)0; wkbBuffer[7] = (char)0; wkbBuffer[8] = (char)0; } switch(layer->type) { case MS_LAYER_POINT: result = force_to_points(wkbBuffer, shape); break; case MS_LAYER_LINE: result = force_to_lines(wkbBuffer, shape); break; case MS_LAYER_POLYGON: result = force_to_polygons(wkbBuffer, shape); break; case MS_LAYER_ANNOTATION: case MS_LAYER_QUERY: case MS_LAYER_CHART: result = dont_force(wkbBuffer, shape); break; case MS_LAYER_RASTER: msDebug( "Ignoring MS_LAYER_RASTER in mapMSSQL2008.c\n" ); break; case MS_LAYER_CIRCLE: msDebug( "Ignoring MS_LAYER_CIRCLE in mapMSSQL2008.c\n" ); break; default: msDebug( "Unsupported layer type in msMSSQL2008LayerNextShape()!" ); break; } find_bounds(shape); } //free(wkbBuffer); msFree(wkbTemp); } /* Next get unique id for row - since the OID shouldn't be larger than a long we'll assume billions as a limit */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(layer->numitems + 2), SQL_C_BINARY, oidBuffer, sizeof(oidBuffer) - 1, &retLen); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) handleSQLError(layer); if (retLen < sizeof(oidBuffer)) { oidBuffer[retLen] = 0; record_oid = strtol(oidBuffer, NULL, 10); shape->index = record_oid; } else { /* non integer fid column, use single pass */ shape->index = -1; } shape->resultindex = (*record); (*record)++; /* move to next shape */ if(shape->type != MS_SHAPE_NULL) { return MS_SUCCESS; } else { msDebug("msMSSQL2008LayerGetShapeRandom bad shape: %d\n", *record); } /* if (layer->type == MS_LAYER_POINT) {return MS_DONE;} */ } } msFreeShape(shape); return MS_FAILURE; } /* find the next shape with the appropriate shape type (convert it if necessary) */ /* also, load in the attribute data */ /* MS_DONE => no more data */ int msMSSQL2008LayerNextShape(layerObj *layer, shapeObj *shape) { int result; msMSSQL2008LayerInfo *layerinfo; layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { msSetError(MS_QUERYERR, "NextShape called with layerinfo = NULL", "msMSSQL2008LayerNextShape()"); return MS_FAILURE; } result = msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)); /* getshaperandom will increment the row_num */ /* layerinfo->row_num ++; */ return result; } /* Execute a query on the DB based on the query result. */ int msMSSQL2008LayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { char *query_str; char *columns_wanted = 0; msMSSQL2008LayerInfo *layerinfo; int t; char buffer[32000] = ""; long shapeindex = record->shapeindex; long resultindex = record->resultindex; if(layer->debug) { msDebug("msMSSQL2008LayerGetShape called for shapeindex = %i\n", shapeindex); } layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { /* Layer not open */ msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShape called on unopened layer (layerinfo = NULL)", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } if (resultindex >= 0 && layerinfo->sql) { /* trying to provide the result from the current resultset (single-pass query) */ if( resultindex < layerinfo->row_num) { /* re-issue the query */ if (!executeSQL(layerinfo->conn, layerinfo->sql)) { msSetError(MS_QUERYERR, "Error executing MSSQL2008 SQL statement: %s\n-%s\n", "msMSSQL2008LayerGetShape()", layerinfo->sql, layerinfo->conn->errorMessage); return MS_FAILURE; } layerinfo->row_num = 0; } while( layerinfo->row_num < resultindex ) { /* move forward until we reach the desired index */ if (msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)) != MS_SUCCESS) return MS_FAILURE; } return msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)); } /* non single-pass case, fetch the record from the database */ if(layer->numitems == 0) { if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) snprintf(buffer, sizeof(buffer), "%s, convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); else snprintf(buffer, sizeof(buffer), "%s.STAsBinary(), convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); columns_wanted = msStrdup(buffer); } else { for(t = 0; t < layer->numitems; t++) { snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(varchar(max), %s),", layer->items[t]); } if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%s, convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); else snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%s.STAsBinary(), convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); columns_wanted = msStrdup(buffer); } /* index_name is ignored here since the hint should be for the spatial index, not the PK index */ snprintf(buffer, sizeof(buffer), "select %s from %s where %s = %d", columns_wanted, layerinfo->geom_table, layerinfo->urid_name, shapeindex); query_str = msStrdup(buffer); if(layer->debug) { msDebug("msMSSQL2008LayerGetShape: %s \n", query_str); } msFree(columns_wanted); if (!executeSQL(layerinfo->conn, query_str)) { msSetError(MS_QUERYERR, "Error executing MSSQL2008 SQL statement: %s\n-%s\n", "msMSSQL2008LayerGetShape()", query_str, layerinfo->conn->errorMessage); msFree(query_str); return MS_FAILURE; } /* we don't preserve the query string in this case (cannot be re-used) */ msFree(query_str); layerinfo->row_num = 0; return msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)); } /* Query the DB for info about the requested table */ int msMSSQL2008LayerGetItems(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; char *sql = NULL; int t, sqlSize; char found_geom = 0; int item_num; SQLSMALLINT cols = 0; if(layer->debug) { msDebug("in msMSSQL2008LayerGetItems (find column names)\n"); } layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { /* layer not opened yet */ msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems called on unopened layer", "msMSSQL2008LayerGetItems()"); return MS_FAILURE; } if(!layerinfo->conn) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems called on MSSQL2008 layer with no connection to DB.", "msMSSQL2008LayerGetItems()"); return MS_FAILURE; } sqlSize = strlen(layerinfo->geom_table) + 30; sql = msSmallMalloc(sizeof(char *) * sqlSize); snprintf(sql, sqlSize, "SELECT top 0 * FROM %s", layerinfo->geom_table); if (!executeSQL(layerinfo->conn, sql)) { msFree(sql); return MS_FAILURE; } msFree(sql); SQLNumResultCols (layerinfo->conn->hstmt, &cols); layer->numitems = cols - 1; /* dont include the geometry column */ layer->items = msSmallMalloc(sizeof(char *) * (layer->numitems + 1)); /* +1 in case there is a problem finding goeometry column */ /* it will return an error if there is no geometry column found, */ /* so this isnt a problem */ found_geom = 0; /* havent found the geom field */ item_num = 0; for(t = 0; t < cols; t++) { char colBuff[256]; columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff)); if(strcmp(colBuff, layerinfo->geom_column) != 0) { /* this isnt the geometry column */ layer->items[item_num] = (char *) msSmallMalloc(strlen(colBuff) + 1); strcpy(layer->items[item_num], colBuff); item_num++; } else { found_geom = 1; } } if(!found_geom) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems: tried to find the geometry column in the results from the database, but couldnt find it. Is it miss-capitialized? '%s'", "msMSSQL2008LayerGetItems()", layerinfo->geom_column); return MS_FAILURE; } return msMSSQL2008LayerInitItemInfo(layer); } /* Get the layer extent as specified in the mapfile or a largest area */ /* covering all features */ int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent) { if(layer->debug) { msDebug("msMSSQL2008LayerGetExtent called\n"); } if (layer->extent.minx == -1.0 && layer->extent.miny == -1.0 && layer->extent.maxx == -1.0 && layer->extent.maxy == -1.0) { extent->minx = extent->miny = -1.0 * FLT_MAX; extent->maxx = extent->maxy = FLT_MAX; } else { extent->minx = layer->extent.minx; extent->miny = layer->extent.miny; extent->maxx = layer->extent.maxx; extent->maxy = layer->extent.maxy; } return MS_SUCCESS; } /* Get primary key column of table */ int msMSSQL2008LayerRetrievePK(layerObj *layer, char **urid_name, char* table_name, int debug) { char sql[1024]; msMSSQL2008LayerInfo *layerinfo = 0; SQLRETURN rc; snprintf(sql, sizeof(sql), "SELECT convert(varchar(50), sys.columns.name) AS ColumnName, sys.indexes.name " "FROM sys.columns INNER JOIN " " sys.indexes INNER JOIN " " sys.tables ON sys.indexes.object_id = sys.tables.object_id INNER JOIN " " sys.index_columns ON sys.indexes.object_id = sys.index_columns.object_id AND sys.indexes.index_id = sys.index_columns.index_id ON " " sys.columns.object_id = sys.index_columns.object_id AND sys.columns.column_id = sys.index_columns.column_id " "WHERE (sys.indexes.is_primary_key = 1) AND (sys.tables.name = N'%s') ", table_name); if (debug) { msDebug("msMSSQL2008LayerRetrievePK: query = %s\n", sql); } layerinfo = (msMSSQL2008LayerInfo *) layer->layerinfo; if(layerinfo->conn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a MSSQL2008 connection.", "msMSSQL2008LayerRetrievePK()"); return(MS_FAILURE); } /* error somewhere above here in this method */ if(!executeSQL(layerinfo->conn, sql)) { char *tmp1; char *tmp2 = NULL; tmp1 = "Error executing MSSQL2008 statement (msMSSQL2008LayerRetrievePK():"; tmp2 = (char *)msSmallMalloc(sizeof(char)*(strlen(tmp1) + strlen(sql) + 1)); strcpy(tmp2, tmp1); strcat(tmp2, sql); msSetError(MS_QUERYERR, tmp2, "msMSSQL2008LayerRetrievePK()"); msFree(tmp2); return(MS_FAILURE); } rc = SQLFetch(layerinfo->conn->hstmt); if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if(debug) { msDebug("msMSSQL2008LayerRetrievePK: No results found.\n"); } return MS_FAILURE; } { char buff[100]; SQLINTEGER retLen; rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_BINARY, buff, sizeof(buff), &retLen); rc = SQLFetch(layerinfo->conn->hstmt); if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { if(debug) { msDebug("msMSSQL2008LayerRetrievePK: Multiple primary key columns are not supported in MapServer\n"); } return MS_FAILURE; } buff[retLen] = 0; *urid_name = msStrdup(buff); } return MS_SUCCESS; } /* Function to parse the Mapserver DATA parameter for geometry * column name, table name and name of a column to serve as a * unique record id */ static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, char **geom_column_type, char **table_name, char **urid_name, char **user_srid, char **index_name, int debug) { char *pos_opt, *pos_scn, *tmp, *pos_srid, *pos_urid, *pos_geomtype, *pos_geomtype2, *pos_indexHint, *data; int slength; data = msStrdup(layer->data); /* replace tabs with spaces */ msReplaceChar(data, '\t', ' '); /* given a string of the from 'geom from ctivalues' or 'geom from () as foo' * return geom_column_name as 'geom' * and table name as 'ctivalues' or 'geom from () as foo' */ /* First look for the optional ' using unique ID' string */ pos_urid = strstrIgnoreCase(data, " using unique "); if(pos_urid) { /* CHANGE - protect the trailing edge for thing like 'using unique ftab_id using srid=33' */ tmp = strstr(pos_urid + 14, " "); if(!tmp) { tmp = pos_urid + strlen(pos_urid); } *urid_name = (char *) msSmallMalloc((tmp - (pos_urid + 14)) + 1); strlcpy(*urid_name, pos_urid + 14, (tmp - (pos_urid + 14)) + 1); } /* Find the srid */ pos_srid = strstrIgnoreCase(data, " using SRID="); if(!pos_srid) { *user_srid = (char *) msSmallMalloc(2); (*user_srid)[0] = '0'; (*user_srid)[1] = 0; } else { slength = strspn(pos_srid + 12, "-0123456789"); if(!slength) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable: You specified 'using SRID=#' but didnt have any numbers!

\n\nMore Help:

\n\n", data); msFree(data); return MS_FAILURE; } else { *user_srid = (char *) msSmallMalloc(slength + 1); strlcpy(*user_srid, pos_srid + 12, slength+1); } } pos_indexHint = strstrIgnoreCase(data, " using index "); if(pos_indexHint) { /* CHANGE - protect the trailing edge for thing like 'using unique ftab_id using srid=33' */ tmp = strstr(pos_indexHint + 13, " "); if(!tmp) { tmp = pos_indexHint + strlen(pos_indexHint); } *index_name = (char *) msSmallMalloc((tmp - (pos_indexHint + 13)) + 1); strlcpy(*index_name, pos_indexHint + 13, tmp - (pos_indexHint + 13)+1); } /* this is a little hack so the rest of the code works. If the ' using SRID=' comes before */ /* the ' using unique ', then make sure pos_opt points to where the ' using SRID' starts! */ pos_opt = pos_urid; if ( !pos_opt || ( pos_srid && pos_srid < pos_opt ) ) pos_opt = pos_srid; if ( !pos_opt || ( pos_indexHint && pos_indexHint < pos_opt ) ) pos_opt = pos_indexHint; if ( !pos_opt ) pos_opt = data + strlen(data); /* Scan for the table or sub-select clause */ pos_scn = strstrIgnoreCase(data, " from "); if(!pos_scn) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable. Must contain 'geometry_column from table_name' or 'geom from (subselect) as foo' (couldn't find ' from '). More help:

\n\n", data); msFree(data); return MS_FAILURE; } /* Scanning the geometry column type */ pos_geomtype = data; while (pos_geomtype < pos_scn && *pos_geomtype != '(' && *pos_geomtype != 0) ++pos_geomtype; if(*pos_geomtype == '(') { pos_geomtype2 = pos_geomtype; while (pos_geomtype2 < pos_scn && *pos_geomtype2 != ')' && *pos_geomtype2 != 0) ++pos_geomtype2; if (*pos_geomtype2 != ')' || pos_geomtype2 == pos_geomtype) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable. Invalid syntax near geometry column type.", data); msFree(data); return MS_FAILURE; } *geom_column_name = (char *) msSmallMalloc((pos_geomtype - data) + 1); strlcpy(*geom_column_name, data, pos_geomtype - data + 1); *geom_column_type = (char *) msSmallMalloc(pos_geomtype2 - pos_geomtype); strlcpy(*geom_column_type, pos_geomtype + 1, pos_geomtype2 - pos_geomtype); } else { /* Copy the geometry column name */ *geom_column_name = (char *) msSmallMalloc((pos_scn - data) + 1); strlcpy(*geom_column_name, data, pos_scn - data + 1); *geom_column_type = msStrdup("geometry"); } /* Copy out the table name or sub-select clause */ *table_name = (char *) msSmallMalloc((pos_opt - (pos_scn + 6)) + 1); strlcpy(*table_name, pos_scn + 6, pos_opt - (pos_scn + 6) + 1); if(strlen(*table_name) < 1 || strlen(*geom_column_name) < 1) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable. Must contain 'geometry_column from table_name' or 'geom from (subselect) as foo' (couldnt find a geometry_column or table/subselect). More help:

\n\n", data); msFree(data); return MS_FAILURE; } if( !pos_urid ) { if( msMSSQL2008LayerRetrievePK(layer, urid_name, *table_name, debug) != MS_SUCCESS ) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "No primary key defined for table, or primary key contains more that one column\n\n", *table_name); msFree(data); return MS_FAILURE; } } if(debug) { msDebug("msMSSQL2008LayerParseData: unique column = %s, srid='%s', geom_column_name = %s, table_name=%s\n", *urid_name, *user_srid, *geom_column_name, *table_name); } msFree(data); return MS_SUCCESS; } #else /* prototypes if MSSQL2008 isnt supposed to be compiled */ int msMSSQL2008LayerOpen(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerOpen called but unimplemented! (mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerOpen()"); return MS_FAILURE; } int msMSSQL2008LayerIsOpen(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008IsLayerOpen called but unimplemented! (mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerIsOpen()"); return MS_FALSE; } void msMSSQL2008LayerFreeItemInfo(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerFreeItemInfo called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerFreeItemInfo()"); } int msMSSQL2008LayerInitItemInfo(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerInitItemInfo called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerInitItemInfo()"); return MS_FAILURE; } int msMSSQL2008LayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msSetError(MS_QUERYERR, "msMSSQL2008LayerWhichShapes called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerWhichShapes()"); return MS_FAILURE; } int msMSSQL2008LayerClose(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerClose called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerClose()"); return MS_FAILURE; } int msMSSQL2008LayerNextShape(layerObj *layer, shapeObj *shape) { msSetError(MS_QUERYERR, "msMSSQL2008LayerNextShape called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerNextShape()"); return MS_FAILURE; } int msMSSQL2008LayerGetShape(layerObj *layer, shapeObj *shape, long record) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShape called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetExtent called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *record) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShapeRandom called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetShapeRandom()"); return MS_FAILURE; } int msMSSQL2008LayerGetItems(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetItems()"); return MS_FAILURE; } /* end above's #ifdef USE_MSSQL2008 */ #endif #ifdef USE_MSSQL2008_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); vtable->LayerInitItemInfo = msMSSQL2008LayerInitItemInfo; vtable->LayerFreeItemInfo = msMSSQL2008LayerFreeItemInfo; vtable->LayerOpen = msMSSQL2008LayerOpen; vtable->LayerIsOpen = msMSSQL2008LayerIsOpen; vtable->LayerWhichShapes = msMSSQL2008LayerWhichShapes; vtable->LayerNextShape = msMSSQL2008LayerNextShape; vtable->LayerGetShape = msMSSQL2008LayerGetShape; vtable->LayerClose = msMSSQL2008LayerClose; vtable->LayerGetItems = msMSSQL2008LayerGetItems; vtable->LayerGetExtent = msMSSQL2008LayerGetExtent; vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; /* vtable->LayerGetAutoStyle, not supported for this layer */ vtable->LayerCloseConnection = msMSSQL2008LayerClose; vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* vtable->LayerCreateItems, use default */ /* vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection, use defaut*/ return MS_SUCCESS; } #endif int msMSSQL2008LayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msMSSQL2008LayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msMSSQL2008LayerFreeItemInfo; layer->vtable->LayerOpen = msMSSQL2008LayerOpen; layer->vtable->LayerIsOpen = msMSSQL2008LayerIsOpen; layer->vtable->LayerWhichShapes = msMSSQL2008LayerWhichShapes; layer->vtable->LayerNextShape = msMSSQL2008LayerNextShape; layer->vtable->LayerGetShape = msMSSQL2008LayerGetShape; layer->vtable->LayerClose = msMSSQL2008LayerClose; layer->vtable->LayerGetItems = msMSSQL2008LayerGetItems; layer->vtable->LayerGetExtent = msMSSQL2008LayerGetExtent; layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; /* layer->vtable->LayerGetAutoStyle, not supported for this layer */ layer->vtable->LayerCloseConnection = msMSSQL2008LayerClose; layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } mapserver-6.4.1/mapprimitive.h0000644002461700001440000000546312261257215016203 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations for rectObj, pointObj, lineObj, shapeObj, etc. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPPRIMITIVE_H #define MAPPRIMITIVE_H /* feature primitives */ typedef struct { double minx, miny, maxx, maxy; } rectObj; #ifndef SWIG typedef struct { double x; double y; } vectorObj; #endif /*SWIG*/ typedef struct { double x; double y; #ifdef USE_POINT_Z_M double z; double m; #endif } pointObj; typedef struct { #ifdef SWIG %immutable; #endif int numpoints; #ifndef SWIG pointObj *point; #endif #ifdef SWIG %mutable; #endif } lineObj; typedef struct { #ifdef SWIG %immutable; #endif int numlines; int numvalues; #ifndef SWIG lineObj *line; char **values; void *geometry; void *renderer_cache; #endif #ifdef SWIG %mutable; #endif rectObj bounds; int type; /* MS_SHAPE_TYPE */ long index; int tileindex; int classindex; char *text; int scratch; int resultindex; /* index within a query result set */ } shapeObj; typedef lineObj multipointObj; #ifndef SWIG /* attribute primatives */ typedef struct { char *name; long type; int index; int size; short numdecimals; } itemObj; #endif #ifndef SWIG typedef struct { int need_geotransform; double rotation_angle; double geotransform[6]; /* Pixel/line to georef. */ double invgeotransform[6]; /* georef to pixel/line */ } geotransformObj; #endif #endif /* MAPPRIMITIVE_H */ mapserver-6.4.1/mappluginlayer.c0000644002461700001440000001706012261257215016515 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of plug-in layer functionality * Author: Jani Averbach, SRC,LLC * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include "mapserver.h" #include "mapthread.h" typedef struct { char *name; layerVTableObj vtable; } VTFactoryItemObj; typedef struct { unsigned int size; unsigned int first_free; VTFactoryItemObj ** vtItems; } VTFactoryObj; static VTFactoryObj gVirtualTableFactory = {0, 0, NULL}; static VTFactoryItemObj * createVTFItem(const char *name) { VTFactoryItemObj *pVTFI; pVTFI = (VTFactoryItemObj *)malloc(sizeof(VTFactoryItemObj)); MS_CHECK_ALLOC(pVTFI, sizeof(VTFactoryItemObj), NULL); pVTFI->name = msStrdup(name); memset(&pVTFI->vtable, 0, sizeof(layerVTableObj)); return pVTFI; } static void destroyVTFItem(VTFactoryItemObj **pVTFI) { free((*pVTFI)->name); (*pVTFI)->name = NULL; memset(&(*pVTFI)->vtable, 0, sizeof(layerVTableObj)); free(*pVTFI); *pVTFI = NULL; } static VTFactoryItemObj * lookupVTFItem(VTFactoryObj *VTFactory, const char *key) { unsigned int i; for (i=0; i < VTFactory->size && VTFactory->vtItems[i]; ++i) { if (0 == strcasecmp(key, VTFactory->vtItems[i]->name)) { return VTFactory->vtItems[i]; } } return NULL; } static int insertNewVTFItem(VTFactoryObj *pVTFactory, VTFactoryItemObj *pVTFI) { /* Ensure there is room for one more item in the array * (safe to use for initial alloc of the array as well) */ if (pVTFactory->first_free == pVTFactory->size) { int i; VTFactoryItemObj **vtItemPtr; vtItemPtr = (VTFactoryItemObj**)realloc(pVTFactory->vtItems, (pVTFactory->size+MS_LAYER_ALLOCSIZE)*sizeof(VTFactoryItemObj*)); MS_CHECK_ALLOC(vtItemPtr, (pVTFactory->size+MS_LAYER_ALLOCSIZE)*sizeof(VTFactoryItemObj*), MS_FAILURE); pVTFactory->size += MS_LAYER_ALLOCSIZE; pVTFactory->vtItems = vtItemPtr; for (i=pVTFactory->first_free; isize; i++) pVTFactory->vtItems[i] = NULL; } /* Insert item */ pVTFactory->vtItems[pVTFactory->first_free] = pVTFI; pVTFactory->first_free++; return MS_SUCCESS; } static VTFactoryItemObj * loadCustomLayerDLL(layerObj *layer, const char *library_path) { int (*pfnPluginInitVTable)(layerVTableObj *, layerObj *); VTFactoryItemObj *pVTFI; pfnPluginInitVTable = msGetSymbol(library_path, "PluginInitializeVirtualTable"); if ( ! pfnPluginInitVTable) { msSetError(MS_MISCERR, "Failed to load dynamic Layer LIB: %s", "loadCustomLayerDLL", library_path); return NULL; } pVTFI = createVTFItem(library_path); if ( ! pVTFI) { return NULL; } if (pfnPluginInitVTable(&pVTFI->vtable, layer)) { destroyVTFItem(&pVTFI); msSetError(MS_MISCERR, "Failed to initialize dynamic Layer: %s", "loadCustomLayerDLL", library_path); return NULL; } return pVTFI; } /* * copyVirtualTable * * copy one virtual table from dest to src. Both of dest and src * have to be allocated already. * * If src contains NULL fields, those are NOT copied over. * * Because of that, it is possible for plugin layer to use default * layer API default functions, just leave those function pointers to NULL. */ static void copyVirtualTable(layerVTableObj *dest, const layerVTableObj *src) { dest->LayerInitItemInfo = src->LayerInitItemInfo ? src->LayerInitItemInfo : dest->LayerInitItemInfo; dest->LayerFreeItemInfo = src->LayerFreeItemInfo ? src->LayerFreeItemInfo : dest->LayerFreeItemInfo; dest->LayerOpen = src->LayerOpen ? src->LayerOpen : dest->LayerOpen; dest->LayerIsOpen = src->LayerIsOpen ? src->LayerIsOpen : dest->LayerIsOpen; dest->LayerWhichShapes = src->LayerWhichShapes ? src->LayerWhichShapes : dest->LayerWhichShapes; dest->LayerNextShape = src->LayerNextShape ? src->LayerNextShape : dest->LayerNextShape; dest->LayerGetShape = src->LayerGetShape ? src->LayerGetShape : dest->LayerGetShape; /* dest->LayerResultsGetShape = src->LayerResultsGetShape ? src->LayerResultsGetShape : dest->LayerResultsGetShape; */ dest->LayerClose = src->LayerClose ? src->LayerClose : dest->LayerClose; dest->LayerGetItems = src->LayerGetItems ? src->LayerGetItems : dest->LayerGetItems; dest->LayerGetExtent = src->LayerGetExtent ? src->LayerGetExtent : dest->LayerGetExtent; dest->LayerGetAutoStyle = src->LayerGetAutoStyle ? src->LayerGetAutoStyle : dest->LayerGetAutoStyle; dest->LayerCloseConnection = src->LayerCloseConnection ? src->LayerCloseConnection : dest->LayerCloseConnection; dest->LayerSetTimeFilter = src->LayerSetTimeFilter ? src->LayerSetTimeFilter : dest->LayerSetTimeFilter; dest->LayerApplyFilterToLayer = src->LayerApplyFilterToLayer ? src->LayerApplyFilterToLayer : dest->LayerApplyFilterToLayer; dest->LayerCreateItems = src->LayerCreateItems ? src->LayerCreateItems : dest->LayerCreateItems; dest->LayerGetNumFeatures = src->LayerGetNumFeatures ? src->LayerGetNumFeatures : dest->LayerGetNumFeatures; dest->LayerGetAutoProjection = src->LayerGetAutoProjection ? src->LayerGetAutoProjection: dest->LayerGetAutoProjection; } int msPluginLayerInitializeVirtualTable(layerObj *layer) { VTFactoryItemObj *pVTFI; msAcquireLock(TLOCK_LAYER_VTABLE); pVTFI = lookupVTFItem(&gVirtualTableFactory, layer->plugin_library); if ( ! pVTFI) { pVTFI = loadCustomLayerDLL(layer, layer->plugin_library); if ( ! pVTFI) { msReleaseLock(TLOCK_LAYER_VTABLE); return MS_FAILURE; } if (insertNewVTFItem(&gVirtualTableFactory, pVTFI) != MS_SUCCESS) { destroyVTFItem(&pVTFI); msReleaseLock(TLOCK_LAYER_VTABLE); return MS_FAILURE; } } msReleaseLock(TLOCK_LAYER_VTABLE); copyVirtualTable(layer->vtable, &pVTFI->vtable); return MS_SUCCESS; } /* msPluginFreeVirtualTableFactory() ** Called by msCleanup() to free the virtual table factory */ void msPluginFreeVirtualTableFactory() { int i; msAcquireLock(TLOCK_LAYER_VTABLE); for (i=0; i #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #endif #ifdef USE_GDAL # include "cpl_vsi.h" #endif void CleanVSIDir( const char *pszDir ); /********************************************************************** * msInitWmsParamsObj() * **********************************************************************/ int msInitWmsParamsObj(wmsParamsObj *wmsparams) { wmsparams->onlineresource = NULL; wmsparams->params = msCreateHashTable(); wmsparams->numparams=0; wmsparams->httpcookiedata = NULL; return MS_SUCCESS; } /********************************************************************** * msFreeWmsParamsObj() * * Frees the contents of the object, but not the object itself. **********************************************************************/ void msFreeWmsParamsObj(wmsParamsObj *wmsparams) { msFree(wmsparams->onlineresource); wmsparams->onlineresource = NULL; msFreeHashTable(wmsparams->params); wmsparams->params = NULL; msFree(wmsparams->httpcookiedata); wmsparams->numparams=0; } /********************************************************************** * msSetWMSParamString() * **********************************************************************/ #ifdef USE_WMS_LYR static int msSetWMSParamString(wmsParamsObj *psWMSParams, const char *name, const char * value, int urlencode) { if (urlencode) { char *pszTmp; /* * Special case handling for characters the WMS specification * says should not be encoded, when they occur in certain * parameters. * * TODO: WMS 1.3 removes SRS and FORMAT from the set of * exceptional cases. */ if( strcmp(name,"LAYERS") == 0 || strcmp(name,"STYLES") == 0 || strcmp(name,"BBOX") == 0 ) { pszTmp = msEncodeUrlExcept(value,','); } else if ( strcmp(name,"SRS") == 0 ) { pszTmp = msEncodeUrlExcept(value,':'); } else if ( strcmp(name,"FORMAT") == 0 ) { pszTmp = msEncodeUrlExcept(value,'/'); } else { pszTmp = msEncodeUrl(value); } msInsertHashTable(psWMSParams->params, name, pszTmp); msFree(pszTmp); } else { msInsertHashTable(psWMSParams->params, name, value); } psWMSParams->numparams++; return MS_SUCCESS; } #endif /* def USE_WMS_LYR */ /********************************************************************** * msSetWMSParamInt() * **********************************************************************/ #ifdef USE_WMS_LYR static int msSetWMSParamInt(wmsParamsObj *wmsparams, const char *name, int value) { char szBuf[100]; snprintf(szBuf, sizeof(szBuf), "%d", value); msInsertHashTable(wmsparams->params, name, szBuf); wmsparams->numparams++; return MS_SUCCESS; } #endif /* def USE_WMS_LYR */ /********************************************************************** * msBuildWMSParamsUrl() * **********************************************************************/ static char *msBuildURLFromWMSParams(wmsParamsObj *wmsparams) { const char *key, *value; size_t bufferSize = 0; int nLen; char *pszURL; /* Compute size required for URL buffer */ nLen = strlen(wmsparams->onlineresource) + 3; key = msFirstKeyFromHashTable(wmsparams->params); while (key != NULL) { value = msLookupHashTable(wmsparams->params, key); nLen += strlen(key) + strlen(value) + 2; key = msNextKeyFromHashTable(wmsparams->params, key); } bufferSize = nLen+1; pszURL = (char*)msSmallMalloc(bufferSize); /* Start with the onlineresource value and append trailing '?' or '&' * if missing. */ strcpy(pszURL, wmsparams->onlineresource); if (strchr(pszURL, '?') == NULL) strcat(pszURL, "?"); else { char *c; c = pszURL+strlen(pszURL)-1; if (*c != '?' && *c != '&') strcpy(c+1, "&"); } /* Now add all the parameters */ nLen = strlen(pszURL); key = msFirstKeyFromHashTable(wmsparams->params); while (key != NULL) { value = msLookupHashTable(wmsparams->params, key); snprintf(pszURL+nLen, bufferSize-nLen, "%s=%s&", key, value); nLen += strlen(key) + strlen(value) + 2; key = msNextKeyFromHashTable(wmsparams->params, key); } /* Get rid of trailing '&'*/ pszURL[nLen-1] = '\0'; return pszURL; } #ifdef USE_WMS_LYR /********************************************************************** * msBuildWMSLayerURLBase() * * Build the base of a GetMap or GetFeatureInfo URL using metadata. * The parameters to set are: * VERSION * LAYERS * FORMAT * TRANSPARENT * STYLES * QUERY_LAYERS (for queriable layers only) * * Returns a reference to a newly allocated string that should be freed * by the caller. **********************************************************************/ static int msBuildWMSLayerURLBase(mapObj *map, layerObj *lp, wmsParamsObj *psWMSParams) { const char *pszOnlineResource, *pszVersion, *pszName, *pszFormat; const char *pszFormatList, *pszStyle, /* *pszStyleList,*/ *pszTime; const char *pszBgColor, *pszTransparent; const char *pszSLD=NULL, *pszStyleSLDBody=NULL, *pszVersionKeyword=NULL; const char *pszSLDBody=NULL, *pszSLDURL = NULL; char *pszSLDGenerated = NULL; /* If lp->connection is not set then use wms_onlineresource metadata */ pszOnlineResource = lp->connection; if (pszOnlineResource == NULL) pszOnlineResource = msOWSLookupMetadata(&(lp->metadata), "MO", "onlineresource"); pszVersion = msOWSLookupMetadata(&(lp->metadata), "MO", "server_version"); pszName = msOWSLookupMetadata(&(lp->metadata), "MO", "name"); pszFormat = msOWSLookupMetadata(&(lp->metadata), "MO", "format"); pszFormatList = msOWSLookupMetadata(&(lp->metadata), "MO", "formatlist"); pszStyle = msOWSLookupMetadata(&(lp->metadata), "MO", "style"); /*pszStyleList = msOWSLookupMetadata(&(lp->metadata), "MO", "stylelist");*/ pszTime = msOWSLookupMetadata(&(lp->metadata), "MO", "time"); pszSLDBody = msOWSLookupMetadata(&(lp->metadata), "MO", "sld_body"); pszSLDURL = msOWSLookupMetadata(&(lp->metadata), "MO", "sld_url"); pszBgColor = msOWSLookupMetadata(&(lp->metadata), "MO", "bgcolor"); pszTransparent = msOWSLookupMetadata(&(lp->metadata), "MO", "transparent"); if (pszOnlineResource==NULL || pszVersion==NULL || pszName==NULL) { msSetError(MS_WMSCONNERR, "One of wms_onlineresource, wms_server_version, wms_name " "metadata is missing in layer %s. " "Please either provide a valid CONNECTION URL, or provide " "those values in the layer's metadata.\n", "msBuildWMSLayerURLBase()", lp->name); return MS_FAILURE; } psWMSParams->onlineresource = msStrdup(pszOnlineResource); if (strncmp(pszVersion, "1.0.7", 5) < 0) pszVersionKeyword = "WMTVER"; else pszVersionKeyword = "VERSION"; msSetWMSParamString(psWMSParams, pszVersionKeyword, pszVersion, MS_FALSE); msSetWMSParamString(psWMSParams, "SERVICE", "WMS", MS_FALSE); msSetWMSParamString(psWMSParams, "LAYERS", pszName, MS_TRUE); if (pszFormat==NULL && pszFormatList==NULL) { msSetError(MS_WMSCONNERR, "At least wms_format or wms_formatlist is required for " "layer %s. " "Please either provide a valid CONNECTION URL, or provide " "those values in the layer's metadata.\n", "msBuildWMSLayerURLBase()", lp->name); return MS_FAILURE; } if (pszFormat != NULL) { msSetWMSParamString(psWMSParams, "FORMAT", pszFormat, MS_TRUE); } else { /* Look for the first format in list that matches */ char **papszTok; int i, n; papszTok = msStringSplit(pszFormatList, ',', &n); for(i=0; pszFormat==NULL && iname); msFreeCharArray(papszTok, n); return MS_FAILURE; } } if (pszStyle==NULL) { /* When no style is selected, use "" which is a valid default. */ pszStyle = ""; } else { /* Was a wms_style_..._sld URL provided? */ char szBuf[100]; snprintf(szBuf, sizeof(szBuf), "style_%.80s_sld", pszStyle); pszSLD = msOWSLookupMetadata(&(lp->metadata), "MO", szBuf); snprintf(szBuf, sizeof(szBuf), "style_%.80s_sld_body", pszStyle); pszStyleSLDBody = msOWSLookupMetadata(&(lp->metadata), "MO", szBuf); if (pszSLD || pszStyleSLDBody) { /* SLD URL is set. If this defn. came from a map context then */ /* the style name may just be an internal name: "Style{%d}" if */ /* that's the case then we should not pass this name via the URL */ if (strncmp(pszStyle, "Style{", 6) == 0) pszStyle = ""; } } /* set STYLES no matter what, even if it's empty (i.e. "STYLES=") * styles is a required param of WMS */ msSetWMSParamString(psWMSParams, "STYLES", pszStyle, MS_TRUE); if (pszSLD != NULL) { /* Only SLD is set */ msSetWMSParamString(psWMSParams, "SLD", pszSLD, MS_TRUE); } else if (pszStyleSLDBody != NULL) { /* SLDBODY are set */ msSetWMSParamString(psWMSParams, "SLD_BODY", pszStyleSLDBody, MS_TRUE); } if (msIsLayerQueryable(lp)) { msSetWMSParamString(psWMSParams, "QUERY_LAYERS", pszName, MS_TRUE); } if (pszTime && strlen(pszTime) > 0) { msSetWMSParamString(psWMSParams, "TIME", pszTime, MS_TRUE); } /* if the metadata wms_sld_body is set to AUTO, we generate * the sld based on classes found in the map file and send * it in the URL. If diffrent from AUTO, we are assuming that * it is a valid sld. */ if (pszSLDBody) { if (strcasecmp(pszSLDBody, "AUTO") == 0) { if (pszVersion && strncmp(pszVersion, "1.3.0", 5) == 0) pszSLDGenerated = msSLDGenerateSLD(map, lp->index, "1.1.0"); else pszSLDGenerated = msSLDGenerateSLD(map, lp->index, NULL); if (pszSLDGenerated) { msSetWMSParamString(psWMSParams, "SLD_BODY", pszSLDGenerated, MS_TRUE); free(pszSLDGenerated); } } else { msSetWMSParamString(psWMSParams, "SLD_BODY", pszSLDBody, MS_TRUE); } } if (pszSLDURL) { msSetWMSParamString(psWMSParams, "SLD", pszSLDURL, MS_TRUE); } if (pszBgColor) { msSetWMSParamString(psWMSParams, "BGCOLOR", pszBgColor, MS_TRUE); } if (pszTransparent) { msSetWMSParamString(psWMSParams, "TRANSPARENT", pszTransparent, MS_TRUE); } else { msSetWMSParamString(psWMSParams, "TRANSPARENT", "TRUE", MS_TRUE); } return MS_SUCCESS; } #endif /* USE_WMS_LYR */ /********************************************************************** * msBuildWMSLayerURL() * * Build a GetMap or GetFeatureInfo URL. * * Returns a reference to a newly allocated string that should be freed * by the caller. **********************************************************************/ static int msBuildWMSLayerURL(mapObj *map, layerObj *lp, int nRequestType, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, rectObj *bbox_ret, int *width_ret, int *height_ret, wmsParamsObj *psWMSParams) { #ifdef USE_WMS_LYR char *pszEPSG = NULL; const char *pszVersion, *pszTmp, *pszRequestParam, *pszExceptionsParam, *pszLayer=NULL, *pszQueryLayers=NULL; rectObj bbox; int bbox_width = map->width, bbox_height = map->height; int nVersion=OWS_VERSION_NOTSET; if (lp->connectiontype != MS_WMS) { msSetError(MS_WMSCONNERR, "Call supported only for CONNECTIONTYPE WMS", "msBuildWMSLayerURL()"); return MS_FAILURE; } /* ------------------------------------------------------------------ * Find out request version * ------------------------------------------------------------------ */ if (lp->connection == NULL || ((pszVersion = strstr(lp->connection, "VERSION=")) == NULL && (pszVersion = strstr(lp->connection, "version=")) == NULL && (pszVersion = strstr(lp->connection, "WMTVER=")) == NULL && (pszVersion = strstr(lp->connection, "wmtver=")) == NULL ) ) { /* CONNECTION missing or seems incomplete... try to build from metadata */ if (msBuildWMSLayerURLBase(map, lp, psWMSParams) != MS_SUCCESS) return MS_FAILURE; /* An error already produced. */ /* If we received MS_SUCCESS then version must have been set */ pszVersion = msLookupHashTable(psWMSParams->params, "VERSION"); if (pszVersion ==NULL) pszVersion = msLookupHashTable(psWMSParams->params, "WMTVER"); nVersion = msOWSParseVersionString(pszVersion); } else { /* CONNECTION string seems complete, start with that. */ char *pszDelimiter; psWMSParams->onlineresource = msStrdup(lp->connection); /* Fetch version info */ pszVersion = strchr(pszVersion, '=')+1; pszDelimiter = strchr(pszVersion, '&'); if (pszDelimiter != NULL) *pszDelimiter = '\0'; nVersion = msOWSParseVersionString(pszVersion); if (pszDelimiter != NULL) *pszDelimiter = '&'; } switch (nVersion) { case OWS_1_0_8: nVersion = OWS_1_1_0; /* 1.0.8 == 1.1.0 */ break; case OWS_1_0_0: case OWS_1_0_1: case OWS_1_0_7: case OWS_1_1_0: case OWS_1_1_1: /* All is good, this is a supported version. */ break; default: /* Not a supported version */ msSetError(MS_WMSCONNERR, "MapServer supports only WMS 1.0.0 to 1.1.1 (please verify the VERSION parameter in the connection string).", "msBuildWMSLayerURL()"); return MS_FAILURE; } /* ------------------------------------------------------------------ * For GetFeatureInfo requests, make sure QUERY_LAYERS is included * ------------------------------------------------------------------ */ if (nRequestType == WMS_GETFEATUREINFO && strstr(psWMSParams->onlineresource, "QUERY_LAYERS=") == NULL && strstr(psWMSParams->onlineresource, "query_layers=") == NULL && msLookupHashTable(psWMSParams->params, "QUERY_LAYERS") == NULL) { pszQueryLayers = msOWSLookupMetadata(&(lp->metadata), "MO", "name"); if (pszQueryLayers == NULL) { msSetError(MS_WMSCONNERR, "wms_name not set or WMS Connection String must contain the QUERY_LAYERS parameter to support GetFeatureInfo requests (with name in uppercase).", "msBuildWMSLayerURL()"); return MS_FAILURE; } } /* ------------------------------------------------------------------ * For GetLegendGraphic requests, make sure LAYER is included * ------------------------------------------------------------------ */ if (nRequestType == WMS_GETLEGENDGRAPHIC && strstr(psWMSParams->onlineresource, "LAYER=") == NULL && strstr(psWMSParams->onlineresource, "layer=") == NULL && msLookupHashTable(psWMSParams->params, "LAYER") == NULL) { pszLayer = msOWSLookupMetadata(&(lp->metadata), "MO", "name"); if (pszLayer == NULL) { msSetError(MS_WMSCONNERR, "wms_name not set or WMS Connection String must contain the LAYER parameter to support GetLegendGraphic requests (with name in uppercase).", "msBuildWMSLayerURL()"); return MS_FAILURE; } } /* ------------------------------------------------------------------ * Figure the SRS we'll use for the request. * - Fetch the map SRS (if it's EPSG) * - Check if map SRS is listed in layer wms_srs metadata * - If map SRS is valid for this layer then use it * - Otherwise request layer in its default SRS and we'll reproject later * ------------------------------------------------------------------ */ if ((pszEPSG = (char*)msOWSGetEPSGProj(&(map->projection), NULL, NULL, MS_TRUE)) != NULL && (pszEPSG = msStrdup(pszEPSG)) != NULL && (strncasecmp(pszEPSG, "EPSG:", 5) == 0 || strncasecmp(pszEPSG, "AUTO:", 5) == 0) ) { const char *pszLyrEPSG, *pszFound; int nLen; char *pszPtr = NULL; /* If it's an AUTO projection then keep only id and strip off */ /* the parameters for now (we'll restore them at the end) */ if (strncasecmp(pszEPSG, "AUTO:", 5) == 0) { if ((pszPtr = strchr(pszEPSG, ','))) *pszPtr = '\0'; } nLen = strlen(pszEPSG); pszLyrEPSG = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE); if (pszLyrEPSG == NULL || (pszFound = strstr(pszLyrEPSG, pszEPSG)) == NULL || ! ((*(pszFound+nLen) == '\0') || isspace(*(pszFound+nLen))) ) { /* Not found in Layer's list of SRS (including projection object) */ free(pszEPSG); pszEPSG = NULL; } if (pszEPSG && pszPtr) *pszPtr = ','; /* Restore full AUTO:... definition */ } if (pszEPSG == NULL && ((pszEPSG = (char*)msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_TRUE)) == NULL || (pszEPSG = msStrdup(pszEPSG)) == NULL || (strncasecmp(pszEPSG, "EPSG:", 5) != 0 && strncasecmp(pszEPSG, "AUTO:", 5) != 0 ) ) ) { msSetError(MS_WMSCONNERR, "Layer must have an EPSG or AUTO projection code (in its PROJECTION object or wms_srs metadata)", "msBuildWMSLayerURL()"); if (pszEPSG) free(pszEPSG); return MS_FAILURE; } /* ------------------------------------------------------------------ * For an AUTO projection, set the Units,lon0,lat0 if not already set * ------------------------------------------------------------------ */ if (strncasecmp(pszEPSG, "AUTO:", 5) == 0 && strchr(pszEPSG, ',') == NULL) { pointObj oPoint; char *pszNewEPSG; /* Use center of map view for lon0,lat0 */ oPoint.x = (map->extent.minx + map->extent.maxx)/2.0; oPoint.y = (map->extent.miny + map->extent.maxy)/2.0; msProjectPoint(&(map->projection), &(map->latlon), &oPoint); pszNewEPSG = (char*)msSmallMalloc(101*sizeof(char)); snprintf(pszNewEPSG, 100, "%s,9001,%.16g,%.16g", pszEPSG, oPoint.x, oPoint.y); pszNewEPSG[100]='\0'; free(pszEPSG); pszEPSG=pszNewEPSG; } /* ------------------------------------------------------------------ * Set layer SRS. * ------------------------------------------------------------------ */ /* No need to set lp->proj if it's already set to the right EPSG code */ if ((pszTmp = msOWSGetEPSGProj(&(lp->projection), NULL, "MO", MS_TRUE)) == NULL || strcasecmp(pszEPSG, pszTmp) != 0) { const char *ows_srs; /* no need to set lp->proj if it is already set and there is only one item in the _srs metadata for this layer - we will assume the projection block matches the _srs metadata (the search for ' ' in ows_srs is a test to see if there are multiple EPSG: codes) */ if( lp->projection.numargs == 0 || (ows_srs = msOWSGetEPSGProj(NULL,&(lp->metadata), "MO", MS_FALSE)) == NULL || (strchr(ows_srs,' ') != NULL) ) { if (strncasecmp(pszEPSG, "EPSG:", 5) == 0) { char szProj[20]; snprintf(szProj, sizeof(szProj), "init=epsg:%s", pszEPSG+5); if (msLoadProjectionString(&(lp->projection), szProj) != 0) return MS_FAILURE; } else { if (msLoadProjectionString(&(lp->projection), pszEPSG) != 0) return MS_FAILURE; } } } /* ------------------------------------------------------------------ * Adjust for MapServer EXTENT being center of pixel and WMS BBOX being * edge of pixel (#2843). * ------------------------------------------------------------------ */ bbox = map->extent; bbox.minx -= map->cellsize * 0.5; bbox.maxx += map->cellsize * 0.5; bbox.miny -= map->cellsize * 0.5; bbox.maxy += map->cellsize * 0.5; /* -------------------------------------------------------------------- */ /* Reproject if needed. */ /* -------------------------------------------------------------------- */ if (msProjectionsDiffer(&(map->projection), &(lp->projection))) { msProjectRect(&(map->projection), &(lp->projection), &bbox); /* -------------------------------------------------------------------- */ /* Sometimes our remote WMS only accepts square pixel */ /* requests. If this is the case adjust adjust the number of */ /* pixels or lines in the request so that the pixels are */ /* square. */ /* -------------------------------------------------------------------- */ { const char *nonsquare_ok = msOWSLookupMetadata(&(lp->metadata), "MO", "nonsquare_ok"); /* assume nonsquare_ok is false */ if( nonsquare_ok != NULL && (strcasecmp(nonsquare_ok,"no") == 0 || strcasecmp(nonsquare_ok,"false") == 0) ) { double cellsize_x = (bbox.maxx-bbox.minx) / bbox_width; double cellsize_y = (bbox.maxy-bbox.miny) / bbox_height; if( cellsize_x < cellsize_y * 0.999999 ) { int new_bbox_height = ceil((cellsize_y/cellsize_x) * bbox_height); if (lp->debug) msDebug("NONSQUARE_OK=%s, adjusted HEIGHT from %d to %d to equalize cellsize at %g.\n", nonsquare_ok, bbox_height, new_bbox_height, cellsize_x ); bbox_height = new_bbox_height; } else if( cellsize_y < cellsize_x * 0.999999 ) { int new_bbox_width = ceil((cellsize_x/cellsize_y) * bbox_width); if (lp->debug) msDebug("NONSQUARE_OK=%s, adjusted WIDTH from %d to %d to equalize cellsize at %g.\n", nonsquare_ok, bbox_width, new_bbox_width, cellsize_y ); bbox_width = new_bbox_width; } else { if (lp->debug) msDebug("NONSQUARE_OK=%s, but cellsize was already square - no change.\n", nonsquare_ok ); } } } } /* -------------------------------------------------------------------- */ /* If the layer has predefined extents, and a predefined */ /* projection that matches the request projection, then */ /* consider restricting the BBOX to match the limits. */ /* -------------------------------------------------------------------- */ if( bbox_width != 0 ) { const char *ows_srs; rectObj layer_rect; ows_srs = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "MO", MS_FALSE); if( ows_srs && strchr(ows_srs,' ') == NULL && msOWSGetLayerExtent( map, lp, "MO", &layer_rect) == MS_SUCCESS ) { /* fulloverlap */ if( msRectContained( &bbox, &layer_rect ) ) { /* no changes */ } /* no overlap */ else if( !msRectOverlap( &layer_rect, &bbox ) ) { bbox_width = 0; bbox_height = 0; } else { double cellsize_x = (bbox.maxx-bbox.minx) / bbox_width; double cellsize_y = (bbox.maxy-bbox.miny) / bbox_height; double cellsize = MIN(cellsize_x,cellsize_y); msRectIntersect( &bbox, &layer_rect ); bbox_width = ceil((bbox.maxx - bbox.minx) / cellsize); bbox_height = ceil((bbox.maxy - bbox.miny) / cellsize); } } } /* -------------------------------------------------------------------- */ /* Potentially return the bbox. */ /* -------------------------------------------------------------------- */ if (bbox_ret != NULL) *bbox_ret = bbox; if( width_ret != NULL ) *width_ret = bbox_width; if( height_ret != NULL ) *height_ret = bbox_height; /* ------------------------------------------------------------------ * Build the request URL. * At this point we set only the following parameters for GetMap: * REQUEST * SRS * BBOX * * And for GetFeatureInfo: * X * Y * INFO_FORMAT * FEATURE_COUNT (only if nFeatureCount > 0) * * The connection string should contain all other required params, * including: * VERSION * LAYERS * FORMAT * TRANSPARENT * STYLES * QUERY_LAYERS (for queryable layers only) * ------------------------------------------------------------------ */ if (nRequestType == WMS_GETFEATUREINFO) { char szBuf[100] = ""; if (nVersion >= OWS_1_0_7) pszRequestParam = "GetFeatureInfo"; else pszRequestParam = "feature_info"; if (nVersion >= OWS_1_1_0) pszExceptionsParam = "application/vnd.ogc.se_xml"; else if (nVersion > OWS_1_1_0) /* 1.0.1 to 1.0.7 */ pszExceptionsParam = "SE_XML"; else pszExceptionsParam = "WMS_XML"; msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE); msSetWMSParamInt( psWMSParams, "WIDTH", bbox_width); msSetWMSParamInt( psWMSParams, "HEIGHT", bbox_height); msSetWMSParamString(psWMSParams, "SRS", pszEPSG, MS_FALSE); snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", bbox.minx, bbox.miny, bbox.maxx, bbox.maxy); msSetWMSParamString(psWMSParams, "BBOX", szBuf, MS_TRUE); msSetWMSParamInt( psWMSParams, "X", nClickX); msSetWMSParamInt( psWMSParams, "Y", nClickY); msSetWMSParamString(psWMSParams, "EXCEPTIONS", pszExceptionsParam, MS_FALSE); msSetWMSParamString(psWMSParams, "INFO_FORMAT", pszInfoFormat, MS_TRUE); if (pszQueryLayers) { /* not set in CONNECTION string */ msSetWMSParamString(psWMSParams, "QUERY_LAYERS", pszQueryLayers, MS_FALSE); } /* If FEATURE_COUNT <= 0 then don't pass this parameter */ /* The spec states that FEATURE_COUNT must be greater than zero */ /* and if not passed then the behavior is up to the server */ if (nFeatureCount > 0) { msSetWMSParamInt(psWMSParams, "FEATURE_COUNT", nFeatureCount); } } else if (nRequestType == WMS_GETLEGENDGRAPHIC) { if(map->extent.maxx > map->extent.minx && map->width > 0 && map->height > 0) { char szBuf[20] = ""; double scaledenom; msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &scaledenom); snprintf(szBuf, 20, "%g",scaledenom); msSetWMSParamString(psWMSParams, "SCALE", szBuf, MS_FALSE); } pszRequestParam = "GetLegendGraphic"; pszExceptionsParam = msOWSLookupMetadata(&(lp->metadata), "MO", "exceptions_format"); if (pszExceptionsParam == NULL) { if (nVersion >= OWS_1_1_0) pszExceptionsParam = "application/vnd.ogc.se_inimage"; else pszExceptionsParam = "INIMAGE"; } if (pszLayer) { /* not set in CONNECTION string */ msSetWMSParamString(psWMSParams, "LAYER", pszLayer, MS_FALSE); } msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE); msSetWMSParamString(psWMSParams, "SRS", pszEPSG, MS_FALSE); } else { /* if (nRequestType == WMS_GETMAP) */ char szBuf[100] = ""; if (nVersion >= OWS_1_0_7) pszRequestParam = "GetMap"; else pszRequestParam = "map"; pszExceptionsParam = msOWSLookupMetadata(&(lp->metadata), "MO", "exceptions_format"); if (pszExceptionsParam == NULL) { if (nVersion >= OWS_1_1_0) pszExceptionsParam = "application/vnd.ogc.se_inimage"; else pszExceptionsParam = "INIMAGE"; } msSetWMSParamString(psWMSParams, "REQUEST", pszRequestParam, MS_FALSE); msSetWMSParamInt( psWMSParams, "WIDTH", bbox_width); msSetWMSParamInt( psWMSParams, "HEIGHT", bbox_height); msSetWMSParamString(psWMSParams, "SRS", pszEPSG, MS_FALSE); snprintf(szBuf, sizeof(szBuf), "%.15g,%.15g,%.15g,%.15g", bbox.minx, bbox.miny, bbox.maxx, bbox.maxy); msSetWMSParamString(psWMSParams, "BBOX", szBuf, MS_TRUE); msSetWMSParamString(psWMSParams, "EXCEPTIONS", pszExceptionsParam, MS_FALSE); } free(pszEPSG); return MS_SUCCESS; #else /* ------------------------------------------------------------------ * WMS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WMSCONNERR, "WMS CLIENT CONNECTION support is not available.", "msBuildWMSLayerURL()"); return MS_FAILURE; #endif /* USE_WMS_LYR */ } /********************************************************************** * msWMSGetFeatureInfoURL() * * Build a GetFeatureInfo URL for this layer. * * Returns a reference to a newly allocated string that should be freed * by the caller. **********************************************************************/ char *msWMSGetFeatureInfoURL(mapObj *map, layerObj *lp, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat) { wmsParamsObj sThisWMSParams; char *pszURL; msInitWmsParamsObj(&sThisWMSParams); if (msBuildWMSLayerURL(map, lp, WMS_GETFEATUREINFO, nClickX, nClickY, nFeatureCount, pszInfoFormat, NULL, NULL, NULL, &sThisWMSParams)!= MS_SUCCESS) { return NULL; } pszURL = msBuildURLFromWMSParams(&sThisWMSParams); msFreeWmsParamsObj(&sThisWMSParams); return pszURL; } /********************************************************************** * msPrepareWMSLayerRequest() * **********************************************************************/ int msPrepareWMSLayerRequest(int nLayerId, mapObj *map, layerObj *lp, int nRequestType, enum MS_CONNECTION_TYPE lastconnectiontype, wmsParamsObj *psLastWMSParams, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, httpRequestObj *pasReqInfo, int *numRequests) { #ifdef USE_WMS_LYR char *pszURL = NULL, *pszHTTPCookieData = NULL; const char *pszTmp; rectObj bbox; int bbox_width, bbox_height; int nTimeout, bOkToMerge, bForceSeparateRequest, bCacheToDisk; wmsParamsObj sThisWMSParams; if (lp->connectiontype != MS_WMS) return MS_FAILURE; msInitWmsParamsObj(&sThisWMSParams); /* ------------------------------------------------------------------ * Build the request URL, this will also set layer projection and * compute BBOX in that projection. * ------------------------------------------------------------------ */ if (nRequestType == WMS_GETMAP && ( msBuildWMSLayerURL(map, lp, WMS_GETMAP, 0, 0, 0, NULL, &bbox, &bbox_width, &bbox_height, &sThisWMSParams) != MS_SUCCESS) ) { /* an error was already reported. */ msFreeWmsParamsObj(&sThisWMSParams); return MS_FAILURE; } else if (nRequestType == WMS_GETFEATUREINFO && msBuildWMSLayerURL(map, lp, WMS_GETFEATUREINFO, nClickX, nClickY, nFeatureCount, pszInfoFormat, NULL, NULL, NULL, &sThisWMSParams) != MS_SUCCESS ) { /* an error was already reported. */ msFreeWmsParamsObj(&sThisWMSParams); return MS_FAILURE; } else if (nRequestType == WMS_GETLEGENDGRAPHIC && msBuildWMSLayerURL(map, lp, WMS_GETLEGENDGRAPHIC, 0, 0, 0, NULL, NULL, NULL, NULL, &sThisWMSParams) != MS_SUCCESS ) { /* an error was already reported. */ msFreeWmsParamsObj(&sThisWMSParams); return MS_FAILURE; } /* ------------------------------------------------------------------ * Check if the request is empty, perhaps due to reprojection problems * or wms_extents restrictions. * ------------------------------------------------------------------ */ if ((nRequestType == WMS_GETMAP) && (bbox_width == 0 || bbox_height == 0) ) { msFreeWmsParamsObj(&sThisWMSParams); return MS_SUCCESS; /* No overlap. */ } /* ------------------------------------------------------------------ * Check if layer overlaps current view window (using wms_latlonboundingbox) * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "MO", "latlonboundingbox")) != NULL) { char **tokens; int n; rectObj ext; tokens = msStringSplit(pszTmp, ' ', &n); if (tokens==NULL || n != 4) { msSetError(MS_WMSCONNERR, "Wrong number of arguments for 'wms_latlonboundingbox' metadata.", "msDrawWMSLayer()"); msFreeWmsParamsObj(&sThisWMSParams); return MS_FAILURE; } ext.minx = atof(tokens[0]); ext.miny = atof(tokens[1]); ext.maxx = atof(tokens[2]); ext.maxy = atof(tokens[3]); msFreeCharArray(tokens, n); /* Reproject latlonboundingbox to the selected SRS for the layer and */ /* check if it overlaps the bbox that we calculated for the request */ msProjectRect(&(map->latlon), &(lp->projection), &ext); if (!msRectOverlap(&bbox, &ext)) { /* No overlap... nothing to do */ msFreeWmsParamsObj(&sThisWMSParams); return MS_SUCCESS; /* No overlap. */ } } /* ------------------------------------------------------------------ * check to see if a the metadata wms_connectiontimeout is set. If it is * the case we will use it, else we use the default which is 30 seconds. * First check the metadata in the layer object and then in the map object. * ------------------------------------------------------------------ */ nTimeout = 30; /* Default is 30 seconds */ if ((pszTmp = msOWSLookupMetadata2(&(lp->metadata), &(map->web.metadata), "MO", "connectiontimeout")) != NULL) { nTimeout = atoi(pszTmp); } /* ------------------------------------------------------------------ * Check if we want to use in memory images instead of writing to disk. * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "MO", "cache_to_disk")) != NULL) { if( strcasecmp(pszTmp,"true") == 0 || strcasecmp(pszTmp,"on") == 0 || strcasecmp(pszTmp,"yes") == 0 ) bCacheToDisk = MS_TRUE; else bCacheToDisk = atoi(pszTmp); } else bCacheToDisk = MS_FALSE; if( bCacheToDisk ) { /* We'll store the remote server's response to a tmp file. */ if (map->web.imagepath == NULL || strlen(map->web.imagepath) == 0) { msSetError(MS_WMSERR, "WEB.IMAGEPATH must be set to use WMS client connections.", "msPrepareWMSLayerRequest()"); return MS_FAILURE; } } /* ------------------------------------------------------------------ * Check if layer can be merged with previous WMS layer requests * Metadata wms_force_separate_request can be set to 1 to prevent this * this layer from being combined with any other layer. * ------------------------------------------------------------------ */ bForceSeparateRequest = MS_FALSE; if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "MO", "force_separate_request")) != NULL) { bForceSeparateRequest = atoi(pszTmp); } bOkToMerge = MS_FALSE; if (!bForceSeparateRequest && lastconnectiontype == MS_WMS && psLastWMSParams != NULL && sThisWMSParams.numparams == psLastWMSParams->numparams && strcmp(sThisWMSParams.onlineresource, psLastWMSParams->onlineresource) == 0) { const char *key, *value1, *value2; bOkToMerge = MS_TRUE; key = msFirstKeyFromHashTable(sThisWMSParams.params); while (key != NULL && bOkToMerge == MS_TRUE) { /* Skip parameters whose values can be different */ if (!(strcmp(key, "LAYERS") == 0 || strcmp(key, "QUERY_LAYERS") == 0 || strcmp(key, "STYLES") == 0) ) { value1 = msLookupHashTable(psLastWMSParams->params, key); value2 = msLookupHashTable(sThisWMSParams.params, key); if (value1==NULL || value2==NULL || strcmp(value1, value2) != 0) { bOkToMerge = MS_FALSE; break; } } key = msNextKeyFromHashTable(sThisWMSParams.params, key); } } /*------------------------------------------------------------------ * Check to see if there's a HTTP Cookie to forward * If Cookie differ between the two connection, it's NOT OK to merge * the connection * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata(&(lp->metadata), "MO", "http_cookie")) != NULL) { if(strcasecmp(pszTmp, "forward") == 0) { pszTmp= msLookupHashTable(&(map->web.metadata),"http_cookie_data"); if(pszTmp != NULL) { pszHTTPCookieData = msStrdup(pszTmp); } } else { pszHTTPCookieData = msStrdup(pszTmp); } } else if ((pszTmp = msOWSLookupMetadata(&(map->web.metadata), "MO", "http_cookie")) != NULL) { if(strcasecmp(pszTmp, "forward") == 0) { pszTmp= msLookupHashTable(&(map->web.metadata),"http_cookie_data"); if(pszTmp != NULL) { pszHTTPCookieData = msStrdup(pszTmp); } } else { pszHTTPCookieData = msStrdup(pszTmp); } } if(bOkToMerge && pszHTTPCookieData != sThisWMSParams.httpcookiedata) { if(pszHTTPCookieData == NULL || sThisWMSParams.httpcookiedata == NULL) { bOkToMerge = MS_FALSE; } if(strcmp(pszHTTPCookieData, sThisWMSParams.httpcookiedata) != 0) { bOkToMerge = MS_FALSE; } } if (bOkToMerge) { /* Merge both requests into sThisWMSParams */ const char *value1, *value2; char *keys[] = {"LAYERS", "QUERY_LAYERS", "STYLES"}; int i; for(i=0; i<3; i++) { value1 = msLookupHashTable(psLastWMSParams->params, keys[i]); value2 = msLookupHashTable(sThisWMSParams.params, keys[i]); if (value1 && value2) { char *pszBuf; int nLen; nLen = strlen(value1) + strlen(value2) +2; pszBuf = malloc(nLen); MS_CHECK_ALLOC(pszBuf, nLen, MS_FAILURE); snprintf(pszBuf, nLen, "%s,%s", value1, value2); msSetWMSParamString(&sThisWMSParams, keys[i], pszBuf,MS_FALSE); /* This key existed already, we don't want it counted twice */ sThisWMSParams.numparams--; msFree(pszBuf); } } } /* ------------------------------------------------------------------ * Build new request URL * ------------------------------------------------------------------ */ pszURL = msBuildURLFromWMSParams(&sThisWMSParams); if (bOkToMerge && (*numRequests)>0) { /* ------------------------------------------------------------------ * Update the last request in the array: (*numRequests)-1 * ------------------------------------------------------------------ */ msFree(pasReqInfo[(*numRequests)-1].pszGetUrl); pasReqInfo[(*numRequests)-1].pszGetUrl = pszURL; pszURL = NULL; pasReqInfo[(*numRequests)-1].debug |= lp->debug; if (nTimeout > pasReqInfo[(*numRequests)-1].nTimeout) pasReqInfo[(*numRequests)-1].nTimeout = nTimeout; } else { /* ------------------------------------------------------------------ * Add a request to the array (already preallocated) * ------------------------------------------------------------------ */ pasReqInfo[(*numRequests)].nLayerId = nLayerId; pasReqInfo[(*numRequests)].pszGetUrl = pszURL; pszURL = NULL; pasReqInfo[(*numRequests)].pszHTTPCookieData = pszHTTPCookieData; pszHTTPCookieData = NULL; if( bCacheToDisk ) { pasReqInfo[(*numRequests)].pszOutputFile = msTmpFile(map, map->mappath, NULL, "wms.tmp"); } else pasReqInfo[(*numRequests)].pszOutputFile = NULL; pasReqInfo[(*numRequests)].nStatus = 0; pasReqInfo[(*numRequests)].nTimeout = nTimeout; pasReqInfo[(*numRequests)].bbox = bbox; pasReqInfo[(*numRequests)].width = bbox_width; pasReqInfo[(*numRequests)].height = bbox_height; pasReqInfo[(*numRequests)].debug = lp->debug; if (msHTTPAuthProxySetup(&(map->web.metadata), &(lp->metadata), pasReqInfo, *numRequests, map, "MO") != MS_SUCCESS) return MS_FAILURE; (*numRequests)++; } /* ------------------------------------------------------------------ * Replace contents of psLastWMSParams with sThisWMSParams * unless bForceSeparateRequest is set in which case we make it empty * ------------------------------------------------------------------ */ if (psLastWMSParams) { msFreeWmsParamsObj(psLastWMSParams); if (!bForceSeparateRequest) *psLastWMSParams = sThisWMSParams; else msInitWmsParamsObj(psLastWMSParams); } else { /* Can't copy it, so we just free it */ msFreeWmsParamsObj(&sThisWMSParams); } return MS_SUCCESS; #else /* ------------------------------------------------------------------ * WMS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WMSCONNERR, "WMS CLIENT CONNECTION support is not available.", "msDrawWMSLayer()"); return(MS_FAILURE); #endif /* USE_WMS_LYR */ } /********************************************************************** * msDrawWMSLayerLow() * **********************************************************************/ int msDrawWMSLayerLow(int nLayerId, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, layerObj *lp, imageObj *img) { #ifdef USE_WMS_LYR int status = MS_SUCCESS; int iReq = -1; char szPath[MS_MAXPATHLEN]; int currenttype; int currentconnectiontype; int numclasses; char *mem_filename = NULL; /* ------------------------------------------------------------------ * Find the request info for this layer in the array, based on nLayerId * ------------------------------------------------------------------ */ for(iReq=0; iReqname?lp->name:"(null)"), pasReqInfo[iReq].nStatus, pasReqInfo[iReq].pszErrBuf ); return MS_SUCCESS; } /* ------------------------------------------------------------------ * Check the Content-Type of the response to see if we got an exception, * if yes then try to parse it and pass the info to msSetError(). * We log an error but we still return SUCCESS here so that the layer * is only skipped intead of aborting the whole draw map. * ------------------------------------------------------------------ */ if (pasReqInfo[iReq].pszContentType && (strcmp(pasReqInfo[iReq].pszContentType, "text/xml") == 0 || strcmp(pasReqInfo[iReq].pszContentType, "application/vnd.ogc.se_xml") == 0)) { FILE *fp; char szBuf[MS_BUFFER_LENGTH]; if( pasReqInfo[iReq].pszOutputFile ) { fp = fopen(pasReqInfo[iReq].pszOutputFile, "r"); if (fp) { /* TODO: For now we'll only read the first chunk and return it * via msSetError()... we should really try to parse the XML * and extract the exception code/message though */ size_t nSize; nSize = fread(szBuf, sizeof(char), MS_BUFFER_LENGTH-1, fp); if (nSize < MS_BUFFER_LENGTH) szBuf[nSize] = '\0'; else { strlcpy(szBuf, "(!!!)", sizeof(szBuf)); /* This should never happen */ } fclose(fp); /* We're done with the remote server's response... delete it. */ if (!lp->debug) unlink(pasReqInfo[iReq].pszOutputFile); } else { strlcpy(szBuf, "(Failed to open exception response)", sizeof(szBuf)); } } else { strlcpy( szBuf, pasReqInfo[iReq].result_data, MS_BUFFER_LENGTH ); } if (lp->debug) msDebug("WMS GetMap request got XML exception for layer '%s': %s.", (lp->name?lp->name:"(null)"), szBuf ); msSetError(MS_WMSERR, "WMS GetMap request got XML exception for layer '%s': %s.", "msDrawWMSLayerLow()", (lp->name?lp->name:"(null)"), szBuf ); return MS_SUCCESS; } /* ------------------------------------------------------------------ * If the output was written to a memory buffer, then we will need * to attach a "VSI" name to this buffer. * ------------------------------------------------------------------ */ if( pasReqInfo[iReq].pszOutputFile == NULL ) { CleanVSIDir( "/vsimem/msout" ); mem_filename = msTmpFile(map, NULL, "/vsimem/msout/", "img.tmp" ); VSIFCloseL( VSIFileFromMemBuffer( mem_filename, (GByte*) pasReqInfo[iReq].result_data, (vsi_l_offset) pasReqInfo[iReq].result_size, FALSE ) ); } /* ------------------------------------------------------------------ * Prepare layer for drawing, reprojecting the image received from the * server if needed... * ------------------------------------------------------------------ */ /* keep the current type that will be restored at the end of this */ /* function. */ currenttype = lp->type; currentconnectiontype = lp->connectiontype; lp->type = MS_LAYER_RASTER; lp->connectiontype = MS_SHAPEFILE; /* set the classes to 0 so that It won't do client side */ /* classification if an sld was set. */ numclasses = lp->numclasses; /* ensure the file connection is closed right away after the layer */ /* is rendered */ msLayerSetProcessingKey( lp, "CLOSE_CONNECTION", "NORMAL"); if (msOWSLookupMetadata(&(lp->metadata), "MO", "sld_body") || msOWSLookupMetadata(&(lp->metadata), "MO", "sld_url")) lp->numclasses = 0; if (lp->data) free(lp->data); if( mem_filename != NULL ) lp->data = mem_filename; else lp->data = msStrdup(pasReqInfo[iReq].pszOutputFile); /* #3138 If PROCESSING "RESAMPLE=..." is set we cannot use the simple case */ if (!msProjectionsDiffer(&(map->projection), &(lp->projection)) && (msLayerGetProcessingKey(lp, "RESAMPLE") == NULL) ) { /* The simple case... no reprojection needed... render layer directly. */ lp->transform = MS_FALSE; /* if (msDrawRasterLayerLow(map, lp, img) != 0) */ /* status = MS_FAILURE; */ if (msDrawLayer(map, lp, img) != 0) status = MS_FAILURE; } else { FILE *fp; char *wldfile; /* OK, we have to resample the raster to map projection... */ lp->transform = MS_TRUE; msLayerSetProcessingKey( lp, "LOAD_WHOLE_IMAGE", "YES" ); /* Create a world file with raster extents */ /* One line per value, in this order: cx, 0, 0, cy, ulx, uly */ wldfile = msBuildPath(szPath, lp->map->mappath, lp->data); if (wldfile && (strlen(wldfile)>=3)) strcpy(wldfile+strlen(wldfile)-3, "wld"); if (wldfile && (fp = VSIFOpenL(wldfile, "wt")) != NULL) { double dfCellSizeX = MS_CELLSIZE(pasReqInfo[iReq].bbox.minx, pasReqInfo[iReq].bbox.maxx, pasReqInfo[iReq].width); double dfCellSizeY = MS_CELLSIZE(pasReqInfo[iReq].bbox.maxy, pasReqInfo[iReq].bbox.miny, pasReqInfo[iReq].height); char world_text[5000]; sprintf( world_text, "%.12f\n0\n0\n%.12f\n%.12f\n%.12f\n", dfCellSizeX, dfCellSizeY, pasReqInfo[iReq].bbox.minx + dfCellSizeX * 0.5, pasReqInfo[iReq].bbox.maxy + dfCellSizeY * 0.5 ); VSIFWriteL( world_text, 1, strlen(world_text), fp ); VSIFCloseL( fp ); /* GDAL should be called to reproject automatically. */ if (msDrawLayer(map, lp, img) != 0) status = MS_FAILURE; if (!lp->debug) VSIUnlink( wldfile ); } else { msSetError(MS_WMSCONNERR, "Unable to create wld file for WMS slide.", "msDrawWMSLayer()"); status = MS_FAILURE; } } /* We're done with the remote server's response... delete it. */ if (!lp->debug) VSIUnlink(lp->data); /* restore prveious type */ lp->type = currenttype; lp->connectiontype = currentconnectiontype; /* restore previous numclasses */ lp->numclasses = numclasses; free(lp->data); lp->data = NULL; return status; #else /* ------------------------------------------------------------------ * WMS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WMSCONNERR, "WMS CLIENT CONNECTION support is not available.", "msDrawWMSLayer()"); return(MS_FAILURE); #endif /* USE_WMS_LYR */ } int msWMSLayerExecuteRequest(mapObj *map, int nOWSLayers, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, int type) { #ifdef USE_WMS_LYR msIOContext *context; httpRequestObj *pasReqInfo; wmsParamsObj sLastWMSParams; int i, numReq = 0; pasReqInfo = (httpRequestObj *)msSmallMalloc((nOWSLayers+1)*sizeof(httpRequestObj)); msHTTPInitRequestObj(pasReqInfo, nOWSLayers+1); msInitWmsParamsObj(&sLastWMSParams); /* Generate the http request */ for (i=0; inumlayers; i++) { if (GET_LAYER(map,map->layerorder[i])->status == MS_ON) { if (type == WMS_GETFEATUREINFO && msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), WMS_GETFEATUREINFO, MS_WMS, &sLastWMSParams, nClickX, nClickY, nFeatureCount, pszInfoFormat, pasReqInfo, &numReq) == MS_FAILURE) { msFreeWmsParamsObj(&sLastWMSParams); msFree(pasReqInfo); return MS_FAILURE; } else if (msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), WMS_GETLEGENDGRAPHIC, MS_WMS, &sLastWMSParams, 0, 0, 0, NULL, pasReqInfo, &numReq) == MS_FAILURE) { msFreeWmsParamsObj(&sLastWMSParams); msFree(pasReqInfo); return MS_FAILURE; } } } if (msOWSExecuteRequests(pasReqInfo, numReq, map, MS_FALSE) == MS_FAILURE) { msHTTPFreeRequestObj(pasReqInfo, numReq); msFree(pasReqInfo); msFreeWmsParamsObj(&sLastWMSParams); return MS_FAILURE; } context = msIO_getHandler( stdout ); if( context == NULL ) { msHTTPFreeRequestObj(pasReqInfo, numReq); msFree(pasReqInfo); msFreeWmsParamsObj(&sLastWMSParams); return MS_FAILURE; } msIO_printf("Content-Type: %s%c%c",pasReqInfo[0].pszContentType, 10,10); if( pasReqInfo[0].pszOutputFile ) { FILE *fp; char szBuf[MS_BUFFER_LENGTH]; fp = fopen(pasReqInfo[0].pszOutputFile, "r"); if (fp) { while(1) { size_t nSize; nSize = fread(szBuf, sizeof(char), MS_BUFFER_LENGTH-1, fp); if (nSize > 0) msIO_contextWrite( context, szBuf, nSize); if (nSize != MS_BUFFER_LENGTH-1) break; } fclose(fp); if (!map->debug) unlink(pasReqInfo[0].pszOutputFile); } else { msSetError(MS_IOERR, "'%s'.", "msWMSLayerExecuteRequest()", pasReqInfo[0].pszOutputFile); return MS_FAILURE; } } else { msIO_contextWrite( context, pasReqInfo[0].result_data, pasReqInfo[0].result_size ); } msHTTPFreeRequestObj(pasReqInfo, numReq); msFree(pasReqInfo); msFreeWmsParamsObj(&sLastWMSParams); return MS_SUCCESS; #else /* ------------------------------------------------------------------ * WMS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WMSCONNERR, "WMS CLIENT CONNECTION support is not available.", "msWMSLayerExecuteRequest()"); return(MS_FAILURE); #endif /* USE_WMS_LYR */ } mapserver-6.4.1/mapcpl.c0000644002461700001440000002206112261257215014735 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions copied from GDAL's CPL. This file contain utility * functions that come from the GDAL/OGR cpl library. The idea * behind it is to have access in mapserver to all these * utilities, without being constrained to link with GDAL/OGR. * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * * * Note: * Names of functions used here are the same as those in the cpl * library with the exception the the CPL prefix is changed to ms * (eg : CPLGetBasename() would become msGetBasename()) * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* $Id$ */ #include #include "mapserver.h" /* should be size of largest possible filename */ #define MS_PATH_BUF_SIZE 2048 static char szStaticResult[MS_PATH_BUF_SIZE]; /************************************************************************/ /* msFindFilenameStart() */ /************************************************************************/ static int msFindFilenameStart( const char * pszFilename ) { int iFileStart; for( iFileStart = strlen(pszFilename); iFileStart > 0 && pszFilename[iFileStart-1] != '/' && pszFilename[iFileStart-1] != '\\'; iFileStart-- ) {} return iFileStart; } /************************************************************************/ /* msGetBasename() */ /************************************************************************/ /** * Extract basename (non-directory, non-extension) portion of filename. * * Returns a string containing the file basename portion of the passed * name. If there is no basename (passed value ends in trailing directory * separator, or filename starts with a dot) an empty string is returned. * *
 * msGetBasename( "abc/def.xyz" ) == "def"
 * msGetBasename( "abc/def" ) == "def"
 * msGetBasename( "abc/def/" ) == ""
 * 
* * @param pszFullFilename the full filename potentially including a path. * * @return just the non-directory, non-extension portion of the path in * an internal string which must not be freed. The string * may be destroyed by the next ms filename handling call. */ const char *msGetBasename( const char *pszFullFilename ) { int iFileStart = msFindFilenameStart( pszFullFilename ); int iExtStart, nLength; for( iExtStart = strlen(pszFullFilename); iExtStart > iFileStart && pszFullFilename[iExtStart] != '.'; iExtStart-- ) {} if( iExtStart == iFileStart ) iExtStart = strlen(pszFullFilename); nLength = iExtStart - iFileStart; assert( nLength < MS_PATH_BUF_SIZE ); strlcpy( szStaticResult, pszFullFilename + iFileStart, nLength+1 ); return szStaticResult; } /* Id: GDAL/port/cplgetsymbol.cpp,v 1.14 2004/11/11 20:40:38 fwarmerdam Exp */ /* ==================================================================== */ /* Unix Implementation */ /* ==================================================================== */ #if defined(HAVE_DLFCN_H) #define GOT_GETSYMBOL #include /************************************************************************/ /* msGetSymbol() */ /************************************************************************/ /** * Fetch a function pointer from a shared library / DLL. * * This function is meant to abstract access to shared libraries and * DLLs and performs functions similar to dlopen()/dlsym() on Unix and * LoadLibrary() / GetProcAddress() on Windows. * * If no support for loading entry points from a shared library is available * this function will always return NULL. Rules on when this function * issues a msError() or not are not currently well defined, and will have * to be resolved in the future. * * Currently msGetSymbol() doesn't try to: *
    *
  • prevent the reference count on the library from going up * for every request, or given any opportunity to unload * the library. *
  • Attempt to look for the library in non-standard * locations. *
  • Attempt to try variations on the symbol name, like * pre-prending or post-pending an underscore. *
* * Some of these issues may be worked on in the future. * * @param pszLibrary the name of the shared library or DLL containing * the function. May contain path to file. If not system supplies search * paths will be used. * @param pszSymbolName the name of the function to fetch a pointer to. * @return A pointer to the function if found, or NULL if the function isn't * found, or the shared library can't be loaded. */ void *msGetSymbol( const char * pszLibrary, const char * pszSymbolName ) { void *pLibrary; void *pSymbol; pLibrary = dlopen(pszLibrary, RTLD_LAZY); if( pLibrary == NULL ) { msSetError(MS_MISCERR, "Dynamic loading failed: %s", "msGetSymbol()", dlerror()); return NULL; } pSymbol = dlsym( pLibrary, pszSymbolName ); #if (defined(__APPLE__) && defined(__MACH__)) /* On mach-o systems, C symbols have a leading underscore and depending * on how dlcompat is configured it may or may not add the leading * underscore. So if dlsym() fails add an underscore and try again. */ if( pSymbol == NULL ) { char withUnder[strlen(pszSymbolName) + 2]; withUnder[0] = '_'; withUnder[1] = 0; strcat(withUnder, pszSymbolName); pSymbol = dlsym( pLibrary, withUnder ); } #endif if( pSymbol == NULL ) { msSetError(MS_MISCERR, "Dynamic loading failed: %s", "msGetSymbol()", dlerror()); return NULL; } return( pSymbol ); } #endif /* def __unix__ && defined(HAVE_DLFCN_H) */ /* ==================================================================== */ /* Windows Implementation */ /* ==================================================================== */ #ifdef WIN32 #define GOT_GETSYMBOL #include /************************************************************************/ /* msGetSymbol() */ /************************************************************************/ void *msGetSymbol( const char * pszLibrary, const char * pszSymbolName ) { void *pLibrary; void *pSymbol; pLibrary = LoadLibrary(pszLibrary); if( pLibrary == NULL ) { msSetError(MS_MISCERR, "Can't load requested dynamic library: %s", "msGetSymbol()", pszLibrary); return NULL; } pSymbol = (void *) GetProcAddress( (HINSTANCE) pLibrary, pszSymbolName ); if( pSymbol == NULL ) { msSetError(MS_MISCERR, "Can't find requested entry point: %s in lib %s", "msGetSymbol()", pszSymbolName, pLibrary); return NULL; } return( pSymbol ); } #endif /* def _WIN32 */ /* ==================================================================== */ /* Dummy implementation. */ /* ==================================================================== */ #ifndef GOT_GETSYMBOL /************************************************************************/ /* msGetSymbol() */ /* */ /* Dummy implementation. */ /************************************************************************/ void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint) { msSetError(MS_MISCERR, "msGetSymbol(%s,%s) called. Failed as this is stub implementation.", "msGetSymbol()", pszLibrary, pszEntryPoint); return NULL; } #endif mapserver-6.4.1/github_issue_no_activity_closer.py0000644002461700001440000000746112261257215022347 0ustar tbonfortusers#!/usr/bin/env python import datetime import getpass import json import re import time import requests AUTOCLOSE_MESSAGE = """\ ### This is an automated comment This issue has been closed due to lack of activity. This doesn't mean the \ issue is invalid, it simply got no attention within the last year. Please \ reopen if still valid. """ AUTOCLOSE_LABEL = "No Recent Activity" def fetch_issues(github_auth): issues = [] url = ("https://api.github.com/repos/mapserver/mapserver-import/issues?" "per_page=100") while url: print "Fetching %s" % url r = requests.get(url, auth=github_auth) r.raise_for_status() time.sleep(1) issues.extend(r.json()) match = re.match(r'<(.*?)>; rel="next"', r.headers['Link'] or '') url = match.group(1) if match else None return issues def close_issue(issue, github_auth): """Attempt to close an issue and return whether it succeeded.""" r = requests.post("https://api.github.com/repos/mapserver/mapserver-import/" "issues/%s" % issue['number'], data=json.dumps({'state': 'closed'}), auth=github_auth) try: r.raise_for_status() time.sleep(1) return True except requests.HTTPError: return False def post_issue_comment(issue, comment_text, github_auth): """Attempt to post an issue comment and return whether it succeeded.""" r = requests.post("https://api.github.com/repos/mapserver/mapserver-import/" "issues/%s/comments" % issue['number'], data=json.dumps({'body': comment_text}), auth=github_auth) try: r.raise_for_status() time.sleep(1) return True except requests.HTTPError: return False def add_issue_label(issue, label, github_auth): """Attempt to add a label to the issue and return whether it succeeded.""" r = requests.post("https://api.github.com/repos/mapserver/mapserver-import/" "issues/%s/labels" % issue['number'], data=json.dumps([label]), auth=github_auth) try: r.raise_for_status() time.sleep(1) return True except requests.HTTPError: return False def close_old_issues(close_before, github_auth): all_issues = fetch_issues(github_auth) for issue in all_issues: issue_last_activity = datetime.datetime.strptime( issue['updated_at'], "%Y-%m-%dT%H:%M:%SZ") print "Processing issue %s with last activity at %s" % (issue['number'], issue_last_activity) if issue_last_activity < close_before: if post_issue_comment(issue, AUTOCLOSE_MESSAGE, github_auth): print " Added comment to old issue %s" % issue['number'] else: print " Error adding comment to old issue %s" % issue['number'] continue if add_issue_label(issue, AUTOCLOSE_LABEL, github_auth): print " Added label to old issue %s" % issue['number'] else: print " Error adding label to old issue %s" % issue['number'] if close_issue(issue, github_auth): print " Closed old issue %s" % issue['number'] else: print " Error closing old issue %s" % issue['number'] if __name__ == '__main__': close_before = datetime.datetime.today() - datetime.timedelta(days=366) print print "This script will close all issues with no activity for a year." print default_user = "mapserver-bot" github_user = (raw_input("GitHub username [%s]: " % default_user) or default_user) github_pass = getpass.getpass() print github_auth = (github_user, github_pass) close_old_issues(close_before, github_auth) mapserver-6.4.1/msencrypt.c0000644002461700001440000000517212261257215015511 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Command-line encryption utility (see MS-RFC-18) * Author: Daniel Morissette * ****************************************************************************** * Copyright (c) 1996-2006 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. ****************************************************************************/ #include "mapserver.h" void PrintUsage() { printf("Usage: msencrypt <-keygen filename>|<-key filename string_to_encrypt>\n"); } int main(int argc, char *argv[]) { if (argc == 3 && strcmp(argv[1], "-keygen")==0) { /* TODO: Move this to a function */ unsigned char pabyKey[16]; char szKeyEncoded[50]; FILE *fp; msGenerateEncryptionKey(pabyKey); msHexEncode(pabyKey, szKeyEncoded, 16); if ((fp = fopen(argv[2], "wt")) != NULL) { fprintf(fp, "%s\n", szKeyEncoded); fclose(fp); } else { printf("ERROR: Failed writing to %s\n", argv[2]); return -1; } } else if (argc == 4 && strcmp(argv[1], "-key")==0) { unsigned char key[16]; char *pszBuf; if (msReadEncryptionKeyFromFile(argv[2], key) != MS_SUCCESS) { printf("ERROR: Failed reading key from file %s\n", argv[2]); return -1; } pszBuf = (char*)malloc((strlen(argv[3])*2+17)*sizeof(char)); MS_CHECK_ALLOC(pszBuf, (strlen(argv[3])*2+17)*sizeof(char), -1); msEncryptStringWithKey(key, argv[3], pszBuf); printf("%s\n", pszBuf); msFree(pszBuf); } else { PrintUsage(); } return 0; } mapserver-6.4.1/README.WIN320000644002461700001440000001753712261257215015012 0ustar tbonfortusers-------------------------------------------------------------------- README.WIN32 - Microsoft Visual C++ Build instructions for MapServer -------------------------------------------------------------------- IMPORTANT - READ THIS FIRST: ---------------------------- The Win32 build process is not very friendly for unexperienced users. So it is strongly recommended that you use one of the precompiled binaries available on the MapServer site: http://mapserver.gis.umn.edu/download/current/windows There are precompiled Win32 binaries available for the last stable release and the latest nightly build and they include the most common options... so you shouldn't have to compile your own executables. If for some reason you still decide to compile Win32 binaries yourself, then don't do it unless you really know what you're doing... and hopefully the rest of this file contains some hints that may help you. Good Luck! -------------------------------------------------------------------- For the developers using MSVC++, a NMAKE makefile (Makefile.vc + nmake.opt) to build the MapServer library and executable programs is included with the distribution. To build the package using the Makefile.vc and NMAKE: - Edit nmake.opt to select (or deselect) optional components of the MapServer. Please read the notes below about each component before you move ahead with the compilation. - Open a DOS prompt window - Run the VCVARS32.BAT script to initialize the VC++ environment variables. VCVARS32.BAT is automatically generated by the MSVC++ install procedure and should be located in the BIN sub-directory of your MSVC++ installation. - Then start the build with: nmake /f Makefile.vc This will create "mapserv.exe" (the main MapServer CGI program), the other command-line utilities, "mapserver.lib" and "libmap.dll" that is used by theMapScript modules. -------------------------------------------------------------------- MapScript -------------------------------------------------------------------- To compile the various versions of MapScript (Perl, PHP, etc) first compile the main mapserver directory and then see the README files in the mapscript/perl, mapscript/php3 or mapscript/python directory for specific instructions. -------------------------------------------------------------------- GD library -------------------------------------------------------------------- - MapServer uses the GD library from http://boutell.com/ and the Win32 makefiles are set by default to work with the pre-built GD version 2.0.33 provided by Boutell.com. These predefine "gdwin32" binaries include freetype2, libpng, libjpeg, libz, and libgif built-in. This is very convenient to get a mapserver build going quickly. If you are building GD and it's supporting libraries (libpng, libjpeg, libgif, and freetype) from source then it is very important to make sure that you update the -DUSE_GD_* flags and various subcomponent paths in the nmake.opt. You will also have to take great care to build the various components in a way that is compatible with MapServer. For instance, if the various components are statically linked into MapServer you will need to use the same build options (ie. /MT or /MT) for all components. Here are some useful pointers: - The original GD library: http://boutell.com/gd/ - libpng: http://www.libpng.org/pub/png/libpng.html - zlib: http://www.info-zip.org/pub/infozip/zlib/ - libjpeg: ftp://ftp.uu.net/graphics/jpeg/ - Freetype: http://www.freetype.org/download.html -------------------------------------------------------------------- REGEX library -------------------------------------------------------------------- - MapServer uses the REGEX library which is standard on all the Unix systems that I know of, but does not come with VC++. If the MapServer distribution did not include a copy of the REGEX library, then you can get a copy from: ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz The default in the nmake.opt is set to compile with GNU regex-0.12 located in the "regex-0.12" directory. - If you are planning to compile the PHP3_MAPSCRIPT.DLL module, then it is important to make sure that the main Makefile.vc creates MAPSERVER.LIB with the same version of REGEX that PHP uses. See the notes in the main Makefile.vc about that. -------------------------------------------------------------------- Notes on Freetype build. -------------------------------------------------------------------- - You can use the Visual Workspace in freetype/lib/arch/win32 to build the library. -------------------------------------------------------------------- Notes on the proj module -------------------------------------------------------------------- - The Proj.4 (cartographic projection routines) is located at http://www.remotesensing.org/proj/ Note on the epsg files location and the nad directory : * there is an environnemnt variable PROJ_LIB_DIR that can be set to locate the directory where the epsg file is located * if you build this module, at the top of the makefile (./src/makefile.vc), you can set the PROJ_LIB variable and this setting will be used to locate the proj support files. ---------------------------------------------------------------------- Notes on libcurl ---------------------------------------------------------------------- Notes libcurl : used to support WMS client connection Mapserver 5.x is using libcurl instead of libwww for WMS client support. - the library is located at http://curl.haxx.se/download.html Quick notes on how to build the library using MSVC++: - Download and extract the library (at this time it is known to work with version 7.10.2 or more recent) - Open the workspace curlib.dsw located under curl-XXX/lib - Build libcurl.dll. Note that the default active configuraion of the project is Win32 Debug. You can modify the configuarion to Release version (Build/Set Active Configuration) Notes on mapserver's nmake.opt modifications : - uncomment the flag WMSCLIENT= -DUSE_WMS_LYR - uncomment and modify according to your installation the flags related to libcurl : * CURL_INC = -I../curl-7.10.2/include * CURL_LIB = ../curl-7.10.2/lib/Relase/libcurl.lib * WINSOCK_LIB = "C:\Program Files\Microsoft Visual Studio\VC98\Lib\WSOCK32.LIB" You also need to install the libcurl.dll in your system directory. (The dll will be located in libc-XXX/lib/Relase abfter your build of the library) ------------------------------------------------------------ Notes on GDAL ------------------------------------------------------------ - If you are compiling the GDAL library (http://www.gdal.org/) with the PNG support, make sure that the libpng that you use in mapserver is the same as the one used in GDAL. ------------------------------------------------------------ Notes on PDF suuport ------------------------------------------------------------ The PDF support allows the output of a map file as a PDF file. To be able to build mapserver with the PDF support, you need to download and build a PDF library from www.pdflib.com (http://www.pdflib.com/pdflib/download/index.html). The best option is to download the zip file containing the source code and build it. Please refer to the docs inside the zip for informations on how to build the library. Here are some quick notes that can help in building mapserver with PDF : 1) Build the PDF lib - open the project PDFLib.dsw - build the project pdflib_dll - after a sucessful build, you should have a pdflib.lib and pdblib.dll under the pdflib directory - copy the pdflib.dll under your system directory (ex : c:/winnt/system32) 2) Build mapserver with PDF - uncomment in the nmake.opt the flags related to PDF $Id$ mapserver-6.4.1/layerobject.c0000644002461700001440000001431512261257215015767 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions for operating on a layerObj that don't belong in a * more specific file such as mapfile.c. * Adapted from mapobject.c. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 2004, Sean Gillies * * 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. ****************************************************************************/ #include "mapserver.h" #ifdef USE_GDAL # include "gdal.h" # include "cpl_conv.h" #endif /* =========================================================================== msInsertClass Returns the index at which the class was inserted. ======================================================================== */ int msInsertClass(layerObj *layer, classObj *classobj, int nIndex) { int i; if (!classobj) { msSetError(MS_CHILDERR, "Cannot insert NULL class", "msInsertClass()"); return -1; } /* Ensure there is room for a new class */ if (msGrowLayerClasses(layer) == NULL) { return -1; } /* Catch attempt to insert past end of styles array */ else if (nIndex >= layer->numclasses) { msSetError(MS_CHILDERR, "Cannot insert class beyond index %d", "msInsertClass()", layer->numclasses-1); return -1; } else if (nIndex < 0) { /* Insert at the end by default */ #ifndef __cplusplus layer->class[layer->numclasses]=classobj; #else layer->_class[layer->numclasses]=classobj; #endif /* set parent pointer */ classobj->layer=layer; MS_REFCNT_INCR(classobj); layer->numclasses++; return layer->numclasses-1; } else if (nIndex >= 0 && nIndex < layer->numclasses) { /* Copy classes existing at the specified nIndex or greater */ /* to an index one higher */ #ifndef __cplusplus for (i=layer->numclasses-1; i>=nIndex; i--) layer->class[i+1] = layer->class[i]; layer->class[nIndex]=classobj; #else for (i=layer->numclasses-1; i>=nIndex; i--) layer->_class[i+1] = layer->_class[i]; layer->_class[nIndex]=classobj; #endif /* set parent pointer */ classobj->layer=layer; MS_REFCNT_INCR(classobj); /* increment number of classes and return */ layer->numclasses++; return nIndex; } else { msSetError(MS_CHILDERR, "Invalid index", "msInsertClass()"); return -1; } } /* =========================================================================== msRemoveClass remove the class at an index from a layer, returning a copy ======================================================================== */ classObj *msRemoveClass(layerObj *layer, int nIndex) { int i; classObj *classobj; if (nIndex < 0 || nIndex >= layer->numclasses) { msSetError(MS_CHILDERR, "Cannot remove class, invalid index %d", "removeClass()", nIndex); return NULL; } else { #ifndef __cplusplus classobj=layer->class[nIndex]; #else classobj=layer->_class[nIndex]; #endif classobj->layer=NULL; MS_REFCNT_DECR(classobj); /* Iteratively copy the higher index classes down one index */ for (i=nIndex; inumclasses-1; i++) { #ifndef __cplusplus layer->class[i]=layer->class[i+1]; #else layer->_class[i]=layer->_class[i+1]; #endif } #ifndef __cplusplus layer->class[i]=NULL; #else layer->_class[i]=NULL; #endif /* decrement number of layers and return copy of removed layer */ layer->numclasses--; return classobj; } } /** * Move the class up inside the array of classes. */ int msMoveClassUp(layerObj *layer, int nClassIndex) { classObj *psTmpClass = NULL; if (layer && nClassIndex < layer->numclasses && nClassIndex >0) { psTmpClass=layer->class[nClassIndex]; layer->class[nClassIndex] = layer->class[nClassIndex-1]; layer->class[nClassIndex-1] = psTmpClass; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveClassUp()", nClassIndex); return (MS_FAILURE); } /** * Move the class down inside the array of classes. */ int msMoveClassDown(layerObj *layer, int nClassIndex) { classObj *psTmpClass = NULL; if (layer && nClassIndex < layer->numclasses-1 && nClassIndex >=0) { psTmpClass=layer->class[nClassIndex]; layer->class[nClassIndex] = layer->class[nClassIndex+1]; layer->class[nClassIndex+1] = psTmpClass; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveClassDown()", nClassIndex); return (MS_FAILURE); } /** * Set the extent of a layer. */ int msLayerSetExtent( layerObj *layer, double minx, double miny, double maxx, double maxy) { layer->extent.minx = minx; layer->extent.miny = miny; layer->extent.maxx = maxx; layer->extent.maxy = maxy; if (minx == -1.0 && miny == -1.0 && maxx == -1.0 && maxy == -1.0) return(MS_SUCCESS); if (!MS_VALID_EXTENT(layer->extent)) { msSetError(MS_MISCERR, "Given layer extent is invalid. minx=%lf, miny=%lf, maxx=%lf, maxy=%lf.", "msLayerSetExtent()", layer->extent.minx, layer->extent.miny, layer->extent.maxx, layer->extent.maxy); return(MS_FAILURE); } return(MS_SUCCESS); } mapserver-6.4.1/mapogcfilter.c0000644002461700001440000040474412261257215016151 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Filter Encoding implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #define _GNU_SOURCE #include "mapserver-config.h" #ifdef USE_OGR #include "cpl_minixml.h" #include "cpl_string.h" #endif #include "mapogcfilter.h" #include "mapserver.h" #include "mapowscommon.h" int FLTIsNumeric(char *pszValue) { if (pszValue != NULL && *pszValue != '\0' && !isspace(*pszValue)) { /*the regex seems to have a problem on windows when mapserver is built using PHP regex*/ #if defined(_WIN32) && !defined(__CYGWIN__) int i = 0, nLength=0, bString=0; nLength = strlen(pszValue); for (i=0; iconnectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_SDE || lp->connectiontype == MS_PLUGIN) { pszFinalExpression = msStrdup("("); pszFinalExpression = msStringConcatenate(pszFinalExpression, pszExpression); pszFinalExpression = msStringConcatenate(pszFinalExpression, ")"); } else if (lp->connectiontype == MS_OGR) { pszFinalExpression = msStrdup(pszExpression); if (lp->filter.type != MS_EXPRESSION) { bConcatWhere = 1; } else { if (lp->filter.string && EQUALN(lp->filter.string,"WHERE ",6)) { bHasAWhere = 1; bConcatWhere =1; } } } else pszFinalExpression = msStrdup(pszExpression); if (bConcatWhere) pszBuffer = msStringConcatenate(pszBuffer, "WHERE "); /* if the filter is set and it's an expression type, concatenate it with this filter. If not just free it */ if (lp->filter.string && lp->filter.type == MS_EXPRESSION) { pszBuffer = msStringConcatenate(pszBuffer, "(("); if (bHasAWhere) pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string+6); else pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); } else if (lp->filter.string) freeExpression(&lp->filter); pszBuffer = msStringConcatenate(pszBuffer, pszFinalExpression); if(lp->filter.string && lp->filter.type == MS_EXPRESSION) pszBuffer = msStringConcatenate(pszBuffer, ")"); /*assuming that expression was properly escaped escapedTextString = msStringEscape(pszBuffer); msLoadExpressionString(&lp->filter, (char*)CPLSPrintf("%s", escapedTextString)); msFree(escapedTextString); */ msLoadExpressionString(&lp->filter, pszBuffer); msFree(pszFinalExpression); if (pszBuffer) msFree(pszBuffer); return MS_TRUE; } return MS_FALSE; } char *FLTGetExpressionForValuesRanges(layerObj *lp, char *item, char *value, int forcecharcter) { int bIscharacter, bSqlLayer; char *pszExpression = NULL, *pszEscapedStr=NULL, *pszTmpExpression=NULL; char **paszElements = NULL, **papszRangeElements=NULL; int numelements,i,nrangeelements; /* double minval, maxval; */ if (lp && item && value) { if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_SDE || lp->connectiontype == MS_PLUGIN) bSqlLayer = MS_TRUE; else bSqlLayer = MS_FALSE; if (strstr(value, "/") == NULL) { /*value(s)*/ paszElements = msStringSplit (value, ',', &numelements); if (paszElements && numelements > 0) { if (forcecharcter) bIscharacter = MS_TRUE; bIscharacter= !FLTIsNumeric(paszElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); for (i=0; i 0) { pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); for (i=0; i 0) { pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); if (nrangeelements == 2 || nrangeelements == 3) { /* minval = atof(papszRangeElements[0]); maxval = atof(papszRangeElements[1]); */ if (bSqlLayer) pszTmpExpression = msStringConcatenate(pszTmpExpression, item); else { pszTmpExpression = msStringConcatenate(pszTmpExpression, "["); pszTmpExpression = msStringConcatenate(pszTmpExpression, item); pszTmpExpression = msStringConcatenate(pszTmpExpression, "]"); } pszTmpExpression = msStringConcatenate(pszTmpExpression, " >= "); pszEscapedStr = msLayerEscapeSQLParam(lp, papszRangeElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; pszTmpExpression = msStringConcatenate(pszTmpExpression, " AND "); if (bSqlLayer) pszTmpExpression = msStringConcatenate(pszTmpExpression, item); else { pszTmpExpression = msStringConcatenate(pszTmpExpression, "["); pszTmpExpression = msStringConcatenate(pszTmpExpression, item); pszTmpExpression = msStringConcatenate(pszTmpExpression, "]"); } pszTmpExpression = msStringConcatenate(pszTmpExpression, " <= "); pszEscapedStr = msLayerEscapeSQLParam(lp, papszRangeElements[1]); pszTmpExpression = msStringConcatenate(pszTmpExpression, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; pszTmpExpression = msStringConcatenate(pszTmpExpression, ")"); } else if (nrangeelements == 1) { pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); if (bSqlLayer) pszTmpExpression = msStringConcatenate(pszTmpExpression, item); else { pszTmpExpression = msStringConcatenate(pszTmpExpression, "["); pszTmpExpression = msStringConcatenate(pszTmpExpression, item); pszTmpExpression = msStringConcatenate(pszTmpExpression, "]"); } pszTmpExpression = msStringConcatenate(pszTmpExpression, " = "); pszEscapedStr = msLayerEscapeSQLParam(lp, papszRangeElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; pszTmpExpression = msStringConcatenate(pszTmpExpression, ")"); } if (pszExpression != NULL) pszExpression = msStringConcatenate(pszExpression, " OR "); pszExpression = msStringConcatenate(pszExpression, pszTmpExpression); msFree(pszTmpExpression); pszTmpExpression = NULL; msFreeCharArray(papszRangeElements, nrangeelements); } } pszExpression = msStringConcatenate(pszExpression, ")"); msFreeCharArray(paszElements, numelements); } } } return pszExpression; } #ifdef USE_OGR int FLTogrConvertGeometry(OGRGeometryH hGeometry, shapeObj *psShape, OGRwkbGeometryType nType) { return msOGRGeometryToShape(hGeometry, psShape, nType); } int FLTShapeFromGMLTree(CPLXMLNode *psTree, shapeObj *psShape , char **ppszSRS) { char *pszSRS = NULL; if (psTree && psShape) { CPLXMLNode *psNext = psTree->psNext; OGRGeometryH hGeometry = NULL; psTree->psNext = NULL; hGeometry = OGR_G_CreateFromGMLTree(psTree ); psTree->psNext = psNext; if (hGeometry) { OGRwkbGeometryType nType; nType = OGR_G_GetGeometryType(hGeometry); if (nType == wkbPolygon25D || nType == wkbMultiPolygon25D) nType = wkbPolygon; else if (nType == wkbLineString25D || nType == wkbMultiLineString25D) nType = wkbLineString; else if (nType == wkbPoint25D || nType == wkbMultiPoint25D) nType = wkbPoint; FLTogrConvertGeometry(hGeometry, psShape, nType); OGR_G_DestroyGeometry(hGeometry); } pszSRS = (char *)CPLGetXMLValue(psTree, "srsName", NULL); if (ppszSRS && pszSRS) *ppszSRS = msStrdup(pszSRS); return MS_TRUE; } return MS_FALSE; } int FLTGetGeosOperator(char *pszValue) { if (!pszValue) return -1; if (strcasecmp(pszValue, "Equals") == 0) return MS_GEOS_EQUALS; else if (strcasecmp(pszValue, "Intersect") == 0 || strcasecmp(pszValue, "Intersects") == 0) return MS_GEOS_INTERSECTS; else if (strcasecmp(pszValue, "Disjoint") == 0) return MS_GEOS_DISJOINT; else if (strcasecmp(pszValue, "Touches") == 0) return MS_GEOS_TOUCHES; else if (strcasecmp(pszValue, "Crosses") == 0) return MS_GEOS_CROSSES; else if (strcasecmp(pszValue, "Within") == 0) return MS_GEOS_WITHIN; else if (strcasecmp(pszValue, "Contains") == 0) return MS_GEOS_CONTAINS; else if (strcasecmp(pszValue, "Overlaps") == 0) return MS_GEOS_OVERLAPS; else if (strcasecmp(pszValue, "Beyond") == 0) return MS_GEOS_BEYOND; else if (strcasecmp(pszValue, "DWithin") == 0) return MS_GEOS_DWITHIN; return -1; } int FLTIsGeosNode(char *pszValue) { if (FLTGetGeosOperator(pszValue) == -1) return MS_FALSE; return MS_TRUE; } int FLTParseEpsgString(char *pszEpsg, projectionObj *psProj) { int nStatus = MS_FALSE; int nTokens = 0; char **tokens = NULL; int nEpsgTmp=0; #ifdef USE_PROJ if (pszEpsg && psProj) { nTokens = 0; /* There are several forms an epsg code may be given. In any case the */ /* epsg code is the last token. */ /* TODO: To make sure it is an epsg code check the string, too. */ /* - urn:ogc:def:crs:EPSG:6.5:4326 */ /* - urn:ogc:def:crs:EPSG::4326 */ /* - http://www.opengis.net/gml/srs/epsg.xml#4326 */ /* - epsg:4326 */ tokens = msStringSplit(pszEpsg,'#', &nTokens); if( tokens && nTokens == 1 ) { msFreeCharArray(tokens, nTokens); tokens = msStringSplit(pszEpsg,':', &nTokens); } if (tokens && nTokens > 1) { nEpsgTmp = atoi(tokens[nTokens-1]); if (nEpsgTmp > 0) { char szTmp[32]; snprintf(szTmp, sizeof(szTmp), "init=epsg:%d",nEpsgTmp); msInitProjection(psProj); if (msLoadProjectionString(psProj, szTmp) == 0) nStatus = MS_TRUE; } } if (tokens) msFreeCharArray(tokens, nTokens); } #endif return nStatus; } int FLTGML2Shape_XMLNode(CPLXMLNode *psNode, shapeObj *psShp) { lineObj line= {0,NULL}; CPLXMLNode *psCoordinates = NULL; char *pszTmpCoord = NULL; char **szCoords = NULL; int nCoords = 0; if (!psNode || !psShp) return MS_FALSE; if( strcasecmp(psNode->pszValue,"PointType") == 0 || strcasecmp(psNode->pszValue,"Point") == 0) { psCoordinates = CPLGetXMLNode(psNode, "coordinates"); if (psCoordinates && psCoordinates->psChild && psCoordinates->psChild->pszValue) { pszTmpCoord = psCoordinates->psChild->pszValue; szCoords = msStringSplit(pszTmpCoord, ',', &nCoords); if (szCoords && nCoords >= 2) { line.numpoints = 1; line.point = (pointObj *)malloc(sizeof(pointObj)); line.point[0].x = atof(szCoords[0]); line.point[0].y = atof(szCoords[1]); #ifdef USE_POINT_Z_M line.point[0].m = 0; #endif psShp->type = MS_SHAPE_POINT; msAddLine(psShp, &line); free(line.point); return MS_TRUE; } } } return MS_FALSE; } /************************************************************************/ /* FLTIsSimpleFilterNoSpatial */ /* */ /* Filter encoding with only attribute queries */ /************************************************************************/ int FLTIsSimpleFilterNoSpatial(FilterEncodingNode *psNode) { if (FLTIsSimpleFilter(psNode) && FLTNumberOfFilterType(psNode, "BBOX") == 0) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* FLTApplySimpleSQLFilter() */ /************************************************************************/ int FLTApplySimpleSQLFilter(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { layerObj *lp = NULL; char *szExpression = NULL; rectObj sQueryRect = map->extent; char *szEPSG = NULL; projectionObj sProjTmp; char *pszBuffer = NULL; int bConcatWhere = 0; int bHasAWhere =0; char *pszTmp = NULL, *pszTmp2 = NULL; char *tmpfilename = NULL; lp = (GET_LAYER(map, iLayerIndex)); /* if there is a bbox use it */ szEPSG = FLTGetBBOX(psNode, &sQueryRect); if(szEPSG && map->projection.numargs > 0) { if (FLTParseEpsgString(szEPSG, &sProjTmp)) { msProjectRect(&sProjTmp, &map->projection, &sQueryRect); msFreeProjection(&sProjTmp); } } /* make sure that the layer can be queried*/ if (!lp->template) lp->template = msStrdup("ttt.html"); /* if there is no class, create at least one, so that query by rect would work*/ if (lp->numclasses == 0) { if (msGrowLayerClasses(lp) == NULL) return MS_FAILURE; initClass(lp->class[0]); } bConcatWhere = 0; bHasAWhere = 0; if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_SDE || lp->connectiontype == MS_PLUGIN) { szExpression = FLTGetSQLExpression(psNode, lp); if (szExpression) { pszTmp = msStrdup("("); pszTmp = msStringConcatenate(pszTmp, szExpression); pszTmp = msStringConcatenate(pszTmp, ")"); msFree(szExpression); szExpression = pszTmp; } } /* concatenates the WHERE clause for OGR layers. This only applies if the expression was empty or not of an expression string. If there is an sql type expression, it is assumed to have the WHERE clause. If it is an expression and does not have a WHERE it is assumed to be a mapserver type expression*/ else if (lp->connectiontype == MS_OGR) { if (lp->filter.type != MS_EXPRESSION) { szExpression = FLTGetSQLExpression(psNode, lp); bConcatWhere = 1; } else { if (lp->filter.string && EQUALN(lp->filter.string,"WHERE ",6)) { szExpression = FLTGetSQLExpression(psNode, lp); bHasAWhere = 1; bConcatWhere =1; } else { szExpression = FLTGetCommonExpression(psNode, lp); } } } else { szExpression = FLTGetCommonExpression(psNode, lp); } if (szExpression) { if (bConcatWhere) pszBuffer = msStringConcatenate(pszBuffer, "WHERE "); /* if the filter is set and it's an expression type, concatenate it with this filter. If not just free it */ if (lp->filter.string && lp->filter.type == MS_EXPRESSION) { pszBuffer = msStringConcatenate(pszBuffer, "(("); if (bHasAWhere) pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string+6); else pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); } else if (lp->filter.string) freeExpression(&lp->filter); pszBuffer = msStringConcatenate(pszBuffer, szExpression); if(lp->filter.string && lp->filter.type == MS_EXPRESSION) pszBuffer = msStringConcatenate(pszBuffer, ")"); msLoadExpressionString(&lp->filter, pszBuffer); free(szExpression); } if (pszBuffer) free(pszBuffer); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = lp->index; map->query.rect = sQueryRect; if(map->debug == MS_DEBUGLEVEL_VVV) { tmpfilename = msTmpFile(map, map->mappath, NULL, "_filter.map"); if (tmpfilename == NULL) { tmpfilename = msTmpFile(map, NULL, NULL, "_filter.map" ); } if (tmpfilename) { msSaveMap(map,tmpfilename); msDebug("FLTApplySimpleSQLFilter(): Map file after Filter was applied %s\n", tmpfilename); msFree(tmpfilename); } } /*for oracle connection, if we have a simple filter with no spatial constraints we should set the connection function to NONE to have a better performance (#2725)*/ if (lp->connectiontype == MS_ORACLESPATIAL && FLTIsSimpleFilterNoSpatial(psNode)) { if (strcasestr(lp->data, "USING") == 0) lp->data = msStringConcatenate(lp->data, " USING NONE"); else if (strcasestr(lp->data, "NONE") == 0) { /*if one of the functions is used, just replace it with NONE*/ if (strcasestr(lp->data, "FILTER")) lp->data = msCaseReplaceSubstring(lp->data, "FILTER", "NONE"); else if (strcasestr(lp->data, "GEOMRELATE")) lp->data = msCaseReplaceSubstring(lp->data, "GEOMRELATE", "NONE"); else if (strcasestr(lp->data, "RELATE")) lp->data = msCaseReplaceSubstring(lp->data, "RELATE", "NONE"); else if (strcasestr(lp->data, "VERSION")) { /*should add NONE just before the VERSION. Cases are: DATA "ORA_GEOMETRY FROM data USING VERSION 10g DATA "ORA_GEOMETRY FROM data USING UNIQUE FID VERSION 10g" */ pszTmp = (char *)strcasestr(lp->data, "VERSION"); pszTmp2 = msStringConcatenate(pszTmp2, " NONE "); pszTmp2 = msStringConcatenate(pszTmp2, pszTmp); lp->data = msCaseReplaceSubstring(lp->data, pszTmp, pszTmp2); msFree(pszTmp2); } else if (strcasestr(lp->data, "SRID")) { lp->data = msStringConcatenate(lp->data, " NONE"); } } } return msQueryByRect(map); /* return MS_SUCCESS; */ } /************************************************************************/ /* FLTIsSimpleFilter */ /* */ /* Filter encoding with only attribute queries and only one bbox. */ /************************************************************************/ int FLTIsSimpleFilter(FilterEncodingNode *psNode) { if (FLTValidForBBoxFilter(psNode)) { if (FLTNumberOfFilterType(psNode, "DWithin") == 0 && FLTNumberOfFilterType(psNode, "Intersect") == 0 && FLTNumberOfFilterType(psNode, "Intersects") == 0 && FLTNumberOfFilterType(psNode, "Equals") == 0 && FLTNumberOfFilterType(psNode, "Disjoint") == 0 && FLTNumberOfFilterType(psNode, "Touches") == 0 && FLTNumberOfFilterType(psNode, "Crosses") == 0 && FLTNumberOfFilterType(psNode, "Within") == 0 && FLTNumberOfFilterType(psNode, "Contains") == 0 && FLTNumberOfFilterType(psNode, "Overlaps") == 0 && FLTNumberOfFilterType(psNode, "Beyond") == 0) return TRUE; } return FALSE; } /************************************************************************/ /* FLTApplyFilterToLayer */ /* */ /* Use the filter encoding node to create mapserver expressions */ /* and apply it to the layer. */ /************************************************************************/ int FLTApplyFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { layerObj *layer = GET_LAYER(map, iLayerIndex); if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerApplyFilterToLayer(psNode, map, iLayerIndex); } /************************************************************************/ /* FLTLayerApplyCondSQLFilterToLayer */ /* */ /* Helper function for layer virtual table architecture */ /************************************************************************/ int FLTLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { /* ==================================================================== */ /* Check here to see if it is a simple filter and if that is */ /* the case, we are going to use the FILTER element on */ /* the layer. */ /* ==================================================================== */ if (FLTIsSimpleFilter(psNode)) { return FLTApplySimpleSQLFilter(psNode, map, iLayerIndex); } return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex); } /************************************************************************/ /* FLTLayerApplyPlainFilterToLayer */ /* */ /* Helper function for layer virtual table architecture */ /************************************************************************/ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { char *pszExpression =NULL; int status =MS_FALSE; pszExpression = FLTGetCommonExpression(psNode, GET_LAYER(map, iLayerIndex)); if(map->debug == MS_DEBUGLEVEL_VVV) msDebug("FLTLayerApplyPlainFilterToLayer(): %s\n", pszExpression); if (pszExpression) { status = FLTApplyFilterToLayerCommonExpression(map, iLayerIndex, pszExpression); msFree(pszExpression); } return status; } /************************************************************************/ /* FilterNode *FLTPaserFilterEncoding(char *szXMLString) */ /* */ /* Parses an Filter Encoding XML string and creates a */ /* FilterEncodingNodes corresponding to the string. */ /* Returns a pointer to the first node or NULL if */ /* unsuccessfull. */ /* Calling function should use FreeFilterEncodingNode function */ /* to free memeory. */ /************************************************************************/ FilterEncodingNode *FLTParseFilterEncoding(char *szXMLString) { CPLXMLNode *psRoot = NULL, *psChild=NULL, *psFilter=NULL; CPLXMLNode *psFilterStart = NULL; FilterEncodingNode *psFilterNode = NULL; if (szXMLString == NULL || strlen(szXMLString) <= 0 || (strstr(szXMLString, "Filter") == NULL)) return NULL; psRoot = CPLParseXMLString(szXMLString); if( psRoot == NULL) return NULL; /* strip namespaces. We srtip all name spaces (#1350)*/ CPLStripXMLNamespace(psRoot, NULL, 1); /* -------------------------------------------------------------------- */ /* get the root element (Filter). */ /* -------------------------------------------------------------------- */ psChild = psRoot; psFilter = NULL; while( psChild != NULL ) { if (psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"Filter")) { psFilter = psChild; break; } else psChild = psChild->psNext; } if (!psFilter) return NULL; psChild = psFilter->psChild; psFilterStart = NULL; while (psChild) { if (FLTIsSupportedFilterType(psChild)) { psFilterStart = psChild; psChild = NULL; } else psChild = psChild->psNext; } if (psFilterStart && FLTIsSupportedFilterType(psFilterStart)) { psFilterNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode, psFilterStart); } CPLDestroyXMLNode( psRoot ); /* -------------------------------------------------------------------- */ /* validate the node tree to make sure that all the nodes are valid.*/ /* -------------------------------------------------------------------- */ if (!FLTValidFilterNode(psFilterNode)) return NULL; return psFilterNode; } /************************************************************************/ /* int FLTValidFilterNode(FilterEncodingNode *psFilterNode) */ /* */ /* Validate that all the nodes are filled properly. We could */ /* have parts of the nodes that are correct and part which */ /* could be incorrect if the filter string sent is corrupted */ /* (eg missing a value :) */ /************************************************************************/ int FLTValidFilterNode(FilterEncodingNode *psFilterNode) { int bReturn = 0; if (!psFilterNode) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_UNDEFINED) return 0; if (psFilterNode->psLeftNode) { bReturn = FLTValidFilterNode(psFilterNode->psLeftNode); if (bReturn == 0) return 0; else if (psFilterNode->psRightNode) return FLTValidFilterNode(psFilterNode->psRightNode); } return 1; } /************************************************************************/ /* FLTFreeFilterEncodingNode */ /* */ /* recursive freeing of Filer Encoding nodes. */ /************************************************************************/ void FLTFreeFilterEncodingNode(FilterEncodingNode *psFilterNode) { if (psFilterNode) { if (psFilterNode->psLeftNode) { FLTFreeFilterEncodingNode(psFilterNode->psLeftNode); psFilterNode->psLeftNode = NULL; } if (psFilterNode->psRightNode) { FLTFreeFilterEncodingNode(psFilterNode->psRightNode); psFilterNode->psRightNode = NULL; } if (psFilterNode->pszSRS) free( psFilterNode->pszSRS); if( psFilterNode->pOther ) { if (psFilterNode->pszValue != NULL && strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) { if( ((FEPropertyIsLike *)psFilterNode->pOther)->pszWildCard ) free( ((FEPropertyIsLike *)psFilterNode->pOther)->pszWildCard ); if( ((FEPropertyIsLike *)psFilterNode->pOther)->pszSingleChar ) free( ((FEPropertyIsLike *)psFilterNode->pOther)->pszSingleChar ); if( ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar ) free( ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar ); } else if (psFilterNode->eType == FILTER_NODE_TYPE_GEOMETRY_POINT || psFilterNode->eType == FILTER_NODE_TYPE_GEOMETRY_LINE || psFilterNode->eType == FILTER_NODE_TYPE_GEOMETRY_POLYGON) { msFreeShape((shapeObj *)(psFilterNode->pOther)); } /* else */ /* TODO free pOther special fields */ free( psFilterNode->pOther ); } /* Cannot free pszValue before, 'cause we are testing it above */ if( psFilterNode->pszValue ) free( psFilterNode->pszValue ); free(psFilterNode); } } /************************************************************************/ /* FLTCreateFilterEncodingNode */ /* */ /* return a FilerEncoding node. */ /************************************************************************/ FilterEncodingNode *FLTCreateFilterEncodingNode(void) { FilterEncodingNode *psFilterNode = NULL; psFilterNode = (FilterEncodingNode *)malloc(sizeof (FilterEncodingNode)); psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; psFilterNode->pszValue = NULL; psFilterNode->pOther = NULL; psFilterNode->pszSRS = NULL; psFilterNode->psLeftNode = NULL; psFilterNode->psRightNode = NULL; return psFilterNode; } FilterEncodingNode *FLTCreateBinaryCompFilterEncodingNode(void) { FilterEncodingNode *psFilterNode = NULL; psFilterNode = FLTCreateFilterEncodingNode(); /* used to store case sensitivity flag. Default is 0 meaning the comparing is case snetitive */ psFilterNode->pOther = (int *)malloc(sizeof(int)); (*(int *)(psFilterNode->pOther)) = 0; return psFilterNode; } /************************************************************************/ /* FLTInsertElementInNode */ /* */ /* Utility function to parse an XML node and transfter the */ /* contennts into the Filer Encoding node structure. */ /************************************************************************/ void FLTInsertElementInNode(FilterEncodingNode *psFilterNode, CPLXMLNode *psXMLNode) { int nStrLength = 0; char *pszTmp = NULL; FilterEncodingNode *psCurFilNode= NULL; CPLXMLNode *psCurXMLNode = NULL; CPLXMLNode *psTmpNode = NULL; CPLXMLNode *psFeatureIdNode = NULL; char *pszFeatureId=NULL, *pszFeatureIdList=NULL; char **tokens = NULL; int nTokens = 0; if (psFilterNode && psXMLNode && psXMLNode->pszValue) { psFilterNode->pszValue = msStrdup(psXMLNode->pszValue); psFilterNode->psLeftNode = NULL; psFilterNode->psRightNode = NULL; /* -------------------------------------------------------------------- */ /* Logical filter. AND, OR and NOT are supported. Example of */ /* filer using logical filters : */ /* */ /* */ /* */ /* Person/Age */ /* 50 */ /* */ /* */ /* Person/Address/City */ /* Toronto */ /* */ /* */ /* */ /* -------------------------------------------------------------------- */ if (FLTIsLogicalFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_LOGICAL; if (strcasecmp(psFilterNode->pszValue, "AND") == 0 || strcasecmp(psFilterNode->pszValue, "OR") == 0) { if (psXMLNode->psChild && psXMLNode->psChild->psNext) { /*2 operators */ if (psXMLNode->psChild->psNext->psNext == NULL) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode->psLeftNode, psXMLNode->psChild); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode->psRightNode, psXMLNode->psChild->psNext); } else { psCurXMLNode = psXMLNode->psChild; psCurFilNode = psFilterNode; while(psCurXMLNode) { if (psCurXMLNode->psNext && psCurXMLNode->psNext->psNext) { psCurFilNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psCurFilNode->psLeftNode, psCurXMLNode); psCurFilNode->psRightNode = FLTCreateFilterEncodingNode(); psCurFilNode->psRightNode->eType = FILTER_NODE_TYPE_LOGICAL; psCurFilNode->psRightNode->pszValue = msStrdup(psFilterNode->pszValue); psCurFilNode = psCurFilNode->psRightNode; psCurXMLNode = psCurXMLNode->psNext; } else if (psCurXMLNode->psNext) { /*last 2 operators*/ psCurFilNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psCurFilNode->psLeftNode, psCurXMLNode); psCurFilNode->psRightNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psCurFilNode->psRightNode, psCurXMLNode->psNext); psCurXMLNode = psCurXMLNode->psNext->psNext; } } } } } else if (strcasecmp(psFilterNode->pszValue, "NOT") == 0) { if (psXMLNode->psChild) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode->psLeftNode, psXMLNode->psChild); } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; }/* end if is logical */ /* -------------------------------------------------------------------- */ /* Spatial Filter. */ /* BBOX : */ /* */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 35.5472,42.8143*/ /* */ /* */ /* */ /* */ /* DWithin */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 */ /* */ /* 10 */ /* */ /* */ /* */ /* Intersect */ /* */ /* type="ogc:BinarySpatialOpType" substitutionGroup="ogc:spatialOps"/>*/ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* -------------------------------------------------------------------- */ else if (FLTIsSpatialFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_SPATIAL; if (strcasecmp(psXMLNode->pszValue, "BBOX") == 0) { char *pszSRS = NULL; CPLXMLNode *psPropertyName = NULL; CPLXMLNode *psBox = NULL, *psEnvelope=NULL; rectObj sBox; int bCoordinatesValid = 0; psPropertyName = CPLGetXMLNode(psXMLNode, "PropertyName"); psBox = CPLGetXMLNode(psXMLNode, "Box"); if (!psBox) psBox = CPLGetXMLNode(psXMLNode, "BoxType"); /*FE 1.0 used box FE1.1 uses envelop*/ if (psBox) bCoordinatesValid = FLTParseGMLBox(psBox, &sBox, &pszSRS); else if ((psEnvelope = CPLGetXMLNode(psXMLNode, "Envelope"))) bCoordinatesValid = FLTParseGMLEnvelope(psEnvelope, &sBox, &pszSRS); if (psPropertyName == NULL || !bCoordinatesValid) psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; if (psPropertyName && bCoordinatesValid) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); /* not really using the property name anywhere ?? */ /* Is is always Geometry ? */ if (psPropertyName->psChild && psPropertyName->psChild->pszValue) { psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(psPropertyName->psChild->pszValue); } /* srs and coordinates */ psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_BBOX; /* srs might be empty */ if (pszSRS) psFilterNode->psRightNode->pszValue = pszSRS; psFilterNode->psRightNode->pOther = (rectObj *)msSmallMalloc(sizeof(rectObj)); ((rectObj *)psFilterNode->psRightNode->pOther)->minx = sBox.minx; ((rectObj *)psFilterNode->psRightNode->pOther)->miny = sBox.miny; ((rectObj *)psFilterNode->psRightNode->pOther)->maxx = sBox.maxx; ((rectObj *)psFilterNode->psRightNode->pOther)->maxy = sBox.maxy; } } else if (strcasecmp(psXMLNode->pszValue, "DWithin") == 0 || strcasecmp(psXMLNode->pszValue, "Beyond") == 0) { shapeObj *psShape = NULL; int bPoint = 0, bLine = 0, bPolygon = 0; char *pszUnits = NULL; char *pszSRS = NULL; CPLXMLNode *psGMLElement = NULL, *psDistance=NULL; psGMLElement = CPLGetXMLNode(psXMLNode, "Point"); if (!psGMLElement) psGMLElement = CPLGetXMLNode(psXMLNode, "PointType"); if (psGMLElement) bPoint =1; else { psGMLElement= CPLGetXMLNode(psXMLNode, "Polygon"); if (psGMLElement) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiPolygon"))) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiSurface"))) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "Box"))) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "LineString"))) bLine = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiPoint"))) bPoint = 1; } psDistance = CPLGetXMLNode(psXMLNode, "Distance"); if (psGMLElement && psDistance && psDistance->psChild && psDistance->psChild->psNext && psDistance->psChild->psNext->pszValue) { pszUnits = (char *)CPLGetXMLValue(psDistance, "units", NULL); psShape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(psShape); if (FLTShapeFromGMLTree(psGMLElement, psShape, &pszSRS)) /* if (FLTGML2Shape_XMLNode(psPoint, psShape)) */ { /*set the srs if available*/ if (pszSRS) psFilterNode->pszSRS = pszSRS; psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); /* not really using the property name anywhere ?? Is is always */ /* Geometry ? */ psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup("Geometry"); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); if (bPoint) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POINT; else if (bLine) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_LINE; else if (bPolygon) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POLYGON; psFilterNode->psRightNode->pOther = (shapeObj *)psShape; /*the value will be distance;units*/ psFilterNode->psRightNode->pszValue = msStrdup(psDistance->psChild->psNext->pszValue); if (pszUnits) { psFilterNode->psRightNode->pszValue= msStringConcatenate(psFilterNode->psRightNode->pszValue, ";"); psFilterNode->psRightNode->pszValue= msStringConcatenate(psFilterNode->psRightNode->pszValue, pszUnits); } } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else if (strcasecmp(psXMLNode->pszValue, "Intersect") == 0 || strcasecmp(psXMLNode->pszValue, "Intersects") == 0 || strcasecmp(psXMLNode->pszValue, "Equals") == 0 || strcasecmp(psXMLNode->pszValue, "Disjoint") == 0 || strcasecmp(psXMLNode->pszValue, "Touches") == 0 || strcasecmp(psXMLNode->pszValue, "Crosses") == 0 || strcasecmp(psXMLNode->pszValue, "Within") == 0 || strcasecmp(psXMLNode->pszValue, "Contains") == 0 || strcasecmp(psXMLNode->pszValue, "Overlaps") == 0) { shapeObj *psShape = NULL; int bLine = 0, bPolygon = 0, bPoint=0; char *pszSRS = NULL; CPLXMLNode *psGMLElement = NULL; psGMLElement = CPLGetXMLNode(psXMLNode, "Polygon"); if (psGMLElement) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiPolygon"))) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiSurface"))) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "Box"))) bPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "LineString"))) bLine = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiPoint"))) bPoint = 1; else if ((psGMLElement = CPLGetXMLNode(psXMLNode, "Point"))) bPoint = 1; else if ((psGMLElement = CPLGetXMLNode(psXMLNode, "PointType"))) bPoint = 1; if (psGMLElement) { psShape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(psShape); if (FLTShapeFromGMLTree(psGMLElement, psShape, &pszSRS)) /* if (FLTGML2Shape_XMLNode(psPoint, psShape)) */ { /*set the srs if available*/ if (pszSRS) psFilterNode->pszSRS = pszSRS; psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); /* not really using the property name anywhere ?? Is is always */ /* Geometry ? */ psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup("Geometry"); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); if (bPoint) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POINT; if (bLine) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_LINE; else if (bPolygon) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POLYGON; psFilterNode->psRightNode->pOther = (shapeObj *)psShape; } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } }/* end of is spatial */ /* -------------------------------------------------------------------- */ /* Comparison Filter */ /* -------------------------------------------------------------------- */ else if (FLTIsComparisonFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_COMPARISON; /* -------------------------------------------------------------------- */ /* binary comaparison types. Example : */ /* */ /* */ /* */ /* SomeProperty */ /* 100 */ /* */ /* */ /* -------------------------------------------------------------------- */ if (FLTIsBinaryComparisonFilterType(psXMLNode->pszValue)) { psTmpNode = CPLSearchXMLNode(psXMLNode, "PropertyName"); if (psTmpNode && psTmpNode->psChild && psTmpNode->psChild->pszValue && strlen(psTmpNode->psChild->pszValue) > 0) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(psTmpNode->psChild->pszValue); psTmpNode = CPLSearchXMLNode(psXMLNode, "Literal"); if (psTmpNode) { psFilterNode->psRightNode = FLTCreateBinaryCompFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; if (psTmpNode && psTmpNode->psChild && psTmpNode->psChild->pszValue && strlen(psTmpNode->psChild->pszValue) > 0) { psFilterNode->psRightNode->pszValue = msStrdup(psTmpNode->psChild->pszValue); /*check if the matchCase attribute is set*/ if (psXMLNode->psChild && psXMLNode->psChild->eType == CXT_Attribute && psXMLNode->psChild->pszValue && strcasecmp(psXMLNode->psChild->pszValue, "matchCase") == 0 && psXMLNode->psChild->psChild && psXMLNode->psChild->psChild->pszValue && strcasecmp( psXMLNode->psChild->psChild->pszValue, "false") == 0) { (*(int *)psFilterNode->psRightNode->pOther) = 1; } } /* special case where the user puts an empty value */ /* for the Literal so it can end up as an empty */ /* string query in the expression */ else psFilterNode->psRightNode->pszValue = NULL; } } if (psFilterNode->psLeftNode == NULL || psFilterNode->psRightNode == NULL) psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } /* -------------------------------------------------------------------- */ /* PropertyIsBetween filter : extract property name and boudary */ /* values. The boundary values are stored in the right */ /* node. The values are separated by a semi-column (;) */ /* Eg of Filter : */ /* */ /* DEPTH */ /* 400 */ /* 800 */ /* */ /* */ /* Or */ /* */ /* DEPTH */ /* 400 */ /* 800 */ /* */ /* -------------------------------------------------------------------- */ else if (strcasecmp(psXMLNode->pszValue, "PropertyIsBetween") == 0) { CPLXMLNode *psUpperNode = NULL, *psLowerNode = NULL; if (psXMLNode->psChild && strcasecmp(psXMLNode->psChild->pszValue, "PropertyName") == 0 && psXMLNode->psChild->psNext && strcasecmp(psXMLNode->psChild->psNext->pszValue, "LowerBoundary") == 0 && psXMLNode->psChild->psNext->psNext && strcasecmp(psXMLNode->psChild->psNext->psNext->pszValue, "UpperBoundary") == 0) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); if (psXMLNode->psChild->psChild && psXMLNode->psChild->psChild->pszValue) { psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(psXMLNode->psChild->psChild->pszValue); } psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); if (psXMLNode->psChild->psNext->psChild && psXMLNode->psChild->psNext->psNext->psChild && psXMLNode->psChild->psNext->psChild->pszValue && psXMLNode->psChild->psNext->psNext->psChild->pszValue) { /* check if the is there */ psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_BOUNDARY; if (psXMLNode->psChild->psNext->psChild->psChild) psLowerNode = psXMLNode->psChild->psNext->psChild->psChild; else psLowerNode = psXMLNode->psChild->psNext->psChild; if (psXMLNode->psChild->psNext->psNext->psChild->psChild) psUpperNode = psXMLNode->psChild->psNext->psNext->psChild->psChild; else psUpperNode = psXMLNode->psChild->psNext->psNext->psChild; nStrLength = strlen(psLowerNode->pszValue); nStrLength += strlen(psUpperNode->pszValue); nStrLength += 2; /* adding a ; between bounary values */ psFilterNode->psRightNode->pszValue = (char *)malloc(sizeof(char)*(nStrLength)); strcpy( psFilterNode->psRightNode->pszValue, psLowerNode->pszValue); strlcat(psFilterNode->psRightNode->pszValue, ";", nStrLength); strlcat(psFilterNode->psRightNode->pszValue, psUpperNode->pszValue, nStrLength); } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; }/* end of PropertyIsBetween */ /* -------------------------------------------------------------------- */ /* PropertyIsLike */ /* */ /* */ /* */ /* LAST_NAME */ /* JOHN* */ /* */ /* */ /* -------------------------------------------------------------------- */ else if (strcasecmp(psXMLNode->pszValue, "PropertyIsLike") == 0) { if (CPLSearchXMLNode(psXMLNode, "Literal") && CPLSearchXMLNode(psXMLNode, "PropertyName") && CPLGetXMLValue(psXMLNode, "wildCard", "") && CPLGetXMLValue(psXMLNode, "singleChar", "") && (CPLGetXMLValue(psXMLNode, "escape", "") || CPLGetXMLValue(psXMLNode, "escapeChar", ""))) /* psXMLNode->psChild && strcasecmp(psXMLNode->psChild->pszValue, "wildCard") == 0 && psXMLNode->psChild->psNext && strcasecmp(psXMLNode->psChild->psNext->pszValue, "singleChar") == 0 && psXMLNode->psChild->psNext->psNext && strcasecmp(psXMLNode->psChild->psNext->psNext->pszValue, "escape") == 0 && psXMLNode->psChild->psNext->psNext->psNext && strcasecmp(psXMLNode->psChild->psNext->psNext->psNext->pszValue, "PropertyName") == 0 && psXMLNode->psChild->psNext->psNext->psNext->psNext && strcasecmp(psXMLNode->psChild->psNext->psNext->psNext->psNext->pszValue, "Literal") == 0) */ { /* -------------------------------------------------------------------- */ /* Get the wildCard, the singleChar and the escapeChar used. */ /* -------------------------------------------------------------------- */ psFilterNode->pOther = (FEPropertyIsLike *)malloc(sizeof(FEPropertyIsLike)); /*default is case sensitive*/ ((FEPropertyIsLike *)psFilterNode->pOther)->bCaseInsensitive = 0; pszTmp = (char *)CPLGetXMLValue(psXMLNode, "wildCard", ""); if (pszTmp) ((FEPropertyIsLike *)psFilterNode->pOther)->pszWildCard = msStrdup(pszTmp); pszTmp = (char *)CPLGetXMLValue(psXMLNode, "singleChar", ""); if (pszTmp) ((FEPropertyIsLike *)psFilterNode->pOther)->pszSingleChar = msStrdup(pszTmp); pszTmp = (char *)CPLGetXMLValue(psXMLNode, "escape", ""); if (pszTmp && strlen(pszTmp)>0) ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar = msStrdup(pszTmp); else { pszTmp = (char *)CPLGetXMLValue(psXMLNode, "escapeChar", ""); if (pszTmp) ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar = msStrdup(pszTmp); } pszTmp = (char *)CPLGetXMLValue(psXMLNode, "matchCase", ""); if (pszTmp && strlen(pszTmp) > 0 && strcasecmp(pszTmp, "false") == 0) { ((FEPropertyIsLike *)psFilterNode->pOther)->bCaseInsensitive =1; } /* -------------------------------------------------------------------- */ /* Create left and right node for the attribute and the value. */ /* -------------------------------------------------------------------- */ psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psTmpNode = CPLSearchXMLNode(psXMLNode, "PropertyName"); if (psTmpNode && psTmpNode->psChild && psTmpNode->psChild->pszValue && strlen(psTmpNode->psChild->pszValue) > 0) { /* if (psXMLNode->psChild->psNext->psNext->psNext->psChild && psXMLNode->psChild->psNext->psNext->psNext->psChild->pszValue) { psFilterNode->psLeftNode->pszValue = msStrdup(psXMLNode->psChild->psNext->psNext->psNext->psChild->pszValue); */ psFilterNode->psLeftNode->pszValue = msStrdup(psTmpNode->psChild->pszValue); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; } psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); psTmpNode = CPLSearchXMLNode(psXMLNode, "Literal"); if (psTmpNode && psTmpNode->psChild && psTmpNode->psChild->pszValue && strlen(psTmpNode->psChild->pszValue) > 0) { /* if (psXMLNode->psChild->psNext->psNext->psNext->psNext->psChild && psXMLNode->psChild->psNext->psNext->psNext->psNext->psChild->pszValue) { psFilterNode->psRightNode->pszValue = msStrdup(psXMLNode->psChild->psNext->psNext->psNext->psNext->psChild->pszValue); */ psFilterNode->psRightNode->pszValue = msStrdup(psTmpNode->psChild->pszValue); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } } /* -------------------------------------------------------------------- */ /* FeatureId Filter */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Note that for FES1.1.0 the featureid has been depricated in */ /* favor of GmlObjectId */ /* */ /* -------------------------------------------------------------------- */ else if (FLTIsFeatureIdFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_FEATUREID; pszFeatureId = (char *)CPLGetXMLValue(psXMLNode, "fid", NULL); /*for FE 1.1.0 GmlObjectId */ if (pszFeatureId == NULL) pszFeatureId = (char *)CPLGetXMLValue(psXMLNode, "id", NULL); pszFeatureIdList = NULL; psFeatureIdNode = psXMLNode; while (psFeatureIdNode) { pszFeatureId = (char *)CPLGetXMLValue(psFeatureIdNode, "fid", NULL); if (!pszFeatureId) pszFeatureId = (char *)CPLGetXMLValue(psFeatureIdNode, "id", NULL); if (pszFeatureId) { if (pszFeatureIdList) pszFeatureIdList = msStringConcatenate(pszFeatureIdList, ","); /*typname could be part of the value : INWATERA_1M.1234*/ tokens = msStringSplit(pszFeatureId,'.', &nTokens); if (tokens && nTokens == 2) pszFeatureIdList = msStringConcatenate(pszFeatureIdList, tokens[1]); else pszFeatureIdList = msStringConcatenate(pszFeatureIdList, pszFeatureId); if (tokens) msFreeCharArray(tokens, nTokens); } psFeatureIdNode = psFeatureIdNode->psNext; } if (pszFeatureIdList) { psFilterNode->pszValue = msStrdup(pszFeatureIdList); msFree(pszFeatureIdList); } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } } } /************************************************************************/ /* int FLTIsLogicalFilterType((char *pszValue) */ /* */ /* return TRUE if the value of the node is of logical filter */ /* encoding type. */ /************************************************************************/ int FLTIsLogicalFilterType(char *pszValue) { if (pszValue) { if (strcasecmp(pszValue, "AND") == 0 || strcasecmp(pszValue, "OR") == 0 || strcasecmp(pszValue, "NOT") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsBinaryComparisonFilterType(char *pszValue) */ /* */ /* Binary comparison filter type. */ /************************************************************************/ int FLTIsBinaryComparisonFilterType(char *pszValue) { if (pszValue) { if (strcasecmp(pszValue, "PropertyIsEqualTo") == 0 || strcasecmp(pszValue, "PropertyIsNotEqualTo") == 0 || strcasecmp(pszValue, "PropertyIsLessThan") == 0 || strcasecmp(pszValue, "PropertyIsGreaterThan") == 0 || strcasecmp(pszValue, "PropertyIsLessThanOrEqualTo") == 0 || strcasecmp(pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsComparisonFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of comparison filter */ /* encoding type. */ /************************************************************************/ int FLTIsComparisonFilterType(char *pszValue) { if (pszValue) { if (FLTIsBinaryComparisonFilterType(pszValue) || strcasecmp(pszValue, "PropertyIsLike") == 0 || strcasecmp(pszValue, "PropertyIsBetween") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsFeatureIdFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of featureid filter */ /* encoding type. */ /************************************************************************/ int FLTIsFeatureIdFilterType(char *pszValue) { if (pszValue && (strcasecmp(pszValue, "FeatureId") == 0 || strcasecmp(pszValue, "GmlObjectId") == 0)) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* int FLTIsSpatialFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of spatial filter */ /* encoding type. */ /************************************************************************/ int FLTIsSpatialFilterType(char *pszValue) { if (pszValue) { if ( strcasecmp(pszValue, "BBOX") == 0 || strcasecmp(pszValue, "DWithin") == 0 || strcasecmp(pszValue, "Intersect") == 0 || strcasecmp(pszValue, "Intersects") == 0 || strcasecmp(pszValue, "Equals") == 0 || strcasecmp(pszValue, "Disjoint") == 0 || strcasecmp(pszValue, "Touches") == 0 || strcasecmp(pszValue, "Crosses") == 0 || strcasecmp(pszValue, "Within") == 0 || strcasecmp(pszValue, "Contains") == 0 || strcasecmp(pszValue, "Overlaps") == 0 || strcasecmp(pszValue, "Beyond") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsSupportedFilterType(CPLXMLNode *psXMLNode) */ /* */ /* Verfify if the value of the node is one of the supported */ /* filter type. */ /************************************************************************/ int FLTIsSupportedFilterType(CPLXMLNode *psXMLNode) { if (psXMLNode) { if (FLTIsLogicalFilterType(psXMLNode->pszValue) || FLTIsSpatialFilterType(psXMLNode->pszValue) || FLTIsComparisonFilterType(psXMLNode->pszValue) || FLTIsFeatureIdFilterType(psXMLNode->pszValue)) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* FLTNumberOfFilterType */ /* */ /* Loop trhough the nodes and return the number of nodes of */ /* specified value. */ /************************************************************************/ int FLTNumberOfFilterType(FilterEncodingNode *psFilterNode, const char *szType) { int nCount = 0; int nLeftNode=0 , nRightNode = 0; if (!psFilterNode || !szType || !psFilterNode->pszValue) return 0; if (strcasecmp(psFilterNode->pszValue, (char*)szType) == 0) nCount++; if (psFilterNode->psLeftNode) nLeftNode = FLTNumberOfFilterType(psFilterNode->psLeftNode, szType); nCount += nLeftNode; if (psFilterNode->psRightNode) nRightNode = FLTNumberOfFilterType(psFilterNode->psRightNode, szType); nCount += nRightNode; return nCount; } /************************************************************************/ /* FLTValidForBBoxFilter */ /* */ /* Validate if there is only one BBOX filter node. Here is waht */ /* is supported (is valid) : */ /* - one node which is a BBOX */ /* - a logical AND with a valid BBOX */ /* */ /* eg 1: */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 35.5472,42.8143*/ /* */ /* */ /* */ /* */ /* eg 2 : */ /* */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 35.5472,42.8143*/ /* */ /* */ /* */ /* SomeProperty */ /* 100 */ /* */ /* */ /* */ /* */ /************************************************************************/ int FLTValidForBBoxFilter(FilterEncodingNode *psFilterNode) { int nCount = 0; if (!psFilterNode || !psFilterNode->pszValue) return 1; nCount = FLTNumberOfFilterType(psFilterNode, "BBOX"); if (nCount > 1) return 0; else if (nCount == 0) return 1; /* nCount ==1 */ if (strcasecmp(psFilterNode->pszValue, "BBOX") == 0) return 1; if (strcasecmp(psFilterNode->pszValue, "AND") == 0) { if (strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") ==0 || strcasecmp(psFilterNode->psRightNode->pszValue, "BBOX") ==0) return 1; } return 0; } int FLTIsLineFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_GEOMETRY_LINE) return 1; return 0; } int FLTIsPolygonFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_GEOMETRY_POLYGON) return 1; return 0; } int FLTIsPointFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_GEOMETRY_POINT) return 1; return 0; } int FLTIsBBoxFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (strcasecmp(psFilterNode->pszValue, "BBOX") == 0) return 1; /* if (strcasecmp(psFilterNode->pszValue, "AND") == 0) { if (strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") ==0 || strcasecmp(psFilterNode->psRightNode->pszValue, "BBOX") ==0) return 1; } */ return 0; } shapeObj *FLTGetShape(FilterEncodingNode *psFilterNode, double *pdfDistance, int *pnUnit) { char **tokens = NULL; int nTokens = 0; FilterEncodingNode *psNode = psFilterNode; char *szUnitStr = NULL; char *szUnit = NULL; if (psNode) { if (psNode->eType == FILTER_NODE_TYPE_SPATIAL && psNode->psRightNode) psNode = psNode->psRightNode; if (psNode->eType == FILTER_NODE_TYPE_GEOMETRY_POINT || psNode->eType == FILTER_NODE_TYPE_GEOMETRY_LINE || psNode->eType == FILTER_NODE_TYPE_GEOMETRY_POLYGON) { if (psNode->pszValue && pdfDistance) { /* sytnax expected is "distance;unit" or just "distance" if unit is there syntax is "URI#unit" (eg http://..../#m) or just "unit" */ tokens = msStringSplit(psNode->pszValue,';', &nTokens); if (tokens && nTokens >= 1) { *pdfDistance = atof(tokens[0]); if (nTokens == 2 && pnUnit) { szUnitStr = msStrdup(tokens[1]); msFreeCharArray(tokens, nTokens); nTokens = 0; tokens = msStringSplit(szUnitStr,'#', &nTokens); msFree(szUnitStr); if (tokens && nTokens >= 1) { if (nTokens ==1) szUnit = tokens[0]; else szUnit = tokens[1]; if (strcasecmp(szUnit,"m") == 0 || strcasecmp(szUnit,"meters") == 0 ) *pnUnit = MS_METERS; else if (strcasecmp(szUnit,"km") == 0 || strcasecmp(szUnit,"kilometers") == 0) *pnUnit = MS_KILOMETERS; else if (strcasecmp(szUnit,"NM") == 0 || strcasecmp(szUnit,"nauticalmiles") == 0) *pnUnit = MS_NAUTICALMILES; else if (strcasecmp(szUnit,"mi") == 0 || strcasecmp(szUnit,"miles") == 0) *pnUnit = MS_MILES; else if (strcasecmp(szUnit,"in") == 0 || strcasecmp(szUnit,"inches") == 0) *pnUnit = MS_INCHES; else if (strcasecmp(szUnit,"ft") == 0 || strcasecmp(szUnit,"feet") == 0) *pnUnit = MS_FEET; else if (strcasecmp(szUnit,"deg") == 0 || strcasecmp(szUnit,"dd") == 0) *pnUnit = MS_DD; else if (strcasecmp(szUnit,"px") == 0) *pnUnit = MS_PIXELS; msFreeCharArray(tokens, nTokens); } } } } return (shapeObj *)psNode->pOther; } } return NULL; } /************************************************************************/ /* FLTGetBBOX */ /* */ /* Loop through the nodes are return the coordinates of the */ /* first bbox node found. The retrun value is the epsg code of */ /* the bbox. */ /************************************************************************/ char *FLTGetBBOX(FilterEncodingNode *psFilterNode, rectObj *psRect) { char *pszReturn = NULL; if (!psFilterNode || !psRect) return NULL; if (psFilterNode->pszValue && strcasecmp(psFilterNode->pszValue, "BBOX") == 0) { if (psFilterNode->psRightNode && psFilterNode->psRightNode->pOther) { psRect->minx = ((rectObj *)psFilterNode->psRightNode->pOther)->minx; psRect->miny = ((rectObj *)psFilterNode->psRightNode->pOther)->miny; psRect->maxx = ((rectObj *)psFilterNode->psRightNode->pOther)->maxx; psRect->maxy = ((rectObj *)psFilterNode->psRightNode->pOther)->maxy; return psFilterNode->psRightNode->pszValue; } } else { pszReturn = FLTGetBBOX(psFilterNode->psLeftNode, psRect); if (pszReturn) return pszReturn; else return FLTGetBBOX(psFilterNode->psRightNode, psRect); } return pszReturn; } /************************************************************************/ /* GetMapserverExpression */ /* */ /* Return a mapserver expression base on the Filer encoding nodes. */ /************************************************************************/ char *FLTGetMapserverExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; const char *pszAttribute = NULL; char szTmp[256]; char **tokens = NULL; int nTokens = 0, i=0,bString=0; char *pszTmp; if (!psFilterNode) return NULL; if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON) { if ( psFilterNode->psLeftNode && psFilterNode->psRightNode) { if (FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) { pszExpression = FLTGetBinaryComparisonExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0) { pszExpression = FLTGetIsBetweenComparisonExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) { pszExpression = FLTGetIsLikeComparisonExpression(psFilterNode); } } } else if (psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL) { if (strcasecmp(psFilterNode->pszValue, "AND") == 0 || strcasecmp(psFilterNode->pszValue, "OR") == 0) { pszExpression = FLTGetLogicalComparisonExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszExpression = FLTGetLogicalComparisonExpresssion(psFilterNode, lp); } } else if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL) { /* TODO */ } else if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode->pszValue) { pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if (pszAttribute) { tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); if (tokens && nTokens > 0) { for (i=0; ieType == FILTER_NODE_TYPE_COMPARISON) { if ( psFilterNode->psLeftNode && psFilterNode->psRightNode) { if (FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) { pszExpression = FLTGetBinaryComparisonSQLExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0) { pszExpression = FLTGetIsBetweenComparisonSQLExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) { pszExpression = FLTGetIsLikeComparisonSQLExpression(psFilterNode, lp); } } } else if (psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL) { if (strcasecmp(psFilterNode->pszValue, "AND") == 0 || strcasecmp(psFilterNode->pszValue, "OR") == 0) { pszExpression = FLTGetLogicalComparisonSQLExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszExpression = FLTGetLogicalComparisonSQLExpresssion(psFilterNode, lp); } } else if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL) { /* TODO */ } else if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode->pszValue) { pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if (pszAttribute) { tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); bString = 0; if (tokens && nTokens > 0) { for (i=0; ipszValue)) pszExpression = FLTGetLogicalComparisonExpresssion(psFilterNode, lp); else if (FLTIsComparisonFilterType(psFilterNode->pszValue)) { if (FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) pszExpression = FLTGetBinaryComparisonExpresssion(psFilterNode, lp); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0) pszExpression = FLTGetIsBetweenComparisonExpresssion(psFilterNode, lp); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) pszExpression = FLTGetIsLikeComparisonExpression(psFilterNode); } return pszExpression; } /************************************************************************/ /* FLTGetLogicalComparisonSQLExpresssion */ /* */ /* Return the expression for logical comparison expression. */ /************************************************************************/ char *FLTGetLogicalComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszBuffer = NULL; char *pszTmp = NULL; int nTmp = 0; if (lp == NULL) return NULL; /* ==================================================================== */ /* special case for BBOX node. */ /* ==================================================================== */ if (psFilterNode->psLeftNode && psFilterNode->psRightNode && ((strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") == 0) || (strcasecmp(psFilterNode->psRightNode->pszValue, "BBOX") == 0))) { if (strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") != 0) pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); else pszTmp = FLTGetSQLExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 1)); sprintf(pszBuffer, "%s", pszTmp); } /* -------------------------------------------------------------------- */ /* OR and AND */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && psFilterNode->psRightNode) { pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + strlen(psFilterNode->pszValue) + 5)); pszBuffer[0] = '\0'; strcat(pszBuffer, " ("); strcat(pszBuffer, pszTmp); strcat(pszBuffer, " "); strcat(pszBuffer, psFilterNode->pszValue); strcat(pszBuffer, " "); free( pszTmp ); nTmp = strlen(pszBuffer); pszTmp = FLTGetSQLExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)realloc(pszBuffer, sizeof(char) * (strlen(pszTmp) + nTmp +3)); strcat(pszBuffer, pszTmp); strcat(pszBuffer, ") "); } /* -------------------------------------------------------------------- */ /* NOT */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 9)); pszBuffer[0] = '\0'; strcat(pszBuffer, " (NOT "); strcat(pszBuffer, pszTmp); strcat(pszBuffer, ") "); } else return NULL; /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ if( pszTmp != NULL ) free( pszTmp ); return pszBuffer; } /************************************************************************/ /* FLTGetLogicalComparisonExpresssion */ /* */ /* Return the expression for logical comparison expression. */ /************************************************************************/ char *FLTGetLogicalComparisonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszTmp = NULL; char *pszBuffer = NULL; int nTmp = 0; if (!psFilterNode || !FLTIsLogicalFilterType(psFilterNode->pszValue)) return NULL; /* ==================================================================== */ /* special case for BBOX node. */ /* ==================================================================== */ if (psFilterNode->psLeftNode && psFilterNode->psRightNode && (strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") == 0 || strcasecmp(psFilterNode->psRightNode->pszValue, "BBOX") == 0 || FLTIsGeosNode(psFilterNode->psLeftNode->pszValue) || FLTIsGeosNode(psFilterNode->psRightNode->pszValue))) { /*strcat(szBuffer, " (");*/ if (strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") != 0 && strcasecmp(psFilterNode->psLeftNode->pszValue, "DWithin") != 0 && FLTIsGeosNode(psFilterNode->psLeftNode->pszValue) == MS_FALSE) pszTmp = FLTGetNodeExpression(psFilterNode->psLeftNode, lp); else pszTmp = FLTGetNodeExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 3)); pszBuffer[0] = '\0'; /* if (strcasecmp(psFilterNode->psLeftNode->pszValue, "PropertyIsLike") == 0 || strcasecmp(psFilterNode->psRightNode->pszValue, "PropertyIsLike") == 0) sprintf(pszBuffer, "%s", pszTmp); else */ sprintf(pszBuffer, "(%s)", pszTmp); free(pszTmp); return pszBuffer; } /* -------------------------------------------------------------------- */ /* OR and AND */ /* -------------------------------------------------------------------- */ if (psFilterNode->psLeftNode && psFilterNode->psRightNode) { pszTmp = FLTGetNodeExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + strlen(psFilterNode->pszValue) + 5)); pszBuffer[0] = '\0'; strcat(pszBuffer, " ("); strcat(pszBuffer, pszTmp); strcat(pszBuffer, " "); strcat(pszBuffer, psFilterNode->pszValue); strcat(pszBuffer, " "); free(pszTmp); pszTmp = FLTGetNodeExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; nTmp = strlen(pszBuffer); pszBuffer = (char *)realloc(pszBuffer, sizeof(char) * (strlen(pszTmp) + nTmp +3)); strcat(pszBuffer, pszTmp); strcat(pszBuffer, ") "); free(pszTmp); } /* -------------------------------------------------------------------- */ /* NOT */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszTmp = FLTGetNodeExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 9)); pszBuffer[0] = '\0'; strcat(pszBuffer, " (NOT "); strcat(pszBuffer, pszTmp); strcat(pszBuffer, ") "); free(pszTmp); } else return NULL; return pszBuffer; } /************************************************************************/ /* FLTGetBinaryComparisonExpresssion */ /* */ /* Return the expression for a binary comparison filter node. */ /************************************************************************/ char *FLTGetBinaryComparisonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; int bString=0; char szTmp[256]; szBuffer[0] = '\0'; if (!psFilterNode || !FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) return NULL; /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (psFilterNode->psRightNode->pszValue) { const char* pszOFGType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszOFGType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszOFGType!= NULL && strcasecmp(pszOFGType, "Character") == 0) bString = 1; else if (FLTIsNumeric(psFilterNode->psRightNode->pszValue) == MS_FALSE) bString = 1; } /* specical case to be able to have empty strings in the expression. */ if (psFilterNode->psRightNode->pszValue == NULL) bString = 1; if (bString) strlcat(szBuffer, " (\"[", bufferSize); else strlcat(szBuffer, " ([", bufferSize); /* attribute */ strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize); if (bString) strlcat(szBuffer, "]\" ", bufferSize); else strlcat(szBuffer, "] ", bufferSize); /* logical operator */ if (strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0) { /*case insensitive set ? */ if (psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) { strlcat(szBuffer, "IEQ", bufferSize); } else strlcat(szBuffer, "=", bufferSize); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0) strlcat(szBuffer, "!=", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0) strlcat(szBuffer, "<", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0) strlcat(szBuffer, ">", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0) strlcat(szBuffer, "<=", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) strlcat(szBuffer, ">=", bufferSize); strlcat(szBuffer, " ", bufferSize); /* value */ if (bString) strlcat(szBuffer, "\"", bufferSize); if (psFilterNode->psRightNode->pszValue) strlcat(szBuffer, psFilterNode->psRightNode->pszValue, bufferSize); if (bString) strlcat(szBuffer, "\"", bufferSize); strlcat(szBuffer, ") ", bufferSize); return msStrdup(szBuffer); } /************************************************************************/ /* FLTGetBinaryComparisonSQLExpresssion */ /* */ /* Return the expression for a binary comparison filter node. */ /************************************************************************/ char *FLTGetBinaryComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; int bString=0; char szTmp[256]; char* pszEscapedStr = NULL; szBuffer[0] = '\0'; if (!psFilterNode || ! FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) return NULL; /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (psFilterNode->psRightNode->pszValue) { const char* pszOFGType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszOFGType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszOFGType!= NULL && strcasecmp(pszOFGType, "Character") == 0) bString = 1; else if (FLTIsNumeric(psFilterNode->psRightNode->pszValue) == MS_FALSE) bString = 1; } /* specical case to be able to have empty strings in the expression. */ if (psFilterNode->psRightNode->pszValue == NULL) bString = 1; /*opening bracket*/ strlcat(szBuffer, " (", bufferSize); pszEscapedStr = msLayerEscapePropertyName(lp, psFilterNode->psLeftNode->pszValue); /* attribute */ /*case insensitive set ? */ if (bString && strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0 && psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) { snprintf(szTmp, sizeof(szTmp), "lower(%s) ", pszEscapedStr); strlcat(szBuffer, szTmp, bufferSize); } else strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr = NULL; /* logical operator */ if (strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0) strlcat(szBuffer, "=", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0) strlcat(szBuffer, "<>", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0) strlcat(szBuffer, "<", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0) strlcat(szBuffer, ">", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0) strlcat(szBuffer, "<=", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) strlcat(szBuffer, ">=", bufferSize); strlcat(szBuffer, " ", bufferSize); /* value */ if (bString && psFilterNode->psRightNode->pszValue && strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0 && psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) { char* pszEscapedStr; pszEscapedStr = msLayerEscapeSQLParam(lp, psFilterNode->psRightNode->pszValue); snprintf(szTmp, sizeof(szTmp), "lower('%s') ", pszEscapedStr); msFree(pszEscapedStr); strlcat(szBuffer, szTmp, bufferSize); } else { if (bString) strlcat(szBuffer, "'", bufferSize); if (psFilterNode->psRightNode->pszValue) { if (bString) { char* pszEscapedStr; pszEscapedStr = msLayerEscapeSQLParam(lp, psFilterNode->psRightNode->pszValue); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr=NULL; } else strlcat(szBuffer, psFilterNode->psRightNode->pszValue, bufferSize); } if (bString) strlcat(szBuffer, "'", bufferSize); } /*closing bracket*/ strlcat(szBuffer, ") ", bufferSize); return msStrdup(szBuffer); } /************************************************************************/ /* FLTGetIsBetweenComparisonSQLExpresssion */ /* */ /* Build an SQL expresssion for IsBteween Filter. */ /************************************************************************/ char *FLTGetIsBetweenComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; char **aszBounds = NULL; int nBounds = 0; int bString=0; char szTmp[256]; char* pszEscapedStr; szBuffer[0] = '\0'; if (!psFilterNode || !(strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0)) return NULL; if (!psFilterNode->psLeftNode || !psFilterNode->psRightNode ) return NULL; /* -------------------------------------------------------------------- */ /* Get the bounds value which are stored like boundmin;boundmax */ /* -------------------------------------------------------------------- */ aszBounds = msStringSplit(psFilterNode->psRightNode->pszValue, ';', &nBounds); if (nBounds != 2) return NULL; /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (aszBounds[0]) { const char* pszOFGType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszOFGType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszOFGType!= NULL && strcasecmp(pszOFGType, "Character") == 0) bString = 1; else if (FLTIsNumeric(aszBounds[0]) == MS_FALSE) bString = 1; } if (!bString) { if (aszBounds[1]) { if (FLTIsNumeric(aszBounds[1]) == MS_FALSE) bString = 1; } } /* -------------------------------------------------------------------- */ /* build expresssion. */ /* -------------------------------------------------------------------- */ /*opening paranthesis */ strlcat(szBuffer, " (", bufferSize); /* attribute */ pszEscapedStr = msLayerEscapePropertyName(lp, psFilterNode->psLeftNode->pszValue); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr = NULL; /*between*/ strlcat(szBuffer, " BETWEEN ", bufferSize); /*bound 1*/ if (bString) strlcat(szBuffer,"'", bufferSize); pszEscapedStr = msLayerEscapeSQLParam( lp, aszBounds[0]); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr=NULL; if (bString) strlcat(szBuffer,"'", bufferSize); strlcat(szBuffer, " AND ", bufferSize); /*bound 2*/ if (bString) strlcat(szBuffer, "'", bufferSize); pszEscapedStr = msLayerEscapeSQLParam( lp, aszBounds[1]); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr=NULL; if (bString) strlcat(szBuffer,"'", bufferSize); /*closing paranthesis*/ strlcat(szBuffer, ")", bufferSize); return msStrdup(szBuffer); } /************************************************************************/ /* FLTGetIsBetweenComparisonExpresssion */ /* */ /* Build expresssion for IsBteween Filter. */ /************************************************************************/ char *FLTGetIsBetweenComparisonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; char **aszBounds = NULL; int nBounds = 0; int bString=0; char szTmp[256]; szBuffer[0] = '\0'; if (!psFilterNode || !(strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0)) return NULL; if (!psFilterNode->psLeftNode || !psFilterNode->psRightNode ) return NULL; /* -------------------------------------------------------------------- */ /* Get the bounds value which are stored like boundmin;boundmax */ /* -------------------------------------------------------------------- */ aszBounds = msStringSplit(psFilterNode->psRightNode->pszValue, ';', &nBounds); if (nBounds != 2) { msFreeCharArray(aszBounds, nBounds); return NULL; } /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (aszBounds[0]) { const char* pszOFGType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszOFGType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszOFGType!= NULL && strcasecmp(pszOFGType, "Character") == 0) bString = 1; else if (FLTIsNumeric(aszBounds[0]) == MS_FALSE) bString = 1; } if (!bString) { if (aszBounds[1]) { if (FLTIsNumeric(aszBounds[1]) == MS_FALSE) bString = 1; } } /* -------------------------------------------------------------------- */ /* build expresssion. */ /* -------------------------------------------------------------------- */ if (bString) strlcat(szBuffer, " (\"[", bufferSize); else strlcat(szBuffer, " ([", bufferSize); /* attribute */ strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize); if (bString) strlcat(szBuffer, "]\" ", bufferSize); else strlcat(szBuffer, "] ", bufferSize); strlcat(szBuffer, " >= ", bufferSize); if (bString) strlcat(szBuffer,"\"", bufferSize); strlcat(szBuffer, aszBounds[0], bufferSize); if (bString) strlcat(szBuffer,"\"", bufferSize); strlcat(szBuffer, " AND ", bufferSize); if (bString) strlcat(szBuffer, " \"[", bufferSize); else strlcat(szBuffer, " [", bufferSize); /* attribute */ strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize); if (bString) strlcat(szBuffer, "]\" ", bufferSize); else strlcat(szBuffer, "] ", bufferSize); strlcat(szBuffer, " <= ", bufferSize); if (bString) strlcat(szBuffer,"\"", bufferSize); strlcat(szBuffer, aszBounds[1], bufferSize); if (bString) strlcat(szBuffer,"\"", bufferSize); strlcat(szBuffer, ")", bufferSize); msFreeCharArray(aszBounds, nBounds); return msStrdup(szBuffer); } /************************************************************************/ /* FLTGetIsLikeComparisonExpression */ /* */ /* Build expression for IsLike filter. */ /************************************************************************/ char *FLTGetIsLikeComparisonExpression(FilterEncodingNode *psFilterNode) { const size_t bufferSize = 1024; char szBuffer[1024]; char szTmp[256]; char *pszValue = NULL; char *pszWild = NULL; char *pszSingle = NULL; char *pszEscape = NULL; int bCaseInsensitive = 0; int nLength=0, i=0, iTmp=0; if (!psFilterNode || !psFilterNode->pOther || !psFilterNode->psLeftNode || !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue) return NULL; pszWild = ((FEPropertyIsLike *)psFilterNode->pOther)->pszWildCard; pszSingle = ((FEPropertyIsLike *)psFilterNode->pOther)->pszSingleChar; pszEscape = ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar; bCaseInsensitive = ((FEPropertyIsLike *)psFilterNode->pOther)->bCaseInsensitive; if (!pszWild || strlen(pszWild) == 0 || !pszSingle || strlen(pszSingle) == 0 || !pszEscape || strlen(pszEscape) == 0) return NULL; /* -------------------------------------------------------------------- */ /* Use operand with regular expressions. */ /* -------------------------------------------------------------------- */ szBuffer[0] = '\0'; sprintf(szTmp, "%s", " (\"["); szTmp[4] = '\0'; strlcat(szBuffer, szTmp, bufferSize); /* attribute */ strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize); szBuffer[strlen(szBuffer)] = '\0'; /*#3521 */ if(bCaseInsensitive == 1) sprintf(szTmp, "%s", "]\" ~* /"); else sprintf(szTmp, "%s", "]\" =~ /"); szTmp[7] = '\0'; strlcat(szBuffer, szTmp, bufferSize); szBuffer[strlen(szBuffer)] = '\0'; pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); iTmp =0; if (nLength > 0 && pszValue[0] != pszWild[0] && pszValue[0] != pszSingle[0] && pszValue[0] != pszEscape[0]) { szTmp[iTmp]= '^'; iTmp++; } for (i=0; ipOther || !psFilterNode->psLeftNode || !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue) return NULL; pszWild = ((FEPropertyIsLike *)psFilterNode->pOther)->pszWildCard; pszSingle = ((FEPropertyIsLike *)psFilterNode->pOther)->pszSingleChar; pszEscape = ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar; bCaseInsensitive = ((FEPropertyIsLike *)psFilterNode->pOther)->bCaseInsensitive; if (!pszWild || strlen(pszWild) == 0 || !pszSingle || strlen(pszSingle) == 0 || !pszEscape || strlen(pszEscape) == 0) return NULL; if (pszEscape[0] == '\'') { /* This might be valid, but the risk of SQL injection is too high */ /* and the below code is not ready for that */ /* Someone who does this has clearly suspect intentions ! */ msSetError(MS_MISCERR, "Single quote character is not allowed as an escaping character.", "FLTGetIsLikeComparisonSQLExpression()"); return NULL; } szBuffer[0] = '\0'; /*opening bracket*/ strlcat(szBuffer, " (", bufferSize); /* attribute name */ pszEscapedStr = msLayerEscapePropertyName(lp, psFilterNode->psLeftNode->pszValue); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr = NULL; if (lp->connectiontype == MS_POSTGIS) { if (bCaseInsensitive == 1) strlcat(szBuffer, "::text ilike '", bufferSize); else strlcat(szBuffer, "::text like '", bufferSize); } else strlcat(szBuffer, " like '", bufferSize); pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); pszEscapedStr = (char*) msSmallMalloc( 3 * nLength + 1); for (i=0, j=0; iconnectiontype != MS_OGR) { strlcat(szBuffer, " escape '", bufferSize); szTmp[0] = pszEscape[0]; if (pszEscape[0] == '\\') { szTmp[1] = '\\'; szTmp[2] = '\''; szTmp[3] = '\0'; } else { szTmp[1] = '\''; szTmp[2] = '\0'; } strlcat(szBuffer, szTmp, bufferSize); } strlcat(szBuffer, ") ", bufferSize); return msStrdup(szBuffer); } /************************************************************************/ /* FLTHasSpatialFilter */ /* */ /* Utility function to see if a spatial filter is included in */ /* the node. */ /************************************************************************/ int FLTHasSpatialFilter(FilterEncodingNode *psNode) { int bResult = MS_FALSE; if (!psNode) return MS_FALSE; if (psNode->eType == FILTER_NODE_TYPE_LOGICAL) { if (psNode->psLeftNode) bResult = FLTHasSpatialFilter(psNode->psLeftNode); if (bResult) return MS_TRUE; if (psNode->psRightNode) bResult = FLTHasSpatialFilter(psNode->psRightNode); if (bResult) return MS_TRUE; } else if (FLTIsBBoxFilter(psNode) || FLTIsPointFilter(psNode) || FLTIsLineFilter(psNode) || FLTIsPolygonFilter(psNode)) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* FLTCreateFeatureIdFilterEncoding */ /* */ /* Utility function to create a filter node of FeatureId type. */ /************************************************************************/ FilterEncodingNode *FLTCreateFeatureIdFilterEncoding(char *pszString) { FilterEncodingNode *psFilterNode = NULL; char **tokens = NULL; int nTokens = 0; if (pszString) { psFilterNode = FLTCreateFilterEncodingNode(); psFilterNode->eType = FILTER_NODE_TYPE_FEATUREID; /*split if tyname is included in the string*/ tokens = msStringSplit(pszString,'.', &nTokens); if (tokens && nTokens == 2) psFilterNode->pszValue = msStrdup(tokens[1]); else psFilterNode->pszValue = msStrdup(pszString); if (tokens) msFreeCharArray(tokens, nTokens); return psFilterNode; } return NULL; } /************************************************************************/ /* FLTParseGMLBox */ /* */ /* Parse gml box. Used for FE 1.0 */ /************************************************************************/ int FLTParseGMLBox(CPLXMLNode *psBox, rectObj *psBbox, char **ppszSRS) { int bCoordinatesValid = 0; CPLXMLNode *psCoordinates = NULL, *psCoordChild=NULL; CPLXMLNode *psCoord1 = NULL, *psCoord2 = NULL; CPLXMLNode *psX = NULL, *psY = NULL; char **papszCoords=NULL, **papszMin=NULL, **papszMax = NULL; int nCoords = 0, nCoordsMin = 0, nCoordsMax = 0; char *pszTmpCoord = NULL; const char *pszSRS = NULL; const char *pszTS = NULL; const char *pszCS = NULL; double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0; if (psBox) { pszSRS = CPLGetXMLValue(psBox, "srsName", NULL); if (ppszSRS && pszSRS) *ppszSRS = msStrdup(pszSRS); psCoordinates = CPLGetXMLNode(psBox, "coordinates"); if (!psCoordinates) return 0; pszTS = CPLGetXMLValue(psCoordinates, "ts", NULL); pszCS = CPLGetXMLValue(psCoordinates, "cs", NULL); psCoordChild = psCoordinates->psChild; while (psCoordinates && psCoordChild && psCoordChild->eType != CXT_Text) { psCoordChild = psCoordChild->psNext; } if (psCoordChild && psCoordChild->pszValue) { pszTmpCoord = psCoordChild->pszValue; if (pszTS) papszCoords = msStringSplit(pszTmpCoord, pszTS[0], &nCoords); else papszCoords = msStringSplit(pszTmpCoord, ' ', &nCoords); if (papszCoords && nCoords == 2) { if (pszCS) papszMin = msStringSplit(papszCoords[0], pszCS[0], &nCoordsMin); else papszMin = msStringSplit(papszCoords[0], ',', &nCoordsMin); if (papszMin && nCoordsMin == 2) { if (pszCS) papszMax = msStringSplit(papszCoords[1], pszCS[0], &nCoordsMax); else papszMax = msStringSplit(papszCoords[1], ',', &nCoordsMax); } if (papszMax && nCoordsMax == 2) { bCoordinatesValid =1; minx = atof(papszMin[0]); miny = atof(papszMin[1]); maxx = atof(papszMax[0]); maxy = atof(papszMax[1]); } msFreeCharArray(papszMin, nCoordsMin); msFreeCharArray(papszMax, nCoordsMax); } msFreeCharArray(papszCoords, nCoords); } else { psCoord1 = CPLGetXMLNode(psBox, "coord"); if (psCoord1 && psCoord1->psNext && psCoord1->psNext->pszValue && strcmp(psCoord1->psNext->pszValue, "coord") ==0) { psCoord2 = psCoord1->psNext; psX = CPLGetXMLNode(psCoord1, "X"); psY = CPLGetXMLNode(psCoord1, "Y"); if (psX && psY && psX->psChild && psY->psChild && psX->psChild->pszValue && psY->psChild->pszValue) { minx = atof(psX->psChild->pszValue); miny = atof(psY->psChild->pszValue); psX = CPLGetXMLNode(psCoord2, "X"); psY = CPLGetXMLNode(psCoord2, "Y"); if (psX && psY && psX->psChild && psY->psChild && psX->psChild->pszValue && psY->psChild->pszValue) { maxx = atof(psX->psChild->pszValue); maxy = atof(psY->psChild->pszValue); bCoordinatesValid = 1; } } } } } if (bCoordinatesValid) { psBbox->minx = minx; psBbox->miny = miny; psBbox->maxx = maxx; psBbox->maxy = maxy; } return bCoordinatesValid; } /************************************************************************/ /* FLTParseGMLEnvelope */ /* */ /* Utility function to parse a gml:Enevelop (used for SOS and FE1.1)*/ /************************************************************************/ int FLTParseGMLEnvelope(CPLXMLNode *psRoot, rectObj *psBbox, char **ppszSRS) { CPLXMLNode *psChild=NULL; CPLXMLNode *psUpperCorner=NULL, *psLowerCorner=NULL; char *pszLowerCorner=NULL, *pszUpperCorner=NULL; int bValid = 0; char **tokens; int n; if (psRoot && psBbox && psRoot->eType == CXT_Element && EQUAL(psRoot->pszValue,"Envelope")) { /*Get the srs if available*/ if (ppszSRS) { psChild = psRoot->psChild; while (psChild != NULL) { if (psChild->eType == CXT_Attribute && psChild->pszValue && EQUAL(psChild->pszValue, "srsName") && psChild->psChild && psChild->psChild->pszValue) { *ppszSRS = msStrdup(psChild->psChild->pszValue); break; } psChild = psChild->psNext; } } psLowerCorner = CPLSearchXMLNode(psRoot, "lowerCorner"); psUpperCorner = CPLSearchXMLNode(psRoot, "upperCorner"); if (psLowerCorner && psUpperCorner && EQUAL(psLowerCorner->pszValue,"lowerCorner") && EQUAL(psUpperCorner->pszValue,"upperCorner")) { /*get the values*/ psChild = psLowerCorner->psChild; while (psChild != NULL) { if (psChild->eType != CXT_Text) psChild = psChild->psNext; else break; } if (psChild && psChild->eType == CXT_Text) pszLowerCorner = psChild->pszValue; psChild = psUpperCorner->psChild; while (psChild != NULL) { if (psChild->eType != CXT_Text) psChild = psChild->psNext; else break; } if (psChild && psChild->eType == CXT_Text) pszUpperCorner = psChild->pszValue; if (pszLowerCorner && pszUpperCorner) { tokens = msStringSplit(pszLowerCorner, ' ', &n); if (tokens && n >= 2) { psBbox->minx = atof(tokens[0]); psBbox->miny = atof(tokens[1]); msFreeCharArray(tokens, n); tokens = msStringSplit(pszUpperCorner, ' ', &n); if (tokens && n >= 2) { psBbox->maxx = atof(tokens[0]); psBbox->maxy = atof(tokens[1]); msFreeCharArray(tokens, n); bValid = 1; } } } } } if (bValid && ppszSRS && *ppszSRS) { projectionObj sProjTmp; msInitProjection(&sProjTmp); if (msLoadProjectionStringEPSG(&sProjTmp, *ppszSRS) == 0) { msAxisNormalizePoints( &sProjTmp, 1, &psBbox->minx, &psBbox->miny); msAxisNormalizePoints( &sProjTmp, 1, &psBbox->maxx, &psBbox->maxy); } } return bValid; } static void FLTReplacePropertyName(FilterEncodingNode *psFilterNode, const char *pszOldName, char *pszNewName) { if (psFilterNode && pszOldName && pszNewName) { if (psFilterNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { if (psFilterNode->pszValue && strcasecmp(psFilterNode->pszValue, pszOldName) == 0) { msFree(psFilterNode->pszValue); psFilterNode->pszValue = msStrdup(pszNewName); } } if (psFilterNode->psLeftNode) FLTReplacePropertyName(psFilterNode->psLeftNode, pszOldName, pszNewName); if (psFilterNode->psRightNode) FLTReplacePropertyName(psFilterNode->psRightNode, pszOldName, pszNewName); } } static void FLTStripNameSpacesFromPropertyName(FilterEncodingNode *psFilterNode) { char **tokens=NULL; int n=0; if (psFilterNode) { if (psFilterNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { if (psFilterNode->pszValue && strstr(psFilterNode->pszValue, ":")) { tokens = msStringSplit(psFilterNode->pszValue, ':', &n); if (tokens && n==2) { msFree(psFilterNode->pszValue); psFilterNode->pszValue = msStrdup(tokens[1]); } if (tokens && n>0) msFreeCharArray(tokens, n); } } if (psFilterNode->psLeftNode) FLTStripNameSpacesFromPropertyName(psFilterNode->psLeftNode); if (psFilterNode->psRightNode) FLTStripNameSpacesFromPropertyName(psFilterNode->psRightNode); } } /************************************************************************/ /* FLTPreParseFilterForAlias */ /* */ /* Utility function to replace aliased' attributes with their */ /* real name. */ /************************************************************************/ void FLTPreParseFilterForAlias(FilterEncodingNode *psFilterNode, mapObj *map, int i, const char *namespaces) { layerObj *lp=NULL; char szTmp[256]; const char *pszFullName = NULL; int layerWasOpened = MS_FALSE; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode && map && i>=0 && inumlayers) { /*strip name speces befor hand*/ FLTStripNameSpacesFromPropertyName(psFilterNode); lp = GET_LAYER(map, i); layerWasOpened = msLayerIsOpen(lp); if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { for(i=0; inumitems; i++) { if (!lp->items[i] || strlen(lp->items[i]) <= 0) continue; snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszFullName = msOWSLookupMetadata(&(lp->metadata), namespaces, szTmp); if (pszFullName) { FLTReplacePropertyName(psFilterNode, pszFullName, lp->items[i]); } } if (!layerWasOpened) /* do not close the layer if it has been opened somewhere else (paging?) */ msLayerClose(lp); } } #else msSetError(MS_MISCERR, "OWS support is not available.", "FLTPreParseFilterForAlias()"); #endif } #ifdef USE_LIBXML2 xmlNodePtr FLTGetCapabilities(xmlNsPtr psNsParent, xmlNsPtr psNsOgc, int bTemporal) { xmlNodePtr psRootNode = NULL, psNode = NULL, psSubNode = NULL, psSubSubNode = NULL; psRootNode = xmlNewNode(psNsParent, BAD_CAST "Filter_Capabilities"); psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Spatial_Capabilities", NULL); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "GeometryOperands", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:Point"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:LineString"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:Polygon"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:Envelope"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "SpatialOperators", NULL); #ifdef USE_GEOS psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Equals"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Disjoint"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Touches"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Within"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Overlaps"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Crosses"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Intersects"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Contains"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "DWithin"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Beyond"); #endif psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "BBOX"); if (bTemporal) { psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Temporal_Capabilities", NULL); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "TemporalOperands", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "TemporalOperand", BAD_CAST "gml:TimePeriod"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "TemporalOperand", BAD_CAST "gml:TimeInstant"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "TemporalOperators", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "TemporalOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "TM_Equals"); } psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Scalar_Capabilities", NULL); xmlNewChild(psNode, psNsOgc, BAD_CAST "LogicalOperators", NULL); psNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperators", NULL); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "LessThan"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "GreaterThan"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "LessThanEqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "GreaterThanEqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "EqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "NotEqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "Like"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "Between"); psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Id_Capabilities", NULL); xmlNewChild(psNode, psNsOgc, BAD_CAST "EID", NULL); xmlNewChild(psNode, psNsOgc, BAD_CAST "FID", NULL); return psRootNode; } #endif #endif mapserver-6.4.1/scalebar.c0000644002461700001440000000427212261257215015241 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Commandline scalebar generating utility, mostly for testing. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" int main(int argc, char *argv[]) { mapObj *map=NULL; imageObj *image = NULL; if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } /* ---- check the number of arguments, return syntax if not correct ---- */ if( argc < 3 ) { fprintf(stdout,"Syntax: scalebar [mapfile] [output image]\n" ); exit(1); } map = msLoadMap(argv[1], NULL); if(!map) { msWriteError(stderr); exit(1); } image = msDrawScalebar(map); if(!image) { msWriteError(stderr); exit(1); } msSaveImage(map, image, argv[2]); msFreeImage(image); msFreeMap(map); return(MS_TRUE); } mapserver-6.4.1/mapjoin.c0000644002461700001440000006007412261257215015124 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements MapServer joins. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #define ROW_ALLOCATION_SIZE 10 /* DBF/XBase function prototypes */ int msDBFJoinConnect(layerObj *layer, joinObj *join); int msDBFJoinPrepare(joinObj *join, shapeObj *shape); int msDBFJoinNext(joinObj *join); int msDBFJoinClose(joinObj *join); int msDBFJoinTable(layerObj *layer, joinObj *join, shapeObj *shape); /* CSV (comma delimited text file) function prototypes */ int msCSVJoinConnect(layerObj *layer, joinObj *join); int msCSVJoinPrepare(joinObj *join, shapeObj *shape); int msCSVJoinNext(joinObj *join); int msCSVJoinClose(joinObj *join); int msCSVJoinTable(layerObj *layer, joinObj *join, shapeObj *shape); /* MySQL function prototypes */ int msMySQLJoinConnect(layerObj *layer, joinObj *join); int msMySQLJoinPrepare(joinObj *join, shapeObj *shape); int msMySQLJoinNext(joinObj *join); int msMySQLJoinClose(joinObj *join); int msMySQLJoinTable(layerObj *layer, joinObj *join, shapeObj *shape); /* PostgreSQL function prototypes */ int msPOSTGRESQLJoinConnect(layerObj *layer, joinObj *join); int msPOSTGRESQLJoinPrepare(joinObj *join, shapeObj *shape); int msPOSTGRESQLJoinNext(joinObj *join); int msPOSTGRESQLJoinClose(joinObj *join); /* wrapper function for DB specific join functions */ int msJoinConnect(layerObj *layer, joinObj *join) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinConnect(layer, join); break; case(MS_DB_CSV): return msCSVJoinConnect(layer, join); break; case(MS_DB_MYSQL): return msMySQLJoinConnect(layer, join); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinConnect(layer, join); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinConnect()"); return MS_FAILURE; } int msJoinPrepare(joinObj *join, shapeObj *shape) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinPrepare(join, shape); break; case(MS_DB_CSV): return msCSVJoinPrepare(join, shape); break; case(MS_DB_MYSQL): return msMySQLJoinPrepare(join, shape); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinPrepare(join, shape); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinPrepare()"); return MS_FAILURE; } int msJoinNext(joinObj *join) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinNext(join); break; case(MS_DB_CSV): return msCSVJoinNext(join); break; case(MS_DB_MYSQL): return msMySQLJoinNext(join); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinNext(join); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinNext()"); return MS_FAILURE; } int msJoinClose(joinObj *join) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinClose(join); break; case(MS_DB_CSV): return msCSVJoinClose(join); break; case(MS_DB_MYSQL): return msMySQLJoinClose(join); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinClose(join); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinClose()"); return MS_FAILURE; } /* */ /* XBASE join functions */ /* */ typedef struct { DBFHandle hDBF; int fromindex, toindex; char *target; int nextrecord; } msDBFJoinInfo; int msDBFJoinConnect(layerObj *layer, joinObj *join) { int i; char szPath[MS_MAXPATHLEN]; msDBFJoinInfo *joininfo; if(join->joininfo) return(MS_SUCCESS); /* already open */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate a msDBFJoinInfo struct */ joininfo = (msDBFJoinInfo *) malloc(sizeof(msDBFJoinInfo)); if(!joininfo) { msSetError(MS_MEMERR, "Error allocating XBase table info structure.", "msDBFJoinConnect()"); return(MS_FAILURE); } /* initialize any members that won't get set later on in this function */ joininfo->target = NULL; joininfo->nextrecord = 0; join->joininfo = joininfo; /* open the XBase file */ if((joininfo->hDBF = msDBFOpen( msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, join->table), "rb" )) == NULL) { if((joininfo->hDBF = msDBFOpen( msBuildPath(szPath, layer->map->mappath, join->table), "rb" )) == NULL) { msSetError(MS_IOERR, "(%s)", "msDBFJoinConnect()", join->table); return(MS_FAILURE); } } /* get "to" item index */ if((joininfo->toindex = msDBFGetItemIndex(joininfo->hDBF, join->to)) == -1) { msSetError(MS_DBFERR, "Item %s not found in table %s.", "msDBFJoinConnect()", join->to, join->table); return(MS_FAILURE); } /* get "from" item index */ for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i],join->from) == 0) { /* found it */ joininfo->fromindex = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msDBFJoinConnect()", join->from, layer->name); return(MS_FAILURE); } /* finally store away the item names in the XBase table */ join->numitems = msDBFGetFieldCount(joininfo->hDBF); join->items = msDBFGetItems(joininfo->hDBF); if(!join->items) return(MS_FAILURE); return(MS_SUCCESS); } int msDBFJoinPrepare(joinObj *join, shapeObj *shape) { msDBFJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msDBFJoinPrepare()"); return(MS_FAILURE); } if(!shape) { msSetError(MS_JOINERR, "Shape to be joined is empty.", "msDBFJoinPrepare()"); return(MS_FAILURE); } if(!shape->values) { msSetError(MS_JOINERR, "Shape to be joined has no attributes.", "msDBFJoinPrepare()"); return(MS_FAILURE); } joininfo->nextrecord = 0; /* starting with the first record */ if(joininfo->target) free(joininfo->target); /* clear last target */ joininfo->target = msStrdup(shape->values[joininfo->fromindex]); return(MS_SUCCESS); } int msDBFJoinNext(joinObj *join) { int i, n; msDBFJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msDBFJoinNext()"); return(MS_FAILURE); } if(!joininfo->target) { msSetError(MS_JOINERR, "No target specified, run msDBFJoinPrepare() first.", "msDBFJoinNext()"); return(MS_FAILURE); } /* clear any old data */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } n = msDBFGetRecordCount(joininfo->hDBF); for(i=joininfo->nextrecord; itarget, msDBFReadStringAttribute(joininfo->hDBF, i, joininfo->toindex)) == 0) break; } if(i == n) { /* unable to do the join */ if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msDBFJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) join->values[i] = msStrdup("\0"); /* intialize to zero length strings */ joininfo->nextrecord = n; return(MS_DONE); } if((join->values = msDBFGetValues(joininfo->hDBF,i)) == NULL) return(MS_FAILURE); joininfo->nextrecord = i+1; /* so we know where to start looking next time through */ return(MS_SUCCESS); } int msDBFJoinClose(joinObj *join) { msDBFJoinInfo *joininfo = join->joininfo; if(!joininfo) return(MS_SUCCESS); /* already closed */ if(joininfo->hDBF) msDBFClose(joininfo->hDBF); if(joininfo->target) free(joininfo->target); free(joininfo); joininfo = NULL; return(MS_SUCCESS); } /* */ /* CSV (comma separated value) join functions */ /* */ typedef struct { int fromindex, toindex; char *target; char ***rows; int numrows; int nextrow; } msCSVJoinInfo; int msCSVJoinConnect(layerObj *layer, joinObj *join) { int i; FILE *stream; char szPath[MS_MAXPATHLEN]; msCSVJoinInfo *joininfo; char buffer[MS_BUFFER_LENGTH]; if(join->joininfo) return(MS_SUCCESS); /* already open */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate a msCSVJoinInfo struct */ if((joininfo = (msCSVJoinInfo *) malloc(sizeof(msCSVJoinInfo))) == NULL) { msSetError(MS_MEMERR, "Error allocating CSV table info structure.", "msCSVJoinConnect()"); return(MS_FAILURE); } /* initialize any members that won't get set later on in this function */ joininfo->target = NULL; joininfo->nextrow = 0; join->joininfo = joininfo; /* open the CSV file */ if((stream = fopen( msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, join->table), "r" )) == NULL) { if((stream = fopen( msBuildPath(szPath, layer->map->mappath, join->table), "r" )) == NULL) { msSetError(MS_IOERR, "(%s)", "msCSVJoinConnect()", join->table); return(MS_FAILURE); } } /* once through to get the number of rows */ joininfo->numrows = 0; while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) joininfo->numrows++; rewind(stream); if((joininfo->rows = (char ***) malloc(joininfo->numrows*sizeof(char **))) == NULL) { msSetError(MS_MEMERR, "Error allocating rows.", "msCSVJoinConnect()"); return(MS_FAILURE); } /* load the rows */ i = 0; while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { msStringTrimEOL(buffer); joininfo->rows[i] = msStringSplitComplex(buffer, ",", &(join->numitems), MS_ALLOWEMPTYTOKENS); i++; } fclose(stream); /* get "from" item index */ for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i],join->from) == 0) { /* found it */ joininfo->fromindex = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msCSVJoinConnect()", join->from, layer->name); return(MS_FAILURE); } /* get "to" index (for now the user tells us which column, 1..n) */ joininfo->toindex = atoi(join->to) - 1; if(joininfo->toindex < 0 || joininfo->toindex > join->numitems) { msSetError(MS_JOINERR, "Invalid column index %s.", "msCSVJoinConnect()", join->to); return(MS_FAILURE); } /* store away the column names (1..n) */ if((join->items = (char **) malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, "Error allocating space for join item names.", "msCSVJoinConnect()"); return(MS_FAILURE); } for(i=0; inumitems; i++) { join->items[i] = (char *) malloc(8); /* plenty of space */ sprintf(join->items[i], "%d", i+1); } return(MS_SUCCESS); } int msCSVJoinPrepare(joinObj *join, shapeObj *shape) { msCSVJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msCSVJoinPrepare()"); return(MS_FAILURE); } if(!shape) { msSetError(MS_JOINERR, "Shape to be joined is empty.", "msCSVJoinPrepare()"); return(MS_FAILURE); } if(!shape->values) { msSetError(MS_JOINERR, "Shape to be joined has no attributes.", "msCSVJoinPrepare()"); return(MS_FAILURE); } joininfo->nextrow = 0; /* starting with the first record */ if(joininfo->target) free(joininfo->target); /* clear last target */ joininfo->target = msStrdup(shape->values[joininfo->fromindex]); return(MS_SUCCESS); } int msCSVJoinNext(joinObj *join) { int i,j; msCSVJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msCSVJoinNext()"); return(MS_FAILURE); } /* clear any old data */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } for(i=joininfo->nextrow; inumrows; i++) { /* find a match */ if(strcmp(joininfo->target, joininfo->rows[i][joininfo->toindex]) == 0) break; } if((join->values = (char ** )malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msCSVJoinNext()"); return(MS_FAILURE); } if(i == joininfo->numrows) { /* unable to do the join */ for(j=0; jnumitems; j++) join->values[j] = msStrdup("\0"); /* intialize to zero length strings */ joininfo->nextrow = joininfo->numrows; return(MS_DONE); } for(j=0; jnumitems; j++) join->values[j] = msStrdup(joininfo->rows[i][j]); joininfo->nextrow = i+1; /* so we know where to start looking next time through */ return(MS_SUCCESS); } int msCSVJoinClose(joinObj *join) { int i; msCSVJoinInfo *joininfo = join->joininfo; if(!joininfo) return(MS_SUCCESS); /* already closed */ for(i=0; inumrows; i++) msFreeCharArray(joininfo->rows[i], join->numitems); free(joininfo->rows); if(joininfo->target) free(joininfo->target); free(joininfo); joininfo = NULL; return(MS_SUCCESS); } #ifdef USE_MYSQL #ifndef _mysql_h #include #endif char* DB_HOST = NULL; char* DB_USER = NULL; char* DB_PASSWD = NULL; char* DB_DATABASE = NULL; char* delim; #define MYDEBUG if (0) MYSQL_RES *msMySQLQuery(char *q, MYSQL *conn) { MYSQL_RES *qresult=NULL; if (mysql_query(conn,q) < 0) { mysql_close(conn); msSetError(MS_QUERYERR, "Bad mysql query (%s)", "msMySQLQuery()", q); return qresult; } if (!(qresult=mysql_store_result(conn))) { mysql_close(conn); msSetError(MS_QUERYERR, "mysql query failed (%s)", "msMySQLQuery()", q); return qresult; } return qresult; } /* */ /* mysql join functions */ /* */ typedef struct { MYSQL mysql, *conn; MYSQL_RES *qresult; MYSQL_ROW row; int rows; int fromindex; char *tocolumn; char *target; int nextrecord; } msMySQLJoinInfo; #endif int msMySQLJoinConnect(layerObj *layer, joinObj *join) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinConnect()"); return(MS_FAILURE); #else int i; char qbuf[4000]; char *conn_decrypted; msMySQLJoinInfo *joininfo; MYDEBUG if (setvbuf(stdout, NULL, _IONBF , 0)) { printf("Whoops..."); }; if(join->joininfo) return(MS_SUCCESS); /* already open */ /* allocate a msMySQLJoinInfo struct */ joininfo = (msMySQLJoinInfo *) malloc(sizeof(msMySQLJoinInfo)); if(!joininfo) { msSetError(MS_MEMERR, "Error allocating mysql table info structure.", "msMySQLJoinConnect()"); return(MS_FAILURE); } /* initialize any members that won't get set later on in this function */ joininfo->qresult = NULL; joininfo->target = NULL; joininfo->nextrecord = 0; join->joininfo = joininfo; /* open the mysql connection */ if( join->connection == NULL ) { msSetError(MS_QUERYERR, "Error parsing MYSQL JOIN: nothing specified in CONNECTION statement.", "msMySQLJoinConnect()"); return(MS_FAILURE); } conn_decrypted = msDecryptStringTokens(layer->map, join->connection); if (conn_decrypted == NULL) { msSetError(MS_QUERYERR, "Error parsing MYSQL JOIN: unable to decrypt CONNECTION statement.", "msMySQLJoinConnect()"); return(MS_FAILURE); } delim = msStrdup(":"); DB_HOST = msStrdup(strtok(conn_decrypted, delim)); DB_USER = msStrdup(strtok(NULL, delim)); DB_PASSWD = msStrdup(strtok(NULL, delim)); DB_DATABASE = msStrdup(strtok(NULL, delim)); free(conn_decrypted); if (DB_HOST == NULL || DB_USER == NULL || DB_PASSWD == NULL || DB_DATABASE == NULL) { msSetError(MS_QUERYERR, "DB param error: at least one of HOST, USER, PASSWD or DATABASE is null!", "msMySQLJoinConnect()"); return MS_FAILURE; } if (strcmp(DB_PASSWD, "none") == 0) strcpy(DB_PASSWD, ""); #if MYSQL_VERSION_ID >= 40000 mysql_init(&(joininfo->mysql)); if (!(joininfo->conn = mysql_real_connect(&(joininfo->mysql),DB_HOST,DB_USER,DB_PASSWD,NULL, 0, NULL, 0))) #else if (!(joininfo->conn = mysql_connect(&(joininfo->mysql),DB_HOST,DB_USER,DB_PASSWD))) #endif { char tmp[4000]; snprintf( tmp, sizeof(tmp), "Failed to connect to SQL server: Error: %s\nHost: %s\nUsername:%s\nPassword:%s\n", mysql_error(joininfo->conn), DB_HOST, DB_USER, DB_PASSWD); msSetError(MS_QUERYERR, "%s", "msMYSQLLayerOpen()", tmp); free(joininfo); return MS_FAILURE; } MYDEBUG printf("msMYSQLLayerOpen2 called
\n"); if (mysql_select_db(joininfo->conn,DB_DATABASE) < 0) { mysql_close(joininfo->conn); } MYDEBUG printf("msMYSQLLayerOpen3 called
\n"); if (joininfo->qresult != NULL) { /* query leftover */ MYDEBUG printf("msMYSQLLayerOpen4 called
\n"); mysql_free_result(joininfo->qresult); } MYDEBUG printf("msMYSQLLayerOpen5 called
\n"); snprintf(qbuf, sizeof(qbuf), "SELECT count(%s) FROM %s", join->to, join->table); MYDEBUG printf("%s
\n", qbuf); if ((joininfo->qresult = msMySQLQuery(qbuf, joininfo->conn))) { /* There were some rows found, write 'em out for debug */ int numrows = mysql_affected_rows(joininfo->conn); MYDEBUG printf("%d rows
\n", numrows); for(i=0; iqresult); MYDEBUG printf("(%s)
\n",row[0]); joininfo->rows = atoi(row[0]); } } else { msSetError(MS_DBFERR, "Item %s not found in table %s.", "msMySQLJoinConnect()", join->to, join->table); return(MS_FAILURE); } snprintf(qbuf, sizeof(qbuf), "EXPLAIN %s", join->table); if ((joininfo->qresult = msMySQLQuery(qbuf, joininfo->conn))) { /* There were some rows found, write 'em out for debug */ join->numitems = mysql_affected_rows(joininfo->conn); if((join->items = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinConnect()"); return(MS_FAILURE); } MYDEBUG printf("%d rows
\n", join->numitems); for(i=0; inumitems; i++) { MYSQL_ROW row = mysql_fetch_row(joininfo->qresult); MYDEBUG printf("(%s)
\n",row[0]); join->items[i] = msStrdup(row[0]); } } else { msSetError(MS_DBFERR, "Item %s not found in table %s.", "msMySQLJoinConnect()", join->to, join->table); return(MS_FAILURE); } joininfo->tocolumn = msStrdup(join->to); /* get "from" item index */ for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i],join->from) == 0) { /* found it */ joininfo->fromindex = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msMySQLJoinConnect()", join->from, layer->name); return(MS_FAILURE); } /* finally store away the item names in the XBase table */ if(!join->items) return(MS_FAILURE); return(MS_SUCCESS); #endif } int msMySQLJoinPrepare(joinObj *join, shapeObj *shape) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinPrepare()"); return(MS_FAILURE); #else msMySQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msMySQLJoinPrepare()"); return(MS_FAILURE); } if(!shape) { msSetError(MS_JOINERR, "Shape to be joined is empty.", "msMySQLJoinPrepare()"); return(MS_FAILURE); } if(!shape->values) { msSetError(MS_JOINERR, "Shape to be joined has no attributes.", "msMySQLJoinPrepare()"); return(MS_FAILURE); } joininfo->nextrecord = 0; /* starting with the first record */ if(joininfo->target) free(joininfo->target); /* clear last target */ joininfo->target = msStrdup(shape->values[joininfo->fromindex]); return(MS_SUCCESS); #endif } int msMySQLJoinNext(joinObj *join) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinNext()"); return(MS_FAILURE); #else int i, n; char qbuf[4000]; msMySQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msMySQLJoinNext()"); return(MS_FAILURE); } if(!joininfo->target) { msSetError(MS_JOINERR, "No target specified, run msMySQLJoinPrepare() first.", "msMySQLJoinNext()"); return(MS_FAILURE); } /* clear any old data */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } n = joininfo->rows; /* for(i=joininfo->nextrecord; itarget, msMySQLReadStringAttribute(joininfo->conn, i, joininfo->toindex)) == 0) break; */ /* } */ snprintf(qbuf, sizeof(qbuf), "SELECT * FROM %s WHERE %s = %s", join->table, joininfo->tocolumn, joininfo->target); MYDEBUG printf("%s
\n", qbuf); if ((joininfo->qresult = msMySQLQuery(qbuf, joininfo->conn))) { /* There were some rows found, write 'em out for debug */ int numrows = mysql_affected_rows(joininfo->conn); int numfields = mysql_field_count(joininfo->conn); MYDEBUG printf("%d rows
\n", numrows); if (numrows > 0) { MYSQL_ROW row = mysql_fetch_row(joininfo->qresult); for(i=0; i\n"); free(join->values); if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) { /* join->values[i] = msStrdup("\0"); */ /* intialize to zero length strings */ join->values[i] = msStrdup(row[i]); /* intialize to zero length strings */ /* rows = atoi(row[0]); */ } } else { if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) join->values[i] = msStrdup("\0"); /* intialize to zero length strings */ return(MS_DONE); } } else { msSetError(MS_QUERYERR, "Query error (%s)", "msMySQLJoinNext()", qbuf); return(MS_FAILURE); } #ifdef __NOTDEF__ if(i == n) { /* unable to do the join */ if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) join->values[i] = msStrdup("\0"); /* intialize to zero length strings */ joininfo->nextrecord = n; return(MS_DONE); } if((join->values = msMySQLGetValues(joininfo->conn,i)) == NULL) return(MS_FAILURE); joininfo->nextrecord = i+1; /* so we know where to start looking next time through */ #endif /* __NOTDEF__ */ return(MS_SUCCESS); #endif } int msMySQLJoinClose(joinObj *join) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinClose()"); return(MS_FAILURE); #else msMySQLJoinInfo *joininfo = join->joininfo; if(!joininfo) return(MS_SUCCESS); /* already closed */ mysql_close(joininfo->conn); if(joininfo->target) free(joininfo->target); free(joininfo); joininfo = NULL; return(MS_SUCCESS); #endif } mapserver-6.4.1/mapregex.h0000644002461700001440000000712012261257215015275 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Regex wrapper * Author: Bill Binko * ****************************************************************************** * Copyright (c) 1996-2005 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 MAP_REGEX_H #define MAP_REGEX_H #ifdef __cplusplus extern "C" { #endif /* We want these to match the POSIX standard, so we need these*/ /* === regex2.h === */ #ifdef WIN32 #define MS_API_EXPORT(type) __declspec(dllexport) type __stdcall #elif defined(__GNUC__) && __GNUC__ >= 4 #define MS_API_EXPORT(type) __attribute__ ((visibility("default"))) type #else #define MS_API_EXPORT(type) type #endif typedef struct { void* sys_regex; } ms_regex_t; typedef int ms_regoff_t; typedef struct { ms_regoff_t rm_so; /* Byte offset from string's start to substring's start. */ ms_regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } ms_regmatch_t; MS_API_EXPORT(int) ms_regcomp(ms_regex_t *, const char *, int); MS_API_EXPORT(size_t) ms_regerror(int, const ms_regex_t *, char *, size_t); MS_API_EXPORT(int) ms_regexec(const ms_regex_t *, const char *, size_t, ms_regmatch_t [], int); MS_API_EXPORT(void) ms_regfree(ms_regex_t *); #ifndef BUILDING_REGEX_PROXY /* === regcomp.c === */ #define MS_REG_BASIC 0000 #define MS_REG_EXTENDED 0001 #define MS_REG_ICASE 0002 #define MS_REG_NOSUB 0004 #define MS_REG_NEWLINE 0010 #define MS_REG_NOSPEC 0020 #define MS_REG_PEND 0040 #define MS_REG_DUMP 0200 /* === regerror.c === */ #define MS_REG_OKAY 0 #define MS_REG_NOMATCH 1 #define MS_REG_BADPAT 2 #define MS_REG_ECOLLATE 3 #define MS_REG_ECTYPE 4 #define MS_REG_EESCAPE 5 #define MS_REG_ESUBREG 6 #define MS_REG_EBRACK 7 #define MS_REG_EPAREN 8 #define MS_REG_EBRACE 9 #define MS_REG_BADBR 10 #define MS_REG_ERANGE 11 #define MS_REG_ESPACE 12 #define MS_REG_BADRPT 13 #define MS_REG_EMPTY 14 #define MS_REG_ASSERT 15 #define MS_REG_INVARG 16 #define MS_REG_ATOI 255 /* convert name to number (!) */ #define MS_REG_ITOA 0400 /* convert number to name (!) */ /* === regexec.c === */ #define MS_REG_NOTBOL 00001 #define MS_REG_NOTEOL 00002 #define MS_REG_STARTEND 00004 #define MS_REG_TRACE 00400 /* tracing of execution */ #define MS_REG_LARGE 01000 /* force large representation */ #define MS_REG_BACKR 02000 /* force use of backref code */ #endif #ifdef __cplusplus } #endif #endif mapserver-6.4.1/mapcopy.h0000644002461700001440000000671212261257215015143 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations related to copyng mapObjs. Provided by Mladen Turk * for resolution of bug 701 * http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=701. * Author: Mladen Turk (and Sean Gilles?) * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* Following works for GCC and MSVC. That's ~98% of our users, if Tyler * Mitchell's survey is correct */ #define MS_COPYSTELEM(_name) (dst)->/**/_name = (src)->/**/_name #define MS_MACROBEGIN do { #define MS_MACROEND } while (0) #define MS_COPYRECT(_dst, _src) \ MS_MACROBEGIN \ (_dst)->minx = (_src)->minx; \ (_dst)->miny = (_src)->miny; \ (_dst)->maxx = (_src)->maxx; \ (_dst)->maxy = (_src)->maxy; \ MS_MACROEND #ifdef USE_POINT_Z_M #define MS_COPYPOINT(_dst, _src) \ MS_MACROBEGIN \ (_dst)->x = (_src)->x; \ (_dst)->y = (_src)->y; \ (_dst)->m = (_src)->m; \ MS_MACROEND #else #define MS_COPYPOINT(_dst, _src) \ MS_MACROBEGIN \ (_dst)->x = (_src)->x; \ (_dst)->y = (_src)->y; \ MS_MACROEND #endif #ifdef USE_GD #define MS_COPYCOLOR(_dst, _src) \ MS_MACROBEGIN \ (_dst)->pen = (_src)->pen; \ (_dst)->red = (_src)->red; \ (_dst)->green = (_src)->green;\ (_dst)->blue = (_src)->blue; \ (_dst)->alpha = (_src)->alpha; \ MS_MACROEND #else #define MS_COPYCOLOR(_dst, _src) \ MS_MACROBEGIN \ (_dst)->red = (_src)->red; \ (_dst)->green = (_src)->green;\ (_dst)->blue = (_src)->blue; \ (_dst)->alpha = (_src)->alpha; \ MS_MACROEND #endif #define MS_COPYSTRING(_dst, _src) \ MS_MACROBEGIN \ if ((_dst) != NULL) \ msFree((_dst)); \ if ((_src)) \ (_dst) = strdup((_src)); \ else \ (_dst) = NULL; \ MS_MACROEND mapserver-6.4.1/mapwfs.c0000644002461700001440000037026212261257215014767 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: WFS server implementation * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2002, Daniel Morissette, DM Solutions Group Inc * * 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 ****************************************************************************/ #include "mapserver.h" #if defined(USE_WFS_SVR) /* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */ #include "cpl_minixml.h" #include "cpl_conv.h" #include "mapogcfilter.h" #include "mapowscommon.h" #include "maptemplate.h" #ifdef WFS_USE_LIBXML2 #include "maplibxml2.h" #endif /* ** msWFSException() ** ** Report current MapServer error in XML exception format. */ int msWFSException(mapObj *map, const char *locator, const char *code, const char *version ) { const char *encoding; char *schemalocation = NULL; /* In WFS, exceptions are always XML. */ if( version == NULL ) version = "1.1.0"; if( msOWSParseVersionString(version) >= OWS_1_1_0 ) return msWFSException11( map, locator, code, version ); encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n", schemalocation); free(schemalocation); msIO_printf(" \n", code, locator); /* Optional element currently unused. */ /* msIO_printf(" \n"); */ msWriteErrorXML(stdout); /* msIO_printf(" \n"); */ msIO_printf(" \n"); msIO_printf("\n"); return MS_FAILURE; /* so we can call 'return msWFSException();' anywhere */ } /* ** Helper function to build a list of output formats. ** ** Given a layer it will return all formats valid for that layer, otherwise ** all formats permitted on layers in the map are returned. The string ** returned should be freed by the caller. */ char *msWFSGetOutputFormatList(mapObj *map, layerObj *layer, const char *version ) { int i, got_map_list = 0; static const int out_list_size = 20000; char *out_list = (char*) msSmallCalloc(1,out_list_size); if( strncasecmp(version,"1.0",3) != 0 ) strcpy(out_list,"text/xml; subtype=gml/3.1.1"); else strcpy(out_list,"GML2"); for( i = 0; i < map->numlayers; i++ ) { const char *format_list; layerObj *lp; int j, n; char **tokens; lp = GET_LAYER(map, i); if( layer != NULL && layer != lp ) continue; format_list = msOWSLookupMetadata(&(lp->metadata), "F","getfeature_formatlist"); if( format_list == NULL && !got_map_list ) { format_list = msOWSLookupMetadata(&(map->web.metadata), "F","getfeature_formatlist"); got_map_list = 1; } if( format_list == NULL ) continue; n = 0; tokens = msStringSplit(format_list, ',', &n); for( j = 0; j < n; j++ ) { int iformat; const char *fname, *hit; outputFormatObj *format_obj; msStringTrim( tokens[j] ); iformat = msGetOutputFormatIndex(map,tokens[j]); if( iformat < 0 ) continue; format_obj = map->outputformatlist[iformat]; fname = format_obj->name; if( strncasecmp(version,"1.0",3) != 0 && format_obj->mimetype != NULL ) fname = format_obj->mimetype; hit = strstr(out_list,fname); if( hit != NULL && (hit[strlen(fname)] == '\0' || hit[strlen(fname)] == ',')) continue; if( strlen(out_list) + strlen(fname)+3 < out_list_size ) { strcat( out_list, "," ); strcat( out_list, fname ); } else break; } msFreeCharArray( tokens, n ); } return out_list; } /* ** */ static void msWFSPrintRequestCap(const char *wmtver, const char *request, const char *script_url, const char *format_tag, const char *formats_list) { msIO_printf(" <%s>\n", request); /* We expect to receive a NULL-terminated args list of formats */ if (format_tag != NULL) { int i, n; char **tokens; n = 0; tokens = msStringSplit(formats_list, ',', &n); msIO_printf(" <%s>\n", format_tag); for( i = 0; i < n; i++ ) { msIO_printf(" <%s/>\n", tokens[i] ); } msFreeCharArray( tokens, n ); msIO_printf(" \n", format_tag); } msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", script_url); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", script_url); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n", request); } /* msWFSLocateSRSInList() ** ** Utility function to check if a space separated list contains the one passed in argument. ** The list comes normaly from ows_srs metadata, and is expected to use the simple EPSG notation ** (EPSG:4326 ESPG:42304 ...). The srs comes from the query string and can either ** be of simple EPSG format or using gc:def:crs:EPSG:xxx format */ int msWFSLocateSRSInList(const char *pszList, const char *srs) { int nTokens,i; char **tokens = NULL; int bFound = MS_FALSE; char epsg_string[100]; const char *code; if (!pszList || !srs) return MS_FALSE; if (strncasecmp(srs, "EPSG:",5) == 0) code = srs+5; else if (strncasecmp(srs, "urn:ogc:def:crs:EPSG:",21) == 0) { if (srs[21] == ':') code = srs+21; else code = srs+20; while( *code != ':' && *code != '\0') code++; if( *code == ':' ) code++; } else if (strncasecmp(srs, "urn:EPSG:geographicCRS:",23) == 0) code = srs + 23; else return MS_FALSE; snprintf( epsg_string, sizeof(epsg_string), "EPSG:%s", code ); tokens = msStringSplit(pszList, ' ', &nTokens ); if (tokens && nTokens > 0) { for (i=0; iprojection), &(map->web.metadata), "FO", MS_TRUE); if(pszMapSRS && nVersion > OWS_1_0_0) msLoadProjectionStringEPSG(&(map->projection), pszMapSRS); if (srs == NULL || nVersion == OWS_1_0_0) { for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if (lp->status != MS_ON) continue; if (pszMapSRS) pszLayerSRS = pszMapSRS; else pszLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE); if (pszLayerSRS == NULL) { msSetError(MS_WFSERR, "Server config error: SRS must be set at least at the map or at the layer level.", "msWFSGetFeature()"); if (pszOutputSRS) msFree(pszOutputSRS); return MS_FAILURE; } if (pszOutputSRS == NULL) pszOutputSRS = msStrdup(pszLayerSRS); else if (strcasecmp(pszLayerSRS,pszOutputSRS) != 0) { msSetError(MS_WFSERR, "Invalid GetFeature Request: All TYPENAMES in a single GetFeature request must have been advertized in the same SRS. Please check the capabilities and reformulate your request.", "msWFSGetFeature()"); if (pszOutputSRS) msFree(pszOutputSRS); return MS_FAILURE; } } } else { /*srs is given so it should be valid for all layers*/ /*get all the srs defined at the map level and check them aginst the srsName passed as argument*/ pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_FALSE); if (pszMapSRS) { if (!msWFSLocateSRSInList(pszMapSRS, srs)) { msSetError(MS_WFSERR, "Invalid GetFeature Request:Invalid SRS. Please check the capabilities and reformulate your request.", "msWFSGetFeature()"); return MS_FAILURE; } pszOutputSRS = msStrdup(srs); } else { for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if (lp->status != MS_ON) continue; pszLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_FALSE); if (!pszLayerSRS) { msSetError(MS_WFSERR, "Server config error: SRS must be set at least at the map or at the layer level.", "msWFSGetFeature()"); return MS_FAILURE; } if (!msWFSLocateSRSInList(pszLayerSRS, srs)) { msSetError(MS_WFSERR, "Invalid GetFeature Request:Invalid SRS. Please check the capabilities and reformulate your request.", "msWFSGetFeature()"); return MS_FAILURE; } } pszOutputSRS = msStrdup(srs); } } if (pszOutputSRS && nVersion >= OWS_1_1_0) { projectionObj sProjTmp; int nTmp=0; msInitProjection(&sProjTmp); nTmp = msLoadProjectionStringEPSG(&(sProjTmp), pszOutputSRS); if (nTmp == 0) { msProjectRect(&(map->projection), &(sProjTmp), &map->extent); } msFreeProjection(&(sProjTmp)); /*check if the srs passed is valid. Assuming that it is an EPSG:xxx format, Or urn:ogc:def:crs:EPSG:xxx format. */ if (strncasecmp(pszOutputSRS, "EPSG:", 5) == 0 || strncasecmp(pszOutputSRS, "urn:ogc:def:crs:EPSG:",21) == 0) { /*we load the projection sting in the map and possibly set the axis order*/ msFreeProjection(&map->projection); msLoadProjectionStringEPSG(&(map->projection), pszOutputSRS); } else if (strncasecmp(pszOutputSRS, "urn:EPSG:geographicCRS:",23) == 0) { char epsg_string[100]; const char *code; code = pszOutputSRS + 23; snprintf( epsg_string, sizeof(epsg_string), "EPSG:%s", code ); /*we load the projection sting in the map and possibly set the axis order*/ /*reproject the map extent from current projection to output projection*/ msFreeProjection(&map->projection); msLoadProjectionStringEPSG(&(map->projection), epsg_string); } } /* Set map output projection to which output features should be reprojected */ else if (pszOutputSRS && strncasecmp(pszOutputSRS, "EPSG:", 5) == 0) { int nTmp =0; projectionObj sProjTmp; /*reproject the map extent from current projection to output projection*/ msInitProjection(&sProjTmp); if (nVersion >= OWS_1_1_0) nTmp = msLoadProjectionStringEPSG(&(sProjTmp), pszOutputSRS); else nTmp = msLoadProjectionString(&(sProjTmp), pszOutputSRS); if (nTmp == 0) msProjectRect(&(map->projection), &(sProjTmp), &map->extent); msFreeProjection(&(sProjTmp)); msFreeProjection(&map->projection); msInitProjection(&map->projection); if (nVersion >= OWS_1_1_0) nTmp = msLoadProjectionStringEPSG(&(map->projection), pszOutputSRS); else nTmp = msLoadProjectionString(&(map->projection), pszOutputSRS); if (nTmp != 0) { msSetError(MS_WFSERR, "msLoadProjectionString() failed", "msWFSGetFeature()"); return MS_FAILURE; } } if (pszOutputSRS) msFree(pszOutputSRS); return MS_SUCCESS; } /* msWFSIsLayerSupported() ** ** Returns true (1) is this layer meets the requirements to be served as ** a WFS feature type. */ int msWFSIsLayerSupported(layerObj *lp) { /* In order to be supported, lp->type must be specified, even for ** layers that are OGR, SDE, SDO, etc connections. */ if ((lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE || lp->type == MS_LAYER_POLYGON ) && lp->connectiontype != MS_WMS && lp->connectiontype != MS_GRATICULE) { return 1; /* true */ } return 0; /* false */ } /* msWFSGetGeomElementName() ** ** Return the geometry propery name base on the layer type */ const char *msWFSGetGeomElementName(mapObj *map, layerObj *lp) { switch(lp->type) { case MS_LAYER_POINT: return "pointProperty"; case MS_LAYER_LINE: return "lineStringProperty"; case MS_LAYER_POLYGON: return "polygonProperty"; default: break; } return "???unknown???"; } /* msWFSGetGeomType() ** ** Return GML name for geometry type in this layer ** This is based on MapServer geometry type and layers with mixed geometries ** may not return the right feature type. */ #ifdef notdef /* not currently used */ static const char *msWFSGetGeomType(layerObj *lp) { switch(lp->type) { case MS_LAYER_POINT: return "PointPropertyType"; case MS_LAYER_LINE: return "LineStringPropertyType"; case MS_LAYER_POLYGON: return "PolygonPropertyType"; default: break; } return "???unknown???"; } #endif /* def notdef */ /* ** msWFSDumpLayer() */ int msWFSDumpLayer(mapObj *map, layerObj *lp) { rectObj ext; const char *pszWfsSrs = NULL; projectionObj poWfs; msIO_printf(" \n"); if (lp->name && strlen(lp->name) > 0 && (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0]))) msIO_fprintf(stdout, "\n",lp->name); msOWSPrintEncodeParam(stdout, "LAYER.NAME", lp->name, OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(lp->metadata), "FO", "title", OWS_WARN, " %s\n", lp->name); msOWSPrintEncodeMetadata(stdout, &(lp->metadata), "FO", "abstract", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadataList(stdout, &(lp->metadata), "FO", "keywordlist", " \n", " \n", " %s\n", NULL); /* In WFS, every layer must have exactly one SRS and there is none at */ /* the top level contrary to WMS */ /* */ /* So here is the way we'll deal with SRS: */ /* 1- If a top-level map projection (or wfs_srs metadata) is set then */ /* all layers are advertized in the map's projection and they will */ /* be reprojected on the fly in the GetFeature request. */ /* 2- If there is no top-level map projection (or wfs_srs metadata) then */ /* each layer is advertized in its own projection as defined in the */ /* layer's projection object or wfs_srs metadata. */ /* */ if (msOWSGetEPSGProj(&(map->projection),&(map->web.metadata),"FO",MS_TRUE) != NULL) { /* Map has a SRS. Use it for all layers. */ pszWfsSrs = msOWSGetEPSGProj(&(map->projection),&(map->web.metadata), "FO", MS_TRUE); } else { /* Map has no SRS. Use layer SRS or produce a warning. */ pszWfsSrs = msOWSGetEPSGProj(&(lp->projection),&(lp->metadata), "FO", MS_TRUE); } msOWSPrintEncodeParam(stdout, "(at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs_srs metadata", pszWfsSrs, OWS_WARN, " %s\n", NULL); /* If layer has no proj set then use map->proj for bounding box. */ if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) { msInitProjection(&poWfs); if (pszWfsSrs != NULL) msLoadProjectionString(&(poWfs), pszWfsSrs); if(lp->projection.numargs > 0) { msOWSPrintLatLonBoundingBox(stdout, " ", &(ext), &(lp->projection), &(poWfs), OWS_WFS); } else { msOWSPrintLatLonBoundingBox(stdout, " ", &(ext), &(map->projection), &(poWfs), OWS_WFS); } msFreeProjection(&poWfs); } else { msIO_printf("\n"); } msOWSPrintURLType(stdout, &(lp->metadata), "FO", "metadataurl", OWS_NOERR, NULL, "MetadataURL", " type=\"%s\"", NULL, NULL, " format=\"%s\"", "%s", MS_TRUE, MS_FALSE, MS_FALSE, MS_TRUE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); if (msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid") == NULL) { msIO_fprintf(stdout, "\n"); } msIO_printf(" \n"); return MS_SUCCESS; } /* ** msWFSGetCapabilities() */ int msWFSGetCapabilities(mapObj *map, wfsParamsObj *wfsparams, cgiRequestObj *req, owsRequestObj *ows_request) { char *script_url=NULL, *script_url_encoded; const char *updatesequence=NULL; const char *wmtver=NULL; const char *encoding; char *formats_list; char tmpString[OWS_VERSION_MAXLEN]; int wfsSupportedVersions[] = {OWS_1_1_0, OWS_1_0_0}; int wfsNumSupportedVersions = 2; int i=0, tmpInt=0; /* acceptversions: do OWS Common style of version negotiation */ if (wfsparams->pszAcceptVersions && strlen(wfsparams->pszAcceptVersions) > 0) { char **tokens; int i, j; tokens = msStringSplit(wfsparams->pszAcceptVersions, ',', &j); for (i=0; ipszAcceptVersions); return msWFSException(map, "acceptversions", "VersionNegotiationFailed",wmtver); } } else /* negotiate version */ tmpInt = msOWSNegotiateVersion(msOWSParseVersionString(wfsparams->pszVersion), wfsSupportedVersions, wfsNumSupportedVersions); /* set result as string and carry on */ if (wfsparams->pszVersion) msFree(wfsparams->pszVersion); wfsparams->pszVersion = msStrdup(msOWSGetVersionString(tmpInt, tmpString)); if( wfsparams->pszVersion == NULL || strncmp(wfsparams->pszVersion,"1.1",3) == 0 ) return msWFSGetCapabilities11( map, wfsparams, req, ows_request); /* Decide which version we're going to return... only 1.0.0 for now */ wmtver = "1.0.0"; /* We need this server's onlineresource. */ if ((script_url=msOWSGetOnlineResource(map, "FO", "onlineresource", req)) == NULL || (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL) { msSetError(MS_WFSERR, "Server URL not found", "msWFSGetCapabilities()"); return msWFSException(map, "mapserv", "NoApplicableCode", wmtver); } free(script_url); script_url = NULL; updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence"); if (!updatesequence) updatesequence = msStrdup("0"); if (wfsparams->pszUpdateSequence != NULL) { i = msOWSNegotiateUpdateSequence(wfsparams->pszUpdateSequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWFSGetCapabilities()", wfsparams->pszUpdateSequence, updatesequence); free(script_url_encoded); return msWFSException(map, "updatesequence", "CurrentUpdateSequence", wmtver); } if (i > 0) { /* invalid */ msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWFSGetCapabilities()", wfsparams->pszUpdateSequence, updatesequence); free(script_url_encoded); return msWFSException(map, "updatesequence", "InvalidUpdateSequence", wmtver); } } encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); msIO_printf("\n", wmtver, updatesequence, msOWSGetSchemasLocation(map), wmtver); /* Report MapServer Version Information */ msIO_printf("\n\n\n", msGetVersion()); /* ** SERVICE definition */ msIO_printf("\n"); msIO_printf(" MapServer WFS\n"); /* the majority of this section is dependent on appropriately named metadata in the WEB object */ msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "title", OWS_WARN, " %s\n", map->name); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "abstract", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadataList(stdout, &(map->web.metadata), "FO", "keywordlist", " \n", " \n", " %s\n", NULL); /* Service/onlineresource */ /* Defaults to same as request onlineresource if wfs_service_onlineresource */ /* is not set. */ msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "service_onlineresource", OWS_NOERR, " %s\n", script_url_encoded); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "fees", OWS_NOERR, " %s\n", NULL); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "accessconstraints", OWS_NOERR, " %s\n", NULL); msIO_printf("\n\n"); /* ** CAPABILITY definitions: list of supported requests */ msIO_printf("\n"); msIO_printf(" \n"); msWFSPrintRequestCap(wmtver, "GetCapabilities", script_url_encoded, NULL, NULL); /* msWFSPrintRequestCap(wmtver, "DescribeFeatureType", script_url_encoded, "SchemaDescriptionLanguage", "XMLSCHEMA", "SFE_XMLSCHEMA", NULL); */ /* msWFSPrintRequestCap(wmtver, "GetFeature", script_url_encoded, "ResultFormat", "GML2", "GML3", NULL); */ /* don't advertise the GML3 or GML for SFE support */ if (msOWSRequestIsEnabled(map, NULL, "F", "DescribeFeatureType", MS_TRUE)) msWFSPrintRequestCap(wmtver, "DescribeFeatureType", script_url_encoded, "SchemaDescriptionLanguage", "XMLSCHEMA" ); if (msOWSRequestIsEnabled(map, NULL, "F", "GetFeature", MS_TRUE)) { formats_list = msWFSGetOutputFormatList( map, NULL, wfsparams->pszVersion ); msWFSPrintRequestCap(wmtver, "GetFeature", script_url_encoded, "ResultFormat", formats_list ); msFree( formats_list ); } msIO_printf(" \n"); msIO_printf("\n\n"); /* ** FeatureTypeList: layers */ msIO_printf("\n"); /* Operations supported... set default at top-level, and more operations */ /* can be added inside each layer... for MapServer only query is supported */ msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); for(i=0; inumlayers; i++) { layerObj *lp; lp = GET_LAYER(map, i); if (lp->status == MS_DELETE) continue; if (!msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) continue; if (msWFSIsLayerSupported(lp)) { msWFSDumpLayer(map, lp); } } msIO_printf("\n\n"); /* ** OGC Filter Capabilities ... for now we support only BBOX */ msIO_printf("\n"); msIO_printf(" \n"); msIO_printf(" \n"); #ifdef USE_GEOS msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); #endif msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf("\n\n"); /* ** Done! */ msIO_printf("\n"); free(script_url_encoded); return MS_SUCCESS; } /* ** Helper functions for producing XML schema. */ static const char *msWFSGetGeometryType(char *type, int outputformat) { if(!type) return "???undefined???"; if(strcasecmp(type, "point") == 0) { switch(outputformat) { case OWS_GML2: case OWS_GML3: return "PointPropertyType"; } } else if(strcasecmp(type, "multipoint") == 0) { switch(outputformat) { case OWS_GML2: case OWS_GML3: return "MultiPointPropertyType"; } } else if(strcasecmp(type, "line") == 0) { switch(outputformat) { case OWS_GML2: return "LineStringPropertyType"; case OWS_GML3: return "CurvePropertyType"; } } else if(strcasecmp(type, "multiline") == 0) { switch(outputformat) { case OWS_GML2: return "MultiLineStringPropertyType"; case OWS_GML3: return "MultiCurvePropertyType"; } } else if(strcasecmp(type, "polygon") == 0) { switch(outputformat) { case OWS_GML2: return "PolygonPropertyType"; case OWS_GML3: return "SurfacePropertyType"; } } else if(strcasecmp(type, "multipolygon") == 0) { switch(outputformat) { case OWS_GML2: return "MultiPolygonPropertyType"; case OWS_GML3: return "MultiSurfacePropertyType"; } } return "???unkown???"; } static void msWFSWriteGeometryElement(FILE *stream, gmlGeometryListObj *geometryList, int outputformat, const char *tab) { int i; gmlGeometryObj *geometry=NULL; if(!stream || !tab) return; if(geometryList && geometryList->numgeometries == 1 && strcasecmp(geometryList->geometries[0].name, "none") == 0) return; if(!geometryList || geometryList->numgeometries == 0) { /* write a default container */ msIO_fprintf(stream, "%s\n", tab, OWS_GML_DEFAULT_GEOMETRY_NAME); return; } else { if(geometryList->numgeometries == 1) { geometry = &(geometryList->geometries[0]); msIO_fprintf(stream, "%sname, msWFSGetGeometryType(geometry->type, outputformat), geometry->occurmin); if(geometry->occurmax == OWS_GML_OCCUR_UNBOUNDED) msIO_fprintf(stream, " maxOccurs=\"unbounded\"/>\n"); else msIO_fprintf(stream, " maxOccurs=\"%d\"/>\n", geometry->occurmax); } else { msIO_fprintf(stream, "%s\n", tab); for(i=0; inumgeometries; i++) { geometry = &(geometryList->geometries[i]); msIO_fprintf(stream, " %sname, msWFSGetGeometryType(geometry->type, outputformat), geometry->occurmin); if(geometry->occurmax == OWS_GML_OCCUR_UNBOUNDED) msIO_fprintf(stream, " maxOccurs=\"unbounded\"/>\n"); else msIO_fprintf(stream, " maxOccurs=\"%d\"/>\n", geometry->occurmax); } msIO_fprintf(stream, "%s\n", tab); } } return; } static void msWFSWriteItemElement(FILE *stream, gmlItemObj *item, const char *tab) { char *element_name; char *element_type = "string"; if(!stream || !item || !tab) return; if(!item->visible) return; /* not exposing this attribute */ if(item->template) return; /* can't adequately deal with templated items yet */ if(item->alias) /* TODO: what about name spaces embedded in the alias? */ element_name = item->alias; else element_name = item->name; if(item->type) { /* Map from MapServer types to XSD types */ if( strcasecmp(item->type,"Integer") == 0 ) element_type = "integer"; else if( EQUAL(item->type,"Real") || EQUAL(item->type,"double") /* just in case someone provided the xsd type directly */ ) element_type = "double"; else if( EQUAL(item->type,"Character") ) element_type = "string"; else if( EQUAL(item->type,"Date") ) element_type = "date"; else if( EQUAL(item->type,"Boolean") ) element_type = "boolean"; } msIO_fprintf(stream, "%s\n", tab, element_name, element_type); return; } static void msWFSWriteConstantElement(FILE *stream, gmlConstantObj *constant, const char *tab) { char *element_type = "string"; if(!stream || !constant || !tab) return; if(constant->type) element_type = constant->type; msIO_fprintf(stream, "%s\n", tab, constant->name, element_type); return; } static void msWFSWriteGroupElement(FILE *stream, gmlGroupObj *group, const char *tab, const char *namespace) { if(group->type) msIO_fprintf(stream, "%s\n", tab, group->name, namespace, group->type); else msIO_fprintf(stream, "%s\n", tab, group->name, namespace, group->name); return; } static void msWFSWriteGroupElementType(FILE *stream, gmlGroupObj *group, gmlItemListObj *itemList, gmlConstantListObj *constantList, const char *tab) { int i, j; char *element_tab; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; /* setup the element tab */ element_tab = (char *) malloc(sizeof(char)*strlen(tab)+5); MS_CHECK_ALLOC_NO_RET(element_tab, sizeof(char)*strlen(tab)+5); sprintf(element_tab, "%s ", tab); if(group->type) msIO_fprintf(stream, "%s\n", tab, group->type); else msIO_fprintf(stream, "%s\n", tab, group->name); msIO_fprintf(stream, "%s \n", tab); /* now the items/constants (e.g. elements) in the group */ for(i=0; inumitems; i++) { for(j=0; jnumconstants; j++) { /* find the right gmlConstantObj */ constant = &(constantList->constants[j]); if(strcasecmp(constant->name, group->items[i]) == 0) { msWFSWriteConstantElement(stream, constant, element_tab); break; } } if(j != constantList->numconstants) continue; /* found this item */ for(j=0; jnumitems; j++) { /* find the right gmlItemObj */ item = &(itemList->items[j]); if(strcasecmp(item->name, group->items[i]) == 0) { msWFSWriteItemElement(stream, item, element_tab); break; } } } msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s\n", tab); return; } /* ** msWFSDescribeFeatureType() */ int msWFSDescribeFeatureType(mapObj *map, wfsParamsObj *paramsObj, owsRequestObj *ows_request) { int i, numlayers=0; char **layers = NULL; char **tokens; int n=0; const char *value; const char *user_namespace_prefix = "ms"; const char *user_namespace_uri = "http://mapserver.gis.umn.edu/mapserver"; char *user_namespace_uri_encoded = NULL; const char *collection_name = OWS_WFS_FEATURE_COLLECTION_NAME; char *encoded_name = NULL, *encoded; int outputformat = OWS_DEFAULT_SCHEMA; /* default output is GML 2.1 compliant schema*/ gmlNamespaceListObj *namespaceList=NULL; /* for external application schema support */ char *mimetype = NULL; if(paramsObj->pszTypeName && numlayers == 0) { /* Parse comma-delimited list of type names (layers) */ /* */ /* __TODO__ Need to handle type grouping, e.g. "(l1,l2),l3,l4" */ /* */ layers = msStringSplit(paramsObj->pszTypeName, ',', &numlayers); if (numlayers > 0) { /* strip namespace if there is one :ex TYPENAME=cdf:Other */ tokens = msStringSplit(layers[0], ':', &n); if (tokens && n==2 && msGetLayerIndex(map, layers[0]) < 0) { msFreeCharArray(tokens, n); tokens = NULL; for (i=0; ipszOutputFormat) { if(strcasecmp(paramsObj->pszOutputFormat, "XMLSCHEMA") == 0 || strstr(paramsObj->pszOutputFormat, "gml/2")!= NULL) { mimetype = msEncodeHTMLEntities("text/xml; subtype=gml/2.1.2"); outputformat = OWS_DEFAULT_SCHEMA; } else if(strcasecmp(paramsObj->pszOutputFormat, "SFE_XMLSCHEMA") == 0 || strstr(paramsObj->pszOutputFormat, "gml/3")!= NULL) { mimetype = msEncodeHTMLEntities("text/xml; subtype=gml/3.1.1"); outputformat = OWS_SFE_SCHEMA; } else { msSetError(MS_WFSERR, "Unsupported DescribeFeatureType outputFormat (%s).", "msWFSDescribeFeatureType()", paramsObj->pszOutputFormat); return msWFSException(map, "outputformat", "InvalidParameterValue", paramsObj->pszVersion); } } /*set the output format to gml3 for wfs1.1*/ if(mimetype == NULL) { if (paramsObj->pszVersion == NULL || strncmp(paramsObj->pszVersion,"1.1",3) == 0 ) { mimetype = msEncodeHTMLEntities("text/xml; subtype=gml/3.1.1"); outputformat = OWS_SFE_SCHEMA; } else mimetype = msEncodeHTMLEntities("text/xml"); } /* Validate layers */ if (numlayers > 0) { for (i=0; iindex, ows_request->enabled_layers, ows_request->numlayers)) ) { msSetError(MS_WFSERR, "Invalid typename (%s). A layer might be disabled for \ this request. Check wfs/ows_enable_request settings.", "msWFSDescribeFeatureType()", layers[i]);/* paramsObj->pszTypeName); */ return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion); } } } /* ** retrieve any necessary external namespace/schema configuration information */ namespaceList = msGMLGetNamespaces(&(map->web), "G"); if (namespaceList == NULL) { msSetError(MS_MISCERR, "Unable to populate namespace list", "msWFSDescribeFeatureType()"); return MS_FAILURE; } /* ** DescribeFeatureType response */ value = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (value) msIO_setHeader("Content-Type","%s; charset=%s",mimetype, value); else msIO_setHeader("Content-Type","%s",mimetype); msIO_sendHeaders(); if (mimetype) msFree(mimetype); msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_uri"); if(value) user_namespace_uri = value; user_namespace_uri_encoded = msEncodeHTMLEntities(user_namespace_uri); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix"); if(value) user_namespace_prefix = value; if(user_namespace_prefix != NULL && msIsXMLTagValid(user_namespace_prefix) == MS_FALSE) msIO_printf("\n", user_namespace_prefix); msIO_printf("numnamespaces; i++) { if(namespaceList->namespaces[i].uri) { char *uri_encoded=NULL; uri_encoded = msEncodeHTMLEntities(namespaceList->namespaces[i].uri); msIO_printf(" xmlns:%s=\"%s\" \n", namespaceList->namespaces[i].prefix, uri_encoded); msFree(uri_encoded); } } msIO_printf(" elementFormDefault=\"qualified\" version=\"0.1\" >\n"); encoded = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); if(outputformat == OWS_SFE_SCHEMA) /* reference GML 3.1.1 schema */ msIO_printf("\n \n", encoded); else /* default GML 2.1.x schema */ msIO_printf("\n \n", encoded); msFree(encoded); /* any additional namespace includes */ for(i=0; inumnamespaces; i++) { if(namespaceList->namespaces[i].uri && namespaceList->namespaces[i].schemalocation) { char *schema_location_encoded=NULL, *uri_encoded=NULL; uri_encoded = msEncodeHTMLEntities(namespaceList->namespaces[i].uri); schema_location_encoded = msEncodeHTMLEntities(namespaceList->namespaces[i].schemalocation); msIO_printf("\n \n", uri_encoded, schema_location_encoded); msFree(uri_encoded); msFree(schema_location_encoded); } } /* output definition for the default feature container, can't use wfs:FeatureCollection with GML3: kept here so that the behaviour with whs1.0 and gml3 output is preserved. We can use the wfs:FeatureCollection for wfs1.1*/ if(outputformat == OWS_SFE_SCHEMA && strncmp(paramsObj->pszVersion,"1.1",3) != 0) { value = msOWSLookupMetadata(&(map->web.metadata), "FO", "feature_collection"); if(value) collection_name = value; msIO_printf(" \n", collection_name, user_namespace_prefix, collection_name); msIO_printf(" \n", collection_name); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); } /* ** loop through layers */ for(i=0; inumlayers; i++) { layerObj *lp; int j, bFound = 0; lp = GET_LAYER(map, i); for (j=0; jname && strcasecmp(lp->name, layers[j]) == 0) bFound = 1; } if ((numlayers == 0 || bFound) && msWFSIsLayerSupported(lp) && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) ) { /* ** OK, describe this layer IF you can open it and retrieve items */ if (msLayerOpen(lp) == MS_SUCCESS) { if (msLayerGetItems(lp) == MS_SUCCESS) { int k; gmlGroupListObj *groupList=NULL; gmlItemListObj *itemList=NULL; gmlConstantListObj *constantList=NULL; gmlGeometryListObj *geometryList=NULL; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; const char *layer_namespace_prefix; char *encoded_type=NULL; itemList = msGMLGetItems(lp, "G"); /* GML-related metadata */ constantList = msGMLGetConstants(lp, "G"); groupList = msGMLGetGroups(lp, "G"); geometryList = msGMLGetGeometries(lp, "GFO"); if (itemList == NULL || constantList == NULL || groupList == NULL || geometryList == NULL) { msSetError(MS_MISCERR, "Unable to populate item and group metadata structures", "msWFSDescribeFeatureType()"); return MS_FAILURE; } value = msOWSLookupMetadata(&(lp->metadata), "OFG", "namespace_prefix"); if(value) layer_namespace_prefix = value; else layer_namespace_prefix = user_namespace_prefix; /* value = msOWSLookupMetadata(&(lp->metadata), "OFG", "layername"); */ encoded_name = msEncodeHTMLEntities( lp->name ); value = msOWSLookupMetadata(&(lp->metadata), "OFG", "layer_type"); if(value) { encoded_type = msEncodeHTMLEntities(value); msIO_printf("\n" " \n\n", encoded_name, layer_namespace_prefix, encoded_type); msFree(encoded_type); } else msIO_printf("\n" " \n\n", encoded_name, layer_namespace_prefix, encoded_name); if(strcmp(layer_namespace_prefix, user_namespace_prefix) != 0) continue; /* the rest is defined in an external schema */ msIO_printf(" \n", encoded_name); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); /* write the geometry schema element(s) */ msWFSWriteGeometryElement(stdout, geometryList, outputformat, " "); /* write the constant-based schema elements */ for(k=0; knumconstants; k++) { constant = &(constantList->constants[k]); if(msItemInGroups(constant->name, groupList) == MS_FALSE) msWFSWriteConstantElement(stdout, constant, " "); } /* write the item-based schema elements */ for(k=0; knumitems; k++) { item = &(itemList->items[k]); if(msItemInGroups(item->name, groupList) == MS_FALSE) msWFSWriteItemElement(stdout, item, " "); } for(k=0; knumgroups; k++) msWFSWriteGroupElement(stdout, &(groupList->groups[k]), " ", user_namespace_prefix); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); msIO_printf(" \n"); /* any group types */ for(k=0; knumgroups; k++) msWFSWriteGroupElementType(stdout, &(groupList->groups[k]), itemList, constantList, " "); msGMLFreeItems(itemList); msGMLFreeConstants(constantList); msGMLFreeGroups(groupList); msGMLFreeGeometries(geometryList); } msLayerClose(lp); } else { msIO_printf("\n\n\n\n", encoded_name); } } } /* ** Done! */ msIO_printf("\n\n"); msFree(encoded_name); msFree(user_namespace_uri_encoded); if(layers) msFreeCharArray(layers, numlayers); msGMLFreeNamespaces(namespaceList); return MS_SUCCESS; } /* ** msWFSGetFeature_GMLPreamble() ** ** Generate the GML preamble up to the first feature for the builtin ** WFS GML support. */ typedef struct { const char *user_namespace_prefix; const char *user_namespace_uri; char *user_namespace_uri_encoded; const char *collection_name; const char *typename; char *script_url, *script_url_encoded; const char *output_schema_format; } WFSGMLInfo; static int msWFSGetFeature_GMLPreamble( mapObj *map, cgiRequestObj *req, WFSGMLInfo *gmlinfo, wfsParamsObj *paramsObj, int outputformat, int iResultTypeHits, int iNumberOfFeatures ) { const char *value; int i; char *encoded, *encoded_typename, *encoded_schema; gmlNamespaceListObj *namespaceList=NULL; /* for external application schema support */ namespaceList = msGMLGetNamespaces(&(map->web), "G"); if (namespaceList == NULL) { msSetError(MS_MISCERR, "Unable to populate namespace list", "msWFSGetFeature_GMLPreamble()"); return MS_FAILURE; } /* ** Establish script_url. */ if ((gmlinfo->script_url=msOWSGetOnlineResource(map,"FO","onlineresource",req)) ==NULL || (gmlinfo->script_url_encoded = msEncodeHTMLEntities(gmlinfo->script_url)) == NULL) { msSetError(MS_WFSERR, "Server URL not found", "msWFSGetFeature()"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } /* ** Write encoding. */ msOWSPrintEncodeMetadata(stdout, &(map->web.metadata), "FO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_uri"); if(value) gmlinfo->user_namespace_uri = value; gmlinfo->user_namespace_uri_encoded = msEncodeHTMLEntities(gmlinfo->user_namespace_uri); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix"); if(value) gmlinfo->user_namespace_prefix = value; if(gmlinfo->user_namespace_prefix != NULL && msIsXMLTagValid(gmlinfo->user_namespace_prefix) == MS_FALSE) msIO_printf("\n", gmlinfo->user_namespace_prefix); value = msOWSLookupMetadata(&(map->web.metadata), "FO", "feature_collection"); if(value) gmlinfo->collection_name = value; encoded = msEncodeHTMLEntities( paramsObj->pszVersion ); encoded_typename = msEncodeHTMLEntities( gmlinfo->typename ); encoded_schema = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); /* ** GML 2.x */ if(outputformat == OWS_GML2) { /* use a wfs:FeatureCollection */ msIO_printf("user_namespace_prefix, gmlinfo->user_namespace_uri_encoded); /* any additional namespaces */ for(i=0; inumnamespaces; i++) { if(namespaceList->namespaces[i].uri) { char *uri_encoded=NULL; uri_encoded = msEncodeHTMLEntities(namespaceList->namespaces[i].uri); msIO_printf(" xmlns:%s=\"%s\" \n", namespaceList->namespaces[i].prefix, uri_encoded); msFree(uri_encoded); } } msIO_printf(" xsi:schemaLocation=\"http://www.opengis.net/wfs %s/wfs/%s/WFS-basic.xsd \n" " %s %sSERVICE=WFS&VERSION=%s&REQUEST=DescribeFeatureType&TYPENAME=%s&OUTPUTFORMAT=%s\">\n", encoded_schema, encoded, gmlinfo->user_namespace_uri_encoded, gmlinfo->script_url_encoded, encoded, encoded_typename, gmlinfo->output_schema_format); } /* ** GML 3 */ else { if(paramsObj->pszVersion && strncmp(paramsObj->pszVersion,"1.1",3) == 0 ) { msIO_printf("user_namespace_prefix, gmlinfo->user_namespace_uri_encoded); } else { msIO_printf("<%s:%s\n" " version=\"1.0.0\"\n" " xmlns:%s=\"%s\"\n" " xmlns:gml=\"http://www.opengis.net/gml\"\n" " xmlns:ogc=\"http://www.opengis.net/ogc\"\n" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n", gmlinfo->user_namespace_prefix, gmlinfo->collection_name, gmlinfo->user_namespace_prefix, gmlinfo->user_namespace_uri_encoded); } /* any additional namespaces */ for(i=0; inumnamespaces; i++) { if(namespaceList->namespaces[i].uri) { char *uri_encoded=NULL; uri_encoded = msEncodeHTMLEntities(namespaceList->namespaces[i].uri); msIO_printf(" xmlns:%s=\"%s\" \n", namespaceList->namespaces[i].prefix, uri_encoded); msFree(uri_encoded); } } if(paramsObj->pszVersion && strncmp(paramsObj->pszVersion,"1.1",3) == 0) { if (iResultTypeHits == 1) { char timestring[100]; struct tm *now; time_t tim=time(NULL); now=localtime(&tim); snprintf(timestring, sizeof(timestring), "%d-%02d-%02dT%02d:%02d:%02d", now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); msIO_printf(" xsi:schemaLocation=\"%s %sSERVICE=WFS&VERSION=%s&REQUEST=DescribeFeatureType&TYPENAME=%s&OUTPUTFORMAT=%s http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\" timeStamp=\"%s\" numberOfFeatures=\"%d\">\n", gmlinfo->user_namespace_uri_encoded, gmlinfo->script_url_encoded, encoded, encoded_typename, gmlinfo->output_schema_format, timestring, iNumberOfFeatures); } else msIO_printf(" xsi:schemaLocation=\"%s %sSERVICE=WFS&VERSION=%s&REQUEST=DescribeFeatureType&TYPENAME=%s&OUTPUTFORMAT=%s http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\">\n", gmlinfo->user_namespace_uri_encoded, gmlinfo->script_url_encoded, encoded, encoded_typename, gmlinfo->output_schema_format); } else msIO_printf(" xsi:schemaLocation=\"%s %sSERVICE=WFS&VERSION=%s&REQUEST=DescribeFeatureType&TYPENAME=%s&OUTPUTFORMAT=%s\">\n", gmlinfo->user_namespace_uri_encoded, gmlinfo->script_url_encoded, encoded, encoded_typename, gmlinfo->output_schema_format); } msFree(encoded); msFree(encoded_schema); msFree(encoded_typename); msGMLFreeNamespaces(namespaceList); return MS_SUCCESS; } /* ** msWFSGetFeature_GMLPostfix() ** ** Generate the GML file tail closing the collection and cleanup a bit. */ static int msWFSGetFeature_GMLPostfix( mapObj *map, cgiRequestObj *req, WFSGMLInfo *gmlinfo, wfsParamsObj *paramsObj, int outputformat, int maxfeatures, int iResultTypeHits, int iNumberOfFeatures ) { if (((iNumberOfFeatures==0) || (maxfeatures == 0)) && iResultTypeHits == 0) { msIO_printf(" \n"); if(outputformat == OWS_GML3) msIO_printf(" missing\n"); else msIO_printf(" missing\n"); msIO_printf(" \n"); } if(outputformat == OWS_GML2) msIO_printf("\n\n"); else { if(paramsObj->pszVersion && strncmp(paramsObj->pszVersion,"1.1",3) == 0) msIO_printf("\n\n"); else msIO_printf("\n\n", gmlinfo->user_namespace_prefix, gmlinfo->collection_name); } free(gmlinfo->script_url); free(gmlinfo->script_url_encoded); msFree(gmlinfo->user_namespace_uri_encoded); return MS_SUCCESS; } /* ** msWFSGetFeature() */ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req, owsRequestObj *ows_request) /* const char *wmtver, char **names, char **values, int numentries) */ { int i, j, status; int maxfeatures=-1,startindex=-1; rectObj bbox; char **layers = NULL; int numlayers = 0; char *pszFilter = NULL; int bFilterSet = 0; int bBBOXSet = 0; char *sBBoxSrs = NULL; int bFeatureIdSet = 0; const char *value; const char *tmpmaxfeatures = NULL; WFSGMLInfo gmlinfo; const char *output_mime_type = "text/xml; subtype=gml/3.1.1"; int outputformat = OWS_GML2; /* default output is GML 2.1 */ outputFormatObj *psFormat = NULL; char **aFIDLayers = NULL; char **aFIDValues = NULL; int iFIDLayers = 0; int iNumberOfFeatures = 0; int iResultTypeHits = 0; char **papszPropertyName = NULL; int nPropertyNames = 0; int nQueriedLayers=0; layerObj *lpQueried=NULL; /*use msLayerGetShape instead of msLayerResultsGetShape of complex filter #3305 int bComplexFilter = MS_FALSE; */ /* Initialize gml options */ memset( &gmlinfo, 0, sizeof(gmlinfo) ); gmlinfo.user_namespace_prefix = "ms"; gmlinfo.user_namespace_uri = "http://mapserver.gis.umn.edu/mapserver"; gmlinfo.collection_name = OWS_WFS_FEATURE_COLLECTION_NAME; gmlinfo.typename = ""; gmlinfo.output_schema_format = "XMLSCHEMA"; /* Default filter is map extents */ bbox = map->extent; /* Read CGI parameters */ /* */ /* __TODO__ Need to support XML encoded requests */ /* */ if (paramsObj->pszResultType != NULL) { if (strcasecmp(paramsObj->pszResultType, "hits") == 0) iResultTypeHits = 1; } /* typename is mandatory unlsess featureid is specfied. We do not support featureid */ if (paramsObj->pszTypeName==NULL && paramsObj->pszFeatureId == NULL) { msSetError(MS_WFSERR, "Incomplete WFS request: TYPENAME parameter missing", "msWFSGetFeature()"); return msWFSException(map, "typename", "MissingParameterValue", paramsObj->pszVersion); } if(paramsObj->pszTypeName) { int j, k, y,z; char **tokens; int n=0, i=0; char szTmp[256]; const char *pszFullName = NULL; /* keep a ref for layer use. */ gmlinfo.typename = paramsObj->pszTypeName; /* Parse comma-delimited list of type names (layers) */ /* */ /* __TODO__ Need to handle type grouping, e.g. "(l1,l2),l3,l4" */ /* */ layers = msStringSplit(gmlinfo.typename, ',', &numlayers); /* ==================================================================== */ /* TODO: check if the typename contains namespaces (ex cdf:Other), */ /* If that is the case extract only the layer name. */ /* ==================================================================== */ if (layers==NULL || numlayers < 1) { msSetError(MS_WFSERR, "At least one type name required in TYPENAME parameter.", "msWFSGetFeature()"); return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion); } tokens = msStringSplit(layers[0], ':', &n); if (tokens && n==2 && msGetLayerIndex(map, layers[0]) < 0) { msFreeCharArray(tokens, n); for (i=0; inumlayers; j++) { layerObj *lp; lp = GET_LAYER(map, j); /* Keep only selected layers, set to OFF by default. */ lp->status = MS_OFF; } for (k=0; knumlayers; j++) { layerObj *lp; char *pszPropertyName = NULL; lp = GET_LAYER(map, j); if (msWFSIsLayerSupported(lp) && lp->name && (strcasecmp(lp->name, layers[k]) == 0) && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) ) { bLayerFound = MS_TRUE; lp->status = MS_ON; if (lp->template == NULL) { /* Force setting a template to enable query. */ lp->template = msStrdup("ttt.html"); } /* set the gml_include_items METADATA */ if (paramsObj->pszPropertyName) { pszPropertyName = paramsObj->pszPropertyName; /*we parse the propertyname parameter only once*/ if (papszPropertyName == NULL) { if (strlen(pszPropertyName) > 0 && (pszPropertyName[0] == '(' || numlayers == 1)) { if (numlayers == 1 && pszPropertyName[0] != '(') { /* Accept PROPERTYNAME without () when there is a single TYPENAME */ char* pszTmpPropertyName = msSmallMalloc(1+strlen(pszPropertyName)+1+1); sprintf(pszTmpPropertyName, "(%s)", pszPropertyName); tokens = msStringSplit(pszTmpPropertyName+1, '(', &nPropertyNames); free(pszTmpPropertyName); } else tokens = msStringSplit(pszPropertyName+1, '(', &nPropertyNames); /*expecting to always have a list of property names equal to the number of layers(typename)*/ if (nPropertyNames != numlayers) { if (tokens) msFreeCharArray(tokens, nPropertyNames); msSetError(MS_WFSERR, "Optional PROPERTYNAME parameter. A list of properties may be specified for each type name. Example TYPENAME=name1&name2&PROPERTYNAME=(prop1,prop2)(prop1)", "msWFSGetFeature()"); return msWFSException(map, "PROPERTYNAME", "InvalidParameterValue", paramsObj->pszVersion); } papszPropertyName = (char **)msSmallMalloc(sizeof(char *)*nPropertyNames); for (i=0; i 0) { /*trim namespaces. PROPERTYNAME=(ns:prop1,ns:prop2)(prop1)*/ if (strstr(tokens[i], ":")) { char **tokens1, **tokens2; int n1=0,n2=0,l=0; char *pszTmp = NULL; tokens1 = msStringSplit(tokens[i], ',', &n1); for (l=0; l0) msFreeCharArray(tokens2, n2); } else pszTmp = msStringConcatenate(pszTmp,tokens1[l]); } papszPropertyName[i] = msStrdup(pszTmp); msFree(pszTmp); if (tokens1 && n1>0) msFreeCharArray(tokens1, n1); } else papszPropertyName[i] = msStrdup(tokens[i]); /* remove trailing ) */ papszPropertyName[i][strlen(papszPropertyName[i])-1] = '\0'; } else papszPropertyName[i] = NULL; /*should return an error*/ } if (tokens) msFreeCharArray(tokens, nPropertyNames); } else { msSetError(MS_WFSERR, "Optional PROPERTYNAME parameter. A list of properties may be specified for each type name. Example TYPENAME=name1&name2&PROPERTYNAME=(prop1,prop2)(prop1)", "msWFSGetFeature()"); return msWFSException(map, "PROPERTYNAME", "InvalidParameterValue", paramsObj->pszVersion); } } /*do an alias replace for the current layer*/ if (papszPropertyName && msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { for(z=0; znumitems; z++) { if (!lp->items[z] || strlen(lp->items[z]) <= 0) continue; snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[z]); pszFullName = msOWSLookupMetadata(&(lp->metadata), "G", szTmp); if (pszFullName) papszPropertyName[k] = msReplaceSubstring(papszPropertyName[k], pszFullName, lp->items[z]); } /*validate that the property names passed are part of the items list*/ tokens = msStringSplit(papszPropertyName[k], ',', &n); for (y=0; y 0) { if (strcasecmp(tokens[y], "*") == 0 || strcasecmp(tokens[y], "!") == 0) continue; for(z=0; znumitems; z++) { if (strcasecmp(tokens[y], lp->items[z]) == 0) break; } /*we need to check of the property name is the geometry name; In that case it is a valid property name*/ if (msOWSLookupMetadata(&(lp->metadata), "OFG", "geometries") != NULL) snprintf(szTmp, sizeof(szTmp), "%s", msOWSLookupMetadata(&(lp->metadata), "OFG", "geometries")); else snprintf(szTmp, sizeof(szTmp), OWS_GML_DEFAULT_GEOMETRY_NAME); if (z == lp->numitems && strcasecmp(tokens[y], szTmp) != 0) { msSetError(MS_WFSERR, "Invalid PROPERTYNAME %s", "msWFSGetFeature()", tokens[y]); msFreeCharArray(tokens, n); return msWFSException(map, "PROPERTYNAME", "InvalidParameterValue", paramsObj->pszVersion); } } } if (tokens && n > 0) msFreeCharArray(tokens, n); msLayerClose(lp); } if (papszPropertyName) { if (strlen(papszPropertyName[k]) > 0) { if (strcasecmp(papszPropertyName[k], "*") == 0) { msInsertHashTable(&(lp->metadata), "GML_INCLUDE_ITEMS", "all"); } /*this character is only used internally and allows postrequest to have a proper property name parsing. It means do not affect what was set in the map file, It is set necessary when a wfs post request is used with several query elements, with some having property names and some not*/ else if (strcasecmp(papszPropertyName[k], "!") == 0) { } else { msInsertHashTable(&(lp->metadata), "GML_INCLUDE_ITEMS", papszPropertyName[k]); /* exclude geometry if it was not asked for */ if (msOWSLookupMetadata(&(lp->metadata), "OFG", "geometries") != NULL) snprintf(szTmp, sizeof(szTmp), "%s", msOWSLookupMetadata(&(lp->metadata), "OFG", "geometries")); else snprintf(szTmp, sizeof(szTmp), OWS_GML_DEFAULT_GEOMETRY_NAME); if (strstr(papszPropertyName[k], szTmp) == NULL) msInsertHashTable(&(lp->metadata), "GML_GEOMETRIES", "none"); } } else /*empty string*/ msInsertHashTable(&(lp->metadata), "GML_GEOMETRIES", "none"); } } } } if (!bLayerFound) { /* Requested layer name was not in capabilities: * either it just doesn't exist */ msSetError(MS_WFSERR, "TYPENAME '%s' doesn't exist in this server. Please check the capabilities and reformulate your request.", "msWFSGetFeature()", layers[k]); return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion); } } } if (papszPropertyName && nPropertyNames > 0) { for (i=0; ipszOutputFormat) { /* We support only GML2 and GML3 for now. */ if(strcasecmp(paramsObj->pszOutputFormat, "GML2") == 0 || strcasecmp(paramsObj->pszOutputFormat, "text/xml; subtype=gml/2.1.2") == 0) { outputformat = OWS_GML2; gmlinfo.output_schema_format = "XMLSCHEMA"; output_mime_type = "text/xml; subtype=gml/2.1.2"; } else if(strcasecmp(paramsObj->pszOutputFormat, "GML3") == 0 || strcasecmp(paramsObj->pszOutputFormat, "text/xml; subtype=gml/3.1.1") == 0) { outputformat = OWS_GML3; gmlinfo.output_schema_format = "SFE_XMLSCHEMA"; output_mime_type = "text/xml; subtype=gml/3.1.1"; } else { const char *format_list; hashTableObj *md; /* validate selected format against all selected layers. */ for(j=0; j < map->numlayers; j++) { layerObj *lp; lp = GET_LAYER(map, j); if( lp->status != MS_ON ) continue; md = &(lp->metadata); format_list = msOWSLookupMetadata(md, "F","getfeature_formatlist"); if( format_list == NULL ) { md = &(map->web.metadata); format_list = msOWSLookupMetadata(md, "F","getfeature_formatlist"); } if (format_list) { psFormat = msOwsIsOutputFormatValid( map, paramsObj->pszOutputFormat, md, "F", "getfeature_formatlist"); } if (psFormat == NULL) { msSetError(MS_WFSERR, "'%s' is not a permitted output format for layer '%s', review wfs_getfeature_formatlist setting.", "msWFSGetFeature()", paramsObj->pszOutputFormat, lp->name ); return msWFSException(map, "outputformat", "InvalidParameterValue", paramsObj->pszVersion ); } if( psFormat->imagemode != MS_IMAGEMODE_FEATURE ) { msSetError(MS_WFSERR, "OUTPUTFORMAT '%s' does not have IMAGEMODE FEATURE, and is not permitted for WFS output.", "msWFSGetFeature()", paramsObj->pszOutputFormat ); return msWFSException( map, "outputformat", "InvalidParameterValue", paramsObj->pszVersion ); } } } /* If OUTPUTFORMAT not set, default to gml */ } else { /*set the output format using the version if available*/ if(paramsObj->pszVersion == NULL || strncmp(paramsObj->pszVersion,"1.1",3) == 0 ) { outputformat = OWS_GML3; gmlinfo.output_schema_format = "text/xml;%20subtype=gml/3.1.1"; output_mime_type = "text/xml; subtype=gml/3.1.1"; } } if(strncmp(paramsObj->pszVersion,"1.0",3) == 0 ) { output_mime_type = "text/xml"; } /* else if (strcasecmp(names[i], "PROPERTYNAME") == 0) */ /* { */ /* */ /* } */ tmpmaxfeatures = msOWSLookupMetadata(&(map->web.metadata), "FO", "maxfeatures"); if (tmpmaxfeatures) maxfeatures = atoi(tmpmaxfeatures); if (paramsObj->nMaxFeatures > 0) { if (maxfeatures < 0 || (maxfeatures > 0 && paramsObj->nMaxFeatures < maxfeatures)) maxfeatures = paramsObj->nMaxFeatures; } nQueriedLayers=0; for(j=0; jnumlayers; j++) { layerObj *lp; lp = GET_LAYER(map, j); if (lp->status == MS_ON) { /* No reason to handle tolerances for WFS GetFeature */ lp->tolerance = 0; lpQueried = GET_LAYER(map, j); nQueriedLayers++; } } if (paramsObj->nStartIndex > -1) { startindex = 1 + paramsObj->nStartIndex; map->query.startindex = startindex; } /* maxfeatures set */ if (maxfeatures > 0) { for(j=0; jnumlayers; j++) { layerObj *lp; lp = GET_LAYER(map, j); if (lp->status == MS_ON) { /*over-ride the value only if it is unset or wfs maxfeattures is lower that what is currently set*/ if (lp->maxfeatures <=0 || (lp->maxfeatures > 0 && maxfeatures < lp->maxfeatures)) lp->maxfeatures = maxfeatures; } } map->query.maxfeatures = maxfeatures; } /* startindex set */ if (startindex > 0 && nQueriedLayers > 1) { for(j=0; jnumlayers; j++) { layerObj *lp; lp = GET_LAYER(map, j); if (lp->status == MS_ON) { msLayerEnablePaging(lp, MS_FALSE); } } } else if (startindex > 0 && lpQueried) { lpQueried->startindex = startindex; } if (paramsObj->pszFilter) { bFilterSet = 1; pszFilter = paramsObj->pszFilter; } if (paramsObj->pszBbox) { char **tokens; int n; tokens = msStringSplit(paramsObj->pszBbox, ',', &n); if (tokens==NULL || (n != 4 && n !=5)) { msSetError(MS_WFSERR, "Wrong number of arguments for BBOX.", "msWFSGetFeature()"); return msWFSException(map, "bbox", "InvalidParameterValue", paramsObj->pszVersion); } bbox.minx = atof(tokens[0]); bbox.miny = atof(tokens[1]); bbox.maxx = atof(tokens[2]); bbox.maxy = atof(tokens[3]); /*5th aregument is assumed to be projection*/ if (n == 5) sBBoxSrs = msStrdup(tokens[4]); msFreeCharArray(tokens, n); bBBOXSet = 1; /* Note: BBOX SRS is implicit, it is the SRS of the selected */ /* feature types, see pszOutputSRS in TYPENAMES above. */ } if (paramsObj->pszFeatureId) { bFeatureIdSet = 1; } #ifdef USE_OGR if (bFilterSet && pszFilter && strlen(pszFilter) > 0) { char **tokens = NULL; int nFilters; FilterEncodingNode *psNode = NULL; int iLayerIndex =1; char **paszFilter = NULL; errorObj *ms_error; /* -------------------------------------------------------------------- */ /* Validate the parameters. When a FILTER parameter is given, */ /* It needs the TYPENAME parameter for the layers. Also Filter */ /* is Mutually exclusive with FEATUREID and BBOX (see wfs specs */ /* 1.0 section 13.7.3 on GetFeature) */ /* */ /* -------------------------------------------------------------------- */ if (gmlinfo.typename == NULL || strlen(gmlinfo.typename) <= 0 || layers == NULL || numlayers <= 0) { msSetError(MS_WFSERR, "Required TYPENAME parameter missing for GetFeature with a FILTER parameter.", "msWFSGetFeature()"); return msWFSException(map, "typename", "MissingParameterValue", paramsObj->pszVersion); } if (bBBOXSet) { msSetError(MS_WFSERR, "BBOX parameter and FILTER parameter are mutually exclusive in GetFeature.", "msWFSGetFeature()"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } if (bFeatureIdSet) { msSetError(MS_WFSERR, "FEATUREID parameter and FILTER parameter are mutually exclusive in GetFeature.", "msWFSGetFeature()"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } /* -------------------------------------------------------------------- */ /* Parse the Filter parameter. If there are several Filter */ /* parameters, each Filter is inside a parantheses. Eg : */ /* FILTER=( */ /* INWATERA_1M/WKB_GEOM|INWATERA_1M/WKB_GEOM */ /* 10,10 20,20*/ /* )( */ /* INWATERA_1M/WKB_GEOM10,10*/ /* 20,20) */ /* -------------------------------------------------------------------- */ nFilters = 0; if (strlen(pszFilter) > 0 && pszFilter[0] == '(') { tokens = msStringSplit(pszFilter+1, '(', &nFilters); if (tokens && nFilters > 0 && numlayers == nFilters) { paszFilter = (char **)msSmallMalloc(sizeof(char *)*nFilters); for (i=0; ipszVersion); } /* -------------------------------------------------------------------- */ /* run through the filters and build the class expressions. */ /* TODO: items may have namespace prefixes, or reference aliases, */ /* or groups. Need to be a bit more sophisticated here. */ /* -------------------------------------------------------------------- */ for (i=0; ipszVersion); } psNode = FLTParseFilterEncoding(paszFilter[i]); if (!psNode) { msSetError(MS_WFSERR, "Invalid or Unsupported FILTER in GetFeature : %s", "msWFSGetFeature()", pszFilter); return msWFSException(map, "filter", "InvalidParameterValue", paramsObj->pszVersion); } /*preparse the filter for gml aliases*/ FLTPreParseFilterForAlias(psNode, map, iLayerIndex, "G"); if (msWFSGetFeatureApplySRS(map, paramsObj->pszSrs, paramsObj->pszVersion) == MS_FAILURE) return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion); /* run filter. If no results are found, do not throw exception */ /* this is a null result */ if( FLTApplyFilterToLayer(psNode, map, iLayerIndex) != MS_SUCCESS ) { ms_error = msGetErrorObj(); if(ms_error->code != MS_NOTFOUND) { msSetError(MS_WFSERR, "FLTApplyFilterToLayer() failed", "msWFSGetFeature()"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } } FLTFreeFilterEncodingNode( psNode ); psNode = NULL; } if (paszFilter) free(paszFilter); }/* end if filter set */ if (bFeatureIdSet) { char **tokens = NULL, **tokens1=NULL ; int nTokens = 0, j=0, nTokens1=0, k=0; FilterEncodingNode *psNode = NULL; /* Keep only selected layers, set to OFF by default. */ for(j=0; jnumlayers; j++) { layerObj *lp; lp = GET_LAYER(map, j); lp->status = MS_OFF; } /*featureid can be a list INWATERA_1M.1234, INWATERA_1M.1235 We will keep all the feature id from the same layer together so that an OR would be applied if several of them are present */ tokens = msStringSplit(paramsObj->pszFeatureId, ',', &nTokens); iFIDLayers = 0; if (tokens && nTokens >=1) { aFIDLayers = (char **)msSmallMalloc(sizeof(char *)*nTokens); aFIDValues = (char **)msSmallMalloc(sizeof(char *)*nTokens); for (j=0; jpszVersion); } if (tokens1) msFreeCharArray(tokens1, nTokens1); } } if (tokens) msFreeCharArray(tokens, nTokens); /*turn on the layers and make sure projections are set properly*/ for (j=0; j< iFIDLayers; j++) { for (k=0; knumlayers; k++) { layerObj *lp; lp = GET_LAYER(map, k); if (msWFSIsLayerSupported(lp) && lp->name && strcasecmp(lp->name, aFIDLayers[j]) == 0) { lp->status = MS_ON; } if (msWFSGetFeatureApplySRS(map, paramsObj->pszSrs, paramsObj->pszVersion) == MS_FAILURE) return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion); } } for (j=0; j< iFIDLayers; j++) { for (k=0; knumlayers; k++) { layerObj *lp; lp = GET_LAYER(map, k); if (msWFSIsLayerSupported(lp) && lp->name && strcasecmp(lp->name, aFIDLayers[j]) == 0) { lp->status = MS_ON; if (lp->template == NULL) { /* Force setting a template to enable query. */ lp->template = msStrdup("ttt.html"); } psNode = FLTCreateFeatureIdFilterEncoding(aFIDValues[j]); if( FLTApplyFilterToLayer(psNode, map, lp->index) != MS_SUCCESS ) { msSetError(MS_WFSERR, "FLTApplyFilterToLayer() failed", "msWFSGetFeature"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } FLTFreeFilterEncodingNode( psNode ); psNode = NULL; break; } } if (k == map->numlayers) { /*layer not found*/ msSetError(MS_WFSERR, "Invalid typename given with FeatureId in GetFeature : %s. A layer might be disabled for \ this request. Check wfs/ows_enable_request settings.", "msWFSGetFeature()", aFIDLayers[j]); if (aFIDLayers && aFIDValues) { for (j=0; jpszVersion); } } if (aFIDLayers && aFIDValues) { for (j=0; jpszSrs, paramsObj->pszVersion) == MS_FAILURE) return msWFSException(map, "typename", "InvalidParameterValue", paramsObj->pszVersion); /* ** Perform Query (only BBOX for now) */ /* __TODO__ Using a rectangle query may not be the most efficient way */ /* to do things here. */ if (!bFilterSet && !bFeatureIdSet) { if (!bBBOXSet) { const char *pszMapSRS=NULL, *pszLayerSRS=NULL; bbox = map->extent; map->query.type = MS_QUERY_BY_RECT; /* setup the query */ map->query.mode = MS_QUERY_MULTIPLE; /*if srsName was given for wfs 1.1.0, It is at this point loaded into the map object and should be used*/ if(!paramsObj->pszSrs) pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_TRUE); for(j=0; jnumlayers; j++) { layerObj *lp; rectObj ext; int status; lp = GET_LAYER(map, j); if (lp->status == MS_ON) { if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) { if (pszMapSRS != NULL && strncmp(pszMapSRS, "EPSG:", 5) == 0) { if( msOWSParseVersionString(paramsObj->pszVersion) >= OWS_1_1_0 ) status = msLoadProjectionStringEPSG(&(map->projection), pszMapSRS); else status = msLoadProjectionString(&(map->projection), pszMapSRS); if (status != 0) { msSetError(MS_WFSERR, "msLoadProjectionString() failed: %s", "msWFSGetFeature()", pszMapSRS); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } } /*make sure that the layer projectsion is loaded. It could come from a ows/wfs_srs metadata*/ if (lp->projection.numargs == 0) { pszLayerSRS = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE); if (pszLayerSRS) { if (strncmp(pszLayerSRS, "EPSG:", 5) == 0) { if( msOWSParseVersionString(paramsObj->pszVersion) >= OWS_1_1_0 ) msLoadProjectionStringEPSG(&(lp->projection), pszLayerSRS); else msLoadProjectionString(&(lp->projection), pszLayerSRS); } } } if (msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) { msProjectRect(&lp->projection, &map->projection, &(ext)); } bbox = ext; } map->query.rect = bbox; map->query.layer = j; if(msQueryByRect(map) != MS_SUCCESS) { errorObj *ms_error; ms_error = msGetErrorObj(); if(ms_error->code != MS_NOTFOUND) { msSetError(MS_WFSERR, "ms_error->code not found", "msWFSGetFeature()"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } } } } } else { if (sBBoxSrs) { int status; projectionObj sProjTmp; msInitProjection(&sProjTmp); /*do the axis order for now. It is unclear if the bbox are expected ro respect the axis oder defined in the projectsion #3296*/ if(strncmp(paramsObj->pszVersion,"1.1",3) == 0) { if ((status=msLoadProjectionStringEPSG(&sProjTmp, sBBoxSrs)) == 0) { msAxisNormalizePoints( &sProjTmp, 1, &bbox.minx, &bbox.miny ); msAxisNormalizePoints( &sProjTmp, 1, &bbox.maxx, &bbox.maxy ); } } else status = msLoadProjectionString(&sProjTmp, sBBoxSrs); if (status == 0 && map->projection.numargs > 0) msProjectRect(&sProjTmp, &map->projection, &bbox); msFree(sBBoxSrs); } map->query.type = MS_QUERY_BY_RECT; /* setup the query */ map->query.mode = MS_QUERY_MULTIPLE; map->query.rect = bbox; if(msQueryByRect(map) != MS_SUCCESS) { errorObj *ms_error; ms_error = msGetErrorObj(); if(ms_error->code != MS_NOTFOUND) { msSetError(MS_WFSERR, "ms_error->code not found", "msWFSGetFeature()"); return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); } } } } /* if no results where written (TODO: this needs to be GML2/3 specific I imagine */ for(j=0; jnumlayers; j++) { if (GET_LAYER(map, j)->resultcache && GET_LAYER(map, j)->resultcache->numresults > 0) { iNumberOfFeatures += GET_LAYER(map, j)->resultcache->numresults; } } /* ** GML Header generation. */ status = MS_SUCCESS; if( psFormat == NULL ) { value = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (value) msIO_setHeader("Content-Type","%s; charset=%s", output_mime_type,value); else msIO_setHeader("Content-Type","%s",output_mime_type); msIO_sendHeaders(); status = msWFSGetFeature_GMLPreamble( map, req, &gmlinfo, paramsObj, outputformat, iResultTypeHits, iNumberOfFeatures ); if(status != MS_SUCCESS) { return MS_FAILURE; } } /* handle case of maxfeatures = 0 */ /*internally use a start index that start with 0 as the first index*/ if( psFormat == NULL ) { if(maxfeatures != 0 && iResultTypeHits == 0) status = msGMLWriteWFSQuery(map, stdout, (char *) gmlinfo.user_namespace_prefix, outputformat); } else { mapservObj *mapserv = msAllocMapServObj(); /* Setup dummy mapserv object */ mapserv->sendheaders = MS_TRUE; mapserv->map = map; msFreeCgiObj(mapserv->request); mapserv->request = req; map->querymap.status = MS_FALSE; status = msReturnTemplateQuery( mapserv, psFormat->name, NULL ); mapserv->request = NULL; mapserv->map = NULL; msFreeMapServObj( mapserv ); if( status != MS_SUCCESS ) { return msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion ); } } if( psFormat == NULL && status == MS_SUCCESS ) { msWFSGetFeature_GMLPostfix( map, req, &gmlinfo, paramsObj, outputformat, maxfeatures, iResultTypeHits, iNumberOfFeatures ); } /* ** Done! Now a bit of clean-up. */ return status; } #endif /* USE_WFS_SVR */ /* ** msWFSDispatch() is the entry point for WFS requests. ** - If this is a valid request then it is processed and MS_SUCCESS is returned ** on success, or MS_FAILURE on failure. ** - If this does not appear to be a valid WFS request then MS_DONE ** is returned and MapServer is expected to process this as a regular ** MapServer request. */ int msWFSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request, int force_wfs_mode) { #ifdef USE_WFS_SVR int status; int returnvalue = MS_DONE; /* static char *wmtver = NULL, *request=NULL, *service=NULL; */ wfsParamsObj *paramsObj; /* ** Populate the Params object based on the request */ paramsObj = msWFSCreateParamsObj(); /* TODO : store also parameters that are inside the map object */ /* into the paramsObj. */ if (msWFSParseRequest(map, requestobj, ows_request, paramsObj, force_wfs_mode) == MS_FAILURE) return msWFSException(map, "request", "InvalidRequest", NULL); if (force_wfs_mode) { /*request is always required*/ if (paramsObj->pszRequest==NULL || strlen(paramsObj->pszRequest)<=0) { msSetError(MS_WFSERR, "Incomplete WFS request: REQUEST parameter missing", "msWFSDispatch()"); returnvalue = msWFSException(map, "request", "MissingParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } /*version: wfs 1.0 and 1.1.0 POST request: optional wfs 1.0 and 1.1.0 GET request: optional for getcapabilities and required for describefeatute and getfeature */ if (paramsObj->pszVersion == NULL && requestobj && requestobj->postrequest == MS_FALSE && strcasecmp(paramsObj->pszRequest, "GetCapabilities") != 0) { msSetError(MS_WFSERR, "Invalid WFS request: VERSION parameter missing", "msWFSDispatch()"); returnvalue = msWFSException(map, "version", "MissingParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } if (paramsObj->pszVersion == NULL || strlen(paramsObj->pszVersion) <=0) paramsObj->pszVersion = msStrdup("1.1.0"); /*service wfs 1.0 and 1.1.0 GET: required and should be set to WFS wfs 1.0 POST: required wfs 1.1.1 POST: optional */ if ((paramsObj->pszService == NULL || strlen(paramsObj->pszService) == 0) && ((requestobj && requestobj->postrequest == MS_FALSE) || strcasecmp(paramsObj->pszVersion,"1.0") ==0)) { msSetError(MS_WFSERR, "Invalid WFS request: Missing SERVICE parameter", "msWFSDispatch()"); returnvalue = msWFSException(map, "service", "MissingParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } if (paramsObj->pszService == NULL || strlen(paramsObj->pszService) == 0) paramsObj->pszService = msStrdup("WFS"); if (paramsObj->pszService!=NULL && strcasecmp(paramsObj->pszService, "WFS") != 0) { msSetError(MS_WFSERR, "Invalid WFS request: SERVICE parameter must be set to WFS", "msWFSDispatch()"); returnvalue = msWFSException(map, "service", "InvalidParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } if (paramsObj->pszService == NULL && strcasecmp(paramsObj->pszVersion, "1.0") == 0) { msSetError(MS_WFSERR, "Invalid WFS request: SERVICE parameter missing", "msWFSDispatch()"); returnvalue = msWFSException(map, "service", "MissingParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } } /* If SERVICE is specified then it MUST be "WFS" */ if (paramsObj->pszService != NULL && strcasecmp(paramsObj->pszService, "WFS") != 0) { msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return MS_DONE; /* Not a WFS request */ } /* If SERVICE, VERSION and REQUEST not included than this isn't a WFS req*/ if (paramsObj->pszService == NULL && paramsObj->pszVersion==NULL && paramsObj->pszRequest==NULL) { msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return MS_DONE; /* Not a WFS request */ } /* VERSION *and* REQUEST *and* SERVICE required by all WFS requests including * GetCapabilities. */ if (paramsObj->pszVersion==NULL || strlen(paramsObj->pszVersion)<=0) { msSetError(MS_WFSERR, "Incomplete WFS request: VERSION parameter missing", "msWFSDispatch()"); returnvalue = msWFSException11(map, "version", "MissingParameterValue", "1.1.0"); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } if (paramsObj->pszRequest==NULL || strlen(paramsObj->pszRequest)<=0) { msSetError(MS_WFSERR, "Incomplete WFS request: REQUEST parameter missing", "msWFSDispatch()"); returnvalue = msWFSException(map, "request", "MissingParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } if (paramsObj->pszService==NULL || strlen(paramsObj->pszService)<=0) { msSetError(MS_WFSERR, "Incomplete WFS request: SERVICE parameter missing", "msWFSDispatch()"); returnvalue = msWFSException(map, "service", "MissingParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } if ((status = msOWSMakeAllLayersUnique(map)) != MS_SUCCESS) { msSetError(MS_WFSERR, "msOWSMakeAllLayersUnique() failed", "msWFSDispatch()"); returnvalue = msWFSException(map, "mapserv", "NoApplicableCode", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } /* ** Start dispatching requests */ if (strcasecmp(paramsObj->pszRequest, "GetCapabilities") == 0 ) { msOWSRequestLayersEnabled(map, "F", paramsObj->pszRequest, ows_request); if (ows_request->numlayers == 0) { msSetError(MS_WFSERR, "WFS request not enabled. Check wfs/ows_enable_request settings.", "msWFSDispatch()"); returnvalue = msWFSException(map, "request", "InvalidParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } returnvalue = msWFSGetCapabilities(map, paramsObj, requestobj, ows_request); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } /* ** Validate VERSION against the versions that we support... we don't do this ** for GetCapabilities in order to allow version negociation. */ if (strcmp(paramsObj->pszVersion, "1.0.0") != 0 && strcmp(paramsObj->pszVersion, "1.1.0") != 0) { msSetError(MS_WFSERR, "WFS Server does not support VERSION %s.", "msWFSDispatch()", paramsObj->pszVersion); returnvalue = msWFSException11(map, "version", "InvalidParameterValue","1.1.0"); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } /* Since the function can still return MS_DONE, we add an extra service check to not call msOWSRequestLayersEnabled twice */ if (strcasecmp(paramsObj->pszService, "WFS") == 0) { msOWSRequestLayersEnabled(map, "F", paramsObj->pszRequest, ows_request); if (ows_request->numlayers == 0) { msSetError(MS_WFSERR, "WFS request not enabled. Check wfs/ows_enable_request settings.", "msWFSDispatch()"); returnvalue = msWFSException(map, "request", "InvalidParameterValue", paramsObj->pszVersion); msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } } returnvalue = MS_DONE; /* Continue dispatching... */ if (strcasecmp(paramsObj->pszRequest, "DescribeFeatureType") == 0) returnvalue = msWFSDescribeFeatureType(map, paramsObj, ows_request); else if (strcasecmp(paramsObj->pszRequest, "GetFeature") == 0) returnvalue = msWFSGetFeature(map, paramsObj, requestobj, ows_request); else if (strcasecmp(paramsObj->pszRequest, "GetFeatureWithLock") == 0 || strcasecmp(paramsObj->pszRequest, "LockFeature") == 0 || strcasecmp(paramsObj->pszRequest, "Transaction") == 0 ) { /* Unsupported WFS request */ msSetError(MS_WFSERR, "Unsupported WFS request: %s", "msWFSDispatch()", paramsObj->pszRequest); returnvalue = msWFSException(map, "request", "InvalidParameterValue", paramsObj->pszVersion); } else if (strcasecmp(paramsObj->pszService, "WFS") == 0) { /* Invalid WFS request */ msSetError(MS_WFSERR, "Invalid WFS request: %s", "msWFSDispatch()", paramsObj->pszRequest); returnvalue = msWFSException(map, "request", "InvalidParameterValue", paramsObj->pszVersion); } /* This was not detected as a WFS request... let MapServer handle it */ msWFSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; #else msSetError(MS_WFSERR, "WFS server support is not available.", "msWFSDispatch()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msWFSCreateParamsObj */ /* */ /* Create a parameter object, initialize it. */ /* The caller should free the object using msWFSFreeParamsObj. */ /************************************************************************/ wfsParamsObj *msWFSCreateParamsObj() { wfsParamsObj *paramsObj = (wfsParamsObj *)calloc(1, sizeof(wfsParamsObj)); MS_CHECK_ALLOC(paramsObj, sizeof(wfsParamsObj), NULL); paramsObj->nMaxFeatures = -1; paramsObj->nStartIndex = -1; return paramsObj; } /************************************************************************/ /* msWFSFreeParmsObj */ /* */ /* Free params object. */ /************************************************************************/ void msWFSFreeParamsObj(wfsParamsObj *wfsparams) { if (wfsparams) { free(wfsparams->pszVersion); free(wfsparams->pszUpdateSequence); free(wfsparams->pszRequest); free(wfsparams->pszService); free(wfsparams->pszTypeName); free(wfsparams->pszFilter); free(wfsparams->pszBbox); free(wfsparams->pszGeometryName); free(wfsparams->pszOutputFormat); free(wfsparams->pszFeatureId); free(wfsparams->pszSrs); free(wfsparams->pszResultType); free(wfsparams->pszPropertyName); free(wfsparams->pszAcceptVersions); } } const char *msWFSGetDefaultVersion(mapObj *map) { if (msOWSLookupMetadata(&(map->web.metadata), "F", "getcapabilities_version")) return msOWSLookupMetadata(&(map->web.metadata), "F", "getcapabilities_version"); else return "1.1.0"; } /************************************************************************/ /* msWFSParseRequest */ /* */ /* Parse request into the params object. */ /************************************************************************/ int msWFSParseRequest(mapObj *map, cgiRequestObj *request, owsRequestObj *ows_request, wfsParamsObj *wfsparams, int force_wfs_mode) { #ifdef USE_WFS_SVR int i = 0; if (!request || !wfsparams) return MS_FAILURE; if (request->NumParams > 0) { for(i=0; iNumParams; i++) { if (request->ParamNames[i] && request->ParamValues[i]) { if (strcasecmp(request->ParamNames[i], "VERSION") == 0) wfsparams->pszVersion = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "UPDATESEQUENCE") == 0) wfsparams->pszUpdateSequence = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "REQUEST") == 0) wfsparams->pszRequest = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "SERVICE") == 0) wfsparams->pszService = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "MAXFEATURES") == 0) wfsparams->nMaxFeatures = atoi(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "STARTINDEX") == 0) wfsparams->nStartIndex = atoi(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "BBOX") == 0) wfsparams->pszBbox = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "SRSNAME") == 0) wfsparams->pszSrs = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESULTTYPE") == 0) wfsparams->pszResultType = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "TYPENAME") == 0) wfsparams->pszTypeName = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "FILTER") == 0) wfsparams->pszFilter = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OUTPUTFORMAT") == 0) wfsparams->pszOutputFormat = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "FEATUREID") == 0) wfsparams->pszFeatureId = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "PROPERTYNAME") == 0) wfsparams->pszPropertyName = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "ACCEPTVERSIONS") == 0) wfsparams->pszAcceptVersions = msStrdup(request->ParamValues[i]); } } /* version is optional is the GetCapabilities. If not */ /* provided, set it. Default it to 1.1.0*/ if (wfsparams->pszVersion == NULL && wfsparams->pszRequest && strcasecmp(wfsparams->pszRequest, "GetCapabilities") == 0) { wfsparams->pszVersion = msStrdup(msWFSGetDefaultVersion(map)); } } /* -------------------------------------------------------------------- */ /* Parse the post request. It is assumed to be an XML document. */ /* -------------------------------------------------------------------- */ #ifdef USE_OGR if (request->postrequest) { #ifdef WFS_USE_LIBXML2 xmlDocPtr doc; xmlNodePtr rootnode, node, node1; char *schema_file =NULL; const char *schema_location=NULL, *validate=NULL; const char *pszValue=NULL; char *pszTmp=NULL; char *pszLayerPropertyName=NULL, *pszLayerFilter=NULL; /* xmlXPathAxisFunc */ /* load document */ doc = xmlParseDoc((xmlChar *)request->postrequest); if (doc == NULL || (rootnode = xmlDocGetRootElement(doc)) == NULL) { msSetError(MS_WFSERR, "Invalid POST request. XML is not well-formed", "msWFSParseRequest()"); return MS_FAILURE; } /*get the request*/ if (strcasecmp(rootnode->name, "GetCapabilities") == 0) wfsparams->pszRequest = "GetCapabilities"; else if (strcasecmp(rootnode->name, "GetFeature") == 0) wfsparams->pszRequest = "GetFeature"; else if (strcasecmp(rootnode->name, "DescribeFeatureType") == 0) wfsparams->pszRequest = "DescribeFeatureType"; msOWSRequestLayersEnabled(map, "F", wfsparams->pszRequest, ows_request); if (wfsparams->pszRequest == NULL) { /* Unsupported WFS request */ msSetError(MS_WFSERR, "Unsupported WFS request.", "msWFSParseRequest()"); return MS_FAILURE; } if (ows_request->numlayers == 0) { /* not enabled WFS request */ msSetError(MS_WFSERR, "WFS request not enabled. Check wfs/ows_enable_request settings.", "msWFSParseRequest()"); return MS_FAILURE; } /*get version and service if available*/ pszValue = xmlGetProp(rootnode, (xmlChar *)"version"); if (pszValue) wfsparams->pszVersion = msStrdup(pszValue); pszValue = xmlGetProp(rootnode, (xmlChar *)"service"); if (pszValue) wfsparams->pszService = msStrdup(pszValue); /* version is optional for the GetCapabilities. If not provided, set it*/ if (wfsparams->pszVersion == NULL && strcmp(wfsparams->pszRequest,"GetCapabilities") == 0) { wfsparams->pszVersion = msStrdup(msWFSGetDefaultVersion(map)); } /*do we validate the xml ?*/ validate = msOWSLookupMetadata(&(map->web.metadata), "FO", "validate_xml"); if (validate && strcasecmp(validate, "true") == 0 && (schema_location = msOWSLookupMetadata(&(map->web.metadata), "FO", "schemas_dir"))) { if ((wfsparams->pszService && strcmp(wfsparams->pszService, "WFS") == 0) || force_wfs_mode) { schema_file = msStringConcatenate(schema_file, schema_location); if (wfsparams->pszVersion == NULL || strncasecmp(wfsparams->pszVersion, "1.1", 3) ==0) { schema_file = msStringConcatenate(schema_file, "wfs/1.1.0/wfs.xsd"); if (msOWSSchemaValidation(schema_file, request->postrequest) != 0) { msSetError(MS_WFSERR, "Invalid POST request. XML is not valid", "msWFSParseRequest()"); return MS_FAILURE; } } } } /*parse describefeature*/ if (strcmp(wfsparams->pszRequest,"DescribeFeatureType") == 0) { /*look for TypeName and outputFormat*/ for (node = rootnode->children; node; node = node->next) { if (node->type != XML_ELEMENT_NODE) continue; if (strcmp(node->name, "TypeName") == 0) { pszValue = xmlNodeGetContent(node); if (wfsparams->pszTypeName == NULL) wfsparams->pszTypeName = msStrdup(pszValue); else { wfsparams->pszTypeName = msStringConcatenate(wfsparams->pszTypeName, ","); wfsparams->pszTypeName = msStringConcatenate(wfsparams->pszTypeName, pszValue); } } } pszValue = xmlGetProp(rootnode, (xmlChar *)"outputFormat"); if (pszValue) wfsparams->pszOutputFormat = msStrdup(pszValue); } /*parse GetFeature*/ if (strcmp(wfsparams->pszRequest,"GetFeature") == 0) { pszValue = xmlGetProp(rootnode, (xmlChar *)"resultType"); if (pszValue) wfsparams->pszResultType = msStrdup(pszValue); pszValue = xmlGetProp(rootnode, (xmlChar *)"maxFeatures"); if (pszValue) wfsparams->nMaxFeatures = atoi(pszValue); pszValue = xmlGetProp(rootnode, (xmlChar *)"startIndex"); if (pszValue) wfsparams->nStartIndex = atoi(pszValue); pszValue = xmlGetProp(rootnode, (xmlChar *)"outputFormat"); if (pszValue) wfsparams->pszOutputFormat = msStrdup(pszValue); /* free typename and filter. There may have been */ /* values if they were passed in the URL */ if (wfsparams->pszTypeName) free(wfsparams->pszTypeName); wfsparams->pszTypeName = NULL; if (wfsparams->pszFilter) free(wfsparams->pszFilter); wfsparams->pszFilter = NULL; for (node = rootnode->children; node; node = node->next) { if (node->type != XML_ELEMENT_NODE) continue; if (strcmp(node->name, "Query") == 0) { /* get SRS: TODO support srs per layer. Now we only have one srs that applies to al layers*/ pszValue = xmlGetProp(node, (xmlChar *)"srsName"); if (pszValue) { if (wfsparams->pszSrs ) msFree( wfsparams->pszSrs); wfsparams->pszSrs = msStrdup(pszValue); } /*type name*/ pszValue = xmlGetProp(node, (xmlChar *)"typeName"); if (pszValue) { if (wfsparams->pszTypeName == NULL) wfsparams->pszTypeName = msStrdup(pszValue); else { wfsparams->pszTypeName = msStringConcatenate(wfsparams->pszTypeName, ","); wfsparams->pszTypeName = msStringConcatenate(wfsparams->pszTypeName, pszValue); } } /*PropertyName and Filter*/ pszLayerPropertyName = NULL; pszLayerFilter = NULL; for (node1 = node->children; node1; node1 = node1->next) { if (node1->type != XML_ELEMENT_NODE) continue; if (strcmp(node1->name, "PropertyName") == 0) { pszValue = xmlNodeGetContent(node1); if (pszLayerPropertyName == NULL) pszLayerPropertyName = msStrdup(pszValue); else { pszLayerPropertyName= msStringConcatenate(pszLayerPropertyName, ","); pszLayerPropertyName = msStringConcatenate(pszLayerPropertyName, pszValue); } } if (strcmp(node1->name, "Filter") == 0) { pszValue = xmlNodeGetContent(node1); if (pszValue) { xmlBufferPtr buffer; pszTmp = NULL; buffer = xmlBufferCreate(); xmlNodeDump(buffer, node1->doc, node1, 0, 0); pszTmp = msStringConcatenate(pszTmp, "("); pszTmp = msStringConcatenate(pszTmp, buffer->content); pszTmp = msStringConcatenate(pszTmp, ")"); xmlBufferFree(buffer); wfsparams->pszFilter = msStringConcatenate(wfsparams->pszFilter,pszTmp); msFree(pszTmp); } } } pszTmp = NULL; if (pszLayerPropertyName == NULL) pszTmp = msStrdup("(!)"); else { pszTmp = msStringConcatenate(pszTmp, "("); pszTmp = msStringConcatenate(pszTmp, pszLayerPropertyName); pszTmp = msStringConcatenate(pszTmp, ")"); msFree(pszLayerPropertyName); } wfsparams->pszPropertyName = msStringConcatenate(wfsparams->pszPropertyName, pszTmp); msFree(pszTmp); }/*Query node*/ } } /* check for request */ /* only works??? if psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/wfs:GetCapabilities|/GetCapabilities"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/GetCapabilities"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/wfs:GetCapabilities"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"GetCapabilities"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"//GetCapabilities"); */ #else /*#ifdef WFS_USE_LIBXML2*/ CPLXMLNode *psRoot, *psQuery, *psFilter, *psTypeName, *psPropertyName = NULL; CPLXMLNode *psGetFeature = NULL; CPLXMLNode *psGetCapabilities = NULL; CPLXMLNode *psDescribeFeature = NULL; CPLXMLNode *psOperation = NULL; const char *pszValue; char *pszSerializedFilter, *pszTmp, *pszTmp2 = NULL; int bMultiLayer = 0; psRoot = CPLParseXMLString(request->postrequest); if(map->debug == MS_DEBUGLEVEL_VVV) { msDebug("msWFSParseRequest(): WFS post request: %s\n", request->postrequest); } if (psRoot) { /* need to strip namespaces */ CPLStripXMLNamespace(psRoot, NULL, 1); for( psOperation = psRoot; psOperation != NULL; psOperation = psOperation->psNext ) { if(psOperation->eType == CXT_Element) { if(strcasecmp(psOperation->pszValue,"GetFeature")==0) { psGetFeature = psOperation; break; } else if(strcasecmp(psOperation->pszValue,"GetCapabilities")==0) { psGetCapabilities = psOperation; pszValue = CPLGetXMLValue(psGetFeature, "updateSequence", NULL); if (pszValue) wfsparams->pszUpdateSequence = msStrdup(pszValue); break; } else if(strcasecmp(psOperation->pszValue, "DescribeFeatureType")==0) { psDescribeFeature = psOperation; break; } /* these are unsupported requests. Just set the */ /* request value and return; */ else if (strcasecmp(psOperation->pszValue, "GetFeatureWithLock") == 0) { wfsparams->pszRequest = msStrdup("GetFeatureWithLock"); break; } else if (strcasecmp(psOperation->pszValue, "LockFeature") == 0) { wfsparams->pszRequest = msStrdup("LockFeature"); break; } else if (strcasecmp(psOperation->pszValue, "Transaction") == 0) { wfsparams->pszRequest = msStrdup("Transaction"); break; } } } /* -------------------------------------------------------------------- */ /* Parse the GetFeature */ /* -------------------------------------------------------------------- */ if (psGetFeature) { wfsparams->pszRequest = msStrdup("GetFeature"); pszValue = CPLGetXMLValue(psGetFeature, "version", NULL); if (pszValue) wfsparams->pszVersion = msStrdup(pszValue); pszValue = CPLGetXMLValue(psGetFeature, "service", NULL); if (pszValue) wfsparams->pszService = msStrdup(pszValue); pszValue = CPLGetXMLValue(psGetFeature, "resultType", NULL); if (pszValue) wfsparams->pszResultType = msStrdup(pszValue); pszValue = CPLGetXMLValue(psGetFeature, "maxFeatures", NULL); if (pszValue) wfsparams->nMaxFeatures = atoi(pszValue); pszValue = CPLGetXMLValue(psGetFeature, "startIndex", NULL); if (pszValue) wfsparams->nStartIndex = atoi(pszValue); pszValue = CPLGetXMLValue(psGetFeature, "outputFormat", NULL); if (pszValue) wfsparams->pszOutputFormat = msStrdup(pszValue); psQuery = CPLGetXMLNode(psGetFeature, "Query"); if (psQuery) { /* free typname and filter. There may have been */ /* values if they were passed in the URL */ if (wfsparams->pszTypeName) free(wfsparams->pszTypeName); wfsparams->pszTypeName = NULL; if (wfsparams->pszFilter) free(wfsparams->pszFilter); wfsparams->pszFilter = NULL; if (psQuery->psNext && psQuery->psNext->pszValue && strcasecmp(psQuery->psNext->pszValue, "Query") == 0) bMultiLayer = 1; /* -------------------------------------------------------------------- */ /* Parse typenames and filters. If there are multiple queries, */ /* typenames will be build with comma between thme */ /* (typename1,typename2,...) and filters will be build with */ /* bracets enclosinf the filters :(filter1)(filter2)... */ /* propertynames are stored like (property1,property2)(property1) */ /* -------------------------------------------------------------------- */ while (psQuery && psQuery->pszValue && strcasecmp(psQuery->pszValue, "Query") == 0) { /* get SRS */ pszValue = CPLGetXMLValue(psQuery, "srsName", NULL); if (pszValue) wfsparams->pszSrs = msStrdup(pszValue); /* parse typenames */ pszValue = CPLGetXMLValue(psQuery, "typename", NULL); if (pszValue) { if (wfsparams->pszTypeName == NULL) wfsparams->pszTypeName = msStrdup(pszValue); else { pszTmp = msStrdup(wfsparams->pszTypeName); wfsparams->pszTypeName = (char *)msSmallRealloc(wfsparams->pszTypeName, sizeof(char)* (strlen(pszTmp)+ strlen(pszValue)+2)); sprintf(wfsparams->pszTypeName,"%s,%s",pszTmp, pszValue); free(pszTmp); } } /*parse property name*/ psPropertyName = CPLGetXMLNode(psQuery, "PropertyName"); pszTmp2= NULL; /*when there is no PropertyName, we outpout (!) so that it is parsed properly in GetFeature*/ if (psPropertyName == NULL) pszTmp2 = msStrdup("!"); while (psPropertyName) { if (!psPropertyName->pszValue || strcasecmp(psPropertyName->pszValue, "PropertyName") != 0) { psPropertyName = psPropertyName->psNext; continue; } pszValue = CPLGetXMLValue(psPropertyName, NULL, NULL); if (pszTmp2 == NULL) { pszTmp2 = msStrdup(pszValue); } else { pszTmp = msStrdup(pszTmp2); pszTmp2 = (char *)msSmallRealloc(pszTmp2, sizeof(char)* (strlen(pszTmp)+ strlen(pszValue)+2)); sprintf(pszTmp2,"%s,%s",pszTmp, pszValue); msFree(pszTmp); } psPropertyName = psPropertyName->psNext; } if (pszTmp2) { pszTmp = msStrdup(pszTmp2); pszTmp2 = (char *)msSmallRealloc(pszTmp2, sizeof(char)* (strlen(pszTmp)+ 3)); sprintf(pszTmp2,"(%s)", pszTmp); msFree(pszTmp); if (wfsparams->pszPropertyName == NULL) wfsparams->pszPropertyName = msStrdup(pszTmp2); else { pszTmp = msStrdup(wfsparams->pszPropertyName); wfsparams->pszPropertyName = (char *)msSmallRealloc(wfsparams->pszPropertyName, sizeof(char)*(strlen(pszTmp)+ strlen(pszTmp2)+1)); sprintf(wfsparams->pszPropertyName,"%s%s",wfsparams->pszPropertyName, pszTmp2); msFree(pszTmp); } msFree(pszTmp2); pszTmp2 = NULL; } /* parse filter */ psFilter = CPLGetXMLNode(psQuery, "Filter"); if (psFilter) { if (!bMultiLayer) { char* pszCPLTmp = CPLSerializeXMLTree(psFilter); wfsparams->pszFilter = msStrdup(pszCPLTmp); CPLFree(pszCPLTmp); } else { pszSerializedFilter = CPLSerializeXMLTree(psFilter); pszTmp = (char *)msSmallMalloc(sizeof(char)* (strlen(pszSerializedFilter)+3)); sprintf(pszTmp, "(%s)", pszSerializedFilter); CPLFree(pszSerializedFilter); if (wfsparams->pszFilter == NULL) wfsparams->pszFilter = msStrdup(pszTmp); else { pszSerializedFilter = msStrdup(wfsparams->pszFilter); wfsparams->pszFilter = (char *)msSmallRealloc(wfsparams->pszFilter, sizeof(char)* (strlen(pszSerializedFilter)+ strlen(pszTmp)+1)); sprintf(wfsparams->pszFilter, "%s%s", pszSerializedFilter, pszTmp); free(pszSerializedFilter); } free(pszTmp); } } psQuery = psQuery->psNext; }/* while psQuery */ } }/* end of GetFeatures */ /* -------------------------------------------------------------------- */ /* Parse GetCapabilities. */ /* -------------------------------------------------------------------- */ if (psGetCapabilities) { wfsparams->pszRequest = msStrdup("GetCapabilities"); pszValue = CPLGetXMLValue(psGetCapabilities, "version", NULL); /* version is optional for the GetCapabilities. If not */ /* provided, set it. */ if (pszValue) wfsparams->pszVersion = msStrdup(pszValue); else wfsparams->pszVersion = msStrdup(msStrdup(msWFSGetDefaultVersion(map))); pszValue = CPLGetXMLValue(psGetCapabilities, "service", NULL); if (pszValue) wfsparams->pszService = msStrdup(pszValue); }/* end of GetCapabilites */ /* -------------------------------------------------------------------- */ /* Parse DescribeFeatureType */ /* -------------------------------------------------------------------- */ if (psDescribeFeature) { wfsparams->pszRequest = msStrdup("DescribeFeatureType"); pszValue = CPLGetXMLValue(psDescribeFeature, "version", NULL); if (pszValue) wfsparams->pszVersion = msStrdup(pszValue); pszValue = CPLGetXMLValue(psDescribeFeature, "service", NULL); if (pszValue) wfsparams->pszService = msStrdup(pszValue); pszValue = CPLGetXMLValue(psDescribeFeature, "outputFormat", NULL); if (pszValue) wfsparams->pszOutputFormat = msStrdup(pszValue); psTypeName = CPLGetXMLNode(psDescribeFeature, "TypeName"); if (psTypeName) { /* free typname and filter. There may have been */ /* values if they were passed in the URL */ if (wfsparams->pszTypeName) free(wfsparams->pszTypeName); wfsparams->pszTypeName = NULL; while (psTypeName && psTypeName->pszValue && strcasecmp(psTypeName->pszValue, "TypeName") == 0) { if (psTypeName->psChild && psTypeName->psChild->pszValue) { pszValue = psTypeName->psChild->pszValue; if (wfsparams->pszTypeName == NULL) wfsparams->pszTypeName = msStrdup(pszValue); else { pszTmp = msStrdup(wfsparams->pszTypeName); wfsparams->pszTypeName = (char *)msSmallRealloc(wfsparams->pszTypeName, sizeof(char)* (strlen(pszTmp)+ strlen(pszValue)+2)); sprintf(wfsparams->pszTypeName,"%s,%s",pszTmp, pszValue); free(pszTmp); } } psTypeName = psTypeName->psNext; } } }/* end of DescibeFeatureType */ } #endif /*WFS_USE_LIBXML2*/ } #endif #endif return MS_SUCCESS; } mapserver-6.4.1/testcopy.c0000644002461700001440000000527112261257215015337 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Test of msCopyMap() * Author: Sean Gilles * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" void printAtts(mapObj*, const char*); int main(int argc, char *argv[]) { mapObj *original_map, *clone_map; /* --------------------------------------------------------------------- * Test 1: free original before freeing clone * --------------------------------------------------------------------- */ /* Load map file */ original_map = msLoadMap("tests/test.map", NULL); if (original_map == NULL) { /* Write errors */ msWriteError(stderr); msResetErrorList(); exit(0); } /* Dump out some attributes */ printAtts(original_map, "Original"); /* Clone it */ clone_map = msNewMapObj(); msCopyMap(clone_map, original_map); /* Write errors */ msWriteError(stderr); msResetErrorList(); /* Free */ msFreeMap(original_map); /* Dump clone's attributes */ printAtts(clone_map, "Clone"); /* Free clone */ msFreeMap(clone_map); exit(0); } void printAtts(mapObj *map, const char *title) { printf("\n%s Attributes\n----------------------\n", title); printf("Map Name: %s\n", map->name); printf("Numlayers: %d\n", map->numlayers); printf("Map Fontset Filename: %s\n", map->fontset.filename); printf("Map Symbolset Filename: %s\n", map->symbolset.filename); } mapserver-6.4.1/mapfile.h0000644002461700001440000001563512261257215015114 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Keyword definitions for the mapfiles and symbolfiles. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPFILE_H #define MAPFILE_H enum MS_LEXER_STATES {MS_TOKENIZE_DEFAULT=0, MS_TOKENIZE_FILE, MS_TOKENIZE_STRING, MS_TOKENIZE_EXPRESSION, MS_TOKENIZE_URL_VARIABLE, MS_TOKENIZE_URL_STRING, MS_TOKENIZE_VALUE, MS_TOKENIZE_NAME}; enum MS_TOKEN_SOURCES {MS_FILE_TOKENS=0, MS_STRING_TOKENS, MS_URL_TOKENS}; /* ** Keyword definitions for the mapfiles and symbolfiles (used by lexer) */ #define ANGLE 1000 #define ANTIALIAS 1001 #define BACKGROUNDCOLOR 1002 #define BUFFER 1003 #define CLASS 1004 #define CLASSITEM 1005 #define COLOR 1006 #define DATA 1007 #define DD 1008 #define EMPTY 1010 #define END 1011 #define ERROR 1012 #define EXPRESSION 1013 #define EXTENT 1014 #define FEATURE 1015 #define FILLED 1016 #define FOOTER 1017 #define FONT 1018 #define FONTSET 1019 #define FROM 1020 #define GROUP 1021 #define HEADER 1022 #define IMAGE 1023 #define IMAGECOLOR 1024 #define IMAGEPATH 1025 #define IMAGEURL 1026 #define INDEX 1027 #define INTERLACE 1028 #define INTERVALS 1029 #define JOIN 1030 #define KEYSIZE 1031 #define KEYSPACING 1032 #define LABEL 1033 #define LABELCACHE 1035 #define LABELITEM 1036 #define LABELMAXSCALE 1037 #define LABELMINSCALE 1038 #define LAYER 1040 #define LEGEND 1041 #define LOG 1043 #define MAP 1044 #define MAXFEATURES 1047 #define MAXSCALE 1048 #define MAXSIZE 1049 #define MAXTEMPLATE 1050 #define MINDISTANCE 1051 #define MINFEATURESIZE 1053 #define MINSCALE 1054 #define MINSIZE 1055 #define MINTEMPLATE 1056 #define NAME 1057 #define NFTEMPLATE 1058 #define OFFSET 1060 #define OFFSITE 1061 #define OUTLINECOLOR 1062 #define PARTIALS 1063 #define POINTS 1064 #define POSITION 1065 #define POSTLABELCACHE 1098 #define PROJECTION 1066 #define QUERY 1067 #define QUERYITEM 1068 #define QUERYMAP 1069 #define REFERENCE 1070 #define SCALE 1071 #define SCALEBAR 1072 #define SHADOWCOLOR 1074 #define SHADOWSIZE 1075 #define SHAPEPATH 1076 #define SIZE 1077 #define STATUS 1078 #define STYLE 1080 #define SYMBOL 1081 #define SYMBOLSCALE 1082 #define TABLE 1083 #define TEMPLATE 1084 #define TEXT 1085 #define TEXTITEM 1086 #define TILEINDEX 1088 #define TILEITEM 1089 #define TOLERANCE 1090 #define TO 1091 #define TRANSPARENT 1092 #define TRANSFORM 1093 #define TYPE 1094 #define UNITS 1095 #define WEB 1096 #define WRAP 1097 #define FORCE 1098 #define TOLERANCEUNITS 1099 #define CHARACTER 1100 #define CONNECTION 1101 #define CONNECTIONTYPE 1102 #define SYMBOLSET 1105 #define OVERLAYBACKGROUNDCOLOR 1106 #define OVERLAYCOLOR 1107 #define OVERLAYMAXSIZE 1108 #define OVERLAYMINSIZE 1109 #define OVERLAYOUTLINECOLOR 1110 #define OVERLAYSIZE 1111 #define OVERLAYSYMBOL 1112 #define IMAGETYPE 1113 #define IMAGEQUALITY 1114 #define GAP 1115 #define FILTER 1116 #define FILTERITEM 1117 #define REQUIRES 1118 #define LABELREQUIRES 1119 #define METADATA 1120 #define LATLON 1121 #define RESOLUTION 1122 #define SIZEUNITS 1123 #define STYLEITEM 1124 #define DUMP 1125 #define TITLE 1126 #define LINECAP 1127 #define LINEJOIN 1128 #define LINEJOINMAXSIZE 1129 #define TRANSPARENCY 1130 #define MARKER 1131 #define MARKERSIZE 1132 #define MINBOXSIZE 1133 #define MAXBOXSIZE 1134 #define OUTPUTFORMAT 1135 #define MIMETYPE 1136 #define DRIVER 1137 #define IMAGEMODE 1138 #define FORMATOPTION 1139 #define GRATICULE 1140 #define GRID 1141 #define MAXARCS 1142 #define MINARCS 1143 #define MAXINTERVAL 1144 #define MININTERVAL 1145 #define MAXSUBDIVIDE 1146 #define MINSUBDIVIDE 1147 #define LABELFORMAT 1148 #define DATAPATTERN 1150 #define FILEPATTERN 1151 #define TEMPLATEPATTERN 1152 #define PROCESSING 1153 /* The DEBUG macro is also used to request debugging output. Redefine for keyword purposes. */ #ifdef DEBUG #undef DEBUG #endif #define DEBUG 1154 #define EXTENSION 1155 #define KEYIMAGE 1156 #define QUERYFORMAT 1157 #define CONFIG 1158 #define BANDSITEM 1159 #define ENCODING 1162 #define WIDTH 1163 #define MINWIDTH 1164 #define MAXWIDTH 1165 #define OUTLINEWIDTH 1166 /* Color Range support (was Gradient Support)*/ #define COLORRANGE 1170 #define DATARANGE 1172 #define RANGEITEM 1173 /* WKT support (bug 1466) */ #define WKT 1180 #define LEGENDFORMAT 1190 /* bug 1518 */ #define BROWSEFORMAT 1191 #define RELATIVETO 1192 #define OPACITY 1193 #define PRIORITY 1194 #define PATTERN 1195 #define MAXSCALEDENOM 1196 #define MINSCALEDENOM 1197 #define LABELMAXSCALEDENOM 1198 #define LABELMINSCALEDENOM 1199 #define SYMBOLSCALEDENOM 1200 #define SCALEDENOM 1201 #define CLASSGROUP 1202 #define ALIGN 1203 /* bug 2468 */ #define MAXGEOWIDTH 1204 #define MINGEOWIDTH 1205 #define ITEMS 1206 /* rfc40 label wrapping */ #define MAXLENGTH 1210 #define MINLENGTH 1211 /* rfc44 URL configuration support */ #define VALIDATION 1212 /* rfc48 geometry transforms */ #define GEOMTRANSFORM 1220 /* rfc55 output resolution */ #define DEFRESOLUTION 1221 /* label repeat enhancement */ #define REPEATDISTANCE 1222 /* rfc60 label collision detection */ #define MAXOVERLAPANGLE 1223 /* rfc66 temporary path */ #define TEMPPATH 1224 /* rfc68 union connection type */ #define UNION 1225 /* rfc69 cluster */ #define CLUSTER 1226 #define MAXDISTANCE 1227 #define REGION 1228 #define INITIALGAP 1229 #define ANCHORPOINT 1230 #define MASK 1250 #define POLAROFFSET 1251 /* rfc78 leader-lines labels */ #define LEADER 1260 #define GRIDSTEP 1261 /* rfc 86 scale-dependant token substitutions */ #define SCALETOKEN 1270 #define VALUES 1271 /* rfc59 bindvals objects */ #define BINDVALS 2000 #define TILESRS 1272 #endif /* MAPFILE_H */ mapserver-6.4.1/mapwcs20.c0000644002461700001440000043465712261257215015137 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OpenGIS Web Coverage Server (WCS) 2.0 implementation. * Author: Stephan Meissl * Fabian Schindler * and the MapServer team. * ****************************************************************************** * Copyright (c) 2010, 2011 EOX IT Services GmbH, Austria * * 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. ****************************************************************************/ #include "mapserver-config.h" #if defined(USE_WCS_SVR) #include #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include "mapwcs.h" #include #include "gdal.h" #include "cpl_port.h" #include "maptime.h" #include "mapprimitive.h" #include "cpl_string.h" #include #include #if defined(USE_LIBXML2) #include #include "maplibxml2.h" #include #endif /* defined(USE_LIBXML2) */ /************************************************************************/ /* msStringParseInteger() */ /* */ /* Tries to parse a string as a integer value. If not possible */ /* the value MS_WCS20_UNBOUNDED is stored as value. */ /* If no characters could be parsed, MS_FAILURE is returned. If at */ /* least some characters could be parsed, MS_DONE is returned and */ /* only if all characters could be parsed, MS_SUCCESS is returned. */ /************************************************************************/ static int msStringParseInteger(const char *string, int *dest) { char *parse_check; *dest = (int)strtol(string, &parse_check, 0); if(parse_check == string) { return MS_FAILURE; } else if(parse_check - strlen(string) != string) { return MS_DONE; } return MS_SUCCESS; } /************************************************************************/ /* msStringParseDouble() */ /* */ /* Tries to parse a string as a double value. If not possible */ /* the value 0 is stored as value. */ /* If no characters could be parsed, MS_FAILURE is returned. If at */ /* least some characters could be parsed, MS_DONE is returned and */ /* only if all characters could be parsed, MS_SUCCESS is returned. */ /************************************************************************/ static int msStringParseDouble(const char *string, double *dest) { char *parse_check = NULL; *dest = strtod(string, &parse_check); if(parse_check == string) { return MS_FAILURE; } else if(parse_check - strlen(string) != string) { return MS_DONE; } return MS_SUCCESS; } /************************************************************************/ /* msWCSParseTimeOrScalar20() */ /* */ /* Parses a string, either as a time or a scalar value and */ /* writes the output into the timeScalarUnion. */ /************************************************************************/ static int msWCSParseTimeOrScalar20(timeScalarUnion *u, const char *string) { struct tm time; if (string) { while(*string == ' ') string ++; } if (!string || strlen(string) == 0 || !u) { msSetError(MS_WCSERR, "Invalid string", "msWCSParseTimeOrScalar20()"); return MS_WCS20_ERROR_VALUE; } /* if the string is equal to "*" it means the value * of the interval is unbounded */ if (EQUAL(string, "*")) { u->scalar = MS_WCS20_UNBOUNDED; u->unbounded = 1; return MS_WCS20_UNDEFINED_VALUE; } /* if returned a valid value, use it */ if (msStringParseDouble(string, &(u->scalar)) == MS_SUCCESS) { return MS_WCS20_SCALAR_VALUE; } /* otherwise it might be a time value */ msTimeInit(&time); if (msParseTime(string, &time) == MS_TRUE) { u->time = mktime(&time); return MS_WCS20_TIME_VALUE; } /* the value could neither be parsed as a double nor as a time value */ else { msSetError(MS_WCSERR, "String %s could not be parsed to a time or scalar value", "msWCSParseTimeOrScalar20()",string); return MS_WCS20_ERROR_VALUE; } } /************************************************************************/ /* msWCSCreateSubsetObj20() */ /* */ /* Creates a new wcs20SubsetObj and initializes it to standard */ /* values. */ /************************************************************************/ static wcs20SubsetObjPtr msWCSCreateSubsetObj20() { wcs20SubsetObjPtr subset = (wcs20SubsetObjPtr) malloc(sizeof(wcs20SubsetObj)); MS_CHECK_ALLOC(subset, sizeof(wcs20SubsetObj), NULL); subset->axis = NULL; subset->crs = NULL; subset->min.scalar = subset->max.scalar = MS_WCS20_UNBOUNDED; subset->min.unbounded = subset->max.unbounded = 0; subset->operation = MS_WCS20_SLICE; return subset; } /************************************************************************/ /* msWCSFreeSubsetObj20() */ /* */ /* Frees a wcs20SubsetObj and releases all linked resources. */ /************************************************************************/ static void msWCSFreeSubsetObj20(wcs20SubsetObjPtr subset) { if (NULL == subset) { return; } msFree(subset->axis); msFree(subset->crs); msFree(subset); } /************************************************************************/ /* msWCSCreateAxisObj20() */ /* */ /* Creates a new wcs20AxisObj and initializes it to standard */ /* values. */ /************************************************************************/ static wcs20AxisObjPtr msWCSCreateAxisObj20() { wcs20AxisObj *axis = (wcs20AxisObjPtr)malloc(sizeof(wcs20AxisObj)); MS_CHECK_ALLOC(axis, sizeof(wcs20AxisObj), NULL); axis->name = NULL; axis->size = 0; axis->resolution = MS_WCS20_UNBOUNDED; axis->resolutionUOM = NULL; axis->subset = NULL; return axis; } /************************************************************************/ /* msWCSFreeAxisObj20() */ /* */ /* Frees a wcs20AxisObj and releases all linked resources. */ /************************************************************************/ static void msWCSFreeAxisObj20(wcs20AxisObjPtr axis) { if(NULL == axis) { return; } msFree(axis->name); msFree(axis->resolutionUOM); msWCSFreeSubsetObj20(axis->subset); msFree(axis); } /************************************************************************/ /* msWCSFindAxis20() */ /* */ /* Helper function to retrieve an axis by the name from a params */ /* object. */ /************************************************************************/ static wcs20AxisObjPtr msWCSFindAxis20(wcs20ParamsObjPtr params, const char *name) { int i = 0; for(i = 0; i < params->numaxes; ++i) { if(EQUAL(params->axes[i]->name, name)) { return params->axes[i]; } } return NULL; } /************************************************************************/ /* msWCSInsertAxisObj20() */ /* */ /* Helper function to insert an axis object into the axes list of */ /* a params object. */ /************************************************************************/ static void msWCSInsertAxisObj20(wcs20ParamsObjPtr params, wcs20AxisObjPtr axis) { params->numaxes++; params->axes = (wcs20AxisObjPtr*) msSmallRealloc(params->axes, sizeof(wcs20AxisObjPtr) * (params->numaxes)); params->axes[params->numaxes - 1] = axis; } /************************************************************************/ /* msWCSCreateParamsObj20() */ /* */ /* Creates a new wcs20ParamsObj and initializes it to standard */ /* values. */ /************************************************************************/ wcs20ParamsObjPtr msWCSCreateParamsObj20() { wcs20ParamsObjPtr params = (wcs20ParamsObjPtr) malloc(sizeof(wcs20ParamsObj)); MS_CHECK_ALLOC(params, sizeof(wcs20ParamsObj), NULL); params->version = NULL; params->request = NULL; params->service = NULL; params->accept_versions = NULL; params->sections = NULL; params->updatesequence = NULL; params->ids = NULL; params->width = 0; params->height = 0; params->resolutionX = MS_WCS20_UNBOUNDED; params->resolutionY = MS_WCS20_UNBOUNDED; params->resolutionUnits = NULL; params->numaxes = 0; params->axes = NULL; params->format = NULL; params->multipart = 0; params->interpolation = NULL; params->outputcrs = NULL; params->subsetcrs = NULL; params->bbox.minx = params->bbox.miny = -DBL_MAX; params->bbox.maxx = params->bbox.maxy = DBL_MAX; params->range_subset = NULL; return params; } /************************************************************************/ /* msWCSFreeParamsObj20() */ /* */ /* Frees a wcs20ParamsObj and releases all linked resources. */ /************************************************************************/ void msWCSFreeParamsObj20(wcs20ParamsObjPtr params) { if (NULL == params) { return; } msFree(params->version); msFree(params->request); msFree(params->service); CSLDestroy(params->accept_versions); CSLDestroy(params->sections); msFree(params->updatesequence); CSLDestroy(params->ids); msFree(params->resolutionUnits); msFree(params->format); msFree(params->interpolation); msFree(params->outputcrs); msFree(params->subsetcrs); while(params->numaxes > 0) { params->numaxes -= 1; msWCSFreeAxisObj20(params->axes[params->numaxes]); } msFree(params->axes); CSLDestroy(params->range_subset); msFree(params); } /************************************************************************/ /* msWCSParseSubset20() */ /* */ /* Parses several string parameters and fills them into the */ /* subset object. */ /************************************************************************/ static int msWCSParseSubset20(wcs20SubsetObjPtr subset, const char *axis, const char *crs, const char *min, const char *max) { int ts1, ts2; ts1 = ts2 = MS_WCS20_UNDEFINED_VALUE; if (subset == NULL) { return MS_FAILURE; } if (axis == NULL || strlen(axis) == 0) { msSetError(MS_WCSERR, "Subset axis is not given.", "msWCSParseSubset20()"); return MS_FAILURE; } subset->axis = msStrdup(axis); if (crs != NULL) { subset->crs = msStrdup(crs); } /* Parse first (probably only) part of interval/point; * check whether its a time value or a scalar value */ ts1 = msWCSParseTimeOrScalar20(&(subset->min), min); if (ts1 == MS_WCS20_ERROR_VALUE) { return MS_FAILURE; } /* check if its an interval */ /* if there is a comma, then it is */ if (max != NULL && strlen(max) > 0) { subset->operation = MS_WCS20_TRIM; /* Parse the second value of the interval */ ts2 = msWCSParseTimeOrScalar20(&(subset->max), max); if (ts2 == MS_WCS20_ERROR_VALUE) { return MS_FAILURE; } /* if at least one boundary is defined, use that value */ if ((ts1 == MS_WCS20_UNDEFINED_VALUE) ^ (ts2 == MS_WCS20_UNDEFINED_VALUE)) { if (ts1 == MS_WCS20_UNDEFINED_VALUE) { ts1 = ts2; } } /* if time and scalar values do not fit, throw an error */ else if (ts1 != MS_WCS20_UNDEFINED_VALUE && ts2 != MS_WCS20_UNDEFINED_VALUE && ts1 != ts2) { msSetError(MS_WCSERR, "Interval error: minimum is a %s value, maximum is a %s value", "msWCSParseSubset20()", ts1 ? "time" : "scalar", ts2 ? "time" : "scalar"); return MS_FAILURE; } /* if both min and max are unbounded -> throw an error */ if (subset->min.unbounded && subset->max.unbounded) { msSetError(MS_WCSERR, "Invalid values: no bounds could be parsed", "msWCSParseSubset20()"); return MS_FAILURE; } } /* there is no second value, therefore it is a point. * consequently set the operation to slice */ else { subset->operation = MS_WCS20_SLICE; if (ts1 == MS_WCS20_UNDEFINED_VALUE) { msSetError(MS_WCSERR, "Invalid point value given", "msWCSParseSubset20()"); return MS_FAILURE; } } subset->timeOrScalar = ts1; /* check whether the min is smaller than the max */ if (subset->operation == MS_WCS20_TRIM) { if(subset->timeOrScalar == MS_WCS20_SCALAR_VALUE && subset->min.scalar == MS_WCS20_UNBOUNDED) { subset->min.scalar = -MS_WCS20_UNBOUNDED; } if (subset->timeOrScalar == MS_WCS20_TIME_VALUE && subset->min.time > subset->max.time) { msSetError(MS_WCSERR, "Minimum value of subset axis %s is larger than maximum value", "msWCSParseSubset20()", subset->axis); return MS_FAILURE; } if (subset->timeOrScalar == MS_WCS20_SCALAR_VALUE && subset->min.scalar > subset->max.scalar) { msSetError(MS_WCSERR, "Minimum value (%f) of subset axis '%s' is larger than maximum value (%f).", "msWCSParseSubset20()", subset->min.scalar, subset->axis, subset->max.scalar); return MS_FAILURE; } } return MS_SUCCESS; } /************************************************************************/ /* msWCSParseSubsetKVPString20() */ /* */ /* Creates a new wcs20SubsetObj, parses a string and fills */ /* the parsed values into the object. Returns NULL on failure. */ /* Subset string: axis [ , crs ] ( intervalOrPoint ) */ /************************************************************************/ static int msWCSParseSubsetKVPString20(wcs20SubsetObjPtr subset, char *string) { char *axis, *crs, *min, *max; axis = string; crs = NULL; min = NULL; max = NULL; /* find first '(' */ min = strchr(string, '('); /* if min could not be found, the string is invalid */ if (min == NULL) { msSetError(MS_WCSERR, "Invalid axis subset string: '%s'", "msWCSParseSubsetKVPString20()", string); return MS_FAILURE; } /* set min to first letter */ *min = '\0'; ++min; /* cut the trailing ')' */ if (min[strlen(min) - 1] == ')') { min[strlen(min) - 1] = '\0'; } /* look if also a max is defined */ max = strchr(min, ','); if (max != NULL) { *max = '\0'; ++max; } /* look if also a crs is defined */ crs = strchr(axis, ','); if (crs != NULL) { *crs = '\0'; ++crs; } return msWCSParseSubset20(subset, axis, crs, min, max); } /************************************************************************/ /* msWCSParseSizeString20() */ /* */ /* Parses a string containing the axis and the size as an integer. */ /* Size string: axis ( size ) */ /************************************************************************/ static int msWCSParseSizeString20(char *string, char *outAxis, size_t axisStringLen, int *outSize) { char *number = NULL; char *check = NULL; /* find first '(', the character before the number */ number = strchr(string, '('); if(NULL == number) { msSetError(MS_WCSERR, "Invalid size parameter value.", "msWCSParseSize20()"); return MS_FAILURE; } /* cut trailing ')' */ check = strchr(string, ')'); if(NULL == check) { msSetError(MS_WCSERR, "Invalid size parameter value.", "msWCSParseSize20()"); return MS_FAILURE; } *number = '\0'; ++number; *check = '\0'; strlcpy(outAxis, string, axisStringLen); /* parse size value */ if(msStringParseInteger(number, outSize) != MS_SUCCESS) { msSetError(MS_WCSERR, "Parameter value '%s' is not a valid integer.", "msWCSParseSize20()", number); return MS_FAILURE; } return MS_SUCCESS; } /************************************************************************/ /* msWCSParseResolutionString20() */ /* */ /* Parses a resolution string and returns the axis, the units of */ /* measure and the resolution value. */ /* Subset string: axis ( value ) */ /************************************************************************/ static int msWCSParseResolutionString20(char *string, char *outAxis, size_t axisStringLen, double *outResolution) { char *number = NULL; char *check = NULL; /* find brackets */ number = strchr(string, '('); if(NULL == number) { msSetError(MS_WCSERR, "Invalid resolution parameter value : %s.", "msWCSParseSize20()", string); return MS_FAILURE; } /* cut trailing ')' */ check = strchr(string, ')'); if(NULL == check) { msSetError(MS_WCSERR, "Invalid size parameter value.", "msWCSParseSize20()"); return MS_FAILURE; } *number = '\0'; ++number; *check = '\0'; strlcpy(outAxis, string, axisStringLen); if(msStringParseDouble(number, outResolution) != MS_SUCCESS) { *outResolution = MS_WCS20_UNBOUNDED; msSetError(MS_WCSERR, "Invalid resolution parameter value : %s.", "msWCSParseSize20()", number); return MS_FAILURE; } return MS_SUCCESS; } /************************************************************************/ /* msWCSParseRequest20_XMLGetCapabilities() */ /* */ /* Parses a DOM element, representing a GetCapabilities-request */ /* to a params object. */ /************************************************************************/ #if defined(USE_LIBXML2) static int msWCSParseRequest20_XMLGetCapabilities( xmlNodePtr root, wcs20ParamsObjPtr params) { xmlNodePtr child; char *content = NULL; XML_FOREACH_CHILD(root, child) { XML_LOOP_IGNORE_COMMENT_OR_TEXT(child) else if (EQUAL((char *)child->name, "AcceptVersions")) { xmlNodePtr versionNode = NULL; XML_FOREACH_CHILD(child, versionNode) { /* for(child = firstChild->children; child != NULL; child = child->next) */ XML_LOOP_IGNORE_COMMENT_OR_TEXT(versionNode); XML_ASSERT_NODE_NAME(versionNode, "Version"); content = (char *)xmlNodeGetContent(versionNode); params->accept_versions = CSLAddString(params->accept_versions, content); xmlFree(content); } } else if(EQUAL((char *)child->name, "Sections")) { xmlNodePtr sectionNode = NULL; XML_FOREACH_CHILD(child, sectionNode) { XML_LOOP_IGNORE_COMMENT_OR_TEXT(sectionNode) XML_ASSERT_NODE_NAME(sectionNode, "Section"); content = (char *)xmlNodeGetContent(sectionNode); params->sections = CSLAddString(params->sections, content); xmlFree(content); } } else if(EQUAL((char *)child->name, "UpdateSequence")) { params->updatesequence = (char *)xmlNodeGetContent(child); } else if(EQUAL((char *)child->name, "AcceptFormats")) { /* Maybe not necessary, since only format is xml. */ /* At least ignore it, to not generate an error. */ } else if(EQUAL((char *)child->name, "AcceptLanguages")) { /* ignore */ } else { XML_UNKNOWN_NODE_ERROR(child); } } return MS_SUCCESS; } #endif /************************************************************************/ /* msWCSParseRequest20_XMLDescribeCoverage() */ /* */ /* Parses a DOM element, representing a DescribeCoverage-request */ /* to a params object. */ /************************************************************************/ #if defined(USE_LIBXML2) static int msWCSParseRequest20_XMLDescribeCoverage( xmlNodePtr root, wcs20ParamsObjPtr params) { xmlNodePtr child; int numIds = 0; char *id; XML_FOREACH_CHILD(root, child) { XML_LOOP_IGNORE_COMMENT_OR_TEXT(child) XML_ASSERT_NODE_NAME(child, "CoverageID"); /* Node content is the coverage ID */ id = (char *)xmlNodeGetContent(child); if (id == NULL || strlen(id) == 0) { msSetError(MS_WCSERR, "CoverageID could not be parsed.", "msWCSParseRequest20_XMLDescribeCoverage()"); return MS_FAILURE; } /* insert coverage ID into the list */ ++numIds; params->ids = CSLAddString(params->ids, (char *)id); xmlFree(id); } return MS_SUCCESS; } #endif /************************************************************************/ /* msWCSParseRequest20_XMLGetCoverage() */ /* */ /* Parses a DOM element, representing a GetCoverage-request to a */ /* params object. */ /************************************************************************/ #if defined(USE_LIBXML2) static int msWCSParseRequest20_XMLGetCoverage( mapObj* map, xmlNodePtr root, wcs20ParamsObjPtr params) { xmlNodePtr child; int numIds = 0; char *id; XML_FOREACH_CHILD(root, child) { XML_LOOP_IGNORE_COMMENT_OR_TEXT(child) else if (EQUAL((char *)child->name, "CoverageID")) { /* Node content is the coverage ID */ id = (char *)xmlNodeGetContent(child); if (id == NULL || strlen(id) == 0) { msSetError(MS_WCSERR, "CoverageID could not be parsed.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } /* insert coverage ID into the list */ ++numIds; params->ids = CSLAddString(params->ids, (char *)id); xmlFree(id); } else if (EQUAL((char *) child->name, "Format")) { params->format = (char *)xmlNodeGetContent(child); } else if (EQUAL((char *) child->name, "Mediatype")) { char *content = (char *)xmlNodeGetContent(child); if(content != NULL && (EQUAL(content, "multipart/mixed") || EQUAL(content, "multipart/related"))) { params->multipart = MS_TRUE; } else { msSetError(MS_WCSERR, "Invalid value '%s' for parameter 'Mediatype'.", "msWCSParseRequest20()", content); xmlFree(content); return MS_FAILURE; } xmlFree(content); } else if (EQUAL((char *) child->name, "DimensionTrim")) { wcs20AxisObjPtr axis = NULL; wcs20SubsetObjPtr subset = NULL; xmlNodePtr node = NULL; char *axisName = NULL, *min = NULL, *max = NULL, *crs = NULL; /* get strings for axis, min and max */ XML_FOREACH_CHILD(child, node) { XML_LOOP_IGNORE_COMMENT_OR_TEXT(node) else if (EQUAL((char *)node->name, "Dimension")) { if (axisName != NULL) { msSetError(MS_WCSERR, "Parameter 'Dimension' is already set.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } axisName = (char *) xmlNodeGetContent(node); crs = (char *) xmlGetProp(node, BAD_CAST "crs"); } else if (EQUAL((char *)node->name, "trimLow")) { min = (char *) xmlNodeGetContent(node); } else if (EQUAL((char *)node->name, "trimHigh")) { max = (char *) xmlNodeGetContent(node); } else { msFree(axisName); msFree(min); msFree(max); msFree(crs); XML_UNKNOWN_NODE_ERROR(node); } } if(NULL == (subset = msWCSCreateSubsetObj20())) { msFree(axisName); msFree(min); msFree(max); msFree(crs); return MS_FAILURE; } /* min and max have to have a value */ if(min == NULL ) { min = msStrdup("*"); } if(max == NULL) { max = msStrdup("*"); } if (msWCSParseSubset20(subset, axisName, crs, min, max) == MS_FAILURE) { msWCSFreeSubsetObj20(subset); msWCSException(map, "InvalidSubsetting", "subset", "2.0.1"); return MS_DONE; } if(NULL == (axis = msWCSFindAxis20(params, subset->axis))) { if(NULL == (axis = msWCSCreateAxisObj20())) { msFree(axisName); msFree(min); msFree(max); msFree(crs); return MS_FAILURE; } axis->name = msStrdup(subset->axis); msWCSInsertAxisObj20(params, axis); } axis->subset = subset; /* cleanup */ msFree(axisName); msFree(min); msFree(max); msFree(crs); } else if(EQUAL((char *) child->name, "DimensionSlice")) { msSetError(MS_WCSERR, "Operation '%s' is not supported by MapServer.", "msWCSParseRequest20_XMLGetCoverage()", (char *)child->name); return MS_FAILURE; } else if(EQUAL((char *) child->name, "Size")) { wcs20AxisObjPtr axis; char *axisName; char *content; if(NULL == (axisName = (char *) xmlGetProp(child, BAD_CAST "dimension")) ) { msSetError(MS_WCSERR, "Attribute 'dimension' is missing in element 'Size'.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } if(NULL == (axis = msWCSFindAxis20(params, axisName))) { if(NULL == (axis = msWCSCreateAxisObj20())) { return MS_FAILURE; } axis->name = msStrdup(axisName); msWCSInsertAxisObj20(params, axis); } content = (char *)xmlNodeGetContent(child); if(msStringParseInteger(content, &(axis->size)) != MS_SUCCESS) { msSetError(MS_WCSERR, "Value of element 'Size' could not " "be parsed to a valid integer.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } xmlFree(content); } else if(EQUAL((char *) child->name, "Resolution")) { wcs20AxisObjPtr axis; char *axisName; char *content; if(NULL == (axisName = (char *) xmlGetProp(child, BAD_CAST "dimension"))) { msSetError(MS_WCSERR, "Attribute 'dimension' is missing " "in element 'Resolution'.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } if(NULL == (axis = msWCSFindAxis20(params, axisName))) { if(NULL == (axis = msWCSCreateAxisObj20())) { return MS_FAILURE; } axis->name = msStrdup(axisName); msWCSInsertAxisObj20(params, axis); } axis->resolutionUOM = (char *) xmlGetProp(child, BAD_CAST "uom"); content = (char *)xmlNodeGetContent(child); if(msStringParseDouble(content, &(axis->resolution)) != MS_SUCCESS) { msSetError(MS_WCSERR, "Value of element 'Resolution' could not " "be parsed to a valid value.", "msWCSParseRequest20_XMLGetCoverage()"); xmlFree(content); return MS_FAILURE; } xmlFree(content); } else if(EQUAL((char *) child->name, "Interpolation")) { params->interpolation = (char *) xmlNodeGetContent(child); } else if(EQUAL((char *) child->name, "OutputCRS")) { params->outputcrs = (char *) xmlNodeGetContent(child); } else if(EQUAL((char *) child->name, "rangeSubset")) { xmlNodePtr bandNode = NULL; XML_FOREACH_CHILD(child, bandNode) { char *content = NULL; XML_ASSERT_NODE_NAME(bandNode, "band"); content = (char *)xmlNodeGetContent(bandNode); params->range_subset = CSLAddString(params->range_subset, content); xmlFree(content); } } else if (EQUAL((char *)child->name, "Extension")) { continue; } else { XML_UNKNOWN_NODE_ERROR(child); } } return MS_SUCCESS; } #endif /************************************************************************/ /* msWCSParseRequest20() */ /* */ /* Parses a CGI-request to a WCS 20 params object. It is */ /* either a POST or a GET request. In case of a POST request */ /* the xml content has to be parsed to a DOM structure */ /* before the parameters can be extracted. */ /************************************************************************/ int msWCSParseRequest20(mapObj *map, cgiRequestObj *request, owsRequestObj *ows_request, wcs20ParamsObjPtr params) { int i; if (params == NULL || request == NULL || ows_request == NULL) { msSetError(MS_WCSERR, "Internal error.", "msWCSParseRequest20()"); return MS_FAILURE; } /* Copy arbitrary service, version and request. */ params->service = msStrdup(ows_request->service); if(ows_request->version != NULL) { params->version = msStrdup(ows_request->version); } params->request = msStrdup(ows_request->request); /* Parse the POST request */ if (request->type == MS_POST_REQUEST) { #if defined(USE_LIBXML2) xmlDocPtr doc = ows_request->document; xmlNodePtr root = NULL; const char *validate; int ret = MS_SUCCESS; /* parse to DOM-Structure and get root element */ if(doc == NULL) { xmlErrorPtr error = xmlGetLastError(); msSetError(MS_WCSERR, "XML parsing error: %s", "msWCSParseRequest20()", error->message); return MS_FAILURE; } root = xmlDocGetRootElement(doc); validate = msOWSLookupMetadata(&(map->web.metadata), "CO", "validate_xml"); if (validate != NULL && EQUAL(validate, "TRUE")) { char *schema_dir = msStrdup(msOWSLookupMetadata(&(map->web.metadata), "CO", "schemas_dir")); if (schema_dir != NULL && (params->version == NULL || EQUALN(params->version, "2.0", 3))) { schema_dir = msStringConcatenate(schema_dir, "wcs/2.0.0/wcsAll.xsd"); if (msOWSSchemaValidation(schema_dir, request->postrequest) != 0) { msSetError(MS_WCSERR, "Invalid POST request. " "XML is not valid", "msWCSParseRequest20()"); return MS_FAILURE; } } msFree(schema_dir); } if(EQUAL(params->request, "GetCapabilities")) { ret = msWCSParseRequest20_XMLGetCapabilities(root, params); } else if(params->version != NULL && EQUALN(params->version, "2.0", 3)) { if(EQUAL(params->request, "DescribeCoverage")) { ret = msWCSParseRequest20_XMLDescribeCoverage(root, params); } else if(EQUAL(params->request, "GetCoverage")) { ret = msWCSParseRequest20_XMLGetCoverage(map, root, params); } } return ret; #else /* defined(USE_LIBXML2) */ /* TODO: maybe with CPLXML? */ return MS_FAILURE; #endif /* defined(USE_LIBXML2) */ } /* Parse the KVP GET request */ for (i = 0; i < request->NumParams; ++i) { char *key = NULL, *value = NULL; char **tokens; int num, j; key = request->ParamNames[i]; value = request->ParamValues[i]; if (EQUAL(key, "VERSION")) { continue; } else if (EQUAL(key, "REQUEST")) { continue; } else if (EQUAL(key, "SERVICE")) { continue; } else if (EQUAL(key, "ACCEPTVERSIONS")) { tokens = msStringSplit(value, ',', &num); for(j = 0; j < num; ++j) { params->accept_versions = CSLAddString(params->accept_versions, tokens[j]); } msFreeCharArray(tokens, num); } else if (EQUAL(key, "SECTIONS")) { tokens = msStringSplit(value, ',', &num); for(j = 0; j < num; ++j) { params->sections = CSLAddString(params->sections, tokens[j]); } msFreeCharArray(tokens, num); } else if (EQUAL(key, "UPDATESEQUENCE")) { params->updatesequence = msStrdup(value); } else if (EQUAL(key, "ACCEPTFORMATS")) { /* ignore */ } else if (EQUAL(key, "ACCEPTLANGUAGES")) { /* ignore */ } else if (EQUAL(key, "COVERAGEID")) { if (params->ids != NULL) { msSetError(MS_WCSERR, "Parameter 'CoverageID' is already set. " "For multiple IDs use a comma separated list.", "msWCSParseRequest20()"); return MS_FAILURE; } params->ids = CSLTokenizeString2(value, ",",0); } else if (EQUAL(key, "FORMAT")) { params->format = msStrdup(value); } else if (EQUAL(key, "MEDIATYPE")) { if(EQUAL(value, "multipart/mixed") || EQUAL(value, "multipart/related")) { params->multipart = MS_TRUE; } else { msSetError(MS_WCSERR, "Invalid value '%s' for parameter 'Mediatype'.", "msWCSParseRequest20()", value); return MS_FAILURE; } } else if (EQUAL(key, "INTERPOLATION")) { params->interpolation = msStrdup(value); } else if (EQUAL(key, "OUTPUTCRS")) { params->outputcrs = msStrdup(value); } else if (EQUALN(key, "SIZE", 4)) { wcs20AxisObjPtr axis = NULL; char axisName[500]; int size = 0; if(msWCSParseSizeString20(value, axisName, sizeof(axisName), &size) == MS_FAILURE) { return MS_FAILURE; } if(NULL == (axis = msWCSFindAxis20(params, axisName))) { if(NULL == (axis = msWCSCreateAxisObj20())) { return MS_FAILURE; } axis->name = msStrdup(axisName); msWCSInsertAxisObj20(params, axis); } /* check if the size of the axis is already set */ if(axis->size != 0) { msSetError(MS_WCSERR, "The size of the axis is already set.", "msWCSParseRequest20()"); return MS_FAILURE; } axis->size = size; } else if (EQUALN(key, "RESOLUTION", 10)) { wcs20AxisObjPtr axis = NULL; char axisName[500]; double resolution = 0; if(msWCSParseResolutionString20(value, axisName, sizeof(axisName), &resolution) == MS_FAILURE) { return MS_FAILURE; } /* check if axis object already exists, otherwise create a new one */ if(NULL == (axis = msWCSFindAxis20(params, axisName))) { if(NULL == (axis = msWCSCreateAxisObj20())) { return MS_FAILURE; } axis->name = msStrdup(axisName); msWCSInsertAxisObj20(params, axis); } /* check if the resolution of the axis is already set */ if(axis->resolution != MS_WCS20_UNBOUNDED) { msSetError(MS_WCSERR, "The resolution of the axis is already set.", "msWCSParseRequest20()"); return MS_FAILURE; } axis->resolution = resolution; } else if (EQUALN(key, "SUBSET", 6)) { wcs20AxisObjPtr axis = NULL; wcs20SubsetObjPtr subset = msWCSCreateSubsetObj20(); if(NULL == subset) { return MS_FAILURE; } if (msWCSParseSubsetKVPString20(subset, value) == MS_FAILURE) { msWCSFreeSubsetObj20(subset); msWCSException(map, "InvalidSubsetting", "subset", ows_request->version); return MS_DONE; } if(NULL == (axis = msWCSFindAxis20(params, subset->axis))) { if(NULL == (axis = msWCSCreateAxisObj20())) { return MS_FAILURE; } axis->name = msStrdup(subset->axis); msWCSInsertAxisObj20(params, axis); } if(NULL != axis->subset) { msSetError(MS_WCSERR, "The axis '%s' is already subsetted.", "msWCSParseRequest20()", axis->name); msWCSFreeSubsetObj20(subset); msWCSException(map, "InvalidAxisLabel", "subset", ows_request->version); return MS_DONE; } axis->subset = subset; } else if(EQUAL(key, "RANGESUBSET")) { tokens = msStringSplit(value, ',', &num); for(j = 0; j < num; ++j) { params->range_subset = CSLAddString(params->range_subset, tokens[j]); } msFreeCharArray(tokens, num); } /* Ignore all other parameters here */ } return MS_SUCCESS; } #if defined(USE_LIBXML2) /************************************************************************/ /* msWCSValidateAndFindSubsets20() */ /* */ /* Iterates over every axis in the parameters and checks if the */ /* axis name is in any string list. If found, but there already is */ /* a sample found for this axis, an Error is returned. Also if no */ /* axis is found for a given axis, an error is returned. */ /************************************************************************/ static int msWCSValidateAndFindAxes20( wcs20ParamsObjPtr params, wcs20AxisObjPtr outAxes[]) { static const int numAxis = 2; char *validXAxisNames[] = {"x", "xaxis", "x-axis", "x_axis", "long", "long_axis", "long-axis", "lon", "lon_axis", "lon-axis", NULL}; char *validYAxisNames[] = {"y", "yaxis", "y-axis", "y_axis", "lat", "lat_axis", "lat-axis", NULL}; char **validAxisNames[2]; int iParamAxis, iAcceptedAxis, iName, i; validAxisNames[0] = validXAxisNames; validAxisNames[1] = validYAxisNames; for(i = 0; i < numAxis; ++i) { outAxes[i] = NULL; } /* iterate over all subsets */ for(iParamAxis = 0; iParamAxis < params->numaxes; ++iParamAxis) { int found = 0; /* iterate over all given axes */ for(iAcceptedAxis = 0; iAcceptedAxis < numAxis; ++iAcceptedAxis ) { /* iterate over all possible names for the current axis */ for(iName = 0; validAxisNames[iAcceptedAxis][iName] != NULL ; ++iName) { /* compare axis name with current possible name */ if(EQUAL(params->axes[iParamAxis]->name, validAxisNames[iAcceptedAxis][iName])) { /* if there is already a sample for the axis, throw error */ if(outAxes[iAcceptedAxis] != NULL) { msSetError(MS_WCSERR, "The axis with the name '%s' corresponds " "to the same axis as the subset with the name '%s'.", "msWCSValidateAndFindAxes20()", outAxes[iAcceptedAxis]->name, params->axes[iParamAxis]->name); return MS_FAILURE; } /* if match is found, save it */ outAxes[iAcceptedAxis] = params->axes[iParamAxis]; found = 1; break; } } if (found) { break; } } /* no valid representation for current subset found */ /* exit and throw error */ if(found == 0) { msSetError(MS_WCSERR, "Invalid subset axis '%s'.", "msWCSValidateAndFindAxes20()", params->axes[iParamAxis]->name); return MS_FAILURE; } } return MS_SUCCESS; } /************************************************************************/ /* msWCSPrepareNamespaces20() */ /* */ /* Inserts namespace definitions into the root node of a DOM */ /* structure. */ /************************************************************************/ static void msWCSPrepareNamespaces20(xmlDocPtr pDoc, xmlNodePtr psRootNode, mapObj* map) { xmlNsPtr psXsiNs; char *schemaLocation = NULL; char *xsi_schemaLocation = NULL; xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_WCS_20_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_WCS_NAMESPACE_PREFIX)); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_20_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX ); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_WCS_20_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_WCS_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_GML_32_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_GML_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_GMLCOV_10_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_GMLCOV_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_SWE_20_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_SWE_NAMESPACE_PREFIX); psXsiNs = xmlSearchNs(pDoc, psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); schemaLocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); xsi_schemaLocation = msStrdup(MS_OWSCOMMON_WCS_20_NAMESPACE_URI); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemaLocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, MS_OWSCOMMON_WCS_20_SCHEMAS_LOCATION); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xmlNewNsProp(psRootNode, psXsiNs, BAD_CAST "schemaLocation", BAD_CAST xsi_schemaLocation); msFree(schemaLocation); msFree(xsi_schemaLocation); } /************************************************************************/ /* msWCSGetFormatList20() */ /* */ /* Copied from mapwcs.c. */ /************************************************************************/ static char *msWCSGetFormatsList20( mapObj *map, layerObj *layer ) { char *format_list = msStrdup(""); char **tokens = NULL, **formats = NULL; int i, numtokens = 0, numformats; char *value; /* -------------------------------------------------------------------- */ /* Parse from layer metadata. */ /* -------------------------------------------------------------------- */ if( layer != NULL && (value = msOWSGetEncodeMetadata( &(layer->metadata),"CO","formats", NULL )) != NULL ) { tokens = msStringSplit(value, ' ', &numtokens); msFree(value); } /* -------------------------------------------------------------------- */ /* Parse from map.web metadata. */ /* -------------------------------------------------------------------- */ else if((value = msOWSGetEncodeMetadata( &(map->web.metadata), "CO", "formats", NULL)) != NULL ) { tokens = msStringSplit(value, ' ', &numtokens); msFree(value); } /* -------------------------------------------------------------------- */ /* Or generate from all configured raster output formats that */ /* look plausible. */ /* -------------------------------------------------------------------- */ else { tokens = (char **) msSmallCalloc(map->numoutputformats,sizeof(char*)); for( i = 0; i < map->numoutputformats; i++ ) { switch( map->outputformatlist[i]->renderer ) { /* seemingly normal raster format */ #ifdef USE_GD case MS_RENDER_WITH_GD: #endif case MS_RENDER_WITH_AGG: case MS_RENDER_WITH_RAWDATA: tokens[numtokens++] = msStrdup(map->outputformatlist[i]->name); break; /* rest of formats aren't really WCS compatible */ default: break; } } } /* -------------------------------------------------------------------- */ /* Convert outputFormatObj names into mime types and remove */ /* duplicates. */ /* -------------------------------------------------------------------- */ numformats = 0; formats = (char **) msSmallCalloc(sizeof(char*),numtokens); for( i = 0; i < numtokens; i++ ) { int format_i, j; const char *mimetype; for( format_i = 0; format_i < map->numoutputformats; format_i++ ) { if( EQUAL(map->outputformatlist[format_i]->name, tokens[i]) ) break; } if( format_i == map->numoutputformats ) { msDebug("Failed to find outputformat info on format '%s', ignore.\n", tokens[i] ); continue; } mimetype = map->outputformatlist[format_i]->mimetype; if( mimetype == NULL || strlen(mimetype) == 0 ) { msDebug("No mimetime for format '%s', ignoring.\n", tokens[i] ); continue; } for( j = 0; j < numformats; j++ ) { if( EQUAL(mimetype,formats[j]) ) break; } if( j < numformats ) { msDebug( "Format '%s' ignored since mimetype '%s' duplicates another outputFormatObj.\n", tokens[i], mimetype ); continue; } formats[numformats++] = msStrdup(mimetype); } msFreeCharArray(tokens,numtokens); /* -------------------------------------------------------------------- */ /* Turn mimetype list into comma delimited form for easy use */ /* with xml functions. */ /* -------------------------------------------------------------------- */ for(i = 0; i < numformats; i++) { if(i > 0) { format_list = msStringConcatenate(format_list, (char *) ","); } format_list = msStringConcatenate(format_list, formats[i]); } msFreeCharArray(formats,numformats); return format_list; } /************************************************************************/ /* msWCSSwapAxes20 */ /* */ /* Helper function to determine if a SRS mandates swapped axes. */ /************************************************************************/ static int msWCSSwapAxes20(char *srs_uri) { int srid = 0; /* get SRID from the srs uri */ if(srs_uri != NULL && strlen(srs_uri) > 0) { if(sscanf(srs_uri, "http://www.opengis.net/def/crs/EPSG/0/%d", &srid) != EOF) ; else if(sscanf(srs_uri, "http://www.opengis.net/def/crs/%d", &srid) != EOF) ; else srid = 0; } if (srid == 0) return MS_FALSE; return msIsAxisInverted(srid); } /************************************************************************/ /* msWCSCommon20_CreateBoundedBy() */ /* */ /* Inserts the BoundedBy section into an existing DOM structure. */ /************************************************************************/ static void msWCSCommon20_CreateBoundedBy(layerObj *layer, wcs20coverageMetadataObjPtr cm, xmlNsPtr psGmlNs, xmlNodePtr psRoot, projectionObj *projection, int swapAxes) { xmlNodePtr psBoundedBy, psEnvelope; char lowerCorner[100], upperCorner[100], axisLabels[100], uomLabels[100]; psBoundedBy = xmlNewChild( psRoot, psGmlNs, BAD_CAST "boundedBy", NULL); { psEnvelope = xmlNewChild(psBoundedBy, psGmlNs, BAD_CAST "Envelope", NULL); { xmlNewProp(psEnvelope, BAD_CAST "srsName", BAD_CAST cm->srs_uri); if(projection->proj != NULL && pj_is_latlong(projection->proj)) { if (swapAxes == MS_FALSE) { strlcpy(axisLabels, "long lat", sizeof(axisLabels)); } else { strlcpy(axisLabels, "lat long", sizeof(axisLabels)); } strlcpy(uomLabels, "deg deg", sizeof(uomLabels)); } else { if (swapAxes == MS_FALSE) { strlcpy(axisLabels, "x y", sizeof(axisLabels)); } else { strlcpy(axisLabels, "y x", sizeof(axisLabels)); } strlcpy(uomLabels, "m m", sizeof(uomLabels)); } xmlNewProp(psEnvelope, BAD_CAST "axisLabels", BAD_CAST axisLabels); xmlNewProp(psEnvelope, BAD_CAST "uomLabels", BAD_CAST uomLabels); xmlNewProp(psEnvelope, BAD_CAST "srsDimension", BAD_CAST "2"); if (swapAxes == MS_FALSE) { snprintf(lowerCorner, sizeof(lowerCorner), "%.15g %.15g", cm->extent.minx, cm->extent.miny); snprintf(upperCorner, sizeof(upperCorner), "%.15g %.15g", cm->extent.maxx, cm->extent.maxy); } else { snprintf(lowerCorner, sizeof(lowerCorner), "%.15g %.15g", cm->extent.miny, cm->extent.minx); snprintf(upperCorner, sizeof(upperCorner), "%.15g %.15g", cm->extent.maxy, cm->extent.maxx); } xmlNewChild(psEnvelope, psGmlNs, BAD_CAST "lowerCorner", BAD_CAST lowerCorner); xmlNewChild(psEnvelope, psGmlNs, BAD_CAST "upperCorner", BAD_CAST upperCorner); } } } /************************************************************************/ /* msWCSCommon20_CreateDomainSet() */ /* */ /* Inserts the DomainSet section into an existing DOM structure. */ /************************************************************************/ static void msWCSCommon20_CreateDomainSet(layerObj* layer, wcs20coverageMetadataObjPtr cm, xmlNsPtr psGmlNs, xmlNodePtr psRoot, projectionObj *projection, int swapAxes) { xmlNodePtr psDomainSet, psGrid, psLimits, psGridEnvelope, psOrigin, psOffsetX, psOffsetY; char low[100], high[100], id[100], point[100], resx[100], resy[100], axisLabels[100]; psDomainSet = xmlNewChild( psRoot, psGmlNs, BAD_CAST "domainSet", NULL); { psGrid = xmlNewChild(psDomainSet, psGmlNs, BAD_CAST "RectifiedGrid", NULL); { xmlNewProp(psGrid, BAD_CAST "dimension", BAD_CAST "2"); snprintf(id, sizeof(id), "grid_%s", layer->name); xmlNewNsProp(psGrid, psGmlNs, BAD_CAST "id", BAD_CAST id); psLimits = xmlNewChild(psGrid, psGmlNs, BAD_CAST "limits", NULL); { psGridEnvelope = xmlNewChild(psLimits, psGmlNs, BAD_CAST "GridEnvelope", NULL); { strlcpy(low, "0 0", sizeof(low)); snprintf(high, sizeof(high), "%d %d", cm->xsize - 1, cm->ysize - 1); xmlNewChild(psGridEnvelope, psGmlNs, BAD_CAST "low", BAD_CAST low); xmlNewChild(psGridEnvelope, psGmlNs, BAD_CAST "high", BAD_CAST high); } } if(projection->proj != NULL && pj_is_latlong(projection->proj)) { if (swapAxes == MS_FALSE) { strlcpy(axisLabels, "long lat", sizeof(axisLabels)); } else { strlcpy(axisLabels, "lat long", sizeof(axisLabels)); } } else { if (swapAxes == MS_FALSE) { strlcpy(axisLabels, "x y", sizeof(axisLabels)); } else { strlcpy(axisLabels, "y x", sizeof(axisLabels)); } } xmlNewChild(psGrid, psGmlNs, BAD_CAST "axisLabels", BAD_CAST axisLabels); psOrigin = xmlNewChild(psGrid, psGmlNs, BAD_CAST "origin", NULL); { if (swapAxes == MS_FALSE) { snprintf(point, sizeof(point), "%f %f", cm->extent.minx, cm->extent.maxy); } else { snprintf(point, sizeof(point), "%f %f", cm->extent.maxy, cm->extent.minx); } psOrigin = xmlNewChild(psOrigin, psGmlNs, BAD_CAST "Point", NULL); snprintf(id, sizeof(id), "grid_origin_%s", layer->name); xmlNewNsProp(psOrigin, psGmlNs, BAD_CAST "id", BAD_CAST id); xmlNewProp(psOrigin, BAD_CAST "srsName", BAD_CAST cm->srs_uri); xmlNewChild(psOrigin, psGmlNs, BAD_CAST "pos", BAD_CAST point); } if (swapAxes == MS_FALSE) { snprintf(resx, sizeof(resx), "%f 0", cm->xresolution); snprintf(resy, sizeof(resy), "0 %f", -fabs(cm->yresolution)); } else { snprintf(resx, sizeof(resx), "0 %f", cm->xresolution); snprintf(resy, sizeof(resy), "%f 0", -fabs(cm->yresolution)); } psOffsetX = xmlNewChild(psGrid, psGmlNs, BAD_CAST "offsetVector", BAD_CAST resx); psOffsetY = xmlNewChild(psGrid, psGmlNs, BAD_CAST "offsetVector", BAD_CAST resy); xmlNewProp(psOffsetX, BAD_CAST "srsName", BAD_CAST cm->srs_uri); xmlNewProp(psOffsetY, BAD_CAST "srsName", BAD_CAST cm->srs_uri); } } } /************************************************************************/ /* msWCSCommon20_CreateRangeType() */ /* */ /* Inserts the RangeType section into an existing DOM structure. */ /************************************************************************/ static void msWCSCommon20_CreateRangeType(layerObj* layer, wcs20coverageMetadataObjPtr cm, char *bands, xmlNsPtr psGmlNs, xmlNsPtr psGmlcovNs, xmlNsPtr psSweNs, xmlNsPtr psXLinkNs, xmlNodePtr psRoot) { xmlNodePtr psRangeType, psDataRecord, psField, psQuantity, psUom, psConstraint, psAllowedValues = NULL, psNilValues = NULL; char **arr = NULL; int i, num = 0; if(NULL != bands) { arr = msStringSplit(bands, ',', &num); } psRangeType = xmlNewChild( psRoot, psGmlcovNs, BAD_CAST "rangeType", NULL); psDataRecord = xmlNewChild(psRangeType, psSweNs, BAD_CAST "DataRecord", NULL); /* iterate over every band */ for(i = 0; i < cm->numbands; ++i) { /* only add bands that are in the range subset */ if (NULL != arr && num > 0) { int found = MS_FALSE, j, repr; for(j = 0; j < num; ++j) { msStringParseInteger(arr[j], &repr); if(repr == i + 1) { found = MS_TRUE; break; } } if(found == MS_FALSE) { /* ignore this band since it is not in the range subset */ continue; } } /* add field tag */ psField = xmlNewChild(psDataRecord, psSweNs, BAD_CAST "field", NULL); if(cm->bands[i].name != NULL) { xmlNewProp(psField, BAD_CAST "name", BAD_CAST cm->bands[i].name); } else { xmlNewProp(psField, BAD_CAST "name", BAD_CAST "band"); } /* add Quantity tag */ psQuantity = xmlNewChild(psField, psSweNs, BAD_CAST "Quantity", NULL); if(cm->bands[i].definition != NULL) { xmlNewProp(psQuantity, BAD_CAST "definition", BAD_CAST cm->bands[i].definition); } if(cm->bands[i].description != NULL) { xmlNewChild(psQuantity, psSweNs, BAD_CAST "description", BAD_CAST cm->bands[i].description); } /* if there are given nilvalues -> add them to the first field */ /* all other fields get a reference to these */ if(cm->numnilvalues > 0) { int j; psNilValues = xmlNewChild( xmlNewChild(psQuantity, psSweNs, BAD_CAST "nilValues", NULL), psSweNs, BAD_CAST "NilValues", NULL); for(j = 0; j < cm->numnilvalues; ++j) { xmlNodePtr psTemp = xmlNewChild(psNilValues, psSweNs, BAD_CAST "nilValue", BAD_CAST cm->nilvalues[j]); if(j < cm->numnilvalues) xmlNewProp(psTemp, BAD_CAST "reason", BAD_CAST cm->nilvalues_reasons[j]); } } else { /* create an empty nilValues tag */ xmlNewChild(psQuantity, psSweNs, BAD_CAST "nilValues", NULL); } psUom = xmlNewChild(psQuantity, psSweNs, BAD_CAST "uom", NULL); if(cm->bands[i].uom != NULL) { xmlNewProp(psUom, BAD_CAST "code", BAD_CAST cm->bands[i].uom); } else { xmlNewProp(psUom, BAD_CAST "code", BAD_CAST "W.m-2.Sr-1"); } /* add constraint */ psConstraint = xmlNewChild(psQuantity, psSweNs, BAD_CAST "constraint", NULL); { char interval[100], significant_figures[100]; psAllowedValues = xmlNewChild(psConstraint, psSweNs, BAD_CAST "AllowedValues", NULL); /* Interval */ snprintf(interval, sizeof(interval), "%.5g %.5g", cm->bands[i].interval_min, cm->bands[i].interval_max); xmlNewChild(psAllowedValues, psSweNs, BAD_CAST "interval", BAD_CAST interval); /* Significant figures */ snprintf(significant_figures, sizeof(significant_figures), "%d", cm->bands[i].significant_figures); xmlNewChild(psAllowedValues, psSweNs, BAD_CAST "significantFigures", BAD_CAST significant_figures); } } msFreeCharArray(arr,num); } /************************************************************************/ /* msWCSWriteDocument20() */ /* */ /* Writes out an xml structure to the stream. */ /************************************************************************/ static int msWCSWriteDocument20(mapObj* map, xmlDocPtr psDoc) { xmlChar *buffer = NULL; int size = 0; msIOContext *context = NULL; const char *contenttype = NULL; const char *encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); if( msIO_needBinaryStdout() == MS_FAILURE ) { return MS_FAILURE; } if( EQUAL((char *)xmlDocGetRootElement(psDoc)->name, "RectifiedGridCoverage") ) contenttype = msStrdup("application/gml+xml"); else contenttype = msStrdup("text/xml"); if (encoding) msIO_setHeader("Content-Type","%s; charset=%s", contenttype, encoding); else msIO_setHeader("Content-Type","%s", contenttype); msIO_sendHeaders(); context = msIO_getHandler(stdout); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_contextWrite(context, buffer, size); xmlFree(buffer); return MS_SUCCESS; } /************************************************************************/ /* msWCSWriteFile20() */ /* */ /* Writes an image object to the stream. If multipart is set, */ /* then content sections are inserted. */ /************************************************************************/ static int msWCSWriteFile20(mapObj* map, imageObj* image, wcs20ParamsObjPtr params, int multipart) { int status; char* filename = NULL; char *base_dir = NULL; const char *fo_filename; int i; fo_filename = msGetOutputFormatOption( image->format, "FILENAME", NULL ); /* -------------------------------------------------------------------- */ /* Fetch the driver we will be using and check if it supports */ /* VSIL IO. */ /* -------------------------------------------------------------------- */ if( EQUALN(image->format->driver,"GDAL/",5) ) { GDALDriverH hDriver; const char *pszExtension = image->format->extension; msAcquireLock( TLOCK_GDAL ); hDriver = GDALGetDriverByName( image->format->driver+5 ); if( hDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find %s driver.", "msWCSWriteFile20()", image->format->driver+5 ); return msWCSException(map, "mapserv", "NoApplicableCode", params->version); } if( pszExtension == NULL ) pszExtension = "img.tmp"; if( GDALGetMetadataItem( hDriver, GDAL_DCAP_VIRTUALIO, NULL ) != NULL ) { base_dir = msTmpFile(map, map->mappath, "/vsimem/wcsout", NULL); if( fo_filename ) filename = msStrdup(CPLFormFilename(base_dir, fo_filename,NULL)); else filename = msStrdup(CPLFormFilename(base_dir, "out", pszExtension )); /* CleanVSIDir( "/vsimem/wcsout" ); */ msReleaseLock( TLOCK_GDAL ); status = msSaveImage(map, image, filename); if( status != MS_SUCCESS ) { msSetError(MS_MISCERR, "msSaveImage() failed", "msWCSWriteFile20()"); return msWCSException20(map, "mapserv", "NoApplicableCode", params->version); } } msReleaseLock( TLOCK_GDAL ); } /* -------------------------------------------------------------------- */ /* If we weren't able to write data under /vsimem, then we just */ /* output a single "stock" filename. */ /* -------------------------------------------------------------------- */ if( filename == NULL ) { if(multipart) { msIO_fprintf( stdout, "\r\n--wcs\r\n" ); msIO_fprintf( stdout, "Content-Type: %s\r\n" "Content-Description: coverage data\r\n" "Content-Transfer-Encoding: binary\r\n", MS_IMAGE_MIME_TYPE(map->outputformat)); if( fo_filename != NULL ) msIO_fprintf( stdout, "Content-ID: coverage/%s\r\n" "Content-Disposition: INLINE; filename=%s\r\n\r\n", fo_filename, fo_filename); else msIO_fprintf( stdout, "Content-ID: coverage/wcs.%s\r\n" "Content-Disposition: INLINE\r\n\r\n", MS_IMAGE_EXTENSION(map->outputformat)); } else { msIO_setHeader("Content-Type","%s",MS_IMAGE_MIME_TYPE(map->outputformat)); msIO_setHeader("Content-Description","coverage data"); msIO_setHeader("Content-Transfer-Encoding","binary"); if( fo_filename != NULL ) { msIO_setHeader("Content-ID","coverage/%s",fo_filename); msIO_setHeader("Content-Disposition","INLINE; filename=%s",fo_filename); } else { msIO_setHeader("Content-ID","coverage/wcs.%s",MS_IMAGE_EXTENSION(map->outputformat)); msIO_setHeader("Content-Disposition","INLINE"); } msIO_sendHeaders(); } status = msSaveImage(map, image, NULL); if( status != MS_SUCCESS ) { msSetError( MS_MISCERR, "msSaveImage() failed", "msWCSWriteFile20()"); return msWCSException(map, "mapserv", "NoApplicableCode", params->version); } if(multipart) msIO_fprintf( stdout, "\r\n--wcs--\r\n" ); return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* When potentially listing multiple files, we take great care */ /* to identify the "primary" file and list it first. In fact */ /* it is the only file listed in the coverages document. */ /* -------------------------------------------------------------------- */ { char **all_files = CPLReadDir( base_dir ); int count = CSLCount(all_files); if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; msAcquireLock( TLOCK_GDAL ); for( i = count-1; i >= 0; i-- ) { const char *this_file = all_files[i]; if( EQUAL(this_file,".") || EQUAL(this_file,"..") ) { all_files = CSLRemoveStrings( all_files, i, 1, NULL ); continue; } if( i > 0 && EQUAL(this_file,CPLGetFilename(filename)) ) { all_files = CSLRemoveStrings( all_files, i, 1, NULL ); all_files = CSLInsertString(all_files,0,CPLGetFilename(filename)); i++; } } /* -------------------------------------------------------------------- */ /* Dump all the files in the memory directory as mime sections. */ /* -------------------------------------------------------------------- */ count = CSLCount(all_files); if(count > 1 && multipart == MS_FALSE) { msDebug( "msWCSWriteFile20(): force multipart output without gml summary because we have multiple files in the result.\n" ); multipart = MS_TRUE; msIO_setHeader("Content-Type","multipart/related; boundary=wcs"); msIO_sendHeaders(); } for( i = 0; i < count; i++ ) { const char *mimetype = NULL; FILE *fp; unsigned char block[4000]; int bytes_read; if( i == 0 && !EQUAL(MS_IMAGE_MIME_TYPE(map->outputformat), "unknown") ) mimetype = MS_IMAGE_MIME_TYPE(map->outputformat); if( mimetype == NULL ) mimetype = "application/octet-stream"; if(multipart) { msIO_fprintf( stdout, "\r\n--wcs\r\n" ); msIO_fprintf( stdout, "Content-Type: %s\r\n" "Content-Description: coverage data\r\n" "Content-Transfer-Encoding: binary\r\n" "Content-ID: coverage/%s\r\n" "Content-Disposition: INLINE; filename=%s\r\n\r\n", mimetype, all_files[i], all_files[i]); } else { msIO_setHeader("Content-Type","%s",mimetype); msIO_setHeader("Content-Description","coverage data"); msIO_setHeader("Content-Transfer-Encoding","binary"); msIO_setHeader("Content-ID","coverage/%s",all_files[i]); msIO_setHeader("Content-Disposition","INLINE; filename=%s",all_files[i]); msIO_sendHeaders(); } fp = VSIFOpenL( CPLFormFilename(base_dir, all_files[i], NULL), "rb" ); if( fp == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to open %s for streaming to stdout.", "msWCSWriteFile20()", all_files[i] ); return MS_FAILURE; } while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 ) msIO_fwrite( block, 1, bytes_read, stdout ); VSIFCloseL( fp ); VSIUnlink( CPLFormFilename(base_dir, all_files[i], NULL) ); } msFree(base_dir); msFree(filename); CSLDestroy( all_files ); msReleaseLock( TLOCK_GDAL ); if(multipart) msIO_fprintf( stdout, "\r\n--wcs--\r\n" ); return MS_SUCCESS; } return MS_SUCCESS; } /************************************************************************/ /* msWCSGetRangesetAxisMetadata20() */ /* */ /* Looks up a layers metadata for a specific axis information. */ /************************************************************************/ static const char *msWCSLookupRangesetAxisMetadata20(hashTableObj *table, const char *axis, const char *item) { char buf[500], *value; if(table == NULL || axis == NULL || item == NULL) { return NULL; } strlcpy(buf, axis, sizeof(buf)); strlcat(buf, "_", sizeof(buf)); strlcat(buf, item, sizeof(buf)); if((value = msLookupHashTable(table, buf)) != NULL) { return value; } return msOWSLookupMetadata(table, "CO", buf); } /************************************************************************/ /* msWCSGetCoverageMetadata20() */ /* */ /* Inits a coverageMetadataObj. Uses msWCSGetCoverageMetadata() */ /* but exchanges the SRS URN by an URI for compliancy with 2.0. */ /************************************************************************/ static int msWCSGetCoverageMetadata20(layerObj *layer, wcs20coverageMetadataObj *cm) { char *srs_uri = NULL; int i = 0; memset(cm,0,sizeof(wcs20coverageMetadataObj)); if ( msCheckParentPointer(layer->map,"map") == MS_FAILURE ) return MS_FAILURE; if((cm->srs = msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "CO", MS_TRUE)) == NULL) { if((cm->srs = msOWSGetEPSGProj(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_TRUE)) == NULL) { msSetError(MS_WCSERR, "Unable to determine the SRS for this layer, " "no projection defined and no metadata available.", "msWCSGetCoverageMetadata20()"); return MS_FAILURE; } } /* -------------------------------------------------------------------- */ /* Get the SRS in uri format. */ /* -------------------------------------------------------------------- */ if((srs_uri = msOWSGetProjURI(&(layer->projection), &(layer->metadata), "CO", MS_TRUE)) == NULL) { srs_uri = msOWSGetProjURI(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_TRUE); } if( srs_uri != NULL ) { if( strlen(srs_uri) > sizeof(cm->srs_uri) - 1 ) { msSetError(MS_WCSERR, "SRS URI too long!", "msWCSGetCoverageMetadata()"); return MS_FAILURE; } strlcpy( cm->srs_uri, srs_uri, sizeof(cm->srs_uri) ); msFree( srs_uri ); } else { cm->srs_uri[0] = '\0'; } /* setup nilvalues */ cm->numnilvalues = 0; cm->nilvalues = NULL; cm->nilvalues_reasons = NULL; cm->native_format = NULL; /* -------------------------------------------------------------------- */ /* If we have "virtual dataset" metadata on the layer, then use */ /* that in preference to inspecting the file(s). */ /* We require extent and either size or resolution. */ /* -------------------------------------------------------------------- */ if( msOWSLookupMetadata(&(layer->metadata), "CO", "extent") != NULL && (msOWSLookupMetadata(&(layer->metadata), "CO", "resolution") != NULL || msOWSLookupMetadata(&(layer->metadata), "CO", "size") != NULL) ) { const char *value; /* get extent */ cm->extent.minx = 0.0; cm->extent.maxx = 0.0; cm->extent.miny = 0.0; cm->extent.maxy = 0.0; if( msOWSGetLayerExtent( layer->map, layer, "CO", &cm->extent ) == MS_FAILURE ) return MS_FAILURE; /* get resolution */ cm->xresolution = 0.0; cm->yresolution = 0.0; if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "resolution")) != NULL ) { char **tokens; int n; tokens = msStringSplit(value, ' ', &n); if( tokens == NULL || n != 2 ) { msSetError( MS_WCSERR, "Wrong number of arguments for wcs|ows_resolution metadata.", "msWCSGetCoverageMetadata20()"); msFreeCharArray( tokens, n ); return MS_FAILURE; } cm->xresolution = atof(tokens[0]); cm->yresolution = atof(tokens[1]); msFreeCharArray( tokens, n ); } /* get Size (in pixels and lines) */ cm->xsize = 0; cm->ysize = 0; if( (value=msOWSLookupMetadata(&(layer->metadata), "CO", "size")) != NULL ) { char **tokens; int n; tokens = msStringSplit(value, ' ', &n); if( tokens == NULL || n != 2 ) { msSetError( MS_WCSERR, "Wrong number of arguments for wcs|ows_size metadata.", "msWCSGetCoverageMetadata20()"); msFreeCharArray( tokens, n ); return MS_FAILURE; } cm->xsize = atoi(tokens[0]); cm->ysize = atoi(tokens[1]); msFreeCharArray( tokens, n ); } /* try to compute raster size */ if( cm->xsize == 0 && cm->ysize == 0 && cm->xresolution != 0.0 && cm->yresolution != 0.0 && cm->extent.minx != cm->extent.maxx && cm->extent.miny != cm->extent.maxy ) { cm->xsize = (int) ((cm->extent.maxx - cm->extent.minx) / cm->xresolution + 0.5); cm->ysize = (int) fabs((cm->extent.maxy - cm->extent.miny) / cm->yresolution + 0.5); } /* try to compute raster resolution */ if( (cm->xresolution == 0.0 || cm->yresolution == 0.0) && cm->xsize != 0 && cm->ysize != 0 ) { cm->xresolution = (cm->extent.maxx - cm->extent.minx) / cm->xsize; cm->yresolution = (cm->extent.maxy - cm->extent.miny) / cm->ysize; } /* do we have information to do anything */ if( cm->xresolution == 0.0 || cm->yresolution == 0.0 || cm->xsize == 0 || cm->ysize == 0 ) { msSetError( MS_WCSERR, "Failed to collect extent and resolution for WCS coverage from metadata for layer '%s'. Need value wcs|ows_resolution or wcs|ows_size values.", "msWCSGetCoverageMetadata20()", layer->name ); return MS_FAILURE; } /* compute geotransform */ cm->geotransform[0] = cm->extent.minx; cm->geotransform[1] = cm->xresolution; cm->geotransform[2] = 0.0; cm->geotransform[3] = cm->extent.maxy; cm->geotransform[4] = 0.0; cm->geotransform[5] = -fabs(cm->yresolution); /* get bands count, or assume 1 if not found */ cm->numbands = 1; if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "bandcount")) != NULL) { int numbands = 0; msStringParseInteger(value, &numbands); cm->numbands = (size_t)numbands; } cm->bands = msSmallCalloc(sizeof(wcs20rasterbandMetadataObj), cm->numbands); /* get bands type, or assume float if not found */ cm->imagemode = MS_IMAGEMODE_FLOAT32; if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "imagemode")) != NULL ) { if( EQUAL(value,"INT16") ) cm->imagemode = MS_IMAGEMODE_INT16; else if( EQUAL(value,"FLOAT32") ) cm->imagemode = MS_IMAGEMODE_FLOAT32; else if( EQUAL(value,"BYTE") ) cm->imagemode = MS_IMAGEMODE_BYTE; else { msSetError( MS_WCSERR, "Content of wcs|ows_imagemode (%s) not recognised. Should be one of BYTE, INT16 or FLOAT32.", "msWCSGetCoverageMetadata20()", value ); return MS_FAILURE; } } if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "native_format")) != NULL ) { cm->native_format = msStrdup(value); } /* determine nilvalues and reasons */ { int n_nilvalues = 0, n_nilvalues_reasons = 0; char **t_nilvalues = NULL, **t_nilvalues_reasons = NULL; if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "nilvalues")) != NULL ) { t_nilvalues = msStringSplit(value, ' ', &n_nilvalues); } else if((value = msOWSLookupMetadata(&(layer->metadata), "CO", "rangeset_nullvalue")) != NULL) { t_nilvalues = msStringSplit(value, ' ', &n_nilvalues); } if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", "nilvalues_reasons")) != NULL ) { t_nilvalues_reasons = msStringSplit(value, ' ', &n_nilvalues_reasons); } if(n_nilvalues > 0) { int i; cm->numnilvalues = n_nilvalues; cm->nilvalues = msSmallCalloc(sizeof(char*), n_nilvalues); cm->nilvalues_reasons = msSmallCalloc(sizeof(char*), n_nilvalues); for(i = 0; i < n_nilvalues; ++i) { cm->nilvalues[i] = msStrdup(t_nilvalues[i]); if(i < n_nilvalues_reasons) { cm->nilvalues_reasons[i] = msStrdup(t_nilvalues_reasons[i]); } else { cm->nilvalues_reasons[i] = msStrdup(""); } } } msFreeCharArray(t_nilvalues, n_nilvalues); msFreeCharArray(t_nilvalues_reasons, n_nilvalues_reasons); } { int num_band_names = 0, i, j; char **band_names = NULL; char *wcs11_band_names_key = "rangeset_axes"; char *wcs20_band_names_key = "band_names"; char *wcs11_interval_key = "interval"; char *wcs20_interval_key = "interval"; char *interval_key = NULL; char *significant_figures_key = "significant_figures"; char *wcs11_keys[] = { "label", "semantic", "values_type", "values_semantic", "description" }; char *wcs20_keys[] = { "band_name", "band_interpretation", "band_uom", "band_definition", "band_description" }; char **keys = NULL; char **interval_array; int num_interval; wcs20rasterbandMetadataObj default_values; /* Decide whether WCS1.1 or WCS2.0 keys should be used */ if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", wcs20_band_names_key) ) != NULL ) { keys = wcs20_keys; interval_key = wcs20_interval_key; band_names = msStringSplit(value, ' ', &num_band_names); } else if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", wcs11_band_names_key)) != NULL ) { keys = wcs11_keys; interval_key = wcs11_interval_key; band_names = msStringSplit(value, ' ', &num_band_names); } /* return with error when number of bands does not match */ /* the number of names */ if (num_band_names != cm->numbands && num_band_names != 0) { msFreeCharArray(band_names, num_band_names); msSetError( MS_WCSERR, "Wrong number of band names given in layer '%s'. " "Expected %d, got %d.", "msWCSGetCoverageMetadata20()", layer->name, (int)cm->numbands, num_band_names ); return MS_FAILURE; } /* look up default metadata values */ for(j = 1; j < 5; ++j) { if(keys != NULL) { default_values.values[j] = (char *)msOWSLookupMetadata(&(layer->metadata), "CO", keys[j]); } } /* set default values for interval and significant figures */ switch(cm->imagemode) { case MS_IMAGEMODE_BYTE: case MS_IMAGEMODE_PC256: default_values.interval_min = 0.; default_values.interval_max = 255.; default_values.significant_figures = 3; break; case MS_IMAGEMODE_INT16: default_values.interval_min = 0.; default_values.interval_max = (double)USHRT_MAX; default_values.significant_figures = 5; break; case MS_IMAGEMODE_FLOAT32: default_values.interval_min = -FLT_MAX; default_values.interval_max = FLT_MAX; default_values.significant_figures = 12; break; } /* lookup default interval values */ if (interval_key != NULL && (value = msOWSLookupMetadata(&(layer->metadata), "CO", interval_key)) != NULL) { interval_array = msStringSplit(value, ' ', &num_interval); if (num_interval != 2 || msStringParseDouble(interval_array[0], &(default_values.interval_min)) != MS_SUCCESS || msStringParseDouble(interval_array[1], &(default_values.interval_max)) != MS_SUCCESS) { msFreeCharArray(band_names, num_band_names); msFreeCharArray(interval_array, num_interval); msSetError(MS_WCSERR, "Wrong interval format for default axis.", "msWCSGetCoverageMetadata20()"); return MS_FAILURE; } msFreeCharArray(interval_array, num_interval); } /* lookup default value for significant figures */ if((value = msOWSLookupMetadata(&(layer->metadata), "CO", significant_figures_key)) != NULL) { if(msStringParseInteger(value, &(default_values.significant_figures)) != MS_SUCCESS) { msFreeCharArray(band_names, num_band_names); msSetError(MS_WCSERR, "Wrong significant figures format " "for default axis.", "msWCSGetCoverageMetadata20()"); return MS_FAILURE; } } /* iterate over every band */ for(i = 0; i < cm->numbands; ++i) { cm->bands[i].name = NULL; /* look up band metadata or copy defaults */ if(num_band_names != 0) { cm->bands[i].name = msStrdup(band_names[i]); for(j = 1; j < 5; ++j) { value = (char *)msWCSLookupRangesetAxisMetadata20(&(layer->metadata), cm->bands[i].name, keys[j]); if(value != NULL) { cm->bands[i].values[j] = msStrdup(value); } else if(default_values.values[j] != NULL) { cm->bands[i].values[j] = msStrdup(default_values.values[j]); } } } /* set up interval */ value = (char *)msWCSLookupRangesetAxisMetadata20(&(layer->metadata), cm->bands[i].name, interval_key); if(value != NULL) { num_interval = 0; interval_array = msStringSplit(value, ' ', &num_interval); if (num_interval != 2 || msStringParseDouble(interval_array[0], &(cm->bands[i].interval_min)) != MS_SUCCESS || msStringParseDouble(interval_array[1], &(cm->bands[i].interval_max)) != MS_SUCCESS) { msFreeCharArray(band_names, num_band_names); msFreeCharArray(interval_array, num_interval); msSetError(MS_WCSERR, "Wrong interval format for axis %s.", "msWCSGetCoverageMetadata20()", cm->bands[i].name); return MS_FAILURE; } msFreeCharArray(interval_array, num_interval); } else { cm->bands[i].interval_min = default_values.interval_min; cm->bands[i].interval_max = default_values.interval_max; } /* set up significant figures */ value = (char *)msWCSLookupRangesetAxisMetadata20(&(layer->metadata), cm->bands[i].name, significant_figures_key); if(value != NULL) { if(msStringParseInteger(value, &(cm->bands[i].significant_figures)) != MS_SUCCESS) { msFreeCharArray(band_names, num_band_names); msSetError(MS_WCSERR, "Wrong significant figures format " "for axis %s.", "msWCSGetCoverageMetadata20()", cm->bands[i].name); return MS_FAILURE; } } else { cm->bands[i].significant_figures = default_values.significant_figures; } } msFreeCharArray(band_names, num_band_names); } } else if( layer->data == NULL ) { /* no virtual metadata, not ok unless we're talking 1 image, hopefully we can fix that */ msSetError( MS_WCSERR, "RASTER Layer with no DATA statement and no WCS virtual dataset metadata. Tileindexed raster layers not supported for WCS without virtual dataset metadata (cm->extent, wcs_res, wcs_size).", "msWCSGetCoverageMetadata20()" ); return MS_FAILURE; } else { /* work from the file (e.g. DATA) */ GDALDatasetH hDS; GDALDriverH hDriver; GDALRasterBandH hBand; const char szPath[MS_MAXPATHLEN]; const char *driver_short_name, *driver_long_name; msGDALInitialize(); msTryBuildPath3((char *)szPath, layer->map->mappath, layer->map->shapepath, layer->data); msAcquireLock( TLOCK_GDAL ); hDS = GDALOpen( szPath, GA_ReadOnly ); if( hDS == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_IOERR, "%s", "msWCSGetCoverageMetadata20()", CPLGetLastErrorMsg() ); return MS_FAILURE; } msGetGDALGeoTransform( hDS, layer->map, layer, cm->geotransform ); cm->xsize = GDALGetRasterXSize( hDS ); cm->ysize = GDALGetRasterYSize( hDS ); cm->extent.minx = cm->geotransform[0]; cm->extent.maxx = cm->geotransform[0] + cm->geotransform[1] * cm->xsize + cm->geotransform[2] * cm->ysize; cm->extent.miny = cm->geotransform[3] + cm->geotransform[4] * cm->xsize + cm->geotransform[5] * cm->ysize; cm->extent.maxy = cm->geotransform[3]; cm->xresolution = cm->geotransform[1]; cm->yresolution = cm->geotransform[5]; cm->numbands = GDALGetRasterCount( hDS ); /* TODO nilvalues? */ if( cm->numbands == 0 ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_WCSERR, "Raster file %s has no raster bands. This cannot be used in a layer.", "msWCSGetCoverageMetadata20()", layer->data ); return MS_FAILURE; } hBand = GDALGetRasterBand( hDS, 1 ); switch( GDALGetRasterDataType( hBand ) ) { case GDT_Byte: cm->imagemode = MS_IMAGEMODE_BYTE; break; case GDT_Int16: cm->imagemode = MS_IMAGEMODE_INT16; break; default: cm->imagemode = MS_IMAGEMODE_FLOAT32; break; } cm->bands = msSmallCalloc(sizeof(wcs20rasterbandMetadataObj), cm->numbands); /* get as much band metadata as possible */ for(i = 0; i < cm->numbands; ++i) { char bandname[32]; GDALColorInterp colorInterp; hBand = GDALGetRasterBand(hDS, i + 1); snprintf(bandname, sizeof(bandname), "band%d", i+1); cm->bands[i].name = msStrdup(bandname); colorInterp = GDALGetRasterColorInterpretation(hBand); cm->bands[i].interpretation = msStrdup(GDALGetColorInterpretationName(colorInterp)); cm->bands[i].uom = msStrdup(GDALGetRasterUnitType(hBand)); if(strlen(cm->bands[i].uom) == 0) { msFree(cm->bands[i].uom); cm->bands[i].uom = NULL; } /* set up interval and significant figures */ switch(cm->imagemode) { case MS_IMAGEMODE_BYTE: case MS_IMAGEMODE_PC256: cm->bands[i].interval_min = 0.; cm->bands[i].interval_max = 255.; cm->bands[i].significant_figures = 3; break; case MS_IMAGEMODE_INT16: cm->bands[i].interval_min = 0.; cm->bands[i].interval_max = (double)USHRT_MAX; cm->bands[i].significant_figures = 5; break; case MS_IMAGEMODE_FLOAT32: cm->bands[i].interval_min = -FLT_MAX; cm->bands[i].interval_max = FLT_MAX; cm->bands[i].significant_figures = 12; break; } } hDriver = GDALGetDatasetDriver(hDS); driver_short_name = GDALGetDriverShortName(hDriver); driver_long_name = GDALGetDriverLongName(hDriver); /* TODO: improve this, exchange strstr() */ for(i = 0; i < layer->map->numoutputformats; ++i) { if(strstr( layer->map->outputformatlist[i]->driver, driver_short_name) != NULL || strstr(layer->map->outputformatlist[i]->driver, driver_long_name) != NULL) { cm->native_format = msStrdup(layer->map->outputformatlist[i]->mimetype); break; } } GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } return MS_SUCCESS; } /************************************************************************/ /* msWCSClearCoverageMetadata20() */ /* */ /* Returns all dynamically allocated memory from a coverage meta- */ /* data object. */ /************************************************************************/ static int msWCSClearCoverageMetadata20(wcs20coverageMetadataObj *cm) { int i = 0, j = 0; msFree(cm->native_format); for(i = 0; i < cm->numnilvalues; ++i) { msFree(cm->nilvalues[i]); msFree(cm->nilvalues_reasons[i]); } msFree(cm->nilvalues); msFree(cm->nilvalues_reasons); for(i = 0; i < cm->numbands; ++i) { for(j = 0; j < 5; ++j) { msFree(cm->bands[i].values[j]); } } msFree(cm->bands); return MS_SUCCESS; } /************************************************************************/ /* msWCSException20() */ /* */ /* Writes out an OWS compliant exception. */ /************************************************************************/ int msWCSException20(mapObj *map, const char *exceptionCode, const char *locator, const char *version) { int size = 0; char *status = "400 Bad Request"; char *errorString = NULL; char *errorMessage = NULL; char *schemasLocation = NULL; const char * encoding; char *xsi_schemaLocation = NULL; char version_string[OWS_VERSION_MAXLEN]; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psMainNode = NULL; xmlNsPtr psNsOws = NULL; xmlNsPtr psNsXsi = NULL; xmlChar *buffer = NULL; encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); errorString = msGetErrorString("\n"); errorMessage = msEncodeHTMLEntities(errorString); schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "ExceptionReport"); psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_20_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); xmlSetNs(psRootNode, psNsOws); psNsXsi = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); /* add attributes to root element */ xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST version); xmlNewProp(psRootNode, BAD_CAST "xml:lang", BAD_CAST msOWSGetLanguage(map, "exception")); /* get 2 digits version string: '2.0' */ msOWSGetVersionString(OWS_2_0_0, version_string); version_string[3]= '\0'; xsi_schemaLocation = msStrdup((char *)psNsOws->href); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)schemasLocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/ows/"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, version_string); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/owsExceptionReport.xsd"); /* add namespace'd attributes to root element */ xmlNewNsProp(psRootNode, psNsXsi, BAD_CAST "schemaLocation", BAD_CAST xsi_schemaLocation); /* add child element */ psMainNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Exception", NULL); /* add attributes to child */ xmlNewProp(psMainNode, BAD_CAST "exceptionCode", BAD_CAST exceptionCode); if (locator != NULL) { xmlNewProp(psMainNode, BAD_CAST "locator", BAD_CAST locator); } if (errorMessage != NULL) { xmlNewChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST errorMessage); } /*psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_2_0_0, schemasLocation, version, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage);*/ xmlDocSetRootElement(psDoc, psRootNode); if(EQUAL(exceptionCode, "OperationNotSupported") || EQUAL(exceptionCode, "OptionNotSupported")) { status = "501 Not Implemented"; } else if (EQUAL(exceptionCode, "NoSuchCoverage") || EQUAL(exceptionCode, "emptyCoverageIdList") || EQUAL(exceptionCode, "InvalidAxisLabel") || EQUAL(exceptionCode, "InvalidSubsetting")) { status = "404 Not Found"; } msIO_setHeader("Status", "%s", status); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_printf("%s", buffer); /* free buffer and the document */ free(errorString); free(errorMessage); free(schemasLocation); free(xsi_schemaLocation); xmlFree(buffer); xmlFreeDoc(psDoc); /* clear error since we have already reported it */ msResetErrorList(); return MS_FAILURE; } #define MAX_MIMES 20 static int msWCSGetCapabilities20_CreateProfiles( mapObj *map, xmlNodePtr psServiceIdentification, xmlNsPtr psOwsNs) { xmlNodePtr psProfile, psTmpNode; char *available_mime_types[MAX_MIMES]; int i = 0; /* even indices are urls, uneven are mime-types, or null*/ char *urls_and_mime_types[] = { MS_WCS_20_PROFILE_CORE, NULL, MS_WCS_20_PROFILE_KVP, NULL, MS_WCS_20_PROFILE_POST, NULL, MS_WCS_20_PROFILE_GML, NULL, MS_WCS_20_PROFILE_GML_MULTIPART, NULL, MS_WCS_20_PROFILE_GML_SPECIAL, NULL, MS_WCS_20_PROFILE_GML_GEOTIFF, "image/tiff", MS_WCS_20_PROFILE_GEOTIFF, "image/tiff", MS_WCS_20_PROFILE_CRS, NULL, MS_WCS_20_PROFILE_SCALING, NULL, MS_WCS_20_PROFILE_RANGESUBSET, NULL, NULL, NULL /* guardian */ }; /* navigate to node where profiles shall be inserted */ for(psTmpNode = psServiceIdentification->children; psTmpNode->next != NULL; psTmpNode = psTmpNode->next) { if(EQUAL((char *)psTmpNode->name, "ServiceTypeVersion")) break; } /* get list of all available mime types */ msGetOutputFormatMimeList(map, available_mime_types, MAX_MIMES); while(urls_and_mime_types[i] != NULL) { char *mime_type; mime_type = urls_and_mime_types[i+1]; /* check if there is a mime type */ if(mime_type != NULL) { /* check if the mime_type is in the list of outputformats */ if(CSLPartialFindString(available_mime_types, mime_type) == -1) continue; } /* create a new node and attach it in the tree */ psProfile = xmlNewNode(psOwsNs, BAD_CAST "Profile"); xmlNodeSetContent(psProfile, BAD_CAST urls_and_mime_types[i]); xmlAddNextSibling(psTmpNode, psProfile); psTmpNode = psProfile; i += 2; } return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities20_CoverageSummary() */ /* */ /* Helper function to create a short summary for a specific */ /* coverage. */ /************************************************************************/ static int msWCSGetCapabilities20_CoverageSummary( mapObj *map, wcs20ParamsObjPtr params, xmlDocPtr doc, xmlNodePtr psContents, layerObj *layer ) { wcs20coverageMetadataObj cm; int status; xmlNodePtr psCSummary, psMetadata; const char *metadatalink_href = msOWSLookupMetadata(&(layer->metadata), "CO", "metadatalink_href"); xmlNsPtr psWcsNs = xmlSearchNs( doc, xmlDocGetRootElement(doc), BAD_CAST "wcs" ); xmlNsPtr psOwsNs = xmlSearchNs( doc, xmlDocGetRootElement(doc), BAD_CAST "ows" ); xmlNsPtr psXlinkNs = xmlSearchNs( doc, xmlDocGetRootElement(doc), BAD_CAST "xlink" ); status = msWCSGetCoverageMetadata20(layer, &cm); if(status != MS_SUCCESS) return MS_FAILURE; psCSummary = xmlNewChild( psContents, psWcsNs, BAD_CAST "CoverageSummary", NULL ); xmlNewChild(psCSummary, psWcsNs, BAD_CAST "CoverageId", BAD_CAST layer->name); xmlNewChild(psCSummary, psWcsNs, BAD_CAST "CoverageSubtype", BAD_CAST "RectifiedGridCoverage"); /* Add references to additional coverage metadata */ if (metadatalink_href != NULL) { const char *metadatalink_type = msOWSLookupMetadata(&(layer->metadata), "CO", "metadatalink_type"); const char *metadatalink_format = msOWSLookupMetadata(&(layer->metadata), "CO", "metadatalink_format"); psMetadata = xmlNewChild(psCSummary, psOwsNs, BAD_CAST "Metadata", NULL); xmlNewNsProp(psMetadata, psXlinkNs, BAD_CAST "type", BAD_CAST "simple"); xmlNewNsProp(psMetadata, psXlinkNs, BAD_CAST "href", BAD_CAST metadatalink_href); if (metadatalink_type != NULL) { xmlNewProp(psMetadata, BAD_CAST "about", BAD_CAST metadatalink_type); } if (metadatalink_format != NULL) { xmlNewNsProp(psMetadata, psXlinkNs, BAD_CAST "role", BAD_CAST metadatalink_format); } } msWCSClearCoverageMetadata20(&cm); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities20() */ /* */ /* Performs the GetCapabilities operation. Writes out a xml */ /* structure with server specific information and a summary */ /* of all available coverages. */ /************************************************************************/ int msWCSGetCapabilities20(mapObj *map, cgiRequestObj *req, wcs20ParamsObjPtr params, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode, psOperationsNode, psNode; const char *updatesequence = NULL; xmlNsPtr psOwsNs = NULL, psXLinkNs = NULL, psWcsNs = NULL; char *script_url=NULL, *script_url_encoded=NULL, *format_list=NULL; int i; /* -------------------------------------------------------------------- */ /* Create document. */ /* -------------------------------------------------------------------- */ psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "Capabilities"); xmlDocSetRootElement(psDoc, psRootNode); /* -------------------------------------------------------------------- */ /* Name spaces */ /* -------------------------------------------------------------------- */ msWCSPrepareNamespaces20(psDoc, psRootNode, map); /* lookup namespaces */ psOwsNs = xmlSearchNs( psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX ); psWcsNs = xmlSearchNs( psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_WCS_NAMESPACE_PREFIX ); xmlSearchNs( psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_GML_NAMESPACE_PREFIX ); psXLinkNs = xmlSearchNs( psDoc, psRootNode, BAD_CAST "xlink" ); xmlSetNs(psRootNode, psWcsNs); xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->version ); updatesequence = msOWSLookupMetadata(&(map->web.metadata), "CO", "updatesequence"); if (params->updatesequence != NULL) { i = msOWSNegotiateUpdateSequence(params->updatesequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_WCSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWCSGetCapabilities20()", params->updatesequence, updatesequence); xmlFreeDoc(psDoc); return msWCSException(map, "updatesequence", "CurrentUpdateSequence", params->version); } if (i > 0) { /* invalid */ msSetError(MS_WCSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWCSGetCapabilities20()", params->updatesequence, updatesequence); xmlFreeDoc(psDoc); return msWCSException(map, "updatesequence", "InvalidUpdateSequence", params->version); } } if(updatesequence != NULL) { xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence); } /* -------------------------------------------------------------------- */ /* Service identification. */ /* -------------------------------------------------------------------- */ if ( MS_WCS_20_CAPABILITIES_INCLUDE_SECTION(params, "ServiceIdentification") ) { psNode = xmlAddChild(psRootNode, msOWSCommonServiceIdentification( psOwsNs, map, "OGC WCS", params->version, "CO")); msWCSGetCapabilities20_CreateProfiles(map, psNode, psOwsNs); } /* Service Provider */ if ( MS_WCS_20_CAPABILITIES_INCLUDE_SECTION(params, "ServiceProvider") ) { xmlAddChild(psRootNode, msOWSCommonServiceProvider(psOwsNs, psXLinkNs, map, "CO")); } /* -------------------------------------------------------------------- */ /* Operations metadata. */ /* -------------------------------------------------------------------- */ if ( MS_WCS_20_CAPABILITIES_INCLUDE_SECTION(params, "OperationsMetadata") ) { if ((script_url = msOWSGetOnlineResource(map, "CO", "onlineresource", req)) == NULL || (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL) { xmlFreeDoc(psDoc); msSetError(MS_WCSERR, "Server URL not found", "msWCSGetCapabilities20()"); return msWCSException(map, "mapserv", "NoApplicableCode", params->version); } free(script_url); psOperationsNode = xmlAddChild(psRootNode,msOWSCommonOperationsMetadata(psOwsNs)); /* -------------------------------------------------------------------- */ /* GetCapabilities - add Sections and AcceptVersions? */ /* -------------------------------------------------------------------- */ psNode = msOWSCommonOperationsMetadataOperation( psOwsNs, psXLinkNs, "GetCapabilities", OWS_METHOD_GETPOST, script_url_encoded); xmlAddChild(psNode->last->last->last, msOWSCommonOperationsMetadataDomainType(OWS_2_0_0, psOwsNs, "Constraint", "PostEncoding", "XML")); xmlAddChild(psOperationsNode, psNode); /* -------------------------------------------------------------------- */ /* DescribeCoverage */ /* -------------------------------------------------------------------- */ if (msOWSRequestIsEnabled(map, NULL, "C", "DescribeCoverage", MS_FALSE)) { psNode = msOWSCommonOperationsMetadataOperation( psOwsNs, psXLinkNs, "DescribeCoverage", OWS_METHOD_GETPOST, script_url_encoded); xmlAddChild(psNode->last->last->last, msOWSCommonOperationsMetadataDomainType(OWS_2_0_0, psOwsNs, "Constraint", "PostEncoding", "XML")); xmlAddChild(psOperationsNode, psNode); } /* -------------------------------------------------------------------- */ /* GetCoverage */ /* -------------------------------------------------------------------- */ if (msOWSRequestIsEnabled(map, NULL, "C", "GetCoverage", MS_FALSE)) { psNode = msOWSCommonOperationsMetadataOperation( psOwsNs, psXLinkNs, "GetCoverage", OWS_METHOD_GETPOST, script_url_encoded); xmlAddChild(psNode->last->last->last, msOWSCommonOperationsMetadataDomainType(OWS_2_0_0, psOwsNs, "Constraint", "PostEncoding", "XML")); xmlAddChild(psOperationsNode, psNode); } msFree(script_url_encoded); } /* -------------------------------------------------------------------- */ /* Service metadata. */ /* -------------------------------------------------------------------- */ if ( MS_WCS_20_CAPABILITIES_INCLUDE_SECTION(params, "ServiceMetadata") ) { psNode = xmlNewChild(psRootNode, psWcsNs, BAD_CAST "ServiceMetadata", NULL); /* Add formats list */ format_list = msWCSGetFormatsList20(map, NULL); msLibXml2GenerateList(psNode, psWcsNs, "formatSupported", format_list, ','); msFree(format_list); } /* -------------------------------------------------------------------- */ /* Contents section. */ /* -------------------------------------------------------------------- */ if ( MS_WCS_20_CAPABILITIES_INCLUDE_SECTION(params, "Contents") ) { psNode = xmlNewChild( psRootNode, psWcsNs, BAD_CAST "Contents", NULL ); if(ows_request->numlayers == 0) { xmlAddChild(psNode, xmlNewComment(BAD_CAST("WARNING: No WCS layers are enabled. " "Check wcs/ows_enable_request settings."))); } else { for(i = 0; i < map->numlayers; ++i) { layerObj *layer = map->layers[i]; int status; if(!msWCSIsLayerSupported(layer)) continue; if (!msIntegerInArray(layer->index, ows_request->enabled_layers, ows_request->numlayers)) continue; status = msWCSGetCapabilities20_CoverageSummary( map, params, psDoc, psNode, layer ); if(status != MS_SUCCESS) { xmlFreeDoc(psDoc); xmlCleanupParser(); return msWCSException(map, "mapserv", "Internal", params->version); } } } } /* -------------------------------------------------------------------- */ /* Write out the document and clean up. */ /* -------------------------------------------------------------------- */ msWCSWriteDocument20(map, psDoc); xmlFreeDoc(psDoc); xmlCleanupParser(); return MS_SUCCESS; } /************************************************************************/ /* msWCSDescribeCoverage20_CoverageDescription() */ /* */ /* Creates a description of a specific coverage with the three */ /* major sections: BoundedBy, DomainSet and RangeType. */ /************************************************************************/ static int msWCSDescribeCoverage20_CoverageDescription(mapObj *map, layerObj *layer, wcs20ParamsObjPtr params, xmlDocPtr psDoc, xmlNodePtr psRootNode ) { int status, swapAxes; wcs20coverageMetadataObj cm; xmlNodePtr psCD; xmlNsPtr psWcsNs, psGmlNs, psGmlcovNs, psSweNs, psXLinkNs; psWcsNs = psGmlNs = psGmlcovNs = psSweNs = psXLinkNs = NULL; psWcsNs = xmlSearchNs(psDoc, xmlDocGetRootElement(psDoc), BAD_CAST MS_OWSCOMMON_WCS_NAMESPACE_PREFIX); psGmlNs = xmlSearchNs(psDoc, xmlDocGetRootElement(psDoc), BAD_CAST MS_OWSCOMMON_GML_NAMESPACE_PREFIX); psGmlcovNs = xmlSearchNs(psDoc, xmlDocGetRootElement(psDoc), BAD_CAST MS_OWSCOMMON_GMLCOV_NAMESPACE_PREFIX); psSweNs = xmlSearchNs(psDoc, xmlDocGetRootElement(psDoc), BAD_CAST MS_OWSCOMMON_SWE_NAMESPACE_PREFIX); psXLinkNs = xmlSearchNs(psDoc, xmlDocGetRootElement(psDoc), BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); /* -------------------------------------------------------------------- */ /* Verify layer is processable. */ /* -------------------------------------------------------------------- */ if( msCheckParentPointer(layer->map,"map") == MS_FAILURE ) return MS_FAILURE; if(!msWCSIsLayerSupported(layer)) return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Setup coverage metadata. */ /* -------------------------------------------------------------------- */ status = msWCSGetCoverageMetadata20(layer, &cm); if(status != MS_SUCCESS) return status; swapAxes = msWCSSwapAxes20(cm.srs_uri); /* fill in bands rangeset info, if required. */ /* msWCSSetDefaultBandsRangeSetInfo( NULL, &cm, layer ); */ /* -------------------------------------------------------------------- */ /* Create CoverageDescription node. */ /* -------------------------------------------------------------------- */ psCD = xmlNewChild( psRootNode, psWcsNs, BAD_CAST "CoverageDescription", NULL ); xmlNewNsProp(psCD, psGmlNs, BAD_CAST "id", BAD_CAST layer->name); /* -------------------------------------------------------------------- */ /* gml:boundedBy */ /* -------------------------------------------------------------------- */ msWCSCommon20_CreateBoundedBy(layer, &cm, psGmlNs, psCD, &(layer->projection), swapAxes); xmlNewChild(psCD, psWcsNs, BAD_CAST "CoverageId", BAD_CAST layer->name); /* -------------------------------------------------------------------- */ /* gml:domainSet */ /* -------------------------------------------------------------------- */ msWCSCommon20_CreateDomainSet(layer, &cm, psGmlNs, psCD, &(layer->projection), swapAxes); /* -------------------------------------------------------------------- */ /* gmlcov:rangeType */ /* -------------------------------------------------------------------- */ msWCSCommon20_CreateRangeType(layer, &cm, NULL, psGmlNs, psGmlcovNs, psSweNs, psXLinkNs, psCD); /* -------------------------------------------------------------------- */ /* wcs:ServiceParameters */ /* -------------------------------------------------------------------- */ { xmlNodePtr psSP; psSP = xmlNewChild( psCD, psWcsNs, BAD_CAST "ServiceParameters", NULL); xmlNewChild(psSP, psWcsNs, BAD_CAST "CoverageSubtype", BAD_CAST "RectifiedGridCoverage"); /* -------------------------------------------------------------------- */ /* SupportedCRS */ /* -------------------------------------------------------------------- */ /* for now, WCS 2.0 does not allow per coverage CRS definitions */ /*{ xmlNodePtr psSupportedCrss; char *owned_value; psSupportedCrss = xmlNewChild(psSP, psWcsNs, BAD_CAST "SupportedCRSs", NULL); if ((owned_value = msOWSGetProjURI(&(layer->projection), &(layer->metadata), "CO", MS_FALSE)) != NULL) { } else if ((owned_value = msOWSGetProjURI(&(layer->map->projection), &(layer->map->web.metadata), "CO", MS_FALSE)) != NULL) { } else { msDebug("missing required information, no SRSs defined.\n"); } if (owned_value != NULL && strlen(owned_value) > 0) { msLibXml2GenerateList(psSupportedCrss, psWcsNs, "SupportedCRS", owned_value, ' '); } xmlNewChild(psSupportedCrss, psWcsNs, BAD_CAST "NativeCRS", BAD_CAST cm.srs_uri); msFree(owned_value); }*/ /* -------------------------------------------------------------------- */ /* SupportedFormats */ /* -------------------------------------------------------------------- */ /* for now, WCS 2.0 does not allow per coverage format definitions */ /*{ xmlNodePtr psSupportedFormats; char *format_list; psSupportedFormats = xmlNewChild(psSP, psWcsNs, BAD_CAST "SupportedFormats", NULL); format_list = msWCSGetFormatsList20(layer->map, layer); if (strlen(format_list) > 0) { msLibXml2GenerateList(psSupportedFormats, psWcsNs, "SupportedFormat", format_list, ','); msFree(format_list); }*/ /* -------------------------------------------------------------------- */ /* nativeFormat */ /* -------------------------------------------------------------------- */ xmlNewChild(psSP, psWcsNs, BAD_CAST "nativeFormat", BAD_CAST (cm.native_format ? cm.native_format : "")); if (!cm.native_format) { msDebug("msWCSDescribeCoverage20_CoverageDescription(): " "No native format specified.\n"); } } msWCSClearCoverageMetadata20(&cm); return MS_SUCCESS; } /************************************************************************/ /* msWCSDescribeCoverage20() */ /* */ /* Implementation of the DescibeCoverage Operation. The result */ /* of this operation is a xml document, containing specific */ /* information about a coverage identified by an ID. The result */ /* is written on the stream. */ /************************************************************************/ int msWCSDescribeCoverage20(mapObj *map, wcs20ParamsObjPtr params, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode; xmlNsPtr psWcsNs = NULL; int i, j; /* create DOM document and root node */ psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "CoverageDescriptions"); xmlDocSetRootElement(psDoc, psRootNode); /* prepare initial namespace definitions */ msWCSPrepareNamespaces20(psDoc, psRootNode, map); psWcsNs = xmlSearchNs(psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_WCS_NAMESPACE_PREFIX); xmlSetNs(psRootNode, psWcsNs); /* check if IDs are given */ if (params->ids) { /* for each given ID in the ID-list */ for (j = 0; params->ids[j]; j++) { i = msGetLayerIndex(map, params->ids[j]); if (i == -1 || (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) ) { msSetError(MS_WCSERR, "Unknown coverage: (%s)", "msWCSDescribeCoverage20()", params->ids[j]); return msWCSException(map, "NoSuchCoverage", "coverage", params->version); } /* create coverage description for the specified layer */ if(msWCSDescribeCoverage20_CoverageDescription(map, (GET_LAYER(map, i)), params, psDoc, psRootNode) == MS_FAILURE) { msSetError(MS_WCSERR, "Error retrieving coverage description.", "msWCSDescribeCoverage20()"); return msWCSException(map, "MissingParameterValue", "coverage", params->version); } } } else { /* Throw error, since IDs are mandatory */ msSetError(MS_WCSERR, "Missing COVERAGEID parameter.", "msWCSDescribeCoverage20()"); return msWCSException(map, "MissingParameterValue", "coverage", params->version); } /* write out the DOM document to the stream */ msWCSWriteDocument20(map, psDoc); /* cleanup */ xmlFreeDoc(psDoc); xmlCleanupParser(); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCoverage_FinalizeParamsObj20() */ /* */ /* Finalizes a wcs20ParamsObj for a GetCoverage operation. In the */ /* process, the params boundig box is adjusted to the subsets, */ /* width, height and resolution are determined and the subset crs */ /* is found out. */ /************************************************************************/ static int msWCSGetCoverage20_FinalizeParamsObj(wcs20ParamsObjPtr params, wcs20AxisObjPtr *axes) { char *crs = NULL; if (axes[0] != NULL) { if(axes[0]->subset != NULL) { msDebug("Subset for X-axis found: %s\n", axes[0]->subset->axis); if (!axes[0]->subset->min.unbounded) params->bbox.minx = axes[0]->subset->min.scalar; if (!axes[0]->subset->max.unbounded) params->bbox.maxx = axes[0]->subset->max.scalar; crs = axes[0]->subset->crs; } params->width = axes[0]->size; params->resolutionX = axes[0]->resolution; if(axes[0]->resolutionUOM != NULL) { params->resolutionUnits = msStrdup(axes[0]->resolutionUOM); } } if (axes[1] != NULL) { if(axes[1]->subset != NULL) { msDebug("Subset for Y-axis found: %s\n", axes[1]->subset->axis); if (!axes[1]->subset->min.unbounded) params->bbox.miny = axes[1]->subset->min.scalar; if (!axes[1]->subset->max.unbounded) params->bbox.maxy = axes[1]->subset->max.scalar; if(crs != NULL && axes[0] != NULL && axes[0]->subset!= NULL) { if(!EQUAL(crs, axes[1]->subset->crs)) { msSetError(MS_WCSERR, "CRS for axis %s and axis %s are not the same.", "msWCSCreateBoundingBox20()", axes[0]->name, axes[1]->name); return MS_FAILURE; } } else { crs = axes[1]->subset->crs; } } params->height = axes[1]->size; params->resolutionY = axes[1]->resolution; if(params->resolutionUnits == NULL && axes[1]->resolutionUOM != NULL) { params->resolutionUnits = msStrdup(axes[1]->resolutionUOM); } else if(params->resolutionUnits != NULL && axes[1]->resolutionUOM != NULL && !EQUAL(params->resolutionUnits, axes[1]->resolutionUOM)) { msSetError(MS_WCSERR, "The units of measure of the resolution for" "axis %s and axis %s are not the same.", "msWCSCreateBoundingBox20()", axes[0]->name, axes[1]->name); return MS_FAILURE; } } /* check if projections are equal */ if(crs != NULL) { params->subsetcrs = msStrdup(crs); } else { params->subsetcrs = msStrdup("imageCRS"); } return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCoverage20_GetBands() */ /* */ /* Returns a string, containing a comma-separated list of band */ /* indices. */ /************************************************************************/ static int msWCSGetCoverage20_GetBands(mapObj *map, layerObj *layer, wcs20ParamsObjPtr params, wcs20coverageMetadataObjPtr cm, char **bandlist) { int i = 0, count, maxlen, index; char *tmp = NULL; char **band_ids = NULL; /* if rangesubset parameter is not given, default to all bands */ if(NULL == params->range_subset) { *bandlist = msStrdup("1"); for(i = 1; i < cm->numbands; ++i) { char strnumber[10]; snprintf(strnumber, sizeof(strnumber), ",%d", i + 1); *bandlist = msStringConcatenate(*bandlist, strnumber); } return MS_SUCCESS; } count = CSLCount(params->range_subset); maxlen = count * 4 * sizeof(char); *bandlist = msSmallCalloc(sizeof(char), maxlen); if (NULL == (tmp = msOWSGetEncodeMetadata(&layer->metadata, "CO", "rangeset_axes", NULL))) { tmp = msOWSGetEncodeMetadata(&layer->metadata, "CO", "band_names", NULL); } if(NULL != tmp) { band_ids = CSLTokenizeString2(tmp, " ", 0); msFree(tmp); } for(i = 0; i < count; ++i) { /* print ',' if not the first value */ if(i != 0) { strlcat(*bandlist, ",", maxlen); } /* check if the string represents an integer */ if(msStringParseInteger(params->range_subset[i], &index) == MS_SUCCESS) { tmp = msIntToString((int)index); strlcat(*bandlist, tmp, maxlen); msFree(tmp); continue; } /* check if the string is equal to a band identifier */ /* if so, what is the index of the band */ index = CSLFindString(band_ids, params->range_subset[i]); if(index != -1) { tmp = msIntToString((int)index + 1); strlcat(*bandlist, tmp, maxlen); msFree(tmp); continue; } msSetError(MS_WCSERR, "'%s' is not a valid band identifier.", "msWCSGetCoverage20_GetBands()", params->range_subset[i]); return MS_FAILURE; } CSLDestroy(band_ids); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCoverage20() */ /* */ /* Implementation of the GetCoverage Operation. The coverage */ /* is either returned as an image or as a multipart xml/image. */ /* The result is written on the stream. */ /************************************************************************/ int msWCSGetCoverage20(mapObj *map, cgiRequestObj *request, wcs20ParamsObjPtr params, owsRequestObj *ows_request) { layerObj *layer = NULL; wcs20coverageMetadataObj cm; imageObj *image = NULL; outputFormatObj *format = NULL; rectObj subsets, bbox; projectionObj imageProj; int status, i; double x_1, x_2, y_1, y_2; char *coverageName, *bandlist=NULL, numbands[8]; /* number of coverage ids should be 1 */ if (params->ids == NULL || params->ids[0] == NULL) { msSetError(MS_WCSERR, "Required parameter CoverageID was not supplied.", "msWCSGetCoverage20()"); return msWCSException(map, "MissingParameterValue", "coverage", params->version); } if (params->ids[1] != NULL) { msSetError(MS_WCSERR, "GetCoverage operation supports only one coverage.", "msWCSGetCoverage20()"); return msWCSException(map, "TooManyParameterValues", "coverage", params->version); } /* find the right layer */ layer = NULL; for(i = 0; i < map->numlayers; i++) { coverageName = msOWSGetEncodeMetadata(&(GET_LAYER(map, i)->metadata), "CO", "name", GET_LAYER(map, i)->name); if (EQUAL(coverageName, params->ids[0]) && (msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers))) { layer = GET_LAYER(map, i); i = map->numlayers; /* to exit loop don't use break, we want to free resources first */ } msFree(coverageName); } /* throw exception if no Layer was found */ if (layer == NULL) { msSetError(MS_WCSERR, "COVERAGEID=%s not found, not in supported layer list. A layer might be disabled for \ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", params->ids[0]); return msWCSException(map, "NoSuchCoverage", "coverageid", params->version); } /* retrieve coverage metadata */ status = msWCSGetCoverageMetadata20(layer, &cm); if (status != MS_SUCCESS) { msWCSClearCoverageMetadata20(&cm); return MS_FAILURE; } /* fill in bands rangeset info, if required. */ /* msWCSSetDefaultBandsRangeSetInfo(NULL, &cm, layer ); */ /* set resolution, size and maximum extent */ layer->extent = map->extent = cm.extent; map->cellsize = cm.xresolution; map->width = cm.xsize; map->height = cm.ysize; /************************************************************************/ /* finalize the params object. determine subset crs and subset */ /* bbox. Also project the image to the subset crs. */ /************************************************************************/ msInitProjection(&imageProj); if (msLoadProjectionString(&imageProj, cm.srs) == -1) { msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Error loading CRS %s.", "msWCSGetCoverage20()", params->subsetcrs); return msWCSException(map, "InvalidParameterValue", "projection", params->version); } /* iterate over all subsets and check if they are valid*/ for(i = 0; i < params->numaxes; ++i) { if(params->axes[i]->subset != NULL) { if(params->axes[i]->subset->timeOrScalar == MS_WCS20_TIME_VALUE) { msSetError(MS_WCSERR, "Time values for subsets are not supported. ", "msWCSGetCoverage20()"); return msWCSException(map, "InvalidSubsetting", "subset", params->version); } if(params->axes[i]->subset->operation == MS_WCS20_SLICE) { msSetError(MS_WCSERR, "Subset operation 'slice' is not supported.", "msWCSGetCoverage20()"); return msWCSException(map, "InvalidSubsetting", "subset", params->version); } } } { wcs20AxisObjPtr *axes; axes = msSmallMalloc(sizeof(wcs20AxisObjPtr) * 2); if(msWCSValidateAndFindAxes20(params, axes) == MS_FAILURE) { msWCSClearCoverageMetadata20(&cm); msFree(axes); return msWCSException(map, "InvalidAxisLabel", "subset", params->version); } if(msWCSGetCoverage20_FinalizeParamsObj(params, axes) == MS_FAILURE) { msWCSClearCoverageMetadata20(&cm); msFree(axes); return msWCSException(map, "InvalidParameterValue", "extent", params->version); } msFree(axes); } subsets = params->bbox; if(EQUAL(params->subsetcrs, "imageCRS")) { /* subsets are in imageCRS; reproject them to real coordinates */ rectObj orig_bbox = subsets; msFreeProjection(&(map->projection)); map->projection = imageProj; if(subsets.minx != -DBL_MAX || subsets.maxx != DBL_MAX) { x_1 = cm.geotransform[0] + orig_bbox.minx * cm.geotransform[1] + orig_bbox.miny * cm.geotransform[2]; x_2 = cm.geotransform[0] + (orig_bbox.maxx+1) * cm.geotransform[1] + (orig_bbox.maxy+1) * cm.geotransform[2]; subsets.minx = MIN(x_1, x_2); subsets.maxx = MAX(x_1, x_2); } if(subsets.miny != -DBL_MAX || subsets.maxy != DBL_MAX) { y_1 = cm.geotransform[3] + (orig_bbox.maxx+1) * cm.geotransform[4] + (orig_bbox.maxy+1) * cm.geotransform[5]; /*subsets.miny -= cm.geotransform[4]/2 + cm.geotransform[5]/2;*/ y_2 = cm.geotransform[3] + orig_bbox.minx * cm.geotransform[4] + orig_bbox.miny * cm.geotransform[5]; subsets.miny = MIN(y_1, y_2); subsets.maxy = MAX(y_1, y_2); } } else { /* if crs is not the 'imageCRS' */ projectionObj subsetProj; /* if the subsets have a crs given, project the image extent to it */ msInitProjection(&subsetProj); if(msLoadProjectionString(&subsetProj, params->subsetcrs) != MS_SUCCESS) { msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Error loading CRS %s.", "msWCSGetCoverage20()", params->subsetcrs); return msWCSException(map, "InvalidParameterValue", "projection", params->version); } if(msProjectionsDiffer(&imageProj, &subsetProj)) { msProjectRect(&imageProj, &subsetProj, &(layer->extent)); map->extent = layer->extent; msFreeProjection(&(map->projection)); map->projection = subsetProj; msFreeProjection(&imageProj); } else { msFreeProjection(&(map->projection)); map->projection = imageProj; msFreeProjection(&subsetProj); } } /* create boundings of params subsets and image extent */ if(msRectOverlap(&subsets, &(layer->extent)) == MS_FALSE) { /* extent and bbox do not overlap -> exit */ msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Image extent does not intersect with desired region.", "msWCSGetCoverage20()"); return msWCSException(map, "ExtentError", "extent", params->version); } /* write combined bounding box */ bbox.minx = MAX(subsets.minx, map->extent.minx); bbox.miny = MAX(subsets.miny, map->extent.miny); bbox.maxx = MIN(subsets.maxx, map->extent.maxx); bbox.maxy = MIN(subsets.maxy, map->extent.maxy); /* check if we are overspecified */ if((params->width != 0 && params->resolutionX != MS_WCS20_UNBOUNDED) || (params->height != 0 && params->resolutionY != MS_WCS20_UNBOUNDED)) { msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "GetCoverage operation supports only one of SIZE or RESOLUTION per axis.", "msWCSGetCoverage20()"); return msWCSException(map, "TooManyParameterValues", "coverage", params->version); } /************************************************************************/ /* check both axes: see if either size or resolution are given (and */ /* calculate the other value). If both are not given, calculate them */ /* from the bounding box. */ /************************************************************************/ /* check x axis */ if(params->width != 0) { /* TODO Unit Of Measure? */ params->resolutionX = (bbox.maxx - bbox.minx) / params->width; } else if(params->resolutionX != MS_WCS20_UNBOUNDED) { params->width = MS_NINT((bbox.maxx - bbox.minx) / params->resolutionX); } else { if(ABS(bbox.maxx - bbox.minx) != ABS(map->extent.maxx - map->extent.minx)) { double total = ABS(map->extent.maxx - map->extent.minx), part = ABS(bbox.maxx - bbox.minx); params->width = MS_NINT((part * map->width) / total); } else { params->width = map->width; } params->resolutionX = (bbox.maxx - bbox.minx) / params->width; } /* check y axis */ if(params->height != 0) { params->resolutionY = (bbox.maxy - bbox.miny) / params->height; } else if(params->resolutionY != MS_WCS20_UNBOUNDED) { params->height = MS_NINT((bbox.maxy - bbox.miny) / params->resolutionY); } else { if(ABS(bbox.maxy - bbox.miny) != ABS(map->extent.maxy - map->extent.miny)) { double total = ABS(map->extent.maxy - map->extent.miny), part = ABS(bbox.maxy - bbox.miny); params->height = MS_NINT((part * map->height) / total); } else { params->height = map->height; } params->resolutionY = (bbox.maxy - bbox.miny) / params->height; } /* WCS 2.0 is center of pixel oriented */ bbox.minx += params->resolutionX * 0.5; bbox.maxx -= params->resolutionX * 0.5; bbox.miny += params->resolutionY * 0.5; bbox.maxy -= params->resolutionY * 0.5; /* if parameter 'outputcrs' is given, project the image to this crs */ if(params->outputcrs != NULL) { projectionObj outputProj; msInitProjection(&outputProj); if(msLoadProjectionString(&outputProj, params->outputcrs) == -1) { msFreeProjection(&outputProj); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, "InvalidParameterValue", "coverage", params->version); } if(msProjectionsDiffer(&(map->projection), &outputProj)) { msDebug("msWCSGetCoverage20(): projecting to outputcrs %s\n", params->outputcrs); msProjectRect(&(map->projection), &outputProj, &bbox); msFreeProjection(&(map->projection)); map->projection = outputProj; /* recalculate resolutions, needed if UOM changes (e.g: deg -> m) */ params->resolutionX = (bbox.maxx - bbox.minx) / params->width; params->resolutionY = (bbox.maxy - bbox.miny) / params->height; } } /* set the bounding box as new map extent */ map->extent = bbox; map->width = params->width; map->height = params->height; /* Are we exceeding the MAXSIZE limit on result size? */ if(map->width > map->maxsize || map->height > map->maxsize ) { msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Raster size out of range, width and height of " "resulting coverage must be no more than MAXSIZE=%d.", "msWCSGetCoverage20()", map->maxsize); return msWCSException(map, "InvalidParameterValue", "size", params->version); } /* Mapserver only supports square cells */ if (params->resolutionX <= params->resolutionY) map->cellsize = params->resolutionX; else map->cellsize = params->resolutionY; msDebug("msWCSGetCoverage20(): Set parameters from original" "data. Width: %d, height: %d, cellsize: %f, extent: %f,%f,%f,%f\n", map->width, map->height, map->cellsize, map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy); /** * Which format to use? * * 1) format parameter * 2) native format (from metadata) or GDAL format of the input dataset * 3) exception **/ if (!params->format) { if (cm.native_format) { params->format = msStrdup(cm.native_format); } } if (!params->format) { msSetError(MS_WCSERR, "Output format could not be automatically determined. " "Use the FORMAT parameter to specify a format.", "msWCSGetCoverage20()"); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, "MissingParameterValue", "format", params->version); } /* make sure layer is on */ layer->status = MS_ON; msMapComputeGeotransform(map); /* fill in bands rangeset info, if required. */ /* msWCSSetDefaultBandsRangeSetInfo(params, &cm, layer); */ /* msDebug("Bandcount: %d\n", cm.bandcount); */ msApplyDefaultOutputFormats(map); if (msGetOutputFormatIndex(map, params->format) == -1) { msSetError(MS_WCSERR, "Unrecognized value '%s' for the FORMAT parameter.", "msWCSGetCoverage20()", params->format); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, "InvalidParameterValue", "format", params->version); } /* create a temporary outputformat (we likely will need to tweak parts) */ format = msCloneOutputFormat(msSelectOutputFormat(map, params->format)); msApplyOutputFormat(&(map->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); if(msWCSGetCoverage20_GetBands(map, layer, params, &cm, &bandlist) != MS_SUCCESS) { msFree(bandlist); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, "InvalidParameterValue", "rangesubset", params->version); } msLayerSetProcessingKey(layer, "BANDS", bandlist); snprintf(numbands, sizeof(numbands), "%d", msCountChars(bandlist, ',')+1); msSetOutputFormatOption(map->outputformat, "BAND_COUNT", numbands); /* check for the interpolation */ /* Defaults to NEAREST */ if(params->interpolation != NULL) { if(EQUALN(params->interpolation,"NEAREST",7)) { msLayerSetProcessingKey(layer, "RESAMPLE", "NEAREST"); } else if(EQUAL(params->interpolation,"BILINEAR")) { msLayerSetProcessingKey(layer, "RESAMPLE", "BILINEAR"); } else if(EQUAL(params->interpolation,"AVERAGE")) { msLayerSetProcessingKey(layer, "RESAMPLE", "AVERAGE"); } else { msFree(bandlist); msSetError( MS_WCSERR, "'%s' specifies an unsupported interpolation method.", "msWCSGetCoverage20()", params->interpolation ); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, "InvalidParameterValue", "interpolation", params->version); } } else { msLayerSetProcessingKey(layer, "RESAMPLE", "NEAREST"); } /* since the dataset is only used in one layer, set it to be */ /* closed after drawing the layer. This normally defaults to */ /* DEFER and will produce a memory leak, because the dataset */ /* will not be closed. */ if( msLayerGetProcessingKey(layer, "CLOSE_CONNECTION") == NULL ) { msLayerSetProcessingKey(layer, "CLOSE_CONNECTION", "NORMAL"); } /* create the image object */ if (!map->outputformat) { msWCSClearCoverageMetadata20(&cm); msFree(bandlist); msSetError(MS_WCSERR, "The map outputformat is missing!", "msWCSGetCoverage20()"); return msWCSException(map, NULL, NULL, params->version); } else if (MS_RENDERER_PLUGIN(map->outputformat)) { image = msImageCreate(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->imagecolor); } else if (MS_RENDERER_RAWDATA(map->outputformat)) { image = msImageCreate(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->imagecolor); } else { msFree(bandlist); msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Map outputformat not supported for WCS!", "msWCSGetCoverage20()"); return msWCSException(map, NULL, NULL, params->version); } if (image == NULL) { msFree(bandlist); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, NULL, NULL, params->version); } if(layer->mask) { int maskLayerIdx = msGetLayerIndex(map,layer->mask); layerObj *maskLayer; outputFormatObj *altFormat; if(maskLayerIdx == -1) { msSetError(MS_MISCERR, "Layer (%s) references unknown mask layer (%s)", "msDrawLayer()", layer->name,layer->mask); return (MS_FAILURE); } maskLayer = GET_LAYER(map, maskLayerIdx); if(!maskLayer->maskimage) { int i,retcode; int origstatus, origlabelcache; char *origImageType = msStrdup(map->imagetype); altFormat = msSelectOutputFormat(map, "png24"); msInitializeRendererVTable(altFormat); /* TODO: check the png24 format hasn't been tampered with, i.e. it's agg */ maskLayer->maskimage= msImageCreate(image->width, image->height,altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!maskLayer->maskimage) { msSetError(MS_MISCERR, "Unable to initialize mask image.", "msDrawLayer()"); return (MS_FAILURE); } /* * force the masked layer to status on, and turn off the labelcache so that * eventual labels are added to the temporary image instead of being added * to the labelcache */ origstatus = maskLayer->status; origlabelcache = maskLayer->labelcache; maskLayer->status = MS_ON; maskLayer->labelcache = MS_OFF; /* draw the mask layer in the temporary image */ retcode = msDrawLayer(map, maskLayer, maskLayer->maskimage); maskLayer->status = origstatus; maskLayer->labelcache = origlabelcache; if(retcode != MS_SUCCESS) { return MS_FAILURE; } /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == MS_IMAGE_RENDERER(maskLayer->maskimage)) { MS_IMAGE_RENDERER(maskLayer->maskimage)->freeSymbol(s); s->renderer = NULL; } } } /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */ msFree(map->imagetype); map->imagetype = origImageType; } } /* Actually produce the "grid". */ if( MS_RENDERER_RAWDATA(map->outputformat) ) { status = msDrawRasterLayerLow( map, layer, image, NULL ); } else { rasterBufferObj rb; MS_IMAGE_RENDERER(image)->getRasterBufferHandle(image,&rb); status = msDrawRasterLayerLow( map, layer, image, &rb ); } if( status != MS_SUCCESS ) { msFree(bandlist); msFreeImage(image); msWCSClearCoverageMetadata20(&cm); return msWCSException(map, NULL, NULL, params->version ); } /* GML+Image */ /* Embed the image into multipart message */ if(params->multipart == MS_TRUE) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode, psRangeSet, psFile, psRangeParameters; xmlNsPtr psGmlNs = NULL, psGmlcovNs = NULL, psSweNs = NULL, psXLinkNs = NULL; wcs20coverageMetadataObj tmpCm; char *srs_uri, *default_filename; const char *filename; char *file_ref, *role; int length = 0, swapAxes; /* Create Document */ psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST MS_WCS_GML_COVERAGETYPE_RECTIFIED_GRID_COVERAGE); xmlDocSetRootElement(psDoc, psRootNode); msWCSPrepareNamespaces20(psDoc, psRootNode, map); psGmlNs = xmlSearchNs(psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_GML_NAMESPACE_PREFIX); psGmlcovNs = xmlSearchNs(psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_GMLCOV_NAMESPACE_PREFIX); psSweNs = xmlSearchNs(psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_SWE_NAMESPACE_PREFIX); xmlSearchNs(psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_WCS_NAMESPACE_PREFIX); psXLinkNs = xmlSearchNs(psDoc, psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlNewNsProp(psRootNode, psGmlNs, BAD_CAST "id", BAD_CAST layer->name); xmlSetNs(psRootNode, psGmlcovNs); srs_uri = msOWSGetProjURI(&map->projection, NULL, "CO", 1); tmpCm = cm; tmpCm.extent = map->extent; tmpCm.xsize = map->width; tmpCm.ysize = map->height; strlcpy(tmpCm.srs_uri, srs_uri, sizeof(tmpCm.srs_uri)); tmpCm.xresolution = map->gt.geotransform[1]; tmpCm.yresolution = map->gt.geotransform[5]; tmpCm.extent.minx = MIN(map->gt.geotransform[0], map->gt.geotransform[0] + map->width * tmpCm.xresolution); tmpCm.extent.miny = MIN(map->gt.geotransform[3], map->gt.geotransform[3] + map->height * tmpCm.yresolution); tmpCm.extent.maxx = MAX(map->gt.geotransform[0], map->gt.geotransform[0] + map->width * tmpCm.xresolution); tmpCm.extent.maxy = MAX(map->gt.geotransform[3], map->gt.geotransform[3] + map->height * tmpCm.yresolution); swapAxes = msWCSSwapAxes20(srs_uri); msFree(srs_uri); /* Setup layer information */ msWCSCommon20_CreateBoundedBy(layer, &tmpCm, psGmlNs, psRootNode, &(map->projection), swapAxes); msWCSCommon20_CreateDomainSet(layer, &tmpCm, psGmlNs, psRootNode, &(map->projection), swapAxes); psRangeSet = xmlNewChild(psRootNode, psGmlNs, BAD_CAST "rangeSet", NULL); psFile = xmlNewChild(psRangeSet, psGmlNs, BAD_CAST "File", NULL); /* TODO: wait for updated specifications */ psRangeParameters = xmlNewChild(psFile, psGmlNs, BAD_CAST "rangeParameters", NULL); default_filename = msStrdup("out."); default_filename = msStringConcatenate(default_filename, MS_IMAGE_EXTENSION(image->format)); filename = msGetOutputFormatOption(image->format, "FILENAME", default_filename); length = strlen("cid:coverage/") + strlen(filename) + 1; file_ref = msSmallMalloc(length); strlcpy(file_ref, "cid:coverage/", length); strlcat(file_ref, filename, length); msFree(default_filename); if(EQUAL(MS_IMAGE_MIME_TYPE(map->outputformat), "image/tiff")) { length = strlen(MS_WCS_20_PROFILE_GML_GEOTIFF) + 1; role = msSmallMalloc(length); strlcpy(role, MS_WCS_20_PROFILE_GML_GEOTIFF, length); } else { length = strlen(MS_IMAGE_MIME_TYPE(map->outputformat)) + 1; role = msSmallMalloc(length); strlcpy(role, MS_IMAGE_MIME_TYPE(map->outputformat), length); } xmlNewNsProp(psRangeParameters, psXLinkNs, BAD_CAST "href", BAD_CAST file_ref); xmlNewNsProp(psRangeParameters, psXLinkNs, BAD_CAST "role", BAD_CAST role); xmlNewNsProp(psRangeParameters, psXLinkNs, BAD_CAST "arcrole", BAD_CAST "fileReference"); xmlNewChild(psFile, psGmlNs, BAD_CAST "fileReference", BAD_CAST file_ref); xmlNewChild(psFile, psGmlNs, BAD_CAST "fileStructure", NULL); xmlNewChild(psFile, psGmlNs, BAD_CAST "mimeType", BAD_CAST MS_IMAGE_MIME_TYPE(map->outputformat)); msWCSCommon20_CreateRangeType(layer, &cm, bandlist, psGmlNs, psGmlcovNs, psSweNs, psXLinkNs, psRootNode); msIO_setHeader("Content-Type","multipart/related; boundary=wcs"); msIO_sendHeaders(); msIO_printf("\r\n--wcs\r\n"); msWCSWriteDocument20(map, psDoc); msWCSWriteFile20(map, image, params, 1); msFree(file_ref); msFree(role); xmlFreeDoc(psDoc); xmlCleanupParser(); /* just print out the file without gml */ } else { msWCSWriteFile20(map, image, params, 0); } msFree(bandlist); msWCSClearCoverageMetadata20(&cm); msFreeImage(image); return MS_SUCCESS; } #endif /* defined(USE_LIBXML2) */ #endif /* defined(USE_WCS_SVR) */ mapserver-6.4.1/mapaxisorder.sh0000755002461700001440000000577312261257215016365 0ustar tbonfortusers#!/bin/bash INFILE="./mapaxisorder.csv" OUTFILE="./mapaxisorder.h" # define an array 8x4096 filled with 0 unset ARRAY declare -a ARRAY for i in {0..4095} do ARRAY[$i]="00000000" done # fill array from $INFILE while read -r LINE do # numeric values only if [ "$LINE" -eq "$LINE" ] 2>/dev/null then let row=$(( $LINE / 8 )) let index=$(( $LINE % 8 )) unset tmp if [ $index -gt 0 ] then tmp=${ARRAY[$row]:0:$(( $index ))} fi ARRAY[$row]=${tmp}1${ARRAY[$row]:$(( $index+1 ))} fi done < $INFILE print_header () { echo '/******************************************************************************' echo ' * $Id: $' echo ' *' echo ' * Project: MapServer' echo ' * Purpose: Axis lookup table' echo ' *' echo ' ******************************************************************************' echo ' * Copyright (c) 1996-2005 Regents of the University of Minnesota.' echo ' *' echo ' * Permission is hereby granted, free of charge, to any person obtaining a' echo ' * copy of this software and associated documentation files (the "Software"),' echo ' * to deal in the Software without restriction, including without limitation' echo ' * the rights to use, copy, modify, merge, publish, distribute, sublicense,' echo ' * and/or sell copies of the Software, and to permit persons to whom the' echo ' * Software is furnished to do so, subject to the following conditions:' echo ' *' echo ' * The above copyright notice and this permission notice shall be included in ' echo ' * all copies of this Software or works derived from this Software.' echo ' *' echo ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS' echo ' * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,' echo ' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL' echo ' * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER' echo ' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING' echo ' * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER' echo ' * DEALINGS IN THE SOFTWARE.' echo ' ****************************************************************************/' } print_comment () { echo ' ' echo '/*' echo ' * Generated file' echo ' *' echo ' * This file was generated from by means of a script. Do not edit manually.' echo ' */' echo ' ' } print_body () { echo '#ifdef __cplusplus' echo 'extern "C" '{ echo '#endif' echo ' ' echo 'static unsigned char axisOrientationEpsgCodes[] = {' # traverse array and print out elements for i in {0..4095} do echo -n " ${ARRAY[$i]:7:1} << 7 | ${ARRAY[$i]:6:1} << 6 | ${ARRAY[$i]:5:1} << 5 | ${ARRAY[$i]:4:1} << 4 | ${ARRAY[$i]:3:1} << 3 | ${ARRAY[$i]:2:1} << 2 | ${ARRAY[$i]:1:1} << 1 | ${ARRAY[$i]:0:1} << 0" if [ $i -le 4094 ] then echo , else echo fi done echo '};' echo ' ' echo '#ifdef __cplusplus' echo '}' echo '#endif' } print_header > ./$OUTFILE print_comment >> ./$OUTFILE print_body >> ./$OUTFILE exit 0 mapserver-6.4.1/mapwcs11.c0000644002461700001440000016254112261257215015125 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OpenGIS Web Coverage Server (WCS) 1.1.0 Implementation. This * file holds some WCS 1.1.0 specific functions but other parts * are still implemented in mapwcs.c. * Author: Frank Warmerdam and the MapServer team. * ****************************************************************************** * Copyright (c) 2007, Frank Warmerdam * * 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. *****************************************************************************/ #include #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include "mapwcs.h" #if defined(USE_WCS_SVR) #include "mapwcs.h" #include "gdal.h" #include "cpl_string.h" /* GDAL string handling */ #endif #if defined(USE_LIBXML2) #include "maplibxml2.h" #endif #if defined(USE_WCS_SVR) && defined(USE_LIBXML2) /* ** msWCSException11() ** ** Report current MapServer error in XML exception format. ** Wrapper function around msOWSCommonExceptionReport. Merely ** passes WCS specific info. ** */ int msWCSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version) { int size = 0; char *errorString = NULL; char *errorMessage = NULL; char *schemasLocation = NULL; const char * encoding; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode = NULL; xmlNsPtr psNsOws = NULL; xmlChar *buffer = NULL; psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); errorString = msGetErrorString("\n"); errorMessage = msEncodeHTMLEntities(errorString); schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_1_0, schemasLocation, version, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage); xmlDocSetRootElement(psDoc, psRootNode); xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_printf("%s", buffer); /*free buffer and the document */ free(errorString); free(errorMessage); free(schemasLocation); xmlFree(buffer); xmlFreeDoc(psDoc); xmlFreeNs(psNsOws); /* clear error since we have already reported it */ msResetErrorList(); return MS_FAILURE; } /************************************************************************/ /* msWCSGetFormatsList11() */ /* */ /* Fetch back a comma delimited formats list for the past layer */ /* if one is supplied, otherwise for all formats supported by */ /* the server. Formats should be identified by mime type. */ /************************************************************************/ static char *msWCSGetFormatsList11( mapObj *map, layerObj *layer ) { char *format_list = msStrdup(""); char **tokens = NULL, **formats = NULL; int i, numtokens = 0, numformats; char *value; msApplyDefaultOutputFormats(map); /* -------------------------------------------------------------------- */ /* Parse from layer metadata. */ /* -------------------------------------------------------------------- */ if( layer != NULL && (value = msOWSGetEncodeMetadata( &(layer->metadata),"CO","formats", "GTiff" )) != NULL ) { tokens = msStringSplit(value, ' ', &numtokens); msFree(value); } /* -------------------------------------------------------------------- */ /* Parse from map.web metadata. */ /* -------------------------------------------------------------------- */ else if((value = msOWSGetEncodeMetadata( &(map->web.metadata), "CO", "formats", NULL)) != NULL ) { tokens = msStringSplit(value, ' ', &numtokens); msFree(value); } /* -------------------------------------------------------------------- */ /* Or generate from all configured raster output formats that */ /* look plausible. */ /* -------------------------------------------------------------------- */ else { tokens = (char **) calloc(map->numoutputformats,sizeof(char*)); for( i = 0; i < map->numoutputformats; i++ ) { switch( map->outputformatlist[i]->renderer ) { /* seeminly normal raster format */ #ifdef USE_GD case MS_RENDER_WITH_GD: #endif case MS_RENDER_WITH_AGG: case MS_RENDER_WITH_RAWDATA: tokens[numtokens++] = msStrdup(map->outputformatlist[i]->name); break; /* rest of formats aren't really WCS compatible */ default: break; } } } /* -------------------------------------------------------------------- */ /* Convert outputFormatObj names into mime types and remove */ /* duplicates. */ /* -------------------------------------------------------------------- */ numformats = 0; formats = (char **) calloc(sizeof(char*),numtokens); for( i = 0; i < numtokens; i++ ) { int format_i, j; const char *mimetype; for( format_i = 0; format_i < map->numoutputformats; format_i++ ) { if( strcasecmp(map->outputformatlist[format_i]->name, tokens[i]) == 0 ) break; } if( format_i == map->numoutputformats ) { msDebug("Failed to find outputformat info on format '%s', ignore.\n", tokens[i] ); continue; } mimetype = map->outputformatlist[format_i]->mimetype; if( mimetype == NULL || strlen(mimetype) == 0 ) { msDebug("No mimetime for format '%s', ignoring.\n", tokens[i] ); continue; } for( j = 0; j < numformats; j++ ) { if( strcasecmp(mimetype,formats[j]) == 0 ) break; } if( j < numformats ) { msDebug( "Format '%s' ignored since mimetype '%s' duplicates another outputFormatObj.\n", tokens[i], mimetype ); continue; } formats[numformats++] = msStrdup(mimetype); } msFreeCharArray(tokens,numtokens); /* -------------------------------------------------------------------- */ /* Turn mimetype list into comma delimited form for easy use */ /* with xml functions. */ /* -------------------------------------------------------------------- */ for(i=0; i 0) { format_list = msStringConcatenate(format_list, (char *) ","); } format_list = msStringConcatenate(format_list, formats[i]); } msFreeCharArray(formats,numformats); return format_list; } /************************************************************************/ /* msWCSGetCapabilities11_CoverageSummary() */ /* */ /* Generate a WCS 1.1 CoverageSummary. */ /************************************************************************/ static int msWCSGetCapabilities11_CoverageSummary( mapObj *map, wcsParamsObj *params, cgiRequestObj *req, xmlDocPtr doc, xmlNodePtr psContents, layerObj *layer ) { coverageMetadataObj cm; int status; const char *value; char *owned_value; char *format_list; xmlNodePtr psCSummary; xmlNsPtr psOwsNs = xmlSearchNs( doc, psContents, BAD_CAST "ows" ); char **tokens = NULL; int i = 0; int n = 0; status = msWCSGetCoverageMetadata(layer, &cm); if(status != MS_SUCCESS) return MS_FAILURE; psCSummary = xmlNewChild( psContents, NULL, BAD_CAST "CoverageSummary", NULL ); /* -------------------------------------------------------------------- */ /* Title (from description) */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata( &(layer->metadata), "CO", "description"); if( value == NULL ) value = msOWSLookupMetadata( &(layer->metadata), "CO", "title"); if( value == NULL ) value = layer->name; xmlNewChild( psCSummary, psOwsNs, BAD_CAST "Title", BAD_CAST value ); /* -------------------------------------------------------------------- */ /* Abstract */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata( &(layer->metadata), "CO", "abstract"); xmlNewChild( psCSummary, psOwsNs, BAD_CAST "Abstract", BAD_CAST value ); /* -------------------------------------------------------------------- */ /* Keywords */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata(&(layer->metadata), "CO", "keywordlist"); if (value) { xmlNodePtr psNode; psNode = xmlNewChild(psCSummary, psOwsNs, BAD_CAST "Keywords", NULL); tokens = msStringSplit(value, ',', &n); if (tokens && n > 0) { for (i=0; imetadata), "CO", "metadatalink_href"); if (value) { xmlNodePtr psMetadata = xmlNewChild(psCSummary, psOwsNs, BAD_CAST "Metadata", NULL); xmlNsPtr psXlinkNs = xmlSearchNs( doc, xmlDocGetRootElement(doc), BAD_CAST "xlink" ); const char *metadatalink_type = msOWSLookupMetadata(&(layer->metadata), "CO", "metadatalink_type"); const char *metadatalink_format = msOWSLookupMetadata(&(layer->metadata), "CO", "metadatalink_format"); xmlNewNsProp(psMetadata, psXlinkNs, BAD_CAST "type", BAD_CAST "simple"); xmlNewNsProp(psMetadata, psXlinkNs, BAD_CAST "href", BAD_CAST value); if (metadatalink_type != NULL) { xmlNewProp(psMetadata, BAD_CAST "about", BAD_CAST metadatalink_type); } if (metadatalink_format != NULL) { xmlNewNsProp(psMetadata, psXlinkNs, BAD_CAST "role", BAD_CAST metadatalink_format); } } /* -------------------------------------------------------------------- */ /* WGS84 bounding box. */ /* -------------------------------------------------------------------- */ xmlAddChild( psCSummary, msOWSCommonWGS84BoundingBox( psOwsNs, 2, cm.llextent.minx, cm.llextent.miny, cm.llextent.maxx, cm.llextent.maxy )); /* -------------------------------------------------------------------- */ /* Supported CRSes. */ /* -------------------------------------------------------------------- */ if( (owned_value = msOWSGetProjURN( &(layer->projection), &(layer->metadata), "CO", MS_FALSE)) != NULL ) { /* ok */ } else if((owned_value = msOWSGetProjURN( &(layer->map->projection), &(layer->map->web.metadata), "CO", MS_FALSE)) != NULL ) { /* ok */ } else msDebug( "mapwcs.c: missing required information, no SRSs defined.\n"); if( owned_value != NULL && strlen(owned_value) > 0 ) msLibXml2GenerateList( psCSummary, NULL, "SupportedCRS", owned_value, ' ' ); msFree( owned_value ); /* -------------------------------------------------------------------- */ /* SupportedFormats */ /* -------------------------------------------------------------------- */ format_list = msWCSGetFormatsList11( map, layer ); if (strlen(format_list) > 0 ) msLibXml2GenerateList( psCSummary, NULL, "SupportedFormat", format_list, ',' ); msFree( format_list ); /* -------------------------------------------------------------------- */ /* Identifier (layer name) */ /* -------------------------------------------------------------------- */ xmlNewChild( psCSummary, NULL, BAD_CAST "Identifier", BAD_CAST layer->name ); return MS_SUCCESS; } /************************************************************************/ /* msWCSGetCapabilities11() */ /************************************************************************/ int msWCSGetCapabilities11(mapObj *map, wcsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode, psMainNode, psNode; char *identifier_list = NULL, *format_list = NULL; const char *updatesequence=NULL; const char *encoding; xmlNsPtr psOwsNs, psXLinkNs; char *schemaLocation = NULL; char *xsi_schemaLocation = NULL; char *script_url=NULL, *script_url_encoded=NULL; xmlChar *buffer = NULL; int size = 0, i; msIOContext *context = NULL; int ows_version = OWS_1_1_0; /* -------------------------------------------------------------------- */ /* Handle updatesequence */ /* -------------------------------------------------------------------- */ updatesequence = msOWSLookupMetadata(&(map->web.metadata), "CO", "updatesequence"); encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); if (params->updatesequence != NULL) { i = msOWSNegotiateUpdateSequence(params->updatesequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_WCSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWCSGetCapabilities11()", params->updatesequence, updatesequence); return msWCSException11(map, "updatesequence", "CurrentUpdateSequence", params->version); } if (i > 0) { /* invalid */ msSetError(MS_WCSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWCSGetCapabilities11()", params->updatesequence, updatesequence); return msWCSException11(map, "updatesequence", "InvalidUpdateSequence", params->version); } } /* -------------------------------------------------------------------- */ /* Build list of layer identifiers available. */ /* -------------------------------------------------------------------- */ identifier_list = msStrdup(""); for(i=0; inumlayers; i++) { layerObj *layer = map->layers[i]; int new_length; if(!msWCSIsLayerSupported(layer)) continue; new_length = strlen(identifier_list) + strlen(layer->name) + 2; identifier_list = (char *) realloc(identifier_list,new_length); if( strlen(identifier_list) > 0 ) strcat( identifier_list, "," ); strcat( identifier_list, layer->name ); } /* -------------------------------------------------------------------- */ /* Create document. */ /* -------------------------------------------------------------------- */ psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "Capabilities"); xmlDocSetRootElement(psDoc, psRootNode); /* -------------------------------------------------------------------- */ /* Name spaces */ /* -------------------------------------------------------------------- */ xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wcs/1.1", NULL)); psOwsNs = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_110_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psXLinkNs = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX ); /*xmlNewProp(psRootNode, BAD_CAST " */ xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->version ); updatesequence = msOWSLookupMetadata(&(map->web.metadata), "CO", "updatesequence"); if (updatesequence) xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence); schemaLocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); xsi_schemaLocation = msStrdup("http://www.opengis.net/wcs/1.1"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemaLocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/wcs/1.1/wcsGetCapabilities.xsd "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, MS_OWSCOMMON_OWS_110_NAMESPACE_URI); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemaLocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/ows/1.1.0/owsAll.xsd"); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); msFree(schemaLocation); msFree(xsi_schemaLocation); /* -------------------------------------------------------------------- */ /* Service metadata. */ /* -------------------------------------------------------------------- */ if( params->section == NULL || strstr(params->section,"All") != NULL || strstr(params->section,"ServiceIdentification") != NULL ) { xmlAddChild(psRootNode, msOWSCommonServiceIdentification( psOwsNs, map, "OGC WCS", params->version, "CO")); } /*service provider*/ if( params->section == NULL || strstr(params->section,"All") != NULL || strstr(params->section,"ServiceProvider") != NULL ) { xmlAddChild(psRootNode, msOWSCommonServiceProvider( psOwsNs, psXLinkNs, map, "CO")); } /* -------------------------------------------------------------------- */ /* Operations metadata. */ /* -------------------------------------------------------------------- */ /*operation metadata */ if ((script_url=msOWSGetOnlineResource(map, "CO", "onlineresource", req)) == NULL || (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL) { msSetError(MS_WCSERR, "Server URL not found", "msWCSGetCapabilities11()"); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } free( script_url ); if( params->section == NULL || strstr(params->section,"All") != NULL || strstr(params->section,"OperationsMetadata") != NULL ) { psMainNode= xmlAddChild(psRootNode,msOWSCommonOperationsMetadata(psOwsNs)); /* -------------------------------------------------------------------- */ /* GetCapabilities - add Sections and AcceptVersions? */ /* -------------------------------------------------------------------- */ psNode = msOWSCommonOperationsMetadataOperation( psOwsNs, psXLinkNs, "GetCapabilities", OWS_METHOD_GETPOST, script_url_encoded); xmlAddChild(psMainNode, psNode); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "service", "WCS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "version", (char *)params->version)); /* -------------------------------------------------------------------- */ /* DescribeCoverage */ /* -------------------------------------------------------------------- */ if (msOWSRequestIsEnabled(map, NULL, "C", "DescribeCoverage", MS_FALSE)) { psNode = msOWSCommonOperationsMetadataOperation( psOwsNs, psXLinkNs, "DescribeCoverage", OWS_METHOD_GETPOST, script_url_encoded); xmlAddChild(psMainNode, psNode); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "service", "WCS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "version", (char *)params->version)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "identifiers", identifier_list )); } /* -------------------------------------------------------------------- */ /* GetCoverage */ /* -------------------------------------------------------------------- */ if (msOWSRequestIsEnabled(map, NULL, "C", "GetCoverage", MS_FALSE)) { psNode = msOWSCommonOperationsMetadataOperation( psOwsNs, psXLinkNs, "GetCoverage", OWS_METHOD_GETPOST, script_url_encoded); format_list = msWCSGetFormatsList11( map, NULL ); xmlAddChild(psMainNode, psNode); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "service", "WCS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "version", (char *)params->version)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "Identifier", identifier_list )); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "InterpolationType", "NEAREST_NEIGHBOUR,BILINEAR" )); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "format", format_list )); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "store", "false" )); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType( ows_version, psOwsNs, "Parameter", "GridBaseCRS", "urn:ogc:def:crs:epsg::4326" )); msFree( format_list ); } } /* -------------------------------------------------------------------- */ /* Contents section. */ /* -------------------------------------------------------------------- */ if( params->section == NULL || strstr(params->section,"All") != NULL || strstr(params->section,"Contents") != NULL ) { psMainNode = xmlNewChild( psRootNode, NULL, BAD_CAST "Contents", NULL ); if(ows_request->numlayers == 0) { xmlAddChild(psMainNode, xmlNewComment(BAD_CAST "WARNING: No WCS layers are enabled. " "Check wcs/ows_enable_request settings.")); } else { for(i=0; inumlayers; i++) { layerObj *layer = map->layers[i]; int status; if(!msWCSIsLayerSupported(layer)) continue; if (!msIntegerInArray(layer->index, ows_request->enabled_layers, ows_request->numlayers)) continue; status = msWCSGetCapabilities11_CoverageSummary( map, params, req, psDoc, psMainNode, layer ); if(status != MS_SUCCESS) return MS_FAILURE; } } } /* -------------------------------------------------------------------- */ /* Write out the document. */ /* -------------------------------------------------------------------- */ if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); context = msIO_getHandler(stdout); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_contextWrite(context, buffer, size); xmlFree(buffer); /*free buffer and the document */ /*xmlFree(buffer);*/ xmlFreeDoc(psDoc); xmlCleanupParser(); /* clean up */ free( script_url_encoded ); free( identifier_list ); return(MS_SUCCESS); } /************************************************************************/ /* msWCSDescribeCoverage_CoverageDescription11() */ /************************************************************************/ static int msWCSDescribeCoverage_CoverageDescription11( layerObj *layer, wcsParamsObj *params, xmlNodePtr psRootNode, xmlNsPtr psOwsNs ) { int status; coverageMetadataObj cm; xmlNodePtr psCD, psDomain, psSD, psGridCRS; const char *value; /* -------------------------------------------------------------------- */ /* Verify layer is processable. */ /* -------------------------------------------------------------------- */ if( msCheckParentPointer(layer->map,"map") == MS_FAILURE ) return MS_FAILURE; if(!msWCSIsLayerSupported(layer)) return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Setup coverage metadata. */ /* -------------------------------------------------------------------- */ status = msWCSGetCoverageMetadata(layer, &cm); if(status != MS_SUCCESS) return status; /* fill in bands rangeset info, if required. */ msWCSSetDefaultBandsRangeSetInfo( params, &cm, layer ); /* -------------------------------------------------------------------- */ /* Create CoverageDescription node. */ /* -------------------------------------------------------------------- */ psCD = xmlNewChild( psRootNode, NULL, BAD_CAST "CoverageDescription", NULL ); /* -------------------------------------------------------------------- */ /* Title (from description) */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata( &(layer->metadata), "CO", "description"); if( value == NULL ) value = layer->name; xmlNewChild( psCD, psOwsNs, BAD_CAST "Title", BAD_CAST value ); /* -------------------------------------------------------------------- */ /* Abstract */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata( &(layer->metadata), "CO", "abstract"); xmlNewChild( psCD, psOwsNs, BAD_CAST "Abstract", BAD_CAST value ); /* -------------------------------------------------------------------- */ /* Keywords */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata(&(layer->metadata), "CO", "keywordlist"); if (value) msLibXml2GenerateList( xmlNewChild(psCD, psOwsNs, BAD_CAST "Keywords", NULL), NULL, "Keyword", value, ',' ); /* -------------------------------------------------------------------- */ /* Identifier (layer name) */ /* -------------------------------------------------------------------- */ xmlNewChild( psCD, NULL, BAD_CAST "Identifier", BAD_CAST layer->name); /* -------------------------------------------------------------------- */ /* Domain */ /* -------------------------------------------------------------------- */ psDomain = xmlNewChild( psCD, NULL, BAD_CAST "Domain", NULL ); /* -------------------------------------------------------------------- */ /* SpatialDomain */ /* -------------------------------------------------------------------- */ psSD = xmlNewChild( psDomain, NULL, BAD_CAST "SpatialDomain", NULL ); /* -------------------------------------------------------------------- */ /* imageCRS bounding box. */ /* -------------------------------------------------------------------- */ xmlAddChild( psSD, msOWSCommonBoundingBox( psOwsNs, "urn:ogc:def:crs:OGC::imageCRS", 2, 0, 0, cm.xsize-1, cm.ysize-1 )); /* -------------------------------------------------------------------- */ /* native CRS bounding box. */ /* -------------------------------------------------------------------- */ xmlAddChild( psSD, msOWSCommonBoundingBox( psOwsNs, cm.srs_urn, 2, cm.extent.minx, cm.extent.miny, cm.extent.maxx, cm.extent.maxy )); /* -------------------------------------------------------------------- */ /* WGS84 bounding box. */ /* -------------------------------------------------------------------- */ xmlAddChild( psSD, msOWSCommonWGS84BoundingBox( psOwsNs, 2, cm.llextent.minx, cm.llextent.miny, cm.llextent.maxx, cm.llextent.maxy )); /* -------------------------------------------------------------------- */ /* GridCRS */ /* -------------------------------------------------------------------- */ { char format_buf[500]; psGridCRS = xmlNewChild( psSD, NULL, BAD_CAST "GridCRS", NULL ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridBaseCRS", BAD_CAST cm.srs_urn ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridType", BAD_CAST "urn:ogc:def:method:WCS:1.1:2dSimpleGrid" ); sprintf( format_buf, "%.15g %.15g", cm.geotransform[0]+cm.geotransform[1]/2+cm.geotransform[2]/2, cm.geotransform[3]+cm.geotransform[4]/2+cm.geotransform[5]/2); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridOrigin", BAD_CAST format_buf ); sprintf( format_buf, "%.15g %.15g", cm.geotransform[1], cm.geotransform[5] ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridOffsets", BAD_CAST format_buf ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridCS", BAD_CAST "urn:ogc:def:cs:OGC:0.0:Grid2dSquareCS" ); } #ifdef notdef /* TemporalDomain */ /* TODO: figure out when a temporal domain is valid, for example only tiled rasters support time as a domain, plus we need a timeitem */ if(msOWSLookupMetadata(&(layer->metadata), "CO", "timeposition") || msOWSLookupMetadata(&(layer->metadata), "CO", "timeperiod")) { msIO_printf(" \n"); /* TimePosition (should support a value AUTO, then we could mine positions from the timeitem) */ msOWSPrintEncodeMetadataList(stdout, &(layer->metadata), "CO", "timeposition", NULL, NULL, " %s\n", NULL); /* TODO: add TimePeriod (only one per layer) */ msIO_printf(" \n"); } msIO_printf(" \n"); #endif /* -------------------------------------------------------------------- */ /* Range */ /* -------------------------------------------------------------------- */ { xmlNodePtr psField, psInterpMethods, psAxis; char *value; psField = xmlNewChild( xmlNewChild( psCD, NULL, BAD_CAST "Range", NULL ), NULL, BAD_CAST "Field", NULL ); value = msOWSGetEncodeMetadata( &(layer->metadata), "CO", "rangeset_label", NULL ); if( value ) xmlNewChild( psField, psOwsNs, BAD_CAST "Title", BAD_CAST value ); msFree(value); /* ows:Abstract? TODO */ value = msOWSGetEncodeMetadata( &(layer->metadata), "CO", "rangeset_name", "raster" ); xmlNewChild( psField, NULL, BAD_CAST "Identifier", BAD_CAST value ); msFree(value); xmlNewChild( xmlNewChild( psField, NULL, BAD_CAST "Definition", NULL ), psOwsNs, BAD_CAST "AnyValue", NULL ); /* NullValue */ value = msOWSGetEncodeMetadata( &(layer->metadata), "CO", "rangeset_nullvalue", NULL); if( value ) xmlNewChild( psField, NULL, BAD_CAST "NullValue", BAD_CAST value ); msFree(value); /* InterpolationMethods */ psInterpMethods = xmlNewChild( psField, NULL, BAD_CAST "InterpolationMethods", NULL ); xmlNewChild( psInterpMethods, NULL, BAD_CAST "InterpolationMethod", BAD_CAST "bilinear" ); xmlNewChild( psInterpMethods, NULL, BAD_CAST "Default", BAD_CAST "nearest neighbor" ); /* -------------------------------------------------------------------- */ /* Bands axis. */ /* -------------------------------------------------------------------- */ { xmlNodePtr psKeys; int iBand; value = msOWSGetEncodeMetadata( &(layer->metadata), "CO", "bands_name", "bands" ); psAxis = xmlNewChild( psField, NULL, BAD_CAST "Axis", NULL ); xmlNewProp( psAxis, BAD_CAST "identifier", BAD_CAST value ); msFree(value); psKeys = xmlNewChild( psAxis, NULL, BAD_CAST "AvailableKeys", NULL ); for( iBand = 0; iBand < cm.bandcount; iBand++ ) { char szBandName[32]; snprintf( szBandName, sizeof(szBandName), "%d", iBand+1 ); xmlNewChild( psKeys, NULL, BAD_CAST "Key", BAD_CAST szBandName ); } } } /* -------------------------------------------------------------------- */ /* SupportedCRS */ /* -------------------------------------------------------------------- */ { char *owned_value; if( (owned_value = msOWSGetProjURN( &(layer->projection), &(layer->metadata), "CO", MS_FALSE)) != NULL ) { /* ok */ } else if((owned_value = msOWSGetProjURN( &(layer->map->projection), &(layer->map->web.metadata), "CO", MS_FALSE)) != NULL ) { /* ok */ } else msDebug( "mapwcs.c: missing required information, no SRSs defined.\n"); if( owned_value != NULL && strlen(owned_value) > 0 ) msLibXml2GenerateList( psCD, NULL, "SupportedCRS", owned_value, ' ' ); msFree( owned_value ); } /* -------------------------------------------------------------------- */ /* SupportedFormats */ /* -------------------------------------------------------------------- */ { char *format_list; format_list = msWCSGetFormatsList11( layer->map, layer ); if (strlen(format_list) > 0 ) msLibXml2GenerateList( psCD, NULL, "SupportedFormat", format_list, ',' ); msFree( format_list ); } return MS_SUCCESS; } /************************************************************************/ /* msWCSDescribeCoverage11() */ /************************************************************************/ int msWCSDescribeCoverage11(mapObj *map, wcsParamsObj *params, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode; xmlNsPtr psOwsNs; char *schemaLocation = NULL; char *xsi_schemaLocation = NULL; const char *encoding; int i,j; encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); /* -------------------------------------------------------------------- */ /* We will actually get the coverages list as a single item in */ /* a string list with that item having the comma delimited */ /* coverage names. Split it up now, and assign back in place */ /* of the old coverages list. */ /* -------------------------------------------------------------------- */ if( CSLCount(params->coverages) == 1 ) { char **old_coverages = params->coverages; params->coverages = CSLTokenizeStringComplex( old_coverages[0], ",", FALSE, FALSE ); CSLDestroy( old_coverages ); } /* -------------------------------------------------------------------- */ /* Validate that the requested coverages exist as named layers. */ /* -------------------------------------------------------------------- */ if(params->coverages) { /* use the list */ for( j = 0; params->coverages[j]; j++ ) { i = msGetLayerIndex(map, params->coverages[j]); if ( (i == -1) || (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) ) { msSetError( MS_WCSERR, "COVERAGE %s cannot be opened / does not exist", "msWCSDescribeCoverage()", params->coverages[j]); return msWCSException11(map, "coverage", "CoverageNotDefined", params->version); } } } /* -------------------------------------------------------------------- */ /* Create document. */ /* -------------------------------------------------------------------- */ psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "CoverageDescriptions"); xmlDocSetRootElement(psDoc, psRootNode); /* -------------------------------------------------------------------- */ /* Name spaces */ /* -------------------------------------------------------------------- */ xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wcs/1.1", NULL)); psOwsNs = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_110_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX ); schemaLocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); xsi_schemaLocation = msStrdup("http://www.opengis.net/wcs/1.1"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemaLocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/wcs/1.1/wcsDescribeCoverage.xsd "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, MS_OWSCOMMON_OWS_110_NAMESPACE_URI); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemaLocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/ows/1.1.0/owsAll.xsd"); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); msFree(schemaLocation); msFree(xsi_schemaLocation); /* -------------------------------------------------------------------- */ /* Generate a CoverageDescription for each requested coverage. */ /* -------------------------------------------------------------------- */ if(params->coverages) { /* use the list */ for( j = 0; params->coverages[j]; j++ ) { i = msGetLayerIndex(map, params->coverages[j]); msWCSDescribeCoverage_CoverageDescription11((GET_LAYER(map, i)), params, psRootNode, psOwsNs ); } } else { /* return all layers */ for(i=0; inumlayers; i++) { if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) continue; msWCSDescribeCoverage_CoverageDescription11((GET_LAYER(map, i)), params, psRootNode, psOwsNs ); } } /* -------------------------------------------------------------------- */ /* Write out the document. */ /* -------------------------------------------------------------------- */ { xmlChar *buffer = NULL; int size = 0; msIOContext *context = NULL; if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; if (encoding) msIO_setHeader("Content-Type","text/xml; charset=%s", encoding); else msIO_setHeader("Content-Type","text/xml"); msIO_sendHeaders(); context = msIO_getHandler(stdout); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1); msIO_contextWrite(context, buffer, size); xmlFree(buffer); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ xmlFreeDoc(psDoc); xmlCleanupParser(); return MS_SUCCESS; } #endif /* defined(USE_WCS_SVR) && defined(USE_LIBXML2) */ /************************************************************************/ /* msWCSGetCoverageBands11() */ /* */ /* We expect input to be of the form: */ /* RangeSubset=raster:interpolation[bands[1]]. */ /* */ /* RangeSet=raster:[bands[1,2]] */ /* or */ /* RangeSet=raster:bilinear */ /* */ /* This function tries to return a bandlist if found, and will */ /* also push an INTERPOLATION keyword into the parameters list */ /* if found in the RangeSubset. */ /************************************************************************/ #if defined(USE_WCS_SVR) int msWCSGetCoverageBands11( mapObj *map, cgiRequestObj *request, wcsParamsObj *params, layerObj *lp, char **p_bandlist ) { char *rangesubset, *field_id; const char *axis_id, *value; int i; /* -------------------------------------------------------------------- */ /* Fetch the RangeSubset from the parameters, skip building a */ /* bands list if not found. */ /* -------------------------------------------------------------------- */ value = msWCSGetRequestParameter(request, "RangeSubset"); if( value == NULL ) return MS_SUCCESS; rangesubset = msStrdup(value); /* -------------------------------------------------------------------- */ /* What is the (rangeset_name)? */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata( &(lp->metadata), "CO", "rangeset_name" ); if( value == NULL ) value = "raster"; field_id = msStrdup(value); /* -------------------------------------------------------------------- */ /* What is the (bands_name)? */ /* -------------------------------------------------------------------- */ axis_id = msOWSLookupMetadata( &(lp->metadata), "CO", "bands_name" ); if( axis_id == NULL ) axis_id = "bands"; /* -------------------------------------------------------------------- */ /* Parse out the field identifier from the request and verify. */ /* -------------------------------------------------------------------- */ value = rangesubset + strlen(field_id); if( strcasecmp(rangesubset,field_id) == 0 ) return MS_SUCCESS; /* we only got field ... default options */ if( strlen(rangesubset) <= strlen(field_id)+1 || strncasecmp(rangesubset,field_id,strlen(field_id)) != 0 || (*value != '[' && *value != ':') ) { msSetError( MS_WCSERR, "RangeSubset field name malformed, expected '%s', got RangeSubset=%s", "msWCSGetCoverageBands11()", field_id, rangesubset ); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } free( field_id ); field_id = NULL; /* -------------------------------------------------------------------- */ /* Parse out the interpolation, if found. */ /* -------------------------------------------------------------------- */ if( *value == ':' ) { assert( params->interpolation == NULL ); params->interpolation = msStrdup(value+1); for( i = 0; params->interpolation[i] != '\0'; i++ ) { if( params->interpolation[i] == '[' ) { params->interpolation[i] = '\0'; break; } } value += strlen(params->interpolation) + 1; } /* -------------------------------------------------------------------- */ /* Parse out the axis name, and verify. */ /* -------------------------------------------------------------------- */ if( *value != '[' ) return MS_SUCCESS; value++; if( strlen(value) <= strlen(axis_id)+1 || strncasecmp(value,axis_id,strlen(axis_id)) != 0 || value[strlen(axis_id)] != '[' ) { msSetError( MS_WCSERR, "RangeSubset axis name malformed, expected '%s', got RangeSubset=%s", "msWCSGetCoverageBands11()", axis_id, rangesubset ); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } /* -------------------------------------------------------------------- */ /* Parse the band list. Basically assuming the band list is */ /* everything from here to a close ';'. */ /* -------------------------------------------------------------------- */ value += strlen(axis_id) + 1; *p_bandlist = msStrdup(value); for( i = 0; (*p_bandlist)[i] != '\0'; i++ ) { if( (*p_bandlist)[i] == '[' ) { (*p_bandlist)[i] = '\0'; break; } } return MS_SUCCESS; } #endif /************************************************************************/ /* msWCSReturnCoverage11() */ /* */ /* Return a render image as a coverage to the caller with WCS */ /* 1.1 "mime" wrapping. */ /************************************************************************/ #if defined(USE_WCS_SVR) int msWCSReturnCoverage11( wcsParamsObj *params, mapObj *map, imageObj *image ) { int status, i; char *filename = NULL; char *base_dir = NULL; const char *encoding; const char *fo_filename; encoding = msOWSLookupMetadata(&(map->web.metadata), "CO", "encoding"); fo_filename = msGetOutputFormatOption( image->format, "FILENAME", NULL ); /* -------------------------------------------------------------------- */ /* Fetch the driver we will be using and check if it supports */ /* VSIL IO. */ /* -------------------------------------------------------------------- */ if( EQUALN(image->format->driver,"GDAL/",5) ) { GDALDriverH hDriver; const char *pszExtension = image->format->extension; msAcquireLock( TLOCK_GDAL ); hDriver = GDALGetDriverByName( image->format->driver+5 ); if( hDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find %s driver.", "msWCSReturnCoverage11()", image->format->driver+5 ); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } if( pszExtension == NULL ) pszExtension = "img.tmp"; if( GDALGetMetadataItem( hDriver, GDAL_DCAP_VIRTUALIO, NULL ) != NULL ) { base_dir = msTmpFile(map, map->mappath, "/vsimem/wcsout", NULL); if( fo_filename ) filename = msStrdup(CPLFormFilename(base_dir, fo_filename,NULL)); else filename = msStrdup(CPLFormFilename(base_dir, "out", pszExtension )); /* CleanVSIDir( "/vsimem/wcsout" ); */ msReleaseLock( TLOCK_GDAL ); status = msSaveImage(map, image, filename); if( status != MS_SUCCESS ) { msFree(filename); msSetError(MS_MISCERR, "msSaveImage() failed", "msWCSReturnCoverage11()"); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } } msReleaseLock( TLOCK_GDAL ); } /* -------------------------------------------------------------------- */ /* Output stock header. */ /* -------------------------------------------------------------------- */ if (encoding) { msIO_setHeader("Content-Type","multipart/mixed; boundary=wcs"); msIO_sendHeaders(); msIO_fprintf( stdout, "\r\n--wcs\r\n" "Content-Type: text/xml; charset=%s\r\n" "Content-ID: wcs.xml\r\n\r\n" "\n" "\n" " \n", encoding); } else { msIO_setHeader("Content-Type","multipart/mixed; boundary=wcs"); msIO_sendHeaders(); msIO_fprintf( stdout, "\r\n--wcs\r\n" "Content-Type: text/xml\r\n" "Content-ID: wcs.xml\r\n\r\n" "\n" "\n" " \n"); } /* -------------------------------------------------------------------- */ /* If we weren't able to write data under /vsimem, then we just */ /* output a single "stock" filename. */ /* -------------------------------------------------------------------- */ if( filename == NULL ) { msIO_fprintf( stdout, " \n" " \n" "\n" "\r\n--wcs\r\n" "Content-Type: %s\r\n" "Content-Description: coverage data\r\n" "Content-Transfer-Encoding: binary\r\n" "Content-ID: coverage/wcs.%s\r\n" "Content-Disposition: INLINE\r\n\r\n", MS_IMAGE_EXTENSION(map->outputformat), MS_IMAGE_MIME_TYPE(map->outputformat), MS_IMAGE_EXTENSION(map->outputformat)); status = msSaveImage(map, image, NULL); if( status != MS_SUCCESS ) { msSetError( MS_MISCERR, "msSaveImage() failed", "msWCSReturnCoverage11()"); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } msIO_fprintf( stdout, "\r\n--wcs--\r\n" ); return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* When potentially listing multiple files, we take great care */ /* to identify the "primary" file and list it first. In fact */ /* it is the only file listed in the coverages document. */ /* -------------------------------------------------------------------- */ { char **all_files = CPLReadDir( base_dir ); int count = CSLCount(all_files); if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; msAcquireLock( TLOCK_GDAL ); for( i = count-1; i >= 0; i-- ) { const char *this_file = all_files[i]; if( EQUAL(this_file,".") || EQUAL(this_file,"..") ) { all_files = CSLRemoveStrings( all_files, i, 1, NULL ); continue; } if( i > 0 && EQUAL(this_file,CPLGetFilename(filename)) ) { all_files = CSLRemoveStrings( all_files, i, 1, NULL ); all_files = CSLInsertString(all_files,0,CPLGetFilename(filename)); i++; } } msIO_fprintf( stdout, " \n" " \n" "\n", CPLGetFilename(filename) ); /* -------------------------------------------------------------------- */ /* Dump all the files in the memory directory as mime sections. */ /* -------------------------------------------------------------------- */ count = CSLCount(all_files); for( i = 0; i < count; i++ ) { const char *mimetype = NULL; FILE *fp; unsigned char block[4000]; int bytes_read; if( i == 0 ) mimetype = MS_IMAGE_MIME_TYPE(map->outputformat); if( mimetype == NULL ) mimetype = "application/octet-stream"; msIO_fprintf( stdout, "\r\n--wcs\r\n" "Content-Type: %s\r\n" "Content-Description: coverage data\r\n" "Content-Transfer-Encoding: binary\r\n" "Content-ID: coverage/%s\r\n" "Content-Disposition: INLINE\r\n\r\n", mimetype, all_files[i]); fp = VSIFOpenL( CPLFormFilename(base_dir, all_files[i], NULL), "rb" ); if( fp == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to open %s for streaming to stdout.", "msWCSReturnCoverage11()", all_files[i] ); return MS_FAILURE; } while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 ) msIO_fwrite( block, 1, bytes_read, stdout ); VSIFCloseL( fp ); VSIUnlink( CPLFormFilename(base_dir, all_files[i], NULL) ); } msFree(base_dir); msFree(filename); CSLDestroy( all_files ); msReleaseLock( TLOCK_GDAL ); msIO_fprintf( stdout, "\r\n--wcs--\r\n" ); return MS_SUCCESS; } } #endif /* defined(USE_WCS_SVR) && defined(USE_LIBXML2) */ /************************************************************************/ /* ==================================================================== */ /* If we don't have libxml2 but WCS SVR was selected, then */ /* report WCS 1.1 requests as unsupported. */ /* ==================================================================== */ /************************************************************************/ #if defined(USE_WCS_SVR) && !defined(USE_LIBXML2) #include "mapwcs.h" /* ==================================================================== */ int msWCSDescribeCoverage11(mapObj *map, wcsParamsObj *params, owsRequestObj *ows_request) { msSetError( MS_WCSERR, "WCS 1.1 request made, but mapserver requires libxml2 for WCS 1.1 services and this is not configured.", "msWCSDescribeCoverage11()", "NoApplicableCode" ); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } /* ==================================================================== */ int msWCSGetCapabilities11(mapObj *map, wcsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request) { msSetError( MS_WCSERR, "WCS 1.1 request made, but mapserver requires libxml2 for WCS 1.1 services and this is not configured.", "msWCSGetCapabilities11()", "NoApplicableCode" ); return msWCSException11(map, "mapserv", "NoApplicableCode", params->version); } int msWCSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version) { /* fallback to reporting using 1.0 style exceptions. */ return msWCSException( map, locator, exceptionCode, "1.0.0" ); } #endif /* defined(USE_WCS_SVR) && !defined(USE_LIBXML2) */ mapserver-6.4.1/mapserv.h0000644002461700001440000000521612261257215015146 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations supporting mapserv.c. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPSERV_H #define MAPSERV_H #if defined(_WIN32) && !defined(__CYGWIN__) #include #endif #include #include #include "maptemplate.h" #include "maptile.h" #include "cgiutil.h" /* ** Defines */ #define NUMEXP "[-]?(([0-9]+)|([0-9]*[.][0-9]+)([eE][-+]?[0-9]+)?)" #define EXTENT_PADDING .05 /* ** Macros */ #define TEMPLATE_TYPE(s) (((strncmp("http://", s, 7) == 0) || (strncmp("https://", s, 8) == 0) || (strncmp("ftp://", s, 6)) == 0) ? MS_URL : MS_FILE) MS_DLL_EXPORT int msCGIWriteLog(mapservObj *mapserv, int show_error); MS_DLL_EXPORT void msCGIWriteError(mapservObj *mapserv); MS_DLL_EXPORT mapObj *msCGILoadMap(mapservObj *mapserv); int msCGISetMode(mapservObj *mapserv); int msCGILoadForm(mapservObj *mapserv); int msCGIDispatchBrowseRequest(mapservObj *mapserv); int msCGIDispatchCoordinateRequest(mapservObj *mapserv); int msCGIDispatchQueryRequest(mapservObj *mapserv); int msCGIDispatchImageRequest(mapservObj *mapserv); int msCGIDispatchLegendRequest(mapservObj *mapserv); int msCGIDispatchLegendIconRequest(mapservObj *mapserv); MS_DLL_EXPORT int msCGIDispatchRequest(mapservObj *mapserv); #endif /* MAPSERV_H */ mapserver-6.4.1/mapows.h0000644002461700001440000005374112261257215015005 0ustar tbonfortusers/***************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Web Services (WMS, WFS, WCS) support function definitions * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPOWS_H #define MAPOWS_H #include "maphttp.h" #include /* This is the URL to the official OGC Schema Repository. We use it by * default for OGC services unless the ows_schemas_lcoation web metadata * is set in the mapfile. */ #define OWS_DEFAULT_SCHEMAS_LOCATION "http://schemas.opengis.net" /*==================================================================== * mapows.c *====================================================================*/ typedef struct { char *pszVersion; char *pszUpdateSequence; char *pszRequest; char *pszService; char *pszTypeName; char *pszFilter; char *pszGeometryName; int nMaxFeatures; char *pszBbox; /* only used with a Get Request */ char *pszOutputFormat; /* only used with DescibeFeatureType */ char *pszFeatureId; char *pszSrs; char *pszResultType; char *pszPropertyName; int nStartIndex; char *pszAcceptVersions; } wfsParamsObj; /* * sosParamsObj * Used to preprocess SOS request parameters * */ typedef struct { char *pszVersion; char *pszAcceptVersions; char *pszUpdateSequence; char *pszRequest; char *pszService; char *pszOutputFormat; char *pszSensorId; char *pszProcedure; char *pszOffering; char *pszObservedProperty; char *pszEventTime; char *pszResult; char *pszResponseFormat; char *pszResultModel; char *pszResponseMode; char *pszBBox; char *pszFeatureOfInterest; char *pszSrsName; } sosParamsObj; /* wmsParamsObj * * Used to preprocess WMS request parameters and combine layers that can * be comined in a GetMap request. */ typedef struct { char *onlineresource; hashTableObj *params; int numparams; char *httpcookiedata; } wmsParamsObj; /* owsRequestObj: Represent a OWS specific request with its enabled layers */ typedef struct { int numlayers; int *enabled_layers; char *service; char *version; char *request; void *document; /* xmlDocPtr or CPLXMLNode* */ } owsRequestObj; MS_DLL_EXPORT int msOWSDispatch(mapObj *map, cgiRequestObj *request, int ows_mode); MS_DLL_EXPORT const char * msOWSLookupMetadata(hashTableObj *metadata, const char *namespaces, const char *name); MS_DLL_EXPORT const char * msOWSLookupMetadataWithLanguage(hashTableObj *metadata, const char *namespaces, const char *name, const char *validated_language); MS_DLL_EXPORT const char * msOWSLookupMetadata2(hashTableObj *pri, hashTableObj *sec, const char *namespaces, const char *name); MS_DLL_EXPORT int msOWSRequestIsEnabled(mapObj *map, layerObj *layer, const char *namespaces, const char *name, int check_all_layers); MS_DLL_EXPORT void msOWSRequestLayersEnabled(mapObj *map, const char *namespaces, const char *request, owsRequestObj *request_layers); MS_DLL_EXPORT int msOWSParseRequestMetadata(const char *metadata, const char *request, int *disabled); /* Constants for OWS Service version numbers */ #define OWS_0_1_2 0x000102 #define OWS_0_1_4 0x000104 #define OWS_0_1_6 0x000106 #define OWS_0_1_7 0x000107 #define OWS_1_0_0 0x010000 #define OWS_1_0_1 0x010001 #define OWS_1_0_6 0x010006 #define OWS_1_0_7 0x010007 #define OWS_1_0_8 0x010008 #define OWS_1_1_0 0x010100 #define OWS_1_1_1 0x010101 #define OWS_1_1_2 0x010102 #define OWS_1_3_0 0x010300 #define OWS_2_0_0 0x020000 #define OWS_2_0_1 0x020001 #define OWS_VERSION_MAXLEN 20 /* Buffer size for msOWSGetVersionString() */ #define OWS_VERSION_NOTSET -1 #define OWS_VERSION_BADFORMAT -2 MS_DLL_EXPORT int msOWSParseVersionString(const char *pszVersion); MS_DLL_EXPORT const char *msOWSGetVersionString(int nVersion, char *pszBuffer); #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR) MS_DLL_EXPORT int msOWSMakeAllLayersUnique(mapObj *map); MS_DLL_EXPORT int msOWSNegotiateVersion(int requested_version, int supported_versions[], int num_supported_versions); MS_DLL_EXPORT char *msOWSTerminateOnlineResource(const char *src_url); MS_DLL_EXPORT char *msOWSGetOnlineResource(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req); MS_DLL_EXPORT char *msOWSGetOnlineResource2(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req, const char *validated_language); MS_DLL_EXPORT const char *msOWSGetSchemasLocation(mapObj *map); MS_DLL_EXPORT const char *msOWSGetLanguage(mapObj *map, const char *context); MS_DLL_EXPORT char **msOWSGetLanguageList(mapObj *map, const char *namespaces, int *numitems); MS_DLL_EXPORT char *msOWSGetLanguageFromList(mapObj *map, const char *namespaces, const char *requested_language); /* OWS_NOERR and OWS_WARN passed as action_if_not_found to printMetadata() */ #define OWS_NOERR 0 #define OWS_WARN 1 /* OWS_WMS and OWS_WFS used for functions that differ in behavior between */ /* WMS and WFS services (e.g. msOWSPrintLatLonBoundingBox()) */ #define OWS_WMS 1 #define OWS_WFS 2 MS_DLL_EXPORT int msOWSPrintInspireCommonExtendedCapabilities(FILE *stream, mapObj *map, const char *namespaces, const int action_if_not_found, const char *tag_name, const char *validated_language, const int service); int msOWSPrintInspireCommonMetadata(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found); int msOWSPrintInspireCommonLanguages(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const char *validated_language); MS_DLL_EXPORT int msOWSPrintMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintEncodeMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) ; int msOWSPrintEncodeMetadata2(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language); char *msOWSGetEncodeMetadata(hashTableObj *metadata, const char *namespaces, const char *name, const char *default_value); int msOWSPrintValidateMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintGroupMetadata(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintGroupMetadata2(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language); int msOWSPrintURLType(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *tag_format, const char *tag_name, const char *type_format, const char *width_format, const char *height_format, const char *urlfrmt_format, const char *href_format, int type_is_mandatory, int width_is_mandatory, int height_is_mandatory, int format_is_mandatory, int href_is_mandatory, const char *default_type, const char *default_width, const char *default_height, const char *default_urlfrmt, const char *default_href, const char *tabspace); int msOWSPrintParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintEncodeParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintMetadataList(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, const char *startTag, const char *endTag, const char *itemFormat, const char *default_value); int msOWSPrintEncodeMetadataList(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, const char *startTag, const char *endTag, const char *itemFormat, const char *default_value); int msOWSPrintEncodeParamList(FILE *stream, const char *name, const char *value, int action_if_not_found, char delimiter, const char *startTag, const char *endTag, const char *format, const char *default_value); void msOWSProjectToWGS84(projectionObj *srcproj, rectObj *ext); void msOWSPrintLatLonBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, projectionObj *wfsproj, int nService); void msOWSPrintEX_GeographicBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj); void msOWSPrintBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, hashTableObj *layer_meta, hashTableObj *map_meta, const char *namespaces, int wms_version); void msOWSPrintContactInfo( FILE *stream, const char *tabspace, int nVersion, hashTableObj *metadata, const char *namespaces ); int msOWSGetLayerExtent(mapObj *map, layerObj *lp, const char *namespaces, rectObj *ext); int msOWSExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, mapObj *map, int bCheckLocalCache); void msOWSProcessException(layerObj *lp, const char *pszFname, int nErrorCode, const char *pszFuncName); char *msOWSBuildURLFilename(const char *pszPath, const char *pszURL, const char *pszExt); const char *msOWSGetEPSGProj(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne); char *msOWSGetProjURN(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne); char *msOWSGetProjURI(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne); void msOWSGetDimensionInfo(layerObj *layer, const char *pszDimension, const char **pszDimUserValue, const char **pszDimUnits, const char **pszDimDefault, const char **pszDimNearValue, const char **pszDimUnitSymbol, const char **pszDimMultiValue); int msOWSNegotiateUpdateSequence(const char *requested_updateSequence, const char *updatesequence); outputFormatObj *msOwsIsOutputFormatValid(mapObj *map, const char *format, hashTableObj *metadata, const char *namespaces, const char *name); #endif /* #if any wxs service enabled */ /*==================================================================== * mapgml.c *====================================================================*/ #define OWS_GML2 0 /* Supported GML formats */ #define OWS_GML3 1 #define OWS_WFS_FEATURE_COLLECTION_NAME "msFeatureCollection" #define OWS_GML_DEFAULT_GEOMETRY_NAME "msGeometry" #define OWS_GML_OCCUR_UNBOUNDED -1 /* TODO, there must be a better way to generalize these lists of objects... */ typedef struct { char *name; /* name of the item */ char *alias; /* is the item aliased for presentation? (NULL if not) */ char *type; /* raw type for this item (NULL for a "string") (TODO: should this be a lookup table instead?) */ #ifndef __cplusplus char *template; /* presentation string for this item, needs to be a complete XML tag */ #else char *_template; /* presentation string for this item, needs to be a complete XML tag */ #endif int encode; /* should the value be HTML encoded? Default is MS_TRUE */ int visible; /* should this item be output, default is MS_FALSE */ int width; /* field width, zero if unknown */ int precision; /* field precision (decimal places), zero if unknown or N/A */ } gmlItemObj; typedef struct { gmlItemObj *items; int numitems; } gmlItemListObj; typedef struct { char *name; /* name of the constant */ char *type; /* raw type for this item (NULL for a "string") */ char *value; /* output value for this constant (output will look like: value) */ } gmlConstantObj; typedef struct { gmlConstantObj *constants; int numconstants; } gmlConstantListObj; typedef struct { char *name; /* name of the geometry (type of GML property) */ char *type; /* raw type for these geometries (point|multipoint|line|multiline|polygon|multipolygon */ int occurmin, occurmax; /* number of occurances (default 0,1) */ } gmlGeometryObj; typedef struct { gmlGeometryObj *geometries; int numgeometries; } gmlGeometryListObj; typedef struct { char *name; /* name of the group */ char **items; /* list of items in the group */ int numitems; /* number of items */ char *type; /* name of the complex type */ } gmlGroupObj; typedef struct { gmlGroupObj *groups; int numgroups; } gmlGroupListObj; typedef struct { char *prefix; char *uri; char *schemalocation; } gmlNamespaceObj; typedef struct { gmlNamespaceObj *namespaces; int numnamespaces; } gmlNamespaceListObj; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) MS_DLL_EXPORT int msItemInGroups(char *name, gmlGroupListObj *groupList); MS_DLL_EXPORT gmlItemListObj *msGMLGetItems(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeItems(gmlItemListObj *itemList); MS_DLL_EXPORT gmlConstantListObj *msGMLGetConstants(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeConstants(gmlConstantListObj *constantList); MS_DLL_EXPORT gmlGeometryListObj *msGMLGetGeometries(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeGeometries(gmlGeometryListObj *geometryList); MS_DLL_EXPORT gmlGroupListObj *msGMLGetGroups(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeGroups(gmlGroupListObj *groupList); MS_DLL_EXPORT gmlNamespaceListObj *msGMLGetNamespaces(webObj *web, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeNamespaces(gmlNamespaceListObj *namespaceList); #endif /* export to fix bug 851 */ MS_DLL_EXPORT int msGMLWriteQuery(mapObj *map, char *filename, const char *namespaces); #ifdef USE_WFS_SVR MS_DLL_EXPORT int msGMLWriteWFSQuery(mapObj *map, FILE *stream, char *wfs_namespace, int outputformat); #endif /*==================================================================== * mapwms.c *====================================================================*/ int msWMSDispatch(mapObj *map, cgiRequestObj *req, owsRequestObj *ows_request, int force_wms_mode); MS_DLL_EXPORT int msWMSLoadGetMapParams(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format, const char *wms_request, owsRequestObj *ows_request); /*==================================================================== * mapwmslayer.c *====================================================================*/ #define WMS_GETMAP 1 #define WMS_GETFEATUREINFO 2 #define WMS_GETLEGENDGRAPHIC 3 int msInitWmsParamsObj(wmsParamsObj *wmsparams); void msFreeWmsParamsObj(wmsParamsObj *wmsparams); int msPrepareWMSLayerRequest(int nLayerId, mapObj *map, layerObj *lp, int nRequestType, enum MS_CONNECTION_TYPE lastconnectiontype, wmsParamsObj *psLastWMSParams, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, httpRequestObj *pasReqInfo, int *numRequests); int msDrawWMSLayerLow(int nLayerId, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, layerObj *lp, imageObj *img); MS_DLL_EXPORT char *msWMSGetFeatureInfoURL(mapObj *map, layerObj *lp, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat); int msWMSLayerExecuteRequest(mapObj *map, int nOWSLayers, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, int type); /*==================================================================== * mapwfs.c *====================================================================*/ /* Supported DescribeFeature formats */ #define OWS_DEFAULT_SCHEMA 0 /* basically a GML 2.1 schema */ #define OWS_SFE_SCHEMA 1 /* GML for simple feature exchange (formerly GML3L0) */ MS_DLL_EXPORT int msWFSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request, int force_wfs_mode); int msWFSParseRequest(mapObj *map, cgiRequestObj *, owsRequestObj *ows_request, wfsParamsObj *, int force_wfs_mode); wfsParamsObj *msWFSCreateParamsObj(void); void msWFSFreeParamsObj(wfsParamsObj *wfsparams); int msWFSIsLayerSupported(layerObj *lp); int msWFSException(mapObj *map, const char *locator, const char *code, const char *version); #ifdef USE_WFS_SVR const char *msWFSGetGeomElementName(mapObj *map, layerObj *lp); int msWFSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version); int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *wfsparams, cgiRequestObj *req, owsRequestObj *ows_request); char *msWFSGetOutputFormatList(mapObj *map, layerObj *layer,const char*version); #endif /*==================================================================== * mapwfslayer.c *====================================================================*/ int msPrepareWFSLayerRequest(int nLayerId, mapObj *map, layerObj *lp, httpRequestObj *pasReqInfo, int *numRequests); void msWFSUpdateRequestInfo(layerObj *lp, httpRequestObj *pasReqInfo); int msWFSLayerOpen(layerObj *lp, const char *pszGMLFilename, rectObj *defaultBBOX); int msWFSLayerIsOpen(layerObj *lp); int msWFSLayerInitItemInfo(layerObj *layer); int msWFSLayerGetItems(layerObj *layer); int msWFSLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); int msWFSLayerClose(layerObj *lp); MS_DLL_EXPORT char *msWFSExecuteGetFeature(layerObj *lp); /*==================================================================== * mapcontext.c *====================================================================*/ MS_DLL_EXPORT int msWriteMapContext(mapObj *map, FILE *stream); MS_DLL_EXPORT int msSaveMapContext(mapObj *map, char *filename); MS_DLL_EXPORT int msLoadMapContext(mapObj *map, char *filename, int unique_layer_names); MS_DLL_EXPORT int msLoadMapContextURL(mapObj *map, char *urlfilename, int unique_layer_names); /*==================================================================== * mapwcs.c *====================================================================*/ int msWCSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request); /* only 1 public function */ /*==================================================================== * mapogsos.c *====================================================================*/ int msSOSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request); /* only 1 public function */ #endif /* MAPOWS_H */ mapserver-6.4.1/astyle.sh0000755002461700001440000000041512261257215015154 0ustar tbonfortusers#!/bin/bash ASTYLEOPTS="--style=kr --indent=spaces=2 -c --lineend=linux -S" ASTYLEBIN=astyle $ASTYLEBIN $ASTYLEOPTS *.c *.h *.cpp opengl/*.h $ASTYLEBIN $ASTYLEOPTS -R 'mapscript/*.c' $ASTYLEBIN $ASTYLEOPTS -R 'mapscript/*.h' #find . -name '*.orig' -exec rm -f {} \; mapserver-6.4.1/fonts/0000755002461700001440000000000012261257215014445 5ustar tbonfortusersmapserver-6.4.1/fonts/README0000644002461700001440000000105012261257215015321 0ustar tbonfortusersFontsets are very simple lookup tables so that you can use simple aliases to refer to fonts rather than cryptic file names. The format is as follows: [font file] [font alias] The font file is either fullpath or a path relative to the fontset file. Font alias can be up to 20 chars and is a short name by which you may refer to fonts in your map files. We can't distribute any TrueType fonts with the system, but there are lots of good free ones available on the net. Visit the FreeType homepage (http://www.freetype.org/) for lots of good pointers. mapserver-6.4.1/fonts/fonts.list.example0000644002461700001440000000147412261257215020133 0ustar tbonfortusersarial arial.ttf arial-bold arialbd.ttf arial-italic ariali.ttf arial-bold-italic arialbi.ttf arial_black ariblk.ttf comic_sans comic.ttf comic_sans-bold comicbd.ttf courier cour.ttf courier-bold courbd.ttf courier-italic couri.ttf courier-bold-italic courbi.ttf georgia georgia.ttf georgia-bold georgiab.ttf georgia-italic georgiai.ttf georgia-bold-italic georgiaz.ttf impact impact.ttf monotype.com monotype.ttf recreation_symbols recreate.ttf times times.ttf times-bold timesbd.ttf times-italic timesi.ttf times-bold-italic timesbi.ttf trebuchet_ms trebuc.ttf trebuchet_ms-bold trebucbd.ttf trebuchet_ms-italic trebucit.ttf trebuchet_ms-bold-italic trebucbi.ttf verdana verdana.ttf verdana-bold verdanab.ttf verdana-italic verdanai.ttf verdana-bold-italic verdanaz.ttf mapserver-6.4.1/maprasterquery.c0000644002461700001440000016001612261257215016550 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of query operations on rasters. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include "mapserver.h" #include "mapresample.h" #include "mapthread.h" #include "mapraster.h" int msRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record); int msRASTERLayerGetItems(layerObj *layer); #ifdef USE_GDAL /* ==================================================================== */ /* For now the rasterLayerInfo lives here since it is just used */ /* to hold information related to queries. */ /* ==================================================================== */ typedef struct { /* query cache results */ int query_results; int query_alloc_max; int query_request_max; int query_result_hard_max; int raster_query_mode; int band_count; int refcount; rectObj which_rect; int next_shape; double *qc_x; double *qc_y; double *qc_x_reproj; double *qc_y_reproj; float *qc_values; int *qc_class; int *qc_red; int *qc_green; int *qc_blue; int *qc_count; int *qc_tileindex; /* query bound in force */ shapeObj *searchshape; /* Only nearest result to this point. */ int range_mode; /* MS_QUERY_SINGLE, MS_QUERY_MULTIPLE or -1 (skip test) */ double range_dist; pointObj target_point; GDALColorTableH hCT; double shape_tolerance; } rasterLayerInfo; #define RQM_UNKNOWN 0 #define RQM_ENTRY_PER_PIXEL 1 #define RQM_HIST_ON_CLASS 2 #define RQM_HIST_ON_VALUE 3 extern int InvGeoTransform( double *gt_in, double *gt_out ); #define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y)) /************************************************************************/ /* addResult() */ /* */ /* this is a copy of the code in mapquery.c. Should we prepare */ /* a small public API for managing results caches? */ /************************************************************************/ static int addResult(resultCacheObj *cache, int classindex, int shapeindex, int tileindex) { int i; if(cache->numresults == cache->cachesize) { /* just add it to the end */ if(cache->cachesize == 0) cache->results = (resultObj *) malloc(sizeof(resultObj)*MS_RESULTCACHEINCREMENT); else cache->results = (resultObj *) realloc(cache->results, sizeof(resultObj)*(cache->cachesize+MS_RESULTCACHEINCREMENT)); if(!cache->results) { msSetError(MS_MEMERR, "Realloc() error.", "addResult()"); return(MS_FAILURE); } cache->cachesize += MS_RESULTCACHEINCREMENT; } i = cache->numresults; cache->results[i].classindex = classindex; cache->results[i].tileindex = tileindex; cache->results[i].shapeindex = shapeindex; cache->results[i].resultindex = -1; /* unused */ cache->numresults++; return(MS_SUCCESS); } /************************************************************************/ /* msRasterLayerInfoFree() */ /************************************************************************/ static void msRasterLayerInfoFree( layerObj *layer ) { rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo == NULL ) return; if( rlinfo->qc_x != NULL ) { free( rlinfo->qc_x ); free( rlinfo->qc_y ); free( rlinfo->qc_x_reproj ); free( rlinfo->qc_y_reproj ); } if( rlinfo->qc_values ) free( rlinfo->qc_values ); if( rlinfo->qc_class ) { free( rlinfo->qc_class ); } if( rlinfo->qc_red ) { free( rlinfo->qc_red ); free( rlinfo->qc_green ); free( rlinfo->qc_blue ); } if( rlinfo->qc_count != NULL ) free( rlinfo->qc_count ); if( rlinfo->qc_tileindex != NULL ) free( rlinfo->qc_tileindex ); free( rlinfo ); layer->layerinfo = NULL; } /************************************************************************/ /* msRasterLayerInfoInitialize() */ /************************************************************************/ static void msRasterLayerInfoInitialize( layerObj *layer ) { rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo != NULL ) return; rlinfo = (rasterLayerInfo *) msSmallCalloc(1,sizeof(rasterLayerInfo)); layer->layerinfo = rlinfo; rlinfo->band_count = -1; rlinfo->raster_query_mode = RQM_ENTRY_PER_PIXEL; rlinfo->range_mode = -1; /* inactive */ rlinfo->refcount = 0; rlinfo->shape_tolerance = 0.0; /* We need to do this or the layer->layerinfo will be interpreted */ /* as shapefile access info because the default connectiontype is */ /* MS_SHAPEFILE. */ if (layer->connectiontype != MS_WMS) layer->connectiontype = MS_RASTER; rlinfo->query_result_hard_max = 1000000; if( CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" ) != NULL ) { rlinfo->query_result_hard_max = atoi(CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" )); } } /************************************************************************/ /* msRasterQueryAddPixel() */ /************************************************************************/ static void msRasterQueryAddPixel( layerObj *layer, pointObj *location, pointObj *reprojectedLocation, float *values ) { rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; int red = 0, green = 0, blue = 0, nodata = FALSE; int p_class = -1; if( rlinfo->query_results == rlinfo->query_result_hard_max ) return; /* -------------------------------------------------------------------- */ /* Is this our first time in? If so, do an initial allocation */ /* for the data arrays suitable to our purposes. */ /* -------------------------------------------------------------------- */ if( rlinfo->query_alloc_max == 0 ) { rlinfo->query_alloc_max = 2; switch( rlinfo->raster_query_mode ) { case RQM_ENTRY_PER_PIXEL: rlinfo->qc_x = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_y = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_x_reproj = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_y_reproj = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_values = (float *) msSmallCalloc(sizeof(float), rlinfo->query_alloc_max*rlinfo->band_count); rlinfo->qc_red = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); rlinfo->qc_green = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); rlinfo->qc_blue = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); if( layer->numclasses > 0 ) rlinfo->qc_class = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); break; case RQM_HIST_ON_CLASS: break; case RQM_HIST_ON_VALUE: break; default: assert( FALSE ); } } /* -------------------------------------------------------------------- */ /* Reallocate the data arrays larger if they are near the max */ /* now. */ /* -------------------------------------------------------------------- */ if( rlinfo->query_results == rlinfo->query_alloc_max ) { rlinfo->query_alloc_max = rlinfo->query_alloc_max * 2 + 100; if( rlinfo->qc_x != NULL ) rlinfo->qc_x = msSmallRealloc(rlinfo->qc_x, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_y != NULL ) rlinfo->qc_y = msSmallRealloc(rlinfo->qc_y, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_x_reproj != NULL ) rlinfo->qc_x_reproj = msSmallRealloc(rlinfo->qc_x_reproj, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_y_reproj != NULL ) rlinfo->qc_y_reproj = msSmallRealloc(rlinfo->qc_y_reproj, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_values != NULL ) rlinfo->qc_values = msSmallRealloc(rlinfo->qc_values, sizeof(float) * rlinfo->query_alloc_max * rlinfo->band_count ); if( rlinfo->qc_class != NULL ) rlinfo->qc_class = msSmallRealloc(rlinfo->qc_class, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_red != NULL ) rlinfo->qc_red = msSmallRealloc(rlinfo->qc_red, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_green != NULL ) rlinfo->qc_green = msSmallRealloc(rlinfo->qc_green, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_blue != NULL ) rlinfo->qc_blue = msSmallRealloc(rlinfo->qc_blue, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_count != NULL ) rlinfo->qc_count = msSmallRealloc(rlinfo->qc_count, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_tileindex != NULL ) rlinfo->qc_tileindex = msSmallRealloc(rlinfo->qc_tileindex, sizeof(int) * rlinfo->query_alloc_max); } /* -------------------------------------------------------------------- */ /* Handle colormap */ /* -------------------------------------------------------------------- */ if( rlinfo->hCT != NULL ) { int pct_index = (int) floor(values[0]); GDALColorEntry sEntry; if( GDALGetColorEntryAsRGB( rlinfo->hCT, pct_index, &sEntry ) ) { red = sEntry.c1; green = sEntry.c2; blue = sEntry.c3; if( sEntry.c4 == 0 ) nodata = TRUE; } else nodata = TRUE; } /* -------------------------------------------------------------------- */ /* Color derived from greyscale value. */ /* -------------------------------------------------------------------- */ else { if( rlinfo->band_count >= 3 ) { red = (int) MAX(0,MIN(255,values[0])); green = (int) MAX(0,MIN(255,values[1])); blue = (int) MAX(0,MIN(255,values[2])); } else { red = green = blue = (int) MAX(0,MIN(255,values[0])); } } /* -------------------------------------------------------------------- */ /* Handle classification. */ /* */ /* NOTE: The following is really quite inadequate to deal with */ /* classifications based on [red], [green] and [blue] as */ /* described in: */ /* http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1021 */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_class != NULL ) { p_class = msGetClass_FloatRGB(layer, values[0], red, green, blue ); if( p_class == -1 ) nodata = TRUE; else { nodata = FALSE; rlinfo->qc_class[rlinfo->query_results] = p_class; if( layer->class[p_class]->numstyles > 0 ) { red = layer->class[p_class]->styles[0]->color.red; green = layer->class[p_class]->styles[0]->color.green; blue = layer->class[p_class]->styles[0]->color.blue; } else { red = green = blue = 0; } } } /* -------------------------------------------------------------------- */ /* Record the color. */ /* -------------------------------------------------------------------- */ rlinfo->qc_red[rlinfo->query_results] = red; rlinfo->qc_green[rlinfo->query_results] = green; rlinfo->qc_blue[rlinfo->query_results] = blue; /* -------------------------------------------------------------------- */ /* Record spatial location. */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_x != NULL ) { rlinfo->qc_x[rlinfo->query_results] = location->x; rlinfo->qc_y[rlinfo->query_results] = location->y; rlinfo->qc_x_reproj[rlinfo->query_results] = reprojectedLocation->x; rlinfo->qc_y_reproj[rlinfo->query_results] = reprojectedLocation->y; } /* -------------------------------------------------------------------- */ /* Record actual pixel value(s). */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_values != NULL ) memcpy( rlinfo->qc_values + rlinfo->query_results * rlinfo->band_count, values, sizeof(float) * rlinfo->band_count ); /* -------------------------------------------------------------------- */ /* Add to the results cache. */ /* -------------------------------------------------------------------- */ if( ! nodata ) { addResult( layer->resultcache, p_class, rlinfo->query_results, 0 ); rlinfo->query_results++; } } /************************************************************************/ /* msRasterQueryByRectLow() */ /************************************************************************/ static int msRasterQueryByRectLow(mapObj *map, layerObj *layer, GDALDatasetH hDS, rectObj queryRect) { double adfGeoTransform[6], adfInvGeoTransform[6]; double dfXMin, dfYMin, dfXMax, dfYMax, dfX, dfY, dfAdjustedRange; int nWinXOff, nWinYOff, nWinXSize, nWinYSize; int nRXSize, nRYSize; float *pafRaster; int nBandCount, *panBandMap, iPixel, iLine; CPLErr eErr; rasterLayerInfo *rlinfo; rectObj searchrect; int needReproject = MS_FALSE; rlinfo = (rasterLayerInfo *) layer->layerinfo; /* -------------------------------------------------------------------- */ /* Reproject the search rect into the projection of this */ /* layer/file if needed. */ /* -------------------------------------------------------------------- */ searchrect = queryRect; #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection))) { msProjectRect(&(map->projection), &(layer->projection), &searchrect); needReproject = MS_TRUE; } else layer->project = MS_FALSE; #endif /* -------------------------------------------------------------------- */ /* Transform the rectangle in target ground coordinates to */ /* pixel/line extents on the file. Process all 4 corners, to */ /* build extents. */ /* -------------------------------------------------------------------- */ nRXSize = GDALGetRasterXSize( hDS ); nRYSize = GDALGetRasterYSize( hDS ); msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform ); InvGeoTransform( adfGeoTransform, adfInvGeoTransform ); /* top left */ dfXMin = dfXMax = GEO_TRANS(adfInvGeoTransform, searchrect.minx, searchrect.maxy); dfYMin = dfYMax = GEO_TRANS(adfInvGeoTransform+3, searchrect.minx, searchrect.maxy); /* top right */ dfX = GEO_TRANS(adfInvGeoTransform , searchrect.maxx, searchrect.maxy); dfY = GEO_TRANS(adfInvGeoTransform+3, searchrect.maxx, searchrect.maxy); dfXMin = MIN(dfXMin,dfX); dfXMax = MAX(dfXMax,dfX); dfYMin = MIN(dfYMin,dfY); dfYMax = MAX(dfYMax,dfY); /* bottom left */ dfX = GEO_TRANS(adfInvGeoTransform , searchrect.minx, searchrect.miny); dfY = GEO_TRANS(adfInvGeoTransform+3, searchrect.minx, searchrect.miny); dfXMin = MIN(dfXMin,dfX); dfXMax = MAX(dfXMax,dfX); dfYMin = MIN(dfYMin,dfY); dfYMax = MAX(dfYMax,dfY); /* bottom right */ dfX = GEO_TRANS(adfInvGeoTransform , searchrect.maxx, searchrect.miny); dfY = GEO_TRANS(adfInvGeoTransform+3, searchrect.maxx, searchrect.miny); dfXMin = MIN(dfXMin,dfX); dfXMax = MAX(dfXMax,dfX); dfYMin = MIN(dfYMin,dfY); dfYMax = MAX(dfYMax,dfY); /* -------------------------------------------------------------------- */ /* Trim the rectangle to the area of the file itself, but out */ /* to the edges of the touched edge pixels. */ /* -------------------------------------------------------------------- */ dfXMin = MAX(0.0,MIN(nRXSize,floor(dfXMin))); dfYMin = MAX(0.0,MIN(nRYSize,floor(dfYMin))); dfXMax = MAX(0.0,MIN(nRXSize,ceil(dfXMax))); dfYMax = MAX(0.0,MIN(nRYSize,ceil(dfYMax))); /* -------------------------------------------------------------------- */ /* Convert to integer offset/size values. */ /* -------------------------------------------------------------------- */ nWinXOff = (int) dfXMin; nWinYOff = (int) dfYMin; nWinXSize = (int) (dfXMax - dfXMin); nWinYSize = (int) (dfYMax - dfYMin); /* -------------------------------------------------------------------- */ /* What bands are we operating on? */ /* -------------------------------------------------------------------- */ panBandMap = msGetGDALBandList( layer, hDS, 0, &nBandCount ); if( rlinfo->band_count == -1 ) rlinfo->band_count = nBandCount; if( nBandCount != rlinfo->band_count ) { msSetError( MS_IMGERR, "Got %d bands, but expected %d bands.", "msRasterQueryByRectLow()", nBandCount, rlinfo->band_count ); return -1; } /* -------------------------------------------------------------------- */ /* Try to load the raster data. For now we just load the first */ /* band in the file. Later we will deal with the various band */ /* selection criteria. */ /* -------------------------------------------------------------------- */ pafRaster = (float *) calloc(sizeof(float),nWinXSize*nWinYSize*nBandCount); MS_CHECK_ALLOC(pafRaster, sizeof(float)*nWinXSize*nWinYSize*nBandCount, -1); eErr = GDALDatasetRasterIO( hDS, GF_Read, nWinXOff, nWinYOff, nWinXSize, nWinYSize, pafRaster, nWinXSize, nWinYSize, GDT_Float32, nBandCount, panBandMap, 4 * nBandCount, 4 * nBandCount * nWinXSize, 4 ); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", "msRasterQueryByRectLow()", CPLGetLastErrorMsg() ); free( pafRaster ); return -1; } /* -------------------------------------------------------------------- */ /* Fetch color table for intepreting colors if needed. */ /* -------------------------------------------------------------------- */ rlinfo->hCT = GDALGetRasterColorTable( GDALGetRasterBand( hDS, panBandMap[0] ) ); free( panBandMap ); /* -------------------------------------------------------------------- */ /* When computing whether pixels are within range we do it */ /* based on the center of the pixel to the target point but */ /* really it ought to be the nearest point on the pixel. It */ /* would be too much trouble to do this rigerously, so we just */ /* add a fudge factor so that a range of zero will find the */ /* pixel the target falls in at least. */ /* -------------------------------------------------------------------- */ dfAdjustedRange = sqrt(adfGeoTransform[1] * adfGeoTransform[1] + adfGeoTransform[2] * adfGeoTransform[2] + adfGeoTransform[4] * adfGeoTransform[4] + adfGeoTransform[5] * adfGeoTransform[5]) * 0.5 * 1.41421356237 + sqrt( rlinfo->range_dist ); dfAdjustedRange = dfAdjustedRange * dfAdjustedRange; /* -------------------------------------------------------------------- */ /* Loop over all pixels determining which are "in". */ /* -------------------------------------------------------------------- */ for( iLine = 0; iLine < nWinYSize; iLine++ ) { for( iPixel = 0; iPixel < nWinXSize; iPixel++ ) { pointObj sPixelLocation,sReprojectedPixelLocation; if( rlinfo->query_results == rlinfo->query_result_hard_max ) break; /* transform pixel/line to georeferenced */ sPixelLocation.x = GEO_TRANS(adfGeoTransform, iPixel + nWinXOff + 0.5, iLine + nWinYOff + 0.5 ); sPixelLocation.y = GEO_TRANS(adfGeoTransform+3, iPixel + nWinXOff + 0.5, iLine + nWinYOff + 0.5 ); /* If projections differ, convert this back into the map */ /* projection for distance testing, and comprison to the */ /* search shape. Save the original pixel location coordinates */ /* in sPixelLocationInLayerSRS, so that we can return those */ /* coordinates if we have a hit */ sReprojectedPixelLocation = sPixelLocation; if( needReproject ) msProjectPoint( &(layer->projection), &(map->projection), &sReprojectedPixelLocation); /* If we are doing QueryByShape, check against the shape now */ if( rlinfo->searchshape != NULL ) { if( rlinfo->shape_tolerance == 0.0 && rlinfo->searchshape->type == MS_SHAPE_POLYGON ) { if( msIntersectPointPolygon( &sReprojectedPixelLocation, rlinfo->searchshape ) == MS_FALSE ) continue; } else { shapeObj tempShape; lineObj tempLine; memset( &tempShape, 0, sizeof(shapeObj) ); tempShape.type = MS_SHAPE_POINT; tempShape.numlines = 1; tempShape.line = &tempLine; tempLine.numpoints = 1; tempLine.point = &sReprojectedPixelLocation; if( msDistanceShapeToShape(rlinfo->searchshape, &tempShape) > rlinfo->shape_tolerance ) continue; } } if( rlinfo->range_mode >= 0 ) { double dist; dist = (rlinfo->target_point.x - sReprojectedPixelLocation.x) * (rlinfo->target_point.x - sReprojectedPixelLocation.x) + (rlinfo->target_point.y - sReprojectedPixelLocation.y) * (rlinfo->target_point.y - sReprojectedPixelLocation.y); if( dist >= dfAdjustedRange ) continue; /* If we can only have one feature, trim range and clear */ /* previous result. */ if( rlinfo->range_mode == MS_QUERY_SINGLE ) { rlinfo->range_dist = dist; rlinfo->query_results = 0; } } msRasterQueryAddPixel( layer, &sPixelLocation, // return coords in layer SRS &sReprojectedPixelLocation, pafRaster + (iLine*nWinXSize + iPixel) * nBandCount ); } } /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ free( pafRaster ); return MS_SUCCESS; } #endif /* def USE_GDAL */ /************************************************************************/ /* msRasterQueryByRect() */ /************************************************************************/ int msRasterQueryByRect(mapObj *map, layerObj *layer, rectObj queryRect) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterQueryByRect()" ); return MS_FAILURE; #else int status = MS_SUCCESS; char *filename=NULL; layerObj *tlp=NULL; /* pointer to the tile layer either real or temporary */ int tileitemindex=-1, tilelayerindex=-1, tilesrsindex=-1; shapeObj tshp; char tilename[MS_PATH_LENGTH], tilesrsname[1024]; int done, destroy_on_failure; char szPath[MS_MAXPATHLEN]; rectObj searchrect; rasterLayerInfo *rlinfo = NULL; /* -------------------------------------------------------------------- */ /* Get the layer info. */ /* -------------------------------------------------------------------- */ if(!layer->layerinfo) { msRasterLayerInfoInitialize( layer ); destroy_on_failure = 1; } else { destroy_on_failure = 0; } rlinfo = (rasterLayerInfo *) layer->layerinfo; /* -------------------------------------------------------------------- */ /* Clear old results cache. */ /* -------------------------------------------------------------------- */ if(layer->resultcache) { if(layer->resultcache->results) free(layer->resultcache->results); free(layer->resultcache); layer->resultcache = NULL; } /* -------------------------------------------------------------------- */ /* Initialize the results cache. */ /* -------------------------------------------------------------------- */ layer->resultcache = (resultCacheObj *)msSmallMalloc(sizeof(resultCacheObj)); layer->resultcache->results = NULL; layer->resultcache->numresults = layer->resultcache->cachesize = 0; layer->resultcache->bounds.minx = layer->resultcache->bounds.miny = layer->resultcache->bounds.maxx = layer->resultcache->bounds.maxy = -1; /* -------------------------------------------------------------------- */ /* Check if we should really be acting on this layer and */ /* provide debug info in various cases. */ /* -------------------------------------------------------------------- */ if(layer->debug > 0 || map->debug > 1) msDebug( "msRasterQueryByRect(%s): entering.\n", layer->name ); if(!layer->data && !layer->tileindex) { if(layer->debug > 0 || map->debug > 0 ) msDebug( "msRasterQueryByRect(%s): layer data and tileindex NULL ... doing nothing.", layer->name ); return MS_SUCCESS; } if((layer->status != MS_ON) && layer->status != MS_DEFAULT ) { if(layer->debug > 0 ) msDebug( "msRasterQueryByRect(%s): not status ON or DEFAULT, doing nothing.", layer->name ); return MS_SUCCESS; } /* ==================================================================== */ /* Handle setting up tileindex layer. */ /* ==================================================================== */ if(layer->tileindex) { /* we have an index file */ msInitShape(&tshp); searchrect = queryRect; status = msDrawRasterSetupTileLayer(map, layer, &searchrect, MS_TRUE, &tilelayerindex, &tileitemindex, &tilesrsindex, &tlp); if (status != MS_SUCCESS) { goto cleanup; } } else { /* we have to manually apply to scaletoken logic as we're not going through msLayerOpen() */ status = msLayerApplyScaletokens(layer,map->scaledenom); if (status != MS_SUCCESS) { goto cleanup; } } /* -------------------------------------------------------------------- */ /* Iterate over all tiles (just one in untiled case). */ /* -------------------------------------------------------------------- */ done = MS_FALSE; while( done == MS_FALSE && status == MS_SUCCESS ) { GDALDatasetH hDS; char *decrypted_path = NULL; /* -------------------------------------------------------------------- */ /* Get filename. */ /* -------------------------------------------------------------------- */ if(layer->tileindex) { status = msDrawRasterIterateTileIndex(layer, tlp, &tshp, tileitemindex, tilesrsindex, tilename, sizeof(tilename), tilesrsname, sizeof(tilesrsname)); if( status == MS_FAILURE) { break; } if(status == MS_DONE) break; /* no more tiles/images */ filename = tilename; } else { filename = layer->data; done = MS_TRUE; /* only one image so we're done after this */ } if(strlen(filename) == 0) continue; /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ msGDALInitialize(); msDrawRasterBuildRasterPath(map, layer, filename, szPath); decrypted_path = msDecryptStringTokens( map, szPath ); if( !decrypted_path ) { status = MS_FAILURE; goto cleanup; } msAcquireLock( TLOCK_GDAL ); hDS = GDALOpen(decrypted_path, GA_ReadOnly ); if( hDS == NULL ) { int ignore_missing = msMapIgnoreMissingData( map ); const char *cpl_error_msg = msDrawRasterGetCPLErrorMsg(decrypted_path, szPath); msFree( decrypted_path ); decrypted_path = NULL; msReleaseLock( TLOCK_GDAL ); if ( ignore_missing == MS_MISSING_DATA_FAIL ) { if( layer->debug || map->debug ) msSetError( MS_IMGERR, "Unable to open file %s for layer %s ... fatal error.\n%s", "msRasterQueryByRect()", szPath, layer->name, cpl_error_msg); status = MS_FAILURE; goto cleanup; } if( ignore_missing == MS_MISSING_DATA_LOG ) { if( layer->debug || map->debug ) msDebug( "Unable to open file %s for layer %s ... ignoring this missing data.\n%s", filename, layer->name, cpl_error_msg ); } continue; } msFree( decrypted_path ); decrypted_path = NULL; if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS ) { msReleaseLock( TLOCK_GDAL ); status = MS_FAILURE; goto cleanup; } /* -------------------------------------------------------------------- */ /* Perform actual query on this file. */ /* -------------------------------------------------------------------- */ if( status == MS_SUCCESS ) status = msRasterQueryByRectLow( map, layer, hDS, queryRect ); GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } /* next tile */ /* -------------------------------------------------------------------- */ /* Cleanup tileindex if it is open. */ /* -------------------------------------------------------------------- */ cleanup: if(layer->tileindex) { /* tiling clean-up */ msDrawRasterCleanupTileLayer(tlp, tilelayerindex); } else { msLayerRestoreFromScaletokens(layer); } /* -------------------------------------------------------------------- */ /* On failure, or empty result set, cleanup the rlinfo since we */ /* likely won't ever have it accessed or cleaned up later. */ /* -------------------------------------------------------------------- */ if( status == MS_FAILURE || rlinfo->query_results == 0 ) { if(destroy_on_failure) { msRasterLayerInfoFree( layer ); } } else { /* populate the items/numitems layer-level values */ msRASTERLayerGetItems(layer); } return status; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRasterQueryByShape() */ /************************************************************************/ int msRasterQueryByShape(mapObj *map, layerObj *layer, shapeObj *selectshape) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterQueryByRect()" ); return MS_FAILURE; #else rasterLayerInfo *rlinfo = NULL; int status; double tolerance; rectObj searchrect; msRasterLayerInfoInitialize( layer ); rlinfo = (rasterLayerInfo *) layer->layerinfo; /* If the selection shape is point or line we use the default tolerance of 3, but for polygons we require an exact hit. */ if(layer->tolerance == -1) { if(selectshape->type == MS_SHAPE_POINT || selectshape->type == MS_SHAPE_LINE) tolerance = 3; else tolerance = 0; } else tolerance = layer->tolerance; if(layer->toleranceunits == MS_PIXELS) tolerance = tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = tolerance * (msInchesPerUnit(layer->toleranceunits,0) / msInchesPerUnit(map->units,0)); rlinfo->searchshape = selectshape; rlinfo->shape_tolerance = tolerance; msComputeBounds( selectshape ); searchrect = selectshape->bounds; searchrect.minx -= tolerance; /* expand the search box to account for layer tolerances (e.g. buffered searches) */ searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; status = msRasterQueryByRect( map, layer, searchrect ); rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo ) rlinfo->searchshape = NULL; return status; #endif /* USE_GDAL */ } /************************************************************************/ /* msRasterQueryByPoint() */ /************************************************************************/ int msRasterQueryByPoint(mapObj *map, layerObj *layer, int mode, pointObj p, double buffer, int maxresults) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterQueryByRect()" ); return MS_FAILURE; #else int result; int previous_maxresults; double layer_tolerance; rectObj bufferRect; rasterLayerInfo *rlinfo = NULL; msRasterLayerInfoInitialize( layer ); rlinfo = (rasterLayerInfo *) layer->layerinfo; /* -------------------------------------------------------------------- */ /* If the buffer is not set, then use layer tolerances */ /* instead. The "buffer" distince is now in georeferenced */ /* units. Note that tolerances in pixels are basically map */ /* display pixels, not underlying raster pixels. It isn't */ /* clear that there is any way of requesting a buffer size in */ /* underlying pixels. */ /* -------------------------------------------------------------------- */ if(buffer <= 0) { /* use layer tolerance */ if(layer->tolerance == -1) layer_tolerance = 3; else layer_tolerance = layer->tolerance; if(layer->toleranceunits == MS_PIXELS) buffer = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else buffer = layer_tolerance * (msInchesPerUnit(layer->toleranceunits,0) / msInchesPerUnit(map->units,0)); } /* -------------------------------------------------------------------- */ /* Setup target point information, at this point they are in */ /* map coordinates. */ /* -------------------------------------------------------------------- */ rlinfo->range_dist = buffer * buffer; rlinfo->target_point = p; /* -------------------------------------------------------------------- */ /* if we are in the MS_QUERY_SINGLE mode, first try a query with */ /* zero tolerance. If this gets a raster pixel then we can be */ /* reasonably assured that it is the closest to the query */ /* point. This will potentially be must more efficient than */ /* processing all pixels within the tolerance. */ /* -------------------------------------------------------------------- */ if( mode == MS_QUERY_SINGLE ) { rectObj pointRect; pointRect.minx = p.x; pointRect.maxx = p.x; pointRect.miny = p.y; pointRect.maxy = p.y; rlinfo->range_mode = MS_QUERY_SINGLE; result = msRasterQueryByRect( map, layer, pointRect ); if( rlinfo->query_results > 0 ) return result; } /* -------------------------------------------------------------------- */ /* Setup a rectangle that is everything within the designated */ /* range and do a search against that. */ /* -------------------------------------------------------------------- */ bufferRect.minx = p.x - buffer; bufferRect.maxx = p.x + buffer; bufferRect.miny = p.y - buffer; bufferRect.maxy = p.y + buffer; rlinfo->range_mode = mode; if( maxresults != 0 ) { previous_maxresults = rlinfo->query_result_hard_max; rlinfo->query_result_hard_max = maxresults; } result = msRasterQueryByRect( map, layer, bufferRect ); if( rlinfo != NULL && maxresults != 0 ) rlinfo->query_result_hard_max = previous_maxresults; return result; #endif /* USE_GDAL */ } /************************************************************************/ /* ==================================================================== */ /* RASTER Query Layer */ /* */ /* The results of a raster query are treated as a set of shapes */ /* that can be accessed using the normal layer semantics. */ /* ==================================================================== */ /************************************************************************/ /************************************************************************/ /* msRASTERLayerOpen() */ /************************************************************************/ int msRASTERLayerOpen(layerObj *layer) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRASTERLayerOpen()" ); return MS_FAILURE; #else rasterLayerInfo *rlinfo; /* If we don't have info, initialize an empty one now */ if( layer->layerinfo == NULL ) msRasterLayerInfoInitialize( layer ); rlinfo = (rasterLayerInfo *) layer->layerinfo; rlinfo->refcount = rlinfo->refcount + 1; return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERIsLayerOpen() */ /************************************************************************/ int msRASTERLayerIsOpen(layerObj *layer) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterLayerIsOpen()" ); return MS_FALSE; #else if (layer->layerinfo) return MS_TRUE; return MS_FALSE; #endif } /************************************************************************/ /* msRASTERLayerFreeItemInfo() */ /************************************************************************/ void msRASTERLayerFreeItemInfo(layerObj *layer) {} /************************************************************************/ /* msRASTERLayerInitItemInfo() */ /* */ /* Perhaps we should be validating the requested items here? */ /************************************************************************/ int msRASTERLayerInitItemInfo(layerObj *layer) { return MS_SUCCESS; } /************************************************************************/ /* msRASTERLayerWhichShapes() */ /************************************************************************/ int msRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; rlinfo->which_rect = rect; rlinfo->next_shape = 0; return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerClose() */ /************************************************************************/ int msRASTERLayerClose(layerObj *layer) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo != NULL ) { rlinfo->refcount--; if( rlinfo->refcount < 0 ) msRasterLayerInfoFree( layer ); } return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerNextShape() */ /************************************************************************/ int msRASTERLayerNextShape(layerObj *layer, shapeObj *shape) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo->next_shape < 0 || rlinfo->next_shape >= rlinfo->query_results ) { msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_DONE; } else { resultObj record; record.shapeindex = rlinfo->next_shape++; record.tileindex = 0; record.classindex = record.resultindex = -1; return msRASTERLayerGetShape( layer, shape, &record); } #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerGetShape() */ /************************************************************************/ int msRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; int i; long shapeindex = record->shapeindex; msFreeShape(shape); shape->type = MS_SHAPE_NULL; /* -------------------------------------------------------------------- */ /* Validate requested record id. */ /* -------------------------------------------------------------------- */ if( shapeindex < 0 || shapeindex >= rlinfo->query_results ) { msSetError(MS_MISCERR, "Out of range shape index requested. Requested %ld\n" "but only %d shapes available.", "msRASTERLayerGetShape()", shapeindex, rlinfo->query_results ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Apply the geometry. */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_x != NULL ) { lineObj line; pointObj point; shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = &point; point.x = rlinfo->qc_x[shapeindex]; point.y = rlinfo->qc_y[shapeindex]; #ifdef USE_POINT_Z_M point.m = 0.0; #endif msAddLine( shape, &line ); msComputeBounds( shape ); } /* -------------------------------------------------------------------- */ /* Apply the requested items. */ /* -------------------------------------------------------------------- */ if( layer->numitems > 0 ) { shape->values = (char **) msSmallMalloc(sizeof(char *) * layer->numitems); shape->numvalues = layer->numitems; for( i = 0; i < layer->numitems; i++ ) { const size_t bufferSize = 1000; char szWork[1000]; szWork[0] = '\0'; if( EQUAL(layer->items[i],"x") && rlinfo->qc_x_reproj ) snprintf( szWork, bufferSize, "%.8g", rlinfo->qc_x_reproj[shapeindex] ); else if( EQUAL(layer->items[i],"y") && rlinfo->qc_y_reproj ) snprintf( szWork, bufferSize, "%.8g", rlinfo->qc_y_reproj[shapeindex] ); else if( EQUAL(layer->items[i],"value_list") && rlinfo->qc_values ) { int iValue; for( iValue = 0; iValue < rlinfo->band_count; iValue++ ) { if( iValue != 0 ) strlcat( szWork, ",", bufferSize); snprintf( szWork+strlen(szWork), bufferSize-strlen(szWork), "%.8g", rlinfo->qc_values[shapeindex * rlinfo->band_count + iValue] ); } } else if( EQUALN(layer->items[i],"value_",6) && rlinfo->qc_values ) { int iValue = atoi(layer->items[i]+6); snprintf( szWork, bufferSize, "%.8g", rlinfo->qc_values[shapeindex*rlinfo->band_count+iValue] ); } else if( EQUAL(layer->items[i],"class") && rlinfo->qc_class ) { int p_class = rlinfo->qc_class[shapeindex]; if( layer->class[p_class]->name != NULL ) snprintf( szWork, bufferSize, "%.999s", layer->class[p_class]->name ); else snprintf( szWork, bufferSize, "%d", p_class ); } else if( EQUAL(layer->items[i],"red") && rlinfo->qc_red ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_red[shapeindex] ); else if( EQUAL(layer->items[i],"green") && rlinfo->qc_green ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_green[shapeindex] ); else if( EQUAL(layer->items[i],"blue") && rlinfo->qc_blue ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_blue[shapeindex] ); else if( EQUAL(layer->items[i],"count") && rlinfo->qc_count ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_count[shapeindex] ); shape->values[i] = msStrdup(szWork); } } /* -------------------------------------------------------------------- */ /* Eventually we should likey apply the geometry properly but */ /* we don't really care about the geometry for query purposes. */ /* -------------------------------------------------------------------- */ return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerGetItems() */ /************************************************************************/ int msRASTERLayerGetItems(layerObj *layer) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo == NULL ) return MS_FAILURE; layer->items = (char **) msSmallCalloc(sizeof(char *),10); layer->numitems = 0; if( rlinfo->qc_x_reproj ) layer->items[layer->numitems++] = msStrdup("x"); if( rlinfo->qc_y_reproj ) layer->items[layer->numitems++] = msStrdup("y"); if( rlinfo->qc_values ) { int i; for( i = 0; i < rlinfo->band_count; i++ ) { char szName[100]; snprintf( szName, sizeof(szName), "value_%d", i ); layer->items[layer->numitems++] = msStrdup(szName); } layer->items[layer->numitems++] = msStrdup("value_list"); } if( rlinfo->qc_class ) layer->items[layer->numitems++] = msStrdup("class"); if( rlinfo->qc_red ) layer->items[layer->numitems++] = msStrdup("red"); if( rlinfo->qc_green ) layer->items[layer->numitems++] = msStrdup("green"); if( rlinfo->qc_blue ) layer->items[layer->numitems++] = msStrdup("blue"); if( rlinfo->qc_count ) layer->items[layer->numitems++] = msStrdup("count"); return msRASTERLayerInitItemInfo(layer); #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerGetExtent() */ /************************************************************************/ int msRASTERLayerGetExtent(layerObj *layer, rectObj *extent) { #ifndef USE_GDAL return MS_FAILURE; #else char szPath[MS_MAXPATHLEN]; mapObj *map = layer->map; double adfGeoTransform[6]; int nXSize, nYSize; GDALDatasetH hDS; shapefileObj *tileshpfile; int tilelayerindex = -1; CPLErr eErr = CE_Failure; char *decrypted_path; if( (!layer->data || strlen(layer->data) == 0) && layer->tileindex == NULL) { /* should we be issuing a specific error about not supporting extents for tileindexed raster layers? */ return MS_FAILURE; } if( map == NULL ) return MS_FAILURE; /* If the layer use a tileindex, return the extent of the tileindex shapefile/referenced layer */ if (layer->tileindex) { tilelayerindex = msGetLayerIndex(map, layer->tileindex); if(tilelayerindex != -1) /* does the tileindex reference another layer */ return msLayerGetExtent(GET_LAYER(map, tilelayerindex), extent); else { tileshpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); MS_CHECK_ALLOC(tileshpfile, sizeof(shapefileObj), MS_FAILURE); if(msShapefileOpen(tileshpfile, "rb", msBuildPath3(szPath, map->mappath, map->shapepath, layer->tileindex), MS_TRUE) == -1) if(msShapefileOpen(tileshpfile, "rb", msBuildPath(szPath, map->mappath, layer->tileindex), MS_TRUE) == -1) return MS_FAILURE; *extent = tileshpfile->bounds; msShapefileClose(tileshpfile); free(tileshpfile); return MS_SUCCESS; } } msTryBuildPath3(szPath, map->mappath, map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( map, szPath ); msAcquireLock( TLOCK_GDAL ); if( decrypted_path ) { hDS = GDALOpen(decrypted_path, GA_ReadOnly ); msFree( decrypted_path ); } else hDS = NULL; if( hDS != NULL ) { nXSize = GDALGetRasterXSize( hDS ); nYSize = GDALGetRasterYSize( hDS ); eErr = GDALGetGeoTransform( hDS, adfGeoTransform ); GDALClose( hDS ); } msReleaseLock( TLOCK_GDAL ); if( hDS == NULL || eErr != CE_None ) { return MS_FAILURE; } /* If this appears to be an ungeoreferenced raster than flip it for mapservers purposes. */ if( adfGeoTransform[5] == 1.0 && adfGeoTransform[3] == 0.0 ) { adfGeoTransform[5] = -1.0; adfGeoTransform[3] = nYSize; } extent->minx = adfGeoTransform[0]; extent->maxy = adfGeoTransform[3]; extent->maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1]; extent->miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5]; return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerSetTimeFilter() */ /* */ /* This function is actually just used in the context of */ /* setting a filter on the tileindex for time based queries. */ /* For instance via WMS requests. So it isn't really related */ /* to the "raster query" support at all. */ /* */ /* If a local shapefile tileindex is in use, we will set a */ /* backtics filter (shapefile compatible). If another layer is */ /* being used as the tileindex then we will forward the */ /* SetTimeFilter call to it. If there is no tileindex in */ /* place, we do nothing. */ /************************************************************************/ int msRASTERLayerSetTimeFilter(layerObj *layer, const char *timestring, const char *timefield) { int tilelayerindex; /* -------------------------------------------------------------------- */ /* If we don't have a tileindex the time filter has no effect. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Find the tileindex layer. */ /* -------------------------------------------------------------------- */ tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); /* -------------------------------------------------------------------- */ /* If we are using a local shapefile as our tileindex (that is */ /* to say, the tileindex name is not of another layer), then we */ /* just install a backtics style filter on the raster layer. */ /* This is propogated to the "working layer" created for the */ /* tileindex by code in mapraster.c. */ /* -------------------------------------------------------------------- */ if( tilelayerindex == -1 ) return msLayerMakeBackticsTimeFilter( layer, timestring, timefield ); /* -------------------------------------------------------------------- */ /* Otherwise we invoke the tileindex layers SetTimeFilter */ /* method. */ /* -------------------------------------------------------------------- */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; return msLayerSetTimeFilter( layer->GET_LAYER(map,tilelayerindex), timestring, timefield ); } /************************************************************************/ /* msRASTERLayerInitializeVirtualTable() */ /************************************************************************/ int msRASTERLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msRASTERLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msRASTERLayerFreeItemInfo; layer->vtable->LayerOpen = msRASTERLayerOpen; layer->vtable->LayerIsOpen = msRASTERLayerIsOpen; layer->vtable->LayerWhichShapes = msRASTERLayerWhichShapes; layer->vtable->LayerNextShape = msRASTERLayerNextShape; layer->vtable->LayerGetShape = msRASTERLayerGetShape; layer->vtable->LayerClose = msRASTERLayerClose; layer->vtable->LayerGetItems = msRASTERLayerGetItems; layer->vtable->LayerGetExtent = msRASTERLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCloseConnection = msRASTERLayerClose; */ /* we use backtics for proper tileindex shapefile functioning */ layer->vtable->LayerSetTimeFilter = msRASTERLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } mapserver-6.4.1/mapcrypto.c0000644002461700001440000004513112261257215015502 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Encryption functions (see MS-RFC-18) * Author: Daniel Morissette * ****************************************************************************** * Copyright (c) 1996-2006 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. ****************************************************************************/ #include #include /* isxdigit() */ #include /* rand() */ #include /* time() */ #include "mapserver.h" /********************************************************************** * encipher() and decipher() from the Tiny Encryption Algorithm (TEA) * website at: * http://www.simonshepherd.supanet.com/tea.htm * * TEA was developed and placed in the public domain by David Wheeler * and Roger Needham at the Computer Laboratory of Cambridge University. * * The source below came with the following public domain notice: * * "Please feel free to use any of this code in your applications. * The TEA algorithm (including new-variant TEA) has been placed * in the public domain, as have my assembly language implementations." * * ... and the following usage notes: * * All the routines have the general form * * void encipher(const unsigned long *const v,unsigned long *const w, * const unsigned long * const k); * * void decipher(const unsigned long *const v,unsigned long *const w, * const unsigned long * const k); * * TEA takes 64 bits of data in v[0] and v[1], and 128 bits of key in * k[0] - k[3]. The result is returned in w[0] and w[1]. Returning the * result separately makes implementation of cipher modes other than * Electronic Code Book a little bit easier. * * TEA can be operated in any of the modes of DES. * * n is the number of iterations. 32 is ample, 16 is sufficient, as few * as eight should be OK for most applications, especially ones where * the data age quickly (real-time video, for example). The algorithm * achieves good dispersion after six iterations. The iteration count * can be made variable if required. * * Note this algorithm is optimised for 32-bit CPUs with fast shift * capabilities. It can very easily be ported to assembly language * on most CPUs. * * delta is chosen to be the Golden ratio ((5/4)1/2 - 1/2 ~ 0.618034) * multiplied by 232. On entry to decipher(), sum is set to be delta * n. * Which way round you call the functions is arbitrary: DK(EK(P)) = EK(DK(P)) * where EK and DK are encryption and decryption under key K respectively. * **********************************************************************/ static void encipher(const ms_uint32 *const v, ms_uint32 *const w, const ms_uint32 *const k) { register ms_uint32 y=v[0],z=v[1],sum=0,delta=0x9E3779B9,n=32; while(n-->0) { y += ((z << 4 ^ z >> 5) + z) ^ (sum + k[sum&3]); sum += delta; z += ((y << 4 ^ y >> 5) + y) ^ (sum + k[sum>>11 & 3]); } w[0]=y; w[1]=z; } static void decipher(const ms_uint32 *const v, ms_uint32 *const w, const ms_uint32 *const k) { register ms_uint32 y=v[0],z=v[1],sum=0xC6EF3720, delta=0x9E3779B9,n=32; /* sum = delta<<5, in general sum = delta * n */ while(n-->0) { z -= ((y << 4 ^ y >> 5) + y) ^ (sum + k[sum>>11 & 3]); sum -= delta; y -= ((z << 4 ^ z >> 5) + z) ^ (sum + k[sum&3]); } w[0]=y; w[1]=z; } /********************************************************************** * msHexEncode() * * Hex-encode numbytes from in[] and return the result in out[]. * * out[] should be preallocated by the caller to be at least 2*numbytes+1 * (+1 for the terminating '\0') **********************************************************************/ void msHexEncode(const unsigned char *in, char *out, int numbytes) { char *hex = "0123456789ABCDEF"; while (numbytes-- > 0) { *out++ = hex[*in/16]; *out++ = hex[*in%16]; in++; } *out = '\0'; } /********************************************************************** * msHexDecode() * * Hex-decode numchars from in[] and return the result in out[]. * * If numchars > 0 then only up to this number of chars from in[] are * processed, otherwise the full in[] string up to the '\0' is processed. * * out[] should be preallocated by the caller to be large enough to hold * the resulting bytes. * * Returns the number of bytes written to out[] which may be different from * numchars/2 if an error or a '\0' is encountered. **********************************************************************/ int msHexDecode(const char *in, unsigned char *out, int numchars) { int numbytes_out = 0; /* Make sure numchars is even */ numchars = (numchars/2) * 2; if (numchars < 2) numchars = -1; /* Will result in this value being ignored in the loop*/ while (*in != '\0' && *(in+1) != '\0' && numchars != 0) { *out = 0x10 * (*in >= 'A' ? ((*in & 0xdf) - 'A')+10 : (*in - '0')); in++; *out += (*in >= 'A' ? ((*in & 0xdf) - 'A')+10 : (*in - '0')); in++; out++; numbytes_out++; numchars -= 2; } return numbytes_out; } /********************************************************************** * msGenerateEncryptionKey() * * Create a new encryption key. * * The output buffer should be at least MS_ENCRYPTION_KEY_SIZE bytes. **********************************************************************/ int msGenerateEncryptionKey(unsigned char *k) { int i; /* Use current time as seed for rand() */ srand( (unsigned int) time( NULL )); for(i=0; iencryption_key. * If the key is already set in the mapObj then it does nothing and returns. * * The location of the encryption key can be specified in two ways, * either by setting the environment variable MS_ENCRYPTION_KEY or using * a CONFIG directive: * CONFIG MS_ENCRYPTION_KEY "/path/to/mykey.txt" * Returns MS_SUCCESS/MS_FAILURE. **********************************************************************/ static int msLoadEncryptionKey(mapObj *map) { const char *keyfile; if (map == NULL) { msSetError(MS_MISCERR, "NULL MapObj.", "msLoadEncryptionKey()"); return MS_FAILURE; } if (map->encryption_key_loaded) return MS_SUCCESS; /* Already loaded */ keyfile = msGetConfigOption(map, "MS_ENCRYPTION_KEY"); if (keyfile == NULL) keyfile = getenv("MS_ENCRYPTION_KEY"); if (keyfile && msReadEncryptionKeyFromFile(keyfile,map->encryption_key) == MS_SUCCESS) { map->encryption_key_loaded = MS_TRUE; } else { msSetError(MS_MISCERR, "Failed reading encryption key. Make sure " "MS_ENCRYPTION_KEY is set and points to a valid key file.", "msLoadEncryptionKey()"); return MS_FAILURE; } return MS_SUCCESS; } /********************************************************************** * msEncryptStringWithKey() * * Encrypts and hex-encodes the contents of string in[] and returns the * result in out[] which should have been pre-allocated by the caller * to be at least twice the size of in[] + 16+1 bytes (for padding + '\0'). * **********************************************************************/ void msEncryptStringWithKey(const unsigned char *key, const char *in, char *out) { ms_uint32 v[4], w[4]; const ms_uint32 *k; int last_block = MS_FALSE; /* Casting the key this way is safe only as long as longs are 4 bytes * on this platform */ assert(sizeof(ms_uint32) == 4); k = (const ms_uint32 *) key; while(!last_block) { int i, j; /* encipher() takes v[2] (64 bits) as input. * Copy bytes from in[] to the v[2] input array (pair of 4 bytes) * v[] is padded with zeros if string doesn't align with 8 bytes */ v[0] = 0; v[1] = 0; for(i=0; !last_block && i<2; i++) { for(j=0; j<4; j++) { if (*in == '\0') { last_block = MS_TRUE; break; } v[i] |= *in << (j*8); in++; } } if (*in == '\0') last_block = MS_TRUE; /* Do the actual encryption */ encipher(v, w, k); /* Append hex-encoded bytes to output, 4 bytes at a time */ msHexEncode((unsigned char *)w, out, 4); out += 8; msHexEncode((unsigned char *)(w+1), out, 4); out += 8; } /* Make sure output is 0-terminated */ *out = '\0'; } /********************************************************************** * msDecryptStringWithKey() * * Hex-decodes and then decrypts the contents of string in[] and returns the * result in out[] which should have been pre-allocated by the caller * to be at least half the size of in[]. * **********************************************************************/ void msDecryptStringWithKey(const unsigned char *key, const char *in, char *out) { ms_uint32 v[4], w[4]; const ms_uint32 *k; int last_block = MS_FALSE; /* Casting the key this way is safe only as long as longs are 4 bytes * on this platform */ assert(sizeof(ms_uint32) == 4); k = (const ms_uint32 *) key; while(!last_block) { int i; /* decipher() takes v[2] (64 bits) as input. * Copy bytes from in[] to the v[2] input array (pair of 4 bytes) * v[] is padded with zeros if string doesn't align with 8 bytes */ v[0] = 0; v[1] = 0; if (msHexDecode(in, (unsigned char *)v, 8) != 4) last_block = MS_TRUE; else { in += 8; if (msHexDecode(in, (unsigned char *)(v+1), 8) != 4) last_block = MS_TRUE; else in += 8; } /* Do the actual decryption */ decipher(v, w, k); /* Copy the results to out[] */ for(i=0; i<2; i++) { *out++ = (w[i] & 0x000000ff); *out++ = (w[i] & 0x0000ff00) >> 8; *out++ = (w[i] & 0x00ff0000) >> 16; *out++ = (w[i] & 0xff000000) >> 24; } if (*in == '\0') last_block = MS_TRUE; } /* Make sure output is 0-terminated */ *out = '\0'; } /********************************************************************** * msDecryptStringTokens() * * Returns a newly allocated string (to be msFree'd by the caller) in * which all occurences of encrypted strings delimited by {...} have * been decrypted. * **********************************************************************/ char *msDecryptStringTokens(mapObj *map, const char *in) { char *outbuf, *out; if (map == NULL) { msSetError(MS_MISCERR, "NULL MapObj.", "msLoadEncryptionKey()"); return NULL; } /* Start with a copy of the string. Decryption can only result in * a string with the same or shorter length */ if ((outbuf = (char *)malloc((strlen(in)+1)*sizeof(char))) == NULL) { msSetError(MS_MEMERR, NULL, "msDecryptStringTokens()"); return NULL; } out = outbuf; while(*in != '\0') { if (*in == '{') { /* Possibly beginning of a token, look for closing bracket ** and make sure all chars in between are valid hex encoding chars */ const char *pszStart, *pszEnd; int valid_token = MS_FALSE; pszStart = in+1; if ( (pszEnd = strchr(pszStart, '}')) != NULL && pszEnd - pszStart > 1) { const char *pszTmp; valid_token = MS_TRUE; for(pszTmp = pszStart; pszTmp < pszEnd; pszTmp++) { if (!isxdigit(*pszTmp)) { valid_token = MS_FALSE; break; } } } if (valid_token) { /* Go ahead and decrypt the token */ char *pszTmp; /* Make sure encryption key is loaded. We do this here instead * of at the beginning of the function to avoid loading the * key unless ready necessary. This is a very cheap call if * the key is already loaded */ if (msLoadEncryptionKey(map) != MS_SUCCESS) return NULL; pszTmp = (char*)malloc( (pszEnd-pszStart+1)*sizeof(char)); strlcpy(pszTmp, pszStart, (pszEnd-pszStart)+1); msDecryptStringWithKey(map->encryption_key, pszTmp, out); out += strlen(out); in = pszEnd+1; free(pszTmp); } else { /* Not a valid token, just copy the '{' and keep going */ *out++ = *in++; } } else { /* Just copy any other chars */ *out++ = *in++; } } *out = '\0'; return outbuf; } #ifdef TEST_MAPCRYPTO /* Test for mapcrypto.c functions. To run these tests, use the following ** Makefile directive: test_mapcrypto: $(LIBMAP_STATIC) mapcrypto.c $(CC) $(CFLAGS) mapcrypto.c -DTEST_MAPCRYPTO $(EXE_LDFLAGS) -o test_mapcrypto ** */ int main(int argc, char *argv[]) { const unsigned char bytes_in[] = {0x12, 0x34, 0xff, 0x00, 0x44, 0x22}; unsigned char bytes_out[8], encryption_key[MS_ENCRYPTION_KEY_SIZE*2+1]; char string_buf[256], string_buf2[256]; int numbytes = 0; /* ** Test msHexEncode() */ msHexEncode(bytes_in, string_buf, 6); printf("msHexEncode returned '%s'\n", string_buf); /* ** Test msHexDecode() */ memset(bytes_out, 0, 8); numbytes = msHexDecode(string_buf, bytes_out, -1); printf("msHexDecode(%s, -1) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); memset(bytes_out, 0, 8); numbytes = msHexDecode(string_buf, bytes_out, 4); printf("msHexDecode(%s, 4) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); memset(bytes_out, 0, 8); numbytes = msHexDecode(string_buf, bytes_out, 20); printf("msHexDecode(%s, 20) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); /* ** Test loading encryption key */ if (msReadEncryptionKeyFromFile("/tmp/test.key", encryption_key) != MS_SUCCESS) { printf("msReadEncryptionKeyFromFile() = MS_FAILURE\n"); printf("Aborting tests!\n"); msWriteError(stderr); return -1; } else { msHexEncode(encryption_key, string_buf, MS_ENCRYPTION_KEY_SIZE); printf("msReadEncryptionKeyFromFile() returned '%s'\n", string_buf); } /* ** Test Encryption/Decryption */ /* First with an 8 bytes input string (test boundaries) */ msEncryptStringWithKey(encryption_key, "test1234", string_buf); printf("msEncryptStringWithKey('test1234') returned '%s'\n", string_buf); msDecryptStringWithKey(encryption_key, string_buf, string_buf2); printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, string_buf2); /* Next with an 1 byte input string */ msEncryptStringWithKey(encryption_key, "t", string_buf); printf("msEncryptStringWithKey('t') returned '%s'\n", string_buf); msDecryptStringWithKey(encryption_key, string_buf, string_buf2); printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, string_buf2); /* Next with an 12 bytes input string */ msEncryptStringWithKey(encryption_key, "test123456", string_buf); printf("msEncryptStringWithKey('test123456') returned '%s'\n", string_buf); msDecryptStringWithKey(encryption_key, string_buf, string_buf2); printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, string_buf2); /* ** Test decryption with tokens */ { char *pszBuf; mapObj *map; /* map = msNewMapObj(); */ map = msLoadMap("/tmp/test.map", NULL); sprintf(string_buf2, "string with a {%s} encrypted token", string_buf); pszBuf = msDecryptStringTokens(map, string_buf2); if (pszBuf == NULL) { printf("msDecryptStringTokens() failed.\n"); printf("Aborting tests!\n"); msWriteError(stderr); return -1; } else { printf("msDecryptStringTokens('%s') returned '%s'\n", string_buf2, pszBuf); } msFree(pszBuf); msFreeMap(map); } return 0; } #endif /* TEST_MAPCRYPTO */ mapserver-6.4.1/mapscript/0000755002461700001440000000000012261257215015316 5ustar tbonfortusersmapserver-6.4.1/mapscript/doc/0000755002461700001440000000000012261257215016063 5ustar tbonfortusersmapserver-6.4.1/mapscript/doc/mapscript.css0000644002461700001440000000011612261257215020575 0ustar tbonfortusers @import url(default.css); body { font-family: sans-serif; margin: 15px; } mapserver-6.4.1/mapscript/doc/default.css0000644002461700001440000000746112261257215020231 0ustar tbonfortusers/* :Author: David Goodger :Contact: goodger@users.sourceforge.net :date: $Date$ :version: $Revision$ :copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. */ .first { margin-top: 0 } .last { margin-bottom: 0 } a.toc-backref { text-decoration: none ; color: black } dd { margin-bottom: 0.5em } div.abstract { margin: 2em 5em } div.abstract p.topic-title { font-weight: bold ; text-align: center } div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning, div.admonition { margin: 2em ; border: medium outset ; padding: 1em } div.attention p.admonition-title, div.caution p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title, div.warning p.admonition-title { color: red ; font-weight: bold ; font-family: sans-serif } div.hint p.admonition-title, div.important p.admonition-title, div.note p.admonition-title, div.tip p.admonition-title, div.admonition p.admonition-title { font-weight: bold ; font-family: sans-serif } div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic } div.dedication p.topic-title { font-weight: bold ; font-style: normal } div.figure { margin-left: 2em } div.footer, div.header { font-size: smaller } div.sidebar { margin-left: 1em ; border: medium outset ; padding: 0em 1em ; background-color: #ffffee ; width: 40% ; float: right ; clear: right } div.sidebar p.rubric { font-family: sans-serif ; font-size: medium } div.system-messages { margin: 5em } div.system-messages h1 { color: red } div.system-message { border: medium outset ; padding: 1em } div.system-message p.system-message-title { color: red ; font-weight: bold } div.topic { margin: 2em } h1.title { text-align: center } h2.subtitle { text-align: center } hr { width: 75% } ol.simple, ul.simple { margin-bottom: 1em } ol.arabic { list-style: decimal } ol.loweralpha { list-style: lower-alpha } ol.upperalpha { list-style: upper-alpha } ol.lowerroman { list-style: lower-roman } ol.upperroman { list-style: upper-roman } p.attribution { text-align: right ; margin-left: 50% } p.caption { font-style: italic } p.credits { font-style: italic ; font-size: smaller } p.label { white-space: nowrap } p.rubric { font-weight: bold ; font-size: larger ; color: darkred ; text-align: center } p.sidebar-title { font-family: sans-serif ; font-weight: bold ; font-size: larger } p.sidebar-subtitle { font-family: sans-serif ; font-weight: bold } p.topic-title { font-weight: bold } pre.address { margin-bottom: 0 ; margin-top: 0 ; font-family: serif ; font-size: 100% } pre.line-block { font-family: serif ; font-size: 100% } pre.literal-block, pre.doctest-block { margin-left: 2em ; margin-right: 2em ; background-color: #eeeeee } span.classifier { font-family: sans-serif ; font-style: oblique } span.classifier-delimiter { font-family: sans-serif ; font-weight: bold } span.interpreted { font-family: sans-serif } span.option { white-space: nowrap } span.option-argument { font-style: italic } span.pre { white-space: pre } span.problematic { color: red } table { margin-top: 0.5em ; margin-bottom: 0.5em } table.citation { border-left: solid thin gray ; padding-left: 0.5ex } table.docinfo { margin: 2em 4em } table.footnote { border-left: solid thin black ; padding-left: 0.5ex } td, th { padding-left: 0.5em ; padding-right: 0.5em ; vertical-align: top } th.docinfo-name, th.field-name { font-weight: bold ; text-align: left ; white-space: nowrap } h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { font-size: 100% } tt { background-color: #eeeeee } ul.auto-toc { list-style-type: none } mapserver-6.4.1/mapscript/ruby/0000755002461700001440000000000012261257215016277 5ustar tbonfortusersmapserver-6.4.1/mapscript/ruby/README0000644002461700001440000000226712261257215017166 0ustar tbonfortusersRuby MapScript Interface ------------------------ BUILD ----- The files that are required to create the library 'mapscript.so' : mapscript.i extconf.rb Be sure that you have installed SWIG version 1.3a5 or greater. The installation is tested with ruby version 1.6 and 1.8. To build type : # ruby extconf.rb # make INSTALL ------- If you don't want to install the library, you have to add the library path as argument to the command (ruby -I[path/to/the/library] ...). To install type as 'root' user : # make install EXAMPLES -------- To run the examples: Go to the directory of the examples # cd examples Run the example to receive information about a shape file # ruby shpinfo.rb [path/shapefile.shp] or if you don't have executed 'make install' # ruby -I[path/to/mapscript.so] shpinfo.rb [path/shapefile.shp] e.g.: # ruby -I.. shpinfo.rb lake2spy.shp Run the example to create a PNG file from a shape file. The output will be in the file [shapefile].png. # ruby shp2img.rb [path/shapefile.shp] or # ruby -I[path/to/mapscript.so] shp2img.rb [path/shapefile.shp] e.g.: # ruby -I.. shp2img.rb lake2spy.shp AUTHOR ------ Markus Schnider msr@sourcepole.ch http://www.sourcepole.com mapserver-6.4.1/mapscript/ruby/extconf.rb0000755002461700001440000000226512261257215020302 0ustar tbonfortusers#!/usr/bin/env ruby require 'mkmf' require 'pathname' mapscriptvars = File.open("../../mapscriptvars") make_home = mapscriptvars.gets.chomp make_define = mapscriptvars.gets.chomp make_inc = mapscriptvars.gets.chomp make_libs = mapscriptvars.gets.chomp make_static_libs = mapscriptvars.gets.chomp mapscriptvars.close MAPSERVER_LOCAL_LIBS=Pathname.new(File.dirname(__FILE__) + '/../../.libs').realpath # $CFLAGS works only with 1.8 ??? -> the -Wall argument is not needed !!! $CFLAGS = "" $CPPFLAGS = make_inc + " -idirafter $(rubylibdir)/$(arch) " + make_define $LDFLAGS += " -fPIC -Wl,-rpath,#{MAPSERVER_LOCAL_LIBS}" #$LOCAL_LIBS += " -L../../.libs/ " + " -lmapserver " + make_static_libs $LOCAL_LIBS += " -L#{MAPSERVER_LOCAL_LIBS} " + " -lmapserver " # if the source file 'mapscript_wrap.c' is missing nothing works # this is a workaround !! if !FileTest.exist?("mapscript_wrap.c") $objs = [] $objs.push("mapscript_wrap.o") end #CONFIG['LDSHARED'] = "LD_RUN_PATH=#{MAPSERVER_LOCAL_LIBS} " + CONFIG['LDSHARED'] create_makefile("mapscript") make_file = File.open("Makefile", "a") make_file << "\nmapscript_wrap.c: ../mapscript.i\n\tswig -ruby -o mapscript_wrap.c ../mapscript.i" make_file.close mapserver-6.4.1/mapscript/ruby/CMakeLists.txt0000644002461700001440000000202012261257215021031 0ustar tbonfortusersFIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(Ruby REQUIRED) INCLUDE_DIRECTORIES(${RUBY_INCLUDE_DIRS}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/ruby) SWIG_ADD_MODULE(rubymapscript ruby ../mapscript.i) SWIG_LINK_LIBRARIES(rubymapscript ${RUBY_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES PREFIX "") set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES OUTPUT_NAME mapscript) if(APPLE) set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES SUFFIX ".bundle") endif(APPLE) get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_rubymapscript_REAL_NAME} LOCATION) execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts RbConfig::CONFIG['sitearchdir']" OUTPUT_VARIABLE RUBY_SITEARCHDIR OUTPUT_STRIP_TRAILING_WHITESPACE) install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${RUBY_SITEARCHDIR}) mapserver-6.4.1/mapscript/ruby/examples/0000755002461700001440000000000012261257215020115 5ustar tbonfortusersmapserver-6.4.1/mapscript/ruby/examples/shp2img.rb0000755002461700001440000000157212261257215022023 0ustar tbonfortusers#!/usr/bin/env ruby require "mapscript" include Mapscript filename = ARGV[0] shapefile = ShapefileObj.new(filename, -1) shapepath = File.dirname(filename) shapename = File.basename(filename, "....") map = MapObj.new('') map.shapepath = shapepath map.height = 200 map.width = 200 map.extent = shapefile.bounds $shapetypes = { MS_SHAPEFILE_POINT => MS_LAYER_POINT, MS_SHAPEFILE_ARC => MS_LAYER_LINE, MS_SHAPEFILE_POLYGON => MS_LAYER_POLYGON, MS_SHAPEFILE_MULTIPOINT => MS_LAYER_LINE } layer = LayerObj.new(map) layer.name = shapename layer.type = $shapetypes[shapefile.type] layer.status = MS_ON layer.data = shapename cls = ClassObj.new(layer) style = StyleObj.new() color = ColorObj.new() color.red = 107 color.green = 158 color.blue = 160 style.color = color cls.insertStyle(style) #map.save(shapename+'.map') img = map.draw img.save(shapename+'.png') mapserver-6.4.1/mapscript/ruby/rbmodule.i0000644002461700001440000001007512261257215020265 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Ruby-specific enhancements to MapScript * Author: * ****************************************************************************** * * Ruby-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGRUBY is defined (via 'swig -ruby ...'). * *****************************************************************************/ /****************************************************************************** * Simple Typemaps *****************************************************************************/ /* To support imageObj::getBytes */ %typemap(out) gdBuffer { $result = rb_str_new($1.data, $1.size); msFree($1.data); } /************************************************************************** * MapServer Errors and Ruby Exceptions ************************************************************************** * * Translation of errors reported via the ms_error structure into * Ruby exceptions. Generally copied from Python MapScript by Jim Klassen. * Follows original code by Chris Chamberlin as updated * updated by Sean Gillies . * Uses rb_raise, %exception and $action for SWIG 1.3, do the most * obvious mapping of MapServer errors to Ruby exceptions and map all * others to a new 'MapServerError' exception which can be caught like * this: * * require 'mapscript' * empty_map = Mapscript.MapObj.new('') * begin: * img = empty_map.draw() * rescue Mapscript::MapServerError => msg * print "Caught MapServerError:", msg.to_s * end * *************************************************************************/ %{ VALUE MSExc_MapServerError; VALUE MSExc_MapServerChildError; %} /* Module initialization: call msSetup() and register msCleanup() */ %init %{ /* Copied from pymodule.i to fix #3619 */ if (msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Failed to set up threads and font cache", "msSetup()"); } /* Is there a place to hook to call msCleanup()? */ VALUE exceptionClass = rb_eval_string("Exception"); VALUE mapscriptModule = rb_eval_string("Mapscript"); MSExc_MapServerError = rb_define_class_under(mapscriptModule, "MapserverError", exceptionClass); MSExc_MapServerChildError = rb_define_class_under(mapscriptModule, "MapserverChildErrorError", exceptionClass); %} %{ static void _raise_ms_exception( void ); static void _raise_ms_exception() { int errcode; errorObj *ms_error; char *errmsg; ms_error = msGetErrorObj(); errcode = ms_error->code; errmsg = msGetErrorString("\n"); switch (errcode) { case MS_IOERR: rb_raise(rb_eIOError, errmsg); break; case MS_MEMERR: rb_raise(rb_eNoMemError, errmsg); break; case MS_TYPEERR: rb_raise(rb_eTypeError, errmsg); break; case MS_EOFERR: rb_raise(rb_eEOFError, errmsg); break; case MS_CHILDERR: rb_raise(MSExc_MapServerChildError, errmsg); break; default: rb_raise(MSExc_MapServerError, errmsg); break; } free(errmsg); } %} %exception { msResetErrorList(); $action { errorObj *ms_error = msGetErrorObj(); switch(ms_error->code) { case MS_NOERR: break; case MS_NOTFOUND: msResetErrorList(); break; case -1: break; case MS_IOERR: if (strncmp(ms_error->routine, "msSearchDiskTree()", 20) != 0) { _raise_ms_exception(); msResetErrorList(); return NULL; } default: _raise_ms_exception(); msResetErrorList(); return NULL; } } } mapserver-6.4.1/mapscript/ruby/rbextend.i0000644002461700001440000000111712261257215020264 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Ruby-specific extensions to MapScript objects * Author: * ****************************************************************************** * * Ruby-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGRUBY is defined (via 'swig -ruby ...'). * *****************************************************************************/ mapserver-6.4.1/mapscript/swiginc/0000755002461700001440000000000012261257215016761 5ustar tbonfortusersmapserver-6.4.1/mapscript/swiginc/point.i0000644002461700001440000001057612261257215020275 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript pointObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend pointObj { /* Java pointObj constructors are in java/javaextend.i (bug 1106) */ #ifndef SWIGJAVA pointObj(double x=0.0, double y=0.0, double z=0.0, double m=-2e38) { pointObj *p; p = (pointObj *)calloc(1,sizeof(pointObj)); if (!p) return NULL; p->x = x; p->y = y; #ifdef USE_POINT_Z_M p->z = z; p->m = m; #endif /* USE_POINT_Z_M */ return p; } #endif ~pointObj() { free(self); } int project(projectionObj *projin, projectionObj *projout) { return msProjectPoint(projin, projout, self); } int draw(mapObj *map, layerObj *layer, imageObj *image, int classindex, char *text) { return msDrawPoint(map, layer, self, image, classindex, text); } double distanceToPoint(pointObj *point) { return msDistancePointToPoint(self, point); } double distanceToSegment(pointObj *a, pointObj *b) { return msDistancePointToSegment(self, a, b); } double distanceToShape(shapeObj *shape) { return msDistancePointToShape(self, shape); } int setXY(double x, double y, double m=-2e38) { self->x = x; self->y = y; #ifdef USE_POINT_Z_M self->z = 0.0; self->m = m; #endif /* USE_POINT_Z_M */ return MS_SUCCESS; } int setXYZ(double x, double y, double z, double m=-2e38) { self->x = x; self->y = y; #ifdef USE_POINT_Z_M self->z = z; self->m = m; #endif /* USE_POINT_Z_M */ return MS_SUCCESS; } int setXYZM(double x, double y, double z, double m) { self->x = x; self->y = y; #ifdef USE_POINT_Z_M self->z = z; self->m = m; #endif /* USE_POINT_Z_M */ return MS_SUCCESS; } %newobject toString; char *toString() { char buffer[256]; const char *fmt; #ifdef USE_POINT_Z_M if( self->m < -1e38 ) fmt = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g }"; else fmt = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g, 'm': %.16g }"; #else fmt = "{ 'x': %.16g, 'y': %.16g }"; #endif /* USE_POINT_Z_M */ msPointToFormattedString(self, fmt, (char *) &buffer, 256); return strdup(buffer); } %newobject toShape; shapeObj *toShape() { shapeObj *shape; shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)); shape->line[0].numpoints = 1; shape->line[0].point[0].x = self->x; shape->line[0].point[0].y = self->y; #ifdef USE_POINT_Z_M shape->line[0].point[0].z = self->z; shape->line[0].point[0].m = self->m; #endif /* USE_POINT_Z_M */ return shape; } } mapserver-6.4.1/mapscript/swiginc/querymap.i0000644002461700001440000000332512261257215021001 0ustar tbonfortusers/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript queryMapObj extensions Author: Steve Lime =========================================================================== 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 or substantial portions of the 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. =========================================================================== */ %extend queryMapObj { int updateFromString(char *snippet) { return msUpdateQueryMapFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteQueryMapToString(self); } } mapserver-6.4.1/mapscript/swiginc/outputformat.i0000644002461700001440000000627012261257215021711 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript outputFormatObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend outputFormatObj { outputFormatObj(const char *driver, char *name=NULL) { outputFormatObj *format; format = msCreateDefaultOutputFormat(NULL, driver, name); /* in the case of unsupported formats, msCreateDefaultOutputFormat should return NULL */ if (!format) { msSetError(MS_MISCERR, "Unsupported format driver: %s", "outputFormatObj()", driver); return NULL; } msInitializeRendererVTable(format); MS_REFCNT_INIT(format); format->inmapfile = MS_TRUE; return format; } ~outputFormatObj() { msFreeOutputFormat( self ); } #ifndef SWIGJAVA void setExtension( const char *extension ) { msFree( self->extension ); self->extension = strdup(extension); } void setMimetype( const char *mimetype ) { msFree( self->mimetype ); self->mimetype = strdup(mimetype); } #endif void setOption( const char *key, const char *value ) { msSetOutputFormatOption( self, key, value ); } int validate() { return msOutputFormatValidate( self, MS_FALSE ); } %newobject getOption; char *getOption(const char *key, const char *value="") { return strdup(msGetOutputFormatOption(self, key, value)); } %newobject getOptionAt; char* getOptionAt(int i) { if( i >= 0 && i < self->numformatoptions ) { return strdup(self->formatoptions[i]); } return NULL; } void attachDevice( void *device ) { self->device = device; } } mapserver-6.4.1/mapscript/swiginc/class.i0000644002461700001440000001624412261257215020247 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript classObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend classObj { classObj(layerObj *layer=NULL) { classObj *new_class=NULL; if (!layer) { new_class = (classObj *) malloc(sizeof(classObj)); if (!new_class) { msSetError(MS_MEMERR, "Could not allocate memory for new classObj instance", "classObj()"); return NULL; } if (initClass(new_class) == -1) return NULL; new_class->layer = NULL; return new_class; } else { if(msGrowLayerClasses(layer) == NULL) return NULL; if (initClass(layer->class[layer->numclasses]) == -1) return NULL; layer->class[layer->numclasses]->type = layer->type; layer->class[layer->numclasses]->layer = layer; MS_REFCNT_INCR(layer->class[layer->numclasses]); layer->numclasses++; return (layer->class[layer->numclasses-1]); } return NULL; } ~classObj() { if (self) { if (freeClass(self)==MS_SUCCESS) { free(self); self=NULL; } } } int updateFromString(char *snippet) { return msUpdateClassFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteClassToString(self); } #ifdef SWIGJAVA %newobject cloneClass; classObj *cloneClass() #else %newobject clone; classObj *clone() #endif { classObj *new_class; new_class = (classObj *) malloc(sizeof(classObj)); if (!new_class) { msSetError(MS_MEMERR, "Could not allocate memory for new classObj instance", "clone()"); return NULL; } if (initClass(new_class) == -1) { msSetError(MS_MEMERR, "Failed to initialize Class", "clone()"); return NULL; } new_class->layer = NULL; if (msCopyClass(new_class, self, self->layer) != MS_SUCCESS) { freeClass(new_class); free(new_class); new_class = NULL; } return new_class; } int setExpression(char *expression) { if (!expression || strlen(expression) == 0) { freeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, expression); } %newobject getExpressionString; char *getExpressionString() { return msGetExpressionString(&(self->expression)); } int setText(char *text) { if (!text || strlen(text) == 0) { freeExpression(&self->text); return MS_SUCCESS; } else return msLoadExpressionString(&self->text, text); } %newobject getTextString; char *getTextString() { return msGetExpressionString(&(self->text)); } char *getMetaData(char *name) { char *value = NULL; if (!name) { msSetError(MS_HASHERR, "NULL key", "getMetaData"); } value = (char *) msLookupHashTable(&(self->metadata), name); if (!value) { msSetError(MS_HASHERR, "Key %s does not exist", "getMetaData", name); return NULL; } return value; } int setMetaData(char *name, char *value) { if (msInsertHashTable(&(self->metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } char *getFirstMetaDataKey() { return (char *) msFirstKeyFromHashTable(&(self->metadata)); } char *getNextMetaDataKey(char *lastkey) { return (char *) msNextKeyFromHashTable(&(self->metadata), lastkey); } int drawLegendIcon(mapObj *map, layerObj *layer, int width, int height, imageObj *dstImage, int dstX, int dstY) { return msDrawLegendIcon(map, layer, self, width, height, dstImage, dstX, dstY, MS_TRUE, NULL); } %newobject createLegendIcon; imageObj *createLegendIcon(mapObj *map, layerObj *layer, int width, int height) { return msCreateLegendIcon(map, layer, self, width, height, MS_TRUE); } %newobject getLabel; labelObj *getLabel(int i) { if (i >= 0 && i < self->numlabels) { MS_REFCNT_INCR(self->labels[i]); return self->labels[i]; } else { msSetError(MS_CHILDERR, "Invalid index: %d.", "getLabel()", i); return NULL; } } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {labelObj *label}; #endif int addLabel(labelObj *label) { return msAddLabelToClass(self, label); } #ifdef SWIGCSHARP %clear labelObj *label; #endif %newobject removeLabel; labelObj *removeLabel(int index) { labelObj* label = (labelObj *) msRemoveLabelFromClass(self, index); if (label) MS_REFCNT_INCR(label); return label; } /* See Bugzilla issue 548 for more details about the *Style methods */ %newobject getStyle; styleObj *getStyle(int i) { if (i >= 0 && i < self->numstyles) { MS_REFCNT_INCR(self->styles[i]); return self->styles[i]; } else { msSetError(MS_CHILDERR, "Invalid index: %d", "getStyle()", i); return NULL; } } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {styleObj *style}; #endif int insertStyle(styleObj *style, int index=-1) { return msInsertStyle(self, style, index); } #ifdef SWIGCSHARP %clear styleObj *style; #endif %newobject removeStyle; styleObj *removeStyle(int index) { styleObj* style = (styleObj *) msRemoveStyle(self, index); if (style) MS_REFCNT_INCR(style); return style; } int moveStyleUp(int index) { return msMoveStyleUp(self, index); } int moveStyleDown(int index) { return msMoveStyleDown(self, index); } } mapserver-6.4.1/mapscript/swiginc/rect.i0000644002461700001440000001175212261257215020076 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript rectObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend rectObj { rectObj(double minx=-1.0, double miny=-1.0, double maxx=-1.0, double maxy=-1.0, int imageunits=MS_FALSE) { rectObj *rect; if (imageunits == MS_FALSE) { if (minx > maxx || miny > maxy) { msSetError(MS_RECTERR, "{ 'minx': %f , 'miny': %f , 'maxx': %f , 'maxy': %f }", "rectObj()", minx, miny, maxx, maxy); return NULL; } } else { if (minx > maxx || maxy > miny) { msSetError(MS_RECTERR, "image (pixel/line) units { 'minx': %f , 'miny': %f , 'maxx': %f , 'maxy': %f }", "rectObj()", minx, miny, maxx, maxy); return NULL; } } rect = (rectObj *)calloc(1, sizeof(rectObj)); if (!rect) return(NULL); rect->minx = minx; rect->miny = miny; rect->maxx = maxx; rect->maxy = maxy; return(rect); } ~rectObj() { free(self); } int project(projectionObj *projin, projectionObj *projout) { return msProjectRect(projin, projout, self); } double fit(int width, int height) { return msAdjustExtent(self, width, height); } int draw(mapObj *map, layerObj *layer, imageObj *image, int classindex, char *text) { shapeObj shape; msInitShape(&shape); msRectToPolygon(*self, &shape); shape.classindex = classindex; if(text && layer->class[classindex]->numlabels > 0) { shape.text = strdup(text); msShapeGetAnnotation(layer,&shape); } msDrawShape(map, layer, &shape, image, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); msFreeShape(&shape); return MS_SUCCESS; } %newobject getCenter; pointObj *getCenter() { pointObj *center; center = (pointObj *)calloc(1, sizeof(pointObj)); if (!center) { msSetError(2, "Failed to allocate memory for point", "getCenter()"); return NULL; } center->x = (self->minx + self->maxx)/2; center->y = (self->miny + self->maxy)/2; return center; } %newobject toPolygon; shapeObj *toPolygon() { lineObj line = {0,NULL}; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = MS_SHAPE_POLYGON; line.point = (pointObj *)malloc(sizeof(pointObj)*5); line.point[0].x = self->minx; line.point[0].y = self->miny; line.point[1].x = self->minx; line.point[1].y = self->maxy; line.point[2].x = self->maxx; line.point[2].y = self->maxy; line.point[3].x = self->maxx; line.point[3].y = self->miny; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; msAddLine(shape, &line); msComputeBounds(shape); free(line.point); return shape; } %newobject toString; char *toString() { char buffer[256]; char fmt[]="{ 'minx': %.16g , 'miny': %.16g , 'maxx': %.16g , 'maxy': %.16g }"; msRectToFormattedString(self, (char *) &fmt, (char *) &buffer, 256); return strdup(buffer); } } mapserver-6.4.1/mapscript/swiginc/owsrequest.i0000644002461700001440000001100412261257215021350 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for manipulating OGC request stuff via mapscript. Author: Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 2004 Sean Gillies Copyright (c) 2006 Frank Warmerdam 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 or substantial portions of the 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. =========================================================================== */ %{ static char *msGetEnvURL( const char *key, void *thread_context ) { if( strcmp(key,"REQUEST_METHOD") == 0 ) return "GET"; if( strcmp(key,"QUERY_STRING") == 0 ) return (char *) thread_context; return NULL; } %} %rename(OWSRequest) cgiRequestObj; %include "../../cgiutil.h" /* Class for programming OWS services - SG */ %extend cgiRequestObj { cgiRequestObj() { cgiRequestObj *request; request = msAllocCgiObj(); if (!request) { msSetError(MS_CGIERR, "Failed to initialize object","OWSRequest()"); return NULL; } return request; } ~cgiRequestObj() { msFreeCgiObj(self); } int loadParams() { self->NumParams = loadParams( self, NULL, NULL, 0, NULL); return self->NumParams; } int loadParamsFromURL( const char *url ) { self->NumParams = loadParams( self, msGetEnvURL, NULL, 0, (void*)url ); return self->NumParams; } void setParameter(char *name, char *value) { int i; if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "setItem()", MS_DEFAULT_CGI_PARAMS); } for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { free(self->ParamValues[i]); self->ParamValues[i] = strdup(value); break; } } if (i == self->NumParams) { self->ParamNames[self->NumParams] = strdup(name); self->ParamValues[self->NumParams] = strdup(value); self->NumParams++; } } void addParameter(char *name, char *value) { if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "addParameter()", MS_DEFAULT_CGI_PARAMS); } self->ParamNames[self->NumParams] = strdup(name); self->ParamValues[self->NumParams] = strdup(value); self->NumParams++; } char *getName(int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getName()", self->NumParams-1); return NULL; } return self->ParamNames[index]; } char *getValue(int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getValue()", self->NumParams-1); return NULL; } return self->ParamValues[index]; } char *getValueByName(const char *name) { int i; for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { return self->ParamValues[i]; } } return NULL; } } mapserver-6.4.1/mapscript/swiginc/resultcache.i0000644002461700001440000000332012261257215021433 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript resultCacheObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend resultCacheObj { resultObj *getResult(int i) { if (i >= 0 && i < self->numresults) { return &self->results[i]; } return NULL; } } mapserver-6.4.1/mapscript/swiginc/map.i0000644002461700001440000003327512261257215017722 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript mapObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend mapObj { mapObj(char *filename="") { if (filename && strlen(filename)) return msLoadMap(filename, NULL); else { /* create an empty map, no layers etc... */ return msNewMapObj(); } } ~mapObj() { msFreeMap(self); } #ifdef SWIGJAVA %newobject cloneMap; mapObj *cloneMap() #else %newobject clone; mapObj *clone() #endif { mapObj *dstMap; dstMap = msNewMapObj(); if (msCopyMap(dstMap, self) != MS_SUCCESS) { msFreeMap(dstMap); dstMap = NULL; } return dstMap; } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {layerObj *layer}; #endif int insertLayer(layerObj *layer, int index=-1) { return msInsertLayer(self, layer, index); } #ifdef SWIGCSHARP %clear layerObj *layer; #endif %newobject removeLayer; layerObj *removeLayer(int index) { layerObj *layer=msRemoveLayer(self, index); MS_REFCNT_INCR(layer); return layer; } int setExtent(double minx, double miny, double maxx, double maxy) { return msMapSetExtent( self, minx, miny, maxx, maxy ); } int offsetExtent(double x, double y) { return msMapOffsetExtent( self, x, y ); } int scaleExtent(double zoomfactor, double minscaledenom, double maxscaledenom) { return msMapScaleExtent( self, zoomfactor, minscaledenom, maxscaledenom ); } int setCenter(pointObj *center) { return msMapSetCenter( self, center ); } /* recent rotation work makes setSize the only reliable method for changing the image size. direct access is deprecated. */ int setSize(int width, int height) { return msMapSetSize(self, width, height); } int setRotation( double rotation_angle ) { return msMapSetRotation( self, rotation_angle ); } %newobject getLayer; layerObj *getLayer(int i) { if(i >= 0 && i < self->numlayers) { MS_REFCNT_INCR(self->layers[i]); return (self->layers[i]); /* returns an EXISTING layer */ } else { return NULL; } } %newobject getLayerByName; layerObj *getLayerByName(char *name) { int i; i = msGetLayerIndex(self, name); if(i != -1) { MS_REFCNT_INCR(self->layers[i]); return (self->layers[i]); /* returns an EXISTING layer */ } else return NULL; } int getSymbolByName(char *name) { return msGetSymbolIndex(&self->symbolset, name, MS_TRUE); } void prepareQuery() { int status; status = msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &self->scaledenom); if(status != MS_SUCCESS) self->scaledenom = -1; } %newobject prepareImage; imageObj *prepareImage() { return msPrepareImage(self, MS_FALSE); } void setImageType( char * imagetype ) { outputFormatObj *format; format = msSelectOutputFormat( self, imagetype ); if( format == NULL ) msSetError(MS_MISCERR, "Unable to find IMAGETYPE '%s'.", "setImageType()", imagetype ); else { msFree( self->imagetype ); self->imagetype = strdup(imagetype); msApplyOutputFormat( &(self->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } } void selectOutputFormat( char *imagetype ) { outputFormatObj *format; format = msSelectOutputFormat( self, imagetype ); if ( format == NULL ) msSetError(MS_MISCERR, "Unable to find IMAGETYPE '%s'.", "setImageType()", imagetype ); else { msFree( self->imagetype ); self->imagetype = strdup(imagetype); msApplyOutputFormat( &(self->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } } %newobject getOutputFormat; outputFormatObj *getOutputFormat(int i) { if(i >= 0 && i < self->numoutputformats) { MS_REFCNT_INCR(self->outputformatlist[i]); return (self->outputformatlist[i]); } else { return NULL; } } void setOutputFormat( outputFormatObj *format ) { msApplyOutputFormat( &(self->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } %newobject draw; imageObj *draw() { return msDrawMap(self, MS_FALSE); } %newobject drawQuery; imageObj *drawQuery() { return msDrawMap(self, MS_TRUE); } %newobject drawLegend; imageObj *drawLegend() { return msDrawLegend(self, MS_FALSE, NULL); } %newobject drawScalebar; imageObj *drawScalebar() { return msDrawScalebar(self); } %newobject drawReferenceMap; imageObj *drawReferenceMap() { return msDrawReferenceMap(self); } int embedScalebar(imageObj *image) { return msEmbedScalebar(self, image); } int embedLegend(imageObj *image) { return msEmbedLegend(self, image); } int drawLabelCache(imageObj *image) { return msDrawLabelCache(image, self); } labelCacheMemberObj *getLabel(int i) { return msGetLabelCacheMember(&(self->labelcache), i); } labelCacheMemberObj *nextLabel() { static int i=0; if(ilabelcache.numlabels) return msGetLabelCacheMember(&(self->labelcache), i++); else return NULL; } int queryByFilter(char *string) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_FILTER; self->query.filter = (expressionObj *) malloc(sizeof(expressionObj)); self->query.filter->string = strdup(string); self->query.filter->type = 2000; /* MS_EXPRESSION: lot's of conflicts in mapfile.h */ self->query.filter->compiled = MS_FALSE; self->query.filter->flags = 0; self->query.filter->tokens = self->query.filter->curtoken = NULL; self->query.rect = self->extent; return msQueryByFilter(self); } int queryByPoint(pointObj *point, int mode, double buffer) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_POINT; self->query.mode = mode; self->query.point = *point; self->query.buffer = buffer; return msQueryByPoint(self); } int queryByRect(rectObj rect) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_RECT; self->query.mode = MS_QUERY_MULTIPLE; self->query.rect = rect; return msQueryByRect(self); } int queryByFeatures(int slayer) { self->query.slayer = slayer; return msQueryByFeatures(self); } int queryByShape(shapeObj *shape) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_SHAPE; self->query.mode = MS_QUERY_MULTIPLE; self->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(self->query.shape); msCopyShape(shape, self->query.shape); return msQueryByShape(self); } int setWKTProjection(char *wkt) { return msOGCWKT2ProjectionObj(wkt, &(self->projection), self->debug); } %newobject getProjection; char *getProjection() { return msGetProjectionString(&(self->projection)); } int setProjection(char *proj4) { return msLoadProjectionString(&(self->projection), proj4); } int save(char *filename) { return msSaveMap(self, filename); } int saveQuery(char *filename, int results=MS_FALSE) { return msSaveQuery(self, filename, results); } int loadQuery(char *filename) { return msLoadQuery(self, filename); } void freeQuery(int qlayer=-1) { msQueryFree(self, qlayer); } int saveQueryAsGML(char *filename, const char *ns="GOMF") { return msGMLWriteQuery(self, filename, ns); } char *getMetaData(char *name) { char *value = NULL; if (!name) { msSetError(MS_HASHERR, "NULL key", "getMetaData"); } value = (char *) msLookupHashTable(&(self->web.metadata), name); if (!value) { msSetError(MS_HASHERR, "Key %s does not exist", "getMetaData", name); return NULL; } return value; } int setMetaData(char *name, char *value) { if (msInsertHashTable(&(self->web.metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int removeMetaData(char *name) { return(msRemoveHashTable(&(self->web.metadata), name)); } char *getFirstMetaDataKey() { return (char *) msFirstKeyFromHashTable(&(self->web.metadata)); } char *getNextMetaDataKey(char *lastkey) { return (char *) msNextKeyFromHashTable(&(self->web.metadata), lastkey); } int setSymbolSet(char *szFileName) { msFreeSymbolSet(&self->symbolset); msInitSymbolSet(&self->symbolset); self->symbolset.filename = strdup(szFileName); /* Symbolset shares same fontset as main mapfile */ self->symbolset.fontset = &(self->fontset); return msLoadSymbolSet(&self->symbolset, self); } int getNumSymbols() { return self->symbolset.numsymbols; } int setFontSet(char *filename) { msFreeFontSet(&(self->fontset)); msInitFontSet(&(self->fontset)); self->fontset.filename = strdup(filename); return msLoadFontSet(&(self->fontset), self); } /* I removed a method to get the fonset filename. Instead I updated mapserver.h to allow SWIG access to the fonset, although the numfonts and filename members are read-only. Use the setFontSet method to actually change the fontset. To get the filename do $map->{fontset}->{filename}; -- SG */ int saveMapContext(char *szFileName) { return msSaveMapContext(self, szFileName); } int loadMapContext(char *szFileName, int useUniqueNames=MS_FALSE) { return msLoadMapContext(self, szFileName, useUniqueNames); } int moveLayerUp(int layerindex) { return msMoveLayerUp(self, layerindex); } int moveLayerDown(int layerindex) { return msMoveLayerDown(self, layerindex); } %newobject getLayersDrawingOrder; intarray *getLayersDrawingOrder() { int i; intarray *order; order = new_intarray(self->numlayers); for (i=0; inumlayers; i++) #if (defined(SWIGPYTHON) || defined(SWIGRUBY) ) && SWIG_VERSION >= 0x010328 /* 1.3.28 */ intarray___setitem__(order, i, self->layerorder[i]); #else intarray_setitem(order, i, self->layerorder[i]); #endif return order; } int setLayersDrawingOrder(int *panIndexes) { return msSetLayersdrawingOrder(self, panIndexes); } void setConfigOption(char *key, char *value) { msSetConfigOption(self,key,value); } char *getConfigOption(char *key) { return (char *) msGetConfigOption(self,key); } void applyConfigOptions() { msApplyMapConfigOptions( self ); } /* SLD */ int applySLD(char *sld) { return msSLDApplySLD(self, sld, -1, NULL, NULL); } int applySLDURL(char *sld) { return msSLDApplySLDURL(self, sld, -1, NULL, NULL); } %newobject generateSLD; char *generateSLD() { return (char *) msSLDGenerateSLD(self, -1, NULL); } %newobject processTemplate; char *processTemplate(int bGenerateImages, char **names, char **values, int numentries) { return msProcessTemplate(self, bGenerateImages, names, values, numentries); } %newobject processLegendTemplate; char *processLegendTemplate(char **names, char **values, int numentries) { return msProcessLegendTemplate(self, names, values, numentries); } %newobject processQueryTemplate; char *processQueryTemplate(char **names, char **values, int numentries) { return msProcessQueryTemplate(self, 1, names, values, numentries); } outputFormatObj *getOutputFormatByName(char *name) { return msSelectOutputFormat(self, name); } int appendOutputFormat(outputFormatObj *format) { return msAppendOutputFormat(self, format); } int removeOutputFormat(char *name) { return msRemoveOutputFormat(self, name); } int loadOWSParameters(cgiRequestObj *request, char *wmtver_string="1.1.1") { return msMapLoadOWSParameters(self, request, wmtver_string); } int OWSDispatch( cgiRequestObj *req ) { return msOWSDispatch( self, req, MS_TRUE ); } %newobject convertToString; char* convertToString() { return msWriteMapToString(self); } } mapserver-6.4.1/mapscript/swiginc/web.i0000644002461700001440000000422412261257215017712 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript webObj extensions Author: Steve Lime Umberto Nicoletti unicoletti@prometeo.it =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %include "../../mapserver.h" /* Constructor and destructor for webObj http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=579 */ %extend webObj { webObj() { webObj *web; web = (webObj *) malloc(sizeof(webObj)); initWeb(web); return web; } ~webObj() { if (!self) return; freeWeb(self); free(self); } int updateFromString(char *snippet) { return msUpdateWebFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteWebToString(self); } } mapserver-6.4.1/mapscript/swiginc/image.i0000644002461700001440000002133012261257215020214 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript imageObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================*/ %extend imageObj { /* imageObj constructor now takes filename as an optional argument. * If the target language is Python, we ignore this constructor and * instead use the one in python/pymodule.i. */ #ifndef SWIGPYTHON imageObj(int width, int height, outputFormatObj *input_format=NULL, const char *file=NULL, double resolution=MS_DEFAULT_RESOLUTION, double defresolution=MS_DEFAULT_RESOLUTION) { imageObj *image=NULL; outputFormatObj *format; rendererVTableObj *renderer = NULL; rasterBufferObj *rb = NULL; if (input_format) { format = input_format; } else { format = msCreateDefaultOutputFormat(NULL, "GD/GIF", "gdgif"); if (format == NULL) format = msCreateDefaultOutputFormat(NULL, "GD/PNG", "gdpng"); if (format == NULL) if (format) msInitializeRendererVTable(format); } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "imageObj()"); return NULL; } if (file) { renderer = format->vtable; rb = (rasterBufferObj*) malloc(sizeof(rasterBufferObj)); if (!rb) { msSetError(MS_MEMERR, NULL, "imageObj()"); return NULL; } if ( (renderer->loadImageFromFile((char *)file, rb)) == MS_FAILURE) return NULL; image = msImageCreate(rb->width, rb->height, format, NULL, NULL, resolution, defresolution, NULL); renderer->mergeRasterBuffer(image, rb, 1.0, 0, 0, 0, 0, rb->width, rb->height); msFreeRasterBuffer(rb); free(rb); return image; } image = msImageCreate(width, height, format, NULL, NULL, resolution, defresolution, NULL); return image; } #endif ~imageObj() { msFreeImage(self); } /* saveGeo - see Bugzilla issue 549 */ void save(char *filename, mapObj *map=NULL) { msSaveImage(map, self, filename ); } /* ====================================================================== write() Write image data to an open file handle. Intended to replace saveToString. See python/pyextend.i for the Python specific version of this method. ====================================================================== */ #ifndef SWIGPYTHON int write( FILE *file=NULL ) { int retval=MS_FAILURE; rendererVTableObj *renderer = NULL; if (MS_RENDERER_PLUGIN(self->format)) { if (file) { renderer = self->format->vtable; /* FIXME? as an improvement, pass a map argument instead of the NULL (see #4216) */ retval = renderer->saveImage(self, NULL, file, self->format); } else { retval = msSaveImage(NULL, self, NULL); } } else { msSetError(MS_IMGERR, "Writing of %s format not implemented", "imageObj::write"); } return retval; } #endif /* ----------------------------------------------------------------------- saveToString is deprecated and no longer supported. Users should use the write() method instead. ----------------------------------------------------------------------- */ #if defined SWIGTCL8 Tcl_Obj *saveToString() { #ifdef FORCE_BROKEN_GD_CODE unsigned char *imgbytes; int size; Tcl_Obj *imgstring; #if GD2_VERS > 1 if(self->format->imagemode == MS_IMAGEMODE_RGBA) { gdImageSaveAlpha(self->img.gd, 1); } else if (self->format->imagemode == MS_IMAGEMODE_RGB) { gdImageSaveAlpha(self->img.gd, 0); } #endif if(strcasecmp("ON", msGetOutputFormatOption(self->format, "INTERLACE", "ON" )) == 0) { gdImageInterlace(self->img.gd, 1); } if(self->format->transparent) { gdImageColorTransparent(self->img.gd, 0); } if(strcasecmp(self->format->driver, "gd/gif") == 0) { #ifdef USE_GD_GIF imgbytes = gdImageGifPtr(self->img.gd, &size); #else msSetError(MS_MISCERR, "GIF output is not available.", "saveToString()"); return(MS_FAILURE); #endif } else if (strcasecmp(self->format->driver, "gd/png") == 0) { #ifdef USE_GD_PNG imgbytes = gdImagePngPtr(self->img.gd, &size); #else msSetError(MS_MISCERR, "PNG output is not available.", "saveToString()"); return(MS_FAILURE); #endif } else if (strcasecmp(self->format->driver, "gd/jpeg") == 0) { #ifdef USE_GD_JPEG imgbytes = gdImageJpegPtr(self->img.gd, &size, atoi(msGetOutputFormatOption(self->format, "QUALITY", "75" ))); #else msSetError(MS_MISCERR, "JPEG output is not available.", "saveToString()"); return(MS_FAILURE); #endif } else if (strcasecmp(self->format->driver, "gd/wbmp") == 0) { #ifdef USE_GD_WBMP imgbytes = gdImageWBMPPtr(self->img.gd, &size, 1); #else msSetError(MS_MISCERR, "WBMP output is not available.", "saveToString()"); return(MS_FAILURE); #endif } else { msSetError(MS_MISCERR, "Unknown output image type driver: %s.", "saveToString()", self->format->driver ); return(MS_FAILURE); } /* Tcl implementation to create string */ imgstring = Tcl_NewByteArrayObj(imgbytes, size); msFree(imgbytes); return imgstring; #else /* force_gd_broken_code */ msSetError(MS_MISCERR, "saveToString() is long deprecated and severley broken", "saveToString()", self->format->driver ); return(MS_FAILURE); #endif } #endif /* ------------------------------------------------------------------------- getBytes returns a gdBuffer structure (defined in mapscript.i) which must be typemapped to an object appropriate to the target language. This typemap must also msFree the data member of the gdBuffer. See the type- maps in java/javamodule.i and python/pymodule.i for examples. contributed by Jerry Pisk, jerry.pisk@gmail.com ------------------------------------------------------------------------- */ gdBuffer getBytes() { gdBuffer buffer; buffer.owns_data = MS_TRUE; buffer.data = msSaveImageBuffer(self, &buffer.size, self->format); if( buffer.data == NULL || buffer.size == 0 ) { buffer.data = NULL; msSetError(MS_MISCERR, "Failed to get image buffer", "getBytes"); return buffer; } return buffer; } int getSize() { gdBuffer buffer; int size=0; buffer.data = msSaveImageBuffer(self, &buffer.size, self->format); size = buffer.size; if( buffer.data == NULL || buffer.size == 0 ) { buffer.data = NULL; msSetError(MS_MISCERR, "Failed to get image buffer size", "getSize"); } free(buffer.data); return size; } } mapserver-6.4.1/mapscript/swiginc/dbfinfo.i0000644002461700001440000000471112261257215020545 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript DBFInfo extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ /* class extensions for DBFInfo - TP mods */ %extend DBFInfo { char *getFieldName(int iField) { static char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pszFieldName; } int getFieldWidth(int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnWidth; } int getFieldDecimals(int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnDecimals; } int getFieldType(int iField) { return msDBFGetFieldInfo(self, iField, NULL, NULL, NULL); } } mapserver-6.4.1/mapscript/swiginc/legend.i0000644002461700001440000000331512261257215020373 0ustar tbonfortusers/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript legendObj extensions Author: Steve Lime =========================================================================== 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 or substantial portions of the 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. =========================================================================== */ %extend legendObj { int updateFromString(char *snippet) { return msUpdateLegendFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteLegendToString(self); } } mapserver-6.4.1/mapscript/swiginc/msio.i0000644002461700001440000000651712261257215020113 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Definitions for MapServer IO redirection capability. * Author: Frank Warmerdam, warmerdam@pobox.com * * Note: * copied from mapio.h to avoid to much #ifdef swigging * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * 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. ****************************************************************************/ /* $Id$ */ void msIO_resetHandlers(void); void msIO_installStdoutToBuffer(void); void msIO_installStdinFromBuffer(void); %newobject msIO_stripStdoutBufferContentType; const char *msIO_stripStdoutBufferContentType(); void msIO_stripStdoutBufferContentHeaders(void); /* mapscript only extensions */ const char *msIO_getStdoutBufferString(void); gdBuffer msIO_getStdoutBufferBytes(void); %{ const char *msIO_getStdoutBufferString() { msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_getStdoutBufferString" ); return ""; } buf = (msIOBuffer *) ctx->cbData; /* write one zero byte and backtrack if it isn't already there */ if( buf->data_len == 0 || buf->data[buf->data_offset] != '\0' ) { msIO_bufferWrite( buf, "", 1 ); buf->data_offset--; } return (const char *) (buf->data); } gdBuffer msIO_getStdoutBufferBytes() { msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; gdBuffer gdBuf; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_getStdoutBufferString" ); gdBuf.data = (unsigned char*)""; gdBuf.size = 0; gdBuf.owns_data = MS_FALSE; return gdBuf; } buf = (msIOBuffer *) ctx->cbData; gdBuf.data = buf->data; gdBuf.size = buf->data_offset; gdBuf.owns_data = MS_TRUE; /* we are seizing ownership of the buffer contents */ buf->data_offset = 0; buf->data_len = 0; buf->data = NULL; return gdBuf; } %} mapserver-6.4.1/mapscript/swiginc/shapefile.i0000644002461700001440000001024412261257215021074 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript shapefileObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend shapefileObj { shapefileObj(char *filename, int type=-1) { shapefileObj *shapefile; int status; shapefile = (shapefileObj *)malloc(sizeof(shapefileObj)); if (!shapefile) return NULL; if (type == -1) status = msShapefileOpen(shapefile, "rb", filename, MS_TRUE); else if (type == -2) status = msShapefileOpen(shapefile, "rb+", filename, MS_TRUE); else status = msShapefileCreate(shapefile, filename, type); if (status == -1) { msShapefileClose(shapefile); free(shapefile); return NULL; } return(shapefile); } ~shapefileObj() { msShapefileClose(self); free(self); } int get(int i, shapeObj *shape) { if (i<0 || i>=self->numshapes) return MS_FAILURE; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); return MS_SUCCESS; } %newobject getShape; shapeObj *getShape(int i) { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = self->type; msSHPReadShape(self->hSHP, i, shape); return shape; } int getPoint(int i, pointObj *point) { if (i<0 || i>=self->numshapes) return MS_FAILURE; msSHPReadPoint(self->hSHP, i, point); return MS_SUCCESS; } int getTransformed(mapObj *map, int i, shapeObj *shape) { if (i<0 || i>=self->numshapes) return MS_FAILURE; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); msTransformShapeSimplify(shape, map->extent, map->cellsize); return MS_SUCCESS; } void getExtent(int i, rectObj *rect) { msSHPReadBounds(self->hSHP, i, rect); } int add(shapeObj *shape) { /* Trap NULL or empty shapes -- bug 1201 */ if (!shape) { msSetError(MS_SHPERR, "Can't add NULL shape", "shapefileObj::add"); return MS_FAILURE; } else if (!shape->line) { msSetError(MS_SHPERR, "Can't add empty shape", "shapefileObj::add"); return MS_FAILURE; } return msSHPWriteShape(self->hSHP, shape); } int addPoint(pointObj *point) { return msSHPWritePoint(self->hSHP, point); } DBFInfo *getDBF() { return self->hDBF; } } mapserver-6.4.1/mapscript/swiginc/connpool.i0000644002461700001440000000306212261257215020763 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for connection pool management Author: Umberto Nicoletti, unicoletti@prometeo.it =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ void msConnPoolCloseUnreferenced(); mapserver-6.4.1/mapscript/swiginc/symbolset.i0000644002461700001440000000633312261257215021161 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript symbolSetObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend symbolSetObj { symbolSetObj(const char *symbolfile=NULL) { symbolSetObj *symbolset; mapObj *temp_map=NULL; symbolset = (symbolSetObj *) malloc(sizeof(symbolSetObj)); msInitSymbolSet(symbolset); if (symbolfile) { symbolset->filename = strdup(symbolfile); temp_map = msNewMapObj(); msLoadSymbolSet(symbolset, temp_map); symbolset->map = NULL; msFreeMap(temp_map); } return symbolset; } ~symbolSetObj() { msFreeSymbolSet(self); if (self->filename) free(self->filename); free(self); } %newobject getSymbol; symbolObj *getSymbol(int i) { if (i >= 0 && i < self->numsymbols) { symbolObj *s=self->symbol[i]; MS_REFCNT_INCR(s); return s; } else return NULL; } %newobject getSymbolByName; symbolObj *getSymbolByName(char *symbolname) { int i; if (!symbolname) return NULL; i = msGetSymbolIndex(self, symbolname, MS_TRUE); if (i == -1) return NULL; else { MS_REFCNT_INCR(self->symbol[i]); return self->symbol[i]; } } int index(char *symbolname) { return msGetSymbolIndex(self, symbolname, MS_TRUE); } int appendSymbol(symbolObj *symbol) { return msAppendSymbol(self, symbol); } %newobject removeSymbol; symbolObj *removeSymbol(int index) { symbolObj *s=msRemoveSymbol(self, index); if (s!=NULL) { MS_REFCNT_INCR(s); } return s; } int save(const char *filename) { return msSaveSymbolSet(self, filename); } } mapserver-6.4.1/mapscript/swiginc/line.i0000644002461700001440000000565112261257215020071 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript lineObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend lineObj { lineObj() { lineObj *line; line = (lineObj *)malloc(sizeof(lineObj)); if (!line) return(NULL); line->numpoints=0; line->point=NULL; return line; } ~lineObj() { free(self->point); free(self); } int project(projectionObj *projin, projectionObj *projout) { return msProjectLine(projin, projout, self); } pointObj *get(int i) { if (i<0 || i>=self->numpoints) return NULL; else return &(self->point[i]); } int add(pointObj *p) { if (self->numpoints == 0) { /* new */ self->point = (pointObj *)malloc(sizeof(pointObj)); if (!self->point) return MS_FAILURE; } else { /* extend array */ self->point = (pointObj *)realloc(self->point, sizeof(pointObj)*(self->numpoints+1)); if (!self->point) return MS_FAILURE; } self->point[self->numpoints].x = p->x; self->point[self->numpoints].y = p->y; self->numpoints++; return MS_SUCCESS; } int set(int i, pointObj *p) { if (i<0 || i>=self->numpoints) return MS_FAILURE; self->point[i].x = p->x; self->point[i].y = p->y; return MS_SUCCESS; } } mapserver-6.4.1/mapscript/swiginc/hashtable.i0000644002461700001440000000655612261257215021102 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript hashTableObj extensions Author: Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %{ #include "../../maphash.h" %} /* ======================================================================== * Include maphash header, first stating declarations to ignore * ======================================================================== */ /* ignore the hashObj struct */ %ignore hashObj; /* ignore items and make numitems immutable */ %ignore items; %immutable numitems; %include "../../maphash.h" /* ======================================================================== * Extension methods * ======================================================================== */ %extend hashTableObj { /* New instance */ #if defined(SWIGJAVA) || defined(SWIGCSHARP) hashTableObj() { #else hashTableObj(void) { #endif return msCreateHashTable(); } /* Destroy instance */ ~hashTableObj() { msFreeHashTable(self); } /* set a hash item given key and value */ int set(char *key, char *value) { if (msInsertHashTable(self, key, value) == NULL) { return MS_FAILURE; } return MS_SUCCESS; } /* get value from item by its key */ char *get(char *key, char *default_value=NULL) { char *value = NULL; if (!key) { msSetError(MS_HASHERR, "NULL key", "get"); } value = (char *) msLookupHashTable(self, key); if (!value) { return default_value; } return value; } /* Remove one item from hash table */ int remove(char *key) { return msRemoveHashTable(self, key); } /* Clear all items in hash table (to NULL) */ void clear(void) { msFreeHashItems(self); initHashTable(self); } /* Return the next key or first key if prevkey == NULL */ const char *nextKey(char *prevkey=NULL) { return msNextKeyFromHashTable(self, (const char *) prevkey); } } mapserver-6.4.1/mapscript/swiginc/referencemap.i0000644002461700001440000000334512261257215021574 0ustar tbonfortusers/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript referenceMapObj extensions Author: Steve Lime =========================================================================== 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 or substantial portions of the 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. =========================================================================== */ %extend referenceMapObj { int updateFromString(char *snippet) { return msUpdateReferenceMapFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteReferenceMapToString(self); } } mapserver-6.4.1/mapscript/swiginc/result.i0000644002461700001440000000363512261257215020460 0ustar tbonfortusers/* =========================================================================== $Id: shape.i 9558 2009-11-20 18:11:50Z sdlime $ Project: MapServer Purpose: SWIG interface file for mapscript shapeObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend resultObj { resultObj(long shapeindex) { resultObj *result = (resultObj *) msSmallMalloc(sizeof(resultObj)); result->tileindex = -1; result->resultindex = -1; result->shapeindex = shapeindex; return result; } ~resultObj() { free(self); } } mapserver-6.4.1/mapscript/swiginc/color.i0000644002461700001440000000737012261257215020260 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript colorObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %{ #include "../../mapserver.h" %} %extend colorObj { colorObj(int red=0, int green=0, int blue=0, int pen=MS_PEN_UNSET) { colorObj *color; /* Check colors */ if (red > 255 || green > 255 || blue > 255) { msSetError(MS_MISCERR, "Invalid color index.", "colorObj()"); return NULL; } color = (colorObj *)calloc(1, sizeof(colorObj)); if (!color) return(NULL); MS_INIT_COLOR(*color, red, green, blue, 255); return(color); } ~colorObj() { free(self); } int setRGB(int red, int green, int blue) { /* Check colors */ if (red > 255 || green > 255 || blue > 255) { msSetError(MS_MISCERR, "Invalid color index.", "setRGB()"); return MS_FAILURE; } MS_INIT_COLOR(*self, red, green, blue, 255); return MS_SUCCESS; } int setHex(char *psHexColor) { int red, green, blue; if (psHexColor && strlen(psHexColor)== 7 && psHexColor[0] == '#') { red = msHexToInt(psHexColor+1); green = msHexToInt(psHexColor+3); blue= msHexToInt(psHexColor+5); if (red > 255 || green > 255 || blue > 255) { msSetError(MS_MISCERR, "Invalid color index.", "setHex()"); return MS_FAILURE; } MS_INIT_COLOR(*self, red, green, blue, 255); return MS_SUCCESS; } else { msSetError(MS_MISCERR, "Invalid hex color.", "setHex()"); return MS_FAILURE; } } %newobject toHex; char *toHex() { char hexcolor[8] = ""; if (!self) { msSetError(MS_MISCERR, "Can't express NULL color as hex", "toHex()"); return NULL; } if (self->red < 0 || self->green < 0 || self->blue < 0) { msSetError(MS_MISCERR, "Can't express invalid color as hex", "toHex()"); return NULL; } snprintf(hexcolor, 8, "#%02x%02x%02x", self->red, self->green, self->blue); return strdup(hexcolor); } } mapserver-6.4.1/mapscript/swiginc/cluster.i0000644002461700001440000000451712261257215020623 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript clusterObj extensions Author: Tamas Szekeres =========================================================================== 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 or substantial portions of the 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. =========================================================================== */ %extend clusterObj { int updateFromString(char *snippet) { return msUpdateClusterFromString(self, snippet); } %newobject convertToString; char* convertToString() { return msWriteClusterToString(self); } int setGroup(char *group) { if (!group || strlen(group) == 0) { freeExpression(&self->group); return MS_SUCCESS; } else return msLoadExpressionString(&self->group, group); } %newobject getGroupString; char *getGroupString() { return msGetExpressionString(&(self->group)); } int setFilter(char *filter) { if (!filter || strlen(filter) == 0) { freeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, filter); } %newobject getFilterString; char *getFilterString() { return msGetExpressionString(&(self->filter)); } } mapserver-6.4.1/mapscript/swiginc/label.i0000644002461700001440000001072112261257215020213 0ustar tbonfortusers/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript labelObj extensions Author: Steve Lime =========================================================================== 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 or substantial portions of the 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. =========================================================================== */ %extend labelObj { labelObj() { labelObj *label; label = (labelObj *)calloc(1, sizeof(labelObj)); if (!label) return(NULL); initLabel(label); return(label); } ~labelObj() { freeLabel(self); } int updateFromString(char *snippet) { return msUpdateLabelFromString(self, snippet,MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteLabelToString(self); } int removeBinding(int binding) { if(binding < 0 || binding >= MS_LABEL_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } return MS_SUCCESS; } char *getBinding(int binding) { if(binding < 0 || binding >= MS_LABEL_BINDING_LENGTH) return NULL; return self->bindings[binding].item; } int setBinding(int binding, char *item) { if(!item) return MS_FAILURE; if(binding < 0 || binding >= MS_LABEL_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } self->bindings[binding].item = strdup(item); self->numbindings++; return MS_SUCCESS; } int setExpression(char *expression) { if (!expression || strlen(expression) == 0) { freeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, expression); } %newobject getExpressionString; char *getExpressionString() { return msGetExpressionString(&(self->expression)); } int setText(char *text) { if (!text || strlen(text) == 0) { freeExpression(&self->text); return MS_SUCCESS; } else return msLoadExpressionString(&self->text, text); } %newobject getTextString; char *getTextString() { return msGetExpressionString(&(self->text)); } %newobject getStyle; styleObj *getStyle(int i) { if (i >= 0 && i < self->numstyles) { MS_REFCNT_INCR(self->styles[i]); return self->styles[i]; } else { msSetError(MS_CHILDERR, "Invalid index: %d", "getStyle()", i); return NULL; } } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {styleObj *style}; #endif int insertStyle(styleObj *style, int index=-1) { return msInsertLabelStyle(self, style, index); } #ifdef SWIGCSHARP %clear styleObj *style; #endif %newobject removeStyle; styleObj *removeStyle(int index) { styleObj* style = (styleObj *) msRemoveLabelStyle(self, index); if (style) MS_REFCNT_INCR(style); return style; } int moveStyleUp(int index) { return msMoveLabelStyleUp(self, index); } int moveStyleDown(int index) { return msMoveLabelStyleDown(self, index); } } mapserver-6.4.1/mapscript/swiginc/shape.i0000644002461700001440000001670612261257215020245 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript shapeObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend shapeObj { shapeObj(int type=MS_SHAPE_NULL) { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); if(type >= 0) shape->type = type; return shape; } ~shapeObj() { msFreeShape(self); free(self); } %newobject fromWKT; static shapeObj *fromWKT(char *wkt) { shapeObj *shape; if(!wkt) return NULL; shape = msShapeFromWKT(wkt); if(!shape) return NULL; return shape; } int project(projectionObj *projin, projectionObj *projout) { return msProjectShape(projin, projout, self); } lineObj *get(int i) { if (i<0 || i>=self->numlines) return NULL; else return &(self->line[i]); } int add(lineObj *line) { return msAddLine(self, line); } int draw(mapObj *map, layerObj *layer, imageObj *image) { return msDrawShape(map, layer, self, image, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); } void setBounds() { msComputeBounds(self); return; } #ifdef SWIGJAVA %newobject cloneShape; shapeObj *cloneShape() #else %newobject clone; shapeObj *clone() #endif { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = self->type; msCopyShape(self, shape); return shape; } int copy(shapeObj *dest) { return(msCopyShape(self, dest)); } %newobject toWKT; char *toWKT() { return msShapeToWKT(self); } %newobject buffer; shapeObj *buffer(double width) { return msGEOSBuffer(self, width); } %newobject simplify; shapeObj *simplify(double tolerance) { return msGEOSSimplify(self, tolerance); } %newobject topologyPreservingSimplify; shapeObj *topologyPreservingSimplify(double tolerance) { return msGEOSTopologyPreservingSimplify(self, tolerance); } %newobject convexHull; shapeObj *convexHull() { return msGEOSConvexHull(self); } %newobject boundary; shapeObj *boundary() { return msGEOSBoundary(self); } %newobject getCentroid; pointObj *getCentroid() { return msGEOSGetCentroid(self); } %newobject Union; shapeObj *Union(shapeObj *shape) { return msGEOSUnion(self, shape); } %newobject intersection; shapeObj *intersection(shapeObj *shape) { return msGEOSIntersection(self, shape); } %newobject difference; shapeObj *difference(shapeObj *shape) { return msGEOSDifference(self, shape); } %newobject symDifference; shapeObj *symDifference(shapeObj *shape) { return msGEOSSymDifference(self, shape); } int contains(shapeObj *shape) { return msGEOSContains(self, shape); } int overlaps(shapeObj *shape) { return msGEOSOverlaps(self, shape); } int within(shapeObj *shape) { return msGEOSWithin(self, shape); } int crosses(shapeObj *shape) { return msGEOSCrosses(self, shape); } int intersects(shapeObj *shape) { return msGEOSIntersects(self, shape); } /* if GEOS is not present an alternative computation is provided, see mapgeos.c */ int touches(shapeObj *shape) { return msGEOSTouches(self, shape); } int equals(shapeObj *shape) { return msGEOSEquals(self, shape); } int disjoint(shapeObj *shape) { return msGEOSDisjoint(self, shape); } double getArea() { return msGEOSArea(self); } double getLength() { return msGEOSLength(self); } char *getValue(int i) { if (i >= 0 && i < self->numvalues && self->values) return (self->values[i]); else return NULL; } int contains(pointObj *point) { if (self->type == MS_SHAPE_POLYGON) return msIntersectPointPolygon(point, self); return -1; } double distanceToPoint(pointObj *point) { return msDistancePointToShape(point, self); /* should there be a GEOS version of this? */ } double distanceToShape(shapeObj *shape) { return msGEOSDistance(self, shape); /* note this calls msDistanceShapeToShape() if GEOS support is not present */ } %newobject getLabelPoint; pointObj *getLabelPoint() { pointObj *point = (pointObj *)calloc(1, sizeof(pointObj)); if (point == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for point", "labelPoint()"); return NULL; } if(self->type == MS_SHAPE_POLYGON && msPolygonLabelPoint(self, point, -1) == MS_SUCCESS) return point; free(point); return NULL; } int setValue(int i, char *value) { if (!self->values || !value) { msSetError(MS_SHPERR, "Can't set value", "setValue()"); return MS_FAILURE; } if (i >= 0 && i < self->numvalues) { msFree(self->values[i]); self->values[i] = strdup(value); if (!self->values[i]) { return MS_FAILURE; } else return MS_SUCCESS; } else { msSetError(MS_SHPERR, "Invalid value index", "setValue()"); return MS_FAILURE; } } void initValues(int numvalues) { int i; if(self->values) msFreeCharArray(self->values, self->numvalues); self->values = NULL; self->numvalues = 0; /* Allocate memory for the values */ if (numvalues > 0) { if ((self->values = (char **)malloc(sizeof(char *)*numvalues)) == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for values", "shapeObj()"); return; } else { for (i=0; ivalues[i] = strdup(""); } self->numvalues = numvalues; } } } mapserver-6.4.1/mapscript/swiginc/style.i0000644002461700001440000001236712261257215020304 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript styleObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== See Bugzilla issue 548 about work on styleObj and classObj */ %extend styleObj { styleObj(classObj *parent_class=NULL) { styleObj *style = NULL; if (parent_class!=NULL) { if ((style = msGrowClassStyles(parent_class)) == NULL) return NULL; if ( initStyle(style) == MS_FAILURE ) { msSetError(MS_MISCERR, "Failed to init new styleObj instance", "initStyle()"); } parent_class->numstyles++; MS_REFCNT_INCR(style); } else { style = (styleObj *) malloc(sizeof(styleObj)); if (!style) { msSetError(MS_MEMERR, "Failed to allocate memory for new styleObj instance", "styleObj()"); return NULL; } if ( initStyle(style) == MS_FAILURE ) { msSetError(MS_MISCERR, "Failed to init new styleObj instance", "initStyle()"); msFree(style); return NULL; } } return style; } ~styleObj() { if (self) { if ( freeStyle(self) == MS_SUCCESS ) { free(self); self=NULL; } } } int updateFromString(char *snippet) { return msUpdateStyleFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteStyleToString(self); } #ifdef SWIGJAVA %newobject cloneStyle; styleObj *cloneStyle() #else %newobject clone; styleObj *clone() #endif { styleObj *style; style = (styleObj *) malloc(sizeof(styleObj)); if (!style) { msSetError(MS_MEMERR, "Could not allocate memory for new styleObj instance", "clone()"); return NULL; } if (initStyle(style) == -1) { msSetError(MS_MEMERR, "Failed to initialize Style", "clone()"); return NULL; } if (msCopyStyle(style, self) != MS_SUCCESS) { free(style); return NULL; } return style; } int setSymbolByName(mapObj *map, char* symbolname) { self->symbol = msGetSymbolIndex(&map->symbolset, symbolname, MS_TRUE); if (self->symbolname) free((char*)self->symbolname); if (symbolname) self->symbolname = strdup(symbolname); else self->symbolname = 0; return self->symbol; } int removeBinding(int binding) { if(binding < 0 || binding >= MS_STYLE_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } return MS_SUCCESS; } int setBinding(int binding, char *item) { if(!item) return MS_FAILURE; if(binding < 0 || binding >= MS_STYLE_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } self->bindings[binding].item = strdup(item); self->numbindings++; return MS_SUCCESS; } char *getBinding(int binding) { if(binding < 0 || binding >= MS_STYLE_BINDING_LENGTH) return NULL; return self->bindings[binding].item; } char *getGeomTransform() { return self->_geomtransform.string; } void setGeomTransform(char *transform) { msStyleSetGeomTransform(self, transform); } } mapserver-6.4.1/mapscript/swiginc/symbol.i0000644002461700001440000001245212261257215020444 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript symbolObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %include "../../mapsymbol.h" /* Full support for symbols and addition of them to the map symbolset is done to resolve MapServer bug 579 http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=579 */ %extend symbolObj { symbolObj(char *symbolname, const char *imagefile=NULL) { symbolObj *symbol; symbol = (symbolObj *) malloc(sizeof(symbolObj)); initSymbol(symbol); symbol->name = strdup(symbolname); if (imagefile) { msLoadImageSymbol(symbol, imagefile); } return symbol; } ~symbolObj() { if (self) { if (msFreeSymbol(self)==MS_SUCCESS) { free(self); self=NULL; } } } int setImagepath(const char *imagefile) { return msLoadImageSymbol(self, imagefile); } int setPoints(lineObj *line) { int i; self->sizex = 0; self->sizey = 0; for (i=0; inumpoints; i++) { MS_COPYPOINT(&(self->points[i]), &(line->point[i])); self->sizex = MS_MAX(self->sizex, self->points[i].x); self->sizey = MS_MAX(self->sizey, self->points[i].y); } self->numpoints = line->numpoints; return self->numpoints; } %newobject getPoints; lineObj *getPoints() { int i; lineObj *line; line = (lineObj *) malloc(sizeof(lineObj)); line->point = (pointObj *) malloc(sizeof(pointObj)*(self->numpoints)); for (i=0; inumpoints; i++) { line->point[i].x = self->points[i].x; line->point[i].y = self->points[i].y; } line->numpoints = self->numpoints; return line; } %newobject getImage; imageObj *getImage(outputFormatObj *input_format) { imageObj *image = NULL; outputFormatObj *format = NULL; rendererVTableObj *renderer = NULL; if (self->type != MS_SYMBOL_PIXMAP) { msSetError(MS_SYMERR, "Can't return image from non-pixmap symbol", "getImage()"); return NULL; } if (input_format) { format = input_format; } else { format = msCreateDefaultOutputFormat(NULL, "GD/GIF", "gdgif"); if (format == NULL) format = msCreateDefaultOutputFormat(NULL, "GD/PNG", "gdpng"); if (format) msInitializeRendererVTable(format); } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "getImage()"); return NULL; } renderer = format->vtable; msPreloadImageSymbol(renderer, self); if (self->pixmap_buffer) { image = msImageCreate(self->pixmap_buffer->width, self->pixmap_buffer->height, format, NULL, NULL, MS_DEFAULT_RESOLUTION, MS_DEFAULT_RESOLUTION, NULL); renderer->mergeRasterBuffer(image, self->pixmap_buffer, 1.0, 0, 0, 0, 0, self->pixmap_buffer->width, self->pixmap_buffer->height); } return image; } int setImage(imageObj *image) { rendererVTableObj *renderer = NULL; renderer = image->format->vtable; if (self->pixmap_buffer) { msFreeRasterBuffer(self->pixmap_buffer); free(self->pixmap_buffer); } self->pixmap_buffer = (rasterBufferObj*)malloc(sizeof(rasterBufferObj)); if (!self->pixmap_buffer) { msSetError(MS_MEMERR, NULL, "setImage()"); return MS_FAILURE; } self->type = MS_SYMBOL_PIXMAP; renderer->getRasterBufferCopy(image, self->pixmap_buffer); return MS_SUCCESS; } } mapserver-6.4.1/mapscript/swiginc/scalebar.i0000644002461700001440000000332512261257215020712 0ustar tbonfortusers/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript scalebarObj extensions Author: Steve Lime =========================================================================== 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 or substantial portions of the 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. =========================================================================== */ %extend scalebarObj { int updateFromString(char *snippet) { return msUpdateScalebarFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteScalebarToString(self); } } mapserver-6.4.1/mapscript/swiginc/projection.i0000644002461700001440000000443512261257215021315 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript projectionObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend projectionObj { projectionObj(char *proj4) { int status; projectionObj *proj=NULL; proj = (projectionObj *)malloc(sizeof(projectionObj)); if (!proj) return NULL; msInitProjection(proj); status = msLoadProjectionString(proj, proj4); if (status == -1) { msFreeProjection(proj); free(proj); return NULL; } return proj; } ~projectionObj() { msFreeProjection(self); free(self); } int setWKTProjection(char* wkt) { /* no debug output here */ return msOGCWKT2ProjectionObj(wkt, self, MS_FALSE); } int getUnits() { return GetMapserverUnitUsingProj(self); } } mapserver-6.4.1/mapscript/swiginc/layer.i0000644002461700001440000004320512261257215020253 0ustar tbonfortusers /* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript layerObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend layerObj { layerObj(mapObj *map=NULL) { layerObj *layer; int result; if (!map) { layer = (layerObj *) malloc(sizeof(layerObj)); if (!layer) { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } result = initLayer(layer, NULL); if (result == MS_SUCCESS) { layer->index = -1; return layer; } else { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } } else { if(msGrowMapLayers(map) == NULL) return(NULL); if (initLayer((map->layers[map->numlayers]), map) == -1) return(NULL); map->layers[map->numlayers]->index = map->numlayers; map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; MS_REFCNT_INCR(map->layers[map->numlayers-1]); return (map->layers[map->numlayers-1]); } } ~layerObj() { /*if (!self->map) {*/ if (self) { if(freeLayer(self)==MS_SUCCESS) { free(self); } } } #ifdef SWIGJAVA %newobject cloneLayer; layerObj *cloneLayer() #else %newobject clone; layerObj *clone() #endif { layerObj *layer; int result; layer = (layerObj *) malloc(sizeof(layerObj)); if (!layer) { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } result = initLayer(layer, NULL); if (result != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } if (msCopyLayer(layer, self) != MS_SUCCESS) { freeLayer(layer); free(layer); layer = NULL; } layer->map = NULL; layer->index = -1; return layer; } int updateFromString(char *snippet) { return msUpdateLayerFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteLayerToString(self); } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {classObj *classobj}; #endif int insertClass(classObj *classobj, int index=-1) { return msInsertClass(self, classobj, index); } #ifdef SWIGCSHARP %clear classObj *classobj; #endif /* removeClass() */ %newobject removeClass; classObj *removeClass(int index) { classObj* c = msRemoveClass(self, index); if (c != NULL) { MS_REFCNT_INCR(c); } return c; } int open() { int status; status = msLayerOpen(self); if (status == MS_SUCCESS) { return msLayerGetItems(self); } return status; } int whichShapes(rectObj rect) { int oldconnectiontype = self->connectiontype; self->connectiontype = MS_INLINE; if(msLayerWhichItems(self, MS_TRUE, NULL) != MS_SUCCESS) { self->connectiontype = oldconnectiontype; return MS_FAILURE; } self->connectiontype = oldconnectiontype; return msLayerWhichShapes(self, rect, MS_FALSE); } %newobject nextShape; shapeObj *nextShape() { int status; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); status = msLayerNextShape(self, shape); if(status != MS_SUCCESS) { msFreeShape(shape); free(shape); return NULL; } else return shape; } void close() { msLayerClose(self); } %newobject getShape; shapeObj *getShape(resultObj *record) { int retval; shapeObj *shape; if (!record) return NULL; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = self->type; /* is this right? */ retval = msLayerGetShape(self, shape, record); return shape; } int getNumResults() { if (!self->resultcache) return 0; return self->resultcache->numresults; } %newobject getResultsBounds; rectObj *getResultsBounds() { rectObj *bounds; if (!self->resultcache) return NULL; bounds = (rectObj *) malloc(sizeof(rectObj)); MS_COPYRECT(bounds, &self->resultcache->bounds); return bounds; } resultObj *getResult(int i) { if (!self->resultcache) return NULL; if (i >= 0 && i < self->resultcache->numresults) return &self->resultcache->results[i]; else return NULL; } %newobject getClass; classObj *getClass(int i) { classObj *result=NULL; if (i >= 0 && i < self->numclasses) { result=self->class[i]; MS_REFCNT_INCR(result); } return result; } char *getItem(int i) { if (i >= 0 && i < self->numitems) return (char *) (self->items[i]); else return NULL; } int setItems(char **items, int numitems) { return msLayerSetItems(self, items, numitems); } int draw(mapObj *map, imageObj *image) { return msDrawLayer(map, self, image); } int drawQuery(mapObj *map, imageObj *image) { return msDrawQueryLayer(map, self, image); } /* For querying, we switch layer status ON and then back to original value before returning. */ int queryByFilter(mapObj *map, char *string) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.filter = (expressionObj *) malloc(sizeof(expressionObj)); map->query.filter->string = strdup(string); map->query.filter->type = 2000; /* MS_EXPRESSION: lot's of conflicts in mapfile.h */ map->query.filter->compiled = MS_FALSE; map->query.filter->flags = 0; map->query.filter->tokens = map->query.filter->curtoken = NULL; map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByFilter(map); self->status = status; return retval; } int queryByAttributes(mapObj *map, char *qitem, char *qstring, int mode) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_ATTRIBUTE; map->query.mode = mode; if(qitem) map->query.item = strdup(qitem); if(qstring) map->query.str = strdup(qstring); map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByAttributes(map); self->status = status; return retval; } int queryByPoint(mapObj *map, pointObj *point, int mode, double buffer) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_POINT; map->query.mode = mode; map->query.point = *point; map->query.buffer = buffer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByPoint(map); self->status = status; return retval; } int queryByRect(mapObj *map, rectObj rect) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.rect = rect; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByRect(map); self->status = status; return retval; } int queryByFeatures(mapObj *map, int slayer) { int status; int retval; map->query.slayer = slayer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByFeatures(map); self->status = status; return retval; } int queryByShape(mapObj *map, shapeObj *shape) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_SHAPE; map->query.mode = MS_QUERY_MULTIPLE; map->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(map->query.shape); msCopyShape(shape, map->query.shape); map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByShape(map); self->status = status; return retval; } int queryByIndex(mapObj *map, int tileindex, int shapeindex, int bAddToQuery=MS_FALSE) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_INDEX; map->query.mode = MS_QUERY_SINGLE; map->query.tileindex = tileindex; map->query.shapeindex = shapeindex; map->query.clear_resultcache = !bAddToQuery; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByIndex(map); self->status = status; return retval; } resultCacheObj *getResults(void) { return self->resultcache; } int setFilter(char *filter) { if (!filter || strlen(filter) == 0) { freeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, filter); } %newobject getFilterString; char *getFilterString() { return msGetExpressionString(&(self->filter)); } int setWKTProjection(char *wkt) { self->project = MS_TRUE; return msOGCWKT2ProjectionObj(wkt, &(self->projection), self->debug); } %newobject getProjection; char *getProjection() { return (char *) msGetProjectionString(&(self->projection)); } int setProjection(char *proj4) { self->project = MS_TRUE; return msLoadProjectionString(&(self->projection), proj4); } int addFeature(shapeObj *shape) { self->connectiontype = MS_INLINE; if(self->features != NULL && self->features->tailifhead != NULL) shape->index = self->features->tailifhead->shape.index + 1; else shape->index = 0; if (insertFeatureList(&(self->features), shape) == NULL) return MS_FAILURE; return MS_SUCCESS; } /* Returns the number of inline feature of a layer */ int getNumFeatures() { return msLayerGetNumFeatures(self); } %newobject getExtent; rectObj *getExtent() { rectObj *extent; extent = (rectObj *) malloc(sizeof(rectObj)); msLayerGetExtent(self, extent); return extent; } int setExtent(double minx=-1.0, double miny=-1.0, double maxx=-1.0, double maxy=-1.0) { if (minx > maxx || miny > maxy) { msSetError(MS_RECTERR, "{ 'minx': %f , 'miny': %f , 'maxx': %f , 'maxy': %f }", "layerObj::setExtent()", minx, miny, maxx, maxy); return MS_FAILURE; } return msLayerSetExtent(self, minx, miny, maxx, maxy); } /* The following metadata methods are no longer needed since we have promoted the metadata member of layerObj to a first-class mapscript object. See hashtable.i. Not yet scheduled for deprecation but perhaps in the next major release? --SG */ char *getMetaData(char *name) { char *value = NULL; if (!name) { msSetError(MS_HASHERR, "NULL key", "getMetaData"); } value = (char *) msLookupHashTable(&(self->metadata), name); /* Umberto, 05/17/2006 Exceptions should be reserved for situations when a serious error occurred and normal program flow must be interrupted. In this case returning null should be more that enough. */ #ifndef SWIGJAVA if (!value) { msSetError(MS_HASHERR, "Key %s does not exist", "getMetaData", name); return NULL; } #endif return value; } int setMetaData(char *name, char *value) { if (msInsertHashTable(&(self->metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int removeMetaData(char *name) { return(msRemoveHashTable(&(self->metadata), name)); } char *getFirstMetaDataKey() { return (char *) msFirstKeyFromHashTable(&(self->metadata)); } char *getNextMetaDataKey(char *lastkey) { return (char *) msNextKeyFromHashTable(&(self->metadata), lastkey); } %newobject getWMSFeatureInfoURL; char *getWMSFeatureInfoURL(mapObj *map, int click_x, int click_y, int feature_count, char *info_format) { return (char *) msWMSGetFeatureInfoURL(map, self, click_x, click_y, feature_count, info_format); } %newobject executeWFSGetFeature; char *executeWFSGetFeature(layerObj *layer) { return (char *) msWFSExecuteGetFeature(layer); } int applySLD(char *sld, char *stylelayer) { return msSLDApplySLD(self->map, sld, self->index, stylelayer, NULL); } int applySLDURL(char *sld, char *stylelayer) { return msSLDApplySLDURL(self->map, sld, self->index, stylelayer, NULL); } %newobject generateSLD; char *generateSLD() { return (char *) msSLDGenerateSLD(self->map, self->index, NULL); } int isVisible() { if (!self->map) { msSetError(MS_MISCERR, "visibility has no meaning outside of a map context", "isVisible()"); return MS_FAILURE; } return msLayerIsVisible(self->map, self); } int moveClassUp(int index) { return msMoveClassUp(self, index); } int moveClassDown(int index) { return msMoveClassDown(self, index); } void setProcessingKey(const char *key, const char *value) { msLayerSetProcessingKey( self, key, value ); } /* this method is deprecated ... should use addProcessing() */ void setProcessing(const char *directive ) { msLayerAddProcessing( self, directive ); } void addProcessing(const char *directive ) { msLayerAddProcessing( self, directive ); } char *getProcessing(int index) { return (char *) msLayerGetProcessing(self, index); } char *getProcessingKey(const char *key) { return (char *) msLayerGetProcessingKey(self, key); } int clearProcessing() { return msLayerClearProcessing(self); } int setConnectionType(int connectiontype, const char *library_str) { /* Caller is responsible to close previous layer correctly before * calling msConnectLayer() */ if (msLayerIsOpen(self)) msLayerClose(self); return msConnectLayer(self, connectiontype, library_str); } int getClassIndex(mapObj *map, shapeObj *shape, int *classgroup=NULL, int numclasses=0) { return msShapeGetClass(self, map, shape, classgroup, numclasses); } char *getGeomTransform() { return self->_geomtransform.string; } void setGeomTransform(char *transform) { msFree(self->_geomtransform.string); if (!transform || strlen(transform) > 0) { self->_geomtransform.string = msStrdup(transform); self->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } else { self->_geomtransform.type = MS_GEOMTRANSFORM_NONE; self->_geomtransform.string = NULL; } } } mapserver-6.4.1/mapscript/swiginc/error.i0000644002461700001440000000432712261257215020272 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript errorObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ /* wrap the errorObj and a few functions */ %include "../../maperror.h" /* A few things neccessary for automatically wrapped functions */ %newobject msGetErrorString; %extend errorObj { errorObj() { return msGetErrorObj(); } ~errorObj() {} errorObj *next() { errorObj *ep; if (self == NULL || self->next == NULL) return NULL; ep = msGetErrorObj(); while (ep != self) { /* We reached end of list of active errorObj and didn't find the errorObj... this is bad! */ if (ep->next == NULL) return NULL; ep = ep->next; } return ep->next; } } mapserver-6.4.1/mapscript/swiginc/mapzoom.i0000644002461700001440000006453612261257215020633 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Map zooming convenience methods for MapScript * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * * These functions are adapted from the code in php_mapscript.c. * *****************************************************************************/ %extend mapObj { /* ----------------------------------------------------------------------- Zoom by the given factor to a pixel position within the width and height bounds. If max_extent is not NULL, the zoom is constrained to the max_extents ----------------------------------------------------------------------- */ int zoomPoint(int zoomfactor, pointObj *poPixPos, int width, int height, rectObj *poGeorefExt, rectObj *poMaxGeorefExt) { double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; rectObj oNewGeorefExt; double dfNewScale; int bMaxExtSet; double dfDeltaExt; double dX, dY; dfNewScale = 0.0; bMaxExtSet = 0; dfDeltaExt = -1.0; if (poMaxGeorefExt != NULL) { bMaxExtSet = 1; } /* ----------------------------------------------------------- */ /* check the validity of the parameters. */ /* ----------------------------------------------------------- */ if (zoomfactor == 0 || width <= 0 || height <= 0 || poGeorefExt == NULL || poPixPos == NULL) { msSetError(MS_MISCERR, "Incorrect arguments", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } /* ----------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* ----------------------------------------------------------- */ if (poGeorefExt->minx >= poGeorefExt->maxx) { msSetError(MS_MISCERR, "Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } if (poGeorefExt->miny >= poGeorefExt->maxy) { msSetError(MS_MISCERR, "Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } if (bMaxExtSet == 1) { if (poMaxGeorefExt->minx >= poMaxGeorefExt->maxx) { msSetError(MS_MISCERR, "Max Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } if (poMaxGeorefExt->miny >= poMaxGeorefExt->maxy) { msSetError(MS_MISCERR, "Max Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomPoint()"); } } dfDeltaX = poGeorefExt->maxx - poGeorefExt->minx; dfDeltaY = poGeorefExt->maxy - poGeorefExt->miny; dX = dfDeltaX/((double)width); dY = dfDeltaY/((double)height); dfGeoPosX = poGeorefExt->minx + dX * (double)poPixPos->x; dfGeoPosY = poGeorefExt->maxy - dY * (double)poPixPos->y; /* --- -------------------------------------------------------- */ /* zoom in */ /* ------------------------------------------------------------ */ if (zoomfactor > 1) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaX/(2*zoomfactor)); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaY/(2*zoomfactor)); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaX/(2*zoomfactor)); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaY/(2*zoomfactor)); } if (zoomfactor < 0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaX/2)*(abs(zoomfactor)); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaY/2)*(abs(zoomfactor)); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaX/2)*(abs(zoomfactor)); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaY/2)*(abs(zoomfactor)); } if (zoomfactor == 1) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaX/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaY/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaX/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaY/2); } /* ------------------------------------------------------------ */ /* if the min and max scale are set in the map file, we will */ /* use them to test before zooming. */ /* ------------------------------------------------------------ */ msAdjustExtent(&oNewGeorefExt, self->width, self->height); msCalculateScale(oNewGeorefExt, self->units, self->width, self->height, self->resolution, &dfNewScale); if (self->web.maxscaledenom > 0) { if (zoomfactor < 0 && dfNewScale > self->web.maxscaledenom) { return MS_FAILURE; } } /* ============================================================ */ /* we do a spcial case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ============================================================ */ if (self->web.minscaledenom > 0 && dfNewScale < self->web.minscaledenom && zoomfactor > 1) { /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(self->web.minscaledenom, self->units, dfGeoPosY, self->width, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaExt/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaExt/2); } else return MS_FAILURE; } /* ------------------------------------------------------------ */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* ------------------------------------------------------------ */ if (bMaxExtSet) { dfDeltaX = oNewGeorefExt.maxx - oNewGeorefExt.minx; dfDeltaY = oNewGeorefExt.maxy - oNewGeorefExt.miny; /* Make sure Current georef extents is not bigger than * max extents */ if (dfDeltaX > (poMaxGeorefExt->maxx-poMaxGeorefExt->minx)) dfDeltaX = poMaxGeorefExt->maxx-poMaxGeorefExt->minx; if (dfDeltaY > (poMaxGeorefExt->maxy-poMaxGeorefExt->miny)) dfDeltaY = poMaxGeorefExt->maxy-poMaxGeorefExt->miny; if (oNewGeorefExt.minx < poMaxGeorefExt->minx) { oNewGeorefExt.minx = poMaxGeorefExt->minx; oNewGeorefExt.maxx = oNewGeorefExt.minx + dfDeltaX; } if (oNewGeorefExt.maxx > poMaxGeorefExt->maxx) { oNewGeorefExt.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (oNewGeorefExt.miny < poMaxGeorefExt->miny) { oNewGeorefExt.miny = poMaxGeorefExt->miny; oNewGeorefExt.maxy = oNewGeorefExt.miny + dfDeltaY; } if (oNewGeorefExt.maxy > poMaxGeorefExt->maxy) { oNewGeorefExt.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } /* ------------------------------------------------------------ */ /* set the map extents with new values. */ /* ------------------------------------------------------------ */ self->extent.minx = oNewGeorefExt.minx; self->extent.miny = oNewGeorefExt.miny; self->extent.maxx = oNewGeorefExt.maxx; self->extent.maxy = oNewGeorefExt.maxy; self->cellsize = msAdjustExtent(&(self->extent), self->width, self->height); dfDeltaX = self->extent.maxx - self->extent.minx; dfDeltaY = self->extent.maxy - self->extent.miny; if (bMaxExtSet) { if (self->extent.minx < poMaxGeorefExt->minx) { self->extent.minx = poMaxGeorefExt->minx; self->extent.maxx = self->extent.minx + dfDeltaX; } if (self->extent.maxx > poMaxGeorefExt->maxx) { self->extent.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (self->extent.miny < poMaxGeorefExt->miny) { self->extent.miny = poMaxGeorefExt->miny; self->extent.maxy = self->extent.miny + dfDeltaY; } if (self->extent.maxy > poMaxGeorefExt->maxy) { self->extent.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &(self->scaledenom)); return MS_SUCCESS; } int zoomRectangle(rectObj *poPixRect, int width, int height, rectObj *poGeorefExt, rectObj *poMaxGeorefExt) { double dfDeltaX, dfDeltaY; rectObj oNewGeorefExt; double dfNewScale; double dfDeltaExt; double dfMiddleX, dfMiddleY; double dX, dY; int bMaxExtSet; bMaxExtSet = 0; dfNewScale = 0.0; dfDeltaExt = -1.0; if (poMaxGeorefExt != NULL) bMaxExtSet = 1; /* ----------------------------------------------------------- */ /* check the validity of the parameters. */ /* ----------------------------------------------------------- */ if (poPixRect == 0 || width <= 0 || height <= 0 || poGeorefExt == NULL) { msSetError(MS_MISCERR, "Incorrect arguments", "mapscript::mapObj::zoomRectangle"); return MS_FAILURE; } /* ----------------------------------------------------------- */ /* check if the values passed are consistent min <= max. */ /* ----------------------------------------------------------- */ if (poPixRect->minx >= poPixRect->maxx) { msSetError(MS_MISCERR, "image rectangle minx >= maxx", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } /* This is not a typo: "maxx >= minx". For historical reason, we * keep this as it is. See documentation for more info about this check. */ if (poPixRect->maxy >= poPixRect->miny) { msSetError(MS_MISCERR, "image rectangle maxy >= miny", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (poGeorefExt->minx >= poGeorefExt->maxx) { msSetError(MS_MISCERR, "Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (poGeorefExt->miny >= poGeorefExt->maxy) { msSetError(MS_MISCERR, "Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (bMaxExtSet == 1) { if (poMaxGeorefExt->minx >= poMaxGeorefExt->maxx) { msSetError(MS_MISCERR, "Max Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (poMaxGeorefExt->miny >= poMaxGeorefExt->maxy) { msSetError(MS_MISCERR, "Max Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } } /* ----------------------------------------------------------- */ /* Convert pixel rectangle to georeferenced rectangle */ /* ----------------------------------------------------------- */ dfDeltaX = poGeorefExt->maxx - poGeorefExt->minx; dfDeltaY = poGeorefExt->maxy - poGeorefExt->miny; dX = dfDeltaX/((double)width); dY = dfDeltaY/((double)height); oNewGeorefExt.minx = Pix2Georef((int)poPixRect->minx, 0, width, poGeorefExt->minx, poGeorefExt->maxx, 0); oNewGeorefExt.maxx = Pix2Georef((int)poPixRect->maxx, 0, width, poGeorefExt->minx, poGeorefExt->maxx, 0); oNewGeorefExt.miny = Pix2Georef((int)poPixRect->miny, 0, height, poGeorefExt->miny, poGeorefExt->maxy, 1); oNewGeorefExt.maxy = Pix2Georef((int)poPixRect->maxy, 0, height, poGeorefExt->miny, poGeorefExt->maxy, 1); msAdjustExtent(&oNewGeorefExt, self->width, self->height); /* ------------------------------------------------------------ */ /* if the min and max scale are set in the map file, we will */ /* use them to test before setting extents. */ /* ------------------------------------------------------------ */ msCalculateScale(oNewGeorefExt, self->units, self->width, self->height, self->resolution, &dfNewScale); if (self->web.maxscaledenom > 0 && dfNewScale > self->web.maxscaledenom) return MS_FAILURE; if (self->web.minscaledenom > 0 && dfNewScale < self->web.minscaledenom) { dfMiddleX = oNewGeorefExt.minx + ((oNewGeorefExt.maxx - oNewGeorefExt.minx)/2); dfMiddleY = oNewGeorefExt.miny + ((oNewGeorefExt.maxy - oNewGeorefExt.miny)/2); /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(self->web.minscaledenom, self->units, dfMiddleY, self->width, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfMiddleX - (dfDeltaExt/2); oNewGeorefExt.miny = dfMiddleY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfMiddleX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfMiddleY + (dfDeltaExt/2); } else return MS_FAILURE; } /* ------------------------------------------------------------ */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* ------------------------------------------------------------ */ if (bMaxExtSet) { dfDeltaX = oNewGeorefExt.maxx - oNewGeorefExt.minx; dfDeltaY = oNewGeorefExt.maxy - oNewGeorefExt.miny; /* Make sure Current georef extents is not bigger * than max extents */ if (dfDeltaX > (poMaxGeorefExt->maxx-poMaxGeorefExt->minx)) dfDeltaX = poMaxGeorefExt->maxx-poMaxGeorefExt->minx; if (dfDeltaY > (poMaxGeorefExt->maxy-poMaxGeorefExt->miny)) dfDeltaY = poMaxGeorefExt->maxy-poMaxGeorefExt->miny; if (oNewGeorefExt.minx < poMaxGeorefExt->minx) { oNewGeorefExt.minx = poMaxGeorefExt->minx; oNewGeorefExt.maxx = oNewGeorefExt.minx + dfDeltaX; } if (oNewGeorefExt.maxx > poMaxGeorefExt->maxx) { oNewGeorefExt.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (oNewGeorefExt.miny < poMaxGeorefExt->miny) { oNewGeorefExt.miny = poMaxGeorefExt->miny; oNewGeorefExt.maxy = oNewGeorefExt.miny + dfDeltaY; } if (oNewGeorefExt.maxy > poMaxGeorefExt->maxy) { oNewGeorefExt.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } self->extent.minx = oNewGeorefExt.minx; self->extent.miny = oNewGeorefExt.miny; self->extent.maxx = oNewGeorefExt.maxx; self->extent.maxy = oNewGeorefExt.maxy; self->cellsize = msAdjustExtent(&(self->extent), self->width, self->height); dfDeltaX = self->extent.maxx - self->extent.minx; dfDeltaY = self->extent.maxy - self->extent.miny; if (bMaxExtSet) { if (self->extent.minx < poMaxGeorefExt->minx) { self->extent.minx = poMaxGeorefExt->minx; self->extent.maxx = self->extent.minx + dfDeltaX; } if (self->extent.maxx > poMaxGeorefExt->maxx) { self->extent.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (self->extent.miny < poMaxGeorefExt->miny) { self->extent.miny = poMaxGeorefExt->miny; self->extent.maxy = self->extent.miny + dfDeltaY; } if (self->extent.maxy > poMaxGeorefExt->maxy) { self->extent.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &(self->scaledenom)); return MS_SUCCESS; } /* ------------------------------------------------------------------- Zoom by the given factor to a pixel position within the width and height bounds. If max_extent is not NULL, the zoom is constrained to the max_extents ------------------------------------------------------------------- */ int zoomScale(double scale, pointObj *poPixPos, int width, int height, rectObj *poGeorefExt, rectObj *poMaxGeorefExt) { double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; rectObj oNewGeorefExt; double dfNewScale, dfCurrentScale; int bMaxExtSet; int nTmp; double dfDeltaExt; double dX, dY; dfNewScale = 0.0; dfCurrentScale = 0.0; nTmp = 0; bMaxExtSet = 0; dfDeltaExt = -1.0; if (poMaxGeorefExt != NULL) { bMaxExtSet = 1; } /* ----------------------------------------------------------- */ /* check the validity of the parameters. */ /* ----------------------------------------------------------- */ if (scale <= 0.0 || width <= 0 || height <= 0 || poGeorefExt == NULL || poPixPos == NULL ) { msSetError(MS_MISCERR, "Incorrect arguments", "mapscript::mapObj::zoomScale"); return MS_FAILURE; } /* ----------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* ----------------------------------------------------------- */ if (poGeorefExt->minx >= poGeorefExt->maxx) { msSetError(MS_MISCERR, "Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomScale()"); return MS_FAILURE; } if (poGeorefExt->miny >= poGeorefExt->maxy) { msSetError(MS_MISCERR, "Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomScale()"); return MS_FAILURE; } if (bMaxExtSet == 1) { if (poMaxGeorefExt->minx >= poMaxGeorefExt->maxx) { msSetError(MS_MISCERR, "Max Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomScale()"); return MS_FAILURE; } if (poMaxGeorefExt->miny >= poMaxGeorefExt->maxy) { msSetError(MS_MISCERR, "Max Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomScale()"); } } dfDeltaX = poGeorefExt->maxx - poGeorefExt->minx; dfDeltaY = poGeorefExt->maxy - poGeorefExt->miny; dX = dfDeltaX/((double)width); dY = dfDeltaY/((double)height); dfGeoPosX = poGeorefExt->minx + dX * (double)poPixPos->x; dfGeoPosY = poGeorefExt->maxy - dY * (double)poPixPos->y; /* ------------------------------------------------------------ */ /* Calculate new extents based on the scale. */ /* ------------------------------------------------------------ */ /* ============================================================ */ /* make sure to take the smallest size because this is the one */ /* that will be used to ajust the scale. */ /* ============================================================ */ if (self->width < self->height) nTmp = self->width; else nTmp = self->height; /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(scale, self->units, dfGeoPosY, nTmp, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaExt/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaExt/2); } else return MS_FAILURE; /* ------------------------------------------------------------ */ /* get current scale. */ /* ------------------------------------------------------------ */ msCalculateScale(*poGeorefExt, self->units, self->width, self->height, self->resolution, &dfCurrentScale); /* ------------------------------------------------------------ * * if the min and max scale are set in the map file, we will * * use them to test before zooming. * * * * This function has the same effect as zoomin or zoom out. * If the current scale is > newscale we zoom in; else it is * a zoom out. * ------------------------------------------------------------ */ msAdjustExtent(&oNewGeorefExt, self->width, self->height); msCalculateScale(oNewGeorefExt, self->units, self->width, self->height, self->resolution, &dfNewScale); if (self->web.maxscaledenom > 0) { if (dfCurrentScale < dfNewScale && dfNewScale > self->web.maxscaledenom) { return MS_FAILURE; } } /* ============================================================ */ /* we do a special case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ============================================================ */ if (self->web.minscaledenom > 0 && dfNewScale < self->web.minscaledenom && dfCurrentScale > dfNewScale) { /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(scale, self->units, dfGeoPosY, nTmp, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaExt/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaExt/2); } else return MS_FAILURE; } /* ------------------------------------------------------------ */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* ------------------------------------------------------------ */ if (bMaxExtSet) { dfDeltaX = oNewGeorefExt.maxx - oNewGeorefExt.minx; dfDeltaY = oNewGeorefExt.maxy - oNewGeorefExt.miny; /* Make sure Current georef extents is not bigger * than max extents */ if (dfDeltaX > (poMaxGeorefExt->maxx-poMaxGeorefExt->minx)) dfDeltaX = poMaxGeorefExt->maxx-poMaxGeorefExt->minx; if (dfDeltaY > (poMaxGeorefExt->maxy-poMaxGeorefExt->miny)) dfDeltaY = poMaxGeorefExt->maxy-poMaxGeorefExt->miny; if (oNewGeorefExt.minx < poMaxGeorefExt->minx) { oNewGeorefExt.minx = poMaxGeorefExt->minx; oNewGeorefExt.maxx = oNewGeorefExt.minx + dfDeltaX; } if (oNewGeorefExt.maxx > poMaxGeorefExt->maxx) { oNewGeorefExt.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (oNewGeorefExt.miny < poMaxGeorefExt->miny) { oNewGeorefExt.miny = poMaxGeorefExt->miny; oNewGeorefExt.maxy = oNewGeorefExt.miny + dfDeltaY; } if (oNewGeorefExt.maxy > poMaxGeorefExt->maxy) { oNewGeorefExt.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } self->extent.minx = oNewGeorefExt.minx; self->extent.miny = oNewGeorefExt.miny; self->extent.maxx = oNewGeorefExt.maxx; self->extent.maxy = oNewGeorefExt.maxy; self->cellsize = msAdjustExtent(&(self->extent), self->width, self->height); dfDeltaX = self->extent.maxx - self->extent.minx; dfDeltaY = self->extent.maxy - self->extent.miny; if (bMaxExtSet) { if (self->extent.minx < poMaxGeorefExt->minx) { self->extent.minx = poMaxGeorefExt->minx; self->extent.maxx = self->extent.minx + dfDeltaX; } if (self->extent.maxx > poMaxGeorefExt->maxx) { self->extent.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (self->extent.miny < poMaxGeorefExt->miny) { self->extent.miny = poMaxGeorefExt->miny; self->extent.maxy = self->extent.miny + dfDeltaY; } if (self->extent.maxy > poMaxGeorefExt->maxy) { self->extent.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &(self->scaledenom)); return MS_SUCCESS; } } mapserver-6.4.1/mapscript/swiginc/labelcache.i0000644002461700001440000000321412261257215021176 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript labelCacheObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 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 or substantial portions of the 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. =========================================================================== */ %extend labelCacheObj { void freeCache() { msFreeLabelCache(self); } } mapserver-6.4.1/mapscript/mapscript.i0000644002461700001440000001664612261257215017507 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for the MapServer mapscript module Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2005 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 or substantial portions of the 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. ============================================================================ */ %module mapscript #ifdef SWIGCSHARP %ignore frompointer; %include swig_csharp_extensions.i #endif #ifdef SWIGJAVA %ignore layerObj::extent; #endif %newobject msLoadMapFromString; %{ #include "../../mapserver.h" #include "../../maptemplate.h" #include "../../mapogcsld.h" #include "../../mapows.h" #include "../../cgiutil.h" #include "../../mapcopy.h" #include "../../maperror.h" #include "../../mapprimitive.h" #include "../../mapshape.h" #ifdef SWIGPYTHON #include "pygdioctx/pygdioctx.h" #endif %} /* Problem with SWIG CSHARP typemap for pointers */ #ifndef SWIGCSHARP %include typemaps.i #endif %include constraints.i %include carrays.i %array_class(int, intarray) /* =========================================================================== Supporting 'None' as an argument to attribute accessor functions Typemaps to support NULL in attribute accessor functions provided to Steve Lime by David Beazley and tested for Python only by Sean Gillies. With the use of these typemaps we can execute statements like layer.group = None ============================================================================ */ #ifdef __cplusplus %typemap(memberin) char * { if ($1) delete [] $1; if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } %typemap(memberin,warning="451:Setting const char * member may leak memory.") const char * { if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } %typemap(globalin) char * { if ($1) delete [] $1; if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } %typemap(globalin,warning="451:Setting const char * variable may leak memory.") const char * { if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } #else %typemap(memberin) char * { if ($1) free((char*)$1); if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } %typemap(memberin,warning="451:Setting const char * member may leak memory.") const char * { if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } %typemap(globalin) char * { if ($1) free((char*)$1); if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } %typemap(globalin,warning="451:Setting const char * variable may leak memory.") const char * { if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } #endif /* __cplusplus */ /* GD Buffer Mapping for use with imageObj::getBytes */ %{ #ifdef __cplusplus extern "C" { #endif typedef struct { unsigned char *data; int size; int owns_data; } gdBuffer; #ifdef __cplusplus } #endif %} /* ============================================================================ Exceptions Note: Python exceptions are in pymodule.i ============================================================================ */ #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGRUBY) %include "../mserror.i" #endif /* ============================================================================ Language-specific module code ============================================================================ */ /* C# */ #ifdef SWIGCSHARP %include "csmodule.i" #endif /* Java */ #ifdef SWIGJAVA %include "javamodule.i" #endif /* Python */ #ifdef SWIGPYTHON %include "pymodule.i" #endif /* SWIGPYTHON */ /* Ruby */ #ifdef SWIGRUBY %include "rbmodule.i" #endif /* Perl */ #ifdef SWIGPERL5 %include "plmodule.i" #endif /* Tcl */ #ifdef SWIGTCL8 %include "tclmodule.i" #endif /* SWIGTCL8 */ /* ============================================================================= Wrap MapServer structs into mapscript classes ============================================================================= */ %include "../../mapserver.h" %include "../../mapserver-version.h" %include "../../mapprimitive.h" %include "../../mapshape.h" %include "../../mapproject.h" %include "../../mapsymbol.h" %apply Pointer NONNULL { mapObj *map }; %apply Pointer NONNULL { layerObj *layer }; /* ============================================================================= Class extension methods are now included from separate interface files ============================================================================= */ %include "../swiginc/error.i" %include "../swiginc/map.i" %include "../swiginc/mapzoom.i" %include "../swiginc/symbol.i" %include "../swiginc/symbolset.i" %include "../swiginc/layer.i" %include "../swiginc/class.i" %include "../swiginc/cluster.i" %include "../swiginc/style.i" %include "../swiginc/rect.i" %include "../swiginc/image.i" %include "../swiginc/shape.i" %include "../swiginc/point.i" %include "../swiginc/line.i" %include "../swiginc/shapefile.i" %include "../swiginc/outputformat.i" %include "../swiginc/projection.i" %include "../swiginc/dbfinfo.i" %include "../swiginc/labelcache.i" %include "../swiginc/color.i" %include "../swiginc/hashtable.i" %include "../swiginc/resultcache.i" %include "../swiginc/result.i" %include "../swiginc/owsrequest.i" %include "../swiginc/connpool.i" %include "../swiginc/msio.i" %include "../swiginc/web.i" %include "../swiginc/label.i" %include "../swiginc/scalebar.i" %include "../swiginc/legend.i" %include "../swiginc/referencemap.i" %include "../swiginc/querymap.i" /* ============================================================================= Language-specific extensions to mapserver classes are included here ============================================================================= */ /* Java */ #ifdef SWIGJAVA %include "javaextend.i" #endif /* Python */ #ifdef SWIGPYTHON %include "pyextend.i" #endif /* SWIGPYTHON */ /* Ruby */ #ifdef SWIGRUBY %include "rbextend.i" #endif mapserver-6.4.1/mapscript/python/0000755002461700001440000000000012261257215016637 5ustar tbonfortusersmapserver-6.4.1/mapscript/python/wxs.py0000644002461700001440000000157212261257215020037 0ustar tbonfortusersimport mapscript map = mapscript.mapObj('../../tests/test.map') map.setMetaData( "ows_onlineresource", "http://dummy.org/" ) ows_req = mapscript.OWSRequest() ows_req.type = mapscript.MS_GET_REQUEST ows_req.setParameter( "SERVICE", "WMS" ); ows_req.setParameter( "VERSION", "1.1.0" ); ows_req.setParameter( "REQUEST", "GetCapabilities" ); mapscript.msIO_installStdoutToBuffer() dispatch_status = map.OWSDispatch(ows_req) if dispatch_status: status = '200 OK' else: status = '500 Internal Server Error' content_type = mapscript.msIO_stripStdoutBufferContentType() mapscript.msIO_stripStdoutBufferContentHeaders() result = mapscript.msIO_getStdoutBufferBytes() try: # MapServer 6.0: mapscript.msCleanup() except: # MapServer 6.1: mapscript.msCleanup(1) response_headers = [('Content-Type', content_type), ('Content-Length', str(len(result)))] mapserver-6.4.1/mapscript/python/pymodule.i0000644002461700001440000001475112261257215020657 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Python-specific enhancements to MapScript * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * * Python-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGPYTHON is defined (via 'swig -python ...'). * *****************************************************************************/ /****************************************************************************** * Simple Typemaps *****************************************************************************/ /* Translates Python None to C NULL for strings */ %typemap(in,parse="z") char * ""; /* Translate Python's built-in file object to FILE * */ %typemap(in) FILE * { if (!PyFile_Check($input)) { PyErr_SetString(PyExc_TypeError, "Input is not file"); return NULL; } $1 = PyFile_AsFile($input); } /* To support imageObj::getBytes */ %typemap(out) gdBuffer { $result = PyString_FromStringAndSize((const char*)$1.data, $1.size); if( $1.owns_data ) msFree($1.data); } /************************************************************************** * MapServer Errors and Python Exceptions ************************************************************************** * * Translation of errors reported via the ms_error structure into * Python exceptions. Original code by Chris Chamberlin * has been updated by Sean Gillies to use * PyErr_SetString, %exception and $action for SWIG 1.3, do the most * obvious mapping of MapServer errors to Python exceptions and map all * others to a new 'MapServerError' exception which can be caught like this: * * from mapscript import * * empty_map = mapObj('') * try: * img = empty_map.draw() * except MapServerError, msg: * print "Caught MapServerError:", msg * *************************************************************************/ %{ PyObject *MSExc_MapServerError; PyObject *MSExc_MapServerChildError; %} /* Module initialization: call msSetup() and register msCleanup() */ %init %{ /* See bug 1203 for discussion of race condition with GD font cache */ if (msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Failed to set up threads and font cache", "msSetup()"); } Py_AtExit(msCleanup); /* Define Generic MapServer error */ MSExc_MapServerError=PyErr_NewException("_mapscript.MapServerError",NULL,NULL); if (MSExc_MapServerError != NULL) PyDict_SetItemString(d, "MapServerError", MSExc_MapServerError); /* Define MapServer MS_CHILD error */ MSExc_MapServerChildError = PyErr_NewException("_mapscript.MapServerChildError", NULL, NULL); if (MSExc_MapServerChildError != NULL) PyDict_SetItemString(d, "MapServerChildError", MSExc_MapServerChildError); %} %{ static void _raise_ms_exception( void ); static void _raise_ms_exception() { int errcode; errorObj *ms_error; char *errmsg; ms_error = msGetErrorObj(); errcode = ms_error->code; errmsg = msGetErrorString("\n"); switch (errcode) { case MS_IOERR: PyErr_SetString(PyExc_IOError, errmsg); break; case MS_MEMERR: PyErr_SetString(PyExc_MemoryError, errmsg); break; case MS_TYPEERR: PyErr_SetString(PyExc_TypeError, errmsg); break; case MS_EOFERR: PyErr_SetString(PyExc_EOFError, errmsg); break; case MS_CHILDERR: PyErr_SetString(MSExc_MapServerChildError, errmsg); break; default: PyErr_SetString(MSExc_MapServerError, errmsg); break; } free(errmsg); } %} %exception { $action { errorObj *ms_error = msGetErrorObj(); switch(ms_error->code) { case MS_NOERR: break; case MS_NOTFOUND: msResetErrorList(); break; case -1: break; case MS_IOERR: if (strcmp(ms_error->routine, "msSearchDiskTree()") != 0) { _raise_ms_exception(); msResetErrorList(); return NULL; } default: _raise_ms_exception(); msResetErrorList(); return NULL; } } } %pythoncode %{ MapServerError = _mapscript.MapServerError MapServerChildError = _mapscript.MapServerChildError %} /* The bogus "if 1:" is to introduce a new scope to work around indentation handling with pythonappend in different versions. (#3180) */ %feature("pythonappend") layerObj %{if 1: self.p_map=None try: # python 2.5 if args and len(args)!=0: self.p_map=args[0] except NameError: # python 2.6 if map: self.p_map=map %} /* The bogus "if 1:" is to introduce a new scope to work around indentation handling with pythonappend in different versions. (#3180) */ %feature("pythonappend") classObj %{if 1: self.p_layer =None try: # python 2.5 if args and len(args)!=0: self.p_layer=args[0] except NameError: # python 2.6 if layer: self.p_layer=layer %} %feature("shadow") insertClass %{ def insertClass(*args): actualIndex=$action(*args) args[1].p_layer=args[0] return actualIndex%} %feature("shadow") getClass %{ def getClass(*args): clazz = $action(*args) if clazz: if args and len(args)!=0: clazz.p_layer=args[0] else: clazz.p_layer=None return clazz%} %feature("shadow") insertLayer %{ def insertLayer(*args): actualIndex=$action(*args) args[1].p_map=args[0] return actualIndex%} %feature("shadow") getLayer %{ def getLayer(*args): layer = $action(*args) if layer: if args and len(args)!=0: layer.p_map=args[0] else: layer.p_map=None return layer%} %feature("shadow") getLayerByName %{ def getLayerByName(*args): layer = $action(*args) if layer: if args and len(args)!=0: layer.p_map=args[0] else: layer.p_map=None return layer%} mapserver-6.4.1/mapscript/python/pyextend.i0000644002461700001440000003206412261257215020656 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Python-specific extensions to MapScript objects * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * * Python-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGPYTHON is defined (via 'swig -python ...'). * *****************************************************************************/ /* fromstring: Factory for mapfile objects */ %pythoncode { def fromstring(data, mappath=None): """Creates map objects from mapfile strings. Parameters ========== data : string Mapfile in a string. mappath : string Optional root map path, enabling relative paths in mapfile. Example ======= >>> mo = fromstring("MAP\nNAME 'test'\nEND") >>> mo.name 'test' """ import re if re.search("^\s*MAP", data, re.I): return msLoadMapFromString(data, mappath) elif re.search("^\s*LAYER", data, re.I): ob = layerObj() ob.updateFromString(data) return ob elif re.search("^\s*CLASS", data, re.I): ob = classObj() ob.updateFromString(data) return ob elif re.search("^\s*STYLE", data, re.I): ob = styleObj() ob.updateFromString(data) return ob else: raise ValueError, "No map, layer, class, or style found. Can not load from provided string" } /* =========================================================================== Python rectObj extensions ======================================================================== */ %extend pointObj { %pythoncode { def __str__(self): return self.toString() } } /* =========================================================================== Python rectObj extensions ======================================================================== */ %extend rectObj { %pythoncode { def __str__(self): return self.toString() def __contains__(self, item): item_type = str(type(item)) if item_type == "": if item.x >= self.minx and item.x <= self.maxx \ and item.y >= self.miny and item.y <= self.maxy: return True else: return False else: raise TypeError, \ '__contains__ does not yet handle %s' % (item_type) } } /****************************************************************************** * Extensions to mapObj *****************************************************************************/ %extend mapObj { /* getLayerOrder() extension returns the map layerorder as a native sequence */ PyObject *getLayerOrder() { int i; PyObject *order; order = PyTuple_New(self->numlayers); for (i = 0; i < self->numlayers; i++) { PyTuple_SetItem(order,i,PyInt_FromLong((long)self->layerorder[i])); } return order; } int setLayerOrder(PyObject *order) { int i, size; size = PyTuple_Size(order); for (i = 0; i < size; i++) { self->layerorder[i] = (int)PyInt_AsLong(PyTuple_GetItem(order, i)); } return MS_SUCCESS; } PyObject* getSize() { PyObject* output ; output = PyTuple_New(2); PyTuple_SetItem(output,0,PyInt_FromLong((long)self->width)); PyTuple_SetItem(output,1,PyInt_FromLong((long)self->height)); return output; } %pythoncode { def get_height(self): return self.getSize()[1] # <-- second member is the height def get_width(self): return self.getSize()[0] # <-- first member is the width def set_height(self, value): return self.setSize(self.getSize()[0], value) def set_width(self, value): return self.setSize(value, self.getSize()[1]) width = property(get_width, set_width) height = property(get_height, set_height) } } /**************************************************************************** * Support for bridging Python file-like objects and GD through IOCtx ***************************************************************************/ /****************************************************************************** * Extensions to imageObj *****************************************************************************/ %extend imageObj { /* New imageObj constructor taking an optional PyFile-ish object * argument. * * Furthermore, we are defaulting width and height so that in case * anyone wants to swig mapscript with the -keyword option, they can * omit width and height. Work done as part of Bugzilla issue 550. */ imageObj(PyObject *arg1=Py_None, PyObject *arg2=Py_None, PyObject *input_format=Py_None, PyObject *input_resolution=Py_None, PyObject *input_defresolution=Py_None) { #ifdef FORCE_BROKEN_GD_CODE imageObj *image=NULL; outputFormatObj *format=NULL; int width; int height; double resolution, defresolution; PyObject *pybytes; rendererVTableObj *renderer = NULL; rasterBufferObj *rb = NULL; unsigned char PNGsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; unsigned char JPEGsig[3] = {255, 216, 255}; resolution = defresolution = MS_DEFAULT_RESOLUTION; if ((PyInt_Check(arg1) && PyInt_Check(arg2)) || PyString_Check(arg1)) { if (input_format == Py_None) { format = msCreateDefaultOutputFormat(NULL, "GD/GIF", "gdgif"); if (format == NULL) format = msCreateDefaultOutputFormat(NULL, "GD/PNG", "gdpng"); if (format) msInitializeRendererVTable(format); } else if (PyString_Check(input_format)) { format = msCreateDefaultOutputFormat(NULL, PyString_AsString(input_format), NULL); } else { if ((SWIG_ConvertPtr(input_format, (void **) &format, SWIGTYPE_p_outputFormatObj, SWIG_POINTER_EXCEPTION | 0 )) == -1) { msSetError(MS_IMGERR, "Can't convert format pointer", "imageObj()"); return NULL; } } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "imageObj()"); return NULL; } } if (PyFloat_Check(input_resolution)) resolution = PyFloat_AsDouble(input_resolution); if (PyFloat_Check(input_defresolution)) defresolution = PyFloat_AsDouble(input_defresolution); if (PyInt_Check(arg1) && PyInt_Check(arg2)) { /* Create from width, height, format/driver */ width = (int) PyInt_AsLong(arg1); height = (int) PyInt_AsLong(arg2); image = msImageCreate(width, height, format, NULL, NULL, resolution, defresolution, NULL); return image; } /* Is arg1 a filename? */ else if (PyString_Check(arg1)) { renderer = format->vtable; rb = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); if (!rb) { msSetError(MS_MEMERR, NULL, "imageObj()"); return NULL; } if ( (renderer->loadImageFromFile(PyString_AsString(arg1), rb)) == MS_FAILURE) return NULL; image = msImageCreate(rb->width, rb->height, format, NULL, NULL, resolution, defresolution, NULL); renderer->mergeRasterBuffer(image, rb, 1.0, 0, 0, 0, 0, rb->width, rb->height); msFreeRasterBuffer(rb); free(rb); return image; } /* Is a file-like object */ else if (arg1 != Py_None) { if (PyObject_HasAttrString(arg1, "seek")) { /* Detect image format */ pybytes = PyObject_CallMethod(arg1, "read", "i", 8); PyObject_CallMethod(arg1, "seek", "i", 0); if (memcmp(PyString_AsString(pybytes),"GIF8",4)==0) { %#ifdef USE_GD_GIF image = createImageObjFromPyFile(arg1, "GD/GIF"); %#else msSetError(MS_MISCERR, "Unable to load GIF image.", "imageObj()"); %#endif } else if (memcmp(PyString_AsString(pybytes),PNGsig,8)==0) { %#ifdef USE_GD_PNG image = createImageObjFromPyFile(arg1, "GD/PNG"); %#else msSetError(MS_MISCERR, "Unable to load PNG image.", "imageObj()"); %#endif } else if (memcmp(PyString_AsString(pybytes),JPEGsig,3)==0) { %#ifdef USE_GD_JPEG image = createImageObjFromPyFile(arg1, "GD/JPEG"); %#else msSetError(MS_MISCERR, "Unable to load JPEG image.", "imageObj()"); %#endif } else { msSetError(MS_MISCERR, "Failed to detect image format. Likely cause is invalid image or improper filemode. On windows, Python files should be opened in 'rb' mode.", "imageObj()"); } return image; } else /* such as a url handle */ { /* If there is no seek method, we absolutely must have a driver name */ if (!PyString_Check(arg2)) { msSetError(MS_MISCERR, "A driver name absolutely must accompany file objects which do not have a seek() method", "imageObj()"); return NULL; } return (imageObj *) createImageObjFromPyFile(arg1, PyString_AsString(arg2)); } } else { msSetError(MS_IMGERR, "Failed to create image", "imageObj()"); return NULL; } #else msSetError(MS_IMGERR, "imageObj() is severely broken and should not be used","imageObj()"); return NULL; #endif } /* ====================================================================== write() Write image data to an open Python file or file-like object. Overrides extension method in mapscript/swiginc/image.i. Intended to replace saveToString. ====================================================================== */ int write( PyObject *file=Py_None ) { unsigned char *imgbuffer=NULL; int imgsize; PyObject *noerr; int retval=MS_FAILURE; rendererVTableObj *renderer = NULL; /* Return immediately if image driver is not GD */ if ( !MS_RENDERER_PLUGIN(self->format) ) { msSetError(MS_IMGERR, "Writing of %s format not implemented", "imageObj::write", self->format->driver); return MS_FAILURE; } if (file == Py_None) /* write to stdout */ retval = msSaveImage(NULL, self, NULL); else if (PyFile_Check(file)) /* a Python (C) file */ { renderer = self->format->vtable; /* FIXME? as an improvement, pass a map argument instead of the NULL (see #4216) */ retval = renderer->saveImage(self, NULL, PyFile_AsFile(file), self->format); } else /* presume a Python file-like object */ { imgbuffer = msSaveImageBuffer(self, &imgsize, self->format); if (imgsize == 0) { msSetError(MS_IMGERR, "failed to get image buffer", "write()"); return MS_FAILURE; } noerr = PyObject_CallMethod(file, "write", "s#", imgbuffer, imgsize); free(imgbuffer); if (noerr == NULL) return MS_FAILURE; else Py_DECREF(noerr); retval = MS_SUCCESS; } return retval; } /* Deprecated */ PyObject *saveToString() { int size=0; unsigned char *imgbytes; PyObject *imgstring; imgbytes = msSaveImageBuffer(self, &size, self->format); if (size == 0) { msSetError(MS_IMGERR, "failed to get image buffer", "saveToString()"); return NULL; } imgstring = PyString_FromStringAndSize((const char*) imgbytes, size); free(imgbytes); return imgstring; } } mapserver-6.4.1/mapscript/python/README0000644002461700001440000000516112261257215017522 0ustar tbonfortusers.. $Id$ Python MapScript for MapServer 5.0 README ================================================================ :Author: Howard Butler :Contact: hobu.inc@gmail.com :Author: Sean Gillies :Contact: sgillies@frii.com :Revision: $Revision: 6560 $ :Date: $Date: 2007-08-11 21:41:45 -0500 (Sat, 11 Aug 2007) $ The Python mapscript module provides users an interface to MapServer classes on any platform, and has been well tested on Python versions 2.2-2.4. Building the Mapscript Module ----------------------------- Before you begin, it's worth spending a few minutes to read the docs about Python distutils: http://www.python.org/doc/current/dist/dist.html Now that you know what distutils does, use it like :: $ python setup.py build Building C Extension Wrappers ----------------------------- If you are building the mapscript module from CVS, not from a release, the C extension wrappers will be absent and must then be generated using SWIG, the Simplified Wrapper and Interface Generator, http://www.swig.org. SWIG version 1.3.29 or higher is recommended. From the mapscript/python directory execute :: $ swig -python -shadow -o mapscript_wrap.c ../mapscript.i and then proceed to the build step explained above. If you are using Python 2.2 or 2.3, you should add a -modern option which produces a higher performance module. :: $ swig -python -shadow -modern -o mapscript_wrap.c ../mapscript.i If you have SWIG version 1.3.31 or greater, you can add in some of SWIG's optimizations to squeeze more performance out of the bindings :: $ swig -python -shadow -modern -templatereduce -fastdispatch -fvirtual -fastproxy -modernargs -castmode -dirvtable -fastinit -fastquery -noproxydel -nobuildnone -o mapscript_wrap.c ../mapscript.i Testing ------- Make the appropriate edits to tests/test.map under the mapserver directory, change directory from mapscript/python and execute :: $ cd tests/cases $ python runalltests.py -v The tests can (and should) be run before the module is installed. Installing ---------- As root or superuser :: $ python setup.py install That's it! Credits ------- Steve Lime (developer) Sean Gillies (developer) Frank Warmerdam (developer) Howard Butler (developer) Norman Vine (cygwin and distutils guru) Tim Cera (install) Michael Schultz (documentation) MapScript is now using code from gdmodule http://newcenturycomputers.net/projects/gdmodule.html which makes possible some new and cool imageObj tricks. The use this code is **greatly** appreciated and MapServer developers look forward to being able to share advances with the gdmodule developers. mapserver-6.4.1/mapscript/python/CMakeLists.txt0000644002461700001440000000433712261257215021406 0ustar tbonfortusersFIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(PythonInterp) # Python library/header finding doesn't seem to honor the python # interpreter that was found beforehand, and defaults to the system # python. We first try to find python.h and libpython.so ourselves # from the hints given by distutils and sys execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_inc; print get_python_inc(True)" OUTPUT_VARIABLE PYTHON_INC OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "import sys; print sys.prefix" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) find_path(PYTHON_INCLUDE_PATH Python.h HINTS ${PYTHON_INC} ) find_library(PYTHON_LIBRARIES NAMES python${PYTHON_VERSION_STRING} python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} python HINTS ${PYTHON_PREFIX}/lib ) #if that failed, fall back to the default cmake method of finding python dev files if(NOT PYTHON_INCLUDE_PATH OR NOT PYTHON_LIBRARIES) FIND_PACKAGE(PythonLibs) endif(NOT PYTHON_INCLUDE_PATH OR NOT PYTHON_LIBRARIES) INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/python) SWIG_ADD_MODULE(pythonmapscript python ../mapscript.i pygdioctx/pygdioctx.c) SWIG_LINK_LIBRARIES(pythonmapscript ${PYTHON_LIBRARIES} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(${SWIG_MODULE_pythonmapscript_REAL_NAME} PROPERTIES PREFIX "") set_target_properties(${SWIG_MODULE_pythonmapscript_REAL_NAME} PROPERTIES OUTPUT_NAME _mapscript) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(True)" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_pythonmapscript_REAL_NAME} LOCATION) set(mapscript_files ${LOC_MAPSCRIPT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/mapscript.py) install(FILES ${mapscript_files} DESTINATION ${PYTHON_SITE_PACKAGES}) #install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mapscript.py DESTINATION ${PYTHON_SITE_PACKAGES}) #install(TARGETS mapscript DESTINATION ${PYTHON_SITE_PACKAGES}) mapserver-6.4.1/mapscript/python/examples/0000755002461700001440000000000012261257215020455 5ustar tbonfortusersmapserver-6.4.1/mapscript/python/examples/shpdump.py0000755002461700001440000000313212261257215022511 0ustar tbonfortusers#!/usr/bin/env python """ Dump the contents of the passed in shapefile. Pass in the basename of the shapefile. This script uses the mapscript extention module. """ import mapscript import sys import os # Utility functions. def usage(): """ Display usage if program is used incorrectly. """ print "Syntax: %s base_filename" % sys.argv[0] sys.exit(2) def plural(x): """ Returns an 's' if plural. Useful in print statements to avoid something like 'point(s)'. """ if x > 1: return 's' return '' # Make sure passing in filename argument. if len(sys.argv) != 2: usage() # Make sure can access .shp file, create shapefileObj. if os.access(sys.argv[1] + ".shp", os.F_OK): sf_obj = mapscript.shapefileObj(sys.argv[1], -1) else: print "Can't access shapefile" sys.exit(2) # Create blank shape object. s_obj = mapscript.shapeObj(-1) # Loop through each shape in the shapefile. for i in range(sf_obj.numshapes): # Get the ith object. sf_obj.get(i, s_obj) print "Shape %i has %i part%s." % (i, s_obj.numlines, plural(s_obj.numlines)) print "bounds (%f, %f) (%f, %f)" % (s_obj.bounds.minx, s_obj.bounds.miny, s_obj.bounds.maxx, s_obj.bounds.maxy) # Loop through parts of each shape. for j in range(s_obj.numlines): # Get the jth part of the ith object. part = s_obj.get(j) print "Part %i has %i point%s." % (j, part.numpoints, plural(part.numpoints)) # Loop through points in each part. for k in range(part.numpoints): # Get the kth point of the jth part of the ith shape. point = part.get(k) print "%i: %f, %f" % (k, point.x, point.y) mapserver-6.4.1/mapscript/python/examples/shpinfo.py0000755002461700001440000000362012261257215022501 0ustar tbonfortusers#!/usr/bin/env python """ Extracts basic descriptive information from the shapefile. """ import mapscript import sys import os # Utility functions. def usage(): """ Display usage if program is used incorrectly. """ print "Syntax: %s base_filename" % sys.argv[0] sys.exit(2) # Make sure passing in filename argument. if len(sys.argv) != 2: usage() # Make sure can access .shp file, create shapefileObj. if os.access(sys.argv[1] + ".shp", os.F_OK): sf_obj = mapscript.shapefileObj(sys.argv[1], -1) else: print "Can't access shapefile" sys.exit(2) # Dictionary of shapefile types. types = { 1: 'point', 3: 'arc', 5: 'polygon', 8: 'multipoint' } # Print out basic information that is part of the shapefile object. print "Shapefile %s:" % sys.argv[1] print print "\ttype: %s" % types[sf_obj.type] print "\tnumber of features: %i" % sf_obj.numshapes print "\tbounds: (%f, %f) (%f, %f)" % (sf_obj.bounds.minx, sf_obj.bounds.miny, sf_obj.bounds.maxx, sf_obj.bounds.maxy) # Including a class to read DBF files. # If not found, quit because can't do anything else without the dbfreader class. try: import dbfreader except: # Can't do anymore. sys.exit(2) # Create DBF object. dbf_obj = dbfreader.DBFFile(sys.argv[1] + ".dbf") # Print out table characteristics. print "" print "\tDBF file: %s" % sys.argv[1] + ".dbf" print "\tnumber of records: %i" % dbf_obj.get_record_count() print "\tnumber of fields: %i" % len(dbf_obj.get_fields()) print "" print "\t%-20s %12s %8s %10s" % ("Name", "Type", "Length", "Decimals") print "\t-----------------------------------------------------" # Print out field characteristics. for field in dbf_obj.get_fields(): print "\t%-20s %12s %8d %10d" % (field.get_name(), field.get_type_name(), field.get_len(), field.field_places) mapserver-6.4.1/mapscript/python/examples/geocode_addresses.py0000755002461700001440000000404512261257215024477 0ustar tbonfortusers#!/usr/bin/python # Script : geocode_addresses.py # # Purpose: simple script to read a csv file, geocode the addresses # with the Geocoder API and write to a new shapefile # # $Id$ # import sys import csv import mapscript import urllib import urllib2 from lxml import etree # uses dbfpy http://pypi.python.org/pypi/dbfpy/2.2.1 from dbfpy.dbf import * # example invocation # ./reproj.py ./foo.csv address_colnum, city_colnum, stateprov_colnum ./bar.csv # check input parameters if (len(sys.argv) != 6): print sys.argv[0] + \ " " sys.exit(1) # geocoder base request URL sGeocoderUrl = "http://www.geocoder.ca/?geoit=xml&locate=" # set csv record indices sAddress = int(sys.argv[2]) sCity = int(sys.argv[3]) sStateProv = int(sys.argv[4]) # open file fCsv = open(sys.argv[1], 'r') # read csv csvIn = csv.reader(fCsv) # create output shp/shx msSFOut = mapscript.shapefileObj(sys.argv[-1], 1) # create output dbf dbfOut = Dbf(sys.argv[-1]+".dbf", new=True) # add fields dbfOut.addField( ("address", 'C', 255), ("city", 'C', 255), ("stateprov", 'C', 255), ("x", 'N', 6,2), ("y", 'N', 7,2) ) for aRow in csvIn: # concatenate request params sRequest = aRow[sAddress] + "," + aRow[sCity] + "," + aRow[sStateProv] # contatenate request params (escaped) and base URL sRequest = sGeocoderUrl + urllib.quote(sRequest) # make the HTTP request ul2Response = urllib2.urlopen(sRequest) # serialize into etree XML object etTree = etree.parse(ul2Response) sY = float(etTree.find('latt').text) sX = float(etTree.find('longt').text) # serialize mapscript pointObj and add to shapefile msPoint = mapscript.pointObj(sX, sY) msSFOut.addPoint(msPoint) # add dbf record dRec=dbfOut.newRecord() dRec['address'] = aRow[sAddress] dRec['city'] = aRow[sCity] dRec['StateProv'] = aRow[sStateProv] dRec['x'] = sX dRec['y'] = sY dRec.store() # close files fCsv.close() dbfOut.close() mapserver-6.4.1/mapscript/python/examples/project_csv.py0000755002461700001440000000221512261257215023353 0ustar tbonfortusers#!/usr/bin/python # # Script : project_csv.py # # Purpose: Simple example to read a csv file and reproject point x/y data # # $Id$ # import sys import csv import mapscript # example invocation # ./reproj.py ./foo.csv 2 3 EPSG:32619 EPSG:4326 # check input parameters if (len(sys.argv) != 6): print sys.argv[0] + \ " " sys.exit(1) else: # set x and y indices x = int(sys.argv[2]) y = int(sys.argv[3]) # set input and output projections projObjIn = mapscript.projectionObj("init="+sys.argv[4].lower()) projObjOut = mapscript.projectionObj("init="+sys.argv[5].lower()) # open file fCsv = open(sys.argv[1], 'r') # read csv csvIn = csv.reader(fCsv) # setup output csvOut = csv.writer(sys.stdout) for aRow in csvIn: # each record # set pointObj point = mapscript.pointObj(float(aRow[x]), float(aRow[y])) # project point.project(projObjIn, projObjOut) # update with reprojected coordinates aRow[x] = point.x aRow[y] = point.y csvOut.writerow(aRow) fCsv.close() mapserver-6.4.1/mapscript/python/pygdioctx/0000755002461700001440000000000012261257215020651 5ustar tbonfortusersmapserver-6.4.1/mapscript/python/pygdioctx/pygdioctx.c0000644002461700001440000001273712261257215023041 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Interface Python file-like objects with GD through IOCtx * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * The PyFileIfaceObj_IOCtx API is * * Copyright 1995 Richard Jones, Bureau of Meteorology Australia. * richard@bofh.asn.au * * Current maintainer is * Chris Gonnerman * Please direct all questions and problems to me. * ****************************************************************************** * GDMODULE LICENSE: * gdmodule - Python GD module Copyright (c) 1995 Richard Jones All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. Neither the name of the Bureau of Meteorology * Australia nor the names of its contributors may be used to endorse * or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifdef USE_GD #include "pygdioctx.h" int PyFileIfaceObj_IOCtx_GetC(gdIOCtx *ctx) { struct PyFileIfaceObj_gdIOCtx *pctx = (struct PyFileIfaceObj_gdIOCtx *)ctx; if (pctx->strObj) { Py_DECREF(pctx->strObj); pctx->strObj = NULL; } pctx->strObj = PyObject_CallMethod(pctx->fileIfaceObj, "read", "i", 1); if (!pctx->strObj || !PyString_Check(pctx->strObj)) { return EOF; } if (PyString_GET_SIZE(pctx->strObj) == 1) { return (int)(unsigned char)PyString_AS_STRING(pctx->strObj)[0]; } return EOF; } int PyFileIfaceObj_IOCtx_GetBuf(gdIOCtx *ctx, void *data, int size) { int err; char *value; struct PyFileIfaceObj_gdIOCtx *pctx = (struct PyFileIfaceObj_gdIOCtx *)ctx; if (pctx->strObj) { Py_DECREF(pctx->strObj); pctx->strObj = NULL; } pctx->strObj = PyObject_CallMethod(pctx->fileIfaceObj, "read", "i", size); if (!pctx->strObj) { return 0; } err = PyString_AsStringAndSize(pctx->strObj, &value, &size); if (err < 0) { /* this throws away the python exception since the gd library * won't pass it up properly. gdmodule should create its own * since the "file" couldn't be read properly. */ PyErr_Clear(); return 0; } memcpy(data, value, size); return size; } void PyFileIfaceObj_IOCtx_Free(gdIOCtx *ctx) { struct PyFileIfaceObj_gdIOCtx *pctx = (struct PyFileIfaceObj_gdIOCtx *)ctx; if (pctx->strObj) { Py_DECREF(pctx->strObj); pctx->strObj = NULL; } if (pctx->fileIfaceObj) { Py_DECREF(pctx->fileIfaceObj); pctx->fileIfaceObj = NULL; } /* NOTE: we leave deallocation of the ctx structure itself to outside * code for memory allocation symmetry. This function is safe to * call multiple times (gd should call it + we call it to be safe). */ } struct PyFileIfaceObj_gdIOCtx * alloc_PyFileIfaceObj_IOCtx(PyObject *fileIfaceObj) { struct PyFileIfaceObj_gdIOCtx *pctx; pctx = calloc(1, sizeof(struct PyFileIfaceObj_gdIOCtx)); if (!pctx) return NULL; pctx->ctx.getC = PyFileIfaceObj_IOCtx_GetC; pctx->ctx.getBuf = PyFileIfaceObj_IOCtx_GetBuf; pctx->ctx.gd_free = PyFileIfaceObj_IOCtx_Free; Py_INCREF(fileIfaceObj); pctx->fileIfaceObj = fileIfaceObj; return pctx; } void free_PyFileIfaceObj_IOCtx(struct PyFileIfaceObj_gdIOCtx *pctx) { if (!pctx) return; assert(pctx->ctx.gd_free != NULL); pctx->ctx.gd_free((gdIOCtxPtr)pctx); free(pctx); } /* =========================================================================== * Mapserver function createImageObjFromPyFile by Sean Gillies, * * ======================================================================== */ imageObj *createImageObjFromPyFile(PyObject *file, const char *driver) { imageObj *image=NULL; struct PyFileIfaceObj_gdIOCtx *pctx; if (file == Py_None) { msSetError(MS_IMGERR, "NULL file object", "createImageObjFromPyFile()"); return NULL; } else if (!driver) { msSetError(MS_IMGERR, "NULL or invalid driver string", "createImageObjFromPyFile()"); return NULL; } else { pctx = alloc_PyFileIfaceObj_IOCtx(file); //image = msImageLoadGDCtx((gdIOCtx *) pctx, driver); free_PyFileIfaceObj_IOCtx(pctx); return image; } } #endif mapserver-6.4.1/mapscript/python/pygdioctx/pygdioctx.h0000644002461700001440000000574212261257215023044 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Interface Python file-like objects with GD through IOCtx * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * The PyFileIfaceObj_IOCtx API is * * Copyright 1995 Richard Jones, Bureau of Meteorology Australia. * richard@bofh.asn.au * * Current maintainer is * Chris Gonnerman * Please direct all questions and problems to me. * ***************************************************************************** * GDMODULE LICENSE: * gdmodule - Python GD module Copyright (c) 1995 Richard Jones All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. Neither the name of the Bureau of Meteorology * Australia nor the names of its contributors may be used to endorse * or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifdef USE_GD #include #include #include #include #include #include #include #include #include #include "../../../mapserver.h" /* ** Code to act as a gdIOCtx wrapper for a python file object ** (read-only; write support would not be difficult to add) */ struct PyFileIfaceObj_gdIOCtx { gdIOCtx ctx; PyObject *fileIfaceObj; PyObject *strObj; }; struct PyFileIfaceObj_gdIOCtx * alloc_PyFileIfaceObj_IOCtx(PyObject *fileIfaceObj); void free_PyFileIfaceObj_IOCtx(struct PyFileIfaceObj_gdIOCtx *pctx); imageObj *createImageObjFromPyFile(PyObject *file, const char *driver); #endif mapserver-6.4.1/mapscript/python/tests/0000755002461700001440000000000012261257215020001 5ustar tbonfortusersmapserver-6.4.1/mapscript/python/tests/runalldoctests.py0000644002461700001440000000126612261257215023426 0ustar tbonfortusersimport doctest import getopt import glob import sys try: import pkg_resources pkg_resources.require('mapscript') except (ImportError, pkg_resources.DistributionNotFound): pass def run(pattern): if pattern is None: testfiles = glob.glob('*.txt') else: testfiles = glob.glob(pattern) for file in testfiles: doctest.testfile(file) if __name__ == "__main__": try: opts, args = getopt.getopt(sys.argv[1:], "t:v") except getopt.GetoptError: print "Usage: python runalldoctests.py [-t GLOB_PATTERN]" sys.exit(2) pattern = None for o, a in opts: if o == '-t': pattern = a run(pattern) mapserver-6.4.1/mapscript/python/tests/TESTING.txt0000644002461700001440000000205412261257215021660 0ustar tbonfortusers.. $Id$ Python MapScript Unit Tests ======================================== Authors: Sean Gillies, sgillies@frii.com Howard Butler, hobu@iastate.edu Running the tests ----------------- To run all of the tests, change directory to cases and execute :: $ cd cases $ python runalltests.py -v This runs all tests found in every TestCase derived class defined in any module named "cases/*test.py". The tests cannot be run properly from another path. The unit test script will insert the local build directory produced by Python distutils into the head of the Python PATH. This allows us to run the unit tests before installing the mapscript module. The unit tests use a map config file, symbolset file, fontset file, and data located in the 'tests' directory of the mapserver distribution. If you encounter any errors, please create a new issue in the MapServer bug tracker http://mapserver.gis.umn.edu/bugs/enter_bug.cgi under the SWIG-MapScript component. Copy the relevant error messages and we'll get to the bug ASAP. Thanks! mapserver-6.4.1/mapscript/python/tests/cases/0000755002461700001440000000000012261257215021077 5ustar tbonfortusersmapserver-6.4.1/mapscript/python/tests/cases/styletest.py0000644002461700001440000002104612261257215023514 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map Styles # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/styletest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase class DrawProgrammedStylesTestCase(MapTestCase): def testDrawPoints(self): """DrawProgrammedStylesTestCase.testDrawPoints: point drawing with styles works as advertised""" points = [mapscript.pointObj(-0.2, 51.6), mapscript.pointObj(0.0, 51.2), mapscript.pointObj(0.2, 51.6)] colors = [mapscript.colorObj(255,0,0), mapscript.colorObj(0,255,0), mapscript.colorObj(0,0,255)] img = self.map.prepareImage() layer = self.map.getLayerByName('POINT') #layer.draw(self.map, img) class0 = layer.getClass(0) for i in range(len(points)): style0 = class0.getStyle(0) style0.color = colors[i] #style0.color.pen = -4 assert style0.color.toHex() == colors[i].toHex() points[i].draw(self.map, layer, img, 0, "foo") img.save('test_draw_points.png') class NewStylesTestCase(MapTestCase): def testStyleConstructor(self): """a new style is properly initialized""" new_style = mapscript.styleObj() assert new_style.color.red == -1 assert new_style.color.green == -1 assert new_style.color.blue == -1 def testCloneStyle(self): """check attributes of a cloned style""" new_style = mapscript.styleObj() new_style.color.setHex('#808080') clone = new_style.clone() assert clone.thisown == 1 assert clone.color.toHex() == '#808080' def testStyleColorSettable(self): """a style can be set with a color tuple""" new_style = mapscript.styleObj() new_style.color.setRGB(1,2,3) assert new_style.color.red == 1 assert new_style.color.green == 2 assert new_style.color.blue == 3 def testStyleBinding(self): """attribute binding can be set and get""" new_style = mapscript.styleObj() assert (not new_style.getBinding(mapscript.MS_STYLE_BINDING_COLOR)) new_style.setBinding(mapscript.MS_STYLE_BINDING_COLOR,"NEW_BINDING") assert (new_style.getBinding(mapscript.MS_STYLE_BINDING_COLOR) == "NEW_BINDING") def testAppendNewStyle(self): """a new style can be appended properly""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) assert class0.numstyles == 2, class0.numstyles new_style = mapscript.styleObj() new_style.color.setRGB(0, 0, 0) new_style.symbol = 1 new_style.size = 3 index = class0.insertStyle(new_style) assert index == 2, index assert class0.numstyles == 3, class0.numstyles msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testAppendNewStyle.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testAppendNewStyleOldWay(self): """NewStylesTestCase.testAppendNewStyleOldWay: a new style can be appended properly using old method""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) assert class0.numstyles == 2, class0.numstyles new_style = mapscript.styleObj(class0) assert new_style.thisown == 1, new_style.thisown new_style.color.setRGB(0, 0, 0) new_style.symbol = 1 new_style.size = 3 msimg = self.map.draw() data = msimg.saveToString() filename = 'testAppendNewStyleOldWay.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testInsertNewStyleAtIndex0(self): """NewStylesTestCase.testInsertNewStyleAtIndex0: a new style can be inserted ahead of all others""" l_layer = self.map.getLayerByName('LINE') class0 = l_layer.getClass(0) new_style = mapscript.styleObj() new_style.color.setRGB(255, 255, 0) new_style.symbol = 1 new_style.size = 7 index = class0.insertStyle(new_style, 0) assert index == 0, index assert class0.numstyles == 2, class0.numstyles msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testInsertNewStyleAtIndex0.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testRemovePointStyle(self): """NewStylesTestCase.testRemovePointStyle: a point style can be properly removed""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) rem_style = class0.removeStyle(1) assert class0.numstyles == 1, class0.numstyles msimg = self.map.draw() filename = 'testRemovePointStyle.png' msimg.save(filename) def testModifyMultipleStyle(self): """NewStylesTestCase.testModifyMultipleStyle: multiple styles can be modified""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) style1 = class0.getStyle(1) style1.color.setRGB(255, 255, 0) msimg = self.map.draw() filename = 'testModifyMutiplePointStyle.png' msimg.save(filename) def testInsertStylePastEnd(self): """NewStylesTestCase.testInsertStylePastEnd: inserting a style past the end of the list raises the proper error""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) new_style = mapscript.styleObj() self.assertRaises(mapscript.MapServerChildError, class0.insertStyle, new_style, 6) def testInsertNULLStyle(self): """attempt to insert a NULL style should raise error""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) self.assertRaises(mapscript.MapServerChildError, class0.insertStyle, None) class BrushCachingTestCase(MapTestCase): def testDrawMapWithSecondPolygon(self): """draw a blue polygon and a red polygon""" p = self.map.getLayerByName('POLYGON') ip = mapscript.layerObj(self.map) ip.type = mapscript.MS_LAYER_POLYGON ip.status = mapscript.MS_DEFAULT c0 = mapscript.classObj(ip) # turn off first polygon layer's color p.getClass(0).getStyle(0).color.setRGB(-1,-1,-1) # copy this style to inline polygon layer, then change outlinecolor c0.insertStyle(p.getClass(0).getStyle(0)) st0 = c0.getStyle(0) st0.outlinecolor.setRGB(255, 0, 0) # pull out the first feature from polygon layer, shift it # and use this as an inline feature in new layer p.open() s0 = p.getFeature(0) p.close() r0 = s0.bounds r1 = mapscript.rectObj(r0.minx-0.1, r0.miny-0.1, r0.maxx-0.1, r0.maxy-0.1) s1 = r1.toPolygon() ip.addFeature(s1) img = self.map.draw() img.save('test_drawmapw2ndpolygon.png') if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/recttest.py0000644002461700001440000001330012261257215023303 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of rectObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/recttest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapPrimitivesTestCase # =========================================================================== # Test begins now class RectObjTestCase(MapPrimitivesTestCase): def testRectObjConstructorNoArgs(self): """a rect can be initialized with no args""" r = mapscript.rectObj() self.assertAlmostEqual(r.minx, -1.0) self.assertAlmostEqual(r.miny, -1.0) self.assertAlmostEqual(r.maxx, -1.0) self.assertAlmostEqual(r.maxy, -1.0) def testRectObjConstructorArgs(self): """a rect can be initialized with arguments""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) self.assertAlmostEqual(r.minx, -1.0) self.assertAlmostEqual(r.miny, -2.0) self.assertAlmostEqual(r.maxx, 3.0) self.assertAlmostEqual(r.maxy, 4.0) def testRectObjConstructorBadXCoords(self): """an invalid extent raises proper error (x direction)""" self.assertRaises(mapscript.MapServerError, mapscript.rectObj, 1.0, -2.0, -3.0, 4.0) def testRectObjConstructorBadYCoords(self): """an invalid extent raises proper error (y direction)""" self.assertRaises(mapscript.MapServerError, mapscript.rectObj, -1.0, 2.0, 3.0, -2.0) def testRectObjToPolygon(self): """a rect can be converted into a MS_POLYGON shape""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) s = r.toPolygon() assert s.numlines == 1, s.numlines line = self.getLineFromShape(s, 0) assert line.numpoints == 5, line.numpoints point = self.getPointFromLine(line, 0) self.assertAlmostEqual(point.x, -1.0) self.assertAlmostEqual(point.y, -2.0) def testExceptionMessage(self): """test formatted error message""" try: r = mapscript.rectObj(1.0, -2.0, -3.0, 4.0) except mapscript.MapServerError, msg: assert str(msg) == "rectObj(): Invalid rectangle. { 'minx': 1.000000 , 'miny': -2.000000 , 'maxx': -3.000000 , 'maxy': 4.000000 }", msg def testRect__str__(self): """__str__ returns properly formatted string""" r = mapscript.rectObj(-1.0, -2.0, 3.0001, 4.0) r_str = str(r) assert r_str == "{ 'minx': -1 , 'miny': -2 , 'maxx': 3.0001 , 'maxy': 4 }", r_str r2 = eval(r_str) self.assertAlmostEqual(r2['minx'], r.minx) self.assertAlmostEqual(r2['miny'], r.miny) self.assertAlmostEqual(r2['maxx'], r.maxx) self.assertAlmostEqual(r2['maxy'], r.maxy) def testRectToString(self): """return properly formatted string""" r = mapscript.rectObj(-1.0, -2.0, 3.0001, 4.0) r_str = r.toString() assert r_str == "{ 'minx': -1 , 'miny': -2 , 'maxx': 3.0001 , 'maxy': 4 }", r_str def testRectContainsPoint(self): """point is contained (spatially) in rectangle""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) p = mapscript.pointObj(0.0, 0.0) assert p in r, (p.x, p.y, r) def testRectContainsPointNot(self): """point is not contained (spatially) in rectangle""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) p = mapscript.pointObj(3.00001, 0.0) assert p not in r, (p.x, p.y, r) class ImageRectObjTestCase(MapPrimitivesTestCase): def testRectObjConstructorArgs(self): """create a rect in image units""" r = mapscript.rectObj(-1.0, 2.0, 3.0, 0.0, mapscript.MS_TRUE) self.assertAlmostEqual(r.minx, -1.0) self.assertAlmostEqual(r.miny, 2.0) self.assertAlmostEqual(r.maxx, 3.0) self.assertAlmostEqual(r.maxy, 0.0) def testRectObjConstructorBadYCoords(self): """in image units miny should be greater than maxy""" self.assertRaises(mapscript.MapServerError, mapscript.rectObj, -1.0, 0.0, 3.0, 2.0, mapscript.MS_TRUE) # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/pointtest.py0000644002461700001440000000771112261257215023510 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Point # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/pointtest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapscriptTestCase class PointObjTestCase(MapscriptTestCase): def testPointObjConstructorNoArgs(self): """point can be created with no arguments""" p = mapscript.pointObj() self.assertAlmostEqual(p.x, 0.0) self.assertAlmostEqual(p.y, 0.0) def testPointObjConstructorArgs(self): """point can be created with arguments""" p = mapscript.pointObj(1.0, 1.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 1.0) def testSetXY(self): """point can have its x and y reset""" p = mapscript.pointObj() p.setXY(1.0, 1.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 1.0) if hasattr(p, 'm'): self.assertAlmostEqual(p.m, -2e38) def testSetXYM(self): """point can have its x and y reset (with m value)""" p = mapscript.pointObj() p.setXY(1.0, 1.0, 1.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 1.0) if hasattr(p, 'm'): self.assertAlmostEqual(p.m, 1.0) def testSetXYZ(self): """point can have its x, y, z reset (with m value)""" p = mapscript.pointObj() p.setXYZ(1.0, 2.0, 3.0, 4.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 2.0) if hasattr(p, 'z') and hasattr(p, 'm'): self.assertAlmostEqual(p.z, 3.0) self.assertAlmostEqual(p.m, 4.0) def testPoint__str__(self): """return properly formatted string""" p = mapscript.pointObj(1.0, 1.0) if hasattr(p, 'z'): p_str = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g }" % (p.x, p.y, p.z) else: p_str = "{ 'x': %.16g, 'y': %.16g }" % (p.x, p.y) assert str(p) == p_str, str(p) def testPointToString(self): """return properly formatted string in toString()""" p = mapscript.pointObj(1.0, 1.0, 0.002, 15.0) if hasattr(p, 'z') and hasattr(p, 'm'): p_str = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g, 'm': %.16g }" \ % (p.x, p.y, p.z, p.m) else: p_str = "{ 'x': %.16g, 'y': %.16g }" % (p.x, p.y) assert p.toString() == p_str, p.toString() if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/outputformattest.py0000644002461700001440000001234712261257215025131 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of outputFormatObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/outputformattest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapTestCase # =========================================================================== # Test begins now class OutputFormatTestCase(unittest.TestCase): """http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511""" def testOutputFormatConstructor(self): new_format = mapscript.outputFormatObj('GDAL/GTiff', 'gtiff') assert new_format.refcount == 1, new_format.refcount assert new_format.name == 'gtiff' assert new_format.mimetype == 'image/tiff' class MapOutputFormatTestCase(MapTestCase): def testAppendNewOutputFormat(self): """test that a new output format can be created on-the-fly""" num = self.map.numoutputformats new_format = mapscript.outputFormatObj('GDAL/GTiff', 'gtiffx') assert new_format.refcount == 1, new_format.refcount self.map.appendOutputFormat(new_format) assert self.map.numoutputformats == num + 1 assert new_format.refcount == 2, new_format.refcount self.map.selectOutputFormat('gtiffx') self.map.save('testAppendNewOutputFormat.map') self.map.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON imgobj = self.map.draw() filename = 'testAppendNewOutputFormat.tif' imgobj.save(filename) def testRemoveOutputFormat(self): """testRemoveOutputFormat may fail depending on GD options""" num = self.map.numoutputformats new_format = mapscript.outputFormatObj('GDAL/GTiff', 'gtiffx') self.map.appendOutputFormat(new_format) assert self.map.numoutputformats == num + 1 assert new_format.refcount == 2, new_format.refcount assert self.map.removeOutputFormat('gtiffx') == mapscript.MS_SUCCESS assert new_format.refcount == 1, new_format.refcount assert self.map.numoutputformats == num self.assertRaises(mapscript.MapServerError, self.map.selectOutputFormat, 'gtiffx') self.map.selectOutputFormat('GTiff') assert self.map.outputformat.mimetype == 'image/tiff' def testBuiltInPNG24Format(self): """test built in PNG RGB format""" self.map.selectOutputFormat('PNG24') assert self.map.outputformat.mimetype == 'image/png; mode=24bit' self.map.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON img = self.map.draw() assert img.format.mimetype == 'image/png; mode=24bit' filename = 'testBuiltInPNG24Format.png' img.save(filename) def testBuiltInJPEGFormat(self): """test built in JPEG format""" self.map.selectOutputFormat('JPEG') assert self.map.outputformat.mimetype == 'image/jpeg' self.map.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON img = self.map.draw() assert img.format.mimetype == 'image/jpeg' filename = 'testBuiltInJPEGFormat.jpg' img.save(filename) def testSelectBuiltInJPEGFormat(self): """test selection of built-in JPEG format""" self.map.selectOutputFormat('JPEG') assert self.map.outputformat.mimetype == 'image/jpeg' class UnsupportedFormatTestCase(unittest.TestCase): """I (Sean) don't ever configure for PDF, so this is the unsupported format.""" def testCreateUnsupported(self): self.assertRaises(mapscript.MapServerError, mapscript.outputFormatObj, 'PDF') # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/symbolsettest.py0000644002461700001440000001451412261257215024377 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of SymbolSet # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/symbolsettest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase, TESTMAPFILE, XMARKS_IMAGE SYMBOLSET = '../../../../tests/symbols.txt' # =========================================================================== # Test begins now class SymbolSetTestCase(unittest.TestCase): def testConstructorNoArgs(self): """new instance of symbolSetObj should have one symbol""" symbolset = mapscript.symbolSetObj() num = symbolset.numsymbols assert num == 1, num def testConstructorFile(self): """new instance of symbolSetObj from symbols.txt""" symbolset = mapscript.symbolSetObj(SYMBOLSET) num = symbolset.numsymbols assert num == 4, num def testAddSymbolToNewSymbolSet(self): """add two new symbols to a SymbolSet""" symbolset = mapscript.symbolSetObj(SYMBOLSET) symbola = mapscript.symbolObj('testa') symbolb = mapscript.symbolObj('testb') symbolset.appendSymbol(symbola) symbolset.appendSymbol(symbolb) num = symbolset.numsymbols assert num == 6, num names = [None, 'circle', 'xmarks-png', 'home-png', 'testa', 'testb'] for i in range(symbolset.numsymbols): symbol = symbolset.getSymbol(i) assert symbol.name == names[i], symbol.name def testRemoveSymbolFromNewSymbolSet(self): """after removing a symbol, expect numsymbols -= 1""" symbolset = mapscript.symbolSetObj(SYMBOLSET) symbolset.removeSymbol(1) num = symbolset.numsymbols assert num == 3, num def testSaveNewSymbolSet(self): """save a new SymbolSet to disk""" symbolset = mapscript.symbolSetObj(SYMBOLSET) symbola = mapscript.symbolObj('testa') symbolb = mapscript.symbolObj('testb') symbolset.appendSymbol(symbola) symbolset.appendSymbol(symbolb) assert symbolset.save('new_symbols.txt') == mapscript.MS_SUCCESS def testError(self): symbolset = mapscript.symbolSetObj(SYMBOLSET) symbola = mapscript.symbolObj('testa') symbolb = mapscript.symbolObj('testb') symbolset.appendSymbol(symbola) symbolset.appendSymbol(symbolb) self.assertRaises(mapscript.MapServerError, symbolset.save, '/bogus/new_symbols.txt') class MapSymbolSetTestCase(MapTestCase): def testGetNumSymbols(self): """expect getNumSymbols == 2 from test fixture test.map""" num = self.map.getNumSymbols() assert num == 4, num def testSymbolSetNumsymbols(self): """expect numsymbols == 2 from test fixture test.map""" num = self.map.symbolset.numsymbols assert num == 4, num def testSymbolSetSymbolNames(self): """test names of symbols in test fixture's symbolset""" set = self.map.symbolset names = [None, 'circle', 'xmarks-png', 'home-png'] for i in range(set.numsymbols): symbol = set.getSymbol(i) assert symbol.name == names[i], symbol.name def testSymbolIndex(self): """expect index of 'circle' symbol to be 1 in test fixture symbolset""" i = self.map.symbolset.index('circle') assert i == 1, i def testBug1962(self): """resetting imagepath doesn't cause segfault""" layer = self.map.getLayerByName('POINT') style0 = layer.getClass(0).getStyle(0) sym0 = style0.symbol sym1 = self.map.symbolset.getSymbol(sym0) sym2 = mapscript.symbolObj('xxx') sym1.setImagepath(XMARKS_IMAGE) self.assertRaises(IOError, sym1.setImagepath, '/bogus/new_symbols.txt') msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.getBytes() filename = 'testBug1962.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testDrawNewSymbol(self): """draw using a new symbol added to the fixture""" symbol = mapscript.symbolObj('xmarks', XMARKS_IMAGE) symbol_index = self.map.symbolset.appendSymbol(symbol) assert symbol_index == 4, symbol_index num = self.map.symbolset.numsymbols assert num == 5, num inline_layer = self.map.getLayerByName('INLINE') s = inline_layer.getClass(0).getStyle(0) s.symbol = symbol_index #s.size = 24 msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testDrawNewSymbol.png' fh = open(filename, 'wb') fh.write(data) fh.close() # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/runalltests.py0000644002461700001440000000442712261257215024040 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: Comprehensive xUnit style Python mapscript test runner # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this script from mapserver/mapscript/python/tests/cases # # $ cd tests/cases # $ python runalltests.py # # It runs all tests found in Python modules ending with "test.py" in the # tests/cases directory. # =========================================================================== import getopt import os import sys import unittest verbosity = 1 try: opts, args = getopt.getopt(sys.argv[1:], 'v') if opts[0][0] == '-v': verbosity = verbosity + 1 except: pass runner = unittest.TextTestRunner(verbosity=verbosity) suite = unittest.TestSuite() load = unittest.defaultTestLoader.loadTestsFromModule tests = os.listdir(os.curdir) tests = [n[:-3] for n in tests if n.endswith('test.py')] for test in tests: m = __import__(test) suite.addTest(load(m)) # --------------------------------------------------------------------------- # Run if __name__ == '__main__': runner.run(suite) mapserver-6.4.1/mapscript/python/tests/cases/layertest.py0000644002461700001440000004065412261257215023476 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Layer # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/layertest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapTestCase # Base class class MapLayerTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayer(1) # =========================================================================== # Test begins now class AlphaTransparencyTestCase(unittest.TestCase): def testMSGDALPHA(self): """test to make sure that no one has hidden ALPHA""" assert mapscript.MS_GD_ALPHA == 1000 class LayerConstructorTestCase(MapLayerTestCase): def testLayerConstructorNoArg(self): """test layer constructor with no argument""" layer = mapscript.layerObj() t = type(layer) assert str(t) == "", t assert layer.thisown == 1 assert layer.index == -1 assert layer.map == None, layer.map def testLayerConstructorMapArg(self): """test layer constructor with map argument""" layer = mapscript.layerObj(self.map) t = type(layer) assert str(t) == "", t assert layer.thisown == 1 assert str(layer) == str(self.map.getLayer(self.map.numlayers-1)) assert layer.map != None, layer.map class LayerCloningTestCase(MapLayerTestCase): def testLayerCloning(self): """check attributes of a cloned layer""" clone = self.layer.clone() assert clone.thisown == 1 assert str(clone) != str(self.layer) assert clone.name == self.layer.name assert clone.numclasses == self.layer.numclasses assert clone.map == None, clone.map assert clone.data == self.layer.data class LayerExtentTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayerByName('POLYGON') def testPolygonExtent(self): """retrieve the extent of a polygon layer""" e = mapscript.rectObj() self.assertRectsEqual(e, self.layer.extent) def testPolygonGetExtent(self): """retrieve the extent of a polygon layer""" e = mapscript.rectObj(-0.25, 51.227222, 0.25, 51.727222) self.assertRectsEqual(e, self.layer.getExtent()) def testGetPresetExtent(self): """test layer.setExtent() and layer.getExtent() to return preset instead of calculating extents""" r = mapscript.rectObj(1.0, 1.0, 3.0, 3.0) self.layer.setExtent(r.minx, r.miny, r.maxx, r.maxy) rect = self.layer.extent assert r.minx == rect.minx, rect assert r.miny == rect.miny, rect.miny assert r.maxx == rect.maxx, rect.maxx assert r.maxy == rect.maxy, rect.maxy def testResetLayerExtent(self): """test resetting a layer's extent""" layer = self.map.getLayerByName('POLYGON') layer.setExtent() self.assertRectsEqual(layer.extent, mapscript.rectObj()) def testDirectExtentAccess(self): """direct access to a layer's extent works properly""" pt_layer = self.map.getLayerByName('POINT') rect = pt_layer.extent assert str(pt_layer.extent) == str(rect), (pt_layer.extent, rect) e = mapscript.rectObj(-0.5, 51.0, 0.5, 52.0) self.assertRectsEqual(e, rect) class LayerRasterProcessingTestCase(MapLayerTestCase): def testSetProcessing(self): """setting a layer's processing directive works""" self.layer.setProcessing('directive0=foo') assert self.layer.numprocessing == 1, self.layer.numprocessing self.layer.setProcessing('directive1=bar') assert self.layer.numprocessing == 2, self.layer.numprocessing directives = [self.layer.getProcessing(i) \ for i in range(self.layer.numprocessing)] assert directives == ['directive0=foo', 'directive1=bar'] def testClearProcessing(self): """clearing a self.layer's processing directive works""" self.layer.setProcessing('directive0=foo') assert self.layer.numprocessing == 1, self.layer.numprocessing self.layer.setProcessing('directive1=bar') assert self.layer.numprocessing == 2, self.layer.numprocessing assert self.layer.clearProcessing() == mapscript.MS_SUCCESS class RemoveClassTestCase(MapLayerTestCase): def testRemoveClass1NumClasses(self): """RemoveClassTestCase.testRemoveClass1NumClasses: removing the layer's first class by index leaves one class left""" c = self.layer.removeClass(0) assert c.thisown == 1 assert self.layer.numclasses == 1 def testRemoveClass1ClassName(self): """RemoveClassTestCase.testRemoveClass1ClassName: confirm removing the layer's first class reverts the name of the second class""" c2name = self.layer.getClass(1).name c = self.layer.removeClass(0) assert self.layer.getClass(0).name == c2name def testRemoveClass2NumClasses(self): """RemoveClassTestCase.testRemoveClass2NumClasses: removing the layer's second class by index leaves one class left""" c = self.layer.removeClass(1) assert self.layer.numclasses == 1 def testRemoveClass2ClassName(self): """RemoveClassTestCase.testRemoveClass2ClassName: confirm removing the layer's second class reverts the name of the first class""" c1name = self.layer.getClass(0).name c = self.layer.removeClass(1) assert self.layer.getClass(0).name == c1name class InsertClassTestCase(MapLayerTestCase): def testLayerInsertClass(self): """insert class at default index""" n = self.layer.numclasses new_class = mapscript.classObj() new_class.name = 'foo' new_index = self.layer.insertClass(new_class) assert new_index == n assert self.layer.numclasses == n + 1 c = self.layer.getClass(new_index) assert c.thisown == 1 assert c.name == new_class.name def testLayerInsertClassAtZero(self): """insert class at index 0""" n = self.layer.numclasses new_class = mapscript.classObj() new_class.name = 'foo' new_index = self.layer.insertClass(new_class, 0) assert new_index == 0 assert self.layer.numclasses == n + 1 c = self.layer.getClass(new_index) assert c.thisown == 1 assert c.name == new_class.name def testInsertNULLClass(self): """inserting NULL class should raise an error""" self.assertRaises(mapscript.MapServerChildError, self.layer.insertClass, None) class LayerTestCase(MapTestCase): def testLayerConstructorOwnership(self): """LayerTestCase.testLayerConstructorOwnership: newly constructed layer has proper ownership""" layer = mapscript.layerObj(self.map) assert layer.thisown == 1 def testGetLayerOrder(self): """LayerTestCase.testGetLayerOrder: get layer drawing order""" order = self.map.getLayerOrder() assert order == tuple(range(7)), order def testSetLayerOrder(self): """LayerTestCase.testSetLayerOrder: set layer drawing order""" ord = (1, 0, 2, 3, 4, 5, 6) self.map.setLayerOrder(ord) order = self.map.getLayerOrder() assert order == ord, order # Layer removal tests class RemoveLayerTestCase(MapTestCase): def testRemoveLayer1NumLayers(self): """removing the first layer by index from the mapfile leaves three""" self.map.removeLayer(0) assert self.map.numlayers == 6 def testRemoveLayer1LayerName(self): """removing first layer reverts it to the second layer's name""" l2name = self.map.getLayer(1).name self.map.removeLayer(0) assert self.map.getLayer(0).name == l2name def testRemoveLayer2NumLayers(self): """removing second layer by index from mapfile leaves three layers""" self.map.removeLayer(1) assert self.map.numlayers == 6 def testRemoveLayer2LayerName(self): """removing of the second layer reverts it to the first layer's name""" l1name = self.map.getLayer(0).name self.map.removeLayer(1) assert self.map.getLayer(0).name == l1name class ExpressionTestCase(MapLayerTestCase): def testClearExpression(self): """layer expression can be properly cleared""" self.layer.setFilter('') fs = self.layer.getFilterString() assert fs == None, fs def testSetStringExpression(self): """layer expression can be set to string""" self.layer.setFilter('foo') fs = self.layer.getFilterString() self.layer.filteritem = 'fid' assert fs == '"foo"', fs self.map.draw() def testSetQuotedStringExpression(self): """layer expression string can be quoted""" self.layer.setFilter('"foo"') fs = self.layer.getFilterString() self.layer.filteritem = 'fid' assert fs == '"foo"', fs self.map.draw() def testSetRegularExpression(self): """layer expression can be regular expression""" self.layer.setFilter('/foo/') self.layer.filteritem = 'fid' fs = self.layer.getFilterString() assert fs == '/foo/', fs self.map.draw() def testSetLogicalExpression(self): """layer expression can be logical expression""" self.layer.setFilter('([fid] >= 2)') fs = self.layer.getFilterString() assert fs == '([fid] >= 2)', fs self.map.draw() def testSetCompoundLogicalExpression(self): """layer expression can be a compound logical expression""" #filter = '( ([fid] >= 2) AND (\'[fname]\' == \'A Polygon\' ))' flt = """( ([fid] >= 2) AND ("[fname]" == 'A Polygon' ))""" excode = self.layer.setFilter(flt) assert excode == mapscript.MS_SUCCESS, excode fs = self.layer.getFilterString() assert fs == flt, fs self.map.draw() class LayerQueryTestCase(MapLayerTestCase): def setUp(self): MapLayerTestCase.setUp(self) self.layer = self.map.getLayerByName('POINT') self.layer.template = 'foo' class SpatialLayerQueryTestCase(LayerQueryTestCase): def testRectQuery(self): qrect = mapscript.rectObj(-10.0, 45.0, 10.0, 55.0) self.layer.queryByRect(self.map, qrect) assert self.layer.getNumResults() == 1 def testShapeQuery(self): qrect = mapscript.rectObj(-10.0, 45.0, 10.0, 55.0) qshape = qrect.toPolygon() self.layer.queryByShape(self.map, qshape) assert self.layer.getNumResults() == 1 def testPointQuery(self): qpoint = mapscript.pointObj(0.0, 51.5) self.layer.queryByPoint(self.map, qpoint, mapscript.MS_MULTIPLE, 2.0) assert self.layer.getNumResults() == 1 def testRectQueryNoResults(self): qrect = mapscript.rectObj(-101.0, 0.0, -100.0, 1.0) self.layer.queryByRect(self.map, qrect) assert self.layer.getNumResults() == 0 def testShapeQueryNoResults(self): qrect = mapscript.rectObj(-101.0, 0.0, -100.0, 1.0) qshape = qrect.toPolygon() self.layer.queryByShape(self.map, qshape) assert self.layer.getNumResults() == 0 def testPointQueryNoResults(self): qpoint = mapscript.pointObj(-100.0, 51.5) self.layer.queryByPoint(self.map, qpoint, mapscript.MS_MULTIPLE, 2.0) assert self.layer.getNumResults() == 0 class AttributeLayerQueryTestCase(LayerQueryTestCase): def testAttributeQuery(self): self.layer.queryByAttributes(self.map, "FNAME", '"A Point"', mapscript.MS_MULTIPLE) assert self.layer.getNumResults() == 1 def testLogicalAttributeQuery(self): self.layer.queryByAttributes(self.map, None, '("[FNAME]" == "A Point")', mapscript.MS_MULTIPLE) assert self.layer.getNumResults() == 1 def testAttributeQueryNoResults(self): self.layer.queryByAttributes(self.map, "FNAME", '"Bogus Point"', mapscript.MS_MULTIPLE) assert self.layer.getNumResults() == 0 class LayerVisibilityTestCase(MapLayerTestCase): def setUp(self): MapLayerTestCase.setUp(self) self.layer.minscaledenom = 1000 self.layer.maxscaledenom = 2000 self.layer.status = mapscript.MS_ON self.map.zoomScale(1500, mapscript.pointObj(100,100), 200, 200, self.map.extent, None) def testInitialVisibility(self): """expect visibility""" assert self.layer.isVisible() == mapscript.MS_TRUE def testStatusOffVisibility(self): """expect false visibility after switching status off""" self.layer.status = mapscript.MS_OFF assert self.layer.isVisible() == mapscript.MS_FALSE def testZoomOutVisibility(self): """expect false visibility after zooming out beyond maximum""" self.map.zoomScale(2500, mapscript.pointObj(100,100), 200, 200, self.map.extent, None) assert self.layer.isVisible() == mapscript.MS_FALSE from random import random class InlineLayerTestCase(unittest.TestCase): def setUp(self): # Inline feature layer self.ilayer = mapscript.layerObj() self.ilayer.type = mapscript.MS_LAYER_POLYGON self.ilayer.status = mapscript.MS_DEFAULT self.ilayer.connectiontype = mapscript.MS_INLINE cs = 'f7fcfd,e5f5f9,ccece6,99d8c9,66c2a4,41ae76,238b45,006d2c,00441b' colors = ['#' + h for h in cs.split(',')] #print colors for i in range(9): # Make a class for feature ci = self.ilayer.insertClass(mapscript.classObj()) co = self.ilayer.getClass(ci) si = co.insertStyle(mapscript.styleObj()) so = co.getStyle(si) so.color.setHex(colors[i]) co.label.color.setHex('#000000') co.label.outlinecolor.setHex('#FFFFFF') co.label.type = mapscript.MS_BITMAP co.label.size = mapscript.MS_SMALL # The shape to add is randomly generated xc = 4.0*(random() - 0.5) yc = 4.0*(random() - 0.5) r = mapscript.rectObj(xc-0.25, yc-0.25, xc+0.25, yc+0.25) s = r.toPolygon() # Classify s.classindex = i s.text = "F%d" % (i) # Add to inline feature layer self.ilayer.addFeature(s) def testExternalClassification(self): mo = mapscript.mapObj() mo.setSize(400, 400) mo.setExtent(-2.5, -2.5, 2.5, 2.5) mo.selectOutputFormat('image/png') mo.insertLayer(self.ilayer) im = mo.draw() im.save('testExternalClassification.png') # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/fonttest.py0000644002461700001440000000647012261257215023326 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of hashTableObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/hashtest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, TESTMAPFILE, TESTS_PATH class FontTestCase(unittest.TestCase): def testSettingFonts(self): mo = mapscript.mapObj() assert mo.fontset.numfonts == 0 mo.fontset.fonts.set('Vera', os.path.join(TESTS_PATH, 'vera', 'Vera.ttf')) # NB: this does *not* increment the fonset.numfonts -- new bug mo.setSize(300, 300) mo.setExtent(-1.0, -1.0, 1.0, 1.0) lo = mapscript.layerObj() lo.type = mapscript.MS_LAYER_POINT lo.connectiontype = mapscript.MS_INLINE lo.status = mapscript.MS_DEFAULT co = mapscript.classObj() co.label.type = mapscript.MS_TRUETYPE co.label.font = 'Vera' co.label.size = 10 co.label.color.setHex('#000000') so = mapscript.styleObj() so.symbol = 0 so.color.setHex('#000000') co.insertStyle(so) lo.insertClass(co) li = mo.insertLayer(lo) lo = mo.getLayer(li) point = mapscript.pointObj(0,0) line = mapscript.lineObj() line.add(point) shape = mapscript.shapeObj(lo.type) shape.add(line) shape.setBounds() shape.text = 'Foo' shape.classindex = 0 lo.addFeature(shape) im = mo.draw() #im = mo.prepareImage() #shape.draw(mo, lo, im) im.save('testSettingFonts.png') # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/owstest.py0000644002461700001440000001103412261257215023160 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of OWS Requests # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/owstest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapTestCase # =========================================================================== # Test begins now class OWSRequestTestCase(MapTestCase): def testInit(self): """OWSRequestTestCase.testInit: OWS initializer works right""" request = mapscript.OWSRequest() request.setParameter("BBOX", "-0.3,51.2,0.3,51.8") assert request.NumParams == 1 assert request.getName(0) == "BBOX" assert request.getValue(0) == "-0.3,51.2,0.3,51.8" def testGetParameter(self): """OWSRequestTestCase.testGetParameter: OWS can get request parameters by index""" request = mapscript.OWSRequest() request.setParameter('foo', 'bar') assert request.getValue(0) == 'bar' def testGetParameterByName(self): """OWSRequestTestCase.testGetParameterByName: OWS can get request parameters by name""" request = mapscript.OWSRequest() request.setParameter('foo', 'bar') assert request.getValueByName('Foo') == 'bar' def testResetParam(self): """OWSRequestTestCase.testResetParam: OWS can reset parameters by name""" request = mapscript.OWSRequest() request.setParameter('foo', 'bar') assert request.NumParams == 1 request.setParameter('Foo', 'bra') assert request.NumParams == 1 assert request.getValue(0) == 'bra' def testLoadWMSRequest(self): """OWSRequestTestCase.testLoadWMSRequest: OWS can load a WMS request""" request = mapscript.OWSRequest() request.setParameter("REQUEST", "GetMap") request.setParameter("VERSION", "1.1.0") request.setParameter("FORMAT", "image/png") request.setParameter("LAYERS", "POINT") request.setParameter("BBOX", "-0.30,51.20,0.30,51.80") request.setParameter("SRS", "EPSG:4326") request.setParameter("HEIGHT", "60") request.setParameter("WIDTH", "60") request.setParameter("STYLES", "") for i in range(self.map.numlayers): self.map.getLayer(i).status = mapscript.MS_ON status = self.map.loadOWSParameters(request) assert status == mapscript.MS_SUCCESS, status self.assertEqual(self.map.height, 60) self.assertEqual(self.map.width, 60) self.assertEqual(self.map.getProjection(), "+init=epsg:4326") # MapServer extents are from middle of the pixel self.assertAlmostEqual(self.map.extent.minx, -0.295) self.assertAlmostEqual(self.map.extent.miny, 51.205) self.assertAlmostEqual(self.map.extent.maxx, 0.295) self.assertAlmostEqual(self.map.extent.maxy, 51.795) img = self.map.draw() img.save("test_load_ows_request.png") # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/resultcachetest.py0000644002461700001440000001350412261257215024656 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of ResultCache # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/resultcachetest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapTestCase, MapPrimitivesTestCase # Base class class LayerQueryTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayer(1) self.layer.template = 'some day i will fix this!' def pointquery(self): p = mapscript.pointObj(0.0, 51.5) self.layer.queryByPoint(self.map, p, mapscript.MS_MULTIPLE, -1) return self.layer.getResults() def indexquery(self): self.layer.queryByIndex(self.map, -1, 0, mapscript.MS_TRUE) return self.layer.getResults() # =========================================================================== # Test begins now class ResultCacheTestCase(LayerQueryTestCase): def testNoDirectAccess(self): """denying direct access to layer's resultcache""" self.assertRaises(AttributeError, getattr, self.layer, 'resultcache') def testNullResultCache(self): """before a query layer's resultcache should be NULL""" results = self.layer.getResults() assert results == None class PointQueryResultsTestCase(LayerQueryTestCase): def testCacheAfterQuery(self): """simple point query returns one result""" results = self.pointquery() assert results.numresults == 1 def testCacheAfterFailedQuery(self): """point query with no results returns NULL""" p = mapscript.pointObj(0.0, 0.0) self.layer.queryByPoint(self.map, p, mapscript.MS_MULTIPLE, -1) results = self.layer.getResults() assert results == None def testDeletionOfResults(self): """deleting results should not harm the layer""" results = self.pointquery() assert results.thisown == 0 del results results = self.layer.getResults() assert results.numresults == 1 def testQueryResultBounds(self): """result bounds should equal layer bounds""" results = self.pointquery() e = self.layer.getExtent() self.assertRectsEqual(results.bounds, e) def testQueryResultMembers(self): """get the single result member""" results = self.pointquery() self.layer.open() res = results.getResult(0) feature = self.layer.getFeature(res.shapeindex, res.tileindex) self.layer.close() self.assertRectsEqual(results.bounds, feature.bounds) assert feature.getValue(1) == 'A Polygon' def testQueryResultsListComp(self): """get all results using list comprehension""" results = self.pointquery() result_list = [results.getResult(i) for i in range(results.numresults)] assert len(result_list) == 1 assert result_list[0].shapeindex == 0 def testQueryByIndex(self): """pop a result into the result set""" self.layer.queryByIndex(self.map, -1, 0, mapscript.MS_FALSE) results = self.layer.getResults() assert results.numresults == 1 self.layer.queryByIndex(self.map, -1, 0, mapscript.MS_TRUE) results = self.layer.getResults() assert results.numresults == 2 class DumpAndLoadTestCase(LayerQueryTestCase): def testSaveAndLoadQuery(self): """test saving query to a file""" results = self.pointquery() self.map.saveQuery('test.qry') self.map.freeQuery() results = self.layer.getResults() assert results == None self.map.loadQuery('test.qry') results = self.layer.getResults() assert results is not None class LayerOffQueryTestCase(LayerQueryTestCase): def testPointQueryOffLayer(self): """simple point query returns one result, even if layer is off""" self.layer.status = mapscript.MS_OFF results = self.pointquery() assert results.numresults == 1 def testIndexQueryOffLayer(self): """simple index query returns one result, even if layer is off""" self.layer.status = mapscript.MS_OFF results = self.indexquery() assert results.numresults == 1 # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/shapetest.py0000644002461700001440000001302412261257215023451 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Shape # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/shapetest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase from testing import MapPrimitivesTestCase, ShapeObjTestCase from testing import MapscriptTestCase class ShapePointTestCase(ShapeObjTestCase): """Test point type shapeObj in stand-alone mode""" def setUp(self): """The test fixture is a shape of one point""" self.points = (mapscript.pointObj(0.0, 1.0),) self.lines = (mapscript.lineObj(),) self.addPointToLine(self.lines[0], self.points[0]) self.shape = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) self.addLineToShape(self.shape, self.lines[0]) def testCreateShape(self): """the number of lines is correct""" assert self.shape.numlines == 1 def testShapeClone(self): """test shape can be copied""" s = self.shape.clone() self.assertShapesEqual(self.shape, s) class InlineFeatureTestCase(MapTestCase): """tests for issue http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=562""" def testAddPointFeature(self): """adding a point to an inline feature works correctly""" inline_layer = self.map.getLayerByName('INLINE') assert inline_layer.connectiontype == mapscript.MS_INLINE p = mapscript.pointObj(0.2, 51.5) l = mapscript.lineObj() self.addPointToLine(l, p) shape = mapscript.shapeObj(inline_layer.type) shape.classindex = 0 self.addLineToShape(shape, l) inline_layer.addFeature(shape) msimg = self.map.draw() filename = 'testAddPointFeature.png' msimg.save(filename) def testGetShape(self): """returning the shape from an inline feature works""" inline_layer = self.map.getLayerByName('INLINE') inline_layer.open() s = inline_layer.getFeature(0) l = self.getLineFromShape(s, 0) p = self.getPointFromLine(l, 0) self.assertAlmostEqual(p.x, -0.2) self.assertAlmostEqual(p.y, 51.5) def testGetNumFeatures(self): """the number of features in the inline layer is correct""" inline_layer = self.map.getLayerByName('INLINE') assert inline_layer.getNumFeatures() == 1 class ShapeValuesTestCase(unittest.TestCase): def testNullValue(self): so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) assert so.numvalues == 0 assert so.getValue(0) == None def testSetValue(self): so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) so.initValues(4) so.setValue(0, 'Foo'); assert so.numvalues == 4 assert so.getValue(0) == 'Foo' assert so.getValue(1) == '' # New class for testing the WKT stuff of RFC-2 class ShapeWKTTestCase(unittest.TestCase): # define a pair of coords, and WKT as class data point_xy = (-105.5000000000000000, 40.0000000000000000) point_wkt = 'POINT (-105.5000000000000000 40.0000000000000000)' def testSetPointWKT(self): # Create new instance and set/init from WKT so = mapscript.shapeObj.fromWKT(self.point_wkt) # expect one line with one point self.assert_(so.numlines == 1, so.numlines) self.assert_(so.get(0).numpoints == 1, so.get(0).numpoints) # expect shape's x and y values to be correct po = so.get(0).get(0) self.assertAlmostEqual(po.x, self.point_xy[0]) self.assertAlmostEqual(po.y, self.point_xy[1]) def testGetPointWKT(self): # Create new instance from class data po = mapscript.pointObj(self.point_xy[0], self.point_xy[1]) lo = mapscript.lineObj() lo.add(po) so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) so.add(lo) # test output WKT wkt = so.toWKT() self.assert_(wkt == self.point_wkt, wkt) # ============================================================================ if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/clonetest.py0000644002461700001440000001061712261257215023456 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of map cloning # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/clonetest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import TESTMAPFILE from testing import MapscriptTestCase # =========================================================================== # Base class class MapCloneTestCase(MapscriptTestCase): """Base class for testing with a map fixture""" def setUp(self): self.mapobj_orig = mapscript.mapObj(TESTMAPFILE) self.mapobj_clone = self.mapobj_orig.clone() def tearDown(self): self.mapobj_orig = None self.mapobj_clone = None # =========================================================================== # Tests begin here class MapCloningTestCase(MapCloneTestCase): def testClonedName(self): """MapCloningTestCase.testClonedName: the name of a cloned map equals the original""" assert self.mapobj_clone.name == self.mapobj_orig.name def testClonedLayers(self): """MapCloningTestCase.testClonedLayers: the layers of a cloned map equal the original""" assert self.mapobj_clone.numlayers == self.mapobj_orig.numlayers assert self.mapobj_clone.getLayer(0).data \ == self.mapobj_orig.getLayer(0).data def testSetFontSet(self): """MapCloningTestCase.testSetFontSet: the number of fonts in a cloned map equal original""" assert self.mapobj_clone.fontset.numfonts == 2 def testSetSymbolSet(self): """MapCloningTestCase.testSetSymbolSet: the number of symbols in a cloned map equal original""" num = self.mapobj_clone.symbolset.numsymbols assert num == 5, num def testDrawClone(self): """drawing a cloned map works properly""" msimg = self.mapobj_clone.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testClone.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testDrawCloneJPEG(self): """drawing a cloned map works properly""" self.mapobj_clone.selectOutputFormat('JPEG') self.mapobj_clone.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON msimg = self.mapobj_clone.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testClone.jpg' fh = open(filename, 'wb') fh.write(data) fh.close() def testDrawClonePNG24(self): """drawing a cloned map works properly""" self.mapobj_clone.selectOutputFormat('PNG24') self.mapobj_clone.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON msimg = self.mapobj_clone.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testClonePNG24.png' fh = open(filename, 'wb') fh.write(data) fh.close() if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/linetest.py0000644002461700001440000000577012261257215023311 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map "zooming" # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/shapetest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapPrimitivesTestCase class LineObjTestCase(MapPrimitivesTestCase): """Testing the lineObj class in stand-alone mode""" def setUp(self): """The test fixture is a line with two points""" self.points = (mapscript.pointObj(0.0, 1.0), mapscript.pointObj(2.0, 3.0)) self.line = mapscript.lineObj() self.addPointToLine(self.line, self.points[0]) self.addPointToLine(self.line, self.points[1]) def testCreateLine(self): """created line has the correct number of points""" assert self.line.numpoints == 2 def testGetPointsFromLine(self): """points in the line share are the same that were input""" for i in range(len(self.points)): got_point = self.getPointFromLine(self.line, i) self.assertPointsEqual(got_point, self.points[i]) def testAddPointToLine(self): """adding a point to a line behaves correctly""" new_point = mapscript.pointObj(4.0, 5.0) self.addPointToLine(self.line, new_point) assert self.line.numpoints == 3 def testAlterNumPoints(self): """numpoints is immutable, this should raise error""" self.assertRaises(AttributeError, setattr, self.line, 'numpoints', 3) if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/symboltest.py0000644002461700001440000001577412261257215023674 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Symbol # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/symboltest.py -v # # =========================================================================== import os, sys import unittest import StringIO # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase from testing import TESTMAPFILE, XMARKS_IMAGE, HOME_IMAGE # =========================================================================== # Test begins now class SymbolTestCase(unittest.TestCase): def testConstructor(self): """create new instance of symbolObj""" symbol = mapscript.symbolObj('test') assert symbol.name == 'test' assert symbol.thisown == 1 def testConstructorImage(self): """create new instance of symbolObj from an image""" symbol = mapscript.symbolObj('xmarks', XMARKS_IMAGE) assert symbol.name == 'xmarks' assert symbol.type == mapscript.MS_SYMBOL_PIXMAP format = mapscript.outputFormatObj('GD/PNG') img = symbol.getImage(format) img.save('sym-%s.%s' % (symbol.name, img.format.extension)) class DynamicGraphicSymbolTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) f = open(HOME_IMAGE, 'rb') s = StringIO.StringIO(f.read()) f.close() symb_img = mapscript.imageObj(s) self.h_symbol = mapscript.symbolObj('house') self.h_symbol.type = mapscript.MS_SYMBOL_PIXMAP self.h_symbol.setImage(symb_img) f = open(XMARKS_IMAGE, 'rb') s = StringIO.StringIO(f.read()) f.close() symb_img = mapscript.imageObj(s) self.x_symbol = mapscript.symbolObj('xmarks') self.x_symbol.type = mapscript.MS_SYMBOL_PIXMAP self.x_symbol.setImage(symb_img) def testSetPCTImage(self): """set image of new symbolObj""" assert self.h_symbol.name == 'house' assert self.h_symbol.type == mapscript.MS_SYMBOL_PIXMAP format = mapscript.outputFormatObj('GD/PNG') format.transparent = mapscript.MS_ON img = self.h_symbol.getImage(format) img.save('set-%s.%s' % (self.h_symbol.name, img.format.extension)) def testDrawSetPCTImage(self): """draw a map using the set image symbol""" symbol_index = self.map.symbolset.appendSymbol(self.h_symbol) assert symbol_index == 4, symbol_index num = self.map.symbolset.numsymbols assert num == 5, num inline_layer = self.map.getLayerByName('INLINE') s = inline_layer.getClass(0).getStyle(0) s.symbol = symbol_index s.size = -1 # pixmap's own size inline_layer.transparency = mapscript.MS_GD_ALPHA img = self.map.draw() img.save('testDrawSetPCTImage.%s' % (img.format.extension)) def testSetRGBAImage(self): """set image of new symbolObj""" assert self.x_symbol.name == 'xmarks' assert self.x_symbol.type == mapscript.MS_SYMBOL_PIXMAP format = mapscript.outputFormatObj('GD/PNG') img = self.x_symbol.getImage(format) img.save('set-%s.%s' % (self.x_symbol.name, img.format.extension)) def testDrawSetRGBAImage(self): """draw a map using the set image symbol""" symbol_index = self.map.symbolset.appendSymbol(self.x_symbol) inline_layer = self.map.getLayerByName('INLINE') s = inline_layer.getClass(0).getStyle(0) s.symbol = symbol_index s.size = -1 # pixmap's own size inline_layer.transparency = mapscript.MS_GD_ALPHA self.map.selectOutputFormat('PNG24') img = self.map.draw() img.save('testDrawSetRGBAImage.%s' % (img.format.extension)) class MapSymbolTestCase(MapTestCase): def testGetPoints(self): """get symbol points as line and test coords""" symbol = self.map.symbolset.getSymbol(1) assert symbol.name == 'circle' line = symbol.getPoints() assert line.numpoints == 1, line.numpoints pt = self.getPointFromLine(line, 0) self.assertPointsEqual(pt, mapscript.pointObj(1.0, 1.0)) def testSetPoints(self): """add lines of points to an existing symbol""" symbol = self.map.symbolset.getSymbol(1) assert symbol.name == 'circle' line = mapscript.lineObj() self.addPointToLine(line, mapscript.pointObj(2.0, 2.0)) self.addPointToLine(line, mapscript.pointObj(3.0, 3.0)) assert symbol.setPoints(line) == 2 assert symbol.numpoints == 2 line = symbol.getPoints() assert line.numpoints == 2, line.numpoints pt = self.getPointFromLine(line, 1) self.assertPointsEqual(pt, mapscript.pointObj(3.0, 3.0)) def testSetStyle(self): """expect success after setting an existing symbol's style""" symbol = self.map.symbolset.getSymbol(1) assert symbol.setPattern(0, 1) == mapscript.MS_SUCCESS def testRGBASymbolInPNG24(self): """draw a RGBA PNG pixmap on PNG canvas""" self.map.setImageType('PNG24') #self.map.getLayerByName('INLINE-PIXMAP-RGBA').status \ # == mapscript.MS_DEFAULT img = self.map.draw() img.save('pixmap-rgba-24.png') def testRGBASymbolInJPEG(self): """draw a RGBA PNG pixmap on JPEG canvas""" self.map.setImageType('JPEG') #self.map.getLayerByName('INLINE-PIXMAP-RGBA').status \ # == mapscript.MS_DEFAULT img = self.map.draw() img.save('pixmap-rgba.jpg') # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/colortest.py0000644002461700001440000000721512261257215023474 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of colorObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/colortest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapPrimitivesTestCase # =========================================================================== # Test begins now class ColorObjTestCase(unittest.TestCase): def testColorObjConstructorNoArgs(self): """a color can be initialized with no arguments""" c = mapscript.colorObj() assert (c.red, c.green, c.blue, c.pen) == (0, 0, 0, -4) def testColorObjConstructorArgs(self): """a color can be initialized with arguments""" c = mapscript.colorObj(1, 2, 3) assert (c.red, c.green, c.blue, c.pen) == (1, 2, 3, -4) def testColorObjToHex(self): """a color can be outputted as hex""" c = mapscript.colorObj(255, 255, 255) assert c.toHex() == '#ffffff' def testColorObjToHexBadly(self): """raise an error in the case of an undefined color""" c = mapscript.colorObj(-1,-1,-1) self.assertRaises(mapscript.MapServerError, c.toHex) def testColorObjSetRGB(self): """a color can be set using setRGB method""" c = mapscript.colorObj() c.setRGB(255, 255, 255) assert (c.red, c.green, c.blue, c.pen) == (255, 255, 255, -4) def testColorObjSetHexLower(self): """a color can be set using lower case hex""" c = mapscript.colorObj() c.setHex('#ffffff') assert (c.red, c.green, c.blue, c.pen) == (255, 255, 255, -4) def testColorObjSetHexUpper(self): """a color can be set using upper case hex""" c = mapscript.colorObj() c.setHex('#FFFFFF') assert (c.red, c.green, c.blue) == (255, 255, 255) def testColorObjSetHexBadly(self): """invalid hex color string raises proper error""" c = mapscript.colorObj() self.assertRaises(mapscript.MapServerError, c.setHex, '#fffffg') # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/zoomtest.py0000644002461700001440000002005112261257215023333 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map "zooming" # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/zoomtest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapZoomTestCase # =========================================================================== # Test begins now class ZoomPointTestCase(MapZoomTestCase): def testRecenter(self): """ZoomPointTestCase.testRecenter: recentering the map with a point returns the same extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj(50.0, 50.0) extent = self.mapobj1.extent self.mapobj1.zoomPoint(1, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-50,-50,50,50)) def testZoomInPoint(self): """ZoomPointTestCase.testZoomInPoint: zooming in by a power of 2 returns the proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj(50.0, 50.0) extent = self.mapobj1.extent self.mapobj1.zoomPoint(2, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-25,-25,25,25)) def testZoomOutPoint(self): """ZoomPointTestCase.testZoomOutPoint: zooming out by a power of 2 returns the proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent self.mapobj1.zoomPoint(-2, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-100,-100,100,100)) def testZoomOutPointConstrained(self): """ZoomPointTestCase.testZoomOutPointConstrained: zooming out to a constrained extent returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) max = mapscript.rectObj() max.minx, max.miny, max.maxx, max.maxy = (-100.0,-100.0,100.0,100.0) p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent self.mapobj1.zoomPoint(-4, p, w, h, extent, max) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, max) def testZoomBadSize(self): """ZoomPointTestCase.testZoomBadSize: zooming to a bad size raises proper error""" p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent w = 0 h = -1 self.assertRaises(mapscript.MapServerError, self.mapobj1.zoomPoint, -2, p, w, h, extent, None); def testZoomBadExtent(self): """ZoomPointTestCase.testZoomBadExtent: zooming to a bad extent raises proper error""" p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent extent.maxx = extent.maxx - 1000000 w = 100 h = 100 self.assertRaises(mapscript.MapServerError, self.mapobj1.zoomPoint, -2, p, w, h, extent, None); class ZoomRectangleTestCase(MapZoomTestCase): def testZoomRectangle(self): """ZoomRectangleTestCase.testZoomRectangle: zooming to an extent returns proper map extent""" w, h = (self.mapobj1.width, self.mapobj1.height) r = mapscript.rectObj(1, 26, 26, 1, 1) extent = self.mapobj1.extent self.mapobj1.zoomRectangle(r, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-49,24,-24,49)) def testZoomRectangleConstrained(self): """ZoomRectangleTestCase.testZoomRectangleConstrained: zooming to a constrained extent returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) max = mapscript.rectObj(-100.0, -100.0, 100.0, 100.0) r = mapscript.rectObj(0, 200, 200, 0, 1) extent = self.mapobj1.extent self.mapobj1.zoomRectangle(r, w, h, extent, max) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, max) def testZoomRectangleBadly(self): """zooming into an invalid extent raises proper error""" w, h = (self.mapobj1.width, self.mapobj1.height) r = mapscript.rectObj(0, 0, 200, 200) extent = self.mapobj1.extent self.assertRaises(mapscript.MapServerError, self.mapobj1.zoomRectangle, r, w, h, extent, None) class ZoomScaleTestCase(MapZoomTestCase): def testRecenter(self): """ZoomScaleTestCase.testRecenter: recentering map returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) scale = 2834.6472 extent = self.mapobj1.extent self.mapobj1.zoomScale(scale, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-50,-50,50,50)) def testZoomInScale(self): """ZoomScaleTestCase.testZoomInScale: zooming in to a specified scale returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) scale = 1417.3236 extent = self.mapobj1.extent self.mapobj1.zoomScale(scale, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-25,-25,25,25)) def testZoomOutScale(self): """ZoomScaleTestCase.testZoomOutScale: zooming out to a specified scale returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) scale = 5669.2944 extent = self.mapobj1.extent self.mapobj1.zoomScale(scale, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-100,-100,100,100)) def testZoomOutPointConstrained(self): """ZoomScaleTestCase.testZoomOutPointConstrained: zooming out to a constrained extent returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) max = mapscript.rectObj() max.minx, max.miny, max.maxx, max.maxy = (-100.0,-100.0,100.0,100.0) p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent scale = 10000 self.mapobj1.zoomScale(scale, p, w, h, extent, max) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, max) # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/threadtest.py0000644002461700001440000001546412261257215023632 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript test of multi-threading # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/threadtest.py -v # # =========================================================================== import os, sys import unittest import threading # the testing module helps us import the pre-installed mapscript from testing import mapscript, TESTMAPFILE, INCOMING def draw_map(name, save=0): #print "making map in thread %s" % (name) mo = mapscript.mapObj(TESTMAPFILE) im = mo.draw() if save: im.save('threadtest_%s.png' % (name)) def trigger_exception(name): #print "triggering exception in thread %s" % (name) mo = mapscript.mapObj(TESTMAPFILE) try: mo.setExtent(1, 50, -1, 51) raise Exception, "We expected a MapServer exception" except mapscript.MapServerError: pass class MultipleThreadsTestCase(unittest.TestCase): def testDrawMultiThreads(self): """map drawing with multiple threads""" workers = [] for i in range(10): name = 'd%d' % (i) thread = threading.Thread(target=draw_map, name=name, args=(name,1)) workers.append(thread) thread.start() def testExceptionsMultiThreads(self): """mapserver exceptions behave with multiple threads""" workers = [] for i in range(10): name = 'e%d' % (i) thread = threading.Thread(target=trigger_exception, name=name, args=(name,)) workers.append(thread) thread.start() def testExceptionContainmentMultiThreads(self): """mapserver exceptions should be contained to a thread""" num = 100 workers = [] # Trigger an exception in the first started thread for i in range(0, 1): name = 'c%d' % (i) thread = threading.Thread(target=trigger_exception, name=name, args=(name,)) workers.append(thread) # Draw normally for i in range(1, num): name = 'c%d' % (i) thread = threading.Thread(target=draw_map, name=name, args=(name,)) workers.append(thread) # Start all threads for i in range(num): workers[i].start() def draw_map_wfs(name, save=0): #print "making map in thread %s" % (name) mo = mapscript.mapObj(TESTMAPFILE) # WFS layer lo = mapscript.layerObj() lo.name = 'cheapo_wfs' lo.setProjection('+init=epsg:4326') lo.connectiontype = mapscript.MS_WFS lo.connection = 'http://zcologia.com:9001/mapserver/members/features.rpy?' lo.metadata.set('wfs_service', 'WFS') lo.metadata.set('wfs_typename', 'users') lo.metadata.set('wfs_version', '1.0.0') lo.type = mapscript.MS_LAYER_POINT lo.status = mapscript.MS_DEFAULT lo.labelitem = 'zco:mid' so1 = mapscript.styleObj() so1.color.setHex('#FFFFFF') so1.size = 9 so1.symbol = 1 #mo.symbolset.index('circle') so2 = mapscript.styleObj() so2.color.setHex('#333333') so2.size = 7 so2.symbol = 1 #mo.symbolset.index('circle') co = mapscript.classObj() co.label.type = mapscript.MS_BITMAP co.label.size = mapscript.MS_SMALL co.label.color.setHex('#000000') co.label.outlinecolor.setHex('#FFFFFF') co.label.position = mapscript.MS_AUTO co.insertStyle(so1) co.insertStyle(so2) lo.insertClass(co) mo.insertLayer(lo) if not mo.web.imagepath: mo.web.imagepath = os.environ.get('TEMP', None) or INCOMING mo.debug = mapscript.MS_ON im = mo.draw() if save: im.save('threadtest_wfs_%s.png' % (name)) def draw_map_wms(name, save=0): #print "making map in thread %s" % (name) mo = mapscript.mapObj(TESTMAPFILE) # WFS layer lo = mapscript.layerObj() lo.name = 'jpl_wms' lo.setProjection('+init=epsg:4326') lo.connectiontype = mapscript.MS_WMS # lo.connection = 'http://wms.jpl.nasa.gov/wms.cgi?' lo.connection = 'http://vmap0.tiles.osgeo.org/wms/vmap0?' lo.metadata.set('wms_service', 'WMS') lo.metadata.set('wms_server_version', '1.1.1') lo.metadata.set('wms_name', 'basic') lo.metadata.set('wms_style', 'visual') lo.metadata.set('wms_format', 'image/jpeg') lo.type = mapscript.MS_LAYER_RASTER lo.status = mapscript.MS_DEFAULT lo.debug = mapscript.MS_ON mo.insertLayer(lo) if not mo.web.imagepath: mo.web.imagepath = os.environ.get('TEMP', None) or INCOMING mo.debug = mapscript.MS_ON mo.selectOutputFormat('image/jpeg') im = mo.draw() if save: im.save('threadtest_wms_%s.jpg' % (name)) class OWSRequestTestCase(unittest.TestCase): #def testDrawWFS(self): # workers = [] # for i in range(10): # name = 'd%d' % (i) # thread = threading.Thread(target=draw_map_wfs, name=name, # args=(name,1)) # workers.append(thread) # thread.start() def testDrawWMS(self): workers = [] for i in range(10): name = 'd%d' % (i) thread = threading.Thread(target=draw_map_wms, name=name, args=(name,1)) workers.append(thread) thread.start() # ----------------------------------------------------------------------------- if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/pgtest.py0000644002461700001440000001171512261257215022764 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of PostGIS Layer # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/pgtest.py -v # # NOTE: these tests use a fixture included in mapserver/tests. To produce # the testing database, follow these steps: # # $ cd mapserver/tests # $ shp2pgsql -s 4326 -I polygon.shp postgis.polygon > polygon.sql # $ su postgres # $ make -f makefile_postgis # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import MapTestCase PG_CONNECTION_STRING="dbname=mapserver_test user=postgres" class TableTest(unittest.TestCase): def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from polygon" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) class ViewTest(unittest.TestCase): def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_sub_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from polygon_v using unique gid using srid=4326" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) class SubSelectTest(unittest.TestCase): def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_sub_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from (select * from polygon) as foo using unique gid using srid=4326" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) class SubSelectNoSRIDTest(unittest.TestCase): """SRID should be diagnosed from the selection""" def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_sub_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from (select * from polygon) as foo using unique gid" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/testing.py0000644002461700001440000001420512261257215023130 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript testing utilities # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Purpose of this module is to export the locally built mapscript module # prior to installation, do some name normalization that allows testing of # the so-called next generation class names, and define some classes # useful to many test cases. # # All test case modules should import mapscript from testing # # from testing import mapscript # # =========================================================================== import os import sys import distutils.util import unittest # define the path to mapserver test data TESTS_PATH = '../../../../tests' TESTMAPFILE = os.path.join(TESTS_PATH, 'test.map') XMARKS_IMAGE = os.path.join(TESTS_PATH, 'xmarks.png') HOME_IMAGE = os.path.join(TESTS_PATH, 'home.png') TEST_IMAGE = os.path.join(TESTS_PATH, 'test.png') INCOMING = '/tmp/' # Put local build directory on head of python path platformdir = '-'.join((distutils.util.get_platform(), '.'.join(map(str, sys.version_info[0:2])))) sys.path.insert(0, os.path.join('../../build', 'lib.' + platformdir)) # import mapscript from the local build directory import mapscript # ========================================================================== # Base testing classes class MapscriptTestCase(unittest.TestCase): def assertAlmostEqual(self, first, second, places=7): """Copied from unittest for use with Python 2.1 or 2.2""" if round(second-first, places) != 0: raise AssertionError, \ '%s != %s within %s places' % (`first`, `second`, `places`) class MapPrimitivesTestCase(MapscriptTestCase): """Base class for testing primitives (points, lines, shapes) in stand-alone mode""" def addPointToLine(self, line, point): """Using either the standard or next_generation_api""" try: line.add(point) except AttributeError: # next_generation_api line.addPoint(point) except: raise def getPointFromLine(self, line, index): """Using either the standard or next_generation_api""" try: point = line.get(index) return point except AttributeError: # next_generation_api point = line.getPoint(index) return point except: raise def addLineToShape(self, shape, line): """Using either the standard or next_generation_api""" try: shape.add(line) except AttributeError: # next_generation_api shape.addLine(line) except: raise def getLineFromShape(self, shape, index): """Using either the standard or next_generation_api""" try: line = shape.get(index) return line except AttributeError: # next_generation_api line = shape.getLine(index) return line except: raise def assertPointsEqual(self, first, second): self.assertAlmostEqual(first.x, second.x) self.assertAlmostEqual(first.y, second.y) def assertLinesEqual(self, first, second): assert first.numpoints == second.numpoints for i in range(first.numpoints): point_first = self.getPointFromLine(first, i) point_second = self.getPointFromLine(second, i) self.assertPointsEqual(point_first, point_second) def assertShapesEqual(self, first, second): assert first.numlines == second.numlines for i in range(first.numlines): line_first = self.getLineFromShape(first, i) line_second = self.getLineFromShape(second, i) self.assertLinesEqual(line_first, line_second) def assertRectsEqual(self, first, second): self.assertAlmostEqual(first.minx, second.minx) self.assertAlmostEqual(first.miny, second.miny) self.assertAlmostEqual(first.maxx, second.maxx) self.assertAlmostEqual(first.maxy, second.maxy) class MapTestCase(MapPrimitivesTestCase): """Base class for testing with a map fixture""" def setUp(self): self.map = mapscript.mapObj(TESTMAPFILE) #self.xmarks_image = xmarks_image #self.test_image = test_image def tearDown(self): self.map = None class MapZoomTestCase(MapPrimitivesTestCase): "Testing new zoom* methods that we are adapting from the PHP MapScript" def setUp(self): self.mapobj1 = mapscript.mapObj(TESTMAPFILE) # Change the extent for purposes of zoom testing rect = mapscript.rectObj() rect.minx, rect.miny, rect.maxx, rect.maxy = (-50.0, -50.0, 50.0, 50.0) self.mapobj1.extent = rect # Change height/width as well self.mapobj1.width, self.mapobj1.height = (100, 100) def tearDown(self): self.mapobj1 = None class ShapeObjTestCase(MapPrimitivesTestCase): """Base class for shapeObj tests""" pass mapserver-6.4.1/mapscript/python/tests/cases/__init__.py0000644002461700001440000000000012261257215023176 0ustar tbonfortusersmapserver-6.4.1/mapscript/python/tests/cases/parentreference.py0000644002461700001440000001057012261257215024624 0ustar tbonfortusers# $Id: refcount.py 6521 2007-08-08 20:39:17Z hobu $ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Umberto Nicoletti, unicoletti@prometeo.it # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/refcount.py -v # # =========================================================================== import os, sys, gc import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase, TESTMAPFILE # =========================================================================== # Test begins now class ParentReferenceTestCase(unittest.TestCase): def initMap(self): self.map=mapscript.mapObj(TESTMAPFILE) def testGetLayerObj(self): self.initMap() layer = self.map.getLayer(1) self.map=None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map != None, layer.map def testGetLayerObjByName(self): self.initMap() layer = self.map.getLayerByName('POLYGON') self.map=None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map != None, layer.map def testLayerObj(self): self.initMap() layer = mapscript.layerObj(self.map) self.map=None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map != None, layer.map def testInsertLayerObj(self): self.initMap() layer = mapscript.layerObj() self.map.insertLayer(layer) self.map=None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map != None, layer.map def testGetClassObj(self): self.initMap() layer = self.map.getLayer(1) clazz = layer.getClass(0) self.map=None layer=None assert str(clazz.p_layer).find('mapscript.layerObj') != -1 gc.collect() assert clazz.layer != None, clazz.layer def testClassObj(self): self.initMap() layer = mapscript.layerObj(self.map) clazz = mapscript.classObj(layer) self.map=None layer=None assert str(clazz.p_layer).find('mapscript.layerObj') != -1 gc.collect() assert clazz.layer != None, clazz.layer def testInsertClassObj(self): self.initMap() layer = mapscript.layerObj() clazz = mapscript.classObj() layer.insertClass(clazz) self.map=None layer=None assert str(clazz.p_layer).find('mapscript.layerObj') != -1 gc.collect() assert clazz.layer != None, clazz.layer def testRemoveClassObj(self): self.initMap() layer = self.map.getLayer(1) clazz = layer.removeClass(0) if hasattr(clazz,'p_layer'): assert clazz.p_layer == None, clazz.p_layer assert clazz.layer == None, clazz.layer self.initMap() position=self.map.getLayer(0).insertClass(clazz) assert position==0, position assert clazz.p_layer != None, clazz.p_layer assert clazz.layer != None, clazz.layer # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/refcount.py0000644002461700001440000002726212261257215023307 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Umberto Nicoletti, unicoletti@prometeo.it # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/refcount.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase, TESTMAPFILE # =========================================================================== # Test begins now class ReferenceCountingTestCase(unittest.TestCase): def initMap(self): self.map=mapscript.mapObj(TESTMAPFILE) def testMap(self): """ReferenceCountingTestCase.testMap: test map constructor with no argument""" test_map = mapscript.mapObj() maptype = type(test_map) assert str(maptype) == "", maptype assert test_map.thisown == 1 assert test_map.refcount == 1 def testMapWithDefaultMap(self): """ReferenceCountingTestCase.testTestMap: test map constructor with default map file""" test_map = mapscript.mapObj(TESTMAPFILE) maptype = type(test_map) assert str(maptype) == "", maptype assert test_map.thisown == 1 assert test_map.refcount == 1 assert test_map.getLayer(0).refcount == 2 def testMapLayersCounting(self): """ReferenceCountingTestCase.testTestMap: test map constructor with default map file""" self.initMap() layerRef1=self.map.getLayer(0) assert layerRef1.refcount == 2 layerRef2=self.map.getLayer(0) assert layerRef2.refcount == 3 def testMapInsertedLayer(self): """MapLayersTestCase.testMapInsertedLayer: test insertion of a new layer at default (last) index""" self.initMap() n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.refcount == 1 assert layer.thisown == 1 index = self.map.insertLayer(layer) assert index == n, index assert self.map.numlayers == n + 1 assert layer.refcount == 2 assert layer.thisown == 1 assert self.map.getLayer(index).refcount == 3 assert self.map.getLayer(index).thisown == 1 assert layer.refcount == 2 assert layer.thisown == 1 def testMapInsertedLayerWithIndex(self): """MapLayersTestCase.testMapInsertedLayerWithIndex: test insertion of a new layer at index 0""" self.initMap() n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.refcount == 1 assert layer.thisown == 1 index = self.map.insertLayer(layer,0) assert index == 0, index assert self.map.numlayers == n + 1 assert layer.refcount == 2 assert layer.thisown == 1 assert self.map.getLayer(index).refcount == 3 assert self.map.getLayer(index).thisown == 1 assert layer.refcount == 2 assert layer.thisown == 1 def testMapRemovedLayerAtTail(self): """removal of highest index (tail) layer""" self.initMap() n = self.map.numlayers layer = self.map.removeLayer(n-1) assert self.map.numlayers == n-1 assert layer.name == 'INLINE-PIXMAP-PCT' assert layer.thisown == 1 assert layer.refcount == 1, layer.refcount self.map.draw() def testMapRemovedLayerAtZero(self): """removal of lowest index (0) layer""" self.initMap() n = self.map.numlayers layer = self.map.removeLayer(0) assert self.map.numlayers == n-1 assert layer.name == 'RASTER' assert layer.thisown == 1 assert layer.refcount == 1, layer.refcount self.map.draw() def testBehaveWhenParentIsNull(self): """behave when parent (map) is null""" self.initMap() layer = mapscript.layerObj() layer.name = 'new' index = self.map.insertLayer(layer,0) assert index == 0, index self.map=None assert layer.map != None, layer.map exception=None try: layer.open() except: # must fail because the new layer is missing information assert True exception=True if not exception: fail def testLayerClone(self): """Clone a layer""" layer = mapscript.layerObj() layer.name='sample' copy = layer.clone() assert layer.refcount == 1, layer.refcount assert copy.refcount == 1, copy.refcount assert layer.name == copy.name assert copy.map == None def testMapGetLayerByName(self): """behave when parent (map) is null""" self.initMap() layer = self.map.getLayerByName("RASTER") assert layer.refcount == 2, layer.refcount assert layer.thisown == 1, layer.thisown def testBehaveWhenParentIsNotNull(self): """behave when parent (map) is not null""" self.initMap() layer = mapscript.layerObj(self.map) layer.name = 'new' assert layer.refcount == 2, layer.refcount def testDummyClass(self): """basic refcounting for classObj""" clazz = mapscript.classObj() assert clazz.refcount == 1, clazz.refcount def testClassWithArgument(self): """classObj constructor with not null layer""" self.initMap() clazz = mapscript.classObj(self.map.getLayer(0)) assert clazz.refcount == 2, clazz.refcount def testClassGetter(self): """classObj getter""" self.initMap() clazz = self.map.getLayer(1).getClass(0) assert clazz.refcount == 2, clazz.refcount def testClassClone(self): """classObj clone""" self.initMap() clazz = self.map.getLayer(1).getClass(0) assert clazz.refcount == 2, clazz.refcount clone = clazz.clone() assert clone.refcount == 1, clone.refcount def testClassInsert(self): """classObj insert at end""" self.initMap() clazz = mapscript.classObj() clazz.minscaledenom = 666 assert clazz.refcount == 1, clazz.refcount idx=self.map.getLayer(1).insertClass(clazz) assert clazz.refcount == 2, clazz.refcount assert self.map.getLayer(1).getClass(idx).refcount == 3, self.map.getLayer(1).getClass(idx).refcount assert self.map.getLayer(1).getClass(idx).minscaledenom == 666, self.map.getLayer(1).getClass(idx).minscaledenom def testClassInsertAtMiddle(self): """classObj insert at pos. 1""" self.initMap() clazz = mapscript.classObj() clazz.minscaledenom = 666 assert clazz.refcount == 1, clazz.refcount idx=self.map.getLayer(1).insertClass(clazz, 1) assert idx == 1, idx assert clazz.refcount == 2, clazz.refcount assert self.map.getLayer(1).getClass(idx).refcount == 3, self.map.getLayer(1).getClass(idx).refcount assert self.map.getLayer(1).getClass(idx).thisown , self.map.getLayer(1).getClass(idx).thisown assert self.map.getLayer(1).getClass(idx).minscaledenom == 666, self.map.getLayer(1).getClass(idx).minscaledenom def testRemoveFirstClass(self): """removal of first class""" self.initMap() clazz = self.map.getLayerByName("POLYGON").removeClass(0) assert clazz != None assert clazz.thisown == 1 assert clazz.refcount == 1, clazz.refcount self.map.draw() def testMapClone(self): """cloning a mapObj""" self.initMap() clone = self.map.clone() assert clone.refcount == 1, clone.refcount def testStyleGetter(self): """styleObj getter""" self.initMap() style = self.map.getLayer(1).getClass(0).getStyle(0) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown def testStyleConstructor(self): """styleObj Constructor""" self.initMap() style = mapscript.styleObj( self.map.getLayer(1).getClass(0) ) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown def testRemoveStyleAtBeginning(self): """styleObj remove first one""" self.initMap() style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown idx = self.map.getLayer(1).getClass(0).insertStyle(style) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown style = self.map.getLayer(1).getClass(0).removeStyle(0) assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown def testInsertStyle(self): """styleObj Insert""" self.initMap() style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown idx = self.map.getLayer(1).getClass(0).insertStyle(style) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown def testCloneStyle(self): """styleObj Clone""" self.initMap() style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown clone = style.clone() assert clone.refcount == 1, clone.refcount assert clone.thisown == 1, clone.thisown assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown style = self.map.getLayer(1).getClass(0).getStyle(0) clone = style.clone() assert clone.refcount == 1, clone.refcount assert clone.thisown == 1, clone.thisown def testBasicSymbolRefcounting(self): """symbolObj refcounting """ self.initMap() symb = self.map.symbolset.getSymbol(0) assert symb.refcount == 2, symb.refcount assert symb.thisown == 1, symb.thisown symb = self.map.symbolset.getSymbolByName("home-png") assert symb.refcount == 2, symb.refcount assert symb.thisown == 1, symb.thisown symb2 = self.map.symbolset.getSymbolByName("home-png") assert symb2.refcount == 3, symb2.refcount assert symb2.thisown == 1, symb2.thisown def testSymbolAppendRemove(self): """appendSymbolObj refcounting """ self.initMap() symb = mapscript.symbolObj("ANEWSYMBOL") assert symb.refcount == 1, symb.refcount assert symb.thisown == 1, symb.thisown idx = self.map.symbolset.appendSymbol(symb) assert symb.refcount == 2, symb.refcount assert symb.thisown == 1, symb.thisown symb = self.map.symbolset.removeSymbol(idx) assert symb.refcount == 1, symb.refcount assert symb.thisown == 1, symb.thisown # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/shapefiletest.py0000644002461700001440000000470412261257215024316 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of shapefileObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/shapefiletest.py -v # # =========================================================================== import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript class AddShapeTestCase(unittest.TestCase): def testAddEmpty(self): """expect an error rather than segfault when adding an empty shape""" # See bug 1201 sf = mapscript.shapefileObj('testAddDud.shp', 1) so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) self.assertRaises(mapscript.MapServerError, sf.add, so) def testGetDBFInfo(self): """Fetch dbf information from shapefile""" sf = mapscript.shapefileObj('../../../../tests/polygon.shp') assert sf.getDBF() != None, sf.getDBF() assert sf.getDBF().nFields == 2, sf.getDBF().nFields assert sf.getDBF().getFieldName(0) == 'FID', sf.getDBF().getFieldName(0) assert sf.getDBF().getFieldName(1) == 'FNAME', sf.getDBF().getFieldName(1) if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/imagetest.py0000644002461700001440000001461512261257215023442 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of map cloning # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/clonetest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript from testing import TEST_IMAGE as test_image from testing import TESTMAPFILE from testing import MapTestCase from StringIO import StringIO import cStringIO import urllib have_image = 0 try: from PIL import Image have_image = 1 except ImportError: pass class SaveToStringTestCase(MapTestCase): def testSaveToString(self): """test that an image can be saved as a string""" msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testSaveToString.png' fh = open(filename, 'wb') fh.write(data) fh.close() if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'P' else: assert 1 class ImageObjTestCase(unittest.TestCase): def testConstructor(self): """imageObj constructor works""" imgobj = mapscript.imageObj(10, 10) assert imgobj.thisown == 1 assert imgobj.height == 10 assert imgobj.width == 10 def testConstructorWithFormat(self): """imageObj with an optional driver works""" driver = 'GD/PNG' format = mapscript.outputFormatObj(driver) imgobj = mapscript.imageObj(10, 10, format) assert imgobj.thisown == 1 assert imgobj.format.driver == driver assert imgobj.height == 10 assert imgobj.width == 10 def testConstructorFilename(self): """imageObj with a filename works""" imgobj = mapscript.imageObj(test_image) assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 imgobj.save('testConstructorFilename.png') def testConstructorFilenameDriver(self): """imageObj with a filename and a driver works""" imgobj = mapscript.imageObj(test_image) assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 imgobj.save('testConstructorFilenameDriver.png') def testConstructorStream(self): """imageObj with a file stream works""" f = open(test_image, 'rb') imgobj = mapscript.imageObj(f) f.close() assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 def testConstructorStringIO(self): """imageObj with a cStringIO works""" f = open(test_image, 'rb') data = f.read() f.close() s = cStringIO.StringIO(data) imgobj = mapscript.imageObj(s) assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 def testConstructorUrlStream(self): """imageObj with a URL stream works""" url = urllib.urlopen('http://mapserver.org/_static/banner.png') imgobj = mapscript.imageObj(url, 'GD/JPEG') assert imgobj.thisown == 1 assert imgobj.height == 68 assert imgobj.width == 439 imgobj.save('testConstructorUrlStream.jpg') class ImageWriteTestCase(MapTestCase): def testImageWrite(self): """image writes data to an open filehandle""" image = self.map.draw() assert image.thisown == 1 filename = 'testImageWrite.png' fh = open(filename, 'wb') image.write(fh) fh.close() if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'P' else: assert 1 def testImageWriteStringIO(self): """image writes data to a StringIO instance""" image = self.map.draw() assert image.thisown == 1 s = cStringIO.StringIO() image.write(s) filename = 'testImageWriteStringIO.png' fh = open(filename, 'wb') fh.write(s.getvalue()) fh.close() if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'P' else: assert 1 def testImageGetBytes(self): """image returns bytes""" image = self.map.draw() assert image.thisown == 1 s = cStringIO.StringIO(image.getBytes()) filename = 'testImageGetBytes.png' fh = open(filename, 'wb') fh.write(s.getvalue()) fh.close() if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'P' else: assert 1 if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/classtest.py0000644002461700001440000001034612261257215023462 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of classObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/classtest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase # =========================================================================== # Test begins now class ClassObjTestCase(unittest.TestCase): def testConstructorNoArg(self): c = mapscript.classObj() assert c.thisown == 1 assert c.layer == None assert c.numstyles == 0 def testConstructorWithArg(self): l = mapscript.layerObj() l.name = 'foo' c = mapscript.classObj(l) assert c.thisown == 1 assert c.layer.name == l.name assert c.numstyles == 0 class ClassCloningTestCase(unittest.TestCase): def testCloneClass(self): """check attributes of a cloned class""" c = mapscript.classObj() c.minscaledenom = 5.0 clone = c.clone() assert clone.thisown == 1 assert clone.minscaledenom == 5.0 class ClassIconTestCase(MapTestCase): """testing for bug 1250""" def testAlphaTransparentPixmap(self): lo = self.map.getLayerByName('INLINE-PIXMAP-RGBA') co = lo.getClass(0) self.map.selectOutputFormat('PNG') im = co.createLegendIcon(self.map, lo, 48, 48) im.save('testAlphaTransparentPixmapIcon.png') def testAlphaTransparentPixmapPNG24(self): lo = self.map.getLayerByName('INLINE-PIXMAP-RGBA') co = lo.getClass(0) self.map.selectOutputFormat('PNG24') im = co.createLegendIcon(self.map, lo, 48, 48) im.save('testAlphaTransparentPixmapIcon24.png') def testAlphaTransparentPixmapJPG(self): lo = self.map.getLayerByName('INLINE-PIXMAP-RGBA') co = lo.getClass(0) self.map.selectOutputFormat('JPEG') im = co.createLegendIcon(self.map, lo, 48, 48) im.save('testAlphaTransparentPixmapIcon.jpg') def testIndexedTransparentPixmap(self): lo = self.map.getLayerByName('INLINE-PIXMAP-PCT') lo.type = mapscript.MS_LAYER_POINT co = lo.getClass(0) self.map.selectOutputFormat('PNG') im = co.createLegendIcon(self.map, lo, 32, 32) im.save('testIndexedTransparentPixmapIcon.png') def testIndexedTransparentPixmapJPG(self): lo = self.map.getLayerByName('INLINE-PIXMAP-PCT') lo.type = mapscript.MS_LAYER_POINT co = lo.getClass(0) self.map.selectOutputFormat('JPEG') im = co.createLegendIcon(self.map, lo, 32, 32) im.save('testIndexedTransparentPixmapIcon.jpg') # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/labeltest.py0000644002461700001440000000527312261257215023437 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/labeltest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase # =========================================================================== # Test begins now class NewLabelsTestCase(MapTestCase): def testLabelBinding(self): """attribute binding can be set and get""" new_label = mapscript.labelObj() assert (not new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR)) new_label.setBinding(mapscript.MS_LABEL_BINDING_COLOR,"NEW_BINDING") assert (new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR) == "NEW_BINDING") class LabelCacheMemberTestCase(MapTestCase): def testCacheMemberText(self): """string attribute has been renamed to 'text' (bug 852)""" img = self.map.draw() assert self.map.labelcache.numlabels == 2, self.map.labelcache.numlabels label = self.map.nextLabel() assert label.text == 'A Point', label.text # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/maptest.py0000644002461700001440000003272212261257215023134 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/maptest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase, TESTMAPFILE # =========================================================================== # Test begins now class MapConstructorTestCase(unittest.TestCase): def testMapConstructorNoArg(self): """MapConstructorTestCase.testMapConstructorNoArg: test map constructor with no argument""" test_map = mapscript.mapObj() maptype = type(test_map) assert str(maptype) == "", maptype assert test_map.thisown == 1 def testMapConstructorEmptyStringArg(self): """MapConstructorTestCase.testMapConstructorEmptyStringArg: test map constructor with old-style empty string argument""" test_map = mapscript.mapObj('') maptype = type(test_map) assert str(maptype) == "", maptype assert test_map.thisown == 1 def testMapConstructorFilenameArg(self): """MapConstructorTestCasetest.testMapConstructorEmptyStringArg: map constructor with filename argument""" test_map = mapscript.mapObj(TESTMAPFILE) maptype = type(test_map) assert str(maptype) == "", maptype assert test_map.thisown == 1 class MapExtentTestCase(MapTestCase): def testSetExtent(self): """MapExtentTestCase.testSetExtent: test the setting of a mapObj's extent""" test_map = mapscript.mapObj(TESTMAPFILE) e = test_map.extent result = test_map.setExtent(e.minx, e.miny, e.maxx, e.maxy) self.assertAlmostEqual(test_map.scaledenom, 14.24445829) assert result == mapscript.MS_SUCCESS, result def testSetExtentBadly(self): """MapExtentTestCase.testSetExtentBadly: test that mapscript raises an error for an invalid mapObj extent""" test_map = mapscript.mapObj(TESTMAPFILE) self.assertRaises(mapscript.MapServerError, test_map.setExtent, 1.0, -2.0, -3.0, 4.0) def testReBindingExtent(self): """test the rebinding of a map's extent""" test_map = mapscript.mapObj(TESTMAPFILE) rect1 = mapscript.rectObj(-10.0, -10.0, 10.0, 10.0) rect2 = mapscript.rectObj(-10.0, -10.0, 10.0, 10.0) test_map.extent = rect1 assert repr(test_map.extent) != repr(rect1), (test_map.extent, rect1) del rect1 self.assertRectsEqual(test_map.extent, rect2) class MapLayersTestCase(MapTestCase): def testMapInsertLayer(self): """MapLayersTestCase.testMapInsertLayer: test insertion of a new layer at default (last) index""" n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.map == None, layer.map index = self.map.insertLayer(layer) assert layer.map != None, layer.map assert index == n, index assert self.map.numlayers == n + 1 names = [self.map.getLayer(i).name for i in range(self.map.numlayers)] assert names == ['RASTER', 'POLYGON', 'LINE', 'POINT', 'INLINE', 'INLINE-PIXMAP-RGBA', 'INLINE-PIXMAP-PCT', 'new'] order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5, 6, 7), order def testMapInsertLayerAtZero(self): """MapLayersTestCase.testMapInsertLayerAtZero: test insertion of a new layer at first index""" n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.map == None, layer.map index = self.map.insertLayer(layer, 0) assert layer.map != None, layer.map assert index == 0, index assert self.map.numlayers == n + 1 names = [self.map.getLayer(i).name for i in range(self.map.numlayers)] assert names == ['new', 'RASTER', 'POLYGON', 'LINE', 'POINT', 'INLINE', 'INLINE-PIXMAP-RGBA', 'INLINE-PIXMAP-PCT'], names order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5, 6, 7), order def testMapInsertLayerDrawingOrder(self): """MapLayersTestCase.testMapInsertLayerDrawingOrder: test affect of insertion of a new layer at index 1 on drawing order""" n = self.map.numlayers # reverse layer drawing order o_start = (6, 5, 4, 3, 2, 1, 0) self.map.setLayerOrder(o_start) # insert Layer layer = mapscript.layerObj() layer.name = 'new' index = self.map.insertLayer(layer, 1) assert index == 1, index # We expect our new layer to be at index 1 in drawing order as well order = self.map.getLayerOrder() assert order == (7, 1, 6, 5, 4, 3, 2, 0), order def testMapInsertLayerBadIndex(self): """MapLayersTestCase.testMapInsertLayerBadIndex: expect an exception when index is too large""" layer = mapscript.layerObj() self.assertRaises(mapscript.MapServerChildError, self.map.insertLayer, layer, 1000) def testMapInsertNULLLayer(self): """expect an exception on attempt to insert a NULL Layer""" self.assertRaises(mapscript.MapServerChildError, self.map.insertLayer, None) def testMapRemoveLayerAtTail(self): """removal of highest index (tail) layer""" n = self.map.numlayers layer = self.map.removeLayer(n-1) assert self.map.numlayers == n-1 assert layer.name == 'INLINE-PIXMAP-PCT' assert layer.thisown == 1 del layer order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5), order def testMapRemoveLayerAtZero(self): """removal of lowest index (0) layer""" n = self.map.numlayers layer = self.map.removeLayer(0) assert self.map.numlayers == n-1 assert layer.name == 'RASTER' order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5), order def testMapRemoveLayerDrawingOrder(self): """test affect of layer removal on drawing order""" n = self.map.numlayers # reverse layer drawing order o_start = (6, 5, 4, 3, 2, 1, 0) self.map.setLayerOrder(o_start) layer = self.map.removeLayer(1) assert self.map.numlayers == n-1 assert layer.name == 'POLYGON' order = self.map.getLayerOrder() assert order == (5, 4, 3, 2, 1, 0), order names = [self.map.getLayer(i).name for i in range(self.map.numlayers)] assert names == ['RASTER', 'LINE', 'POINT', 'INLINE', 'INLINE-PIXMAP-RGBA', 'INLINE-PIXMAP-PCT'], names class MapExceptionTestCase(MapTestCase): def testDrawBadData(self): """MapExceptionTestCase.testDrawBadData: a bad data descriptor in a layer returns proper error""" self.map.getLayerByName('POLYGON').data = 'foo' self.assertRaises(mapscript.MapServerError, self.map.draw) class EmptyMapExceptionTestCase(unittest.TestCase): def setUp(self): self.map = mapscript.mapObj('') def tearDown(self): self.map = None def testDrawEmptyMap(self): """EmptyMapExceptionTestCase.testDrawEmptyMap: drawing an empty map returns proper error""" self.assertRaises(mapscript.MapServerError, self.map.draw) class MapMetaDataTestCase(MapTestCase): def testInvalidKeyAccess(self): """MapMetaDataTestCase.testInvalidKeyAccess: an invalid map metadata key returns proper error""" self.assertRaises(mapscript.MapServerError, self.map.getMetaData, 'foo') def testFirstKeyAccess(self): """MapMetaDataTestCase.testFirstKeyAccess: first metadata key is correct value""" key = self.map.getFirstMetaDataKey() assert key == 'key1' val = self.map.getMetaData(key) assert val == 'value1' def testLastKeyAccess(self): """MapMetaDataTestCase.testLastKeyAccess: last metadata key is correct value""" key = self.map.getFirstMetaDataKey() for i in range(3): key = self.map.getNextMetaDataKey(key) assert key is not None key = self.map.getNextMetaDataKey(key) assert key is None def testMapMetaData(self): """MapMetaDataTestCase.testMapMetaData: map metadata keys are correct values""" keys = [] key = self.map.getFirstMetaDataKey() if key is not None: keys.append(key) while 1: key = self.map.getNextMetaDataKey(key) if not key: break keys.append(key) assert keys == ['key1', 'key2', 'key3', 'key4'], keys def testLayerMetaData(self): """MapMetaDataTestCase.testLayerMetaData: layer metadata keys are correct values""" keys = [] key = self.map.getLayer(1).getFirstMetaDataKey() if key is not None: keys.append(key) while 1: key = self.map.getLayer(1).getNextMetaDataKey(key) if not key: break keys.append(key) assert keys == ['key1', 'key2', 'key3', 'key4'], keys def testClassMetaData(self): """MapMetaDataTestCase.testClassMetaData: class metadata keys are correct values""" keys = [] key = self.map.getLayer(1).getClass(0).getFirstMetaDataKey() if key is not None: keys.append(key) while 1: key = self.map.getLayer(1).getClass(0).getNextMetaDataKey(key) if not key: break keys.append(key) assert keys == ['key1', 'key2', 'key3', 'key4'], keys class NoFontSetTestCase(unittest.TestCase): def testNoGetFontSetFile(self): """an empty map should have fontset filename == None""" self.map = mapscript.mapObj() assert self.map.fontset.filename == None class MapFontSetTestCase(MapTestCase): def testGetFontSetFile(self): """expect fontset file to be 'fonts.txt'""" file = self.map.fontset.filename assert file == 'fonts.txt', file class MapSizeTestCase(MapTestCase): def testDefaultSize(self): assert self.map.width == 200 assert self.map.height == 200 def testSetSize(self): retval = self.map.setSize(480, 480) assert retval == mapscript.MS_SUCCESS, retval assert self.map.width == 480 assert self.map.height == 480 class MapSetWKTTestCase(MapTestCase): def testOGCWKT(self): self.map.setWKTProjection('PROJCS["unnamed",PROJECTION["Albers_Conic_Equal_Area"],PARAMETER["standard_parallel_1",65],PARAMETER["standard_parallel_2",55],PARAMETER["latitude_of_center",0],PARAMETER["longitude_of_center",-153],PARAMETER["false_easting",-4943910.68],PARAMETER["false_northing",0]]') proj4 = self.map.getProjection() assert proj4.find( '+proj=aea' ) != -1 assert proj4.find( '+ellps=WGS84' ) != -1 assert (mapscript.projectionObj(proj4)).getUnits() != mapscript.MS_DD def testESRIWKT(self): self.map.setWKTProjection('ESRI::PROJCS["Pulkovo_1995_GK_Zone_2",GEOGCS["GCS_Pulkovo_1995",DATUM["D_Pulkovo_1995",SPHEROID["Krasovsky_1940",6378245,298.3]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",2500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",9],PARAMETER["Scale_Factor",1],PARAMETER["Latitude_Of_Origin",0],UNIT["Meter",1]]') proj4 = self.map.getProjection() assert proj4.find( '+proj=tmerc' ) != -1 assert proj4.find( '+ellps=krass' ) != -1 assert (mapscript.projectionObj(proj4)).getUnits() != mapscript.MS_DD def testWellKnownGEOGCS(self): self.map.setWKTProjection('WGS84') proj4 = self.map.getProjection() assert proj4.find( '+proj=longlat' ) != -1, proj4 assert proj4.find( '+ellps=WGS84' ) != -1, proj4 assert (mapscript.projectionObj(proj4)).getUnits() != mapscript.MS_METERS # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/cases/hashtest.py0000644002461700001440000001236312261257215023301 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript tests of hashTableObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/hashtest.py -v # # =========================================================================== import os, sys import unittest # the testing module helps us import the pre-installed mapscript from testing import mapscript, MapTestCase # =========================================================================== # Base class for hashtable tests. Derived classes use these tests, but # defined different values for self.table. class HashTableBaseTestCase: keys = ['key1', 'key2', 'key3', 'key4'] values = ['value1', 'value2', 'value3', 'value4'] def testUseNonExistentKey(self): assert self.table.get('bogus') == None def testUseNonExistentKeyWithDefault(self): assert self.table.get('bogus', 'default') == 'default' def testGetValue(self): for key, value in zip(self.keys, self.values): assert self.table.get(key) == value assert self.table.get(key.upper()) == value assert self.table.get(key.capitalize()) == value def testGetValueWithDefault(self): for key, value in zip(self.keys, self.values): assert self.table.get(key, 'foo') == value assert self.table.get(key.upper(), 'foo') == value assert self.table.get(key.capitalize(), 'foo') == value def testClear(self): self.table.clear() for key in self.keys: assert self.table.get(key) == None def testRemoveItem(self): key = self.keys[0] self.table.remove(key) assert self.table.get(key) == None def testNextKey(self): key = self.table.nextKey() assert key == self.keys[0], key for i in range(1, len(self.keys)): key = self.table.nextKey(key) assert key == self.keys[i], key # We're at the end, next should be None key = self.table.nextKey(key) assert key == None, key # TODO # def testKeys(self): # "get sequence of keys" # keys = self.table.keys() # assert keys == self.keys, keys # # def testValues(self): # "get sequence of values" # values = self.table.values() # assert values == self.values, values # =========================================================================== # Test begins now # =========================================================================== # HashTable test case # class HashTableTestCase(unittest.TestCase, HashTableBaseTestCase): """Tests of the MapServer HashTable object""" def setUp(self): "our fixture is a HashTable with two items" self.table = mapscript.hashTableObj() for key, value in zip(self.keys, self.values): self.table.set(key, value) def tearDown(self): self.table = None def testConstructor(self): table = mapscript.hashTableObj() tabletype = type(table) assert str(tabletype) == "", tabletype # ============================================================================== # following tests use the tests/test.map fixture class WebMetadataTestCase(MapTestCase, HashTableBaseTestCase): def setUp(self): MapTestCase.setUp(self) self.table = self.map.web.metadata def tearDown(self): MapTestCase.tearDown(self) self.table = None class LayerMetadataTestCase(WebMetadataTestCase): def setUp(self): MapTestCase.setUp(self) self.table = self.map.getLayer(1).metadata class ClassMetadataTestCase(WebMetadataTestCase): def setUp(self): MapTestCase.setUp(self) self.table = self.map.getLayer(1).getClass(0).metadata # =========================================================================== # Run the tests outside of the main suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/tests/fragments.txt0000644002461700001440000000422512261257215022533 0ustar tbonfortusersFunctional tests of mapfile fragment loading ============================================ Setup ----- Use pkg_resources to maintain sanity with setuptools develop builds >>> try: ... import pkg_resources ... msg = pkg_resources.require('mapscript') ... except: ... pass Loading a MAP string -------------------- Empty map >>> import mapscript >>> mo = mapscript.fromstring("""MAP\nNAME "test"\nEND""") >>> mo # doctest: +ELLIPSIS >>> mo.name 'test' >>> del mo With map path Read in the standard mapserver fixture, and verify quickly >>> import os >>> mapfile = os.path.abspath('../../../tests/test.map') >>> maproot = os.path.abspath("%s/.." % mapfile) >>> f = file(mapfile, 'rb') >>> mapstring = f.read() >>> f.close() >>> mapstring.startswith('MAP') True >>> mo = mapscript.fromstring(mapstring, maproot) >>> mo # doctest: +ELLIPSIS >>> mo.name 'Testing' >>> mo.numlayers 7 # Delete so next tests get a clean slate >>> del mo Without map map Massage the mapfile to use absolute paths to resources >>> absmapstr = mapstring.replace('FONTSET "', 'FONTSET "%s/' % maproot) >>> absmapstr = absmapstr.replace('SYMBOLSET "', 'SYMBOLSET "%s/' % maproot) >>> absmapstr = absmapstr.replace('DATA "', 'DATA "%s/' % maproot) >>> mo = mapscript.fromstring(absmapstr) >>> mo # doctest: +ELLIPSIS >>> mo.name 'Testing' >>> mo.numlayers 7 Layers ------ >>> lo = mapscript.fromstring("""LAYER NAME "test" TYPE POINT END""") >>> lo #doctest: +ELLIPSIS >>> lo.name 'test' >>> lo.type == mapscript.MS_LAYER_POINT True Classes ------- >>> co = mapscript.fromstring("""CLASS TITLE "test" END""") >>> co #doctest: +ELLIPSIS >>> co.title 'test' Styles ------ >>> so = mapscript.fromstring("""STYLE END""") >>> so #doctest: +ELLIPSIS mapserver-6.4.1/mapscript/python/tests/timing/0000755002461700001440000000000012261257215021270 5ustar tbonfortusersmapserver-6.4.1/mapscript/python/tests/timing/timing.map0000644002461700001440000000134312261257215023257 0ustar tbonfortusersMAP NAME "Testing" EXTENT -2 -2 2 2 IMAGETYPE PNG IMAGECOLOR 254 254 254 STATUS ON SIZE 800 800 PROJECTION "init=epsg:4326" END SYMBOL TYPE PIXMAP NAME 'home-png' IMAGE '../../../../tests/home.png' END SYMBOL TYPE PIXMAP NAME 'xmarks-png' IMAGE '../../../../tests/xmarks.png' END LAYER NAME "POLYGON" TYPE POLYGON PROJECTION "init=epsg:4326" END STATUS DEFAULT DATA "timing.shp" CLASS STYLE COLOR 0 0 204 #OUTLINECOLOR 0 0 204 END END END LAYER NAME "POINT" TYPE POINT PROJECTION "init=epsg:4326" END STATUS OFF CLASS STYLE SYMBOL 2 END END END END mapserver-6.4.1/mapscript/python/tests/timing/drawshapes.py0000644002461700001440000000550312261257215024006 0ustar tbonfortusers# $Id$ # # Timing tests of feature drawing -- map.draw vs drawing features # shape by shape. import getopt import os import sys import timeit from random import random from testing import mapscript # Get Number of shapes from the command line try: opts, args = getopt.getopt(sys.argv[1:], 'n:') except getopt.GetoptError: sys.exit(2) numshapes = 100 # default to 100 for o, a in opts: if o == '-n': numshapes = int(a) # The shapefileObj shpfile = mapscript.shapefileObj('timing.shp', mapscript.MS_SHAPEFILE_POLYGON) # Inline feature layer ilayer = mapscript.layerObj() ilayer.type = mapscript.MS_LAYER_POLYGON ilayer.setProjection('init=epsg:4326') ilayer.status = mapscript.MS_DEFAULT ilayer.connectiontype = mapscript.MS_INLINE print numshapes, "shapes" i = 0 while i < numshapes: # The shape to add is randomly generated xc = 4.0*(random() - 0.5) yc = 4.0*(random() - 0.5) r = mapscript.rectObj(xc-0.25, yc-0.25, xc+0.25, yc+0.25) s = r.toPolygon() # Add to shapefile shpfile.add(s) # Add to inline feature layer ilayer.addFeature(s) i = i + 1 del shpfile # closes up the file # Prepare the testing fixture m = mapscript.mapObj('timing.map') l = m.getLayerByName('POLYGON') l.data = os.path.join(os.getcwd(), 'timing') # Save three map images to check afterwards img = m.draw() img.save('timing.png') shpfile = mapscript.shapefileObj('timing.shp') img = m.prepareImage() for i in range(shpfile.numshapes): s = shpfile.getShape(i) s.classindex = 0 s.draw(m, l, img) img.save('timing-shapes.png') class0 = mapscript.classObj(ilayer) class0.insertStyle(l.getClass(0).getStyle(0)) img = m.prepareImage() ilayer.draw(m, img) img.save('timing-inline.png') # ========================================================================= # Test 1A: Draw all shapes at once using map.draw() print "Test 1A: draw map, all shapes at once" s = """\ img = m.draw() """ t = timeit.Timer(stmt=s, setup='from __main__ import m') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) # ========================================================================= # Test 1B: Draw shape by shape from the shapefileObj print "Test 1B: draw shapes one at a time" s = """\ img = m.prepareImage() for i in range(shpfile.numshapes): s = shpfile.getShape(i) s.classindex = 0 s.draw(m, l, img) """ t = timeit.Timer(stmt=s, setup='from __main__ import m, l, shpfile') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) # ========================================================================= # Test 1C: Draw shapes after pushing them into an inline layer print "Test 1C: draw inline layer shapes" s = """\ img = m.prepareImage() ilayer.draw(m, img) """ t = timeit.Timer(stmt=s, setup='from __main__ import m, ilayer') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) mapserver-6.4.1/mapscript/python/tests/timing/testing.py0000644002461700001440000000573512261257215023331 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript testing utilities # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Purpose of this module is to export the locally built mapscript module # prior to installation, do some name normalization that allows testing of # the so-called next generation class names, and define some classes # useful to many test cases. # # All test case modules should import mapscript from testing # # from testing import mapscript # # =========================================================================== import os import sys import distutils.util import unittest # define the path to mapserver test data TESTS_PATH = '../../tests' TESTMAPFILE = os.path.join(TESTS_PATH, 'test.map') XMARKS_IMAGE = os.path.join(TESTS_PATH, 'xmarks.png') TEST_IMAGE = os.path.join(TESTS_PATH, 'test.png') # Put local build directory on head of python path platformdir = '-'.join((distutils.util.get_platform(), '.'.join(map(str, sys.version_info[0:2])))) sys.path.insert(0, os.path.join('build', 'lib.' + platformdir)) # import mapscript from the local build directory import mapscript # normalize names, allows testing of module that uses the experimental # next generation names classnames = [ 'mapObj', 'layerObj', 'classObj', 'styleObj', 'shapeObj', 'lineObj', 'pointObj', 'rectObj', 'outputFormatObj', 'symbolObj', 'symbolSetObj', 'colorObj', 'imageObj', 'shapefileObj', 'projectionObj', 'fontSetObj', 'hashTableObj' ] for name in classnames: try: new_name = name.replace('Obj', '') new_name = new_name.capitalize() new_object = getattr(mapscript, new_name) setattr(mapscript, name, new_object) except AttributeError: pass mapserver-6.4.1/mapscript/python/tests/timing/clonemaps.py0000644002461700001440000000375112261257215023631 0ustar tbonfortusers# $Id$ # # Timing tests of mapfile parsing vs map cloning import os from shutil import copyfile import timeit from testing import mapscript from testing import TESTMAPFILE # =========================================================================== # Test 1A: New maps from mapfile # # reloading the mapfile each time print "Test 1A: reloading maps from mapfile" s = """\ m = mapscript.mapObj(TESTMAPFILE) """ t = timeit.Timer(stmt=s, setup='from __main__ import mapscript, TESTMAPFILE') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) # =========================================================================== # Test 1B: Cloning # # Cloning instead of reloading print "Test 1B: cloning maps instead of reloading" m = mapscript.mapObj(TESTMAPFILE) s = """\ c = m.clone() """ t = timeit.Timer(stmt=s, setup='from __main__ import m') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) # =========================================================================== # Test 2: Add 20 dups of the POLYGON layer to see how results scale timing_map = mapscript.mapObj(TESTMAPFILE) polygon_layer = timing_map.getLayerByName('POLYGON') # duplicate POLYGON layer 20 times for i in range(20): timing_map.insertLayer(polygon_layer) assert timing_map.numlayers == 24 TIMINGMAPFILE = os.path.join(os.getcwd(), 'timing.map') timing_map.save(TIMINGMAPFILE) copyfile('../../tests/fonts.txt', os.path.join(os.getcwd(), 'fonts.txt')) copyfile('../../tests/symbols.txt', os.path.join(os.getcwd(), 'symbols.txt')) # Test 2A: reloading mapfile print "Test 2A: reloading inflated mapfile" s = """\ m = mapscript.mapObj(TIMINGMAPFILE) """ t = timeit.Timer(stmt=s, setup='from __main__ import mapscript, TIMINGMAPFILE') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) print "Test 2B: cloning inflated mapfile" m = mapscript.mapObj(TIMINGMAPFILE) s = """\ c = m.clone() """ t = timeit.Timer(stmt=s, setup='from __main__ import m') print "%.2f usec/pass" % (1000000 * t.timeit(number=100)/100) mapserver-6.4.1/mapscript/python/tests/rundoctests.dist0000755002461700001440000000011612261257215023244 0ustar tbonfortusers#!/bin/sh #export PYTHONPATH="YOUR_DEV_PYTHON_PATH" python runalldoctests.py mapserver-6.4.1/mapscript/python/tests/runtests.py0000644002461700001440000001246112261257215022246 0ustar tbonfortusers# $Id$ # # Project: MapServer # Purpose: Comprehensive xUnit style Python mapscript test suite # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # 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 or substantial portions of the 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. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/runtests.py -v # # =========================================================================== import unittest # Import test cases import cases from cases.recttest import RectObjTestCase from cases.hashtest import HashTableTestCase, WebMetadataTestCase from cases.hashtest import LayerMetadataTestCase, ClassMetadataTestCase from cases.owstest import OWSRequestTestCase from cases.clonetest import MapCloningTestCase from cases.imagetest import ImageObjTestCase, ImageWriteTestCase from cases.imagetest import SaveToStringTestCase from cases.maptest import MapConstructorTestCase from cases.maptest import MapLayersTestCase from cases.maptest import MapExtentTestCase from cases.maptest import MapExceptionTestCase from cases.maptest import EmptyMapExceptionTestCase from cases.maptest import MapMetaDataTestCase from cases.maptest import MapSizeTestCase from cases.layertest import LayerConstructorTestCase from cases.layertest import LayerExtentTestCase from cases.layertest import LayerRasterProcessingTestCase from cases.layertest import LayerTestCase from cases.layertest import RemoveLayerTestCase from cases.zoomtest import ZoomPointTestCase from cases.zoomtest import ZoomRectangleTestCase from cases.zoomtest import ZoomScaleTestCase from cases.linetest import LineObjTestCase from cases.shapetest import ShapePointTestCase from cases.pointtest import PointObjTestCase from cases.shapetest import InlineFeatureTestCase from cases.styletest import DrawProgrammedStylesTestCase from cases.styletest import NewStylesTestCase from cases.styletest import BrushCachingTestCase from cases.colortest import ColorObjTestCase from cases.symboltest import SymbolTestCase from cases.symboltest import MapSymbolTestCase from cases.symbolsettest import SymbolSetTestCase from cases.symbolsettest import MapSymbolSetTestCase from cases.outputformattest import OutputFormatTestCase from cases.outputformattest import MapOutputFormatTestCase from cases.labeltest import LabelCacheMemberTestCase from cases.resultcachetest import ResultCacheTestCase from cases.resultcachetest import PointQueryResultsTestCase from cases.resultcachetest import DumpAndLoadTestCase # Create a test suite suite = unittest.TestSuite() # Add tests to the suite suite.addTests([RectObjTestCase]) suite.addTests([HashTableTestCase, WebMetadataTestCase, LayerMetadataTestCase, ClassMetadataTestCase]) suite.addTests([MapCloningTestCase]) suite.addTests([OWSRequestTestCase]) suite.addTests([ImageObjTestCase, ImageWriteTestCase, SaveToStringTestCase]) suite.addTests([MapConstructorTestCase, MapLayersTestCase, MapExtentTestCase, MapExceptionTestCase, EmptyMapExceptionTestCase, MapMetaDataTestCase]) suite.addTests([LayerConstructorTestCase, LayerExtentTestCase, LayerRasterProcessingTestCase, RemoveLayerTestCase]) suite.addTests([LineObjTestCase, ShapePointTestCase, PointObjTestCase, InlineFeatureTestCase]) suite.addTests([DrawProgrammedStylesTestCase, NewStylesTestCase, BrushCachingTestCase, ColorObjTestCase]) suite.addTests([SymbolTestCase, MapSymbolTestCase]) suite.addTests([SymbolSetTestCase, MapSymbolSetTestCase]) suite.addTests([ZoomPointTestCase, ZoomRectangleTestCase, ZoomScaleTestCase]) suite.addTests([OutputFormatTestCase, MapOutputFormatTestCase]) suite.addTest(LabelCacheMemberTestCase) suite.addTests([ResultCacheTestCase, PointQueryResultsTestCase, DumpAndLoadTestCase]) # ============================================================================ # If module is run as a script, execute every test case in the suite if __name__ == '__main__': unittest.main() mapserver-6.4.1/mapscript/python/setup.py0000644002461700001440000002115712261257215020357 0ustar tbonfortusers# $Id$ # # setup.py file for MapScript # # BUILD # python setup.py build # # INSTALL (usually as root) # python setup.py install # # DEVELOP (build and run in place) # python setup.py develop import sys, os HAVE_SETUPTOOLS = False try: from setuptools import setup from setuptools import Extension HAVE_SETUPTOOLS = True except ImportError: from distutils.core import setup, Extension from distutils import sysconfig from distutils.command.build_ext import build_ext from distutils.ccompiler import get_default_compiler from distutils.sysconfig import get_python_inc try: import subprocess except ImportError: import popen2 # # # Function needed to make unique lists. def unique(list): ret_list = [] dict = {} for item in list: if not dict.has_key(item): dict[item] = '' ret_list.append( item ) return ret_list # --------------------------------------------------------------------------- # Default build options # (may be overriden with setup.cfg or command line switches). # --------------------------------------------------------------------------- include_dirs = ['../..'] library_dirs = ['../../.libs'] libraries = ['mapserver'] extra_link_args = [] extra_compile_args = [] # might need to tweak for Python 2.4 on OSX to be these #extra_compile_args = ['-g', '-arch', 'i386', '-isysroot','/'] save_init_posix = sysconfig._init_posix def ms_init_posix(): save_init_posix() if 'LDCXXSHARED' in sysconfig._config_vars: sysconfig._config_vars['LDSHARED'] = sysconfig._config_vars['LDCXXSHARED'] sysconfig._init_posix = ms_init_posix def read_mapscriptvars(): # Should be created by the mapserver build process. mapscriptvars = "../../mapscriptvars" try: fp = open(mapscriptvars, "r") except IOError, e: raise IOError, '%s. %s' % (e, "Has MapServer been made?") output = {} install_dir = fp.readline().strip() defines = fp.readline().strip() includes = fp.readline().strip() libraries = fp.readline().strip() extra_libs = fp.readline().strip() version = fp.readline().strip() if version: version = version.split()[2] version = version.replace('#','') version = version.replace('"','') output['version'] = version output['libs'] = libraries output['extra_libs'] = extra_libs output['defines'] = defines output['includes'] = includes fp.close() # print output['libs'] # sys.exit(1) return output def get_config(option, config='mapserver-config'): v = read_mapscriptvars() if sys.platform == 'win32': v = read_mapscriptvars() return v[option] command = config + " --%s" % option try: subprocess command, args = command.split()[0], command.split()[1] p = subprocess.Popen([command, args], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) r = child_stdout.read().strip() except NameError: p = popen2.popen3(command) r = p[0].readline().strip() if not r: raise Warning(p[2].readline()) return r class ms_ext(build_ext): MAPSERVER_CONFIG = 'mapserver-config' user_options = build_ext.user_options[:] user_options.extend([ ('mapserver-config=', None, "The name of the mapserver-config binary and/or a full path to it"), ]) def initialize_options(self): print "LD_RUN_PATH set" os.environ["LD_RUN_PATH"] = os.getcwd()+"/../../.libs" build_ext.initialize_options(self) self.gdaldir = None self.mapserver_config = self.MAPSERVER_CONFIG def get_compiler(self): return self.compiler or get_default_compiler() def get_mapserver_config(self, option): return get_config(option, config =self.mapserver_config) def finalize_options(self): if self.include_dirs is None: self.include_dirs = include_dirs includes = self.get_mapserver_config('includes') includes = includes.split() for item in includes: if item[:2] == '-I' or item[:2] == '/I': if item[2:] not in include_dirs: self.include_dirs.append( item[2:] ) if self.library_dirs is None: self.library_dirs = library_dirs libs = self.get_mapserver_config('libs') self.library_dirs = self.library_dirs + [x[2:] for x in libs.split() if x[:2] == "-L"] # silly stuff to deal with setuptools doing things # like -D-DMYDEFINE defs = self.get_mapserver_config('defines') self.define = [x[2:] for x in defs.split() if x[:2] == "-D"] self.define = ','.join(self.define) ex_next = False libs = libs.split() for x in libs: if ex_next: extra_link_args.append(x) ex_next = False elif x[:2] == '-l': libraries.append( x[2:] ) elif x[-4:] == '.lib' or x[-4:] == '.LIB': dir, lib = os.path.split(x) libraries.append( lib[:-4] ) if len(dir) > 0: self.library_dirs.append( dir ) elif x[-2:] == '.a': extra_link_args.append(x) elif x[:10] == '-framework': extra_link_args.append(x) ex_next = True elif x[:2] == '-F': extra_link_args.append(x) # don't forget to add mapserver lib self.libraries = unique(libraries) + ['mapserver',] if self.get_compiler() == 'msvc': for lib in self.libraries: if lib == 'mapserver': self.libraries.remove(lib) self.libraries.append('mapserver_i') self.libraries.append('gd') self.libraries = unique(self.libraries) build_ext.finalize_options(self) self.dir = os.path.abspath('../..') self.library_dirs.append(self.dir) self.include_dirs.append(self.dir) mapserver_module = Extension('_mapscript', sources=["mapscript_wrap.c", "pygdioctx/pygdioctx.c"], # define_macros = define_macros, extra_compile_args = extra_compile_args, extra_link_args = extra_link_args) mapserver_version = get_config('version', config='../../mapserver-config') author = "Steve Lime" author_email = "steve.lime@dnr.state.mn.us" maintainer = "Howard Butler" maintainer_email = "hobu.inc@gmail.com" description = "MapServer Python MapScript bindings" license = "MIT" url="http://www.mapserver.org" name = "MapScript" ext_modules = [mapserver_module,] py_modules = ['mapscript',] readme = file('README','rb').read() if not os.path.exists('mapscript_wrap.c') : swig_cmd = """swig -python -shadow -modern -templatereduce -fastdispatch -fvirtual -fastproxy -modernargs -castmode -dirvtable -fastinit -fastquery -noproxydel -nobuildnone %s -o mapscript_wrap.c ../mapscript.i""" os.system(swig_cmd % get_config('defines', config='../../mapserver-config')) classifiers = [ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'Intended Audience :: Science/Research', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: C', 'Programming Language :: C++', 'Topic :: Scientific/Engineering :: GIS', 'Topic :: Scientific/Engineering :: Information Analysis', ] if HAVE_SETUPTOOLS: setup( name = name, version = mapserver_version, author = author, author_email = author_email, maintainer = maintainer, maintainer_email = maintainer_email, long_description = readme, description = description, license = license, classifiers = classifiers, py_modules = py_modules, url=url, zip_safe = False, cmdclass={'build_ext':ms_ext}, ext_modules = ext_modules ) else: setup( name = name, version = mapserver_version, author = author, author_email = author_email, maintainer = maintainer, maintainer_email = maintainer_email, long_description = readme, description = description, license = license, classifiers = classifiers, py_modules = py_modules, url=url, cmdclass={'build_ext':ms_ext}, ext_modules = ext_modules ) mapserver-6.4.1/mapscript/python/setup.cfg0000644002461700001440000000025112261257215020456 0ustar tbonfortusers# You can override default build options here [build_ext] #include_dirs = ../../ #library_dirs = ../../ libraries = mapserver mapserver_config=../../mapserver-config mapserver-6.4.1/mapscript/perl/0000755002461700001440000000000012261257215016260 5ustar tbonfortusersmapserver-6.4.1/mapscript/perl/.gitignore0000644002461700001440000000007512261257215020252 0ustar tbonfortusersblib/* mapscript.bs mapscript.pm mapscript_wrap.c pm_to_blib mapserver-6.4.1/mapscript/perl/plextend.i0000644002461700001440000000115712261257215020261 0ustar tbonfortusers/****************************************************************************** * * Project: MapServer * Purpose: Perl-specific extensions to MapScript objects * Author: SDL based on Sean's Python conventions * ****************************************************************************** * * Perl-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGPERL is defined (via 'swig -perl5 ...'). * *****************************************************************************/ mapserver-6.4.1/mapscript/perl/plmodule.i0000644002461700001440000001225712261257215020262 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Perl-specific enhancements to MapScript * Author: SDL based on Sean's Python conventions * ****************************************************************************** * * Perl-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGPERL is defined (via 'swig -perl5 ...'). * *****************************************************************************/ /****************************************************************************** * Simple Typemaps *****************************************************************************/ %init %{ if(msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Error initializing MapServer/Mapscript.", "msSetup()"); } %} /* Translate Perl's built-in file object to FILE * */ %typemap(in) FILE * { $1 = PerlIO_exportFILE (IoIFP (sv_2io ($input)), NULL); } /* To support imageObj::getBytes */ %typemap(out) gdBuffer { SV *mysv; mysv = sv_newmortal(); if ($1.data == NULL) sv_setpv(mysv,""); else sv_setpvn(mysv,(const char*)$1.data,$1.size); $result = newRV(mysv); sv_2mortal($result); argvi++; if( $1.owns_data ) msFree($1.data); } %typemap(out) char[ANY] { $result = newSVpvn($1, strlen($1)); argvi++; } /* =============================================================================== RFC-24 implementation follows =============================================================================== Modified constructor according to: - cache population and sync, item 3.2 - reference counter since Perl does not obey %newobject */ %allowexception; %exception layer { /* Accessing layer */ $action; MS_REFCNT_INCR(result); } %exception map { /* Accessing map */ $action; MS_REFCNT_INCR(result); } %feature("shadow") layerObj(mapObj *map) %{ sub new { my $pkg = shift; my $self = mapscriptc::new_layerObj(@_); bless $self, $pkg if defined($self); if (defined($_[0])) { # parent reference mapscript::RFC24_ADD_PARENT_REF( tied(%$self), $_[0]); } return $self; } %} %feature("shadow") getLayer(int i) %{ sub getLayer { my $layer = mapscriptc::mapObj_getLayer(@_); if (defined($layer)) { # parent reference #print "l=$layer,m=$_[0]\n"; mapscript::RFC24_ADD_PARENT_REF( tied(%$layer) , $_[0]); } return $layer; } %} %feature("shadow") getLayerByName(char* name) %{ sub getLayerByName { my $layer = mapscriptc::mapObj_getLayerByName(@_); if (defined($layer)) { # parent reference #print "l=$layer,m=$_[0]\n"; mapscript::RFC24_ADD_PARENT_REF( tied(%$layer) , $_[0]); } return $layer; } %} %feature("shadow") insertLayer %{ sub insertLayer { my $idx = mapscriptc::mapObj_insertLayer(@_); my $layer=$_[1]; # parent reference mapscript::RFC24_ADD_PARENT_REF(tied(%$layer), $_[0]); return $idx; } %} %feature("shadow") ~layerObj() %{ sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); return unless defined $self; delete $ITERATORS{$self}; mapscriptc::delete_layerObj($self); # remove parent reference mapscript::RFC24_DEL_PARENT_REF($self); } %} %feature("shadow") classObj(layerObj *layer) %{ sub new { my $pkg = shift; my $self = mapscriptc::new_classObj(@_); bless $self, $pkg if defined($self); if (defined($_[0])) { # parent reference mapscript::RFC24_ADD_PARENT_REF( tied(%$self), $_[0]); } return $self; } %} %feature("shadow") getClass(int i) %{ sub getClass { my $clazz = mapscriptc::layerObj_getClass(@_); if (defined($clazz)) { # parent reference mapscript::RFC24_ADD_PARENT_REF( tied(%$clazz) , $_[0]); } return $clazz; } %} %feature("shadow") insertClass %{ sub insertClass { my $idx = mapscriptc::layerObj_insertClass(@_); my $clazz=$_[1]; # parent reference mapscript::RFC24_ADD_PARENT_REF(tied(%$clazz), $_[0]); return $idx; } %} %feature("shadow") ~classObj() %{ sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); return unless defined $self; delete $ITERATORS{$self}; mapscriptc::delete_classObj($self); # remove parent reference mapscript::RFC24_DEL_PARENT_REF($self); } %} %perlcode %{ %PARENT_PTRS=(); sub RFC24_ADD_PARENT_REF { my ($child, $parent)=@_; $PARENT_PTRS{ $$child }=$parent; } sub RFC24_DEL_PARENT_REF { my ($child)=@_; delete $PARENT_PTRS{ $$child }; } # USE THIS function only for debugging! sub getPARENT_PTRS { return \%PARENT_PTRS; } %} mapserver-6.4.1/mapscript/perl/README0000644002461700001440000000121512261257215017137 0ustar tbonfortusersTo build type: perl Makefile.PL make make install MapScript requires Swig version 1.3+. If you must re-SWIG things use a command like: swig -perl5 -shadow -outdir . -o mapscript_wrap.c ../mapscript.i and then follow the sequence of steps to install mapscript. If you need to change the name of the mapscript module (default=mapscript) you need to: 1) edit ../mapscript.i and change the name of the swig module 2) edit Makefile.PL and edit the name 'mapscript' in the WriteMakefile subroutine call 3) edit plmodule.i and change the name 'mapscript' to whatever the new name will be throughout the file and now build as normal. mapserver-6.4.1/mapscript/perl/CMakeLists.txt0000644002461700001440000000231712261257215021023 0ustar tbonfortusersFIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(Perl REQUIRED) FIND_PACKAGE(PerlLibs REQUIRED) set(CUSTOM_PERL_SITE_ARCH_DIR ${PERL_SITEARCH} CACHE DIR "Custom installation directory for perl binary extension") INCLUDE_DIRECTORIES(${PERL_INCLUDE_PATH}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) add_definitions(${PERL_EXTRA_C_FLAGS}) SET(CMAKE_SWIG_FLAGS -shadow -w314) include_directories(${PROJECT_SOURCE_DIR}/mapscript/perl) SWIG_ADD_MODULE(perlmapscript perl5 ../mapscript.i) SWIG_LINK_LIBRARIES(perlmapscript ${PERL_LIBRARIES} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(perlmapscript PROPERTIES OUTPUT_NAME mapscript) set_target_properties(perlmapscript PROPERTIES PREFIX "") if(APPLE) set_target_properties(perlmapscript PROPERTIES SUFFIX ".bundle") endif(APPLE) get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_perlmapscript_REAL_NAME} LOCATION) set(mapscript_files ${LOC_MAPSCRIPT_LIB} ${CMAKE_CURRENT_BINARY_DIR}/mapscript.pm) install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}/auto/mapscript) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mapscript.pm DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}) mapserver-6.4.1/mapscript/perl/examples/0000755002461700001440000000000012261257215020076 5ustar tbonfortusersmapserver-6.4.1/mapscript/perl/examples/distanceToPoint.pl0000755002461700001440000000155312261257215023551 0ustar tbonfortusers#!/usr/bin/perl # # Script : distanceToPoint.pl # # Purpose: Returns distance between a shape and a point # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile, $infile_shpid, $x, $y, $distance); GetOptions("infile=s", \$infile, "infile_shpid=s", \$infile_shpid, "x=s", \$x, "y=s", \$y); if(!$infile or !$infile_shpid or !$x or !$y) { print "Usage: $0 --infile=[filename] --infile_shpid=[shpid] --x=[x] --y=[y]\n"; exit 0; } # open the first input shapefile my $inshpf = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile."; my $inshape = $inshpf->getShape($infile_shpid); my $inpt = new mapscript::pointObj($x, $y); $distance = $inshape->distanceToPoint($inpt); undef $inshpf; print "Distance between shape $infile/$infile_shpid and point $x $y is $distance\n"; mapserver-6.4.1/mapscript/perl/examples/shapeprops.pl0000755002461700001440000000155112261257215022624 0ustar tbonfortusers#!/usr/bin/perl # # Script : shapeprops.pl # # Purpose: Applies area, perimeter and centroid calculations to a shapes # in a shapefile (requires mapserver/mapscript to be built with GEOS) # # $Id$ # use strict; use warnings; use mapscript; @ARGV == 1 or die "Usage: $0 \n"; # open the shapefile my $sf = new mapscript::shapefileObj($ARGV[0], -1) or die "Unable to open shapefile $ARGV[0]: $!\n"; # loop over every shape for(my $i = 0; $i < $sf->{numshapes}; $i++) { # fetch the shape my $s = $sf->getShape($i); # calculate area my $a = $s->getArea(); # calculate length / perimeter my $l = $s->getLength(); # calculate centroid my $c = $s->getCentroid(); print <{x}, $c->{y} END # free shape undef $s; } # free shapefile undef $sf; mapserver-6.4.1/mapscript/perl/examples/distanceToShape.pl0000755002461700001440000000216212261257215023515 0ustar tbonfortusers#!/usr/bin/perl # # Script : distanceToShape.pl # # Purpose: Returns distance between two shapes # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile1, $infile1_shpid, $infile2, $infile2_shpid, $distance); GetOptions("infile1=s", \$infile1, "infile1_shpid=s", \$infile1_shpid, "infile2=s", \$infile2, "infile2_shpid=s", \$infile2_shpid); if(!$infile1 or !$infile1_shpid or !$infile2 or !$infile2_shpid) { print "Usage: $0 --infile1=[filename] --infile1_shpid=[shpid] --infile2=[filename] --infile2_shpid=[shpid]\n"; exit 0; } # open the first input shapefile my $inshpf1 = new mapscript::shapefileObj($infile1, -1) or die "Unable to open shapefile $infile1."; my $inshpf2 = new mapscript::shapefileObj($infile2, -1) or die "Unable to open shapefile $infile2."; my $inshape1 = $inshpf1->getShape($infile1_shpid); my $inshape2 = $inshpf2->getShape($infile2_shpid); $distance = $inshape1->distanceToShape($inshape2); undef $inshpf1; undef $inshpf2; print "Distance between shape $infile1/$infile1_shpid and shape $infile2/$infile2_shpid is $distance units\n"; mapserver-6.4.1/mapscript/perl/examples/RFC24.pl0000644002461700001440000000526312261257215021221 0ustar tbonfortusers#!/usr/bin/perl use mapscript; $file=$ARGV[0]; # utility sub assertNotNull { my ($o, $test) = @_; if ($o) { print $test . " PASSED\n"; } else { print $test . " FAILED\n"; } } sub dumpHash { my ($hashmap) = @_; print "Dumping hashmap: $hashmap\n"; for my $k ( keys %$hashmap ) { print "\t".$k.": ".$hashmap{$k}."\n"; } } # layerObj sub testGetLayerObj { my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); $map = undef; assertNotNull( $layer->{map} , "testGetLayerObj"); #$layer->{map}->draw()->save("/tmp/map.png"); } sub testGetLayerObjByName { my $map = new mapscript::mapObj($file); my $layer = $map->getLayerByName("POLYGON"); $map = undef; assertNotNull( $layer->{map} , "testGetLayerObjByName"); } sub testLayerObj { my $map = new mapscript::mapObj($file); my $layer = new mapscript::layerObj($map); $map = undef; assertNotNull( $layer->{map} , "testLayerObj"); } sub testInsertLayerObj { my $map = new mapscript::mapObj($file); my $layer = new mapscript::layerObj(undef); my $position = $map->insertLayer($layer); $map = undef; assertNotNull( $position == 7 , "testInsertLayerObj position"); assertNotNull( $layer->{map} , "testInsertLayerObj notnull"); } # classObj sub testGetClassObj { #dumpHash(mapscript::getPARENT_PTRS()); my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); my $clazz = $layer->getClass(0); #dumpHash(mapscript::getPARENT_PTRS()); #$clazz->{layer}->{map}->draw()->save("/tmp/map1.png"); #print "parent layer=".$clazz->{layer}."\n"; $map = undef; $layer=undef; #print "parent layer=".$clazz->{layer}."\n"; assertNotNull( $clazz->{layer} , "testGetClassObj"); #$clazz->{layer}->{map}->draw()->save("/tmp/map2.png"); #dumpHash(mapscript::getPARENT_PTRS()); } sub testClassObj { my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); my $clazz = new mapscript::classObj($layer); $map = undef; $layer=undef; assertNotNull( $clazz->{layer} , "testClassObj"); } sub testInsertClassObj { my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); my $clazz = new mapscript::classObj(undef); my $position = $layer->insertClass($clazz); $map = undef; $layer=undef; assertNotNull( $position == 2 , "testInsertClassObj position"); assertNotNull( $clazz->{layer} , "testInsertClassObj notnull"); } if ( ! $file ) { print "Usage: RFC24.pl file.map\n"; exit 1; } testGetLayerObj; testGetLayerObjByName; testLayerObj; testInsertLayerObj; testGetClassObj; testClassObj; testInsertClassObj; $hashmap=mapscript::getPARENT_PTRS(); assertNotNull( keys( %$hashmap )==0 , "checking that hashmap of parent ptrs is empty"); print "No of keys:".keys( %$hashmap )."\n"; dumpHash($hashmap); mapserver-6.4.1/mapscript/perl/examples/shpPoint2GPX.pl0000755002461700001440000000626012261257215022707 0ustar tbonfortusers#!/usr/bin/perl # # Script : shpPoint2GPX.pl # # Purpose: Converts a Point shapefile to a GPX document # as per http://www.topografix.com/gpx.asp # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; my ($infile, $outfile, $namecol); GetOptions("input=s", \$infile, "output=s", \$outfile, "namecol=s", \$namecol); if(!$infile or !$outfile or !$namecol) { print "Usage: $0 --input=[filename] --output=[filename] --namecol=[namecol]\n"; exit 0; } # open the input shapefile and dbf my $shapefile = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile: $!\n"; my $table = new XBase "$infile" or die XBase->errstr; if ($shapefile->{type} != 1) { print "input shapefile must be of type point\n"; exit 0; } # unlink and create the output GPX document unlink "$outfile.gpx"; open(GPX, ">$outfile.gpx") or die "Unable to open GPX document $outfile.gpx: $!\n"; # print the GPX header info print < $outfile.gpx Description Name Welcome to MapServer text/html 2007 http://mapserver.gis.umn.edu/License Welcome to MapServer text/html MapServer, mapscript, perl, GPX, GPS END my $shape = new mapscript::shapeObj(-1); # something to hold shapes # print each shape as a waypoint for(my $i=0; $i<$shapefile->{numshapes}; $i++) { $shapefile->get($i, $shape); for(my $j=0; $j<$shape->{numlines}; $j++) { my $part = $shape->get($j); for(my $k=0; $k<$part->{numpoints}; $k++) { my $point = $part->get($k); my %row = $table->get_record_as_hash($j) or die $table->errstr; delete $row{"_DELETED"}; print "\t{y}\" lon=\"$point->{x}\">\n"; if ($row{uc($namecol)}) { print "\t\t$row{$namecol}\n"; } # print out the dbf values as GPX extensions print "\t\t\n"; foreach my $k (keys %row) { print "\t\t\t\n"; } print "\t\t\n\t\n"; } } } # for each shape print < $shapefile->{numshapes} $shapefile->{source} END undef $shapefile; close(GPX); mapserver-6.4.1/mapscript/perl/examples/shp_in_shp.pl0000644002461700001440000000225512261257215022571 0ustar tbonfortusers#!/usr/bin/perl # # Script : shp_in_shp.pl # # Purpose: Tests whether a shape is within another shape # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile1, $infile1_shpid, $infile2, $infile2_shpid, $within); GetOptions("infile1=s", \$infile1, "infile1_shpid=s", \$infile1_shpid, "infile2=s", \$infile2, "infile2_shpid=s", \$infile2_shpid); if(!$infile1 or !$infile1_shpid or !$infile2 or !$infile2_shpid) { print "Usage: $0 --infile1=[filename] --infile1_shpid=[shpid] --infile2=[filename] --infile2_shpid=[shpid]\n"; exit 0; } # open the first input shapefile my $inshpf1 = new mapscript::shapefileObj($infile1, -1) or die "Unable to open shapefile $infile1."; my $inshpf2 = new mapscript::shapefileObj($infile2, -1) or die "Unable to open shapefile $infile2."; my $inshape1 = $inshpf1->getShape($infile1_shpid); my $inshape2 = $inshpf2->getShape($infile2_shpid); $within = $inshape1->within($inshape2); if ($within == 1) { $within = "WITHIN"; } elsif ($within == 0) { $within = "NOT WITHIN"; } undef $inshpf1; undef $inshpf2; print "Shape $infile1/$infile1_shpid is $within shape $infile2/$infile2_shpid\n"; mapserver-6.4.1/mapscript/perl/examples/thin.pl0000644002461700001440000000631112261257215021376 0ustar tbonfortusers#!/usr/bin/perl # Script : thin.pl # # Purpose: An adaption of the ArcView Avenue example script genfeat.ave. It's # basically the Douglas-Peucker generalization algorithm. # (http://mapserver.gis.umn.edu/community/scripts/thin.pl) # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile, $outfile, $tolerance); GetOptions("input=s", \$infile, "output=s", \$outfile, "tolerance=n", \$tolerance); if(!$infile or !$outfile or !$tolerance) { print "Usage: $0 --input=[filename] --output=[filename] --tolerance=[maximum distance between vertices]\n"; exit 0; } die "Tolerance must be greater than zero." unless $tolerance > 0; # initialize counters for reporting my $incount = 0; my $outcount = 0; # open the input shapefile my $inSHP = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile."; die "Cannot thin point/multipoint shapefiles." unless ($inSHP->{type} == 5 or $inSHP->{type} == 3); # create the output shapefile unlink "$outfile.shp"; unlink "$outfile.shx"; unlink "$outfile.dbf"; my $outSHP = new mapscript::shapefileObj($outfile, $inSHP->{type}) or die "Unable to create shapefile '$outfile'. $!\n"; copy("$infile.dbf", "$outfile.dbf") or die "Can't copy file $infile.dbf to $outfile.dbf: $!\n"; my $inshape = new mapscript::shapeObj(-1); # something to hold shapes for(my $i=0; $i<$inSHP->{numshapes}; $i++) { $inSHP->get($i, $inshape); my $outshape = new mapscript::shapeObj(-1); for(my $j=0; $j<$inshape->{numlines}; $j++) { my $inpart = $inshape->get($j); my $outpart = new mapscript::lineObj(); my @stack = (); $incount += $inpart->{numpoints}; my $anchor = $inpart->get(0); # save first point $outpart->add($anchor); my $aIndex = 0; my $fIndex = $inpart->{numpoints} - 1; push @stack, $fIndex; # Douglas - Peucker algorithm while(@stack) { $fIndex = $stack[$#stack]; my $fPoint = $inpart->get($fIndex); my $max = $tolerance; # comparison values my $maxIndex = 0; # process middle points for (($aIndex+1) .. ($fIndex-1)) { my $point = $inpart->get($_); #my $dist = $point->distanceToLine($anchor, $fPoint); my $dist = $point->distanceToSegment($anchor, $fPoint); if($dist >= $max) { $max = $dist; $maxIndex = $_; } } if($maxIndex > 0) { push @stack, $maxIndex; } else { $outpart->add($fPoint); $anchor = $inpart->get(pop @stack); $aIndex = $fIndex; } } # check for collapsed polygons, use original data in that case if(($outpart->{numpoints} < 4) and ($inSHP->{type} == 5)) { $outpart = $inpart; } $outcount += $outpart->{numpoints}; $outshape->add($outpart); } # for each part $outSHP->add($outshape); undef($outshape); # free memory associated with shape } # for each shape $outSHP = ''; # write the file undef $inSHP; undef $outSHP; my $reduction = ((($outcount / $incount) * 100) - 100) * -1; print < 0; # initialize counters for reporting my $incount = 0; my $outcount = 0; # open the input shapefile my $inSHP = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile."; # create the output shapefile unlink "$outfile.shp"; unlink "$outfile.shx"; unlink "$outfile.dbf"; my $outSHP = new mapscript::shapefileObj($outfile, $inSHP->{type}) or die "Unable to create shapefile '$outfile'. $!\n"; copy("$infile.dbf", "$outfile.dbf") or die "Can't copy file $infile.dbf to $outfile.dbf: $!\n"; my $inshape = new mapscript::shapeObj(-1); # something to hold shapes for(my $i=0; $i<$inSHP->{numshapes}; $i++) { $inSHP->get($i, $inshape); my $outshape = new mapscript::shapeObj(-1); print "buffering feature: $i\n"; $outshape = $inshape->buffer($buffer) or die "Unable to buffer feature #$i: $!\n"; # in native map units $outSHP->add($outshape); undef($outshape); # free memory associated with shape } # for each shape $outSHP = ''; # write the file undef $inSHP; undef $outSHP; mapserver-6.4.1/mapscript/perl/examples/dump.pl0000755002461700001440000000222512261257215021404 0ustar tbonfortusers#!/usr/bin/perl use strict; use warnings; use mapscript; use Getopt::Long; my $file; my %types = ( '1' => 'point', '3' => 'arc', '5' => 'polygon', '8' => 'multipoint' ); GetOptions("file=s", \$file); if(!$file) { print "Syntax: dump.pl --file=[filename]\n"; exit 0; } my $shapefile = new mapscript::shapefileObj($file, -1) or die "Unable to open shapefile $file"; print "Shapefile opened (type=". $types{$shapefile->{type}} .") with ". $shapefile->{numshapes} ." shape(s)\n"; my $shape = new mapscript::shapeObj(-1); for(my $i=0; $i<$shapefile->{numshapes}; $i++) { $shapefile->get($i, $shape); print "Shape $i has ". $shape->{numlines} ." part(s) - "; printf "bounds (%f,%f) (%f,%f)\n", $shape->{bounds}->{minx}, $shape->{bounds}->{miny}, $shape->{bounds}->{maxx}, $shape->{bounds}->{maxy}; for(my $j=0; $j<$shape->{numlines}; $j++) { my $part = $shape->get($j); print "Part $j has ". $part->{numpoints} ." point(s)\n"; for(my $k=0; $k<$part->{numpoints}; $k++) { my $point = $part->get($k); print "$k: ". $point->{x} .", ". $point->{y} ."\n"; } } } mapserver-6.4.1/mapscript/perl/examples/wxs.pl0000755002461700001440000000715512261257215021267 0ustar tbonfortusers#!/usr/bin/perl ############################################################################ # $Id: $ # # Project: MapServer # Purpose: MapScript WxS example # Author: Tom Kralidis (tomkralidis@hotmail.com) # ############################################################################## # Copyright (c) 2007, Tom Kralidis # # 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. ############################################################################/ use CGI::Carp qw(fatalsToBrowser); use mapscript; use strict; use warnings; use XML::LibXSLT; use XML::LibXML; my $dispatch; # uber-trivial XSLT document, as a file my $xsltfile = "/tmp/foo.xslt"; # here's the actual document inline for # testing save and alter $xsltFile above =comment my $xsltstring = < <xsl:value-of select="wfs:Title"/> =cut my $mapfile = "/tmp/config.map"; # init OWSRequest object my $req = new mapscript::OWSRequest(); # pick up CGI paramters passed $req->loadParams(); # init mapfile my $map = new mapscript::mapObj($mapfile); # if this is a WFS GetCapabilities request, then intercept # what is normally returned, process with an XSLT document # and then return that to the client if ($req->getValueByName('REQUEST') eq "GetCapabilities" && $req->getValueByName('SERVICE') eq "WFS") { # push STDOUT to a buffer and run the incoming request my $io = mapscript::msIO_installStdoutToBuffer(); $dispatch = $map->OWSDispatch($req); # at this point, the client's request is sent # pull out the HTTP headers my $ct = mapscript::msIO_stripStdoutBufferContentType(); # and then pick up the actual content of the response my $content = mapscript::msIO_getStdoutBufferString(); my $xml = XML::LibXML->new(); my $xslt = XML::LibXSLT->new(); # load XML content my $source = $xml->parse_string($content); # load XSLT document my $style_doc = $xml->parse_file($xsltfile); my $stylesheet = $xslt->parse_stylesheet($style_doc); # invoke the XSLT transformation my $results = $stylesheet->transform($source); # print out the result (header + content) print "Content-type: $ct\n\n"; print $stylesheet->output_string($results); } # else process as normal else { $dispatch = $map->OWSDispatch($req); } mapserver-6.4.1/mapscript/perl/examples/shpinfo.pl0000755002461700001440000000230412261257215022103 0ustar tbonfortusers#!/usr/bin/perl use strict; use warnings; use XBase; use mapscript; use Getopt::Long; my $file; my %types = ( '1' => 'point', '3' => 'arc', '5' => 'polygon', '8' => 'multipoint' ); GetOptions("file=s", \$file); if(!$file) { print "Syntax: shpinfo.pl --file=[filename]\n"; exit 0; } my $shapefile = new mapscript::shapefileObj($file, -1) or die "Unable to open shapefile $file."; print "Shapefile $file:\n\n"; print "\ttype: ". $types{$shapefile->{type}} ."\n"; print "\tnumber of features: ". $shapefile->{numshapes} ."\n"; printf "\tbounds: (%f,%f) (%f,%f)\n", $shapefile->{bounds}->{minx}, $shapefile->{bounds}->{miny}, $shapefile->{bounds}->{maxx}, $shapefile->{bounds}->{maxy}; my $table = new XBase $file.'.dbf' or die XBase->errstr; print "\nXbase table $file.dbf:\n\n"; print "\tnumber of records: ". ($table->last_record+1) ."\n"; print "\tnumber of fields: ". ($table->last_field+1) ."\n\n"; print "\tName Type Length Decimals\n"; print "\t---------------- ---- ------ --------\n"; foreach ($table->field_names) { printf "\t%-16s %4s %6d %8d\n", $_, $table->field_type($_), $table->field_length($_), $table->field_decimal($_) } mapserver-6.4.1/mapscript/php/0000755002461700001440000000000012261257215016105 5ustar tbonfortusersmapserver-6.4.1/mapscript/php/label.c0000644002461700001440000007113712261257215017341 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_label; zend_object_handlers mapscript_label_object_handlers; ZEND_BEGIN_ARG_INFO_EX(label___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_setBinding_args, 0, 0, 2) ZEND_ARG_INFO(0, labelBinding) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_getBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, labelBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_removeBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, labelBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_getStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_insertStyle_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_removeStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_moveStyleUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_moveStyleDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_deleteStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_setExpression_args, 0, 0, 1) ZEND_ARG_INFO(0, expression) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_setText_args, 0, 0, 1) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() /* {{{ proto void __construct() Create a new label instance. */ PHP_METHOD(labelObj, __construct) { php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if ((php_label->label = labelObj_new()) == NULL) { mapscript_throw_exception("Unable to construct labelObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(labelObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("font", php_label->label->font) else IF_GET_STRING("encoding", php_label->label->encoding) else IF_GET_LONG("type", php_label->label->type) else IF_GET_LONG("shadowsizex", php_label->label->shadowsizex) else IF_GET_LONG("shadowsizey", php_label->label->shadowsizey) else IF_GET_DOUBLE("size", php_label->label->size) else IF_GET_DOUBLE("minsize", php_label->label->minsize) else IF_GET_DOUBLE("maxsize", php_label->label->maxsize) else IF_GET_DOUBLE("minscaledenom", php_label->label->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_label->label->maxscaledenom) else IF_GET_LONG("position", php_label->label->position) else IF_GET_LONG("offsetx", php_label->label->offsetx) else IF_GET_LONG("offsety", php_label->label->offsety) else IF_GET_DOUBLE("angle", php_label->label->angle) else IF_GET_LONG("anglemode", php_label->label->anglemode) else IF_GET_LONG("buffer", php_label->label->buffer) else IF_GET_LONG("antialias", php_label->label->antialias) else IF_GET_LONG("wrap", php_label->label->wrap) else IF_GET_LONG("minfeaturesize", php_label->label->minfeaturesize) else IF_GET_LONG("autominfeaturesize", php_label->label->autominfeaturesize) else IF_GET_LONG("repeatdistance", php_label->label->repeatdistance) else IF_GET_LONG("numstyles", php_label->label->numstyles) else IF_GET_LONG("mindistance", php_label->label->mindistance) else IF_GET_LONG("partials", php_label->label->partials) else IF_GET_LONG("force", php_label->label->force) else IF_GET_LONG("outlinewidth", php_label->label->outlinewidth) else IF_GET_LONG("align", php_label->label->align) else IF_GET_LONG("maxlength", php_label->label->maxlength) else IF_GET_LONG("minlength", php_label->label->minlength) else IF_GET_LONG("maxoverlapangle", php_label->label->maxoverlapangle) else IF_GET_LONG("priority", php_label->label->priority) else IF_GET_OBJECT("color", mapscript_ce_color, php_label->color, &php_label->label->color) else IF_GET_OBJECT("leader", mapscript_ce_labelleader, php_label->leader, &php_label->label->leader) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_label->outlinecolor, &php_label->label->outlinecolor) else IF_GET_OBJECT("shadowcolor", mapscript_ce_color, php_label->shadowcolor, &php_label->label->shadowcolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(labelObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("font", php_label->label->font, value) else IF_SET_STRING("encoding", php_label->label->encoding, value) else IF_SET_LONG("type", php_label->label->type, value) else IF_SET_LONG("shadowsizex", php_label->label->shadowsizex, value) else IF_SET_LONG("shadowsizey", php_label->label->shadowsizey, value) else IF_SET_DOUBLE("size", php_label->label->size, value) else IF_SET_DOUBLE("minsize", php_label->label->minsize, value) else IF_SET_DOUBLE("maxsize", php_label->label->maxsize, value) else IF_SET_LONG("position", php_label->label->position, value) else IF_SET_LONG("offsetx", php_label->label->offsetx, value) else IF_SET_LONG("offsety", php_label->label->offsety, value) else IF_SET_DOUBLE("angle", php_label->label->angle, value) else IF_SET_LONG("anglemode", php_label->label->anglemode, value) else IF_SET_LONG("buffer", php_label->label->buffer, value) else IF_SET_LONG("antialias", php_label->label->antialias, value) else IF_SET_BYTE("wrap", php_label->label->wrap, value) else IF_SET_LONG("minfeaturesize", php_label->label->minfeaturesize, value) else IF_SET_LONG("autominfeaturesize", php_label->label->autominfeaturesize, value) else IF_SET_LONG("repeatdistance", php_label->label->repeatdistance, value) else IF_SET_LONG("mindistance", php_label->label->mindistance, value) else IF_SET_LONG("partials", php_label->label->partials, value) else IF_SET_LONG("force", php_label->label->force, value) else IF_SET_LONG("outlinewidth", php_label->label->outlinewidth, value) else IF_SET_LONG("align", php_label->label->align, value) else IF_SET_LONG("maxlength", php_label->label->maxlength, value) else IF_SET_LONG("minlength", php_label->label->minlength, value) else IF_SET_LONG("maxoverlapangle", php_label->label->maxoverlapangle, value) else IF_SET_LONG("priority", php_label->label->priority, value) else IF_SET_DOUBLE("maxscaledenom", php_label->label->maxscaledenom, value) else IF_SET_DOUBLE("minscaledenom", php_label->label->minscaledenom, value) else if ( (STRING_EQUAL("color", property)) || (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("leader", property)) || (STRING_EQUAL("shadowcolor", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if (STRING_EQUAL("numstyles", property)) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int label.updateFromString(string snippet) Update a label from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(labelObj, updateFromString) { zval *zobj = getThis(); char *snippet; long snippet_len = 0; int status = MS_FAILURE; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = labelObj_updateFromString(php_label->label, snippet)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the label object to string. */ PHP_METHOD(labelObj, convertToString) { zval *zobj = getThis(); php_label_object *php_label; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = labelObj_convertToString(php_label->label); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int label.setbinding(const bindingid, string value) Set the attribute binding for a specfiled label property. Returns MS_SUCCESS on success. */ PHP_METHOD(labelObj, setBinding) { zval *zobj = getThis(); char *value; long value_len = 0; long bindingId; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &bindingId, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (bindingId < 0 || bindingId > MS_LABEL_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if (!value || strlen(value) <= 0) { mapscript_throw_exception("Invalid binding value." TSRMLS_CC); return; } if(php_label->label->bindings[bindingId].item) { msFree(php_label->label->bindings[bindingId].item); php_label->label->bindings[bindingId].index = -1; php_label->label->numbindings--; } php_label->label->bindings[bindingId].item = strdup(value); php_label->label->numbindings++; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int label.getbinding(const bindingid) Get the value of a attribute binding for a specfiled label property. Returns the string value if exist, else null. */ PHP_METHOD(labelObj, getBinding) { zval *zobj = getThis(); long bindingId; char *value = NULL; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (bindingId < 0 || bindingId > MS_LABEL_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if( (value = php_label->label->bindings[bindingId].item) != NULL) { RETURN_STRING(value, 1); } RETURN_NULL(); } /* }}} */ /* {{{ proto int label.removebinding(const bindingid) Remove attribute binding for a specfiled label property. Returns MS_SUCCESS on success. */ PHP_METHOD(labelObj, removeBinding) { zval *zobj = getThis(); long bindingId; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (bindingId < 0 || bindingId > MS_LABEL_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if(php_label->label->bindings[bindingId].item) { msFree(php_label->label->bindings[bindingId].item); php_label->label->bindings[bindingId].item = NULL; php_label->label->bindings[bindingId].index = -1; php_label->label->numbindings--; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int getstyle(int index) return the style object. */ PHP_METHOD(labelObj, getStyle) { long index; zval *zobj = getThis(); php_label_object *php_label; styleObj *style = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (index < 0 || index >= php_label->label->numstyles) { mapscript_throw_exception("Invalid style index." TSRMLS_CC); return; } style = php_label->label->styles[index]; MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int insertStyle(styleObj style) return MS_SUCCESS or MS_FAILURE. */ PHP_METHOD(labelObj, insertStyle) { zval *zobj = getThis(); zval *zstyle = NULL; long index = -1; php_label_object *php_label; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zstyle, mapscript_ce_style, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_style = (php_style_object *) zend_object_store_get_object(zstyle TSRMLS_CC); RETURN_LONG(msInsertLabelStyle(php_label->label, php_style->style, index)); } /* }}} */ /* {{{ proto styleObj removeStyle(int index) return the styleObj removed. */ PHP_METHOD(labelObj, removeStyle) { zval *zobj = getThis(); long index; styleObj *style; php_label_object *php_label; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); style = msRemoveLabelStyle(php_label->label, index); /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int moveStyleUp(int index) */ PHP_METHOD(labelObj, moveStyleUp) { long index; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = labelObj_moveStyleUp(php_label->label, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int moveStyleDown(int index) */ PHP_METHOD(labelObj, moveStyleDown) { long index; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = labelObj_moveStyleDown(php_label->label, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int deleteStyle(int index) */ PHP_METHOD(labelObj, deleteStyle) { long index; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = labelObj_deleteStyle(php_label->label, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int label.free() Free the object */ PHP_METHOD(labelObj, free) { zval *zobj = getThis(); php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_label->color); MAPSCRIPT_DELREF(php_label->outlinecolor); MAPSCRIPT_DELREF(php_label->shadowcolor); } /* }}} */ /* {{{ proto int setExpression(string exression) Set the expression string for a label object. */ PHP_METHOD(labelObj, setExpression) { char *expression; long expression_len; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &expression, &expression_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = labelObj_setExpression(php_label->label, expression); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getExpressionString() Get the expression string for a label object. */ PHP_METHOD(labelObj, getExpressionString) { zval *zobj = getThis(); php_label_object *php_label; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = labelObj_getExpressionString(php_label->label); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setText(string text) Set the text string for a label object. */ PHP_METHOD(labelObj, setText) { char *text; long text_len; zval *zobj = getThis(); php_label_object *php_label; php_layer_object *php_layer; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(php_label->parent.val TSRMLS_CC); status = labelObj_setText(php_label->label, php_layer->layer, text); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getTextString() Get the text string for a label object. */ PHP_METHOD(labelObj, getTextString) { zval *zobj = getThis(); php_label_object *php_label; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = labelObj_getTextString(php_label->label); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ zend_function_entry label_functions[] = { PHP_ME(labelObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelObj, __get, label___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, __set, label___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(labelObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, updateFromString, label_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, setBinding, label_setBinding_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getBinding, label_getBinding_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, removeBinding, label_removeBinding_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getStyle, label_getStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, insertStyle, label_insertStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, removeStyle, label_removeStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, moveStyleUp, label_moveStyleUp_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, moveStyleDown, label_moveStyleDown_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, deleteStyle, label_deleteStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, setExpression, label_setExpression_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getExpressionString, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, setText, label_setText_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getTextString, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_label(labelObj *label, parent_object parent, zval *return_value TSRMLS_DC) { php_label_object * php_label; object_init_ex(return_value, mapscript_ce_label); php_label = (php_label_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_label->label = label; if (parent.val) php_label->is_ref = 1; php_label->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_label_object_destroy(void *object TSRMLS_DC) { php_label_object *php_label = (php_label_object *)object; MAPSCRIPT_FREE_OBJECT(php_label); MAPSCRIPT_FREE_PARENT(php_label->parent); MAPSCRIPT_DELREF(php_label->color); MAPSCRIPT_DELREF(php_label->outlinecolor); MAPSCRIPT_DELREF(php_label->shadowcolor); MAPSCRIPT_DELREF(php_label->leader); if (php_label->label && !php_label->is_ref) { labelObj_destroy(php_label->label); } efree(object); } static zend_object_value mapscript_label_object_new_ex(zend_class_entry *ce, php_label_object **ptr TSRMLS_DC) { zend_object_value retval; php_label_object *php_label; MAPSCRIPT_ALLOC_OBJECT(php_label, php_label_object); retval = mapscript_object_new_ex(&php_label->std, ce, &mapscript_label_object_destroy, &mapscript_label_object_handlers TSRMLS_CC); if (ptr) *ptr = php_label; php_label->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_label->parent); php_label->color = NULL; php_label->outlinecolor = NULL; php_label->shadowcolor = NULL; php_label->leader = NULL; return retval; } static zend_object_value mapscript_label_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_label_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_label_object_clone(zval *zobj TSRMLS_DC) { php_label_object *php_label_old, *php_label_new; zend_object_value new_ov; php_label_old = (php_label_object *) zend_object_store_get_object(zobj TSRMLS_CC); new_ov = mapscript_label_object_new_ex(mapscript_ce_label, &php_label_new TSRMLS_CC); zend_objects_clone_members(&php_label_new->std, new_ov, &php_label_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_label_new->label = labelObj_clone(php_label_old->label); return new_ov; } PHP_MINIT_FUNCTION(label) { zend_class_entry ce; memcpy(&mapscript_label_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_label_object_handlers.clone_obj = mapscript_label_object_clone; MAPSCRIPT_REGISTER_CLASS("labelObj", label_functions, mapscript_ce_label, mapscript_label_object_new); mapscript_ce_label->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/querymap.c0000644002461700001440000002045012261257215020115 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_querymap; ZEND_BEGIN_ARG_INFO_EX(querymap___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(querymap___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(querymap_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto querymap __construct() queryMapObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(queryMapObj, __construct) { mapscript_throw_exception("queryMapObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(queryMapObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_querymap_object *php_querymap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = (php_querymap_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("width", php_querymap->querymap->width) else IF_GET_LONG("height", php_querymap->querymap->height) else IF_GET_LONG("style", php_querymap->querymap->style) else IF_GET_LONG("status", php_querymap->querymap->status) else IF_GET_OBJECT("color", mapscript_ce_color, php_querymap->color, &php_querymap->querymap->color) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(queryMapObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_querymap_object *php_querymap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = (php_querymap_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_LONG("width", php_querymap->querymap->width, value) else IF_SET_LONG("height", php_querymap->querymap->height, value) else IF_SET_LONG("style", php_querymap->querymap->style, value) else IF_SET_LONG("status", php_querymap->querymap->status, value) else if ( (STRING_EQUAL("color", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int querymap.updateFromString(string snippet) Update a querymap from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(queryMapObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_querymap_object *php_querymap; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = (php_querymap_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = queryMapObj_updateFromString(php_querymap->querymap, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the querymap object to string. */ PHP_METHOD(queryMapObj, convertToString) { zval *zobj = getThis(); php_querymap_object *php_querymap; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = (php_querymap_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = queryMapObj_convertToString(php_querymap->querymap); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int querymap.free() Free the object */ PHP_METHOD(queryMapObj, free) { zval *zobj = getThis(); php_querymap_object *php_querymap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = (php_querymap_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_querymap->color); } /* }}} */ zend_function_entry querymap_functions[] = { PHP_ME(queryMapObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(queryMapObj, __get, querymap___get_args, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, __set, querymap___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(queryMapObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, updateFromString, querymap_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_querymap(queryMapObj *querymap, parent_object parent, zval *return_value TSRMLS_DC) { php_querymap_object * php_querymap; object_init_ex(return_value, mapscript_ce_querymap); php_querymap = (php_querymap_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_querymap->querymap = querymap; php_querymap->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_querymap_object_destroy(void *object TSRMLS_DC) { php_querymap_object *php_querymap = (php_querymap_object *)object; MAPSCRIPT_FREE_OBJECT(php_querymap); MAPSCRIPT_FREE_PARENT(php_querymap->parent); MAPSCRIPT_DELREF(php_querymap->color); /* We don't need to free the queryMapObj */ efree(object); } static zend_object_value mapscript_querymap_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_querymap_object *php_querymap; MAPSCRIPT_ALLOC_OBJECT(php_querymap, php_querymap_object); retval = mapscript_object_new(&php_querymap->std, ce, &mapscript_querymap_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_querymap->parent); php_querymap->color = NULL; return retval; } PHP_MINIT_FUNCTION(querymap) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("queryMapObj", querymap_functions, mapscript_ce_querymap, mapscript_querymap_object_new); mapscript_ce_querymap->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/web.c0000644002461700001440000002520612261257215017033 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_web; ZEND_BEGIN_ARG_INFO_EX(web___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(web___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(web_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto web __construct() webObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(webObj, __construct) { mapscript_throw_exception("webObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(webObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_web_object *php_web; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = (php_web_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("log", php_web->web->log) else IF_GET_STRING("imagepath", php_web->web->imagepath) else IF_GET_STRING("template", php_web->web->template) else IF_GET_STRING("imageurl", php_web->web->imageurl) else IF_GET_STRING("temppath", php_web->web->temppath) else IF_GET_STRING("header", php_web->web->header) else IF_GET_STRING("footer", php_web->web->footer) else IF_GET_STRING("empty", php_web->web->empty) else IF_GET_STRING("error", php_web->web->error) else IF_GET_STRING("mintemplate", php_web->web->mintemplate) else IF_GET_STRING("maxtemplate", php_web->web->maxtemplate) else IF_GET_DOUBLE("minscaledenom", php_web->web->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_web->web->maxscaledenom) else IF_GET_STRING("queryformat", php_web->web->queryformat) else IF_GET_STRING("legendformat", php_web->web->legendformat) else IF_GET_STRING("browseformat", php_web->web->browseformat) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_web->extent, &php_web->web->extent) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_web->metadata, &php_web->web->metadata) else IF_GET_OBJECT("validation", mapscript_ce_hashtable, php_web->validation, &php_web->web->validation) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(webObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_web_object *php_web; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = (php_web_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("log", php_web->web->log, value) else IF_SET_STRING("imagepath", php_web->web->imagepath, value) else IF_SET_STRING("template", php_web->web->template, value) else IF_SET_STRING("imageurl", php_web->web->imageurl, value) else IF_SET_STRING("temppath", php_web->web->temppath, value) else IF_SET_STRING("header", php_web->web->header, value) else IF_SET_STRING("footer", php_web->web->footer, value) else IF_SET_STRING("mintemplate", php_web->web->mintemplate, value) else IF_SET_STRING("maxtemplate", php_web->web->maxtemplate, value) else IF_SET_DOUBLE("minscaledenom", php_web->web->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_web->web->maxscaledenom, value) else IF_SET_STRING("queryformat", php_web->web->queryformat, value) else IF_SET_STRING("legendformat", php_web->web->legendformat, value) else IF_SET_STRING("browseformat", php_web->web->browseformat, value) else if ( (STRING_EQUAL("empty", property)) || (STRING_EQUAL("error", property)) || (STRING_EQUAL("extent", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else if ( (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("validation", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int web.updateFromString(string snippet) Update a web from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(webObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_web_object *php_web; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = (php_web_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = webObj_updateFromString(php_web->web, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the web object to string. */ PHP_METHOD(webObj, convertToString) { zval *zobj = getThis(); php_web_object *php_web; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = (php_web_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = webObj_convertToString(php_web->web); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int web.free() Free the object. */ PHP_METHOD(webObj, free) { zval *zobj = getThis(); php_web_object *php_web; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = (php_web_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_web->extent); MAPSCRIPT_DELREF(php_web->metadata); MAPSCRIPT_DELREF(php_web->validation); } /* }}} */ zend_function_entry web_functions[] = { PHP_ME(webObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(webObj, __get, web___get_args, ZEND_ACC_PUBLIC) PHP_ME(webObj, __set, web___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(webObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(webObj, updateFromString, web_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(webObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(webObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_web(webObj *web, parent_object parent, zval *return_value TSRMLS_DC) { php_web_object * php_web; object_init_ex(return_value, mapscript_ce_web); php_web = (php_web_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_web->web = web; php_web->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_web_object_destroy(void *object TSRMLS_DC) { php_web_object *php_web = (php_web_object *)object; MAPSCRIPT_FREE_OBJECT(php_web); MAPSCRIPT_FREE_PARENT(php_web->parent); MAPSCRIPT_DELREF(php_web->extent); MAPSCRIPT_DELREF(php_web->metadata); MAPSCRIPT_DELREF(php_web->validation); /* We don't need to free the webObj */ efree(object); } static zend_object_value mapscript_web_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_web_object *php_web; MAPSCRIPT_ALLOC_OBJECT(php_web, php_web_object); retval = mapscript_object_new(&php_web->std, ce, &mapscript_web_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_web->parent); php_web->extent = NULL; php_web->metadata = NULL; php_web->validation = NULL; return retval; } PHP_MINIT_FUNCTION(web) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("webObj", web_functions, mapscript_ce_web, mapscript_web_object_new); mapscript_ce_web->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/php_mapscript.c0000644002461700001440000014233012261257215021125 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000-2005, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" #include "php_mapscript_util.h" #include "php.h" #include "php_globals.h" #include "SAPI.h" #include "ext/standard/info.h" #include "ext/standard/head.h" #include "../../maperror.h" #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #else #include #endif /* All gd functions used in this extension (if they are renamed in the "main/php_compat.h" file of php source) should be added here too for compatibility reasons: when php compiles gd as a shared extention */ #if defined(HAVE_GD_BUNDLED) #undef gdImageColorExact #undef gdImageColorTransparent #undef gdImageCopy #endif #ifndef DLEXPORT #define DLEXPORT ZEND_DLEXPORT #endif //#if defined(_WIN32) && !defined(__CYGWIN__) //void ***tsrm_ls; //#endif zend_object_handlers mapscript_std_object_handlers; ZEND_BEGIN_ARG_INFO_EX(ms_newShapeObj_args, 0, 0, 1) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_shapeObjFromWkt_args, 0, 0, 1) ZEND_ARG_INFO(0, wkt) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newShapeFileObj_args, 0, 0, 2) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newMapObj_args, 0, 0, 1) ZEND_ARG_INFO(0, mapFileName) ZEND_ARG_INFO(0, newMapPath) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newMapObjFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, mapFileString) ZEND_ARG_INFO(0, newMapPath) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newLayerObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newProjectionObj_args, 0, 0, 1) ZEND_ARG_INFO(0, projString) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newStyleObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, class, classObj, 0) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newClassObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, class, classObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newSymbolObj_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_INFO(0, symbolName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newGridObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() /* {{{ proto mapObj ms_newMapObj(string mapFileName, newMapPath) Create a new mapObj instance. */ PHP_FUNCTION(ms_newMapObj) { char *filename; long filename_len = 0; char *path = NULL; long path_len = 0; mapObj *map = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename, &filename_len, &path, &path_len) == FAILURE) { return; PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); map = mapObj_new(filename, path); if (map == NULL) { mapscript_throw_mapserver_exception("Failed to open map file \"%s\", or map file error." TSRMLS_CC, filename); return; } mapscript_create_map(map, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto mapObj ms_newMapObj(string mapFileString, newMapPath) Create a new mapObj instance. */ PHP_FUNCTION(ms_newMapObjFromString) { char *string; long string_len = 0; char *path = NULL; long path_len = 0; mapObj *map = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &string, &string_len, &path, &path_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); map = mapObj_newFromString(string, path); if (map == NULL) { mapscript_throw_mapserver_exception("Error while loading map file from string." TSRMLS_CC); return; } mapscript_create_map(map, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto layerObj ms_newLayerObj(mapObj map [, layerObj layer]) Create a new layerObj instance. */ PHP_FUNCTION(ms_newLayerObj) { zval *zmap, *zlayer = NULL; layerObj *layer; int index; php_map_object *php_map; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *)zend_object_store_get_object(zmap TSRMLS_CC); if (zlayer) php_layer = (php_layer_object *)zend_object_store_get_object(zlayer TSRMLS_CC); if ((layer = layerObj_new(php_map->map)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* if a layer is passed as argument, copy the layer into the new one */ if (zlayer) { index = layer->index; msCopyLayer(layer, php_layer->layer); layer->index = index; } MAPSCRIPT_MAKE_PARENT(zmap, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto projectionObj ms_newProjectionObj(string projString) Create a new projectionObj instance. */ PHP_FUNCTION(ms_newProjectionObj) { char *projString; long projString_len = 0; projectionObj *projection = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projString, &projString_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((projection = projectionObj_new(projString)) == NULL) { mapscript_throw_mapserver_exception("Unable to construct projectionObj." TSRMLS_CC); return; } MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_projection(projection, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto rectObj ms_newRectObj() Create a new rectObj instance. */ PHP_FUNCTION(ms_newRectObj) { php_rect_object * php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_rect); php_rect = (php_rect_object *)zend_object_store_get_object(return_value TSRMLS_CC); if ((php_rect->rect = rectObj_new()) == NULL) { mapscript_throw_exception("Unable to construct rectObj." TSRMLS_CC); return; } } /* }}} */ /* {{{ proto pointObj ms_newPointObj() Create a new pointObj instance. */ PHP_FUNCTION(ms_newPointObj) { pointObj *point = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((point = pointObj_new()) == NULL) { mapscript_throw_mapserver_exception("Unable to construct pointObj." TSRMLS_CC); return; } point->x = 0; point->y = 0; #ifdef USE_POINT_Z_M point->z = 0; point->m = 0; #endif /* Return point object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* {{{ proto lineObj ms_newLineObj() Create a new lineObj instance. */ PHP_FUNCTION(ms_newLineObj) { php_line_object * php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_line); php_line = (php_line_object *)zend_object_store_get_object(return_value TSRMLS_CC); if ((php_line->line = lineObj_new()) == NULL) { mapscript_throw_exception("Unable to construct lineObj." TSRMLS_CC); return; } } /* }}} */ /* {{{ proto styleObj __construct(classObj class [, styleObj style]) Create a new styleObj instance */ PHP_FUNCTION(ms_newStyleObj) { zval *zclass, *zstyle = NULL; styleObj *style; php_class_object *php_class; php_style_object *php_style; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zclass, mapscript_ce_class, &zstyle, mapscript_ce_style) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *)zend_object_store_get_object(zclass TSRMLS_CC); if (zstyle) php_style = (php_style_object *)zend_object_store_get_object(zstyle TSRMLS_CC); if ((style = styleObj_new(php_class->class, (zstyle ? php_style->style : NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return point object */ MAPSCRIPT_MAKE_PARENT(zclass, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* {{{ proto classObj ms_newClassObj(layerObj layer [, classObj class]) Create a new class instance in the specified layer.. */ PHP_FUNCTION(ms_newClassObj) { zval *zlayer, *zclass = NULL; classObj *class; php_layer_object *php_layer; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zlayer, mapscript_ce_layer, &zclass, mapscript_ce_class) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); if (zclass) php_class = (php_class_object *) zend_object_store_get_object(zclass TSRMLS_CC); if ((class = classObj_new(php_layer->layer, (zclass ? php_class->class:NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } MAPSCRIPT_MAKE_PARENT(zlayer, NULL); mapscript_create_class(class, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int ms_newSymbolObj(mapObj map, string symbolName) Create a new symbolObj instance and return its index. */ PHP_FUNCTION(ms_newSymbolObj) { zval *zmap; char *symbolName; long symbolName_len = 0; int retval = 0; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zmap, mapscript_ce_map, &symbolName, &symbolName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *)zend_object_store_get_object(zmap TSRMLS_CC); retval = msAddNewSymbol(php_map->map, symbolName); RETURN_LONG(retval); } /* }}} */ /* {{{ proto shapeObj ms_newShapeObj(int type) Create a new shapeObj instance. */ PHP_FUNCTION(ms_newShapeObj) { php_shape_object * php_shape; long type; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_shape); php_shape = (php_shape_object *)zend_object_store_get_object(return_value TSRMLS_CC); if ((php_shape->shape = shapeObj_new(type)) == NULL) { mapscript_throw_exception("Unable to construct shapeObj." TSRMLS_CC); return; } MAKE_STD_ZVAL(php_shape->values); array_init(php_shape->values); } /* }}} */ /* {{{ proto shapeObj shapeObjFromWkt(string type) Creates new shape object from WKT string. */ PHP_FUNCTION(ms_shapeObjFromWkt) { php_shape_object * php_shape; char *wkt; long str_len = 0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &wkt, &str_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_shape); php_shape = (php_shape_object *)zend_object_store_get_object(return_value TSRMLS_CC); if ((php_shape->shape = msShapeFromWKT(wkt)) == NULL) { mapscript_throw_exception("Unable to construct shapeObj." TSRMLS_CC); return; } MAKE_STD_ZVAL(php_shape->values); array_init(php_shape->values); } /* }}} */ /* {{{ proto shapefile ms_newShapeFileObj(string filename, int type) Create a new shapeFileObj instance. */ PHP_FUNCTION(ms_newShapeFileObj) { char *filename; long filename_len = 0; long type; shapefileObj *shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); shapefile = shapefileObj_new(filename, type); if (shapefile == NULL) { mapscript_throw_mapserver_exception("Failed to open shapefile %s" TSRMLS_CC, filename); return; } mapscript_create_shapefile(shapefile, return_value TSRMLS_CC); } /* }}} */ PHP_FUNCTION(ms_newOWSRequestObj) { cgiRequestObj *request; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((request = cgirequestObj_new()) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return owsrequest object */ mapscript_create_owsrequest(request, return_value TSRMLS_CC); } /* {{{ proto gridObj ms_newGridObj(layerObj layer) Create a new intance of gridObj. */ PHP_FUNCTION(ms_newGridObj) { zval *zlayer; php_layer_object *php_layer; php_grid_object *php_grid; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); php_layer->layer->connectiontype = MS_GRATICULE; if (php_layer->layer->layerinfo != NULL) free(php_layer->layer->layerinfo); php_layer->layer->layerinfo = (graticuleObj *)malloc( sizeof( graticuleObj ) ); initGrid((graticuleObj *)php_layer->layer->layerinfo); if (php_layer->grid && (Z_TYPE_P(php_layer->grid) == IS_OBJECT)) { php_grid = (php_grid_object *) zend_object_store_get_object(php_layer->grid TSRMLS_CC); php_grid->parent.child_ptr = NULL; zend_objects_store_del_ref(php_layer->grid TSRMLS_CC); } MAKE_STD_ZVAL(php_layer->grid); MAPSCRIPT_MAKE_PARENT(zlayer, &php_layer->grid); mapscript_create_grid((graticuleObj *)(php_layer->layer->layerinfo), parent, php_layer->grid TSRMLS_CC); zend_objects_store_add_ref(php_layer->grid TSRMLS_CC); *return_value = *(php_layer->grid); } /* }}} */ /* {{{ proto errorObj ms_GetErrorObj() Return the head of the MapServer errorObj list. */ PHP_FUNCTION(ms_GetErrorObj) { errorObj *error; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((error = msGetErrorObj()) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return error object */ mapscript_create_error(error, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto errorObj ms_ResetErrorList() Clear the MapServer errorObj list. */ PHP_FUNCTION(ms_ResetErrorList) { msResetErrorList(); } /* }} */ /*===================================================================== * PHP function wrappers *====================================================================*/ /************************************************************************/ /* ms_VetVersion() */ /* */ /* Returns a string with MapServer version and configuration */ /* params. */ /************************************************************************/ PHP_FUNCTION(ms_GetVersion) { PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); RETURN_STRING(msGetVersion(), 1); } /************************************************************************/ /* ms_GetVersionInt() */ /* */ /* Returns the MapServer version in int format. */ /* Given version x.y.z, returns x*0x10000+y*0x100+z */ /************************************************************************/ PHP_FUNCTION(ms_GetVersionInt) { PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); RETURN_LONG(msGetVersionInt()); } /* ==================================================================== */ /* utility functions related to msio */ /* ==================================================================== */ PHP_FUNCTION(ms_ioInstallStdoutToBuffer) { msIO_installStdoutToBuffer(); RETURN_TRUE; } PHP_FUNCTION(ms_ioResetHandlers) { msIO_resetHandlers(); RETURN_TRUE; } PHP_FUNCTION(ms_ioInstallStdinFromBuffer) { msIO_installStdinFromBuffer(); RETURN_TRUE; } PHP_FUNCTION(ms_ioGetStdoutBufferString) { char *buffer; msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; if(ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { php_error(E_ERROR, "Can't identify msIO buffer"); RETURN_FALSE; } buf = (msIOBuffer *) ctx->cbData; /* write one zero byte and backtrack if it isn't already there */ if( buf->data_len == 0 || buf->data[buf->data_offset] != '\0' ) { msIO_bufferWrite( buf, "", 1 ); buf->data_offset--; } buffer = (char *) (buf->data); RETURN_STRINGL(buffer, buf->data_offset, 1); } typedef struct { unsigned char *data; int size; int owns_data; } gdBuffer; PHP_FUNCTION(ms_ioGetStdoutBufferBytes) { msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; gdBuffer gdBuf; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { php_error(E_ERROR, "Can't identify msIO buffer"); RETURN_FALSE; } buf = (msIOBuffer *) ctx->cbData; gdBuf.data = buf->data; gdBuf.size = buf->data_offset; gdBuf.owns_data = MS_FALSE; /* we are seizing ownership of the buffer contents */ buf->data_offset = 0; buf->data_len = 0; buf->data = NULL; php_write(gdBuf.data, gdBuf.size TSRMLS_CC); /* return the gdBuf.size, which is the "really used length" of the msIOBuffer */ RETURN_LONG(gdBuf.size); } PHP_FUNCTION(ms_ioStripStdoutBufferContentType) { const char *buf = NULL; buf = msIO_stripStdoutBufferContentType(); if (buf) { RETURN_STRING((char *)buf, 1); } else { RETURN_FALSE; } } PHP_FUNCTION(ms_ioStripStdoutBufferContentHeaders) { msIO_stripStdoutBufferContentHeaders(); } /* ==================================================================== */ /* utility functions */ /* ==================================================================== */ /************************************************************************/ /* void ms_getcwd */ /* */ /* This function is a copy of the */ /* vod php3_posix_getcwd(INTERNAL_FUNCTION_PARAMETERS) */ /* (./php/functions/posix.c). */ /* */ /* Since posix functions seems to not be standard in php, It has been*/ /* added here. */ /************************************************************************/ /* OS/2's gcc defines _POSIX_PATH_MAX but not PATH_MAX */ #if !defined(PATH_MAX) && defined(_POSIX_PATH_MAX) #define PATH_MAX _POSIX_PATH_MAX #endif #if !defined(PATH_MAX) && defined(MAX_PATH) #define PATH_MAX MAX_PATH #endif #if !defined(PATH_MAX) #define PATH_MAX 512 #endif PHP_FUNCTION(ms_getCwd) { char buffer[PATH_MAX]; char *p; p = getcwd(buffer, PATH_MAX); if (!p) { //php3_error(E_WARNING, "posix_getcwd() failed with '%s'", // strerror(errno)); RETURN_FALSE; } RETURN_STRING(buffer, 1); } PHP_FUNCTION(ms_getPid) { RETURN_LONG(getpid()); } /************************************************************************/ /* DLEXPORT void php3_ms_getscale(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Utility function to get the scale based on the width/height */ /* of the pixmap, the georeference and the units of the data. */ /* */ /* Parameters are : */ /* */ /* - Georefernce extents (rectObj) */ /* - Width : width in pixel */ /* - Height : Height in pixel */ /* - Units of the data (int) */ /* */ /* */ /************************************************************************/ PHP_FUNCTION(ms_getScale) { zval *zgeoRefExt = NULL; long width, height,unit; double resolution; php_rect_object *php_geoRefExt; double dfScale = 0.0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ollld", &zgeoRefExt, mapscript_ce_rect, &width, &height, &unit, &resolution) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_geoRefExt = (php_rect_object *)zend_object_store_get_object(zgeoRefExt TSRMLS_CC); if (msCalculateScale(*(php_geoRefExt->rect), unit, width, height, resolution, &dfScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_DOUBLE(dfScale); } /********************************************************************** * ms_tokenizeMap() * * Preparse mapfile and return an array containg one item for each * token in the map. **********************************************************************/ /* {{{ proto array ms_tokenizeMap(string filename) Preparse mapfile and return an array containg one item for each token in the map.*/ PHP_FUNCTION(ms_tokenizeMap) { char *filename; long filename_len = 0; char **tokens; int i, numtokens=0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((tokens = msTokenizeMap(filename, &numtokens)) == NULL) { mapscript_throw_mapserver_exception("Failed tokenizing map file %s" TSRMLS_CC, filename); return; } else { if (array_init(return_value) == FAILURE) { RETURN_FALSE; } for (i=0; ilabelleader->maxdistance) else IF_GET_LONG("gridstep", php_labelleader->labelleader->gridstep) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(labelLeaderObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("maxdistance", property)) || (STRING_EQUAL("gridstep", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } zend_function_entry labelleader_functions[] = { PHP_ME(labelLeaderObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelLeaderObj, __get, labelleader___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelLeaderObj, __set, labelleader___set_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_labelleader(labelLeaderObj *labelleader, parent_object parent, zval *return_value TSRMLS_DC) { php_labelleader_object * php_labelleader; object_init_ex(return_value, mapscript_ce_labelleader); php_labelleader = (php_labelleader_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_labelleader->labelleader = labelleader; php_labelleader->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_labelleader_object_destroy(void *object TSRMLS_DC) { php_labelleader_object *php_labelleader = (php_labelleader_object *)object; MAPSCRIPT_FREE_OBJECT(php_labelleader); MAPSCRIPT_FREE_PARENT(php_labelleader->parent); /* We don't need to free the labelLeaderObj */ efree(object); } static zend_object_value mapscript_labelleader_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_labelleader_object *php_labelleader; MAPSCRIPT_ALLOC_OBJECT(php_labelleader, php_labelleader_object); retval = mapscript_object_new(&php_labelleader->std, ce, &mapscript_labelleader_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_labelleader->parent); return retval; } PHP_MINIT_FUNCTION(labelleader) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("labelLeaderObj", labelleader_functions, mapscript_ce_labelleader, mapscript_labelleader_object_new); mapscript_ce_labelleader->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/php_mapscript_util.h0000644002461700001440000002154112261257215022167 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer : Utility functions * Header - macros * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000, 2001, Daniel Morissette, DM Solutions Group Inc. * * 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 PHP_MAPSCRIPT_UTIL_H #define PHP_MAPSCRIPT_UTIL_H #include "php.h" #include "php_globals.h" #include "php_mapscript.h" #if ZEND_MODULE_API_NO < 20010901 #define TSRMLS_D void #define TSRMLS_DC #define TSRMLS_C #define TSRMLS_CC #endif /* Add pseudo refcount macros for PHP version < 5.3 */ #ifndef Z_REFCOUNT_PP #define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) #define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) #define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz)) #define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) #define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) #define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) #define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref) #define Z_REFCOUNT_P(pz) zval_refcount_p(pz) #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) #define Z_ADDREF_P(pz) zval_addref_p(pz) #define Z_DELREF_P(pz) zval_delref_p(pz) #define Z_ISREF_P(pz) zval_isref_p(pz) #define Z_SET_ISREF_P(pz) zval_set_isref_p(pz) #define Z_UNSET_ISREF_P(pz) zval_unset_isref_p(pz) #define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref) #define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc) #define Z_ADDREF(z) Z_ADDREF_P(&(z)) #define Z_DELREF(z) Z_DELREF_P(&(z)) #define Z_ISREF(z) Z_ISREF_P(&(z)) #define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z)) #define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z)) #define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref) #if defined(__GNUC__) #define zend_always_inline inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define zend_always_inline __forceinline #else #define zend_always_inline inline #endif static zend_always_inline zend_uint zval_refcount_p(zval* pz) { return pz->refcount; } static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) { return pz->refcount = rc; } static zend_always_inline zend_uint zval_addref_p(zval* pz) { return ++pz->refcount; } static zend_always_inline zend_uint zval_delref_p(zval* pz) { return --pz->refcount; } static zend_always_inline zend_bool zval_isref_p(zval* pz) { return pz->is_ref; } static zend_always_inline zend_bool zval_set_isref_p(zval* pz) { return pz->is_ref = 1; } static zend_always_inline zend_bool zval_unset_isref_p(zval* pz) { return pz->is_ref = 0; } static zend_always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref) { return pz->is_ref = isref; } #endif /* PHP >=5.3 replaced ZVAL_DELREF by Z_DELREF_P */ #if ZEND_MODULE_API_NO >= 20090626 #define ZVAL_DELREF Z_DELREF_P #define ZVAL_ADDREF Z_ADDREF_P #endif #define MAPSCRIPT_REGISTER_CLASS(name, functions, class_entry, constructor) \ INIT_CLASS_ENTRY(ce, name, functions); \ class_entry = zend_register_internal_class(&ce TSRMLS_CC); \ class_entry->create_object = constructor; #define MAPSCRIPT_ALLOC_OBJECT(zobj, object_type) \ zobj = ecalloc(1, sizeof(object_type)); #define MAPSCRIPT_FREE_OBJECT(zobj) \ zend_hash_destroy(zobj->std.properties); \ FREE_HASHTABLE(zobj->std.properties); #define MAPSCRIPT_ADDREF(zobj) if (zobj) Z_ADDREF_P(zobj) #define MAPSCRIPT_DELREF(zobj) \ if (zobj) \ { \ if (Z_REFCOUNT_P(zobj) == 1) { \ zval_ptr_dtor(&zobj); \ } \ else { \ Z_DELREF_P(zobj); \ } \ zobj = NULL; \ } #define MAPSCRIPT_INIT_PARENT(parent) \ parent.val = NULL; \ parent.child_ptr = NULL; #define MAPSCRIPT_FREE_PARENT(parent) \ if (parent.child_ptr) \ *parent.child_ptr = NULL; \ MAPSCRIPT_DELREF(parent.val); #define MAPSCRIPT_MAKE_PARENT(zobj, ptr) \ parent.val = zobj; \ parent.child_ptr = ptr; #define MAPSCRIPT_CALL_METHOD_1(zobj, function_name, retval, arg1) \ zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1); #define MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2) \ zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1, arg2); #define STRING_EQUAL(string1, string2) \ strcmp(string1, string2) == 0 /* helpers for getters */ #define IF_GET_STRING(property_name, value) \ if (strcmp(property, property_name)==0) \ { \ RETVAL_STRING( (value ? value:"") , 1); \ } \ #define IF_GET_LONG(property_name, value) \ if (strcmp(property, property_name)==0) \ { \ RETVAL_LONG(value); \ } \ #define IF_GET_DOUBLE(property_name, value) \ if (strcmp(property, property_name)==0) \ { \ RETVAL_DOUBLE(value); \ } \ #define IF_GET_OBJECT(property_name, mapscript_ce, php_object_storage, internal_object) \ if (strcmp(property, property_name)==0) \ { \ if (!php_object_storage) { \ mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \ &php_object_storage TSRMLS_CC); \ } \ RETURN_ZVAL(php_object_storage, 1, 0); \ } #define CHECK_OBJECT(mapscript_ce, php_object_storage, internal_object) \ if (!php_object_storage) { \ mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \ &php_object_storage TSRMLS_CC); \ } /* helpers for setters */ #define IF_SET_STRING(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_string(value); \ if (internal) free(internal); \ if (Z_STRVAL_P(value)) \ internal = strdup(Z_STRVAL_P(value)); \ } #define IF_SET_LONG(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_long(value); \ internal = Z_LVAL_P(value); \ } #define IF_SET_DOUBLE(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_double(value); \ internal = Z_DVAL_P(value); \ } #define IF_SET_BYTE(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_long(value); \ internal = (unsigned char)Z_LVAL_P(value); \ } #define IF_SET_COLOR(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_long(value); \ /* validate the color value */ \ if (Z_LVAL_P(value) < 0 || Z_LVAL_P(value) > 255) { \ mapscript_throw_exception("Invalid color value. It must be between 0 and 255." TSRMLS_CC); \ return; \ } \ internal = Z_LVAL_P(value); \ } zend_object_value mapscript_object_new(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object) TSRMLS_DC); int mapscript_extract_associative_array(HashTable *php, char **array); #endif /* PHP_MAPSCRIPT_UTIL_H */ mapserver-6.4.1/mapscript/php/php_mapscript.h0000644002461700001440000010363712261257215021141 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. Header file * - prototypes / module definitions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000-2005, Daniel Morissette, DM Solutions Group Inc. * * 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 PHP_MAPSCRIPT_H #define PHP_MAPSCRIPT_H #include "php.h" #include "zend_interfaces.h" #include "php_mapscript_util.h" #ifdef USE_PHP_REGEX #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #else #include #endif #include "../../mapserver.h" #include "../../mapregex.h" #endif /* USE_PHP_REGEX */ #include "../../maptemplate.h" #include "../../mapogcsld.h" #define MAPSCRIPT_VERSION "($Revision$ $Date$)" extern zend_module_entry mapscript_module_entry; #define phpext_mapscript_ptr &mapscript_module_entry #ifndef zend_parse_parameters_none #define zend_parse_parameters_none() \ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") #endif /* it looks like that macro is not always defined: ticket #3926 */ #ifndef TRUE #define TRUE 1 #endif /* Taken from the CAIRO php extension */ /* turn error handling to exception mode and restore */ #if defined(PHP_VERSION_ID) && PHP_VERSION_ID >= 50300 /* 5.3 version of the macros */ #define PHP_MAPSCRIPT_ERROR_HANDLING(force_exceptions) \ zend_error_handling error_handling; \ if(force_exceptions || getThis()) { \ zend_replace_error_handling(EH_THROW, mapscript_ce_mapscriptexception, &error_handling TSRMLS_CC); \ } #define PHP_MAPSCRIPT_RESTORE_ERRORS(force_exceptions) \ if(force_exceptions || getThis()) { \ zend_restore_error_handling(&error_handling TSRMLS_CC); \ } #else /* 5.2 versions of the macros */ #define PHP_MAPSCRIPT_ERROR_HANDLING(force_exceptions) \ if(force_exceptions || getThis()) { \ php_set_error_handling(EH_THROW, mapscript_ce_mapscriptexception TSRMLS_CC); \ } #define PHP_MAPSCRIPT_RESTORE_ERRORS(force_exceptions) \ if(force_exceptions || getThis()) { \ php_std_error_handling(); \ } #endif /* MapScript objects */ typedef struct _parent_object { zval *val; // the zval of the parent zval **child_ptr; // a ptr to a parent property, which point to the child object. // should be set to NULL when the child is destroyed } parent_object; typedef struct _php_color_object { zend_object std; parent_object parent; colorObj *color; } php_color_object; typedef struct _php_rect_object { zend_object std; parent_object parent; int is_ref; rectObj *rect; } php_rect_object; typedef struct _php_hashtable_object { zend_object std; parent_object parent; hashTableObj *hashtable; } php_hashtable_object; typedef struct _php_symbol_object { zend_object std; parent_object parent; symbolObj *symbol; } php_symbol_object; typedef struct _php_class_object { zend_object std; parent_object parent; //old layer zval *metadata; zval *leader; classObj *class; } php_class_object; typedef struct _php_image_object { zend_object std; imageObj *image; } php_image_object; typedef struct _php_web_object { zend_object std; parent_object parent; zval *extent; zval *metadata; zval *validation; webObj *web; } php_web_object; typedef struct _php_legend_object { zend_object std; parent_object parent; zval *outlinecolor; zval *label; zval *imagecolor; legendObj *legend; } php_legend_object; typedef struct _php_outputformat_object { zend_object std; parent_object parent; int is_ref; outputFormatObj *outputformat; } php_outputformat_object; typedef struct _php_querymap_object { zend_object std; parent_object parent; zval *color; queryMapObj *querymap; } php_querymap_object; typedef struct _php_grid_object { zend_object std; parent_object parent; graticuleObj *grid; } php_grid_object; typedef struct _php_error_object { zend_object std; errorObj *error; } php_error_object; typedef struct _php_referencemap_object { zend_object std; parent_object parent; zval *extent; zval *color; zval *outlinecolor; referenceMapObj *referencemap; } php_referencemap_object; typedef struct _php_label_object { zend_object std; parent_object parent; int is_ref; zval *color; zval *outlinecolor; zval *shadowcolor; zval *backgroundcolor; zval *backgroundshadowcolor; zval *leader; labelObj *label; } php_label_object; typedef struct _php_style_object { zend_object std; parent_object parent; zval *color; zval *outlinecolor; zval *backgroundcolor; zval *mincolor; zval *maxcolor; styleObj *style; } php_style_object; typedef struct _php_projection_object { zend_object std; parent_object parent; int is_ref; projectionObj *projection; } php_projection_object; typedef struct _php_point_object { zend_object std; parent_object parent; int is_ref; pointObj *point; } php_point_object; typedef struct _php_line_object { zend_object std; parent_object parent; int is_ref; lineObj *line; } php_line_object; typedef struct _php_shape_object { zend_object std; parent_object parent; zval *bounds; zval *values; int is_ref; shapeObj *shape; } php_shape_object; typedef struct _php_shapefile_object { zend_object std; zval *bounds; shapefileObj *shapefile; } php_shapefile_object; typedef struct _php_labelcache_object { zend_object std; parent_object parent; labelCacheObj *labelcache; } php_labelcache_object; typedef struct _php_labelleader_object { zend_object std; parent_object parent; labelLeaderObj *labelleader; } php_labelleader_object; typedef struct _php_labelcachemember_object { zend_object std; parent_object parent; zval *labels; /* should be immutable */ zval *point; /* should be immutable */ zval *styles; /* should be immutable */ zval *poly; /* should be immutable */ labelCacheMemberObj *labelcachemember; } php_labelcachemember_object; typedef struct _php_result_object { zend_object std; parent_object parent; resultObj *result; } php_result_object; typedef struct _php_scalebar_object { zend_object std; parent_object parent; zval *color; zval *backgroundcolor; zval *outlinecolor; zval *label; zval *imagecolor; scalebarObj *scalebar; } php_scalebar_object; typedef struct _php_owsrequest_object { zend_object std; cgiRequestObj *cgirequest; } php_owsrequest_object; typedef struct _php_layer_object { zend_object std; parent_object parent; //old map zval *offsite; zval *grid; zval *metadata; zval *bindvals; zval *projection; zval *cluster; zval *extent; int is_ref; layerObj *layer; } php_layer_object; typedef struct _php_map_object { zend_object std; zval *outputformat; zval *extent; zval *web; zval *reference; zval *imagecolor; zval *scalebar; zval *legend; zval *querymap; zval *labelcache; zval *projection; zval *metadata; zval *configoptions; mapObj *map; } php_map_object; typedef struct _php_cluster_object { zend_object std; parent_object parent; int is_ref; clusterObj *cluster; } php_cluster_object; /* Lifecyle functions*/ PHP_MINIT_FUNCTION(mapscript); PHP_MINFO_FUNCTION(mapscript); PHP_MSHUTDOWN_FUNCTION(mapscript); PHP_RINIT_FUNCTION(mapscript); PHP_RSHUTDOWN_FUNCTION(mapscript); PHP_MINIT_FUNCTION(mapscript_error); PHP_MINIT_FUNCTION(color); PHP_MINIT_FUNCTION(label); PHP_MINIT_FUNCTION(style); PHP_MINIT_FUNCTION(symbol); PHP_MINIT_FUNCTION(image); PHP_MINIT_FUNCTION(web); PHP_MINIT_FUNCTION(legend); PHP_MINIT_FUNCTION(outputformat); PHP_MINIT_FUNCTION(querymap); PHP_MINIT_FUNCTION(grid); PHP_MINIT_FUNCTION(error); PHP_MINIT_FUNCTION(referencemap); PHP_MINIT_FUNCTION(class); PHP_MINIT_FUNCTION(projection); PHP_MINIT_FUNCTION(labelcachemember); PHP_MINIT_FUNCTION(labelcache); PHP_MINIT_FUNCTION(labelleader); PHP_MINIT_FUNCTION(result); PHP_MINIT_FUNCTION(scalebar); PHP_MINIT_FUNCTION(owsrequest); PHP_MINIT_FUNCTION(point); PHP_MINIT_FUNCTION(rect); PHP_MINIT_FUNCTION(hashtable); PHP_MINIT_FUNCTION(line); PHP_MINIT_FUNCTION(shape); PHP_MINIT_FUNCTION(shapefile); PHP_MINIT_FUNCTION(layer); PHP_MINIT_FUNCTION(map); PHP_MINIT_FUNCTION(cluster); /* mapscript functions */ PHP_FUNCTION(ms_GetVersion); PHP_FUNCTION(ms_GetVersionInt); PHP_FUNCTION(ms_GetErrorObj); PHP_FUNCTION(ms_ResetErrorList); PHP_FUNCTION(ms_getCwd); PHP_FUNCTION(ms_getPid); PHP_FUNCTION(ms_getScale); PHP_FUNCTION(ms_tokenizeMap); PHP_FUNCTION(ms_ioInstallStdoutToBuffer); PHP_FUNCTION(ms_ioInstallStdinFromBuffer); PHP_FUNCTION(ms_ioGetStdoutBufferString); PHP_FUNCTION(ms_ioResetHandlers); PHP_FUNCTION(ms_ioStripStdoutBufferContentType); PHP_FUNCTION(ms_ioStripStdoutBufferContentHeaders); PHP_FUNCTION(ms_ioGetStdoutBufferBytes); /* object constructors */ PHP_FUNCTION(ms_newLineObj); PHP_FUNCTION(ms_newRectObj); PHP_FUNCTION(ms_newShapeObj); PHP_FUNCTION(ms_shapeObjFromWkt); PHP_FUNCTION(ms_newOWSRequestObj); PHP_FUNCTION(ms_newShapeFileObj); PHP_FUNCTION(ms_newMapObj); PHP_FUNCTION(ms_newMapObjFromString); PHP_FUNCTION(ms_newLayerObj); PHP_FUNCTION(ms_newPointObj); PHP_FUNCTION(ms_newProjectionObj); PHP_FUNCTION(ms_newStyleObj); PHP_FUNCTION(ms_newSymbolObj); PHP_FUNCTION(ms_newClassObj); PHP_FUNCTION(ms_newGridObj); /* mapscript zend class entries */ extern zend_object_handlers mapscript_std_object_handlers; extern zend_class_entry *mapscript_ce_mapscriptexception; extern zend_class_entry *mapscript_ce_color; extern zend_class_entry *mapscript_ce_label; extern zend_class_entry *mapscript_ce_projection; extern zend_class_entry *mapscript_ce_point; extern zend_class_entry *mapscript_ce_rect; extern zend_class_entry *mapscript_ce_hashtable; extern zend_class_entry *mapscript_ce_style; extern zend_class_entry *mapscript_ce_class; extern zend_class_entry *mapscript_ce_symbol; extern zend_class_entry *mapscript_ce_image; extern zend_class_entry *mapscript_ce_web; extern zend_class_entry *mapscript_ce_legend; extern zend_class_entry *mapscript_ce_outputformat; extern zend_class_entry *mapscript_ce_querymap; extern zend_class_entry *mapscript_ce_grid; extern zend_class_entry *mapscript_ce_error; extern zend_class_entry *mapscript_ce_referencemap; extern zend_class_entry *mapscript_ce_line; extern zend_class_entry *mapscript_ce_shape; extern zend_class_entry *mapscript_ce_shapefile; extern zend_class_entry *mapscript_ce_labelcachemember; extern zend_class_entry *mapscript_ce_labelcache; extern zend_class_entry *mapscript_ce_labelleader; extern zend_class_entry *mapscript_ce_result; extern zend_class_entry *mapscript_ce_scalebar; extern zend_class_entry *mapscript_ce_owsrequest; extern zend_class_entry *mapscript_ce_layer; extern zend_class_entry *mapscript_ce_map; extern zend_class_entry *mapscript_ce_cluster; /* PHP Object constructors */ extern zend_object_value mapscript_object_new(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object) TSRMLS_DC); extern zend_object_value mapscript_object_new_ex(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object), zend_object_handlers *object_handlers TSRMLS_DC); extern void mapscript_fetch_object(zend_class_entry *ce, zval* zval_parent, php_layer_object* layer, void *internal_object, zval **php_object_storage TSRMLS_DC); extern void mapscript_create_color(colorObj *color, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_rect(rectObj *rect, parent_object php_parent, zval *return_value TSRMLS_DC); extern void mapscript_create_hashtable(hashTableObj *hashtable, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_label(labelObj *label, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_style(styleObj *style, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_symbol(symbolObj *symbol, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_class(classObj *class, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_labelcachemember(labelCacheMemberObj *labelcachemember, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_labelcache(labelCacheObj *labelcache, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_labelleader(labelLeaderObj *labelleader, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_result(resultObj *result, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_scalebar(scalebarObj *scalebar, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_owsrequest(cgiRequestObj *cgirequest, zval *return_value TSRMLS_DC); extern void mapscript_create_image(imageObj *image, zval *return_value TSRMLS_DC); extern void mapscript_create_web(webObj *web, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_legend(legendObj *legend, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_outputformat(outputFormatObj *outputformat, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_querymap(queryMapObj *querymap, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_grid(graticuleObj *grid, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_error(errorObj *error, zval *return_value TSRMLS_DC); extern void mapscript_create_referencemap(referenceMapObj *referenceMap, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_point(pointObj *point, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_projection(projectionObj *projection, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_line(lineObj *line, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_shape(shapeObj *shape, parent_object parent, php_layer_object *php_layer, zval *return_value TSRMLS_DC); extern void mapscript_create_shapefile(shapefileObj *shapefile, zval *return_value TSRMLS_DC); extern void mapscript_create_layer(layerObj *layer, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_map(mapObj *map, zval *return_value TSRMLS_DC); extern void mapscript_create_cluster(clusterObj *cluster, parent_object php_parent, zval *return_value TSRMLS_DC); /* Exported functions for PHP Mapscript API */ /* throw a MapScriptException */ extern zval * mapscript_throw_exception(char *format TSRMLS_DC, ...); /* print all MapServer errors (as Warning) and throw a MapScriptException */ extern zval* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...); extern void mapscript_report_mapserver_error(int error_type TSRMLS_DC); extern void mapscript_report_php_error(int error_type, char *format TSRMLS_DC, ...); /*===================================================================== * Internal functions from mapscript_i.c *====================================================================*/ mapObj *mapObj_new(char *filename, char *new_path); mapObj *mapObj_newFromString(char *map_text, char *new_path); void mapObj_destroy(mapObj* self); mapObj *mapObj_clone(mapObj* self); int mapObj_setRotation(mapObj* self, double rotation_angle ); layerObj *mapObj_getLayer(mapObj* self, int i); layerObj *mapObj_getLayerByName(mapObj* self, char *name); int *mapObj_getLayersIndexByGroup(mapObj* self, char *groupname, int *pnCount); int mapObj_getSymbolByName(mapObj* self, char *name); void mapObj_prepareQuery(mapObj* self); imageObj *mapObj_prepareImage(mapObj* self); imageObj *mapObj_draw(mapObj* self); imageObj *mapObj_drawQuery(mapObj* self); imageObj *mapObj_drawLegend(mapObj* self); imageObj *mapObj_drawScalebar(mapObj* self); imageObj *mapObj_drawReferenceMap(mapObj* self); int mapObj_embedScalebar(mapObj* self, imageObj *img); int mapObj_embedLegend(mapObj* self, imageObj *img); int mapObj_drawLabelCache(mapObj* self, imageObj *img); labelCacheMemberObj *mapObj_getLabel(mapObj* self, int i); int mapObj_queryByPoint(mapObj* self, pointObj *point, int mode, double buffer); int mapObj_queryByRect(mapObj* self, rectObj rect); int mapObj_queryByFeatures(mapObj* self, int slayer); int mapObj_queryByShape(mapObj *self, shapeObj *shape); int mapObj_queryByIndex(mapObj *self, int qlayer, int tileindex, int shapeindex, int bAddToQuery); int mapObj_queryByFilter(mapObj* self, char *string); int mapObj_saveQuery(mapObj *self, char *filename, int results); int mapObj_loadQuery(mapObj *self, char *filename); int mapObj_setWKTProjection(mapObj *self, char *string); char* mapObj_getProjection(mapObj* self); int mapObj_setProjection(mapObj* self, char *string); int mapObj_save(mapObj* self, char *filename); char *mapObj_getMetaData(mapObj *self, char *name); int mapObj_setMetaData(mapObj *self, char *name, char *value); int mapObj_removeMetaData(mapObj *self, char *name); void mapObj_freeQuery(mapObj *self, int qlayer); int mapObj_moveLayerup(mapObj *self, int layerindex); int mapObj_moveLayerdown(mapObj *self, int layerindex); int *mapObj_getLayersdrawingOrder(mapObj *self); int mapObj_setLayersdrawingOrder(mapObj *self, int *panIndexes); char *mapObj_processTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries); char *mapObj_processLegendTemplate(mapObj *self, char **names, char **values, int numentries); char *mapObj_processQueryTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries); int mapObj_setSymbolSet(mapObj *self, char *szFileName); int mapObj_getNumSymbols(mapObj *self); int mapObj_setFontSet(mapObj *self, char *szFileName); int mapObj_saveMapContext(mapObj *self, char *szFileName); int mapObj_loadMapContext(mapObj *self, char *szFileName, int bUniqueLayerName); int mapObj_selectOutputFormat(mapObj *self, const char *imagetype); int mapObj_applySLD(mapObj *self, char *sld); int mapObj_applySLDURL(mapObj *self, char *sld); char *mapObj_generateSLD(mapObj *self); int mapObj_loadOWSParameters(mapObj *self, cgiRequestObj *request, char *wmtver_string); int mapObj_OWSDispatch(mapObj *self, cgiRequestObj *req ); int mapObj_insertLayer(mapObj *self, layerObj *layer, int index); layerObj *mapObj_removeLayer(mapObj *self, int layerindex); int mapObj_setCenter(mapObj *self, pointObj *center); int mapObj_offsetExtent(mapObj *self, double x, double y); int mapObj_scaleExtent(mapObj *self, double zoomfactor, double minscaledenom, double maxscaledenom); char *mapObj_convertToString(mapObj *self); layerObj *layerObj_new(mapObj *map); void layerObj_destroy(layerObj* self); int layerObj_updateFromString(layerObj *self, char *snippet); char *layerObj_convertToString(layerObj *self); int layerObj_open(layerObj *self); int layerObj_whichShapes(layerObj *self, rectObj *poRect); shapeObj *layerObj_nextShape(layerObj *self); void layerObj_close(layerObj *self); int layerObj_getShape(layerObj *self, shapeObj *shape, int tileindex, int shapeindex); resultObj *layerObj_getResult(layerObj *self, int i); classObj *layerObj_getClass(layerObj *self, int i); int layerObj_getClassIndex(layerObj *self, mapObj *map, shapeObj *shape, int *classgroup, int numclasses); int layerObj_draw(layerObj *self, mapObj *map, imageObj *img); int layerObj_drawQuery(layerObj *self, mapObj *map, imageObj *img); int layerObj_queryByAttributes(layerObj *self, mapObj *map, char *qitem, char *qstring, int mode); int layerObj_queryByPoint(layerObj *self, mapObj *map, pointObj *point, int mode, double buffer); int layerObj_queryByRect(layerObj *self, mapObj *map,rectObj rect); int layerObj_queryByFeatures(layerObj *self, mapObj *map, int slayer); int layerObj_queryByShape(layerObj *self, mapObj *map, shapeObj *shape); int layerObj_queryByFilter(layerObj *self, mapObj *map, char *string); int layerObj_queryByIndex(layerObj *self, mapObj *map, int tileindex, int shapeindex, int addtoquery); int layerObj_setFilter(layerObj *self, char *string); char* layerObj_getFilter(layerObj *self); int layerObj_setWKTProjection(layerObj *self, char *string); char* layerObj_getProjection(layerObj *self); int layerObj_setProjection(layerObj *self, char *string); int layerObj_addFeature(layerObj *self, shapeObj *shape); char *layerObj_getMetaData(layerObj *self, char *name); int layerObj_setMetaData(layerObj *self, char *name, char *value); int layerObj_removeMetaData(layerObj *self, char *name); char *layerObj_getWMSFeatureInfoURL(layerObj *self, mapObj *map, int click_x, int click_y, int feature_count, char *info_format); char *layerObj_executeWFSGetFeature(layerObj *self); int layerObj_applySLD(layerObj *self, char *sld, char *stylelayer); int layerObj_applySLDURL(layerObj *self, char *sld, char *stylelayer); char *layerObj_generateSLD(layerObj *self); int layerObj_moveClassUp(layerObj *self, int index); int layerObj_moveClassDown(layerObj *self, int index); classObj *layerObj_removeClass(layerObj *self, int index); int layerObj_setConnectionType(layerObj *self, int connectiontype, const char *library_str) ; layerObj *layerObj_clone(layerObj *layer); labelObj *labelObj_new(); int labelObj_updateFromString(labelObj *self, char *snippet); char *labelObj_convertToString(labelObj *self); void labelObj_destroy(labelObj *self); int labelObj_moveStyleUp(labelObj *self, int index); int labelObj_moveStyleDown(labelObj *self, int index); int labelObj_deleteStyle(labelObj *self, int index); labelObj *labelObj_clone(labelObj *label); int labelObj_setExpression(labelObj *self, char *string); char *labelObj_getExpressionString(labelObj *self); int labelObj_setText(labelObj *self,layerObj *layer,char *string); char *labelObj_getTextString(labelObj *self); int legendObj_updateFromString(legendObj *self, char *snippet); char *legendObj_convertToString(legendObj *self); int queryMapObj_updateFromString(queryMapObj *self, char *snippet); char *queryMapObj_convertToString(queryMapObj *self); int referenceMapObj_updateFromString(referenceMapObj *self, char *snippet); char *referenceMapObj_convertToString(referenceMapObj *self); int scalebarObj_updateFromString(scalebarObj *self, char *snippet); char *scalebarObj_convertToString(scalebarObj *self); int webObj_updateFromString(webObj *self, char *snippet); char *webObj_convertToString(webObj *self); classObj *classObj_new(layerObj *layer, classObj *class); labelObj *classObj_getLabel(classObj *self, int i); int classObj_addLabel(classObj *self, labelObj *label); labelObj *classObj_removeLabel(classObj *self, int index); int classObj_updateFromString(classObj *self, char *snippet); char *classObj_convertToString(classObj *self); void classObj_destroy(classObj* self); int classObj_setExpression(classObj *self, char *string); char *classObj_getExpressionString(classObj *self); int classObj_setText(classObj *self,layerObj *layer,char *string); char *classObj_getTextString(classObj *self); int classObj_drawLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height, imageObj *im, int dstX, int dstY); imageObj *classObj_createLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height); int classObj_setSymbolByName(classObj *self, mapObj *map, char *pszSymbolName); int classObj_setOverlaySymbolByName(classObj *self, mapObj *map, char *pszOverlaySymbolName); classObj *classObj_clone(classObj *class, layerObj *layer); int classObj_moveStyleUp(classObj *self, int index); int classObj_moveStyleDown(classObj *self, int index); int classObj_deleteStyle(classObj *self, int index); char *classObj_getMetaData(classObj *self, char *name); int classObj_setMetaData(classObj *self, char *name, char *value); int classObj_removeMetaData(classObj *self, char *name); pointObj *pointObj_new(); void pointObj_destroy(pointObj *self); int pointObj_project(pointObj *self, projectionObj *in, projectionObj *out); int pointObj_draw(pointObj *self, mapObj *map, layerObj *layer, imageObj *img, int class_index, char *label_string); double pointObj_distanceToPoint(pointObj *self, pointObj *point); double pointObj_distanceToLine(pointObj *self, pointObj *a, pointObj *b); double pointObj_distanceToShape(pointObj *self, shapeObj *shape); lineObj *lineObj_new(); void lineObj_destroy(lineObj *self); lineObj *lineObj_clone(lineObj *line); int lineObj_project(lineObj *self, projectionObj *in, projectionObj *out); pointObj *lineObj_get(lineObj *self, int i); int lineObj_add(lineObj *self, pointObj *p); shapeObj *shapeObj_new(int type); void shapeObj_destroy(shapeObj *self); int shapeObj_project(shapeObj *self, projectionObj *in, projectionObj *out); lineObj *shapeObj_get(shapeObj *self, int i); int shapeObj_add(shapeObj *self, lineObj *line); int shapeObj_draw(shapeObj *self, mapObj *map, layerObj *layer, imageObj *img); void shapeObj_setBounds(shapeObj *self); int shapeObj_copy(shapeObj *self, shapeObj *dest); int shapeObj_contains(shapeObj *self, pointObj *point); int shapeObj_intersects(shapeObj *self, shapeObj *shape); pointObj *shapeObj_getpointusingmeasure(shapeObj *self, double m); pointObj *shapeObj_getmeasureusingpoint(shapeObj *self, pointObj *point); shapeObj *shapeObj_buffer(shapeObj *self, double width); shapeObj *shapeObj_simplify(shapeObj *self, double tolerance); shapeObj *shapeObj_topologypreservingsimplify(shapeObj *self, double tolerance); shapeObj *shapeObj_convexHull(shapeObj *self); shapeObj *shapeObj_boundary(shapeObj *self); int shapeObj_contains_geos(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_Union(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_intersection(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_difference(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_symdifference(shapeObj *self, shapeObj *poshape); int shapeObj_overlaps(shapeObj *self, shapeObj *shape); int shapeObj_within(shapeObj *self, shapeObj *shape); int shapeObj_crosses(shapeObj *self, shapeObj *shape); int shapeObj_touches(shapeObj *self, shapeObj *shape); int shapeObj_equals(shapeObj *self, shapeObj *shape); int shapeObj_disjoint(shapeObj *self, shapeObj *shape); pointObj *shapeObj_getcentroid(shapeObj *self); double shapeObj_getarea(shapeObj *self); double shapeObj_getlength(shapeObj *self); pointObj *shapeObj_getLabelPoint(shapeObj *self); rectObj *rectObj_new(); void rectObj_destroy(rectObj *self); int rectObj_project(rectObj *self, projectionObj *in, projectionObj *out); double rectObj_fit(rectObj *self, int width, int height); int rectObj_draw(rectObj *self, mapObj *map, layerObj *layer, imageObj *img, int classindex, char *text); shapefileObj *shapefileObj_new(char *filename, int type); void shapefileObj_destroy(shapefileObj *self); int shapefileObj_get(shapefileObj *self, int i, shapeObj *shape); int shapefileObj_getPoint(shapefileObj *self, int i, pointObj *point); int shapefileObj_getTransformed(shapefileObj *self, mapObj *map, int i, shapeObj *shape); void shapefileObj_getExtent(shapefileObj *self, int i, rectObj *rect); int shapefileObj_add(shapefileObj *self, shapeObj *shape); int shapefileObj_addPoint(shapefileObj *self, pointObj *point); projectionObj *projectionObj_new(char *string); projectionObj *projectionObj_clone(projectionObj *projection); int projectionObj_getUnits(projectionObj *self); void projectionObj_destroy(projectionObj *self); void labelCacheObj_freeCache(labelCacheObj *self); char *DBFInfo_getFieldName(DBFInfo *self, int iField); int DBFInfo_getFieldWidth(DBFInfo *self, int iField); int DBFInfo_getFieldDecimals(DBFInfo *self, int iField); DBFFieldType DBFInfo_getFieldType(DBFInfo *self, int iField); styleObj *styleObj_new(classObj *class, styleObj *style); styleObj *styleObj_label_new(labelObj *label, styleObj *style); int styleObj_updateFromString(styleObj *self, char *snippet); char *styleObj_convertToString(styleObj *self); int styleObj_setSymbolByName(styleObj *self, mapObj *map, char* pszSymbolName); styleObj *styleObj_clone(styleObj *style); void styleObj_setGeomTransform(styleObj *style, char *transform); hashTableObj *hashTableObj_new(); int hashTableObj_set(hashTableObj *self, const char *key, const char *value); const char *hashTableObj_get(hashTableObj *self, const char *key); int hashTableObj_remove(hashTableObj *self, const char *key); void hashTableObj_clear(hashTableObj *self); char *hashTableObj_nextKey(hashTableObj *self, const char *prevkey); cgiRequestObj *cgirequestObj_new(); int cgirequestObj_loadParams(cgiRequestObj *self, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context); void cgirequestObj_setParameter(cgiRequestObj *self, char *name, char *value); void cgirequestObj_addParameter(cgiRequestObj *self, char *name, char *value); char *cgirequestObj_getName(cgiRequestObj *self, int index); char *cgirequestObj_getValue(cgiRequestObj *self, int index); char *cgirequestObj_getValueByName(cgiRequestObj *self, const char *name); void cgirequestObj_destroy(cgiRequestObj *self); resultObj *resultObj_new(); int clusterObj_updateFromString(clusterObj *self, char *snippet); char *clusterObj_convertToString(clusterObj *self); int clusterObj_setGroup(clusterObj *self, char *string); char *clusterObj_getGroupString(clusterObj *self); int clusterObj_setFilter(clusterObj *self, char *string); char *clusterObj_getFilterString(clusterObj *self); outputFormatObj *outputFormatObj_new(const char *driver, char *name); void outputFormatObj_destroy(outputFormatObj* self); int symbolObj_setImage(symbolObj *self, imageObj *image); imageObj *symbolObj_getImage(symbolObj *self, outputFormatObj *input_format); #endif /* PHP_MAPSCRIPT_H */ mapserver-6.4.1/mapscript/php/style.c0000644002461700001440000007432512261257215017424 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_style; zend_object_handlers mapscript_style_object_handlers; ZEND_BEGIN_ARG_INFO_EX(style___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, parent) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_setBinding_args, 0, 0, 2) ZEND_ARG_INFO(0, styleBinding) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_getBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, styleBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_removeBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, styleBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_setGeomTransform_args, 0, 0, 1) ZEND_ARG_INFO(0, transform) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_setPattern_args, 0, 0, 1) ZEND_ARG_INFO(0, pattern) ZEND_END_ARG_INFO() /* {{{ proto void __construct(parent [, styleObj style]) Create a new styleObj instance. parent has to be a classObj or labelObj. */ PHP_METHOD(styleObj, __construct) { zval *zobj = getThis(); zval *zparent, *zstyle = NULL; styleObj *style; php_class_object *php_class = NULL; php_label_object *php_label = NULL; php_style_object *php_style, *php_style2 = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|O", &zparent, &zstyle, mapscript_ce_style) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *)zend_object_store_get_object(zobj TSRMLS_CC); if (Z_TYPE_P(zparent) == IS_OBJECT && Z_OBJCE_P(zparent) == mapscript_ce_class) php_class = (php_class_object *)zend_object_store_get_object(zparent TSRMLS_CC); else if (Z_TYPE_P(zparent) == IS_OBJECT && Z_OBJCE_P(zparent) == mapscript_ce_label) php_label = (php_label_object *)zend_object_store_get_object(zparent TSRMLS_CC); else { mapscript_throw_mapserver_exception("Invalid argument 1: should be a classObj or labelObj" TSRMLS_CC); return; } if (zstyle) php_style2 = (php_style_object *)zend_object_store_get_object(zstyle TSRMLS_CC); if (php_class) { if ((style = styleObj_new(php_class->class, (zstyle ? php_style2->style : NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } } else { if ((style = styleObj_label_new(php_label->label, (zstyle ? php_style2->style : NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } } php_style->style = style; MAPSCRIPT_MAKE_PARENT(zparent, NULL); php_style->parent = parent; MAPSCRIPT_ADDREF(zparent); } /* }}} */ PHP_METHOD(styleObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("symbol", php_style->style->symbol) else IF_GET_STRING("symbolname", php_style->style->symbolname) else IF_GET_DOUBLE("size", php_style->style->size) else IF_GET_DOUBLE("minsize", php_style->style->minsize) else IF_GET_DOUBLE("maxsize", php_style->style->maxsize) else IF_GET_DOUBLE("width", php_style->style->width) else IF_GET_DOUBLE("outlinewidth", php_style->style->outlinewidth) else IF_GET_DOUBLE("minwidth", php_style->style->minwidth) else IF_GET_DOUBLE("maxwidth", php_style->style->maxwidth) else IF_GET_LONG("offsetx", php_style->style->offsetx) else IF_GET_LONG("offsety", php_style->style->offsety) else IF_GET_LONG("polaroffsetpixel", php_style->style->polaroffsetpixel) else IF_GET_LONG("polaroffsetangle", php_style->style->polaroffsetangle) else IF_GET_DOUBLE("angle", php_style->style->angle) else IF_GET_LONG("antialias", php_style->style->antialias) else IF_GET_DOUBLE("minvalue", php_style->style->minvalue) else IF_GET_DOUBLE("maxvalue", php_style->style->maxvalue) else IF_GET_STRING("rangeitem", php_style->style->rangeitem) else IF_GET_LONG("rangeitemindex", php_style->style->rangeitemindex) else IF_GET_DOUBLE("gap", php_style->style->gap) else IF_GET_DOUBLE("initialgap", php_style->style->initialgap) else IF_GET_DOUBLE("maxscaledenom", php_style->style->maxscaledenom) else IF_GET_DOUBLE("minscaledenom", php_style->style->minscaledenom) else IF_GET_LONG("patternlength", php_style->style->patternlength) else IF_GET_LONG("position", php_style->style->position) else IF_GET_LONG("linecap", php_style->style->linecap) else IF_GET_LONG("linejoin", php_style->style->linejoin) else IF_GET_LONG("linejoinmaxsize", php_style->style->linejoinmaxsize) else IF_GET_DOUBLE("angle", php_style->style->angle) else IF_GET_LONG("autoangle", php_style->style->autoangle) else IF_GET_LONG("opacity", php_style->style->opacity) else IF_GET_OBJECT("color", mapscript_ce_color, php_style->color, &php_style->style->color) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_style->outlinecolor, &php_style->style->outlinecolor) else IF_GET_OBJECT("backgroundcolor", mapscript_ce_color, php_style->backgroundcolor, &php_style->style->backgroundcolor) else IF_GET_OBJECT("mincolor", mapscript_ce_color, php_style->mincolor, &php_style->style->mincolor) else IF_GET_OBJECT("maxcolor", mapscript_ce_color, php_style->maxcolor, &php_style->style->maxcolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(styleObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_style_object *php_style; php_map_object *php_map = NULL; php_class_object *php_class; php_layer_object *php_layer; php_labelcachemember_object *php_labelcachemember; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_LONG("symbol", php_style->style->symbol, value) else IF_SET_DOUBLE("size", php_style->style->size, value) else IF_SET_DOUBLE("minsize", php_style->style->minsize, value) else IF_SET_DOUBLE("maxsize", php_style->style->maxsize, value) else IF_SET_DOUBLE("width", php_style->style->width, value) else IF_SET_DOUBLE("outlinewidth", php_style->style->outlinewidth, value) else IF_SET_DOUBLE("minwidth", php_style->style->minwidth, value) else IF_SET_DOUBLE("maxwidth", php_style->style->maxwidth, value) else IF_SET_LONG("offsetx", php_style->style->offsetx, value) else IF_SET_LONG("offsety", php_style->style->offsety, value) else IF_SET_LONG("polaroffsetpixel", php_style->style->polaroffsetpixel, value) else IF_SET_LONG("polaroffsetangle", php_style->style->polaroffsetangle, value) else IF_SET_DOUBLE("angle", php_style->style->angle, value) else IF_SET_LONG("antialias", php_style->style->antialias, value) else IF_SET_DOUBLE("minvalue", php_style->style->minvalue, value) else IF_SET_DOUBLE("maxvalue", php_style->style->maxvalue, value) else IF_SET_DOUBLE("minscaledenom", php_style->style->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_style->style->maxscaledenom, value) else IF_SET_STRING("rangeitem", php_style->style->rangeitem, value) else IF_SET_LONG("rangeitemindex", php_style->style->rangeitemindex, value) else IF_SET_DOUBLE("gap", php_style->style->gap, value) else IF_SET_DOUBLE("initialgap", php_style->style->initialgap, value) else IF_SET_LONG("position", php_style->style->position, value) else IF_SET_LONG("linecap", php_style->style->linecap, value) else IF_SET_LONG("linejoin", php_style->style->linejoin, value) else IF_SET_LONG("linejoinmaxsize", php_style->style->linejoinmaxsize, value) else IF_SET_DOUBLE("angle", php_style->style->angle, value) else IF_SET_LONG("autoangle", php_style->style->autoangle, value) else if (STRING_EQUAL("opacity", property)) { int alpha; convert_to_long(value); php_style->style->opacity = Z_LVAL_P(value); /* apply opacity as the alpha channel color(s) */ if(php_style->style->opacity < 100) alpha = MS_NINT(php_style->style->opacity*2.55); else alpha = 255; php_style->style->color.alpha = alpha; php_style->style->outlinecolor.alpha = alpha; php_style->style->backgroundcolor.alpha = alpha; php_style->style->mincolor.alpha = alpha; php_style->style->maxcolor.alpha = alpha; } else if (STRING_EQUAL("symbolname", property)) { convert_to_string(value); if (php_style->style->symbolname) free(php_style->style->symbolname); if (Z_STRVAL_P(value)) php_style->style->symbolname = strdup(Z_STRVAL_P(value)); /* The parent can be a classObj or a labelCacheMemberObj */ if (Z_OBJCE_P(php_style->parent.val) == mapscript_ce_class) { php_class = (php_class_object *) zend_object_store_get_object(php_style->parent.val TSRMLS_CC); /* Can a class have no layer object ? */ php_layer = (php_layer_object *) zend_object_store_get_object(php_class->parent.val TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this style object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); } else if (Z_OBJCE_P(php_style->parent.val) == mapscript_ce_labelcachemember) { /* The parent is always a map */ php_labelcachemember = (php_labelcachemember_object *) zend_object_store_get_object(php_style->parent.val TSRMLS_CC); if (!php_labelcachemember->parent.val) { mapscript_throw_exception("No map object associated with this style object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_labelcachemember->parent.val TSRMLS_CC); } if (styleObj_setSymbolByName(php_style->style, php_map->map, php_style->style->symbolname) == -1) { mapscript_throw_exception("Symbol not found." TSRMLS_CC); return; } } else if ( (STRING_EQUAL("color", property)) || (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("backgroundcolor", property)) || (STRING_EQUAL("maxcolor", property)) || (STRING_EQUAL("mincolor", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("patternlength", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int style.updateFromString(string snippet) Update a style from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(styleObj, updateFromString) { zval *zobj = getThis(); char *snippet; long snippet_len = 0; int status = MS_FAILURE; zval *retval; zval property_name, value; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = styleObj_updateFromString(php_style->style, snippet)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* verify the symbol if needed */ if (php_style->style->symbolname) { INIT_ZVAL(property_name); INIT_ZVAL(value); ZVAL_STRING(&property_name, "symbolname", 1); ZVAL_STRING(&value, php_style->style->symbolname, 1); MAPSCRIPT_CALL_METHOD_2(zobj, "__set", retval, &property_name, &value); } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the style object to string. */ PHP_METHOD(styleObj, convertToString) { zval *zobj = getThis(); php_style_object *php_style; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = styleObj_convertToString(php_style->style); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int style.setbinding(const bindingid, string value) Set the attribute binding for a specfiled style property. Returns MS_SUCCESS on success. */ PHP_METHOD(styleObj, setBinding) { zval *zobj = getThis(); char *value; long value_len = 0; long bindingId; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &bindingId, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (bindingId < 0 || bindingId > MS_STYLE_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if (!value || strlen(value) <= 0) { mapscript_throw_exception("Invalid binding value." TSRMLS_CC); return; } if(php_style->style->bindings[bindingId].item) { msFree(php_style->style->bindings[bindingId].item); php_style->style->bindings[bindingId].index = -1; php_style->style->numbindings--; } php_style->style->bindings[bindingId].item = strdup(value); php_style->style->numbindings++; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int style.getbinding(const bindingid) Get the value of a attribute binding for a specfiled style property. Returns the string value if exist, else null. */ PHP_METHOD(styleObj, getBinding) { zval *zobj = getThis(); long bindingId; char *value = NULL; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (bindingId < 0 || bindingId > MS_STYLE_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if( (value = php_style->style->bindings[bindingId].item) != NULL) { RETURN_STRING(value, 1); } RETURN_NULL(); } /* }}} */ /* {{{ proto int style.removebinding(const bindingid) Remove attribute binding for a specfiled style property. Returns MS_SUCCESS on success. */ PHP_METHOD(styleObj, removeBinding) { zval *zobj = getThis(); long bindingId; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (bindingId < 0 || bindingId > MS_STYLE_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if(php_style->style->bindings[bindingId].item) { msFree(php_style->style->bindings[bindingId].item); php_style->style->bindings[bindingId].item = NULL; php_style->style->bindings[bindingId].index = -1; php_style->style->numbindings--; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int style.free() Free the object */ PHP_METHOD(styleObj, free) { zval *zobj = getThis(); php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_style->color); MAPSCRIPT_DELREF(php_style->outlinecolor); MAPSCRIPT_DELREF(php_style->backgroundcolor); } /* }}} */ /* {{{ proto int style.getGeomTransform() return the geometry transform expression */ PHP_METHOD(styleObj, getGeomTransform) { zval *zobj = getThis(); php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_style->style->_geomtransform.type == MS_GEOMTRANSFORM_NONE || !php_style->style->_geomtransform.string) RETURN_STRING("", 1); RETURN_STRING(php_style->style->_geomtransform.string, 1); } /* }}} */ /* {{{ proto int style.setGeomTransform() set the geometry transform expression */ PHP_METHOD(styleObj, setGeomTransform) { zval *zobj = getThis(); char *transform; long transform_len = 0; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &transform, &transform_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); styleObj_setGeomTransform(php_style->style, transform); } /* }}} */ /* {{{ proto int style.setpattern(array points) Set the pattern of the style ) */ PHP_METHOD(styleObj, setPattern) { zval *zpattern, **ppzval; HashTable *pattern_hash = NULL; zval *zobj = getThis(); int index = 0, numelements = 0; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &zpattern) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); pattern_hash = Z_ARRVAL_P(zpattern); numelements = zend_hash_num_elements(pattern_hash); if (numelements == 0) { mapscript_report_php_error(E_WARNING, "style->setpoints : invalid array of %d element(s) as parameter." TSRMLS_CC, numelements); RETURN_LONG(MS_FAILURE); } for(zend_hash_internal_pointer_reset(pattern_hash); zend_hash_has_more_elements(pattern_hash) == SUCCESS; zend_hash_move_forward(pattern_hash)) { zend_hash_get_current_data(pattern_hash, (void **)&ppzval); if (Z_TYPE_PP(ppzval) != IS_LONG) convert_to_long(*ppzval); php_style->style->pattern[index] = Z_LVAL_PP(ppzval); index++; } php_style->style->patternlength = numelements; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int style.getPatternArray() Returns an array containing the pattern.*/ PHP_METHOD(styleObj, getPatternArray) { zval *zobj = getThis(); php_style_object *php_style; int index; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); array_init(return_value); if (php_style->style->patternlength > 0) { for (index=0; index < php_style->style->patternlength; index++) { add_next_index_long(return_value, php_style->style->pattern[index]); } } } /* }}} */ zend_function_entry style_functions[] = { PHP_ME(styleObj, __construct, style___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(styleObj, __get, style___get_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, __set, style___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(styleObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, updateFromString, style_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, setBinding, style_setBinding_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, getBinding, style_getBinding_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, removeBinding, style_removeBinding_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, getGeomTransform, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, setGeomTransform, style_setGeomTransform_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, setPattern, style_setPattern_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, getPatternArray, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_style(styleObj *style, parent_object parent, zval *return_value TSRMLS_DC) { php_style_object * php_style; object_init_ex(return_value, mapscript_ce_style); php_style = (php_style_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_style->style = style; php_style->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_style_object_destroy(void *object TSRMLS_DC) { php_style_object *php_style = (php_style_object *)object; MAPSCRIPT_FREE_OBJECT(php_style); MAPSCRIPT_FREE_PARENT(php_style->parent); MAPSCRIPT_DELREF(php_style->color); MAPSCRIPT_DELREF(php_style->outlinecolor); MAPSCRIPT_DELREF(php_style->backgroundcolor); /* We don't need to free the styleObj, the mapObj will do it */ efree(object); } static zend_object_value mapscript_style_object_new_ex(zend_class_entry *ce, php_style_object **ptr TSRMLS_DC) { zend_object_value retval; php_style_object *php_style; MAPSCRIPT_ALLOC_OBJECT(php_style, php_style_object); retval = mapscript_object_new_ex(&php_style->std, ce, &mapscript_style_object_destroy, &mapscript_style_object_handlers TSRMLS_CC); if (ptr) *ptr = php_style; MAPSCRIPT_INIT_PARENT(php_style->parent); php_style->color = NULL; php_style->outlinecolor = NULL; php_style->backgroundcolor = NULL; return retval; } static zend_object_value mapscript_style_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_style_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_style_object_clone(zval *zobj TSRMLS_DC) { php_style_object *php_style_old, *php_style_new; zend_object_value new_ov; php_style_old = (php_style_object *) zend_object_store_get_object(zobj TSRMLS_CC); new_ov = mapscript_style_object_new_ex(mapscript_ce_style, &php_style_new TSRMLS_CC); zend_objects_clone_members(&php_style_new->std, new_ov, &php_style_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_style_new->style = styleObj_clone(php_style_old->style); return new_ov; } PHP_MINIT_FUNCTION(style) { zend_class_entry ce; memcpy(&mapscript_style_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_style_object_handlers.clone_obj = mapscript_style_object_clone; MAPSCRIPT_REGISTER_CLASS("styleObj", style_functions, mapscript_ce_style, mapscript_style_object_new); mapscript_ce_style->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/shapefile.c0000644002461700001440000003567712261257215020233 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_shapefile; ZEND_BEGIN_ARG_INFO_EX(shapefile___construct_args, 0, 0, 2) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getShape_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getPoint_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getExtent_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_addShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_addPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getTransformed_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto shapefile __construct(string filename, int type) Create a new shapeFileObj instance. */ PHP_METHOD(shapeFileObj, __construct) { zval *zobj = getThis(); php_shapefile_object *php_shapefile; char *filename; long filename_len = 0; long type; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *)zend_object_store_get_object(zobj TSRMLS_CC); php_shapefile->shapefile = shapefileObj_new(filename, type); if (php_shapefile->shapefile == NULL) { mapscript_throw_mapserver_exception("Failed to open shapefile %s" TSRMLS_CC, filename); return; } } /* }}} */ PHP_METHOD(shapeFileObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_shapefile_object *php_shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numshapes", php_shapefile->shapefile->numshapes) else IF_GET_LONG("type", php_shapefile->shapefile->type) else IF_GET_LONG("isopen", php_shapefile->shapefile->isopen) else IF_GET_LONG("lastshape", php_shapefile->shapefile->lastshape) else IF_GET_STRING("source", php_shapefile->shapefile->source) else IF_GET_OBJECT("bounds", mapscript_ce_rect, php_shapefile->bounds, &php_shapefile->shapefile->bounds) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(shapeFileObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_shapefile_object *php_shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (STRING_EQUAL("numshapes", property)) || (STRING_EQUAL("type", property)) || (STRING_EQUAL("source", property)) || (STRING_EQUAL("isopen", property)) || (STRING_EQUAL("lastshape", property)) || (STRING_EQUAL("bounds", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int shapefile.getShape(int i) Retrieve shape by index. */ PHP_METHOD(shapeFileObj, getShape) { zval *zobj = getThis(); long index; shapeObj *shape; php_shapefile_object *php_shapefile; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ if ((shape = shapeObj_new(MS_SHAPE_NULL)) == NULL) { mapscript_throw_mapserver_exception("Failed creating new shape (out of memory?)" TSRMLS_CC); return; } if (shapefileObj_get(php_shapefile->shapefile, index, shape) != MS_SUCCESS) { shapeObj_destroy(shape); mapscript_throw_mapserver_exception("Failed reading shape %ld." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shapefile.getPoint(int i) Retrieve a point by index. */ PHP_METHOD(shapeFileObj, getPoint) { zval *zobj = getThis(); long index; pointObj *point; php_shapefile_object *php_shapefile; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ /* Create a new PointObj to hold the result */ if ((point = pointObj_new()) == NULL) { mapscript_throw_mapserver_exception("Failed creating new point (out of memory?)" TSRMLS_CC); return; } /* Read from the file */ if (shapefileObj_getPoint(php_shapefile->shapefile, index, point) != MS_SUCCESS) { pointObj_destroy(point); mapscript_throw_mapserver_exception("Failed reading point %ld." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shapefile.getExtent(int i) Retrieve a shape's bounding box by index. */ PHP_METHOD(shapeFileObj, getExtent) { zval *zobj = getThis(); long index; rectObj *rect; php_shapefile_object *php_shapefile; parent_object p; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); /* Create a new rectObj to hold the result */ if ((rect = rectObj_new()) == NULL) { mapscript_throw_mapserver_exception("Failed creating new rectObj (out of memory?)" TSRMLS_CC); return; } /* Read from the file * shapefileObj_getExtent() has no return value! How do we catch errors? */ shapefileObj_getExtent(php_shapefile->shapefile, index, rect); /* Return rectObj */ MAPSCRIPT_INIT_PARENT(p); mapscript_create_rect(rect, p, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shapefile.addShape(shapeObj shape) Appends a shape to an open shapefile. */ PHP_METHOD(shapeFileObj, addShape) { zval *zobj = getThis(); zval *zshape; php_shapefile_object *php_shapefile; php_shape_object *php_shape; int retval = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); retval = shapefileObj_add(php_shapefile->shapefile, php_shape->shape); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int shapefile.addPoint(pointObj point) Appends a point to a poin layer. */ PHP_METHOD(shapeFileObj, addPoint) { zval *zobj = getThis(); zval *zpoint; php_shapefile_object *php_shapefile; php_point_object *php_point; int retval = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); retval = shapefileObj_addPoint(php_shapefile->shapefile, php_point->point); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int shapefile.getTransformed(mapObj map, int index) Retrieve shape by index. */ PHP_METHOD(shapeFileObj, getTransformed) { zval *zobj = getThis(); zval *zmap; long index; php_shapefile_object *php_shapefile; php_map_object *php_map; shapeObj *shape = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zmap, mapscript_ce_map, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_map = (php_map_object *) zend_object_store_get_object(zmap TSRMLS_CC); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ if ((shape = shapeObj_new(MS_SHAPE_NULL)) == NULL) { mapscript_throw_mapserver_exception("Failed creating new shape (out of memory?)" TSRMLS_CC); return; } /* Read from the file */ if (shapefileObj_getTransformed(php_shapefile->shapefile, php_map->map, index, shape) != MS_SUCCESS) { shapeObj_destroy(shape); mapscript_throw_mapserver_exception("Failed reading shape %ld." TSRMLS_CC, index); return; } /* Return shape object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto void shapefile.free() Free the object */ PHP_METHOD(shapeFileObj, free) { zval *zobj = getThis(); php_shapefile_object *php_shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = (php_shapefile_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_shapefile->bounds); } /* }}} */ zend_function_entry shapefile_functions[] = { PHP_ME(shapeFileObj, __construct, shapefile___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(shapeFileObj, __get, shapefile___get_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, __set, shapefile___set_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getShape, shapefile_getShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getPoint, shapefile_getPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getExtent, shapefile_getExtent_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, addShape, shapefile_addShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, addPoint, shapefile_addPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getTransformed, shapefile_getTransformed_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_shapefile(shapefileObj *shapefile, zval *return_value TSRMLS_DC) { php_shapefile_object * php_shapefile; object_init_ex(return_value, mapscript_ce_shapefile); php_shapefile = (php_shapefile_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_shapefile->shapefile = shapefile; } static void mapscript_shapefile_object_destroy(void *object TSRMLS_DC) { php_shapefile_object *php_shapefile = (php_shapefile_object *)object; MAPSCRIPT_FREE_OBJECT(php_shapefile); MAPSCRIPT_DELREF(php_shapefile->bounds); shapefileObj_destroy(php_shapefile->shapefile); efree(object); } static zend_object_value mapscript_shapefile_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_shapefile_object *php_shapefile; MAPSCRIPT_ALLOC_OBJECT(php_shapefile, php_shapefile_object); retval = mapscript_object_new(&php_shapefile->std, ce, &mapscript_shapefile_object_destroy TSRMLS_CC); php_shapefile->bounds = NULL; return retval; } PHP_MINIT_FUNCTION(shapefile) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("shapeFileObj", shapefile_functions, mapscript_ce_shapefile, mapscript_shapefile_object_new); mapscript_ce_shapefile->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/projection.c0000644002461700001440000001572212261257215020434 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_projection; zend_object_handlers mapscript_projection_object_handlers; ZEND_BEGIN_ARG_INFO_EX(projection___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, projString) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(projection_setWKTProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, wkt) ZEND_END_ARG_INFO() /* {{{ proto projectionObj __construct(string projString) Create a new projectionObj instance. */ PHP_METHOD(projectionObj, __construct) { char *projString; long projString_len = 0; php_projection_object *php_projection; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projString, &projString_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_projection = (php_projection_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if ((php_projection->projection = projectionObj_new(projString)) == NULL) { mapscript_throw_mapserver_exception("Unable to construct projectionObj." TSRMLS_CC); return; } } /* }}} */ /* {{{ proto projectionObj setWKTProjection(string wkt) Set the wkt projection. Return MS_SUCCESS or MS_FAILURE .*/ PHP_METHOD(projectionObj, setWKTProjection) { char *wkt; long wkt_len = 0; php_projection_object *php_projection; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &wkt, &wkt_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_projection = (php_projection_object *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_LONG(msOGCWKT2ProjectionObj(wkt, php_projection->projection, MS_FALSE)); } /* }}} */ /* {{{ proto int projectionObj.getunits() Returns the units of a projection object */ PHP_METHOD(projectionObj, getUnits) { php_projection_object *php_projection; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_projection = (php_projection_object *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_LONG(projectionObj_getUnits(php_projection->projection)); } /* }}} */ zend_function_entry projection_functions[] = { PHP_ME(projectionObj, __construct, projection___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(projectionObj, setWKTProjection, projection_setWKTProjection_args, ZEND_ACC_PUBLIC) PHP_ME(projectionObj, getUnits, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_projection(projectionObj *projection, parent_object parent, zval *return_value TSRMLS_DC) { php_projection_object * php_projection; object_init_ex(return_value, mapscript_ce_projection); php_projection = (php_projection_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_projection->projection = projection; if (parent.val) php_projection->is_ref = 1; php_projection->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_projection_object_destroy(void *object TSRMLS_DC) { php_projection_object *php_projection = (php_projection_object *)object; MAPSCRIPT_FREE_OBJECT(php_projection); MAPSCRIPT_FREE_PARENT(php_projection->parent); if (php_projection->projection && !php_projection->is_ref) { projectionObj_destroy(php_projection->projection); } efree(object); } static zend_object_value mapscript_projection_object_new_ex(zend_class_entry *ce, php_projection_object **ptr TSRMLS_DC) { zend_object_value retval; php_projection_object *php_projection; MAPSCRIPT_ALLOC_OBJECT(php_projection, php_projection_object); retval = mapscript_object_new_ex(&php_projection->std, ce, &mapscript_projection_object_destroy, &mapscript_projection_object_handlers TSRMLS_CC); if (ptr) *ptr = php_projection; php_projection->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_projection->parent); return retval; } static zend_object_value mapscript_projection_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_projection_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_projection_object_clone(zval *zobj TSRMLS_DC) { php_projection_object *php_projection_old, *php_projection_new; zend_object_value new_ov; php_projection_old = (php_projection_object *) zend_object_store_get_object(zobj TSRMLS_CC); new_ov = mapscript_projection_object_new_ex(mapscript_ce_projection, &php_projection_new TSRMLS_CC); zend_objects_clone_members(&php_projection_new->std, new_ov, &php_projection_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_projection_new->projection = projectionObj_clone(php_projection_old->projection); return new_ov; } PHP_MINIT_FUNCTION(projection) { zend_class_entry ce; memcpy(&mapscript_projection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_projection_object_handlers.clone_obj = mapscript_projection_object_clone; MAPSCRIPT_REGISTER_CLASS("projectionObj", projection_functions, mapscript_ce_projection, mapscript_projection_object_new); mapscript_ce_projection->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/php_proj.c0000644002461700001440000005727012261257215020105 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP wraper function to PROJ4 projection module. * Author: Yewondwossen Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000-2005, Y. Assefa, DM Solutions Group inc. * * 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. ********************************************************************** * * $Log$ * Revision 1.10 2005/06/14 16:03:36 dan * Updated copyright date to 2005 * * Revision 1.9 2005/01/04 22:55:27 assefa * Add PHP5 support for windows (Bug 1100). * * Revision 1.8 2002/03/08 23:16:41 assefa * Add PHP4.1 support. * * Revision 1.7 2002/01/22 19:18:54 dan * Fixed a typo in pj_transform() docs * * Revision 1.6 2002/01/22 19:18:17 dan * Took pj_datum_transform() out of docs to discourage its use. * * Revision 1.5 2001/09/25 14:52:54 assefa * Add pj_transform function. * * Revision 1.4 2001/02/23 20:35:57 assefa * Free function does not work for PHP4. Disable it for now. * * Revision 1.3 2001/01/09 05:24:41 dan * Fixes to build with PHP 4.0.4 * * Revision 1.2 2000/11/08 15:44:16 dan * Correct compilation errors with php4. * * Revision 1.1 2000/11/02 16:39:55 dan * PHP PROJ4 module. * * **********************************************************************/ /* * PHP PROJ4 Module * * This is a PHP module that gives acces to basic PROJ4 projection * functionalities. * * There following functions available in this module : * * 1) pj_init : create and initializes a projection structures * * PJ pj_init(array_of_parameters) * * Example : $projarray[0] = "proj=lcc"; * $projarray[1] = "ellps=GRS80"; * $projarray[2] = "lat_0=49"; * $projarray[3] = "lon_0=-95"; * $projarray[4] = "lat_1=49"; * $projarray[5] = "lat_2=77"; * * $pj = pj_init($projarray); * * 2) pj_fwd : Performs a projection from lat/long coordinates to * cartesian coordinates. * * retrun_array pj_fwd(double lat, double long, PJ pj) * * Example : $lat = 45.25; * $long = -75.42; * * $ret = pj_fwd($ingeox, $ingeoy, $pj); * printf("geo x = %f
\n", $ret["u"]); * printf("geo y = %f
\n",$ret["v"]); * * 3) pj_inv : Performs a projection from cartesian coordinates to * lat/long coordinates . * * retrun_array pj_fwd(double geox, double geoy, PJ pj) * * Example : $ingeox = 1537490.335842; * $ingeoy = -181633.471555; * * $ret = pj_inv($ingeox, $ingeoy, $pj); * printf("lat = %f
\n", $ret["u"]); * printf("lon = %f
\n",$ret["v"]); * * * 4) pj_transform : pj_transform(PJ pjsrc, PJ pjdst, double x, double y) * transforms coordinates from source projection to * destination projection. * * Example : $projarray[0] = "proj=lcc"; * $projarray[1] = "ellps=GRS80"; * $projarray[2] = "lat_0=49"; * $projarray[3] = "lon_0=-95"; * $projarray[4] = "lat_1=49"; * $projarray[5] = "lat_2=77"; * $projarray[6] = ""; * * $pjlcc = pj_init($projarray); * $projarray2[0] = "proj=latlong"; * $pjlat = pj_init($projarray2); * * $ingeox = 1537490.335842; * $ingeoy = -181633.471555; * * $ret = pj_transform($pjlcc, $pjlat, $ingeox, $ingeoy); * * 5) pj_free : frees PJ structure * * void pj_free(PJ pj); * **********************************************************************/ #ifdef USE_PROJ #include #include "php_mapscript_util.h" #include "php.h" #include "php_globals.h" #include "maperror.h" #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #else #include #endif #define ZEND_DEBUG 0 #ifndef DLEXPORT #define DLEXPORT ZEND_DLEXPORT #endif #define PHP_PROJ_VERSION "1.0.000 (Nov. 1, 2000)" /*===================================================================== * Prototypes *====================================================================*/ DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_info_proj(void); DLEXPORT int php_init_proj(INIT_FUNC_ARGS); DLEXPORT int php_end_proj(SHUTDOWN_FUNC_ARGS); DLEXPORT void ttt(INTERNAL_FUNCTION_PARAMETERS); #ifdef ZEND_VERSION PHP_MINFO_FUNCTION(phpproj); #else DLEXPORT void php_info_proj(void); #endif static zend_class_entry *proj_class_entry_ptr; #define PHPMS_GLOBAL(a) a static int le_projobj; function_entry php_proj_functions[] = { {"pj_fwd", php_proj_pj_fwd, NULL}, {"pj_inv", php_proj_pj_inv, NULL}, {"pj_init", php_proj_pj_init, NULL}, {"pj_transform", php_proj_pj_transform, NULL}, {"pj_datum_transform", php_proj_pj_datum_transform, NULL}, {"pj_free", php_proj_pj_free, NULL}, {NULL, NULL, NULL} }; php3_module_entry php_proj_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "PHPPROJ", php_proj_functions, php_init_proj, php_end_proj, NULL, NULL, #ifdef ZEND_VERSION PHP_MINFO(phpproj), #else php_info_proj, #endif #if ZEND_MODULE_API_NO >= 20010901 "phpproj, php4.1version", /* extension version number (string) */ #endif STANDARD_MODULE_PROPERTIES }; #if COMPILE_DL DLEXPORT php3_module_entry *get_module(void) { return &php_proj_module_entry; } #endif function_entry php_proj_class_functions[] = { {"ttt", ttt, NULL}, {NULL, NULL, NULL} }; DLEXPORT void ttt(INTERNAL_FUNCTION_PARAMETERS) { } #ifdef ZEND_VERSION PHP_MINFO_FUNCTION(phpproj) #else DLEXPORT void php_info_proj(void) #endif { php3_printf(" Version %s
\n", PHP_PROJ_VERSION); php3_printf("
\n"); } DLEXPORT int php_init_proj(INIT_FUNC_ARGS) { zend_class_entry tmp_class_entry; PHPMS_GLOBAL(le_projobj) = register_list_destructors(php_proj_pj_free, NULL); INIT_CLASS_ENTRY(tmp_class_entry, "proj", php_proj_class_functions); proj_class_entry_ptr = zend_register_internal_class(&tmp_class_entry TSRMLS_CC); return SUCCESS; } DLEXPORT int php_end_proj(SHUTDOWN_FUNC_ARGS) { return SUCCESS; } #if !defined DEG_TO_RAD #define DEG_TO_RAD 0.0174532925199432958 #endif #if !defined RAD_TO_DEG #define RAD_TO_DEG 57.29577951308232 #endif /********************************************************************** * _php_proj_build_proj_object **********************************************************************/ static long _php_proj_build_proj_object(PJ *pj, HashTable *list, pval *return_value TSRMLS_DC) { int pj_id; if (pj == NULL) return 0; pj_id = php3_list_insert(pj, PHPMS_GLOBAL(le_projobj)); _phpms_object_init(return_value, pj_id, php_proj_class_functions, PHP4_CLASS_ENTRY(proj_class_entry_ptr) TSRMLS_CC); return pj_id; } /************************************************************************/ /* DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Creates and initialize a PJ structure that can be used with */ /* proj_fwd and proj_inv function. */ /* */ /* Parameter : */ /* */ /* array : array of parameters */ /* */ /* Ex : */ /* */ /* $projarray[0] = "proj=lcc"; */ /* $projarray[1] = "ellps=GRS80"; */ /* $projarray[2] = "lat_0=49"; */ /* $projarray[3] = "lon_0=-95"; */ /* $projarray[4] = "lat_1=49"; */ /* $projarray[5] = "lat_2=77"; */ /* */ /* $pj = pj_init($projarray); */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS) { pval *pArrayOfParams = NULL; pval **pParam = NULL; HashTable *list=NULL; int nParamCount = 0; int i = 0; PJ *pj = NULL; char **papszBuf = NULL; // char *strttt = NULL; // int ttt; //ttt = strlen(strttt); /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 1, &pArrayOfParams) != SUCCESS) { WRONG_PARAM_COUNT; } if (pArrayOfParams->type == IS_ARRAY) nParamCount = _php3_hash_num_elements(pArrayOfParams->value.ht); else nParamCount = 0; if (nParamCount <= 0) RETURN_LONG(-1); papszBuf = (char **) malloc((nParamCount+2)*sizeof(char *)); for (i = 0; i < nParamCount; i++) { if (_php3_hash_index_find(pArrayOfParams->value.ht, i, (void **)&pParam) != FAILURE) { convert_to_string((*pParam)); if ((*pParam)->value.str.val != NULL) papszBuf[i] = strdup((*pParam)->value.str.val); } } papszBuf[i] = NULL; pj = pj_init(nParamCount, papszBuf); _php_proj_build_proj_object(pj, list, return_value TSRMLS_CC); } /************************************************************************/ /* DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Performs a projection from lat/long coordinates to */ /* cartesian coordinates (projection defines in the pj parameter) */ /* Parameters : */ /* */ /* - double p1 : latitude (in decimal degree ) */ /* - double p2 : longitude (in decimal degree ) */ /* - PJ pj : valid projection structure (see pj_init) */ /* */ /* Ex : */ /* $lat = 45.25; */ /* $lon = -75.42; */ /* */ /* $ret = pj_fwd($lat, $lon, $pj); */ /* printf("geo x = %f
\n", $ret["u"]); */ /* printf("geo y = %f
\n",$ret["v"]); */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS) { HashTable *list=NULL; pval *p1, *p2; pval *pj = NULL; PJ *popj = NULL; projUV pnt; projUV pntReturn = {0,0}; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 3, &p1, &p2, &pj) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); popj = (PJ *)_phpms_fetch_handle(pj, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (popj) { pnt.u = p2->value.dval * DEG_TO_RAD; pnt.v = p1->value.dval * DEG_TO_RAD; pntReturn = pj_fwd(pnt, popj); } add_assoc_double(return_value, "u", pntReturn.u); add_assoc_double(return_value, "v", pntReturn.v); } /************************************************************************/ /* DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Performs a projection from cartesian coordinates */ /* (projection defines in the pj parameter) to lat/long */ /* coordinates. */ /* */ /* Return vales are in decimal degrees. */ /* */ /* Parameters : */ /* */ /* - double p1 : projected coordinates (x) */ /* - double p2 : projected coordinates (y) */ /* - PJ pj : valid projection structure (see pj_init) */ /* */ /* Ex : */ /* $ingeox = 1537490.335842; */ /* $ingeoy = -181633.471555; */ /* */ /* $ret = pj_inv($ingeox, $ingeoy, $pj); */ /* */ /* printf("latitude = %f
\n", $ret["u"]); */ /* printf("longitude = %f
\n",$ret["v"]); */ /************************************************************************/ DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS) { HashTable *list=NULL; pval *p1, *p2; pval *pj = NULL; PJ *popj = NULL; projUV pnt; projUV pntReturn = {0,0}; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 3, &p1, &p2, &pj) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); popj = (PJ *)_phpms_fetch_handle(pj, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (popj) { pnt.u = p1->value.dval; pnt.v = p2->value.dval; pntReturn = pj_inv(pnt, popj); pntReturn.u *= RAD_TO_DEG; pntReturn.v *= RAD_TO_DEG; } add_assoc_double(return_value, "u", pntReturn.v); add_assoc_double(return_value, "v", pntReturn.u); } /************************************************************************/ /* DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Transform coordinates from source projection to destination */ /* projection. */ /* */ /* Parameters : */ /* */ /* - PJ *srcdefn, */ /* - PJ *dstdefn, */ /* - double x */ /* - double y */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS) { HashTable *list=NULL; pval *p1, *p2; pval *pjin, *pjout = NULL; PJ *in = NULL; PJ *out = NULL; projUV pnt = {0, 0}; double z = 0; int error = -1; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 4, &pjin , &pjout, &p1, &p2) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); in = (PJ *)_phpms_fetch_handle(pjin, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); out = (PJ *)_phpms_fetch_handle(pjout, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (in && out) { pnt.u = p1->value.dval; pnt.v = p2->value.dval; if( pj_is_latlong(in) ) { pnt.u *= DEG_TO_RAD; pnt.v *= DEG_TO_RAD; } error = pj_transform(in, out, 1, 0, &(pnt.u), &(pnt.v), &z ); if( pj_is_latlong(out) ) { pnt.u *= RAD_TO_DEG; pnt.v *= RAD_TO_DEG; } } if (error) { php_error(E_ERROR,"Error in pj_transform"); RETURN_LONG(-1); } else { add_assoc_double(return_value, "u", pnt.u); add_assoc_double(return_value, "v", pnt.v); } } /************************************************************************/ /* DLEXPORT */ /* void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Datum from source projection to destination */ /* projection. */ /* */ /* Parameters : */ /* */ /* - PJ *srcdefn, */ /* - PJ *dstdefn, */ /* - double x */ /* - double y */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS) { HashTable *list=NULL; pval *p1, *p2; pval *pjin, *pjout = NULL; PJ *in = NULL; PJ *out = NULL; projUV pnt = {0, 0}; double z = 0; int error = -1; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 4, &pjin , &pjout, &p1, &p2) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); in = (PJ *)_phpms_fetch_handle(pjin, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); out = (PJ *)_phpms_fetch_handle(pjout, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (in && out) { pnt.u = p1->value.dval; pnt.v = p2->value.dval; if( pj_is_latlong(in) ) { pnt.u *= DEG_TO_RAD; pnt.v *= DEG_TO_RAD; } error = pj_transform(in, out, 1, 0, &(pnt.u), &(pnt.v), &z ); if (!error) { if( pj_is_latlong(out) ) { pnt.u *= RAD_TO_DEG; pnt.v *= RAD_TO_DEG; } } } if (error) { php_error(E_ERROR,"Error in pj_datum_transform"); RETURN_LONG(-1); } else { add_assoc_double(return_value, "u", pnt.u); add_assoc_double(return_value, "v", pnt.v); } } /************************************************************************/ /* DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS) */ /************************************************************************/ DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS) { /* ==================================================================== */ /* TODO : freeing does not work properly on PHP4. */ /* ==================================================================== */ #ifdef PHP4_BAD_FREEING HashTable *list=NULL; pval *pj = NULL; PJ *popj = NULL; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 1, &pj) != SUCCESS) { WRONG_PARAM_COUNT; } popj = (PJ *)_phpms_fetch_handle(pj, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (popj) { pj_free(popj); } #endif } #endif /* USE_PROJ */ mapserver-6.4.1/mapscript/php/legend.c0000644002461700001440000002337012261257215017514 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_legend; ZEND_BEGIN_ARG_INFO_EX(legend___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(legend___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(legend_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto legend __construct() legendObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(legendObj, __construct) { mapscript_throw_exception("legendObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(legendObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_legend_object *php_legend; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = (php_legend_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("height", php_legend->legend->height) else IF_GET_LONG("width", php_legend->legend->width) else IF_GET_LONG("keysizex", php_legend->legend->keysizex) else IF_GET_LONG("keysizey", php_legend->legend->keysizey) else IF_GET_LONG("keyspacingx", php_legend->legend->keyspacingx) else IF_GET_LONG("keyspacingy", php_legend->legend->keyspacingy) else IF_GET_LONG("status", php_legend->legend->status) else IF_GET_LONG("position", php_legend->legend->position) else IF_GET_LONG("postlabelcache", php_legend->legend->postlabelcache) else IF_GET_STRING("template", php_legend->legend->template) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_legend->outlinecolor, &php_legend->legend->outlinecolor) else IF_GET_OBJECT("label", mapscript_ce_label, php_legend->label, &php_legend->legend->label) else IF_GET_OBJECT("imagecolor", mapscript_ce_color, php_legend->imagecolor, &php_legend->legend->imagecolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(legendObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_legend_object *php_legend; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = (php_legend_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_LONG("height", php_legend->legend->height, value) else IF_SET_LONG("width", php_legend->legend->width, value) else IF_SET_LONG("keysizex", php_legend->legend->keysizex, value) else IF_SET_LONG("keysizey", php_legend->legend->keysizey, value) else IF_SET_LONG("keyspacingx", php_legend->legend->keyspacingx, value) else IF_SET_LONG("keyspacingy", php_legend->legend->keyspacingy, value) else IF_SET_LONG("status", php_legend->legend->status, value) else IF_SET_LONG("position", php_legend->legend->position, value) else IF_SET_LONG("postlabelcache", php_legend->legend->postlabelcache, value) else IF_SET_STRING("template", php_legend->legend->template, value) else if ( (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("imagecolor", property)) || (STRING_EQUAL("label", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int legend.updateFromString(string snippet) Update a legend from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(legendObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_legend_object *php_legend; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = (php_legend_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = legendObj_updateFromString(php_legend->legend, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the legend object to string. */ PHP_METHOD(legendObj, convertToString) { zval *zobj = getThis(); php_legend_object *php_legend; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = (php_legend_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = legendObj_convertToString(php_legend->legend); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int legend.free() Free the object */ PHP_METHOD(legendObj, free) { zval *zobj = getThis(); php_legend_object *php_legend; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = (php_legend_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_legend->outlinecolor); MAPSCRIPT_DELREF(php_legend->imagecolor); MAPSCRIPT_DELREF(php_legend->label); } /* }}} */ zend_function_entry legend_functions[] = { PHP_ME(legendObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(legendObj, __get, legend___get_args, ZEND_ACC_PUBLIC) PHP_ME(legendObj, __set, legend___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(legendObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(legendObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(legendObj, updateFromString, legend_updateFromString_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_legend(legendObj *legend, parent_object parent, zval *return_value TSRMLS_DC) { php_legend_object * php_legend; object_init_ex(return_value, mapscript_ce_legend); php_legend = (php_legend_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_legend->legend = legend; php_legend->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_legend_object_destroy(void *object TSRMLS_DC) { php_legend_object *php_legend = (php_legend_object *)object; MAPSCRIPT_FREE_OBJECT(php_legend); MAPSCRIPT_FREE_PARENT(php_legend->parent); MAPSCRIPT_DELREF(php_legend->outlinecolor); MAPSCRIPT_DELREF(php_legend->imagecolor); MAPSCRIPT_DELREF(php_legend->label); /* We don't need to free the legendObj */ efree(object); } static zend_object_value mapscript_legend_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_legend_object *php_legend; MAPSCRIPT_ALLOC_OBJECT(php_legend, php_legend_object); retval = mapscript_object_new(&php_legend->std, ce, &mapscript_legend_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_legend->parent); php_legend->outlinecolor = NULL; php_legend->imagecolor = NULL; php_legend->label = NULL; return retval; } PHP_MINIT_FUNCTION(legend) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("legendObj", legend_functions, mapscript_ce_legend, mapscript_legend_object_new); mapscript_ce_legend->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/labelcachemember.c0000644002461700001440000002142712261257215021512 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_labelcachemember; ZEND_BEGIN_ARG_INFO_EX(labelcachemember___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(labelcachemember___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto void __construct() labelCacheMemberObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(labelCacheMemberObj, __construct) { mapscript_throw_exception("labelCacheMemberObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(labelCacheMemberObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_labelcachemember_object *php_labelcachemember; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcachemember = (php_labelcachemember_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("classindex", php_labelcachemember->labelcachemember->classindex) else IF_GET_LONG("featuresize", php_labelcachemember->labelcachemember->featuresize) else IF_GET_LONG("layerindex", php_labelcachemember->labelcachemember->layerindex) else IF_GET_LONG("numstyles", php_labelcachemember->labelcachemember->numstyles) else IF_GET_LONG("numlabels", php_labelcachemember->labelcachemember->numlabels) /* else IF_GET_LONG("shapeindex", php_labelcachemember->labelcachemember->shapeindex) */ else IF_GET_LONG("status", php_labelcachemember->labelcachemember->status) else IF_GET_LONG("markerid", php_labelcachemember->labelcachemember->markerid) /* else IF_GET_LONG("tileindex", php_labelcachemember->labelcachemember->tileindex) */ else IF_GET_OBJECT("point", mapscript_ce_point, php_labelcachemember->point, &php_labelcachemember->labelcachemember->point) else IF_GET_OBJECT("labels", mapscript_ce_label, php_labelcachemember->labels, &php_labelcachemember->labelcachemember->labels) else IF_GET_OBJECT("styles", mapscript_ce_style, php_labelcachemember->styles, php_labelcachemember->labelcachemember->styles) else IF_GET_OBJECT("poly", mapscript_ce_shape, php_labelcachemember->poly, php_labelcachemember->labelcachemember->poly) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(labelCacheMemberObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_labelcachemember_object *php_labelcachemember; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcachemember = (php_labelcachemember_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (STRING_EQUAL("classindex", property)) || (STRING_EQUAL("featuresize", property)) || (STRING_EQUAL("layerindex", property)) || (STRING_EQUAL("numstyles", property)) || (STRING_EQUAL("numlabels", property)) || (STRING_EQUAL("shapeindex", property)) || (STRING_EQUAL("status", property)) || (STRING_EQUAL("markerid", property)) || (STRING_EQUAL("tileindex", property)) || (STRING_EQUAL("labels", property)) || (STRING_EQUAL("styles", property)) || (STRING_EQUAL("poly", property)) || (STRING_EQUAL("point", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* proto void free() Free the object */ PHP_METHOD(labelCacheMemberObj, free) { zval *zobj = getThis(); php_labelcachemember_object *php_labelcachemember; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcachemember = (php_labelcachemember_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_labelcachemember->point); MAPSCRIPT_DELREF(php_labelcachemember->labels); MAPSCRIPT_DELREF(php_labelcachemember->styles); MAPSCRIPT_DELREF(php_labelcachemember->poly); } /* }}} */ zend_function_entry labelcachemember_functions[] = { PHP_ME(labelCacheMemberObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelCacheMemberObj, __get, labelcachemember___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelCacheMemberObj, __set, labelcachemember___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(labelCacheMemberObj, setProperty, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelCacheMemberObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_labelcachemember(labelCacheMemberObj *labelcachemember, parent_object parent, zval *return_value TSRMLS_DC) { php_labelcachemember_object * php_labelcachemember; object_init_ex(return_value, mapscript_ce_labelcachemember); php_labelcachemember = (php_labelcachemember_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_labelcachemember->labelcachemember = labelcachemember; php_labelcachemember->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_labelcachemember_object_destroy(void *object TSRMLS_DC) { php_labelcachemember_object *php_labelcachemember = (php_labelcachemember_object *)object; MAPSCRIPT_FREE_OBJECT(php_labelcachemember); MAPSCRIPT_FREE_PARENT(php_labelcachemember->parent); MAPSCRIPT_DELREF(php_labelcachemember->point); MAPSCRIPT_DELREF(php_labelcachemember->labels); MAPSCRIPT_DELREF(php_labelcachemember->styles); MAPSCRIPT_DELREF(php_labelcachemember->poly); /* We don't need to free the labelCacheMemberObj, the mapObj will do it */ efree(object); } static zend_object_value mapscript_labelcachemember_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_labelcachemember_object *php_labelcachemember; MAPSCRIPT_ALLOC_OBJECT(php_labelcachemember, php_labelcachemember_object); retval = mapscript_object_new(&php_labelcachemember->std, ce, &mapscript_labelcachemember_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_labelcachemember->parent); php_labelcachemember->point = NULL; php_labelcachemember->labels = NULL; php_labelcachemember->styles = NULL; php_labelcachemember->poly = NULL; return retval; } PHP_MINIT_FUNCTION(labelcachemember) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("labelCacheMemberObj", labelcachemember_functions, mapscript_ce_labelcachemember, mapscript_labelcachemember_object_new); mapscript_ce_labelcachemember->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/README0000644002461700001440000000014212261257215016762 0ustar tbonfortusersPlease see the PHP MapScript documentation at: http://www.mapserver.org/mapscript/php/index.html mapserver-6.4.1/mapscript/php/CMakeLists.txt0000644002461700001440000000250012261257215020642 0ustar tbonfortusersFIND_PACKAGE(PHP5 REQUIRED) INCLUDE_DIRECTORIES(${PHP5_INCLUDES}) IF(APPLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -undefined dynamic_lookup") SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -undefined dynamic_lookup") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -undefined dynamic_lookup") SET(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -undefined dynamic_lookup") endif(XCODE) ENDIF(APPLE) add_definitions(-DCOMPILE_DL=1) add_library(php_mapscript MODULE mapscript_error.c color.c rect.c hashtable.c web.c grid.c error.c referencemap.c querymap.c outputformat.c scalebar.c label.c legend.c symbol.c style.c image.c class.c projection.c line.c shape.c shapefile.c point.c labelcache.c labelleader.c labelcachemember.c result.c owsrequest.c cluster.c layer.c map.c php_mapscript_util.c php_mapscript.c mapscript_i.c ) target_link_libraries(php_mapscript ${MAPSERVER_LIBMAPSERVER}) set_target_properties(php_mapscript PROPERTIES PREFIX "") install(TARGETS php_mapscript DESTINATION ${PHP5_EXTENSION_DIR}) #install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mapscript.py DESTINATION ${PYTHON_SITE_PACKAGES}) #install(TARGETS mapscript DESTINATION ${PYTHON_SITE_PACKAGES}) mapserver-6.4.1/mapscript/php/mapscript_i.c0000644002461700001440000014273212261257215020574 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Interface file for MapServer PHP scripting extension * called MapScript. This file was originally based on * the SWIG interface file mapscript.i * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000, 2007, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" /* grab mapserver declarations to wrap */ #include "../../mapserver.h" #include "../../maperror.h" #include "../../mapprimitive.h" #include "../../mapsymbol.h" #include "../../mapshape.h" #include "../../mapproject.h" #include "../../maphash.h" /********************************************************************** * class extensions for mapObj **********************************************************************/ mapObj *mapObj_new(char *filename, char *new_path) { if(filename && strlen(filename)) return msLoadMap(filename, new_path); else { /* create an empty map, no layers etc... */ return msNewMapObj(); } } mapObj *mapObj_newFromString(char *map_text, char *new_path) { if(map_text && strlen(map_text)) return msLoadMapFromString(map_text, new_path); else { /* create an empty map, no layers etc... */ return msNewMapObj(); } } void mapObj_destroy(mapObj* self) { msFreeMap(self); } mapObj *mapObj_clone(mapObj* self) { mapObj *dstMap; dstMap = msNewMapObj(); if (msCopyMap(dstMap, self) != MS_SUCCESS) { msFreeMap(dstMap); dstMap = NULL; } return dstMap; } int mapObj_setRotation(mapObj* self, double rotation_angle ) { return msMapSetRotation( self, rotation_angle ); } layerObj *mapObj_getLayer(mapObj* self, int i) { if(i >= 0 && i < self->numlayers) return (self->layers[i]); /* returns an EXISTING layer */ else return NULL; } layerObj *mapObj_getLayerByName(mapObj* self, char *name) { int i; i = msGetLayerIndex(self, name); if(i != -1) return (self->layers[i]); /* returns an EXISTING layer */ else return NULL; } int *mapObj_getLayersIndexByGroup(mapObj* self, char *groupname, int *pnCount) { return msGetLayersIndexByGroup(self, groupname, pnCount); } int mapObj_getSymbolByName(mapObj* self, char *name) { return msGetSymbolIndex(&self->symbolset, name, MS_TRUE); } void mapObj_prepareQuery(mapObj* self) { int status; status = msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &self->scaledenom); if(status != MS_SUCCESS) self->scaledenom = -1; // degenerate extents ok here } imageObj *mapObj_prepareImage(mapObj* self) { return msPrepareImage(self, MS_FALSE); } imageObj *mapObj_draw(mapObj* self) { return msDrawMap(self, MS_FALSE); } imageObj *mapObj_drawQuery(mapObj* self) { return msDrawMap(self, MS_TRUE); } imageObj *mapObj_drawLegend(mapObj* self) { return msDrawLegend(self, MS_FALSE, NULL); } imageObj *mapObj_drawScalebar(mapObj* self) { return msDrawScalebar(self); } imageObj *mapObj_drawReferenceMap(mapObj* self) { return msDrawReferenceMap(self); } //TODO int mapObj_embedScalebar(mapObj* self, imageObj *img) { return msEmbedScalebar(self, img); } //TODO int mapObj_embedLegend(mapObj* self, imageObj *img) { return msEmbedLegend(self, img); } int mapObj_drawLabelCache(mapObj* self, imageObj *img) { return msDrawLabelCache(img, self); } labelCacheMemberObj* mapObj_getLabel(mapObj* self, int i) { return msGetLabelCacheMember(&(self->labelcache), i); } int mapObj_queryByPoint(mapObj* self, pointObj *point, int mode, double buffer) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_POINT; self->query.mode = mode; self->query.point = *point; self->query.buffer = buffer; return msQueryByPoint(self); } int mapObj_queryByRect(mapObj* self, rectObj rect) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_RECT; self->query.mode = MS_QUERY_MULTIPLE; self->query.rect = rect; return msQueryByRect(self); } int mapObj_queryByFeatures(mapObj* self, int slayer) { self->query.slayer = slayer; return msQueryByFeatures(self); } int mapObj_queryByFilter(mapObj* self, char *string) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_FILTER; self->query.filter = (expressionObj *) malloc(sizeof(expressionObj)); self->query.filter->compiled = MS_FALSE; self->query.filter->flags = 0; self->query.filter->tokens = self->query.filter->curtoken = NULL; self->query.filter->string = strdup(string); self->query.filter->type = 2000; /* MS_EXPRESSION: lot's of conflicts in mapfile.h */ self->query.rect = self->extent; return msQueryByFilter(self); } int mapObj_queryByShape(mapObj *self, shapeObj *shape) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_SHAPE; self->query.mode = MS_QUERY_MULTIPLE; self->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(self->query.shape); msCopyShape(shape, self->query.shape); return msQueryByShape(self); } int mapObj_queryByIndex(mapObj *self, int qlayer, int tileindex, int shapeindex, int bAddToQuery) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_INDEX; self->query.mode = MS_QUERY_SINGLE; self->query.tileindex = tileindex; self->query.shapeindex = shapeindex; self->query.clear_resultcache = !bAddToQuery; self->query.layer = qlayer; return msQueryByIndex(self); } int mapObj_saveQuery(mapObj *self, char *filename, int results) { return msSaveQuery(self, filename, results); } int mapObj_loadQuery(mapObj *self, char *filename) { return msLoadQuery(self, filename); } void mapObj_freeQuery(mapObj *self, int qlayer) { msQueryFree(self, qlayer); } int mapObj_setWKTProjection(mapObj *self, char *string) { return msOGCWKT2ProjectionObj(string, &(self->projection), self->debug); } char *mapObj_getProjection(mapObj* self) { return msGetProjectionString(&self->projection); } int mapObj_setProjection(mapObj* self, char *string) { return(msLoadProjectionString(&(self->projection), string)); } int mapObj_save(mapObj* self, char *filename) { return msSaveMap(self, filename); } char *mapObj_getMetaData(mapObj *self, char *name) { return(msLookupHashTable(&(self->web.metadata), name)); } int mapObj_setMetaData(mapObj *self, char *name, char *value) { if (msInsertHashTable(&(self->web.metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int mapObj_removeMetaData(mapObj *self, char *name) { return(msRemoveHashTable(&(self->web.metadata), name)); } int mapObj_moveLayerup(mapObj *self, int layerindex) { return msMoveLayerUp(self, layerindex); } int mapObj_moveLayerdown(mapObj *self, int layerindex) { return msMoveLayerDown(self, layerindex); } int *mapObj_getLayersdrawingOrder(mapObj *self) { return self->layerorder; } int mapObj_setLayersdrawingOrder(mapObj *self, int *panIndexes) { return msSetLayersdrawingOrder(self, panIndexes); } char *mapObj_processTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries) { return msProcessTemplate(self, bGenerateImages, names, values, numentries); } char *mapObj_processLegendTemplate(mapObj *self, char **names, char **values, int numentries) { return msProcessLegendTemplate(self, names, values, numentries); } char *mapObj_processQueryTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries) { return msProcessQueryTemplate(self, bGenerateImages, names, values, numentries); } int mapObj_setSymbolSet(mapObj *self, char *szFileName) { msFreeSymbolSet(&self->symbolset); msInitSymbolSet(&self->symbolset); // Set symbolset filename self->symbolset.filename = strdup(szFileName); // Symbolset shares same fontset as main mapfile self->symbolset.fontset = &(self->fontset); return msLoadSymbolSet(&self->symbolset, self); } int mapObj_getNumSymbols(mapObj *self) { return self->symbolset.numsymbols; } int mapObj_setFontSet(mapObj *self, char *szFileName) { msFreeFontSet(&(self->fontset)); msInitFontSet(&(self->fontset)); // Set fontset filename self->fontset.filename = strdup(szFileName); return msLoadFontSet(&(self->fontset), self); } int mapObj_saveMapContext(mapObj *self, char *szFilename) { return msSaveMapContext(self, szFilename); } int mapObj_loadMapContext(mapObj *self, char *szFilename, int bUniqueLayerName) { return msLoadMapContext(self, szFilename, bUniqueLayerName); } int mapObj_selectOutputFormat(mapObj *self, const char *imagetype) { outputFormatObj *format = NULL; format = msSelectOutputFormat(self, imagetype); if (format) { msApplyOutputFormat( &(self->outputformat), format, self->transparent, self->interlace, self->imagequality ); return(MS_SUCCESS); } return(MS_FAILURE); } int mapObj_applySLD(mapObj *self, char *sld) { return msSLDApplySLD(self, sld, -1, NULL, NULL); } int mapObj_applySLDURL(mapObj *self, char *sld) { return msSLDApplySLDURL(self, sld, -1, NULL, NULL); } char *mapObj_generateSLD(mapObj *self) { return msSLDGenerateSLD(self, -1, NULL); } int mapObj_loadOWSParameters(mapObj *self, cgiRequestObj *request, char *wmtver_string) { return msMapLoadOWSParameters(self, request, wmtver_string); } int mapObj_OWSDispatch(mapObj *self, cgiRequestObj *req ) { return msOWSDispatch( self, req, MS_TRUE); } int mapObj_insertLayer(mapObj *self, layerObj *layer, int index) { if (self && layer) return msInsertLayer(self, layer, index); return -1; } layerObj *mapObj_removeLayer(mapObj *self, int layerindex) { return msRemoveLayer(self, layerindex); } int mapObj_setCenter(mapObj *self, pointObj *center) { return msMapSetCenter(self, center); } int mapObj_offsetExtent(mapObj *self, double x, double y) { return msMapOffsetExtent(self, x, y); } int mapObj_scaleExtent(mapObj *self, double zoomfactor, double minscaledenom, double maxscaledenom) { return msMapScaleExtent(self, zoomfactor, minscaledenom, maxscaledenom); } char *mapObj_convertToString(mapObj *self) { return msWriteMapToString(self); } /********************************************************************** * class extensions for layerObj, always within the context of a map **********************************************************************/ layerObj *layerObj_new(mapObj *map) { if(msGrowMapLayers(map) == NULL) return(NULL); if(initLayer((map->layers[map->numlayers]), map) == -1) return(NULL); map->layers[map->numlayers]->index = map->numlayers; //Update the layer order list with the layer's index. map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; return (map->layers[map->numlayers-1]); } void layerObj_destroy(layerObj *self) { /* if the layer has a parent_map, let's the map object destroy it */ if ((self->map == NULL) && (self->refcount == 1)) { /* if there is no other PHP Object that use this C layer object, delete it */ freeLayer(self); free(self); self = NULL; } else { MS_REFCNT_DECR(self); } return; } layerObj *layerObj_clone(layerObj *layer) { layerObj *dstLayer; dstLayer = (layerObj *)malloc(sizeof(layerObj)); initLayer(dstLayer, layer->map); msCopyLayer(dstLayer, layer); return dstLayer; } int layerObj_updateFromString(layerObj *self, char *snippet) { return msUpdateLayerFromString(self, snippet, MS_FALSE); } char *layerObj_convertToString(layerObj *self) { return msWriteLayerToString(self); } int layerObj_open(layerObj *self) { return msLayerOpen(self); } int layerObj_whichShapes(layerObj *self, rectObj *poRect) { int oldconnectiontype = self->connectiontype; self->connectiontype = MS_INLINE; if(msLayerWhichItems(self, MS_FALSE, NULL) != MS_SUCCESS) { self->connectiontype = oldconnectiontype; return MS_FAILURE; } self->connectiontype = oldconnectiontype; return msLayerWhichShapes(self, *poRect, MS_FALSE); } shapeObj *layerObj_nextShape(layerObj *self) { int status; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); status = msLayerNextShape(self, shape); if(status != MS_SUCCESS) { msFreeShape(shape); free(shape); return NULL; } else return shape; } void layerObj_close(layerObj *self) { msLayerClose(self); } resultObj *layerObj_getResult(layerObj *self, int i) { if(!self->resultcache) return NULL; if(i >= 0 && i < self->resultcache->numresults) return &self->resultcache->results[i]; else return NULL; } classObj *layerObj_getClass(layerObj *self, int i) // returns an EXISTING class { if(i >= 0 && i < self->numclasses) return (self->class[i]); else return(NULL); } int layerObj_getClassIndex(layerObj *self, mapObj *map, shapeObj *shape, int *classgroup, int numclasses) { return msShapeGetClass(self, map, shape, classgroup, numclasses); } int layerObj_draw(layerObj *self, mapObj *map, imageObj *img) { return msDrawLayer(map, self, img); } int layerObj_drawQuery(layerObj *self, mapObj *map, imageObj *img) { return msDrawQueryLayer(map, self, img); } int layerObj_queryByAttributes(layerObj *self, mapObj *map, char *qitem, char *qstring, int mode) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_ATTRIBUTE; map->query.mode = mode; if(qitem) map->query.item = strdup(qitem); if(qstring) map->query.str = strdup(qstring); map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByAttributes(map); self->status = status; return retval; } int layerObj_queryByPoint(layerObj *self, mapObj *map, pointObj *point, int mode, double buffer) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_POINT; map->query.mode = mode; map->query.point = *point; map->query.buffer = buffer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByPoint(map); self->status = status; return retval; } int layerObj_queryByRect(layerObj *self, mapObj *map, rectObj rect) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.rect = rect; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByRect(map); self->status = status; return retval; } int layerObj_queryByFeatures(layerObj *self, mapObj *map, int slayer) { int status; int retval; map->query.slayer = slayer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByFeatures(map); self->status = status; return retval; } int layerObj_queryByShape(layerObj *self, mapObj *map, shapeObj *shape) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_SHAPE; map->query.mode = MS_QUERY_MULTIPLE; map->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(map->query.shape); msCopyShape(shape, map->query.shape); map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByShape(map); self->status = status; return retval; } int layerObj_queryByFilter(layerObj *self, mapObj *map, char *string) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.filter = (expressionObj *) malloc(sizeof(expressionObj)); map->query.filter->string = strdup(string); map->query.filter->type = 2000; /* MS_EXPRESSION: lot's of conflicts in mapfile.h */ map->query.filter->compiled = MS_FALSE; map->query.filter->flags = 0; map->query.filter->tokens = map->query.filter->curtoken = NULL; map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByFilter(map); self->status = status; return retval; } int layerObj_queryByIndex(layerObj *self, mapObj *map, int tileindex, int shapeindex, int addtoquery) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_INDEX; map->query.mode = MS_QUERY_SINGLE; map->query.tileindex = tileindex; map->query.shapeindex = shapeindex; map->query.clear_resultcache = !addtoquery; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByIndex(map); self->status = status; return retval; } int layerObj_setFilter(layerObj *self, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, string); } char *layerObj_getFilter(layerObj *self) { return msGetExpressionString(&(self->filter)); } int layerObj_setWKTProjection(layerObj *self, char *string) { self->project = MS_TRUE; return msOGCWKT2ProjectionObj(string, &(self->projection), self->debug); } char *layerObj_getProjection(layerObj* self) { return msGetProjectionString(&self->projection); } int layerObj_setProjection(layerObj *self, char *string) { int nReturn; nReturn = msLoadProjectionString(&(self->projection), string); if (nReturn == MS_SUCCESS) self->project = MS_TRUE; return nReturn; } int layerObj_addFeature(layerObj *self, shapeObj *shape) { if(self->features != NULL && self->features->tailifhead != NULL) shape->index = self->features->tailifhead->shape.index + 1; else shape->index = 0; if(insertFeatureList(&(self->features), shape) == NULL) return MS_FAILURE; else return MS_SUCCESS; } char *layerObj_getMetaData(layerObj *self, char *name) { return(msLookupHashTable(&(self->metadata), name)); } int layerObj_setMetaData(layerObj *self, char *name, char *value) { if (msInsertHashTable(&(self->metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int layerObj_removeMetaData(layerObj *self, char *name) { return(msRemoveHashTable(&(self->metadata), name)); } char *layerObj_getWMSFeatureInfoURL(layerObj *self, mapObj *map, int click_x, int click_y, int feature_count, char *info_format) { // NOTE: the returned string should be freed by the caller but right // now we're leaking it. return(msWMSGetFeatureInfoURL(map, self, click_x, click_y, feature_count, info_format)); } char *layerObj_executeWFSGetFeature(layerObj *self) { return (msWFSExecuteGetFeature(self)); } int layerObj_applySLD(layerObj *self, char *sld, char *stylelayer) { return msSLDApplySLD(self->map, sld, self->index, stylelayer, NULL); } int layerObj_applySLDURL(layerObj *self, char *sld, char *stylelayer) { return msSLDApplySLDURL(self->map, sld, self->index, stylelayer, NULL); } char *layerObj_generateSLD(layerObj *self) { return msSLDGenerateSLD(self->map, self->index, NULL); } int layerObj_moveClassUp(layerObj *self, int index) { return msMoveClassUp(self, index); } int layerObj_moveClassDown(layerObj *self, int index) { return msMoveClassDown(self, index); } classObj *layerObj_removeClass(layerObj *self, int index) { return msRemoveClass(self, index); } int layerObj_setConnectionType(layerObj *self, int connectiontype, const char *library_str) { /* Caller is responsible to close previous layer correctly before calling * msConnectLayer() */ if (msLayerIsOpen(self)) msLayerClose(self); return msConnectLayer(self, connectiontype, library_str); } /********************************************************************** * class extensions for labelObj **********************************************************************/ labelObj *labelObj_new() { labelObj *label; label = (labelObj *)malloc(sizeof(labelObj)); if(!label) return(NULL); initLabel(label); return label; } void labelObj_destroy(labelObj *self) { if (freeLabel(self) == MS_SUCCESS) free(self); } labelObj *labelObj_clone(labelObj *label) { labelObj *dstLabel; dstLabel = (labelObj *)malloc(sizeof(labelObj)); initLabel(dstLabel); dstLabel->font = NULL; msCopyLabel(dstLabel, label); return dstLabel; } int labelObj_updateFromString(labelObj *self, char *snippet) { return msUpdateLabelFromString(self, snippet, MS_FALSE); } char *labelObj_convertToString(labelObj *self) { return msWriteLabelToString(self); } int labelObj_moveStyleUp(labelObj *self, int index) { return msMoveLabelStyleUp(self, index); } int labelObj_moveStyleDown(labelObj *self, int index) { return msMoveLabelStyleDown(self, index); } int labelObj_deleteStyle(labelObj *self, int index) { return msDeleteLabelStyle(self, index); } int labelObj_setExpression(labelObj *self, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, string); } char *labelObj_getExpressionString(labelObj *self) { return msGetExpressionString(&(self->expression)); } int labelObj_setText(labelObj *self, layerObj *layer, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->text); return MS_SUCCESS; } return msLoadExpressionString(&self->text, string); } char *labelObj_getTextString(labelObj *self) { return msGetExpressionString(&(self->text)); } /********************************************************************** * class extensions for legendObj **********************************************************************/ int legendObj_updateFromString(legendObj *self, char *snippet) { return msUpdateLegendFromString(self, snippet, MS_FALSE); } char *legendObj_convertToString(legendObj *self) { return msWriteLegendToString(self); } /********************************************************************** * class extensions for queryMapObj **********************************************************************/ int queryMapObj_updateFromString(queryMapObj *self, char *snippet) { return msUpdateQueryMapFromString(self, snippet, MS_FALSE); } char *queryMapObj_convertToString(queryMapObj *self) { return msWriteQueryMapToString(self); } /********************************************************************** * class extensions for referenceMapObj **********************************************************************/ int referenceMapObj_updateFromString(referenceMapObj *self, char *snippet) { return msUpdateReferenceMapFromString(self, snippet, MS_FALSE); } char *referenceMapObj_convertToString(referenceMapObj *self) { return msWriteReferenceMapToString(self); } /********************************************************************** * class extensions for scaleBarObj **********************************************************************/ int scalebarObj_updateFromString(scalebarObj *self, char *snippet) { return msUpdateScalebarFromString(self, snippet, MS_FALSE); } char *scalebarObj_convertToString(scalebarObj *self) { return msWriteScalebarToString(self); } /********************************************************************** * class extensions for webObj **********************************************************************/ int webObj_updateFromString(webObj *self, char *snippet) { return msUpdateWebFromString(self, snippet, MS_FALSE); } char *webObj_convertToString(webObj *self) { return msWriteWebToString(self); } /********************************************************************** * class extensions for classObj, always within the context of a layer **********************************************************************/ classObj *classObj_new(layerObj *layer, classObj *class) { if(msGrowLayerClasses(layer) == NULL) return NULL; if(initClass((layer->class[layer->numclasses])) == -1) return NULL; if (class) { msCopyClass((layer->class[layer->numclasses]), class, layer); layer->class[layer->numclasses]->layer = layer; } layer->class[layer->numclasses]->type = layer->type; layer->class[layer->numclasses]->layer = layer; layer->numclasses++; return (layer->class[layer->numclasses-1]); } int classObj_addLabel(classObj *self, labelObj *label) { return msAddLabelToClass(self, label); } labelObj *classObj_removeLabel(classObj *self, int index) { return msRemoveLabelFromClass(self, index); } labelObj *classObj_getLabel(classObj *self, int i) // returns an EXISTING label { if(i >= 0 && i < self->numlabels) return (self->labels[i]); else return(NULL); } int classObj_updateFromString(classObj *self, char *snippet) { return msUpdateClassFromString(self, snippet, MS_FALSE); } char *classObj_convertToString(classObj *self) { return msWriteClassToString(self); } void classObj_destroy(classObj *self) { return; /* do nothing, map deconstrutor takes care of it all */ } int classObj_setExpression(classObj *self, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, string); } char *classObj_getExpressionString(classObj *self) { return msGetExpressionString(&(self->expression)); } int classObj_setText(classObj *self, layerObj *layer, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->text); return MS_SUCCESS; } return msLoadExpressionString(&self->text, string); } char *classObj_getTextString(classObj *self) { return msGetExpressionString(&(self->text)); } int classObj_drawLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height, imageObj *dstImg, int dstX, int dstY) { #ifdef USE_GD msClearLayerPenValues(layer); // just in case the mapfile has already been processed #endif return msDrawLegendIcon(map, layer, self, width, height, dstImg, dstX, dstY, MS_TRUE, NULL); } imageObj *classObj_createLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height) { return msCreateLegendIcon(map, layer, self, width, height, MS_TRUE); } int classObj_setSymbolByName(classObj *self, mapObj *map, char* pszSymbolName) { /* self->symbol = msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_TRUE); return self->symbol; */ return -1; } int classObj_setOverlaySymbolByName(classObj *self, mapObj *map, char* pszOverlaySymbolName) { /* self->overlaysymbol = msGetSymbolIndex(&map->symbolset, pszOverlaySymbolName, MS_TRUE); return self->overlaysymbol; */ return -1; } classObj *classObj_clone(classObj *class, layerObj *layer) { classObj *dstClass; dstClass = (classObj *)malloc(sizeof(classObj)); initClass(dstClass); msCopyClass(dstClass, class, layer); dstClass->type = layer->type; return dstClass; } int classObj_moveStyleUp(classObj *self, int index) { return msMoveStyleUp(self, index); } int classObj_moveStyleDown(classObj *self, int index) { return msMoveStyleDown(self, index); } int classObj_deleteStyle(classObj *self, int index) { return msDeleteStyle(self, index); } /********************************************************************** * class extensions for pointObj, useful many places **********************************************************************/ pointObj *pointObj_new() { return (pointObj *)malloc(sizeof(pointObj)); } void pointObj_destroy(pointObj *self) { free(self); } int pointObj_project(pointObj *self, projectionObj *in, projectionObj *out) { return msProjectPoint(in, out, self); } int pointObj_draw(pointObj *self, mapObj *map, layerObj *layer, imageObj *img, int class_index, char *label_string) { return msDrawPoint(map, layer, self, img, class_index, label_string); } double pointObj_distanceToPoint(pointObj *self, pointObj *point) { return msDistancePointToPoint(self, point); } double pointObj_distanceToLine(pointObj *self, pointObj *a, pointObj *b) { return msDistancePointToSegment(self, a, b); } double pointObj_distanceToShape(pointObj *self, shapeObj *shape) { return msDistancePointToShape(self, shape); } /********************************************************************** * class extensions for lineObj (eg. a line or group of points), * useful many places **********************************************************************/ lineObj *lineObj_new() { lineObj *line; line = (lineObj *)malloc(sizeof(lineObj)); if(!line) return(NULL); line->numpoints=0; line->point=NULL; return line; } void lineObj_destroy(lineObj *self) { free(self->point); free(self); } lineObj *lineObj_clone(lineObj *line) { lineObj *dstLine; dstLine = (lineObj *)malloc(sizeof(lineObj)); dstLine->numpoints= line->numpoints; dstLine->point = (pointObj *)malloc(sizeof(pointObj)*(dstLine->numpoints)); msCopyLine(dstLine, line); return dstLine; } int lineObj_project(lineObj *self, projectionObj *in, projectionObj *out) { return msProjectLine(in, out, self); } pointObj *lineObj_get(lineObj *self, int i) { if(i<0 || i>=self->numpoints) return NULL; else return &(self->point[i]); } int lineObj_add(lineObj *self, pointObj *p) { if(self->numpoints == 0) { /* new */ self->point = (pointObj *)malloc(sizeof(pointObj)); if(!self->point) return MS_FAILURE; } else { /* extend array */ self->point = (pointObj *)realloc(self->point, sizeof(pointObj)*(self->numpoints+1)); if(!self->point) return MS_FAILURE; } self->point[self->numpoints].x = p->x; self->point[self->numpoints].y = p->y; #ifdef USE_POINT_Z_M self->point[self->numpoints].m = p->m; #endif self->numpoints++; return MS_SUCCESS; } /********************************************************************** * class extensions for shapeObj **********************************************************************/ shapeObj *shapeObj_new(int type) { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if(!shape) return NULL; msInitShape(shape); shape->type = type; return shape; } void shapeObj_destroy(shapeObj *self) { msFreeShape(self); free(self); } int shapeObj_project(shapeObj *self, projectionObj *in, projectionObj *out) { return msProjectShape(in, out, self); } lineObj *shapeObj_get(shapeObj *self, int i) { if(i<0 || i>=self->numlines) return NULL; else return &(self->line[i]); } int shapeObj_add(shapeObj *self, lineObj *line) { return msAddLine(self, line); } int shapeObj_draw(shapeObj *self, mapObj *map, layerObj *layer, imageObj *img) { return msDrawShape(map, layer, self, img, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); } void shapeObj_setBounds(shapeObj *self) { int i, j; self->bounds.minx = self->bounds.maxx = self->line[0].point[0].x; self->bounds.miny = self->bounds.maxy = self->line[0].point[0].y; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { self->bounds.minx = MS_MIN(self->bounds.minx, self->line[i].point[j].x); self->bounds.maxx = MS_MAX(self->bounds.maxx, self->line[i].point[j].x); self->bounds.miny = MS_MIN(self->bounds.miny, self->line[i].point[j].y); self->bounds.maxy = MS_MAX(self->bounds.maxy, self->line[i].point[j].y); } } return; } int shapeObj_copy(shapeObj *self, shapeObj *dest) { return(msCopyShape(self, dest)); } int shapeObj_contains(shapeObj *self, pointObj *point) { if(self->type == MS_SHAPE_POLYGON) return msIntersectPointPolygon(point, self); return -1; } int shapeObj_intersects(shapeObj *self, shapeObj *shape) { switch(self->type) { case(MS_SHAPE_LINE): switch(shape->type) { case(MS_SHAPE_LINE): return msIntersectPolylines(self, shape); case(MS_SHAPE_POLYGON): return msIntersectPolylinePolygon(self, shape); } break; case(MS_SHAPE_POLYGON): switch(shape->type) { case(MS_SHAPE_LINE): return msIntersectPolylinePolygon(shape, self); case(MS_SHAPE_POLYGON): return msIntersectPolygons(self, shape); } break; } return -1; } pointObj *shapeObj_getpointusingmeasure(shapeObj *self, double m) { if (self) return msGetPointUsingMeasure(self, m); return NULL; } pointObj *shapeObj_getmeasureusingpoint(shapeObj *self, pointObj *point) { if (self) return msGetMeasureUsingPoint(self, point); return NULL; } shapeObj *shapeObj_buffer(shapeObj *self, double width) { return msGEOSBuffer(self, width); } shapeObj *shapeObj_simplify(shapeObj *self, double tolerance) { return msGEOSSimplify(self, tolerance); } shapeObj *shapeObj_topologypreservingsimplify(shapeObj *self, double tolerance) { return msGEOSTopologyPreservingSimplify(self, tolerance); } shapeObj *shapeObj_convexHull(shapeObj *self) { return msGEOSConvexHull(self); } shapeObj *shapeObj_boundary(shapeObj *self) { return msGEOSBoundary(self); } int shapeObj_contains_geos(shapeObj *self, shapeObj *shape) { return msGEOSContains(self, shape); } shapeObj *shapeObj_Union(shapeObj *self, shapeObj *shape) { return msGEOSUnion(self, shape); } shapeObj *shapeObj_intersection(shapeObj *self, shapeObj *shape) { return msGEOSIntersection(self, shape); } shapeObj *shapeObj_difference(shapeObj *self, shapeObj *shape) { return msGEOSDifference(self, shape); } shapeObj *shapeObj_symdifference(shapeObj *self, shapeObj *shape) { return msGEOSSymDifference(self, shape); } int shapeObj_overlaps(shapeObj *self, shapeObj *shape) { return msGEOSOverlaps(self, shape); } int shapeObj_within(shapeObj *self, shapeObj *shape) { return msGEOSWithin(self, shape); } int shapeObj_crosses(shapeObj *self, shapeObj *shape) { return msGEOSCrosses(self, shape); } int shapeObj_touches(shapeObj *self, shapeObj *shape) { return msGEOSTouches(self, shape); } int shapeObj_equals(shapeObj *self, shapeObj *shape) { return msGEOSEquals(self, shape); } int shapeObj_disjoint(shapeObj *self, shapeObj *shape) { return msGEOSDisjoint(self, shape); } pointObj *shapeObj_getcentroid(shapeObj *self) { return msGEOSGetCentroid(self); } double shapeObj_getarea(shapeObj *self) { return msGEOSArea(self); } double shapeObj_getlength(shapeObj *self) { return msGEOSLength(self); } pointObj *shapeObj_getLabelPoint(shapeObj *self) { pointObj *point = (pointObj *)calloc(1, sizeof(pointObj)); if (point == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for point", "getLabelPoint()"); return NULL; } if(self->type == MS_SHAPE_POLYGON && msPolygonLabelPoint(self, point, -1) == MS_SUCCESS) return point; free(point); return NULL; } /********************************************************************** * class extensions for rectObj **********************************************************************/ rectObj *rectObj_new() { rectObj *rect; rect = (rectObj *)calloc(1, sizeof(rectObj)); if(!rect) return(NULL); rect->minx = -1; rect->miny = -1; rect->maxx = -1; rect->maxy = -1; return(rect); } void rectObj_destroy(rectObj *self) { free(self); } int rectObj_project(rectObj *self, projectionObj *in, projectionObj *out) { return msProjectRect(in, out, self); } double rectObj_fit(rectObj *self, int width, int height) { return msAdjustExtent(self, width, height); } int rectObj_draw(rectObj *self, mapObj *map, layerObj *layer, imageObj *img, int classindex, char *text) { shapeObj shape; msInitShape(&shape); msRectToPolygon(*self, &shape); shape.classindex = classindex; if(text && layer->class[classindex]->numlabels > 0) { shape.text = strdup(text); msShapeGetAnnotation(layer,&shape); } msDrawShape(map, layer, &shape, img, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); msFreeShape(&shape); return 0; } /********************************************************************** * class extensions for shapefileObj **********************************************************************/ shapefileObj *shapefileObj_new(char *filename, int type) { shapefileObj *shapefile; int status; shapefile = (shapefileObj *)calloc(1,sizeof(shapefileObj)); if(!shapefile) return NULL; if(type == -1) status = msShapefileOpen(shapefile, "rb", filename, MS_TRUE); else if (type == -2) status = msShapefileOpen(shapefile, "rb+", filename, MS_TRUE); else status = msShapefileCreate(shapefile, filename, type); if(status == -1) { msShapefileClose(shapefile); free(shapefile); return NULL; } return(shapefile); } void shapefileObj_destroy(shapefileObj *self) { msShapefileClose(self); free(self); } int shapefileObj_get(shapefileObj *self, int i, shapeObj *shape) { if(i<0 || i>=self->numshapes) return -1; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); self->lastshape = i; return MS_SUCCESS; } int shapefileObj_getPoint(shapefileObj *self, int i, pointObj *point) { if(i<0 || i>=self->numshapes) return -1; return msSHPReadPoint(self->hSHP, i, point); } int shapefileObj_getTransformed(shapefileObj *self, mapObj *map, int i, shapeObj *shape) { if(i<0 || i>=self->numshapes) return -1; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); msTransformShapeSimplify(shape, map->extent, map->cellsize); return 0; } void shapefileObj_getExtent(shapefileObj *self, int i, rectObj *rect) { msSHPReadBounds(self->hSHP, i, rect); } int shapefileObj_add(shapefileObj *self, shapeObj *shape) { return msSHPWriteShape(self->hSHP, shape); } int shapefileObj_addPoint(shapefileObj *self, pointObj *point) { return msSHPWritePoint(self->hSHP, point); } /********************************************************************** * class extensions for projectionObj **********************************************************************/ projectionObj *projectionObj_new(char *string) { int status; projectionObj *proj=NULL; proj = (projectionObj *)malloc(sizeof(projectionObj)); if(!proj) return NULL; msInitProjection(proj); status = msLoadProjectionString(proj, string); if(status == -1) { msFreeProjection(proj); free(proj); return NULL; } return proj; } int projectionObj_getUnits(projectionObj *self) { return GetMapserverUnitUsingProj(self); } void projectionObj_destroy(projectionObj *self) { msFreeProjection(self); free(self); } projectionObj *projectionObj_clone(projectionObj *projection) { projectionObj *dstProjection; dstProjection = (projectionObj *)malloc(sizeof(projectionObj)); msInitProjection(dstProjection); msCopyProjection(dstProjection, projection); return dstProjection; } /********************************************************************** * class extensions for labelCacheObj - TP mods **********************************************************************/ void labelCacheObj_freeCache(labelCacheObj *self) { msFreeLabelCache(self); } /********************************************************************** * class extensions for DBFInfo - TP mods **********************************************************************/ char *DBFInfo_getFieldName(DBFInfo *self, int iField) { static char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pszFieldName; } int DBFInfo_getFieldWidth(DBFInfo *self, int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnWidth; } int DBFInfo_getFieldDecimals(DBFInfo *self, int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnDecimals; } DBFFieldType DBFInfo_getFieldType(DBFInfo *self, int iField) { return msDBFGetFieldInfo(self, iField, NULL, NULL, NULL); } /********************************************************************** * class extensions for styleObj, always within the context of a class **********************************************************************/ styleObj *styleObj_new(classObj *class, styleObj *style) { if(msGrowClassStyles(class) == NULL) return NULL; if(initStyle(class->styles[class->numstyles]) == -1) return NULL; if (style) msCopyStyle(class->styles[class->numstyles], style); class->numstyles++; return class->styles[class->numstyles-1]; } styleObj *styleObj_label_new(labelObj *label, styleObj *style) { if(msGrowLabelStyles(label) == NULL) return NULL; if(initStyle(label->styles[label->numstyles]) == -1) return NULL; if (style) msCopyStyle(label->styles[label->numstyles], style); label->numstyles++; return label->styles[label->numstyles-1]; } int styleObj_updateFromString(styleObj *self, char *snippet) { return msUpdateStyleFromString(self, snippet, MS_FALSE); } char *styleObj_convertToString(styleObj *self) { return msWriteStyleToString(self); } int styleObj_setSymbolByName(styleObj *self, mapObj *map, char* pszSymbolName) { self->symbol = msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_TRUE); return self->symbol; } styleObj *styleObj_clone(styleObj *style) { styleObj *newstyle = NULL; if (!style) return NULL; newstyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(newstyle); msCopyStyle(newstyle, style); return newstyle; } void styleObj_setGeomTransform(styleObj *style, char *transform) { if (!style) return; msStyleSetGeomTransform(style, transform); } cgiRequestObj *cgirequestObj_new() { cgiRequestObj *request; request = msAllocCgiObj(); return request; } int cgirequestObj_loadParams(cgiRequestObj *self, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context) { self->NumParams = loadParams(self, getenv2, raw_post_data, raw_post_data_length, thread_context); return self->NumParams; } void cgirequestObj_setParameter(cgiRequestObj *self, char *name, char *value) { int i; if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "setItem()", MS_DEFAULT_CGI_PARAMS); } for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { free(self->ParamValues[i]); self->ParamValues[i] = strdup(value); break; } } if (i == self->NumParams) { self->ParamNames[self->NumParams] = strdup(name); self->ParamValues[self->NumParams] = strdup(value); self->NumParams++; } } void cgirequestObj_addParameter(cgiRequestObj *self, char *name, char *value) { if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "addParameter()", MS_DEFAULT_CGI_PARAMS); } self->ParamNames[self->NumParams] = strdup(name); self->ParamValues[self->NumParams] = strdup(value); self->NumParams++; } char *cgirequestObj_getName(cgiRequestObj *self, int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getName()", self->NumParams-1); return NULL; } return self->ParamNames[index]; } char *cgirequestObj_getValue(cgiRequestObj *self, int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getValue()", self->NumParams-1); return NULL; } return self->ParamValues[index]; } char *cgirequestObj_getValueByName(cgiRequestObj *self, const char *name) { int i; for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { return self->ParamValues[i]; } } return NULL; } void cgirequestObj_destroy(cgiRequestObj *self) { free(self); } /********************************************************************** * class extensions hashTableObj **********************************************************************/ // New instance hashTableObj *hashTableObj_new() { return msCreateHashTable(); } // set a hash item given key and value int hashTableObj_set(hashTableObj *self, const char *key, const char *value) { if (msInsertHashTable(self, key, value) == NULL) { return MS_FAILURE; } return MS_SUCCESS; } // get value from item by its key const char *hashTableObj_get(hashTableObj *self, const char *key) { return (msLookupHashTable(self, key)); } // Remove one item from hash table int hashTableObj_remove(hashTableObj *self, const char *key) { return (msRemoveHashTable(self, key)); } // Clear all items in hash table (to NULL) void hashTableObj_clear(hashTableObj *self) { msFreeHashItems(self); initHashTable(self); } // Return the next key or first key if previousKey == NULL char *hashTableObj_nextKey(hashTableObj *self, const char *previousKey) { return ((char *)msNextKeyFromHashTable(self, previousKey)); } resultObj *resultObj_new() { resultObj *r = (resultObj *) msSmallMalloc(sizeof(resultObj)); r->tileindex = -1; r->shapeindex = -1; r->resultindex = -1; return r; } /********************************************************************** * class extensions clusterObj **********************************************************************/ int clusterObj_updateFromString(clusterObj *self, char *snippet) { return msUpdateClusterFromString(self, snippet); } char *clusterObj_convertToString(clusterObj *self) { return msWriteClusterToString(self); } int clusterObj_setGroup(clusterObj *self, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->group); return MS_SUCCESS; } else return msLoadExpressionString(&self->group, string); } char *clusterObj_getGroupString(clusterObj *self) { return msGetExpressionString(&(self->group)); } int clusterObj_setFilter(clusterObj *self, char *string) { if (!string || strlen(string) == 0) { freeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, string); } char *clusterObj_getFilterString(clusterObj *self) { return msGetExpressionString(&(self->filter)); } outputFormatObj* outputFormatObj_new(const char *driver, char *name) { outputFormatObj *format; format = msCreateDefaultOutputFormat(NULL, driver, name); /* in the case of unsupported formats, msCreateDefaultOutputFormat should return NULL */ if (!format) { msSetError(MS_MISCERR, "Unsupported format driver: %s", "outputFormatObj()", driver); return NULL; } msInitializeRendererVTable(format); /* Else, continue */ format->refcount++; format->inmapfile = MS_TRUE; return format; } void outputFormatObj_destroy(outputFormatObj* self) { if ( --self->refcount < 1 ) msFreeOutputFormat( self ); } imageObj *symbolObj_getImage(symbolObj *self, outputFormatObj *input_format) { imageObj *image = NULL; outputFormatObj *format = NULL; rendererVTableObj *renderer = NULL; if (self->type != MS_SYMBOL_PIXMAP) { msSetError(MS_SYMERR, "Can't return image from non-pixmap symbol", "getImage()"); return NULL; } if (input_format) { format = input_format; } else { format = msCreateDefaultOutputFormat(NULL, "GD/GIF", "gdgif"); if (format == NULL) format = msCreateDefaultOutputFormat(NULL, "GD/PNG", "gdpng"); if (format) msInitializeRendererVTable(format); } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "getImage()"); return NULL; } renderer = format->vtable; msPreloadImageSymbol(renderer, self); if (self->pixmap_buffer) { image = msImageCreate(self->pixmap_buffer->width, self->pixmap_buffer->height, format, NULL, NULL, MS_DEFAULT_RESOLUTION, MS_DEFAULT_RESOLUTION, NULL); renderer->mergeRasterBuffer(image, self->pixmap_buffer, 1.0, 0, 0, 0, 0, self->pixmap_buffer->width, self->pixmap_buffer->height); } return image; } int symbolObj_setImage(symbolObj *self, imageObj *image) { rendererVTableObj *renderer = NULL; renderer = image->format->vtable; if (self->pixmap_buffer) { msFreeRasterBuffer(self->pixmap_buffer); free(self->pixmap_buffer); } self->pixmap_buffer = (rasterBufferObj*)malloc(sizeof(rasterBufferObj)); if (!self->pixmap_buffer) { msSetError(MS_MEMERR, NULL, "setImage()"); return MS_FAILURE; } self->type = MS_SYMBOL_PIXMAP; renderer->getRasterBufferCopy(image, self->pixmap_buffer); return MS_SUCCESS; } mapserver-6.4.1/mapscript/php/owsrequest.c0000644002461700001440000003454612261257215020506 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" #include "SAPI.h" #include "php_variables.h" char *owsrequest_getenv(const char *name, void *thread_context); zend_class_entry *mapscript_ce_owsrequest; ZEND_BEGIN_ARG_INFO_EX(owsrequest___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_setParameter_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_addParameter_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_getName_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_getValue_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_getValueByName_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() /* {{{ proto owsrequest __construct() Create a new OWSRequestObj instance. */ PHP_METHOD(OWSRequestObj, __construct) { zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; cgiRequestObj *request; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((request = cgirequestObj_new()) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } php_owsrequest->cgirequest = request; } /* }}} */ PHP_METHOD(OWSRequestObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numparams", php_owsrequest->cgirequest->NumParams) else IF_GET_STRING("contenttype", php_owsrequest->cgirequest->contenttype) else IF_GET_STRING("postrequest", php_owsrequest->cgirequest->postrequest) else IF_GET_STRING("httpcookiedata", php_owsrequest->cgirequest->httpcookiedata) else IF_GET_LONG("type", php_owsrequest->cgirequest->type) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(OWSRequestObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (STRING_EQUAL("numparams", property)) || (STRING_EQUAL("type", property)) || (STRING_EQUAL("contenttype", property)) || (STRING_EQUAL("postrequest", property)) || (STRING_EQUAL("httpcookiedata", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int owsrequest.loadParams() Initializes the OWSRequest object from the cgi environment variables REQUEST_METHOD, QUERY_STRING and HTTP_COOKIE. Returns the number of name/value pairs collected. */ PHP_METHOD(OWSRequestObj, loadParams) { zval *zobj = getThis(); zval **val; php_owsrequest_object *php_owsrequest; void *thread_context; #ifdef ZTS thread_context = (void*)TSRMLS_C; #else thread_context = NULL; #endif //PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { //PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } //PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (STRING_EQUAL(sapi_module.name,"cli")) || (STRING_EQUAL(sapi_module.name,"cgi")) || (STRING_EQUAL(sapi_module.name,"cgi-fcgi")) ) { cgirequestObj_loadParams(php_owsrequest->cgirequest, NULL, NULL, 0, thread_context); } else { // check if we have input data for GET method if (SG(request_info).request_method && STRING_EQUAL(SG(request_info).request_method, "GET")) { zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if ( PG(http_globals)[TRACK_VARS_SERVER] && (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "QUERY_STRING", sizeof("QUERY_STRING"), (void **) &val) == SUCCESS) && (Z_TYPE_PP(val) == IS_STRING) && (Z_STRLEN_PP(val) > 0) ) { cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, NULL, 0, thread_context); } } else { cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, SG(request_info).raw_post_data, SG(request_info).raw_post_data_length, thread_context); } } RETURN_LONG(php_owsrequest->cgirequest->NumParams); } /* }}} */ /* {{{ proto int owsrequest.setParameter(string name, string value) Set a request parameter. */ PHP_METHOD(OWSRequestObj, setParameter) { char *name; long name_len = 0; char *value; long value_len = 0; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); cgirequestObj_setParameter(php_owsrequest->cgirequest, name, value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int owsrequest.addParameter(string name, string value) Add a request parameter. */ PHP_METHOD(OWSRequestObj, addParameter) { char *name; long name_len = 0; char *value; long value_len = 0; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); cgirequestObj_addParameter(php_owsrequest->cgirequest, name, value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto string owsrequest.getName(int index) Return the name of the parameter at index in the request’s array of parameter names. */ PHP_METHOD(OWSRequestObj, getName) { long index; zval *zobj = getThis(); char *value = NULL; php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = cgirequestObj_getName(php_owsrequest->cgirequest, index); if (!value) RETURN_STRING("", 1); RETURN_STRING(value,1); } /* }}} */ /* {{{ proto string owsrequest.getValue(int index) Return the value of the parameter at index in the request’s array of parameter values.*/ PHP_METHOD(OWSRequestObj, getValue) { long index; zval *zobj = getThis(); char *value = NULL; php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = cgirequestObj_getValue(php_owsrequest->cgirequest, index); if (!value) RETURN_STRING("", 1); RETURN_STRING(value,1); } /* }}} */ /* {{{ proto string owsrequest.getValueByName(string name) Return the value associated with the parameter name.*/ PHP_METHOD(OWSRequestObj, getValueByName) { char *name; long name_len = 0; zval *zobj = getThis(); char *value = NULL; php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = (php_owsrequest_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = cgirequestObj_getValueByName(php_owsrequest->cgirequest, name); if (!value) RETURN_STRING("", 1); RETURN_STRING(value,1); } /* }}} */ zend_function_entry owsrequest_functions[] = { PHP_ME(OWSRequestObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(OWSRequestObj, __get, owsrequest___get_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, __set, owsrequest___set_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, loadParams, NULL, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, setParameter, owsrequest_setParameter_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, addParameter, owsrequest_addParameter_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, getName, owsrequest_getName_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, getValue, owsrequest_getValue_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, getValueByName, owsrequest_getValueByName_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; char *owsrequest_getenv(const char *name, void *thread_context) { zval **val, **ppzval; zval *cookie_result, *key; HashTable *cookies; char *string_key = NULL, *cookie_tmp; ulong num_key; int numElements, i = 0; TSRMLS_FETCH_FROM_CTX(thread_context); if (STRING_EQUAL(name, "HTTP_COOKIE")) { cookies = PG(http_globals)[TRACK_VARS_COOKIE]->value.ht; numElements = zend_hash_num_elements(cookies); MAKE_STD_ZVAL(cookie_result); ZVAL_STRING(cookie_result, "",1); for(zend_hash_internal_pointer_reset(cookies); zend_hash_has_more_elements(cookies) == SUCCESS; zend_hash_move_forward(cookies), ++i) { zend_hash_get_current_data(cookies, (void **)&ppzval); zend_hash_get_current_key(cookies, &string_key, &num_key, 1); cookie_tmp = malloc((strlen(string_key)+Z_STRLEN_PP(ppzval)+3) * sizeof(char)); sprintf(cookie_tmp, "%s=%s;",string_key,Z_STRVAL_PP(ppzval)); MAKE_STD_ZVAL(key); ZVAL_STRING(key, cookie_tmp,1); add_string_to_string(cookie_result,cookie_result, key); zval_dtor(key); free(cookie_tmp); } return Z_STRVAL_P(cookie_result); } else { zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if ( PG(http_globals)[TRACK_VARS_SERVER] && (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, name, strlen(name)+1, (void **) &val) == SUCCESS) && (Z_TYPE_PP(val) == IS_STRING)) { return Z_STRVAL_PP(val); } } return NULL; } void mapscript_create_owsrequest(cgiRequestObj *cgirequest, zval *return_value TSRMLS_DC) { php_owsrequest_object * php_owsrequest; object_init_ex(return_value, mapscript_ce_owsrequest); php_owsrequest = (php_owsrequest_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_owsrequest->cgirequest = cgirequest; } static void mapscript_owsrequest_object_destroy(void *object TSRMLS_DC) { php_owsrequest_object *php_owsrequest = (php_owsrequest_object *)object; MAPSCRIPT_FREE_OBJECT(php_owsrequest); cgirequestObj_destroy(php_owsrequest->cgirequest); efree(object); } static zend_object_value mapscript_owsrequest_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_owsrequest_object *php_owsrequest; MAPSCRIPT_ALLOC_OBJECT(php_owsrequest, php_owsrequest_object); retval = mapscript_object_new(&php_owsrequest->std, ce, &mapscript_owsrequest_object_destroy TSRMLS_CC); return retval; } PHP_MINIT_FUNCTION(owsrequest) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("OWSRequestObj", owsrequest_functions, mapscript_ce_owsrequest, mapscript_owsrequest_object_new); mapscript_ce_owsrequest->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/map.c0000644002461700001440000036347112261257215017044 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_map; zend_object_handlers mapscript_map_object_handlers; static int mapscript_map_setProjection(int isWKTProj, php_map_object *php_map, char *projString, int setUnitsAndExtents TSRMLS_DC); ZEND_BEGIN_ARG_INFO_EX(map___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, mapFileName) ZEND_ARG_INFO(0, newMapPath) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getSymbolByName_args, 0, 0, 1) ZEND_ARG_INFO(0, symbolName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getSymbolObjectById_args, 0, 0, 1) ZEND_ARG_INFO(0, symbolId) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_embedLegend_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_embedScaleBar_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_drawLabelCache_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLayer_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLayerByName_args, 0, 0, 1) ZEND_ARG_INFO(0, layerName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getColorByIndex_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setExtent_args, 0, 0, 4) ZEND_ARG_INFO(0, minx) ZEND_ARG_INFO(0, miny) ZEND_ARG_INFO(0, maxx) ZEND_ARG_INFO(0, maxy) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setCenter_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_offsetExtent_args, 0, 0, 2) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_scaleExtent_args, 0, 0, 3) ZEND_ARG_INFO(0, zoomFactor) ZEND_ARG_INFO(0, minScaleDenom) ZEND_ARG_INFO(0, maxScaleDenom) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setRotation_args, 0, 0, 1) ZEND_ARG_INFO(0, angle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setSize_args, 0, 0, 2) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_zoomPoint_args, 0, 0, 5) ZEND_ARG_INFO(0, zoomFactor) ZEND_ARG_OBJ_INFO(0, pixelPosition, pointObj, 0) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, geoRefExtent, rectObj, 0) ZEND_ARG_OBJ_INFO(0, maxGeoRefExtent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_zoomRectangle_args, 0, 0, 4) ZEND_ARG_OBJ_INFO(0, pixelExtent, rectObj, 0) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, geoRefExtent, rectObj, 0) ZEND_ARG_OBJ_INFO(0, maxGeoRefExtent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_zoomScale_args, 0, 0, 5) ZEND_ARG_INFO(0, scaleDenom) ZEND_ARG_OBJ_INFO(0, pixelPosition, pointObj, 0) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, geoRefExtent, rectObj, 0) ZEND_ARG_OBJ_INFO(0, maxGeoRefExtent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByPoint_args, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, buffer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByRect_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, rect, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByFeatures_args, 0, 0, 1) ZEND_ARG_INFO(0, slayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByIndex_args, 0, 0, 3) ZEND_ARG_INFO(0, layerIndex) ZEND_ARG_INFO(0, tileIndex) ZEND_ARG_INFO(0, shapeIndex) ZEND_ARG_INFO(0, addToQuery) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, string) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_saveQuery_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, results) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_saveQueryAsGML_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, namespace) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_loadQuery_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_freeQuery_args, 0, 0, 1) ZEND_ARG_INFO(0, layerIndex) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_save_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_ARG_INFO(0, setUnitsAndExtents) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setWKTProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_ARG_INFO(0, setUnitsAndExtents) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setMetaData_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_removeMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLayersIndexByGroup_args, 0, 0, 1) ZEND_ARG_INFO(0, groupName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_moveLayerUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_moveLayerDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setLayersDrawingOrder_args, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, layerIndexes, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_processTemplate_args, 0, 0, 2) ZEND_ARG_ARRAY_INFO(0, params, 0) ZEND_ARG_INFO(0, generateImages) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_processQueryTemplate_args, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, params, 0) ZEND_ARG_INFO(0, generateImages) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_processLegendTemplate_args, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, params, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setSymbolSet_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setFontSet_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_selectOutputFormat_args, 0, 0, 1) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_appendOutputFormat_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, outputformat, outputFormatObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_removeOutputFormat_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getOutputFormat_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_saveMapContext_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_loadMapContext_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, uniqueLayerName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_applySLD_args, 0, 0, 1) ZEND_ARG_INFO(0, sldxml) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_applySLDURL_args, 0, 0, 1) ZEND_ARG_INFO(0, sldurl) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getConfigOption_args, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setConfigOption_args, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_loadOwsParameters_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, request, owsRequestObj, 0) ZEND_ARG_INFO(0, version) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_owsDispatch_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, request, owsRequestObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_insertLayer_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_removeLayer_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLabel_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto void __construct(string mapFileName, newMapPath) Create a new mapObj instance. */ PHP_METHOD(mapObj, __construct) { zval *zobj = getThis(); char *filename; long filename_len = 0; char *path = NULL; long path_len = 0; mapObj *map; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename, &filename_len, &path, &path_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *)zend_object_store_get_object(zobj TSRMLS_CC); map = mapObj_new(filename, path); if (map == NULL) { mapscript_throw_mapserver_exception("Failed to open map file %s" TSRMLS_CC, filename); return; } php_map->map = map; } /* }}} */ PHP_METHOD(mapObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numlayers", php_map->map->numlayers) else IF_GET_STRING("name", php_map->map->name) else IF_GET_STRING("mappath", php_map->map->mappath) else IF_GET_STRING("imagetype", php_map->map->imagetype) else IF_GET_LONG("status", php_map->map->status) else IF_GET_LONG("debug", php_map->map->debug) else IF_GET_LONG("width", php_map->map->width) else IF_GET_LONG("height", php_map->map->height) else IF_GET_LONG("maxsize", php_map->map->maxsize) else IF_GET_DOUBLE("resolution", php_map->map->resolution) else IF_GET_DOUBLE("defresolution", php_map->map->defresolution) else IF_GET_DOUBLE("cellsize", php_map->map->cellsize) else IF_GET_LONG("units", php_map->map->units) else IF_GET_DOUBLE("scaledenom", php_map->map->scaledenom) else IF_GET_STRING("shapepath", php_map->map->shapepath) else IF_GET_LONG("keysizex", php_map->map->legend.keysizex) else IF_GET_LONG("keysizey", php_map->map->legend.keysizey) else IF_GET_LONG("keyspacingx", php_map->map->legend.keyspacingx) else IF_GET_LONG("keyspacingy", php_map->map->legend.keyspacingy) else IF_GET_STRING("symbolsetfilename", php_map->map->symbolset.filename) else IF_GET_LONG("numoutputformats", php_map->map->numoutputformats) else IF_GET_STRING("fontsetfilename", php_map->map->fontset.filename) else IF_GET_OBJECT("outputformat", mapscript_ce_outputformat, php_map->outputformat, php_map->map->outputformat) else IF_GET_OBJECT("configoptions", mapscript_ce_hashtable, php_map->configoptions, &php_map->map->configoptions) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_map->extent, &php_map->map->extent) else IF_GET_OBJECT("web", mapscript_ce_web, php_map->web, &php_map->map->web) else IF_GET_OBJECT("reference", mapscript_ce_referencemap, php_map->reference, &php_map->map->reference) else IF_GET_OBJECT("imagecolor", mapscript_ce_color, php_map->imagecolor, &php_map->map->imagecolor) else IF_GET_OBJECT("scalebar", mapscript_ce_scalebar, php_map->scalebar, &php_map->map->scalebar) else IF_GET_OBJECT("legend", mapscript_ce_legend, php_map->legend, &php_map->map->legend) else IF_GET_OBJECT("querymap", mapscript_ce_querymap, php_map->querymap, &php_map->map->querymap) else IF_GET_OBJECT("labelcache", mapscript_ce_labelcache, php_map->labelcache, &php_map->map->labelcache) else IF_GET_OBJECT("projection", mapscript_ce_projection, php_map->projection, &php_map->map->projection) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(mapObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("name", php_map->map->name, value) else IF_SET_LONG("status", php_map->map->status, value) else IF_SET_LONG("debug", php_map->map->debug, value) else IF_SET_LONG("width", php_map->map->width, value) else IF_SET_LONG("height", php_map->map->height, value) else IF_SET_LONG("maxsize", php_map->map->maxsize, value) else IF_SET_DOUBLE("resolution", php_map->map->resolution, value) else IF_SET_DOUBLE("defresolution", php_map->map->defresolution, value) else IF_SET_DOUBLE("cellsize", php_map->map->cellsize, value) else IF_SET_LONG("units", php_map->map->units, value) else IF_SET_DOUBLE("scaledenom", php_map->map->scaledenom, value) else IF_SET_STRING("shapepath", php_map->map->shapepath, value) else IF_SET_LONG("keysizex", php_map->map->legend.keysizex, value) else IF_SET_LONG("keysizey", php_map->map->legend.keysizey, value) else IF_SET_LONG("keyspacingx", php_map->map->legend.keyspacingx, value) else IF_SET_LONG("keyspacingy", php_map->map->legend.keyspacingy, value) else if ( (STRING_EQUAL("outputformat", property)) || (STRING_EQUAL("extent", property)) || (STRING_EQUAL("web", property)) || (STRING_EQUAL("reference", property)) || (STRING_EQUAL("scalebar", property)) || (STRING_EQUAL("legend", property)) || (STRING_EQUAL("querymap", property)) || (STRING_EQUAL("labelcache", property)) || (STRING_EQUAL("projection", property)) || (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("configoptions", property)) || (STRING_EQUAL("imagecolor", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("numlayers", property)) || (STRING_EQUAL("symbolsetfilename", property)) || (STRING_EQUAL("imagetype", property)) || (STRING_EQUAL("numoutputformats", property)) || (STRING_EQUAL("mappath", property)) || (STRING_EQUAL("fontsetfilename", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int map.getSymbolByName(string symbolName) Returns the symbol index using the name. */ PHP_METHOD(mapObj, getSymbolByName) { zval *zobj = getThis(); char *symbolName; long symbolName_len = 0; int symbolId = -1; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &symbolName, &symbolName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); symbolId = mapObj_getSymbolByName(php_map->map, symbolName); RETURN_LONG(symbolId); } /* }}} */ /* {{{ proto symbolObj map.getSymbolObjectById(int symbolId) Returns the symbol object using a symbol id. Refer to the symbol object reference section for more details. */ PHP_METHOD(mapObj, getSymbolObjectById) { zval *zobj = getThis(); long symbolId; symbolObj *symbol = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &symbolId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( symbolId < 0 || symbolId >= php_map->map->symbolset.numsymbols) { mapscript_throw_exception("Invalid symbol index." TSRMLS_CC); return; } symbol = php_map->map->symbolset.symbol[symbolId]; /* Return style object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_symbol(symbol, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto void map.prepareQuery() Calculate the scale of the map and assign it to the map->scaledenom */ PHP_METHOD(mapObj, prepareQuery) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); mapObj_prepareQuery(php_map->map); } /* }}} */ /* {{{ proto imageObj map.prepareImage() Return handle on blank image object. */ PHP_METHOD(mapObj, prepareImage) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); image = mapObj_prepareImage(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return an image object */ mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto imageObj map.draw() Render map and return handle on image object. */ PHP_METHOD(mapObj, draw) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); image = mapObj_draw(php_map->map); if (image == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawQuery() Renders a query map, returns an image.. */ PHP_METHOD(mapObj, drawQuery) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); image = mapObj_drawQuery(php_map->map); if (image == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawLegend() Render legend and return handle on image object. */ PHP_METHOD(mapObj, drawLegend) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); image = mapObj_drawLegend(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawReferenceMap() Render reference map and return handle on image object. */ PHP_METHOD(mapObj, drawReferenceMap) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); image = mapObj_drawReferenceMap(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawScaleBar() Render scale bar and return handle on image object. */ PHP_METHOD(mapObj, drawScaleBar) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); image = mapObj_drawScalebar(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.embedLegend(image img) Renders the legend within the map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, embedLegend) { zval *zobj = getThis(); zval *zimage; int retval = MS_FAILURE; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); retval = mapObj_embedLegend(php_map->map, php_image->image); if ( (retval == MS_FAILURE) || (retval == -1) ) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto int map.embedScalebar(image img) Renders the scalebar within the map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, embedScaleBar) { zval *zobj = getThis(); zval *zimage; int retval = MS_FAILURE; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); retval = mapObj_embedScalebar(php_map->map, php_image->image); if ( (retval == MS_FAILURE) || (retval == -1) ) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto layerObj map.drawLabelCache(image img) Renders the labels for a map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, drawLabelCache) { zval *zobj = getThis(); zval *zimage; int retval = MS_FAILURE; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); retval = mapObj_drawLabelCache(php_map->map, php_image->image); if ( (retval == MS_FAILURE) || (retval == -1) ) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto int map.getLayer(int index) Returns a layerObj from the map given an index value (0=first layer, etc.) */ PHP_METHOD(mapObj, getLayer) { zval *zobj = getThis(); long index; layerObj *layer = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); layer = mapObj_getLayer(php_map->map, index); if (layer == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return layer object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto layerObj map.getLayerByName(string layerName) Returns a layerObj from the map given a layer name */ PHP_METHOD(mapObj, getLayerByName) { zval *zobj = getThis(); char *layerName; long layerName_len = 0; layerObj *layer = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &layerName, &layerName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); layer = mapObj_getLayerByName(php_map->map, layerName); if (layer == NULL) { mapscript_report_php_error(E_WARNING, "getLayerByName failed for : %s\n" TSRMLS_CC, layerName); RETURN_NULL(); } /* Return layer object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto colorObj map.getColorByIndex(int index) Returns a colorObj from the map given a color index */ PHP_METHOD(mapObj, getColorByIndex) { zval *zobj = getThis(); long index; paletteObj palette; colorObj color; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); palette = php_map->map->palette; if (index < palette.numcolors) { color.red = palette.colors[index].red; color.green = palette.colors[index].green; color.blue = palette.colors[index].blue; } else { mapscript_throw_mapserver_exception("Index shoud not be higher than %d\n" TSRMLS_CC, palette.numcolors-1); return; } /* Return color object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_color(&color, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.setextent(double minx, double miny, double maxx, double maxy) Set map extent property to new value. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, setExtent) { zval *zobj = getThis(); double minx, miny, maxx, maxy; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd", &minx, &miny, &maxx, &maxy) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = msMapSetExtent( php_map->map, minx, miny, maxx, maxy); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setCenter(pointObj center) Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, setCenter) { zval *zobj = getThis(); zval *zpoint; int status = MS_FAILURE; php_map_object *php_map; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); status = mapObj_setCenter(php_map->map, php_point->point); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.offsetExtent(double x, double y) Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, offsetExtent) { zval *zobj = getThis(); double x, y; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &y) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_offsetExtent(php_map->map, x, y); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.scaleExtent(double zoomfactor, double minscaledenom, double maxscaledenom) Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, scaleExtent) { zval *zobj = getThis(); double zoomFactor, minScaleDenom, maxScaleDenom; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &zoomFactor, &minScaleDenom, &maxScaleDenom) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_scaleExtent(php_map->map, zoomFactor, minScaleDenom, maxScaleDenom); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setRotation(double angle) Set map rotation angle. The map view rectangle (specified in EXTENTS) will be rotated by the indicated angle in the counter-clockwise direction. Note that this implies the rendered map will be rotated by the angle in the clockwise direction. */ PHP_METHOD(mapObj, setRotation) { zval *zobj = getThis(); double angle; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &angle) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_setRotation(php_map->map, angle); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setSize(int width, int height) Set map size (width, height) properties to new values and upddate internal geotransform. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, setSize) { zval *zobj = getThis(); long width, height; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = msMapSetSize(php_map->map, width, height); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int zoompoint(int zoomFactor, pointObj pixelPosition, int width, int height, rectObj geoRefExtent, [rectObj mapGeoRefExtent]) Zoom to a given XY postion. */ PHP_METHOD(mapObj, zoomPoint) { zval *zobj = getThis(); zval *zpoint, *zgeoRefExtent, *zmaxGeoRefExtent = NULL; long zoomFactor, width, height; double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; rectObj newGeoRefExtent; double dfNewScale = 0.0; double dfDeltaExt = -1.0; php_point_object *php_pixelPosition; php_rect_object *php_geoRefExtent=NULL, *php_maxGeoRefExtent=NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lOllO|O", &zoomFactor, &zpoint, mapscript_ce_point, &width, &height, &zgeoRefExtent , mapscript_ce_rect, &zmaxGeoRefExtent , mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_pixelPosition = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); php_geoRefExtent = (php_rect_object *) zend_object_store_get_object(zgeoRefExtent TSRMLS_CC); if (zmaxGeoRefExtent) php_maxGeoRefExtent = (php_rect_object *) zend_object_store_get_object(zmaxGeoRefExtent TSRMLS_CC); /* -------------------------------------------------------------------- */ /* check the validity of the parameters. */ /* -------------------------------------------------------------------- */ if (zoomFactor == 0 || width <= 0 || height <= 0 || php_geoRefExtent->rect == NULL || php_pixelPosition->point == NULL || (zmaxGeoRefExtent && php_maxGeoRefExtent->rect == NULL)) { mapscript_throw_mapserver_exception("Incorrect parameters\n" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* -------------------------------------------------------------------- */ if (php_geoRefExtent->rect->minx >= php_geoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_geoRefExtent->rect->miny >= php_geoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } if (zmaxGeoRefExtent) { if (php_maxGeoRefExtent->rect->minx >= php_maxGeoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_maxGeoRefExtent->rect->miny >= php_maxGeoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } } dfGeoPosX = Pix2Georef((int)php_pixelPosition->point->x, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); dfGeoPosY = Pix2Georef((int)php_pixelPosition->point->y, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); dfDeltaX = php_geoRefExtent->rect->maxx - php_geoRefExtent->rect->minx; dfDeltaY = php_geoRefExtent->rect->maxy - php_geoRefExtent->rect->miny; /* -------------------------------------------------------------------- */ /* zoom in */ /* -------------------------------------------------------------------- */ if (zoomFactor > 1) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaX/(2*zoomFactor)); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaY/(2*zoomFactor)); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaX/(2*zoomFactor)); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaY/(2*zoomFactor)); } if (zoomFactor < 0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaX/2)*(abs(zoomFactor)); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaY/2)*(abs(zoomFactor)); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaX/2)*(abs(zoomFactor)); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaY/2)*(abs(zoomFactor)); } if (zoomFactor == 1) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaX/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaY/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaX/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaY/2); } /* -------------------------------------------------------------------- */ /* if the min and max scale are set in the map file, we will */ /* use them to test before zooming. */ /* -------------------------------------------------------------------- */ msAdjustExtent(&newGeoRefExtent, php_map->map->width, php_map->map->height); if (msCalculateScale(newGeoRefExtent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfNewScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_map->map->web.maxscaledenom > 0) { if (zoomFactor < 0 && dfNewScale > php_map->map->web.maxscaledenom) { RETURN_LONG(MS_FAILURE); } } /* ==================================================================== */ /* we do a spcial case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ==================================================================== */ if (php_map->map->web.minscaledenom > 0 && dfNewScale < php_map->map->web.minscaledenom && zoomFactor > 1) { dfDeltaExt = GetDeltaExtentsUsingScale(php_map->map->web.minscaledenom, php_map->map->units, dfGeoPosY, php_map->map->width, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaExt/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* -------------------------------------------------------------------- */ if (zmaxGeoRefExtent) { dfDeltaX = newGeoRefExtent.maxx - newGeoRefExtent.minx; dfDeltaY = newGeoRefExtent.maxy - newGeoRefExtent.miny; /* Make sure Current georef extents is not bigger than max extents */ if (dfDeltaX > (php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx)) dfDeltaX = php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx; if (dfDeltaY > (php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny)) dfDeltaY = php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny; if (newGeoRefExtent.minx < php_maxGeoRefExtent->rect->minx) { newGeoRefExtent.minx = php_maxGeoRefExtent->rect->minx; newGeoRefExtent.maxx = newGeoRefExtent.minx + dfDeltaX; } if (newGeoRefExtent.maxx > php_maxGeoRefExtent->rect->maxx) { newGeoRefExtent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (newGeoRefExtent.miny < php_maxGeoRefExtent->rect->miny) { newGeoRefExtent.miny = php_maxGeoRefExtent->rect->miny; newGeoRefExtent.maxy = newGeoRefExtent.miny + dfDeltaY; } if (newGeoRefExtent.maxy > php_maxGeoRefExtent->rect->maxy) { newGeoRefExtent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } /* -------------------------------------------------------------------- */ /* set the map extents with new values. */ /* -------------------------------------------------------------------- */ php_map->map->extent.minx = newGeoRefExtent.minx; php_map->map->extent.miny = newGeoRefExtent.miny; php_map->map->extent.maxx = newGeoRefExtent.maxx; php_map->map->extent.maxy = newGeoRefExtent.maxy; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); dfDeltaX = php_map->map->extent.maxx - php_map->map->extent.minx; dfDeltaY = php_map->map->extent.maxy - php_map->map->extent.miny; if (zmaxGeoRefExtent) { if (php_map->map->extent.minx < php_maxGeoRefExtent->rect->minx) { php_map->map->extent.minx = php_maxGeoRefExtent->rect->minx; php_map->map->extent.maxx = php_map->map->extent.minx + dfDeltaX; } if (php_map->map->extent.maxx > php_maxGeoRefExtent->rect->maxx) { php_map->map->extent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (php_map->map->extent.miny < php_maxGeoRefExtent->rect->miny) { php_map->map->extent.miny = php_maxGeoRefExtent->rect->miny; php_map->map->extent.maxy = php_map->map->extent.miny + dfDeltaY; } if (php_map->map->extent.maxy > php_maxGeoRefExtent->rect->maxy) { php_map->map->extent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } if (msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int zoomRectangle(rectObj pixelExtent, int width, int height, rectObj geoRefExtent [, rectObj geoRefExtent]) Set the map extents to a given extents.*/ PHP_METHOD(mapObj, zoomRectangle) { zval *zobj = getThis(); zval *zpixelExtent, *zgeoRefExtent, *zmaxGeoRefExtent = NULL; long width, height; double dfDeltaX, dfDeltaY; rectObj newGeoRefExtent; double dfNewScale = 0.0; double dfDeltaExt = -1.0; double dfMiddleX =0.0; double dfMiddleY =0.0; php_rect_object *php_geoRefExtent=NULL, *php_maxGeoRefExtent=NULL, *php_pixelExtent=NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OllO|O", &zpixelExtent , mapscript_ce_rect, &width, &height, &zgeoRefExtent , mapscript_ce_rect, &zmaxGeoRefExtent , mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_pixelExtent = (php_rect_object *) zend_object_store_get_object(zpixelExtent TSRMLS_CC); php_geoRefExtent = (php_rect_object *) zend_object_store_get_object(zgeoRefExtent TSRMLS_CC); if (zmaxGeoRefExtent) php_maxGeoRefExtent = (php_rect_object *) zend_object_store_get_object(zmaxGeoRefExtent TSRMLS_CC); /* -------------------------------------------------------------------- */ /* check the validity of the parameters. */ /* -------------------------------------------------------------------- */ if (width <= 0 || height <= 0 || php_geoRefExtent->rect == NULL || php_pixelExtent->rect == NULL || (zmaxGeoRefExtent && php_maxGeoRefExtent->rect == NULL)) { mapscript_throw_mapserver_exception("Incorrect parameters\n" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* -------------------------------------------------------------------- */ if (php_geoRefExtent->rect->minx >= php_geoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_geoRefExtent->rect->miny >= php_geoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } if (zmaxGeoRefExtent) { if (php_maxGeoRefExtent->rect->minx >= php_maxGeoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_maxGeoRefExtent->rect->miny >= php_maxGeoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } } newGeoRefExtent.minx = Pix2Georef((int)php_pixelExtent->rect->minx, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); newGeoRefExtent.maxx = Pix2Georef((int)php_pixelExtent->rect->maxx, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); newGeoRefExtent.miny = Pix2Georef((int)php_pixelExtent->rect->miny, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); newGeoRefExtent.maxy = Pix2Georef((int)php_pixelExtent->rect->maxy, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); msAdjustExtent(&newGeoRefExtent, php_map->map->width, php_map->map->height); /* -------------------------------------------------------------------- */ /* if the min and max scale are set in the map file, we will */ /* use them to test before setting extents. */ /* -------------------------------------------------------------------- */ if (msCalculateScale(newGeoRefExtent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfNewScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_map->map->web.maxscaledenom > 0 && dfNewScale > php_map->map->web.maxscaledenom) { RETURN_LONG(MS_FAILURE); } if (php_map->map->web.minscaledenom > 0 && dfNewScale < php_map->map->web.minscaledenom) { dfMiddleX = newGeoRefExtent.minx + ((newGeoRefExtent.maxx - newGeoRefExtent.minx)/2); dfMiddleY = newGeoRefExtent.miny + ((newGeoRefExtent.maxy - newGeoRefExtent.miny)/2); dfDeltaExt = GetDeltaExtentsUsingScale(php_map->map->web.minscaledenom, php_map->map->units, dfMiddleY, php_map->map->width, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfMiddleX - (dfDeltaExt/2); newGeoRefExtent.miny = dfMiddleY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfMiddleX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfMiddleY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* -------------------------------------------------------------------- */ if (zmaxGeoRefExtent) { dfDeltaX = newGeoRefExtent.maxx - newGeoRefExtent.minx; dfDeltaY = newGeoRefExtent.maxy - newGeoRefExtent.miny; /* Make sure Current georef extents is not bigger than max extents */ if (dfDeltaX > (php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx)) dfDeltaX = php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx; if (dfDeltaY > (php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny)) dfDeltaY = php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny; if (newGeoRefExtent.minx < php_maxGeoRefExtent->rect->minx) { newGeoRefExtent.minx = php_maxGeoRefExtent->rect->minx; newGeoRefExtent.maxx = newGeoRefExtent.minx + dfDeltaX; } if (newGeoRefExtent.maxx > php_maxGeoRefExtent->rect->maxx) { newGeoRefExtent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (newGeoRefExtent.miny < php_maxGeoRefExtent->rect->miny) { newGeoRefExtent.miny = php_maxGeoRefExtent->rect->miny; newGeoRefExtent.maxy = newGeoRefExtent.miny + dfDeltaY; } if (newGeoRefExtent.maxy > php_maxGeoRefExtent->rect->maxy) { newGeoRefExtent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } php_map->map->extent.minx = newGeoRefExtent.minx; php_map->map->extent.miny = newGeoRefExtent.miny; php_map->map->extent.maxx = newGeoRefExtent.maxx; php_map->map->extent.maxy = newGeoRefExtent.maxy; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); dfDeltaX = php_map->map->extent.maxx - php_map->map->extent.minx; dfDeltaY = php_map->map->extent.maxy - php_map->map->extent.miny; if (zmaxGeoRefExtent) { if (php_map->map->extent.minx < php_maxGeoRefExtent->rect->minx) { php_map->map->extent.minx = php_maxGeoRefExtent->rect->minx; php_map->map->extent.maxx = php_map->map->extent.minx + dfDeltaX; } if (php_map->map->extent.maxx > php_maxGeoRefExtent->rect->maxx) { php_map->map->extent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (php_map->map->extent.miny < php_maxGeoRefExtent->rect->miny) { php_map->map->extent.miny = php_maxGeoRefExtent->rect->miny; php_map->map->extent.maxy = php_map->map->extent.miny + dfDeltaY; } if (php_map->map->extent.maxy > php_maxGeoRefExtent->rect->maxy) { php_map->map->extent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } if (msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int zoomScale(int scaleDenom, pointObj pixelPosition, int width, int height, rectObj geoRefExtent, [rectObj mapGeoRefExtent]) Zoom to a given XY postion. */ PHP_METHOD(mapObj, zoomScale) { zval *zobj = getThis(); zval *zpoint, *zgeoRefExtent, *zmaxGeoRefExtent = NULL; long width, height; double scaleDenom; double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; double dfCurrentScale = 0.0; rectObj newGeoRefExtent; double dfNewScale = 0.0; double dfDeltaExt = -1.0; int tmp = 0; php_point_object *php_pixelPosition; php_rect_object *php_geoRefExtent=NULL, *php_maxGeoRefExtent=NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dOllO|O", &scaleDenom, &zpoint, mapscript_ce_point, &width, &height, &zgeoRefExtent , mapscript_ce_rect, &zmaxGeoRefExtent , mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_pixelPosition = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); php_geoRefExtent = (php_rect_object *) zend_object_store_get_object(zgeoRefExtent TSRMLS_CC); if (zmaxGeoRefExtent) php_maxGeoRefExtent = (php_rect_object *) zend_object_store_get_object(zmaxGeoRefExtent TSRMLS_CC); /* -------------------------------------------------------------------- */ /* check the validity of the parameters. */ /* -------------------------------------------------------------------- */ if (scaleDenom <= 0.0 || width <= 0 || height <= 0 || php_geoRefExtent->rect == NULL || php_pixelPosition->point == NULL || (zmaxGeoRefExtent && php_maxGeoRefExtent->rect == NULL)) { mapscript_throw_mapserver_exception("Incorrect parameters\n" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* -------------------------------------------------------------------- */ if (php_geoRefExtent->rect->minx >= php_geoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_geoRefExtent->rect->miny >= php_geoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } if (zmaxGeoRefExtent) { if (php_maxGeoRefExtent->rect->minx >= php_maxGeoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_maxGeoRefExtent->rect->miny >= php_maxGeoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } } dfGeoPosX = Pix2Georef((int)php_pixelPosition->point->x, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); dfGeoPosY = Pix2Georef((int)php_pixelPosition->point->y, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); dfDeltaX = php_geoRefExtent->rect->maxx - php_geoRefExtent->rect->minx; dfDeltaY = php_geoRefExtent->rect->maxy - php_geoRefExtent->rect->miny; /* -------------------------------------------------------------------- */ /* Calculate new extents based on the sacle. */ /* -------------------------------------------------------------------- */ /* ==================================================================== */ /* make sure to take the smallest size because this is the one */ /* that will be used to ajust the scale. */ /* ==================================================================== */ if (php_map->map->width < php_map->map->height) tmp = php_map->map->width; else tmp = php_map->map->height; dfDeltaExt = GetDeltaExtentsUsingScale(scaleDenom, php_map->map->units, dfGeoPosY, tmp, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaExt/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); /* -------------------------------------------------------------------- */ /* get current scale. */ /* -------------------------------------------------------------------- */ if (msCalculateScale(*php_geoRefExtent->rect, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfCurrentScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* if the min and max scale are set in the map file, we will */ /* use them to test before zooming. */ /* */ /* This function has the same effect as zoomin or zoom out. If */ /* the current scale is > newscale we zoom in; else it is a */ /* zoom out. */ /* -------------------------------------------------------------------- */ msAdjustExtent(&newGeoRefExtent, php_map->map->width, php_map->map->height); if (msCalculateScale(newGeoRefExtent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfNewScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_map->map->web.maxscaledenom > 0) { if (dfCurrentScale < dfNewScale && dfNewScale > php_map->map->web.maxscaledenom) { RETURN_LONG(MS_FAILURE); } } /* ==================================================================== */ /* we do a special case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ==================================================================== */ if (php_map->map->web.minscaledenom > 0 && dfNewScale < php_map->map->web.minscaledenom && dfCurrentScale > dfNewScale) { dfDeltaExt = GetDeltaExtentsUsingScale(php_map->map->web.minscaledenom, php_map->map->units, dfGeoPosY, php_map->map->width, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaExt/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* -------------------------------------------------------------------- */ if (zmaxGeoRefExtent) { dfDeltaX = newGeoRefExtent.maxx - newGeoRefExtent.minx; dfDeltaY = newGeoRefExtent.maxy - newGeoRefExtent.miny; /* Make sure Current georef extents is not bigger than max extents */ if (dfDeltaX > (php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx)) dfDeltaX = php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx; if (dfDeltaY > (php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny)) dfDeltaY = php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny; if (newGeoRefExtent.minx < php_maxGeoRefExtent->rect->minx) { newGeoRefExtent.minx = php_maxGeoRefExtent->rect->minx; newGeoRefExtent.maxx = newGeoRefExtent.minx + dfDeltaX; } if (newGeoRefExtent.maxx > php_maxGeoRefExtent->rect->maxx) { newGeoRefExtent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (newGeoRefExtent.miny < php_maxGeoRefExtent->rect->miny) { newGeoRefExtent.miny = php_maxGeoRefExtent->rect->miny; newGeoRefExtent.maxy = newGeoRefExtent.miny + dfDeltaY; } if (newGeoRefExtent.maxy > php_maxGeoRefExtent->rect->maxy) { newGeoRefExtent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } /* -------------------------------------------------------------------- */ /* set the map extents with new values. */ /* -------------------------------------------------------------------- */ php_map->map->extent.minx = newGeoRefExtent.minx; php_map->map->extent.miny = newGeoRefExtent.miny; php_map->map->extent.maxx = newGeoRefExtent.maxx; php_map->map->extent.maxy = newGeoRefExtent.maxy; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); dfDeltaX = php_map->map->extent.maxx - php_map->map->extent.minx; dfDeltaY = php_map->map->extent.maxy - php_map->map->extent.miny; if (zmaxGeoRefExtent) { if (php_map->map->extent.minx < php_maxGeoRefExtent->rect->minx) { php_map->map->extent.minx = php_maxGeoRefExtent->rect->minx; php_map->map->extent.maxx = php_map->map->extent.minx + dfDeltaX; } if (php_map->map->extent.maxx > php_maxGeoRefExtent->rect->maxx) { php_map->map->extent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (php_map->map->extent.miny < php_maxGeoRefExtent->rect->miny) { php_map->map->extent.miny = php_maxGeoRefExtent->rect->miny; php_map->map->extent.maxy = php_map->map->extent.miny + dfDeltaY; } if (php_map->map->extent.maxy > php_maxGeoRefExtent->rect->maxy) { php_map->map->extent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } if (msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /********************************************************************** * map->queryByPoint() * * Type is MS_SINGLE or MS_MULTIPLE depending on number of results * you want. Passing buffer <=0 defaults to tolerances set in the map * file (in pixels) but you can use a constant buffer (specified in * ground units) instead. **********************************************************************/ /* {{{ proto int map.queryByPoint(pointObj point, int mode, double buffer) Query at point location. */ PHP_METHOD(mapObj, queryByPoint) { zval *zobj = getThis(); zval *zpoint; long mode; double buffer; int status = MS_FAILURE; php_point_object *php_point; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Old", &zpoint, mapscript_ce_point, &mode, &buffer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); status = mapObj_queryByPoint(php_map->map, php_point->point, mode, buffer); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.queryByRect(rectObj rect) */ PHP_METHOD(mapObj, queryByRect) { zval *zobj = getThis(); zval *zrect; int status = MS_FAILURE; php_rect_object *php_rect; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrect, mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_rect = (php_rect_object *) zend_object_store_get_object(zrect TSRMLS_CC); status = mapObj_queryByRect(php_map->map, *(php_rect->rect)); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /********************************************************************** * map->queryByShape(shape) * * Generates a result set based on a single shape, the shape is * assumed to be a polygon at this point. **********************************************************************/ /* {{{ proto int map.queryByShape(shapeObj poShape) */ PHP_METHOD(mapObj, queryByShape) { zval *zobj = getThis(); zval *zshape; int status = MS_FAILURE; php_shape_object *php_shape; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); status = mapObj_queryByShape(php_map->map, php_shape->shape); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.queryByFeatures(int slayer) */ PHP_METHOD(mapObj, queryByFeatures) { zval *zobj = getThis(); long slayer; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &slayer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_queryByFeatures(php_map->map, slayer); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /********************************************************************** * map->queryByIndex(qlayer, tileindex, shapeindex, bAddtoQuery) * * * Add a shape into the query result on a specific layer. * if bAddtoQuery (not mandatory) isset to true, the sahpe will be added to * the existing query result. Else the query result is cleared before adding * the sahpe (which is the default behavior). **********************************************************************/ /* {{{ proto int map.queryByIndex(int layerIndex, int tileIndex, int shapeIndex, int addToQuery) */ PHP_METHOD(mapObj, queryByIndex) { zval *zobj = getThis(); long layerIndex, tileIndex, shapeIndex, addToQuery = MS_FALSE; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll|l", &layerIndex, &tileIndex, &shapeIndex, &addToQuery) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_queryByIndex(php_map->map, layerIndex, tileIndex, shapeIndex, addToQuery); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.queryByFilter(char string) */ PHP_METHOD(mapObj, queryByFilter) { zval *zobj = getThis(); char *string; long string_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_queryByFilter(php_map->map, string); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.savequery(string filename, int results) Save the current query to a specfied file. Can be used with loadquery */ PHP_METHOD(mapObj, saveQuery) { zval *zobj = getThis(); char *filename; long filename_len = 0; int results = MS_FALSE; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &results) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_saveQuery(php_map->map, filename, results); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.savequeryasgml(string filename, string namespace) Save the current query to a specfied file as GML. */ PHP_METHOD(mapObj, saveQueryAsGML) { zval *zobj = getThis(); char *filename; long filename_len = 0; char *namespace = "GOMF"; long namespace_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename, &filename_len, &namespace, &namespace_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = msGMLWriteQuery(php_map->map, filename, namespace); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.loadquery(filename) Load the query from a specfied file. Used with savequery */ PHP_METHOD(mapObj, loadQuery) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_loadQuery(php_map->map, filename); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map->freeQuery(int qlayer) Free the query on a specified layer. If qlayer is set to -1 all queries on all layers will be freed. */ PHP_METHOD(mapObj, freeQuery) { zval *zobj = getThis(); long qlayer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &qlayer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); mapObj_freeQuery(php_map->map, qlayer); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int map.save(string filename) Write map object to a file. */ PHP_METHOD(mapObj, save) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_save(php_map->map, filename); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setProjection(string projection_params[, int setUnitsAndExtents]) Set projection and coord. system for the map. */ PHP_METHOD(mapObj, setProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; long setUnitsAndExtents = MS_FALSE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &projection, &projection_len, &setUnitsAndExtents) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapscript_map_setProjection(MS_FALSE, php_map, projection, setUnitsAndExtents TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getProjection() Return the projection string of the layer. Returns NULL on error. */ PHP_METHOD(mapObj, getProjection) { zval *zobj = getThis(); char *projection = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); projection = mapObj_getProjection(php_map->map); if (projection == NULL) { RETURN_NULL(); } RETVAL_STRING(projection, 1); free(projection); } /* }}} */ /* {{{ proto int map.setWKTProjection(string projection) Set projection and coord. system for the map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, setWKTProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; long setUnitsAndExtents = MS_FALSE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &projection, &projection_len, &setUnitsAndExtents) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapscript_map_setProjection(MS_TRUE, php_map, projection, setUnitsAndExtents TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto string map.getMetaData(string name) Return MetaData entry by name, or empty string if not found. */ PHP_METHOD(mapObj, getMetaData) { zval *zname; zval *zobj = getThis(); php_map_object *php_map; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata); MAPSCRIPT_CALL_METHOD_1(php_map->metadata, "get", retval, zname); RETURN_STRING(Z_STRVAL_P(retval),1); } /* }}} */ /* {{{ proto int map.setMetaData(string name, string value) Set MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(mapObj, setMetaData) { zval *zname, *zvalue; zval *zobj = getThis(); php_map_object *php_map; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zname, &zvalue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata); MAPSCRIPT_CALL_METHOD_2(php_map->metadata, "set", retval, zname, zvalue); RETURN_LONG(Z_LVAL_P(retval)); } /* }}} */ /* {{{ proto int map.removeMetaData(string name) Remove MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(mapObj, removeMetaData) { zval *zname; zval *zobj = getThis(); php_map_object *php_map; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata); MAPSCRIPT_CALL_METHOD_1(php_map->metadata, "remove", retval, zname); RETURN_LONG(Z_LVAL_P(retval)); } /* }}} */ /* {{{ proto int map.getLayersIndexByGroup(string groupname) Return an array of layer's index given a group name. */ PHP_METHOD(mapObj, getLayersIndexByGroup) { zval *zobj = getThis(); char *groupName; long groupName_len = 0; int *indexes = NULL; int count = 0; int i; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &groupName, &groupName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); array_init(return_value); indexes = mapObj_getLayersIndexByGroup(php_map->map, groupName, &count); if (indexes && count > 0) { for (i=0; imap->numlayers > 0) { groups = msGetAllGroupNames(php_map->map, &numTok); for (i=0; imap->numlayers; for (i=0; imap->layers[i]->name, 1); } } /* }}} */ /* {{{ proto int map.movelayerup(int index) Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, moveLayerUp) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_moveLayerup(php_map->map, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.movelayerdown(int index) Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, moveLayerDown) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_moveLayerdown(php_map->map, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getLayersDrawingOrder() Return an array containing all the layers index sorted by drawing order. Note : the first element in the array is the one drawn first.*/ PHP_METHOD(mapObj, getLayersDrawingOrder) { zval *zobj = getThis(); int count = 0; int i; int *layerIndexes = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); array_init(return_value); layerIndexes = mapObj_getLayersdrawingOrder(php_map->map); count = php_map->map->numlayers; /* -------------------------------------------------------------------- */ /* Go through the prioriy list and return the layers index. If */ /* the priority list is not set, it will return the layer */ /* indexs as they were at the load time. */ /* -------------------------------------------------------------------- */ for (i=0; imap->numlayers != numElements) { RETURN_LONG(MS_FAILURE); } indexes = (int*)malloc(sizeof(int)*numElements); for(zend_hash_internal_pointer_reset(indexes_hash); zend_hash_has_more_elements(indexes_hash) == SUCCESS; zend_hash_move_forward(indexes_hash), ++i) { zend_hash_get_current_data(indexes_hash, (void **)&ppzval); indexes[i] = Z_LVAL_PP(ppzval); } if (!mapObj_setLayersdrawingOrder(php_map->map, indexes)) { free(indexes); RETURN_LONG(MS_FAILURE); } free(indexes); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int map.processTemplate(array params, int generateImages)*/ PHP_METHOD(mapObj, processTemplate) { zval *zobj = getThis(); zval *zindexes; HashTable *indexes_hash = NULL; long generateImages; char *buffer = NULL; int index = 0; int numElements = 0; int i, size; char **papszNameValue = NULL; char **papszName = NULL; char **papszValue = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al", &zindexes, &generateImages) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); indexes_hash = Z_ARRVAL_P(zindexes); /** * Allocate 2 times the number of elements in * the array, since with associative arrays in PHP * keys are not counted. */ numElements = zend_hash_num_elements(indexes_hash); size = (numElements * 2 + 1) * sizeof(char *); papszNameValue = (char **)emalloc(size+1); memset((char *)papszNameValue, 0, size); if (mapscript_extract_associative_array(indexes_hash, papszNameValue)) { papszName = (char **)malloc(sizeof(char *)*numElements); papszValue = (char **)malloc(sizeof(char *)*numElements); for (i=0; imap, generateImages, papszName, papszValue, numElements); msFree(papszName); // The strings inside the array are just refs msFree(papszValue); if (buffer) { RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int map.processQueryTemplate(array params, int generateImages)*/ PHP_METHOD(mapObj, processQueryTemplate) { zval *zobj = getThis(); zval *zindexes; HashTable *indexes_hash = NULL; long generateImages = MS_TRUE; char *buffer = NULL; int index = 0; int numElements = 0; int i, size; char **papszNameValue = NULL; char **papszName = NULL; char **papszValue = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &zindexes, &generateImages) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); indexes_hash = Z_ARRVAL_P(zindexes); /** * Allocate 2 times the number of elements in * the array, since with associative arrays in PHP * keys are not counted. */ numElements = zend_hash_num_elements(indexes_hash); size = (numElements * 2 + 1) * sizeof(char *); papszNameValue = (char **)emalloc(size+1); memset((char *)papszNameValue, 0, size); if (mapscript_extract_associative_array(indexes_hash, papszNameValue)) { papszName = (char **)malloc(sizeof(char *)*numElements); papszValue = (char **)malloc(sizeof(char *)*numElements); for (i=0; imap, generateImages, papszName, papszValue, numElements); msFree(papszName); // The strings inside the array are just refs msFree(papszValue); if (buffer) { RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int map.processLegendTemplate(array params)*/ PHP_METHOD(mapObj, processLegendTemplate) { zval *zobj = getThis(); zval *zindexes; HashTable *indexes_hash = NULL; char *buffer = NULL; int index = 0; int numElements = 0; int i, size; char **papszNameValue = NULL; char **papszName = NULL; char **papszValue = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &zindexes) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); indexes_hash = Z_ARRVAL_P(zindexes); /** * Allocate 2 times the number of elements in * the array, since with associative arrays in PHP * keys are not counted. */ numElements = zend_hash_num_elements(indexes_hash); size = (numElements * 2 + 1) * sizeof(char *); papszNameValue = (char **)emalloc(size+1); memset((char *)papszNameValue, 0, size); if (mapscript_extract_associative_array(indexes_hash, papszNameValue)) { papszName = (char **)malloc(sizeof(char *)*numElements); papszValue = (char **)malloc(sizeof(char *)*numElements); for (i=0; imap, papszName, papszValue, numElements); msFree(papszName); // The strings inside the array are just refs msFree(papszValue); if (buffer) { RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int map.setSymbolSet(fileName)*/ PHP_METHOD(mapObj, setSymbolSet) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if(filename_len > 0) { if ((status = mapObj_setSymbolSet(php_map->map, filename)) != 0) { mapscript_throw_mapserver_exception("Failed loading symbolset from %s" TSRMLS_CC, filename); return; } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getNumSymbols() Returns the number of sumbols from this map. */ PHP_METHOD(mapObj, getNumSymbols) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); RETURN_LONG(php_map->map->symbolset.numsymbols); } /* }}} */ /* {{{ proto int map.setFontName(fileName)*/ PHP_METHOD(mapObj, setFontSet) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if(filename_len > 0) { if ((status = mapObj_setFontSet(php_map->map, filename)) != 0) { mapscript_throw_mapserver_exception("Failed loading fontset from %s" TSRMLS_CC, filename); return; } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int selectOutputFormat(string type) Selects the output format to be used in the map. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, selectOutputFormat) { zval *zobj = getThis(); char *type; long type_len = 0; int status = MS_FAILURE; php_map_object *php_map; php_outputformat_object *php_outputformat = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &type, &type_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_map->outputformat) php_outputformat = (php_outputformat_object *) zend_object_store_get_object(php_map->outputformat TSRMLS_CC); if ((status = mapObj_selectOutputFormat(php_map->map, type)) != MS_SUCCESS) { mapscript_report_php_error(E_WARNING, "Unable to set output format to '%s'" TSRMLS_CC, type); } else if (php_map->outputformat) { php_outputformat->outputformat = php_map->map->outputformat; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int appendOutputFormat(outputFormatObj outputformat) Appends outputformat object in the map object. Returns the new numoutputformats value */ PHP_METHOD(mapObj, appendOutputFormat) { zval *zobj = getThis(); zval *zoutputformat = NULL; int retval = 0; php_map_object *php_map; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zoutputformat, mapscript_ce_outputformat) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zoutputformat TSRMLS_CC); retval = msAppendOutputFormat(php_map->map, php_outputformat->outputformat); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int removeOutputFormat(string name) Remove outputformat from the map. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, removeOutputFormat) { zval *zobj = getThis(); char *name; long name_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = msRemoveOutputFormat(php_map->map, name)) != MS_SUCCESS) { mapscript_report_php_error(E_WARNING, "Unable to remove output format to '%s'" TSRMLS_CC, name); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getOutputFormat(int index). Return the outputformat at index position. */ PHP_METHOD(mapObj, getOutputFormat) { zval *zobj = getThis(); long index = -1; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (index < 0 || index >= php_map->map->numoutputformats) { mapscript_throw_mapserver_exception("Invalid outputformat index." TSRMLS_CC); return; } MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_outputformat(php_map->map->outputformatlist[index], parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.saveMapContext(fileName) */ PHP_METHOD(mapObj, saveMapContext) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if(filename_len > 0) { if ((status = mapObj_saveMapContext(php_map->map, filename)) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); mapscript_report_php_error(E_WARNING, "Failed saving map context from %s" TSRMLS_CC, filename); RETURN_LONG(MS_FAILURE); } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.loadMapContext(fileName) */ PHP_METHOD(mapObj, loadMapContext) { zval *zobj = getThis(); char *filename; long filename_len = 0; long unique = MS_FALSE; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &unique) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if(filename_len > 0) { if ((status = mapObj_loadMapContext(php_map->map, filename, unique)) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); mapscript_report_php_error(E_WARNING, "Failed loading map context from %s" TSRMLS_CC, filename); RETURN_LONG(MS_FAILURE); } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int applySLD(string sldxml) Apply the SLD document to the map file. */ PHP_METHOD(mapObj, applySLD) { zval *zobj = getThis(); char *sldxml; long sldxml_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &sldxml, &sldxml_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_applySLD(php_map->map, sldxml); RETURN_LONG(status); } /* }}} */ /* {{{ proto int applySLDURL(string sldurl) Apply the SLD document pointed by the URL to the map file. */ PHP_METHOD(mapObj, applySLDURL) { zval *zobj = getThis(); char *sldurl; long sldurl_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &sldurl, &sldurl_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = mapObj_applySLDURL(php_map->map, sldurl); RETURN_LONG(status); } /* }}} */ /* {{{ proto string generateSLD() Generates an sld based on the map layers/class. */ PHP_METHOD(mapObj, generateSLD) { zval *zobj = getThis(); char *buffer = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); buffer = mapObj_generateSLD(php_map->map); if (buffer) { RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto string map.getConfigOption(string key) Returns the configuation value associated with the key passed as argument. Returns an empty string on error. prototype : value = $map->getconfigoption(key) */ PHP_METHOD(mapObj, getConfigOption) { zval *zobj = getThis(); char *key; long key_len = 0; char *value = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((value = (char *)msGetConfigOption(php_map->map, key)) == NULL) { RETURN_STRING("", 1); } else { RETURN_STRING(value, 1); } } /* }}} */ /* {{{ proto int map.setConfigOption(string key, string value) Sets a config parameter using the key and the value passed. */ PHP_METHOD(mapObj, setConfigOption) { zval *zobj = getThis(); char *key; long key_len = 0; char *value; long value_len = 0; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); msSetConfigOption(php_map->map, key,value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int map.applyConfigOptions() Applies the config options set in the map file. */ PHP_METHOD(mapObj, applyConfigOptions) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); msApplyMapConfigOptions(php_map->map); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int loadowsparameters(OWSRequestObj request, string version) Load OWS request parameters (BBOX, LAYERS, &c.) into map. Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, loadOwsParameters) { zval *zobj = getThis(); zval *zrequest; char *version = NULL; long version_len = 0; int isZval = 1; int status = MS_FAILURE; php_owsrequest_object *php_request; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &zrequest, mapscript_ce_owsrequest, &version, &version_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_request = (php_owsrequest_object *) zend_object_store_get_object(zrequest TSRMLS_CC); if (!version) { version = strdup("1.1.1"); isZval = 0; } status = mapObj_loadOWSParameters(php_map->map, php_request->cgirequest, version); if (!isZval) free(version); RETURN_LONG(status); } /* }}} */ /* {{{ proto int owsDispatch(owsrequest request) Processes and executes the passed OpenGIS Web Services request on the map. */ PHP_METHOD(mapObj, owsDispatch) { zval *zobj = getThis(); zval *zrequest; int status = MS_FAILURE; php_owsrequest_object *php_request; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrequest, mapscript_ce_owsrequest) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_request = (php_owsrequest_object *) zend_object_store_get_object(zrequest TSRMLS_CC); status = mapObj_OWSDispatch(php_map->map, php_request->cgirequest); RETURN_LONG(status); } /* }}} */ /* {{{ proto int insertLayer(layerObj layer, index) Returns the index where the layer had been inserted*/ PHP_METHOD(mapObj, insertLayer) { zval *zobj = getThis(); zval *zlayer; long index = -1; int retval = -1; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zlayer, mapscript_ce_layer, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); if ((retval = mapObj_insertLayer(php_map->map, php_layer->layer, index)) < 0) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* return layer index */ RETURN_LONG(retval); } /* }}} */ /* {{{ proto int removeLayer(int layer_index) Returns layerObj removed on sucesss, else null. */ PHP_METHOD(mapObj, removeLayer) { zval *zobj = getThis(); long index = -1; layerObj *layer = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((layer = mapObj_removeLayer(php_map->map, index)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* return layer object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.getLabel(). Return the next label from the map’s labelcache, allowing iteration over labels. Return NULL when the labelcache is empty. */ PHP_METHOD(mapObj, getLabel) { zval *zobj = getThis(); long index = -1; labelCacheMemberObj *labelCacheMember = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); labelCacheMember=mapObj_getLabel(php_map->map, index); if (labelCacheMember == NULL) RETURN_NULL(); /* Return labelCacheMember object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_labelcachemember(labelCacheMember, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto string convertToString() Convert the map object to string. */ PHP_METHOD(mapObj, convertToString) { zval *zobj = getThis(); php_map_object *php_map; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = mapObj_convertToString(php_map->map); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /************************************************************************/ /* php3_ms_map_getLatLongExtent() */ /* */ /* Utility function (not documented) to get the lat/long */ /* extents of the current map. We assume here that the map has */ /* it's projection (ex LCC or UTM defined). */ /* */ /* Available only with PROJ support. */ /************************************************************************/ PHP_METHOD(mapObj, getLatLongExtent) { #ifdef USE_PROJ zval *zobj = getThis(); rectObj geoRefExt; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); geoRefExt.minx = php_map->map->extent.minx; geoRefExt.miny = php_map->map->extent.miny; geoRefExt.maxx = php_map->map->extent.maxx; geoRefExt.maxy = php_map->map->extent.maxy; if (php_map->map->projection.proj != NULL) { msProjectRect(&(php_map->map->projection), NULL, &geoRefExt); } /* Return rectObj */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_rect(&geoRefExt, parent, return_value TSRMLS_CC); #else mapscript_throw_exception("Available only with PROJ.4 support." TSRMLS_CC); return; #endif } /* {{{ proto int map.free(). Free explicitly the map object. Breaks the internal circular references between the map object and its children. */ PHP_METHOD(mapObj, free) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_map->outputformat); MAPSCRIPT_DELREF(php_map->extent); MAPSCRIPT_DELREF(php_map->web); MAPSCRIPT_DELREF(php_map->reference); MAPSCRIPT_DELREF(php_map->imagecolor); MAPSCRIPT_DELREF(php_map->scalebar); MAPSCRIPT_DELREF(php_map->legend); MAPSCRIPT_DELREF(php_map->querymap); MAPSCRIPT_DELREF(php_map->labelcache); MAPSCRIPT_DELREF(php_map->projection); MAPSCRIPT_DELREF(php_map->metadata); } /* }}} */ zend_function_entry map_functions[] = { PHP_ME(mapObj, __construct, map___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(mapObj, __get, map___get_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, __set, map___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(mapObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getSymbolByName, map_getSymbolByName_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getSymbolObjectById, map_getSymbolObjectById_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, prepareQuery, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, prepareImage, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, draw, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawQuery, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawLegend, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawReferenceMap, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawScaleBar, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, embedLegend, map_embedLegend_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, embedScaleBar, map_embedScaleBar_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawLabelCache, map_drawLabelCache_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayer, map_getLayer_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayerByName, map_getLayerByName_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getColorByIndex, map_getColorByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setExtent, map_setExtent_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setCenter, map_setCenter_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, offsetExtent, map_offsetExtent_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, scaleExtent, map_scaleExtent_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setRotation, map_setRotation_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setSize, map_setSize_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, zoomPoint, map_zoomPoint_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, zoomRectangle, map_zoomRectangle_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, zoomScale, map_zoomScale_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByPoint, map_queryByPoint_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByRect, map_queryByRect_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByShape, map_queryByShape_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByFeatures, map_queryByFeatures_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByFilter, map_queryByFilter_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByIndex, map_queryByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, saveQuery, map_saveQuery_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, saveQueryAsGML, map_saveQueryAsGML_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, loadQuery, map_loadQuery_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, freeQuery, map_freeQuery_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, save, map_save_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getProjection, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setProjection, map_setProjection_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setWKTProjection, map_setWKTProjection_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getMetaData, map_getMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setMetaData, map_setMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, removeMetaData, map_removeMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayersIndexByGroup, map_getLayersIndexByGroup_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getAllGroupNames, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getAllLayerNames, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, moveLayerUp, map_moveLayerUp_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, moveLayerDown, map_moveLayerDown_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayersDrawingOrder, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setLayersDrawingOrder, map_setLayersDrawingOrder_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, processTemplate, map_processTemplate_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, processQueryTemplate, map_processQueryTemplate_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, processLegendTemplate, map_processLegendTemplate_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setSymbolSet, map_setSymbolSet_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getNumSymbols, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setFontSet, map_setFontSet_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, selectOutputFormat, map_selectOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, appendOutputFormat, map_appendOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, removeOutputFormat, map_removeOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getOutputFormat, map_getOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, saveMapContext, map_saveMapContext_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, loadMapContext, map_loadMapContext_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, applySLD, map_applySLD_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, applySLDURL, map_applySLDURL_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, generateSLD, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getConfigOption, map_getConfigOption_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setConfigOption, map_setConfigOption_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, applyConfigOptions, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, loadOwsParameters, map_loadOwsParameters_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, owsDispatch, map_owsDispatch_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, insertLayer, map_insertLayer_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, removeLayer, map_removeLayer_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLabel, map_getLabel_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLatLongExtent, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; static int mapscript_map_setProjection(int isWKTProj, php_map_object *php_map, char *projString, int setUnitsAndExtents TSRMLS_DC) { #ifdef USE_PROJ int status = MS_SUCCESS; int units = MS_METERS; projectionObj in; projectionObj out; rectObj rect; int setNewExtents = 0; php_projection_object *php_projection = NULL; php_rect_object *php_extent = NULL; if (php_map->projection) php_projection = (php_projection_object *) zend_object_store_get_object(php_map->projection TSRMLS_CC); if (php_map->extent) php_extent = (php_rect_object *) zend_object_store_get_object(php_map->extent TSRMLS_CC); in = php_map->map->projection; msInitProjection(&out); if (isWKTProj) msOGCWKT2ProjectionObj(projString, &(out),php_map->map->debug); else msLoadProjectionString(&(out), projString); rect = php_map->map->extent; if (in.proj!= NULL && out.proj!=NULL) { if (msProjectionsDiffer(&in, &out)) { if (msProjectRect(&in, &out, &rect) == MS_SUCCESS) setNewExtents =1; } } /* Free the temporary projection object */ msFreeProjection(&out); if (isWKTProj) status = mapObj_setWKTProjection(php_map->map, projString); else status = mapObj_setProjection(php_map->map, projString); if (status == -1) { mapscript_report_php_error(E_WARNING, "setProjection failed" TSRMLS_CC); return MS_FAILURE; } else if (php_map->projection) { php_projection->projection = &(php_map->map->projection); } units = GetMapserverUnitUsingProj(&(php_map->map->projection)); if (units != -1 && setUnitsAndExtents) { /* -------------------------------------------------------------------- set the units and php_map->map extents. -------------------------------------------------------------------- */ php_map->map->units = units; if (setNewExtents) { php_map->map->extent = rect; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)); if (php_map->extent) php_extent->rect = &(php_map->map->extent); } } return MS_SUCCESS; #else mapscript_throw_exception("Available only with PROJ.4 support." TSRMLS_CC); return MS_FAILURE; #endif } void mapscript_create_map(mapObj *map, zval *return_value TSRMLS_DC) { php_map_object * php_map; object_init_ex(return_value, mapscript_ce_map); php_map = (php_map_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_map->map = map; } static void mapscript_map_object_destroy(void *object TSRMLS_DC) { php_map_object *php_map = (php_map_object *)object; MAPSCRIPT_FREE_OBJECT(php_map); MAPSCRIPT_DELREF(php_map->outputformat); MAPSCRIPT_DELREF(php_map->extent); MAPSCRIPT_DELREF(php_map->web); MAPSCRIPT_DELREF(php_map->reference); MAPSCRIPT_DELREF(php_map->imagecolor); MAPSCRIPT_DELREF(php_map->scalebar); MAPSCRIPT_DELREF(php_map->legend); MAPSCRIPT_DELREF(php_map->querymap); MAPSCRIPT_DELREF(php_map->labelcache); MAPSCRIPT_DELREF(php_map->projection); MAPSCRIPT_DELREF(php_map->metadata); MAPSCRIPT_DELREF(php_map->configoptions); mapObj_destroy(php_map->map); efree(object); } static zend_object_value mapscript_map_object_new_ex(zend_class_entry *ce, php_map_object **ptr TSRMLS_DC) { zend_object_value retval; php_map_object *php_map; MAPSCRIPT_ALLOC_OBJECT(php_map, php_map_object); retval = mapscript_object_new_ex(&php_map->std, ce, &mapscript_map_object_destroy, &mapscript_map_object_handlers TSRMLS_CC); if (ptr) *ptr = php_map; php_map->outputformat = NULL; php_map->extent = NULL; php_map->web = NULL; php_map->reference = NULL; php_map->imagecolor = NULL; php_map->scalebar = NULL; php_map->legend = NULL; php_map->querymap = NULL; php_map->labelcache = NULL; php_map->projection = NULL; php_map->metadata = NULL; php_map->configoptions = NULL; return retval; } static zend_object_value mapscript_map_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_map_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_map_object_clone(zval *zobj TSRMLS_DC) { php_map_object *php_map_old, *php_map_new; zend_object_value new_ov; php_map_old = (php_map_object *) zend_object_store_get_object(zobj TSRMLS_CC); new_ov = mapscript_map_object_new_ex(mapscript_ce_map, &php_map_new TSRMLS_CC); zend_objects_clone_members(&php_map_new->std, new_ov, &php_map_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_map_new->map = mapObj_clone(php_map_old->map); return new_ov; } PHP_MINIT_FUNCTION(map) { zend_class_entry ce; memcpy(&mapscript_map_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_map_object_handlers.clone_obj = mapscript_map_object_clone; MAPSCRIPT_REGISTER_CLASS("mapObj", map_functions, mapscript_ce_map, mapscript_map_object_new); mapscript_ce_map->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/referencemap.c0000644002461700001440000002460312261257215020712 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_referencemap; ZEND_BEGIN_ARG_INFO_EX(referenceMap___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(referenceMap___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(referenceMap_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto referenceMapObj __construct() referenceMapObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(referenceMapObj, __construct) { mapscript_throw_exception("referenceMapObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(referenceMapObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_referencemap_object *php_referencemap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = (php_referencemap_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("image", php_referencemap->referencemap->image) else IF_GET_LONG("width", php_referencemap->referencemap->width) else IF_GET_LONG("height", php_referencemap->referencemap->height) else IF_GET_LONG("status", php_referencemap->referencemap->status) else IF_GET_LONG("marker", php_referencemap->referencemap->marker) else IF_GET_STRING("markername", php_referencemap->referencemap->markername) else IF_GET_LONG("markersize", php_referencemap->referencemap->markersize) else IF_GET_LONG("maxboxsize", php_referencemap->referencemap->maxboxsize) else IF_GET_LONG("minboxsize", php_referencemap->referencemap->minboxsize) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_referencemap->extent, &php_referencemap->referencemap->extent) else IF_GET_OBJECT("color", mapscript_ce_color, php_referencemap->color, &php_referencemap->referencemap->color) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_referencemap->outlinecolor, &php_referencemap->referencemap->outlinecolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(referenceMapObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_referencemap_object *php_referencemap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = (php_referencemap_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("image", php_referencemap->referencemap->image, value) else IF_SET_LONG("width", php_referencemap->referencemap->width, value) else IF_SET_LONG("height", php_referencemap->referencemap->height, value) else IF_SET_LONG("status", php_referencemap->referencemap->status, value) else IF_SET_LONG("marker", php_referencemap->referencemap->marker, value) else IF_SET_STRING("markername", php_referencemap->referencemap->markername, value) else IF_SET_LONG("markersize", php_referencemap->referencemap->markersize, value) else IF_SET_LONG("maxboxsize", php_referencemap->referencemap->maxboxsize, value) else IF_SET_LONG("minboxsize", php_referencemap->referencemap->minboxsize, value) else if ( (STRING_EQUAL("extent", property)) || (STRING_EQUAL("color", property)) || (STRING_EQUAL("outlinecolor", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int referencemap.updateFromString(string snippet) Update a referencemap from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(referenceMapObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_referencemap_object *php_referencemap; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = (php_referencemap_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = referenceMapObj_updateFromString(php_referencemap->referencemap, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the referencemap object to string. */ PHP_METHOD(referenceMapObj, convertToString) { zval *zobj = getThis(); php_referencemap_object *php_referencemap; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = (php_referencemap_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = referenceMapObj_convertToString(php_referencemap->referencemap); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int referencemap.free() Free the object. */ PHP_METHOD(referenceMapObj, free) { zval *zobj = getThis(); php_referencemap_object *php_referencemap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = (php_referencemap_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_referencemap->extent); MAPSCRIPT_DELREF(php_referencemap->color); MAPSCRIPT_DELREF(php_referencemap->outlinecolor); } /* }}} */ zend_function_entry referencemap_functions[] = { PHP_ME(referenceMapObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(referenceMapObj, __get, referenceMap___get_args, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, __set, referenceMap___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(referenceMapObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, updateFromString, referenceMap_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_referencemap(referenceMapObj *referencemap, parent_object parent, zval *return_value TSRMLS_DC) { php_referencemap_object * php_referencemap; object_init_ex(return_value, mapscript_ce_referencemap); php_referencemap = (php_referencemap_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_referencemap->referencemap = referencemap; php_referencemap->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_referencemap_object_destroy(void *object TSRMLS_DC) { php_referencemap_object *php_referencemap = (php_referencemap_object *)object; MAPSCRIPT_FREE_OBJECT(php_referencemap); MAPSCRIPT_FREE_PARENT(php_referencemap->parent); MAPSCRIPT_DELREF(php_referencemap->extent); MAPSCRIPT_DELREF(php_referencemap->color); MAPSCRIPT_DELREF(php_referencemap->outlinecolor); /* We don't need to free the referenceMapObj */ efree(object); } static zend_object_value mapscript_referencemap_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_referencemap_object *php_referencemap; MAPSCRIPT_ALLOC_OBJECT(php_referencemap, php_referencemap_object); retval = mapscript_object_new(&php_referencemap->std, ce, &mapscript_referencemap_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_referencemap->parent); php_referencemap->extent = NULL; php_referencemap->color = NULL; php_referencemap->outlinecolor = NULL; return retval; } PHP_MINIT_FUNCTION(referencemap) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("referenceMapObj", referencemap_functions, mapscript_ce_referencemap, mapscript_referencemap_object_new); mapscript_ce_referencemap->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/Makefile.vc0000644002461700001440000000607212261257215020161 0ustar tbonfortusers# # makefile.vc - MSVC++ makefile for the PHP/MapScript extension # # This VC++ makefile will build the PHP module PHP_MAPSCRIPT.DLL # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # # Flag indicating to the option files that this is the build of PHP/MapScript PHP_BUILD_CALL=TRUE !INCLUDE ../../nmake.opt !INCLUDE nmake.opt PDB_FILE=/Fdphpms.pdb #DZEND_DEBUG=0 was added for #2717 PHP4_FLAGS=/DZEND_WIN32 /DPHP_WIN32 /DPHP4 /DZTS /PHP_COMPILER_ID=VC9 /DZEND_DEBUG=0 #OPTFLAGS = /nologo /Zi $(WARNING_LEVEL) $(DEBUG) $(PDB_FILE) #BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 $(PHP4_FLAGS) #LDFLAGS = /NODEFAULTLIB:msvcrt /dll $(LDEBUG) #LDFLAGS = /NODEFAULTLIB:libcd /dll $(LDEBUG) # Set flag for Visual Studio > 2003 & PHP < 5.3 # see http://bugs.php.net/bug.php?id=39130 !IF $(MSVC_VER) >= 1400 !IFDEF WIN64 VCFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE !ELSE VCFLAGS = -D_USE_32BIT_TIME_T -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE !ENDIF !ENDIF BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 $(PHP4_FLAGS) $(VCFLAGS) OPTFLAGS = /nologo /Zi /MD $(WARNING_LEVEL) $(DEBUG) /EHsc LDFLAGS = /NODEFAULTLIB:libc /dll /FORCE:MULTIPLE $(LDEBUG) # # Set PHP_HOME to point to the root of the PHP source tree # PHP_INC = -I$(PHP_HOME) -I$(PHP_HOME)/main -I$(PHP_HOME)/zend -I$(PHP_HOME)/include -I$(PHP_HOME)/tsrm !IFDEF DLLBUILD MS_LIBS = ../../mapserver_i.lib $(EXTERNAL_LIBS) !ELSE MS_LIBS = $(EXTERNAL_LIBS) ../../mapserver.lib !ENDIF # # The rest of the file should not have to be edited... # PHPMS_CLASS_OBJS = mapscript_error.obj color.obj rect.obj hashtable.obj web.obj grid.obj error.obj referencemap.obj querymap.obj outputformat.obj scalebar.obj label.obj legend.obj symbol.obj style.obj image.obj class.obj projection.obj line.obj shape.obj shapefile.obj point.obj labelcache.obj labelleader.obj labelcachemember.obj result.obj owsrequest.obj cluster.obj layer.obj map.obj PHPMS_OBJS = php_mapscript_util.obj $(PHPMS_CLASS_OBJS) php_mapscript.obj mapscript_i.obj PHPPROJ_OBJS = php_mapscript_util.obj php_proj.obj PHPMS_DLL = php_mapscript.dll PHPPROJ_DLL = php_proj.dll CFLAGS = $(BASE_CFLAGS) $(MS_CFLAGS) -I../.. $(PHP_INC) default: all all: $(PHPMS_DLL) mapscript: $(PHPMS_DLL) proj: $(PHPPROJ_DLL) install: all copy $(PHPMS_DLL) $(PHP_INSTALL_DIR)\$(PHP_INSTALL_DLL_NAME) $(PHPMS_DLL): $(PHPMS_OBJS) link $(LDFLAGS) /out:$(PHPMS_DLL) $(PHPMS_OBJS) $(MS_LIBS) \ $(PHP_HOME)\lib\$(PHP_TS_LIB_NAME) if exist $(PHPMS_DLL).manifest mt -manifest $(PHPMS_DLL).manifest -outputresource:$(PHPMS_DLL);2 $(PHPPROJ_DLL): $(PHPPROJ_OBJS) link $(LDFLAGS) /out:$(PHPPROJ_DLL) $(PHPPROJ_OBJS) $(MS_LIBS) \ $(PHP_HOME)\lib\$(PHP_TS_LIB_NAME) $(PHPMS_OBJS): php_mapscript_util.h php_mapscript.h .c.obj: $(CC) $(CFLAGS) /DCOMPILE_DL=1 /c $*.c /Fo$*.obj clean: del *.obj del $(PHPMS_OBJS) del $(PHPPROJ_OBJS) del $(PHPMS_DLL) del $(PHPPROJ_DLL) del *.lib del *.pdb del *.exp del *.ilk del *.manifest mapserver-6.4.1/mapscript/php/error.c0000644002461700001440000001447512261257215017415 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_error; ZEND_BEGIN_ARG_INFO_EX(error___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(error___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto error __construct() errorObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(errorObj, __construct) { mapscript_throw_exception("errorObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(errorObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_error_object *php_error; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_error = (php_error_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("code", php_error->error->code) else IF_GET_STRING("routine", php_error->error->routine) else IF_GET_STRING("message", php_error->error->message) else IF_GET_LONG("isreported", php_error->error->isreported) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(errorObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_error_object *php_error; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_error = (php_error_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (STRING_EQUAL("code", property)) || (STRING_EQUAL("routine", property)) || (STRING_EQUAL("isreported", property)) || (STRING_EQUAL("message", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int error.next() Returns a ref to the next errorObj in the list, or NULL if we reached the last one */ PHP_METHOD(errorObj, next) { zval *zobj = getThis(); php_error_object *php_error; errorObj *error = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_error = (php_error_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_error->error->next == NULL) RETURN_NULL(); /* Make sure 'self' is still valid. It may have been deleted by * msResetErrorList() */ error = msGetErrorObj(); while(error != php_error->error) { if (error->next == NULL) { mapscript_throw_exception("Trying to access an errorObj that has expired." TSRMLS_CC); return; } error = error->next; } php_error->error = php_error->error->next; *return_value = *zobj; zval_copy_ctor(return_value); INIT_PZVAL(return_value); } /* }}} */ zend_function_entry error_functions[] = { PHP_ME(errorObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(errorObj, __get, error___get_args, ZEND_ACC_PUBLIC) PHP_ME(errorObj, __set, error___set_args, ZEND_ACC_PUBLIC) PHP_ME(errorObj, next, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_error(errorObj *error, zval *return_value TSRMLS_DC) { php_error_object * php_error; object_init_ex(return_value, mapscript_ce_error); php_error = (php_error_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_error->error = error; } static void mapscript_error_object_destroy(void *object TSRMLS_DC) { php_error_object *php_error = (php_error_object *)object; MAPSCRIPT_FREE_OBJECT(php_error); /* We don't need to free the errorObj */ efree(object); } static zend_object_value mapscript_error_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_error_object *php_error; MAPSCRIPT_ALLOC_OBJECT(php_error, php_error_object); retval = mapscript_object_new(&php_error->std, ce, &mapscript_error_object_destroy TSRMLS_CC); return retval; } PHP_MINIT_FUNCTION(error) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("errorObj", error_functions, mapscript_ce_error, mapscript_error_object_new); mapscript_ce_error->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/hashtable.c0000644002461700001440000002313612261257215020211 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_hashtable; ZEND_BEGIN_ARG_INFO_EX(hashtable___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_get_args, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_set_args, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_remove_args, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_nextkey_args, 0, 0, 1) ZEND_ARG_INFO(0, previousKey) ZEND_END_ARG_INFO() /* {{{ proto hashtable __construct() Create a new hashtableObj instance. */ PHP_METHOD(hashtableObj, __construct) { mapscript_throw_exception("hashTableObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(hashtableObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = (php_hashtable_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numitems", php_hashtable->hashtable->numitems) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(hashtableObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("numitems", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int hashtable.get(string key) Get a value from item by its key. Returns empty string if not found. */ PHP_METHOD(hashtableObj, get) { char *key; long key_len = 0; zval *zobj = getThis(); const char *value = NULL; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = (php_hashtable_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = hashTableObj_get(php_hashtable->hashtable, key); if (value == NULL) { RETURN_STRING("",1); } RETURN_STRING((char *)value, 1); } /* }}} */ /* {{{ proto int hashtable.set(string key, string value) Set a hash item given key and value. Returns MS_FAILURE on error. */ PHP_METHOD(hashtableObj, set) { char *key, *value; long key_len, value_len = 0; zval *zobj = getThis(); int status = MS_FAILURE; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = (php_hashtable_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = hashTableObj_set(php_hashtable->hashtable, key, value)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int hashtable.remove(string key) Remove one item from hash table. Returns MS_FAILURE on error. */ PHP_METHOD(hashtableObj, remove) { char *key; long key_len = 0; zval *zobj = getThis(); int status = MS_FAILURE; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = (php_hashtable_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = hashTableObj_remove(php_hashtable->hashtable, key)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int hashtable.clear() Clear all items in hash table (to NULL). */ PHP_METHOD(hashtableObj, clear) { zval *zobj = getThis(); php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = (php_hashtable_object *) zend_object_store_get_object(zobj TSRMLS_CC); hashTableObj_clear(php_hashtable->hashtable); } /* }}} */ /* {{{ proto int hashtable.nextkey(string previousKey) Return the next key or first key if previousKey == NULL. Returns NULL if no item is in the hashTable or end of hashTable reached */ PHP_METHOD(hashtableObj, nextKey) { char *key; long key_len = 0; zval *zobj = getThis(); const char *value = NULL; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = (php_hashtable_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = hashTableObj_nextKey(php_hashtable->hashtable, key); if (value == NULL) RETURN_NULL(); RETURN_STRING(value, 1); } /* }}} */ zend_function_entry hashtable_functions[] = { PHP_ME(hashtableObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(hashtableObj, __get, hashtable___get_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, __set, hashtable___set_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, get, hashtable_get_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, set, hashtable_set_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, remove, hashtable_remove_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, clear, NULL, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, nextKey, hashtable_nextkey_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_hashtable(hashTableObj *hashtable, parent_object parent, zval *return_value TSRMLS_DC) { php_hashtable_object * php_hashtable; object_init_ex(return_value, mapscript_ce_hashtable); php_hashtable = (php_hashtable_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_hashtable->hashtable = hashtable; php_hashtable->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_hashtable_object_destroy(void *object TSRMLS_DC) { php_hashtable_object *php_hashtable = (php_hashtable_object *)object; MAPSCRIPT_FREE_OBJECT(php_hashtable); MAPSCRIPT_FREE_PARENT(php_hashtable->parent); /* We don't need to free the hashTableObj */ efree(object); } static zend_object_value mapscript_hashtable_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_hashtable_object *php_hashtable; MAPSCRIPT_ALLOC_OBJECT(php_hashtable, php_hashtable_object); retval = mapscript_object_new(&php_hashtable->std, ce, &mapscript_hashtable_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_hashtable->parent); return retval; } PHP_MINIT_FUNCTION(hashtable) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("hashTableObj", hashtable_functions, mapscript_ce_hashtable, mapscript_hashtable_object_new); mapscript_ce_hashtable->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/outputformat.c0000644002461700001440000002757612261257215021043 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_outputformat; ZEND_BEGIN_ARG_INFO_EX(outputformat___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, driver) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat_setOption_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat_getOption_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat_getOptionByIndex_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto outputformat __construct() instanciate outputFormatObj */ PHP_METHOD(outputFormatObj, __construct) { zval *zobj = getThis(); php_outputformat_object *php_outputformat; char *driver; long driver_len = 0; char *name = NULL; long name_len = 0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &driver, &driver_len, &name, &name_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *)zend_object_store_get_object(zobj TSRMLS_CC); if ((php_outputformat->outputformat = outputFormatObj_new(driver, name)) == NULL) { mapscript_throw_exception("Unable to construct outputFormatObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(outputFormatObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("name", php_outputformat->outputformat->name) else IF_GET_STRING("mimetype", php_outputformat->outputformat->mimetype) else IF_GET_STRING("driver", php_outputformat->outputformat->driver) else IF_GET_STRING("extension", php_outputformat->outputformat->extension) else IF_GET_LONG("renderer", php_outputformat->outputformat->renderer) else IF_GET_LONG("imagemode", php_outputformat->outputformat->imagemode) else IF_GET_LONG("transparent", php_outputformat->outputformat->transparent) else IF_GET_LONG("bands", php_outputformat->outputformat->bands) else IF_GET_LONG("numformatoptions", php_outputformat->outputformat->numformatoptions) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(outputFormatObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("name", php_outputformat->outputformat->name, value) else IF_SET_STRING("mimetype", php_outputformat->outputformat->mimetype, value) else IF_SET_STRING("driver", php_outputformat->outputformat->driver, value) else IF_SET_STRING("extension", php_outputformat->outputformat->extension, value) else IF_SET_LONG("renderer", php_outputformat->outputformat->renderer, value) else IF_SET_LONG("imagemode", php_outputformat->outputformat->imagemode, value) else IF_SET_LONG("transparent", php_outputformat->outputformat->transparent, value) else if ( (STRING_EQUAL("bands", property)) || (STRING_EQUAL("numformatoptions", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int outputFormat.setOption(string property_name, new_value) Add or Modify the format option list. return true on success.*/ PHP_METHOD(outputFormatObj, setOption) { char *property; long property_len = 0; char *value; long value_len = 0; zval *zobj = getThis(); php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &property, &property_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zobj TSRMLS_CC); msSetOutputFormatOption(php_outputformat->outputformat, property, value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto string outputFormat.getOption(string property_name) Returns the associated value for the format option property passed as argument. Returns an empty string if property not found.*/ PHP_METHOD(outputFormatObj, getOption) { char *property; long property_len = 0; zval *zobj = getThis(); const char *value = NULL; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = msGetOutputFormatOption(php_outputformat->outputformat, property, ""); RETURN_STRING((char*)value,1); } /* }}} */ /* {{{ proto int outputFormat.validate() Checks some internal consistency issues, and returns MS_SUCCESS if things are OK and MS_FAILURE if there are problems. Some problems are fixed up internally. May produce debug output if issues encountered.*/ PHP_METHOD(outputFormatObj, validate) { zval *zobj = getThis(); int status = MS_FALSE; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = msOutputFormatValidate(php_outputformat->outputformat, MS_TRUE); if (status != MS_TRUE) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(MS_FAILURE); } else RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int outputformat.getOptionByIndex(int index). Return the option at index position. */ PHP_METHOD(outputFormatObj, getOptionByIndex) { zval *zobj = getThis(); long index = -1; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = (php_outputformat_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (index < 0 || index >= php_outputformat->outputformat->numformatoptions) { mapscript_throw_mapserver_exception("Invalid format option index." TSRMLS_CC); return; } RETURN_STRING(php_outputformat->outputformat->formatoptions[index],1); } /* }}} */ zend_function_entry outputformat_functions[] = { PHP_ME(outputFormatObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(outputFormatObj, __get, outputformat___get_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, __set, outputformat___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(outputFormatObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, setOption, outputformat_setOption_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, getOption, outputformat_getOption_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, getOptionByIndex, outputformat_getOptionByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, validate, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_outputformat(outputFormatObj *outputformat, parent_object parent, zval *return_value TSRMLS_DC) { php_outputformat_object * php_outputformat; object_init_ex(return_value, mapscript_ce_outputformat); php_outputformat = (php_outputformat_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_outputformat->outputformat = outputformat; if (parent.val) php_outputformat->is_ref = 1; php_outputformat->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_outputformat_object_destroy(void *object TSRMLS_DC) { php_outputformat_object *php_outputformat = (php_outputformat_object *)object; MAPSCRIPT_FREE_OBJECT(php_outputformat); MAPSCRIPT_FREE_PARENT(php_outputformat->parent); if (php_outputformat->outputformat && !php_outputformat->is_ref) { outputFormatObj_destroy(php_outputformat->outputformat); } efree(object); } static zend_object_value mapscript_outputformat_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_outputformat_object *php_outputformat; MAPSCRIPT_ALLOC_OBJECT(php_outputformat, php_outputformat_object); retval = mapscript_object_new(&php_outputformat->std, ce, &mapscript_outputformat_object_destroy TSRMLS_CC); php_outputformat->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_outputformat->parent); return retval; } PHP_MINIT_FUNCTION(outputformat) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("outputFormatObj", outputformat_functions, mapscript_ce_outputformat, mapscript_outputformat_object_new); mapscript_ce_outputformat->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/rect.c0000644002461700001440000002713412261257215017215 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_rect; ZEND_BEGIN_ARG_INFO_EX(rect___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_draw_args, 0, 0, 5) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_ARG_INFO(0, classIndex) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_setExtent_args, 0, 0, 4) ZEND_ARG_INFO(0, minx) ZEND_ARG_INFO(0, miny) ZEND_ARG_INFO(0, maxx) ZEND_ARG_INFO(0, maxy) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_fit_args, 0, 0, 2) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_END_ARG_INFO() /* {{{ proto rect __construct() Create a new rectObj instance. */ PHP_METHOD(rectObj, __construct) { php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if ((php_rect->rect = rectObj_new()) == NULL) { mapscript_throw_exception("Unable to construct rectObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(rectObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_DOUBLE("minx", php_rect->rect->minx) else IF_GET_DOUBLE("miny", php_rect->rect->miny) else IF_GET_DOUBLE("maxx", php_rect->rect->maxx) else IF_GET_DOUBLE("maxy", php_rect->rect->maxy) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int draw(mapObj map, layerObj layer, imageObj img, string class_name, string text) Draws the individual rect using layer. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(rectObj, draw) { zval *zobj = getThis(); zval *zmap, *zlayer, *zimage; char *text = NULL; long text_len = 0; long classIndex; int status = MS_FAILURE; php_rect_object *php_rect; php_map_object *php_map; php_layer_object *php_layer; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOOl|s", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer, &zimage, mapscript_ce_image, &classIndex, &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_map = (php_map_object *) zend_object_store_get_object(zmap TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); if ((status = rectObj_draw(php_rect->rect, php_map->map, php_layer->layer, php_image->image, classIndex, text)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ PHP_METHOD(rectObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_DOUBLE("minx", php_rect->rect->minx, value) else IF_SET_DOUBLE("miny", php_rect->rect->miny, value) else IF_SET_DOUBLE("maxx", php_rect->rect->maxx, value) else IF_SET_DOUBLE("maxy", php_rect->rect->maxy, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int rect.project(projectionObj in, projectionObj out) Project a Rect object Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(rectObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_rect_object *php_rect; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_proj_in = (php_projection_object *) zend_object_store_get_object(zobj_proj_in TSRMLS_CC); php_proj_out = (php_projection_object *) zend_object_store_get_object(zobj_proj_out TSRMLS_CC); status = rectObj_project(php_rect->rect, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int rect.setextent(xmin, ymin, xmax, ymax) Set object property using four values. */ PHP_METHOD(rectObj, setExtent) { zval *zobj = getThis(); double minx, miny, maxx, maxy; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd", &minx, &miny, &maxx, &maxy) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_rect->rect->minx = minx; php_rect->rect->miny = miny; php_rect->rect->maxx = maxx; php_rect->rect->maxy = maxy; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int rect.fit(int nWidth, int nHeight) Adjust extents of the rectangle to fit the width/height specified. */ PHP_METHOD(rectObj, fit) { zval *zobj = getThis(); long width, height; double retval=0.0; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *) zend_object_store_get_object(zobj TSRMLS_CC); retval = rectObj_fit(php_rect->rect, width, height); RETURN_DOUBLE(retval); } /* }}} */ /* {{{ proto rect getCenter() Get center point of the extent. */ PHP_METHOD(rectObj, getCenter) { php_rect_object *php_rect; pointObj *center; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = (php_rect_object *)zend_object_store_get_object(getThis() TSRMLS_CC); center = (pointObj *)calloc(1, sizeof(pointObj)); if (!center) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } center->x = (php_rect->rect->minx + php_rect->rect->maxx)/2; center->y = (php_rect->rect->miny + php_rect->rect->maxy)/2; /* Return result object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(center, parent, return_value TSRMLS_CC); } /* }}} */ zend_function_entry rect_functions[] = { PHP_ME(rectObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(rectObj, getCenter, NULL, ZEND_ACC_PUBLIC) PHP_ME(rectObj, __get, rect___get_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, __set, rect___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(rectObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(rectObj, draw, rect_draw_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, project, rect_project_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, setExtent, rect_setExtent_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, fit, rect_fit_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_rect(rectObj *rect, parent_object parent, zval *return_value TSRMLS_DC) { php_rect_object * php_rect; object_init_ex(return_value, mapscript_ce_rect); php_rect = (php_rect_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_rect->rect = rect; if (parent.val) php_rect->is_ref = 1; php_rect->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_rect_object_destroy(void *object TSRMLS_DC) { php_rect_object *php_rect = (php_rect_object *)object; MAPSCRIPT_FREE_OBJECT(php_rect); MAPSCRIPT_FREE_PARENT(php_rect->parent); if (php_rect->rect && !php_rect->is_ref) { rectObj_destroy(php_rect->rect); } efree(object); } static zend_object_value mapscript_rect_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_rect_object *php_rect; MAPSCRIPT_ALLOC_OBJECT(php_rect, php_rect_object); retval = mapscript_object_new(&php_rect->std, ce, &mapscript_rect_object_destroy TSRMLS_CC); php_rect->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_rect->parent) return retval; } PHP_MINIT_FUNCTION(rect) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("rectObj", rect_functions, mapscript_ce_rect, mapscript_rect_object_new); mapscript_ce_rect->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/labelcache.c0000644002461700001440000001152712261257215020322 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_labelcache; ZEND_BEGIN_ARG_INFO_EX(labelcache___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(labelcache___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto labelcache __construct() labelCacheObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(labelCacheObj, __construct) { mapscript_throw_exception("labelCacheObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(labelCacheObj, __get) { mapscript_throw_exception("labelCacheObj has no property." TSRMLS_CC); } PHP_METHOD(labelCacheObj, __set) { mapscript_throw_exception("labelCacheObj has no property." TSRMLS_CC); } /* {{{ proto int labelcache->freeCache(() Free the labelcache object in the map. Returns true on success or false if an error occurs. */ PHP_METHOD(labelCacheObj, freeCache) { zval *zobj = getThis(); php_labelcache_object *php_labelcache; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcache = (php_labelcache_object *) zend_object_store_get_object(zobj TSRMLS_CC); labelCacheObj_freeCache(php_labelcache->labelcache); RETURN_LONG(MS_SUCCESS); } /* }}}} */ zend_function_entry labelcache_functions[] = { PHP_ME(labelCacheObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelCacheObj, __get, labelcache___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelCacheObj, __set, labelcache___set_args, ZEND_ACC_PUBLIC) PHP_ME(labelCacheObj, freeCache, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_labelcache(labelCacheObj *labelcache, parent_object parent, zval *return_value TSRMLS_DC) { php_labelcache_object * php_labelcache; object_init_ex(return_value, mapscript_ce_labelcache); php_labelcache = (php_labelcache_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_labelcache->labelcache = labelcache; php_labelcache->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_labelcache_object_destroy(void *object TSRMLS_DC) { php_labelcache_object *php_labelcache = (php_labelcache_object *)object; MAPSCRIPT_FREE_OBJECT(php_labelcache); MAPSCRIPT_FREE_PARENT(php_labelcache->parent); /* We don't need to free the labelCacheObj */ efree(object); } static zend_object_value mapscript_labelcache_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_labelcache_object *php_labelcache; MAPSCRIPT_ALLOC_OBJECT(php_labelcache, php_labelcache_object); retval = mapscript_object_new(&php_labelcache->std, ce, &mapscript_labelcache_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_labelcache->parent); return retval; } PHP_MINIT_FUNCTION(labelcache) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("labelCacheObj", labelcache_functions, mapscript_ce_labelcache, mapscript_labelcache_object_new); mapscript_ce_labelcache->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/layer.c0000644002461700001440000023554012261257215017376 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_layer; zend_object_handlers mapscript_layer_object_handlers; ZEND_BEGIN_ARG_INFO_EX(layer___construct_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setExtent_args, 0, 0, 4) ZEND_ARG_INFO(0, minx) ZEND_ARG_INFO(0, miny) ZEND_ARG_INFO(0, maxx) ZEND_ARG_INFO(0, maxy) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getClass_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getClassIndex_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_ARG_INFO(0, classGroup) ZEND_ARG_INFO(0, numClasses) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, expression) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setWKTProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getResult_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_whichShapes_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, extent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_addFeature_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setMetaData_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_removeMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getWMSFeatureInfoURL_args, 0, 0, 4) ZEND_ARG_INFO(0, clickX) ZEND_ARG_INFO(0, clickY) ZEND_ARG_INFO(0, featureCount) ZEND_ARG_INFO(0, infoFormat) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setProcessing_args, 0, 0, 1) ZEND_ARG_INFO(0, string) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setProcessingKey_args, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_applySLD_args, 0, 0, 2) ZEND_ARG_INFO(0, sldxml) ZEND_ARG_INFO(0, namedLayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_applySLDURL_args, 0, 0, 2) ZEND_ARG_INFO(0, sldurl) ZEND_ARG_INFO(0, namedLayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_moveClassUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_moveClassDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_removeClass_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setConnectionType_args, 0, 0, 2) ZEND_ARG_INFO(0, connectionType) ZEND_ARG_INFO(0, pluginLibrary) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_draw_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_drawQuery_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByPoint_args, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, buffer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByRect_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, rect, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByFeatures_args, 0, 0, 1) ZEND_ARG_INFO(0, slayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByAttributes_args, 0, 0, 3) ZEND_ARG_INFO(0, item) ZEND_ARG_INFO(0, string) ZEND_ARG_INFO(0, mode) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, string) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByIndex_args, 0, 0, 2) ZEND_ARG_INFO(0, tileindex) ZEND_ARG_INFO(0, shapeindex) ZEND_ARG_INFO(0, addtoquery) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, record, resultObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setGeomTransform_args, 0, 0, 1) ZEND_ARG_INFO(0, transform) ZEND_END_ARG_INFO() /* {{{ proto void __construct(mapObj map [, layerObj layer]) Create a new layerObj instance. */ PHP_METHOD(layerObj, __construct) { zval *zobj = getThis(); zval *zmap, *zlayer = NULL; layerObj *layer; int index; php_map_object *php_map; php_layer_object *php_layer, *php_layer2=NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *)zend_object_store_get_object(zobj TSRMLS_CC); php_map = (php_map_object *)zend_object_store_get_object(zmap TSRMLS_CC); if (zlayer) php_layer2 = (php_layer_object *)zend_object_store_get_object(zlayer TSRMLS_CC); if ((layer = layerObj_new(php_map->map)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } php_layer->layer = layer; php_layer->is_ref = 1; MAPSCRIPT_MAKE_PARENT(zmap, NULL); php_layer->parent = parent; MAPSCRIPT_ADDREF(zmap); /* if a layer is passed as argument, copy the layer into the new one */ if (zlayer) { index = layer->index; msCopyLayer(layer, php_layer2->layer); layer->index = index; } if (layer->connectiontype != MS_GRATICULE || layer->layerinfo == NULL) { MAKE_STD_ZVAL(php_layer->grid); ZVAL_NULL(php_layer->grid); } } /* }}} */ PHP_METHOD(layerObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numclasses", php_layer->layer->numclasses) else IF_GET_LONG("index", php_layer->layer->index) else IF_GET_LONG("status", php_layer->layer->status) else IF_GET_LONG("debug", php_layer->layer->debug) else IF_GET_STRING("bandsitem", php_layer->layer->bandsitem) else IF_GET_STRING("classitem", php_layer->layer->classitem) else IF_GET_STRING("classgroup", php_layer->layer->classgroup) else IF_GET_STRING("name", php_layer->layer->name) else IF_GET_STRING("group", php_layer->layer->group) else IF_GET_STRING("data", php_layer->layer->data) else IF_GET_LONG("type", php_layer->layer->type) else IF_GET_LONG("dump", php_layer->layer->dump) else IF_GET_DOUBLE("tolerance", php_layer->layer->tolerance) else IF_GET_LONG("toleranceunits", php_layer->layer->toleranceunits) else IF_GET_LONG("sizeunits", php_layer->layer->sizeunits) else IF_GET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom) else IF_GET_LONG("maxclasses", php_layer->layer->maxclasses) else IF_GET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom) else IF_GET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom) else IF_GET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom) else IF_GET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth) else IF_GET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth) else IF_GET_STRING("mask", php_layer->layer->mask) else IF_GET_LONG("minfeaturesize", php_layer->layer->minfeaturesize) else IF_GET_LONG("maxfeatures", php_layer->layer->maxfeatures) else IF_GET_LONG("startindex", php_layer->layer->startindex) else IF_GET_LONG("annotate", php_layer->layer->annotate) else IF_GET_LONG("transform", php_layer->layer->transform) else IF_GET_LONG("labelcache", php_layer->layer->labelcache) else IF_GET_LONG("postlabelcache", php_layer->layer->postlabelcache) else IF_GET_STRING("labelitem", php_layer->layer->labelitem) else IF_GET_STRING("tileitem", php_layer->layer->tileitem) else IF_GET_STRING("tileindex", php_layer->layer->tileindex) else IF_GET_STRING("header", php_layer->layer->header) else IF_GET_STRING("footer", php_layer->layer->footer) else IF_GET_STRING("connection", php_layer->layer->connection) else IF_GET_LONG("connectiontype", php_layer->layer->connectiontype) else IF_GET_STRING("filteritem", php_layer->layer->filteritem) else IF_GET_STRING("template", php_layer->layer->template) else IF_GET_LONG("opacity", php_layer->layer->opacity) else IF_GET_STRING("styleitem", php_layer->layer->styleitem) else IF_GET_LONG("numitems", php_layer->layer->numitems) else IF_GET_LONG("numjoins", php_layer->layer->numjoins) else IF_GET_LONG("num_processing", php_layer->layer->numprocessing) else IF_GET_STRING("requires", php_layer->layer->requires) else IF_GET_STRING("labelrequires", php_layer->layer->labelrequires) else IF_GET_OBJECT("offsite", mapscript_ce_color, php_layer->offsite, &php_layer->layer->offsite) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_layer->extent, &php_layer->layer->extent) else IF_GET_OBJECT("grid", mapscript_ce_grid, php_layer->grid, (graticuleObj *)(php_layer->layer->layerinfo)) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata) else IF_GET_OBJECT("bindvals", mapscript_ce_hashtable, php_layer->bindvals, &php_layer->layer->bindvals) else IF_GET_OBJECT("cluster", mapscript_ce_cluster, php_layer->cluster, &php_layer->layer->cluster) else IF_GET_OBJECT("projection", mapscript_ce_projection, php_layer->projection, &php_layer->layer->projection) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(layerObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); /* special case for "template" which we want to set to NULL and not an empty string */ if(Z_TYPE_P(value)==IS_NULL && !strcmp(property,"template")) { msFree(php_layer->layer->template); php_layer->layer->template = NULL; } else IF_SET_LONG("status", php_layer->layer->status, value) else IF_SET_LONG("debug", php_layer->layer->debug, value) else IF_SET_STRING("classitem", php_layer->layer->classitem, value) else IF_SET_STRING("bandsitem", php_layer->layer->bandsitem, value) else IF_SET_STRING("classgroup", php_layer->layer->classgroup, value) else IF_SET_STRING("name", php_layer->layer->name, value) else IF_SET_STRING("group", php_layer->layer->group, value) else IF_SET_STRING("data", php_layer->layer->data, value) else IF_SET_LONG("type", php_layer->layer->type, value) else IF_SET_LONG("dump", php_layer->layer->dump, value) else IF_SET_DOUBLE("tolerance", php_layer->layer->tolerance, value) else IF_SET_LONG("toleranceunits", php_layer->layer->toleranceunits, value) else IF_SET_LONG("sizeunits", php_layer->layer->sizeunits, value) else IF_SET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom, value) else IF_SET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom, value) else IF_SET_LONG("minfeaturesize", php_layer->layer->minfeaturesize, value) else IF_SET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom, value) else IF_SET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom, value) else IF_SET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth, value) else IF_SET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth, value) else IF_SET_STRING("mask", php_layer->layer->mask, value) else IF_SET_LONG("maxfeatures", php_layer->layer->maxfeatures, value) else IF_SET_LONG("startindex", php_layer->layer->startindex, value) else IF_SET_LONG("annotate", php_layer->layer->annotate, value) else IF_SET_LONG("transform", php_layer->layer->transform, value) else IF_SET_LONG("labelcache", php_layer->layer->labelcache, value) else IF_SET_LONG("postlabelcache", php_layer->layer->postlabelcache, value) else IF_SET_STRING("labelitem", php_layer->layer->labelitem, value) else IF_SET_STRING("tileitem", php_layer->layer->tileitem, value) else IF_SET_STRING("tileindex", php_layer->layer->tileindex, value) else IF_SET_STRING("header", php_layer->layer->header, value) else IF_SET_STRING("footer", php_layer->layer->footer, value) else IF_SET_STRING("connection", php_layer->layer->connection, value) else IF_SET_STRING("filteritem", php_layer->layer->filteritem, value) else IF_SET_STRING("template", php_layer->layer->template, value) else IF_SET_LONG("opacity", php_layer->layer->opacity, value) else IF_SET_STRING("styleitem", php_layer->layer->styleitem, value) else IF_SET_LONG("num_processing", php_layer->layer->numprocessing, value) else IF_SET_STRING("requires", php_layer->layer->requires, value) else IF_SET_STRING("labelrequires", php_layer->layer->labelrequires, value) else if ( (STRING_EQUAL("offsite", property)) || (STRING_EQUAL("grid", property)) || (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("bindvals", property)) || (STRING_EQUAL("projection", property)) || (STRING_EQUAL("maxclasses", property)) || (STRING_EQUAL("numitems", property)) || (STRING_EQUAL("numjoins", property)) || (STRING_EQUAL("extent", property)) || (STRING_EQUAL("cluster", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("numclasses", property)) || (STRING_EQUAL("index", property)) || (STRING_EQUAL("connectiontype", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int draw(imageObj image) Draw a single layer, add labels to cache if required. Returns MS_FAILURE on error. */ PHP_METHOD(layerObj, draw) { zval *zobj = getThis(); zval *zimage; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_draw(php_layer->layer, php_map->map, php_image->image)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int drawQuery(image img) Draw query results for a layer. */ PHP_METHOD(layerObj, drawQuery) { zval *zobj = getThis(); zval *zimage; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_drawQuery(php_layer->layer, php_map->map, php_image->image)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByPoint(pointObj point, int type, double buffer) Query at point location. */ PHP_METHOD(layerObj, queryByPoint) { zval *zobj = getThis(); zval *zpoint; int status = MS_FAILURE; long mode; double buffer; php_layer_object *php_layer; php_map_object *php_map; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Old", &zpoint, mapscript_ce_point, &mode, &buffer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByPoint(php_layer->layer, php_map->map, php_point->point, mode, buffer)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByRect(rectObj rect) Query using rectangular extent. */ PHP_METHOD(layerObj, queryByRect) { zval *zobj = getThis(); zval *zrect; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrect, mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_rect = (php_rect_object *) zend_object_store_get_object(zrect TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByRect(php_layer->layer, php_map->map, *(php_rect->rect))) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByShape(shapeObj shape) Query using a shape */ PHP_METHOD(layerObj, queryByShape) { zval *zobj = getThis(); zval *zshape; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByShape(php_layer->layer, php_map->map, php_shape->shape)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByFeatures(int slayer) Query on a layer using query object. */ PHP_METHOD(layerObj, queryByFeatures) { zval *zobj = getThis(); long slayer; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &slayer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByFeatures(php_layer->layer, php_map->map, slayer)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.queryAttributes(string item, string string, int mode) Query at point location. */ PHP_METHOD(layerObj, queryByAttributes) { zval *zobj = getThis(); char *item; long item_len = 0; char *string; long string_len = 0; long mode; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &item, &item_len, &string, &string_len, &mode) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByAttributes(php_layer->layer, php_map->map, item, string, mode)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.queryByFilter(string string) Query by filter. */ PHP_METHOD(layerObj, queryByFilter) { zval *zobj = getThis(); char *string; long string_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByFilter(php_layer->layer, php_map->map, string)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.queryByIndex(int tileindex, int shapeindex, int addtoquery) Query by index. */ PHP_METHOD(layerObj, queryByIndex) { zval *zobj = getThis(); long tileindex, shapeindex; long addtoquery=MS_FALSE; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|l", &tileindex, &shapeindex, &addtoquery) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((status = layerObj_queryByIndex(php_layer->layer, php_map->map, tileindex, shapeindex, addtoquery)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.updateFromString(string snippet) Update a layer from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(layerObj, updateFromString) { zval *zobj = getThis(); char *snippet; long snippet_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = layerObj_updateFromString(php_layer->layer, snippet)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the layer object to string. */ PHP_METHOD(layerObj, convertToString) { zval *zobj = getThis(); php_layer_object *php_layer; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = layerObj_convertToString(php_layer->layer); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int layer.getClass(int i) Returns a classObj from the layer given an index value (0=first class) */ PHP_METHOD(layerObj, getClass) { zval *zobj = getThis(); long index; classObj *class = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((class = layerObj_getClass(php_layer->layer, index)) == NULL) { mapscript_throw_exception("Invalid class index." TSRMLS_CC); return; } /* Return class object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_class(class, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.getClassIndex(shapeObj shape [, string classGroup, int numClasses]) Returns the class index for the shape */ PHP_METHOD(layerObj, getClassIndex) { zval *zobj = getThis(); zval *zshape, **ppzval, *zclassgroup = NULL; int numElements, *classGroups = NULL; int retval = -1, i = 0; long numClasses = 0; HashTable *classgroup_hash = NULL; php_shape_object *php_shape; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|a!l", &zshape, mapscript_ce_shape, &zclassgroup, &numClasses) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if (zclassgroup) { classgroup_hash = Z_ARRVAL_P(zclassgroup); numElements = zend_hash_num_elements(classgroup_hash); classGroups = (int*)malloc(sizeof(int)*numElements); for(zend_hash_internal_pointer_reset(classgroup_hash); zend_hash_has_more_elements(classgroup_hash) == SUCCESS; zend_hash_move_forward(classgroup_hash), ++i) { zend_hash_get_current_data(classgroup_hash, (void **)&ppzval); classGroups[i] = Z_LVAL_PP(ppzval); } } retval = layerObj_getClassIndex(php_layer->layer, php_map->map, php_shape->shape, classGroups, numClasses); if (zclassgroup) free(classGroups); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int layer.setFilter(string filter) Set layer filter expression. Returns 0 on success, -1 in error. */ PHP_METHOD(layerObj, setFilter) { zval *zobj = getThis(); char *expression; long expression_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &expression, &expression_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = layerObj_setFilter(php_layer->layer, expression)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string layer.getFilterString() Return the layer's filter expression. Returns NULL on error. */ PHP_METHOD(layerObj, getFilterString) { zval *zobj = getThis(); char *value = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = layerObj_getFilter(php_layer->layer); if (value == NULL) { RETURN_NULL(); } RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int layer.setProjection(string projection_params) Set projection and coord. system for the layer. */ PHP_METHOD(layerObj, setProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; php_projection_object *php_projection=NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projection, &projection_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_layer->projection) php_projection = (php_projection_object *) zend_object_store_get_object(php_layer->projection TSRMLS_CC); if ((status = layerObj_setProjection(php_layer->layer, projection)) != MS_SUCCESS) { mapscript_report_php_error(E_WARNING, "setProjection failed" TSRMLS_CC); RETURN_LONG(status); } if (php_layer->projection) php_projection->projection = &(php_layer->layer->projection); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.getProjection() Return the projection string of the layer. Returns NULL on error. */ PHP_METHOD(layerObj, getProjection) { zval *zobj = getThis(); char *projection = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); projection = layerObj_getProjection(php_layer->layer); if (projection == NULL) { RETURN_NULL(); } RETVAL_STRING(projection, 1); free(projection); } /* }}} */ /* {{{ proto int layer.setWKTProjection(string projection_params) Set projection and coord. system for the layer. */ PHP_METHOD(layerObj, setWKTProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; php_projection_object *php_projection=NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projection, &projection_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_layer->projection) php_projection = (php_projection_object *) zend_object_store_get_object(php_layer->projection TSRMLS_CC); if ((status = layerObj_setWKTProjection(php_layer->layer, projection)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_layer->projection) php_projection->projection = &(php_layer->layer->projection); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.getNumResults() Returns the number of results from this layer in the last query. */ PHP_METHOD(layerObj, getNumResults) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->layer->resultcache) RETURN_LONG(0); RETURN_LONG(php_layer->layer->resultcache->numresults); } /* }}} */ /* {{{ proto int layer.getResultsBounds() Returns the bounds of results from this layer in the last query. */ PHP_METHOD(layerObj, getResultsBounds) { zval *zobj = getThis(); php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->layer->resultcache) RETURN_NULL(); /* Return result object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_rect(&(php_layer->layer->resultcache->bounds), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.getResult(int i) Returns a resultObj by index from a layer object.*/ PHP_METHOD(layerObj, getResult) { zval *zobj = getThis(); long index; resultObj *result = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((result = layerObj_getResult(php_layer->layer, index)) == NULL) { mapscript_throw_exception("Invalid result index." TSRMLS_CC); return; } /* Return result object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_result(&(php_layer->layer->resultcache->results[index]), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.open() Open the layer for use with getShape(). Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(layerObj, open) { zval *zobj = getThis(); int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = layerObj_open(php_layer->layer); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } else { msLayerGetItems(php_layer->layer); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.whichshapes(rectObj extent) Returns MS_SUCCESS/MS_FAILURE. */ /* ** Performs a spatial, and optionally an attribute based feature search. The function basically ** prepares things so that candidate features can be accessed by query or drawing functions. For ** OGR and shapefiles this sets an internal bit vector that indicates whether a particular feature ** is to processed. For SDE it executes an SQL statement on the SDE server. Once run the msLayerNextShape ** function should be called to actually access the shapes. ** ** Note that for shapefiles we apply any maxfeatures constraint at this point. That may be the only ** connection type where this is feasible. */ PHP_METHOD(layerObj, whichShapes) { zval *zobj = getThis(); zval *zrect; int status = MS_FAILURE; php_layer_object *php_layer; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrect, mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_rect = (php_rect_object *) zend_object_store_get_object(zrect TSRMLS_CC); status = layerObj_whichShapes(php_layer->layer, php_rect->rect); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.nextshape() Returns a shape or NULL. */ PHP_METHOD(layerObj, nextShape) { zval *zobj = getThis(); shapeObj *shape = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); shape = layerObj_nextShape(php_layer->layer); if (!shape) RETURN_NULL(); /* Return valid object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, php_layer, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.close() Close layer previously opened with open(). */ PHP_METHOD(layerObj, close) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); layerObj_close(php_layer->layer); } /* }}} */ /* {{{ proto int layer.getExtent() Retrieve or calculate a layer's extents. */ PHP_METHOD(layerObj, getExtent) { zval *zobj = getThis(); rectObj *rect = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); /* Create a new rectObj to hold the result */ if ((rect = rectObj_new()) == NULL) { mapscript_throw_mapserver_exception("Failed creating new rectObj (out of memory?)" TSRMLS_CC); return; } if (msLayerGetExtent(php_layer->layer, rect) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } /* Return rectObj */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_rect(rect, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.setExtent(int minx, int miny, int maxx, int maxy) Set the layer extent. */ PHP_METHOD(layerObj, setExtent) { zval *zobj = getThis(); long minx, miny, maxx, maxy; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &minx, &miny, &maxx, &maxy) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (minx > maxx || miny > maxy) { mapscript_throw_mapserver_exception("Invalid min/max values" TSRMLS_CC); return; } RETURN_LONG(msLayerSetExtent(php_layer->layer, minx, miny, maxx, maxy)) } /* }}} */ /* {{{ proto int layer.addFeature(ShapeObj poShape) Add a shape */ PHP_METHOD(layerObj, addFeature) { zval *zobj = getThis(); zval *zshape; int status = MS_FAILURE; php_layer_object *php_layer; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); status = layerObj_addFeature(php_layer->layer, php_shape->shape); RETURN_LONG(status); } /* }}} */ /* {{{ proto string layer.getMetaData(string name) Return MetaData entry by name, or empty string if not found. */ PHP_METHOD(layerObj, getMetaData) { zval *zname; zval *zobj = getThis(); php_layer_object *php_layer; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata); MAPSCRIPT_CALL_METHOD_1(php_layer->metadata, "get", retval, zname); RETURN_STRING(Z_STRVAL_P(retval),1); } /* }}} */ /* {{{ proto int layer.setMetaData(string name, string value) Set MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(layerObj, setMetaData) { zval *zname, *zvalue; zval *zobj = getThis(); php_layer_object *php_layer; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zname, &zvalue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata); MAPSCRIPT_CALL_METHOD_2(php_layer->metadata, "set", retval, zname, zvalue); RETURN_LONG(Z_LVAL_P(retval)); } /* }}} */ /* {{{ proto int layer.removeMetaData(string name) Remove MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(layerObj, removeMetaData) { zval *zname; zval *zobj = getThis(); php_layer_object *php_layer; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata); MAPSCRIPT_CALL_METHOD_1(php_layer->metadata, "remove", retval, zname); RETURN_LONG(Z_LVAL_P(retval)); } /* }}} */ /* {{{ proto string layer.getWMSFeatureInfoURL(int clickX, int clickY, int featureCount, string infoFormat) Return a WMS GetFeatureInfo URL (only for WMS layers). */ PHP_METHOD(layerObj, getWMSFeatureInfoURL) { zval *zobj = getThis(); long clickx, clicky, featureCount; char *infoFormat = NULL; long infoFormat_len = 0; char *value = NULL; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls", &clickx, &clicky, &featureCount, &infoFormat, &infoFormat_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((value = layerObj_getWMSFeatureInfoURL(php_layer->layer, php_map->map, clickx, clicky, featureCount, infoFormat)) == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_STRING("", 1); } RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto char** layer.getItems() Return an array containing all the layer items.*/ PHP_METHOD(layerObj, getItems) { zval *zobj = getThis(); int i, status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); array_init(return_value); status = msLayerGetItems(php_layer->layer); if (status != MS_FAILURE && php_layer->layer->numitems > 0) { for (i=0; ilayer->numitems; i++) { /* add a copy of the group name to the PHP array */ add_next_index_string(return_value, php_layer->layer->items[i], 1); } } } /* }}} */ /* {{{ boolean layer.setProcessing(string) set a processing string to the layer*/ PHP_METHOD(layerObj, setProcessing) { zval *zobj = getThis(); char *string = NULL; long string_len = 0; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer->layer->numprocessing++; if(php_layer->layer->numprocessing == 1) php_layer->layer->processing = (char **) malloc(2*sizeof(char *)); else php_layer->layer->processing = (char **) realloc(php_layer->layer->processing, sizeof(char*) * (php_layer->layer->numprocessing+1)); php_layer->layer->processing[php_layer->layer->numprocessing-1] = strdup(string); php_layer->layer->processing[php_layer->layer->numprocessing] = NULL; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ boolean layer.setProcessingKey(string key, string value) set a processing key string to the layer*/ PHP_METHOD(layerObj, setProcessingKey) { zval *zobj = getThis(); char *key = NULL; long key_len = 0; char *value = NULL; long value_len = 0; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); msLayerSetProcessingKey( php_layer->layer, key, value ); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto char** layer.getProcessing() Return an array containing all the processing strings.*/ PHP_METHOD(layerObj, getProcessing) { zval *zobj = getThis(); int i; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); array_init(return_value); if (php_layer->layer->numprocessing > 0) { for (i=0; ilayer->numprocessing; i++) { add_next_index_string(return_value, php_layer->layer->processing[i], 1); } } } /* }}} */ /* {{{ boolean layer.clearProcessing() clear the processing strings in the layer*/ PHP_METHOD(layerObj, clearProcessing) { zval *zobj = getThis(); int i; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_layer->layer->numprocessing > 0) { for(i=0; ilayer->numprocessing; i++) free(php_layer->layer->processing[i]); php_layer->layer->numprocessing = 0; free(php_layer->layer->processing); } } /* }}} */ /* {{{ string layer.executewfsgetfeature() Executes a GetFeature request on a WFS layer and returns the name of the temporary GML file created. Returns an empty string on error.*/ PHP_METHOD(layerObj, executeWFSGetFeature) { zval *zobj = getThis(); char *value = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((value=layerObj_executeWFSGetFeature(php_layer->layer)) == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int applySLD(string sldxml, string namedlayer) Apply the SLD document to the layer object. The matching between the sld document and the layer will be done using the layer’s name. If a namedlayer argument is passed (argument is optional), the NamedLayer in the sld that matchs it will be used to style the layer. */ PHP_METHOD(layerObj, applySLD) { zval *zobj = getThis(); char *sldxml; long sldxml_len = 0; char *namedLayer = NULL; long namedLayer_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &sldxml, &sldxml_len, &namedLayer, &namedLayer_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = layerObj_applySLD(php_layer->layer, sldxml, namedLayer); RETURN_LONG(status); } /* }}} */ /* {{{ proto int applySLDURL(string sldurl, string namedlayer) Apply the SLD document pointed by the URL to the layer object. The matching between the sld document and the layer will be done using the layer’s name. If a namedlayer argument is passed (argument is optional), the NamedLayer in the sld that matchs it will be used to style the layer. */ PHP_METHOD(layerObj, applySLDURL) { zval *zobj = getThis(); char *sldurl; long sldurl_len = 0; char *namedLayer = NULL; long namedLayer_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &sldurl, &sldurl_len, &namedLayer, &namedLayer_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = layerObj_applySLDURL(php_layer->layer, sldurl, namedLayer); RETURN_LONG(status); } /* }}} */ /* {{{ proto string generateSLD() Returns an SLD XML string based on all the classes found in the layers.*/ PHP_METHOD(layerObj, generateSLD) { zval *zobj = getThis(); char *buffer = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); buffer = layerObj_generateSLD(php_layer->layer); if (buffer) { RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int moveClassUp(int index) The class specified by the class index will be moved up into the array of layers. Returns MS_SUCCESS or MS_FAILURE. */ PHP_METHOD(layerObj, moveClassUp) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = layerObj_moveClassUp(php_layer->layer, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int moveClassDown(int index) The class specified by the class index will be moved down into the array of layers. Returns MS_SUCCESS or MS_FAILURE.*/ PHP_METHOD(layerObj, moveClassDown) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = layerObj_moveClassDown(php_layer->layer, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int removeClass(int index) Removes the class indicated and returns a copy, or NULL in the case of a failure.*/ PHP_METHOD(layerObj, removeClass) { zval *zobj = getThis(); long index; classObj *class; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((class = layerObj_removeClass(php_layer->layer, index)) == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_class(class, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.isVisible() Returns MS_TRUE/MS_FALSE depending on whether the layer is currently visible in the map (i.e. turned on, in scale, etc.). */ PHP_METHOD(layerObj, isVisible) { zval *zobj = getThis(); int retval = MS_FALSE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); retval = msLayerIsVisible(php_map->map, php_layer->layer); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int layer.setConnectionType(int connectionType, string pluginLibrary) Set layer connectiontype. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(layerObj, setConnectionType) { zval *zobj = getThis(); long type; char *plugin = ""; long plugin_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &plugin, &plugin_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = layerObj_setConnectionType(php_layer->layer, type, plugin)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_layer->layer->connectiontype != MS_GRATICULE || php_layer->layer->layerinfo == NULL) { if (php_layer->grid && Z_TYPE_P(php_layer->grid) == IS_OBJECT) { MAPSCRIPT_DELREF(php_layer->grid); MAKE_STD_ZVAL(php_layer->grid); ZVAL_NULL(php_layer->grid); } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int getGridIntersctionCoordinates() Not sure if this function is often used, let it as it is. */ PHP_METHOD(layerObj, getGridIntersectionCoordinates) { zval *zobj = getThis(); graticuleIntersectionObj *values=NULL; zval *tmp_arr1; int i=0; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); array_init(return_value); if (php_layer->layer->connectiontype != MS_GRATICULE) { mapscript_throw_exception("Layer is not of graticule type" TSRMLS_CC); return; } values = msGraticuleLayerGetIntersectionPoints(php_map->map, php_layer->layer); if (values == NULL) return; /* empty array is returned */ /*TOP*/ add_assoc_double(return_value, "topnumpoints", values->nTop); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inTop; i++) { add_next_index_string(tmp_arr1, values->papszTopLabels[i],1); } zend_hash_update(Z_ARRVAL_P(return_value), "toplabels", strlen("toplabels")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inTop; i++) { add_next_index_double(tmp_arr1, values->pasTop[i].x); add_next_index_double(tmp_arr1, values->pasTop[i].y); } zend_hash_update(Z_ARRVAL_P(return_value), "toppoints", strlen("toppoints")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); /*BOTTOM*/ add_assoc_double(return_value, "bottomnumpoints", values->nBottom); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inBottom; i++) { add_next_index_string(tmp_arr1, values->papszBottomLabels[i],1); } zend_hash_update(Z_ARRVAL_P(return_value), "bottomlabels", strlen("bottomlabels")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inBottom; i++) { add_next_index_double(tmp_arr1, values->pasBottom[i].x); add_next_index_double(tmp_arr1, values->pasBottom[i].y); } zend_hash_update(Z_ARRVAL_P(return_value), "bottompoints", strlen("bottompoints")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); /*LEFT*/ add_assoc_double(return_value, "leftnumpoints", values->nLeft); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inLeft; i++) { add_next_index_string(tmp_arr1, values->papszLeftLabels[i],1); } zend_hash_update(Z_ARRVAL_P(return_value), "leftlabels", strlen("leftlabels")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inLeft; i++) { add_next_index_double(tmp_arr1, values->pasLeft[i].x); add_next_index_double(tmp_arr1, values->pasLeft[i].y); } zend_hash_update(Z_ARRVAL_P(return_value), "leftpoints", strlen("leftpoints")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); /*RIGHT*/ add_assoc_double(return_value, "rightnumpoints", values->nRight); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inRight; i++) { add_next_index_string(tmp_arr1, values->papszRightLabels[i],1); } zend_hash_update(Z_ARRVAL_P(return_value), "rightlabels", strlen("rightlabels")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); MAKE_STD_ZVAL(tmp_arr1); array_init(tmp_arr1); for (i=0; inRight; i++) { add_next_index_double(tmp_arr1, values->pasRight[i].x); add_next_index_double(tmp_arr1, values->pasRight[i].y); } zend_hash_update(Z_ARRVAL_P(return_value), "rightpoints", strlen("rightpoints")+1, &tmp_arr1, sizeof(tmp_arr1), NULL); msGraticuleLayerFreeIntersectionPoints(values); } /* }}} */ /* {{{ proto shapeObj layer.getShape(record) Retrieve shapeObj from a resultset by index. */ PHP_METHOD(layerObj, getShape) { zval *zobj = getThis(); zval *zresult; shapeObj *shape = NULL; php_result_object *php_result; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zresult, mapscript_ce_result) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_result = (php_result_object *) zend_object_store_get_object(zresult TSRMLS_CC); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ if ((shape = shapeObj_new(MS_SHAPE_NULL)) == NULL) { mapscript_throw_mapserver_exception("Failed creating new shape (out of memory?)" TSRMLS_CC); return; } if (msLayerGetShape(php_layer->layer, shape, php_result->result) != MS_SUCCESS) { shapeObj_destroy(shape); mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return valid object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, php_layer, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.getGeomTransform() return the geometry transform expression */ PHP_METHOD(layerObj, getGeomTransform) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (php_layer->layer->_geomtransform.type == MS_GEOMTRANSFORM_NONE || !php_layer->layer->_geomtransform.string) RETURN_STRING("", 1); RETURN_STRING(php_layer->layer->_geomtransform.string, 1); } /* }}} */ /* {{{ proto int layer.setGeomTransform() set the geometry transform expression */ PHP_METHOD(layerObj, setGeomTransform) { zval *zobj = getThis(); char *transform; long transform_len = 0; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &transform, &transform_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); msFree(php_layer->layer->_geomtransform.string); if (transform_len > 0) { php_layer->layer->_geomtransform.string = msStrdup(transform); php_layer->layer->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } else { php_layer->layer->_geomtransform.type = MS_GEOMTRANSFORM_NONE; php_layer->layer->_geomtransform.string = NULL; } RETURN_LONG(MS_SUCCESS); } /* {{{ proto void layer.free() Free the object */ PHP_METHOD(layerObj, free) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_layer->offsite); if (php_layer->grid && Z_TYPE_P(php_layer->grid) == IS_OBJECT) MAPSCRIPT_DELREF(php_layer->grid); MAPSCRIPT_DELREF(php_layer->metadata); MAPSCRIPT_DELREF(php_layer->bindvals); MAPSCRIPT_DELREF(php_layer->cluster); MAPSCRIPT_DELREF(php_layer->projection); } /* }}} */ zend_function_entry layer_functions[] = { PHP_ME(layerObj, __construct, layer___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(layerObj, __get, layer___get_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, __set, layer___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(layerObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, draw, layer_draw_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, drawQuery, layer_drawQuery_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, updateFromString, layer_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getClass, layer_getClass_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getClassIndex, layer_getClassIndex_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByPoint, layer_queryByPoint_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByRect, layer_queryByRect_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByShape, layer_queryByShape_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByFeatures, layer_queryByFeatures_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByAttributes, layer_queryByAttributes_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByFilter, layer_queryByFilter_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByIndex, layer_queryByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setFilter, layer_setFilter_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getFilterString, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setProjection, layer_setProjection_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getProjection, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setWKTProjection, layer_setWKTProjection_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getNumResults, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getResultsBounds, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getResult, layer_getResult_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, open, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, whichShapes, layer_whichShapes_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, nextShape, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, close, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getExtent, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setExtent, layer_setExtent_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, addFeature, layer_addFeature_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getMetaData, layer_getMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setMetaData, layer_setMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, removeMetaData, layer_removeMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getWMSFeatureInfoURL, layer_getWMSFeatureInfoURL_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getItems, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setProcessing, layer_setProcessing_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setProcessingKey, layer_setProcessingKey_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getProcessing, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, clearProcessing, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, executeWFSGetFeature, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, applySLD, layer_applySLD_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, applySLDURL, layer_applySLDURL_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, generateSLD, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, moveClassUp, layer_moveClassUp_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, moveClassDown, layer_moveClassDown_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, removeClass, layer_removeClass_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, isVisible, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setConnectionType, layer_setConnectionType_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getGridIntersectionCoordinates, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getShape, layer_getShape_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getGeomTransform, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setGeomTransform, layer_setGeomTransform_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_layer(layerObj *layer, parent_object parent, zval *return_value TSRMLS_DC) { php_layer_object * php_layer; object_init_ex(return_value, mapscript_ce_layer); php_layer = (php_layer_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_layer->layer = layer; if (layer->connectiontype != MS_GRATICULE || layer->layerinfo == NULL) { MAKE_STD_ZVAL(php_layer->grid); ZVAL_NULL(php_layer->grid); } if (parent.val) php_layer->is_ref = 1; php_layer->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_layer_object_destroy(void *object TSRMLS_DC) { php_layer_object *php_layer = (php_layer_object *)object; MAPSCRIPT_FREE_OBJECT(php_layer); MAPSCRIPT_FREE_PARENT(php_layer->parent); MAPSCRIPT_DELREF(php_layer->offsite); if (php_layer->grid && Z_TYPE_P(php_layer->grid) == IS_OBJECT) MAPSCRIPT_DELREF(php_layer->grid); MAPSCRIPT_DELREF(php_layer->metadata); MAPSCRIPT_DELREF(php_layer->bindvals); MAPSCRIPT_DELREF(php_layer->cluster); MAPSCRIPT_DELREF(php_layer->projection); MAPSCRIPT_DELREF(php_layer->extent); if (php_layer->layer && !php_layer->is_ref) { layerObj_destroy(php_layer->layer); } efree(object); } static zend_object_value mapscript_layer_object_new_ex(zend_class_entry *ce, php_layer_object **ptr TSRMLS_DC) { zend_object_value retval; php_layer_object *php_layer; MAPSCRIPT_ALLOC_OBJECT(php_layer, php_layer_object); retval = mapscript_object_new_ex(&php_layer->std, ce, &mapscript_layer_object_destroy, &mapscript_layer_object_handlers TSRMLS_CC); if (ptr) *ptr = php_layer; php_layer->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_layer->parent); php_layer->offsite = NULL; php_layer->grid = NULL; php_layer->metadata = NULL; php_layer->bindvals = NULL; php_layer->cluster = NULL; php_layer->projection = NULL; php_layer->extent = NULL; return retval; } static zend_object_value mapscript_layer_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_layer_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_layer_object_clone(zval *zobj TSRMLS_DC) { php_layer_object *php_layer_old, *php_layer_new; zend_object_value new_ov; php_layer_old = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); new_ov = mapscript_layer_object_new_ex(mapscript_ce_layer, &php_layer_new TSRMLS_CC); zend_objects_clone_members(&php_layer_new->std, new_ov, &php_layer_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_layer_new->layer = layerObj_clone(php_layer_old->layer); return new_ov; } PHP_MINIT_FUNCTION(layer) { zend_class_entry ce; memcpy(&mapscript_layer_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_layer_object_handlers.clone_obj = mapscript_layer_object_clone; MAPSCRIPT_REGISTER_CLASS("layerObj", layer_functions, mapscript_ce_layer, mapscript_layer_object_new); mapscript_ce_layer->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/color.c0000644002461700001440000001433712261257215017377 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_color; ZEND_BEGIN_ARG_INFO_EX(color___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(color___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(color_setRGB_args, 0, 0, 3) ZEND_ARG_INFO(0, red) ZEND_ARG_INFO(0, green) ZEND_ARG_INFO(0, blue) ZEND_END_ARG_INFO() /* {{{ proto void __construct() colorObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(colorObj, __construct) { mapscript_throw_exception("colorObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(colorObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_color = (php_color_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("red", php_color->color->red) else IF_GET_LONG("green", php_color->color->green) else IF_GET_LONG("blue", php_color->color->blue) else IF_GET_LONG("alpha", php_color->color->alpha) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(colorObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_color = (php_color_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_COLOR("red", php_color->color->red, value) else IF_SET_COLOR("green", php_color->color->green, value) else IF_SET_COLOR("blue", php_color->color->blue, value) else IF_SET_COLOR("alpha", php_color->color->alpha, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int color.setRGB(int R, int G, int B) Set new RGB color. */ PHP_METHOD(colorObj, setRGB) { zval *zobj = getThis(); long red, green, blue; php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &red, &green, &blue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_color = (php_color_object *) zend_object_store_get_object(zobj TSRMLS_CC); MS_INIT_COLOR(*(php_color->color), red, green, blue,255); RETURN_LONG(MS_SUCCESS); } /* }}} */ zend_function_entry color_functions[] = { PHP_ME(colorObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(colorObj, __get, color___get_args, ZEND_ACC_PUBLIC) PHP_ME(colorObj, __set, color___set_args, ZEND_ACC_PUBLIC) PHP_ME(colorObj, setRGB, color_setRGB_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_color(colorObj *color, parent_object parent, zval *return_value TSRMLS_DC) { php_color_object * php_color; object_init_ex(return_value, mapscript_ce_color); php_color = (php_color_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_color->color = color; php_color->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_color_object_destroy(void *object TSRMLS_DC) { php_color_object *php_color = (php_color_object *)object; MAPSCRIPT_FREE_OBJECT(php_color); MAPSCRIPT_FREE_PARENT(php_color->parent); /* We don't need to free the colorObj, the mapObj will do it */ efree(object); } static zend_object_value mapscript_color_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_color_object *php_color; MAPSCRIPT_ALLOC_OBJECT(php_color, php_color_object); retval = mapscript_object_new(&php_color->std, ce, &mapscript_color_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_color->parent); return retval; } PHP_MINIT_FUNCTION(color) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("colorObj", color_functions, mapscript_ce_color, mapscript_color_object_new); mapscript_ce_color->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/examples/0000755002461700001440000000000012261257215017723 5ustar tbonfortusersmapserver-6.4.1/mapscript/php/examples/test_draw_map.phtml0000644002461700001440000000227512261257215023630 0ustar tbonfortusers

PHP/MapScript module test

numlayers; // phpinfo(); // // RENDER MAIN MAP // // Note: If you get errors with the saveWebImage() call below, then make sure // that the directory specified by IMAGEPATH in the .MAP file exists and is // writable by the httpd user. // $img = $map->draw(); $url = $img->saveWebImage(); printf("\n", $url, $map->width, $map->height); // // LEGEND // $img = $map->drawLegend(); $url = $img->saveWebImage(); printf("

\n", $url); // // SCALE BAR // $img = $map->drawScaleBar(); $url = $img->saveWebImage(); printf("

\n", $url); ?> mapserver-6.4.1/mapscript/php/examples/phpinfo_mapscript.phtml0000644002461700001440000000075312261257215024523 0ustar tbonfortusers mapserver-6.4.1/mapscript/php/examples/test_writeshape.phtml0000644002461700001440000000254312261257215024207 0ustar tbonfortusersaddXY($x, $y); $oShp->add( $oLine ); $shpFile->addShape($oShp); // Write attribute record dbase_add_record($dbfFile, array($programId)); } $shpFname = "/tmp/shptest"; $shpFile = ms_newShapeFileObj( $shpFname, MS_SHP_POINT); $dbfFile = dbase_create( $shpFname.".dbf", array(array("PROG_ID", "N", 5, 0))); createPoint( 12, 34, 111); createPoint( 22, 14, 222); createPoint( 10, 20, 333); echo "Shapes Created.
"; //---------------------------------------------------------- // done... cleanup //---------------------------------------------------------- $shpFile->free(); echo "Shape File ($shpFname) closed.
"; dbase_close($dbfFile); echo "Dbase file closed.
"; ?> mapserver-6.4.1/mapscript/php/examples/test_layer_mask.phtml0000644002461700001440000000565712261257215024174 0ustar tbonfortusers

PHP/MapScript layer mask test

SelectOutputFormat("PNG"); //////// // Draw the base layers into an imageObj $img1 = $map->prepareimage(); $layer = $map->getLayerByName("bathymetry"); $layer->set("status", 1); $layer->draw($img1); //$img = $map->draw(); $url = $img1->saveWebImage(); echo "

Draw the base layers into an image...

\n"; printf("\n", $url, $map->width, $map->height); ////////////// // Use the parks layer as a mask... we only want to see the base layers // through the area of the park polygons and the rest should be light grey. // Start by creating a new image ... $img2 = $map->prepareimage(); // ... and we'll use a rectObj to draw the opaque mask background $rect = ms_newRectObj(); $rect->setExtent(0, 0, $map->width, $map->height); // We need to create a temporary layer and class to use in drawing the // filled rectangle that will be the opaque part of the mask. $tmplayer = ms_newLayerObj($map); $tmplayer->set("type", MS_LAYER_POLYGON); $tmplayer->set("status", 1); $tmplayer->set("transform", MS_FALSE); $tmpclass = ms_newClassObj($tmplayer); $tmpstyle = ms_newStyleObj($tmpclass); $tmpstyle->color->setRGB(222,222,222); $rect->draw($map, $tmplayer, $img2, 0, ""); // Draw rect with class 0 // Now fetch the park layer and change its only class to use color index 0 // which is the transparent background color... so the parks polygons will // create transparent holes in the mask $layer = $map->getLayerByName("park"); $layer->set("status", 1); $class = $layer->getClass(0); $style = $class->getStyle(0); $style->color->setRGB(12,12,12); $style->outlinecolor->setRGB(12,12,12); $layer->draw($img2); $url = $img2->saveWebImage(); echo "

Draw the mask into another image...

\n"; printf("\n", $url, $map->width, $map->height); //////// // Last step... combine the two images using pasteImage() // echo "

And combine the two with pasteImage()... you see the base layer through the holes in the mask...

\n"; $img1->pasteImage($img2, 0x0c0c0c); $url = $img1->saveWebImage(); printf("\n", $url, $map->width, $map->height); ?> mapserver-6.4.1/mapscript/php/examples/test_draw_legend_icon.phtml0000644002461700001440000000350612261257215025317 0ustar tbonfortusers

PHP/MapScript module test

numlayers; // phpinfo(); // // RENDER MAIN MAP // // Note: If you get errors with the saveWebImage() call below, then make sure // that the directory specified by IMAGEPATH in the .MAP file exists and is // writable by the httpd user. // $img = $map->draw(); $url = $img->saveWebImage(); printf("\n", $url, $map->width, $map->height); // // LEGEND // $img = $map->drawLegend(); $url = $img->saveWebImage(); printf("

Draw into one picture.
\n", $url); // Draw all legend icon from all class in all layers printf("

Draw each icon seperatly.
"); printf(""); for ($i=0; $i<$map->numlayers; $i++) { $layer = $map->getLayer($i); if ($layer->status != MS_OFF && $layer->type != MS_LAYER_QUERY) for ($j=0; $j<$layer->numclasses; $j++) { $myClass = $layer->GetClass($j); $img = $myClass->createLegendIcon($map->keysizex, $map->keysizey); $url = $img->saveWebImage(); printf("", $url, $myClass->name); } } printf("
%s
"); // // SCALE BAR // $img = $map->drawScaleBar(); $url = $img->saveWebImage(); printf("

\n", $url); ?> mapserver-6.4.1/mapscript/php/grid.c0000644002461700001440000001655012261257215017205 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_grid; ZEND_BEGIN_ARG_INFO_EX(grid___construct_args, 0, 1, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(grid___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(grid___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto void __construct(layerObj layer) Create a new intance of gridObj. */ PHP_METHOD(gridObj, __construct) { zval *zlayer; php_layer_object *php_layer; php_grid_object *php_grid, *php_old_grid; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_grid = (php_grid_object *) zend_object_store_get_object(getThis() TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); php_layer->layer->connectiontype = MS_GRATICULE; if (php_layer->layer->layerinfo != NULL) free(php_layer->layer->layerinfo); php_layer->layer->layerinfo = (graticuleObj *)malloc( sizeof( graticuleObj ) ); initGrid((graticuleObj *)php_layer->layer->layerinfo); php_grid->grid = (graticuleObj *)php_layer->layer->layerinfo; if (php_layer->grid && (Z_TYPE_P(php_layer->grid) == IS_OBJECT)) { php_old_grid = (php_grid_object *) zend_object_store_get_object(php_layer->grid TSRMLS_CC); php_old_grid->parent.child_ptr = NULL; zend_objects_store_del_ref(php_layer->grid TSRMLS_CC); } MAKE_STD_ZVAL(php_layer->grid); MAPSCRIPT_MAKE_PARENT(zlayer, &php_layer->grid); mapscript_create_grid((graticuleObj *)(php_layer->layer->layerinfo), parent, php_layer->grid TSRMLS_CC); return_value_ptr = &php_layer->grid; } /* }}} */ PHP_METHOD(gridObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_grid_object *php_grid; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_grid = (php_grid_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_DOUBLE("minsubdivide", php_grid->grid->minsubdivides) else IF_GET_DOUBLE("maxsubdivide", php_grid->grid->maxsubdivides) else IF_GET_DOUBLE("minarcs", php_grid->grid->minarcs) else IF_GET_DOUBLE("maxarcs", php_grid->grid->maxarcs) else IF_GET_DOUBLE("mininterval", php_grid->grid->minincrement) else IF_GET_DOUBLE("maxinterval", php_grid->grid->maxincrement) else IF_GET_STRING("labelformat", php_grid->grid->labelformat) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(gridObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_grid_object *php_grid; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_grid = (php_grid_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_DOUBLE("minsubdivide", php_grid->grid->minsubdivides, value) else IF_SET_DOUBLE("maxsubdivide", php_grid->grid->maxsubdivides, value) else IF_SET_DOUBLE("minarcs", php_grid->grid->minarcs, value) else IF_SET_DOUBLE("maxarcs", php_grid->grid->maxarcs, value) else IF_SET_DOUBLE("mininterval", php_grid->grid->minincrement, value) else IF_SET_DOUBLE("maxinterval", php_grid->grid->maxincrement, value) else IF_SET_STRING("labelformat", php_grid->grid->labelformat, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } zend_function_entry grid_functions[] = { PHP_ME(gridObj, __construct, grid___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(gridObj, __get, grid___get_args, ZEND_ACC_PUBLIC) PHP_ME(gridObj, __set, grid___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(gridObj, set, __set, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_grid(graticuleObj *grid, parent_object parent, zval *return_value TSRMLS_DC) { php_grid_object * php_grid; object_init_ex(return_value, mapscript_ce_grid); php_grid = (php_grid_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_grid->grid = grid; php_grid->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_grid_object_destroy(void *object TSRMLS_DC) { php_grid_object *php_grid = (php_grid_object *)object; MAPSCRIPT_FREE_OBJECT(php_grid); MAPSCRIPT_FREE_PARENT(php_grid->parent); /* We don't need to free the gridObj */ efree(object); } static zend_object_value mapscript_grid_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_grid_object *php_grid; MAPSCRIPT_ALLOC_OBJECT(php_grid, php_grid_object); retval = mapscript_object_new(&php_grid->std, ce, &mapscript_grid_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_grid->parent); return retval; } PHP_MINIT_FUNCTION(grid) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("gridObj", grid_functions, mapscript_ce_grid, mapscript_grid_object_new); mapscript_ce_grid->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/README.WIN320000644002461700001440000000730112261257215017567 0ustar tbonfortusers PHP/MapScript Mapserver Module ============================== -------------------------------------------------------------------- IMPORTANT - READ THIS FIRST: The Win32 build process is not very friendly for unexperienced users. So it is strongly recommended that you use one of the precompiled versions of php_mapscript.dll available on DM Solutions Group's web site: http://www2.dmsolutions.ca/mapserver/dl/ If for some reason you still decide to compile Win32 binaries yourself, then don't do it unless you really know what you're doing... and hopefully the rest of this file contains some hints that may help you. Good Luck! -------------------------------------------------------------------- This file contains informations specific to building the PHP/MapScript extension on Windows using MSVC++ 6.0. See also the file README for more general information about the PHP/MapScript extension. -------------------------- Step 1: Build the PHP.LIB import library ======= *** PHP3 *** Before you can build the 'php3_mapscript.dll' extension, you need the PHP.LIB import library. To build PHP.LIB, you will have to download the php_3.0.14.tar.gz source code, and follow the instructions in the README.WIN32 file in there to build php.exe with MSVC++ 6.0. - Extract php_3.0.14.tar.gz to your HD - Read the php_3.0.14\README.WIN32 file. - Open php_3.0.14\win32\php3.dsw using MSVC++ 6.0 - Start building php.exe, this will also create PHP.LIB *** PHP4.0.4 (and more recent versions) *** The PHP 4.0.4 win32 binaries (php-4.0.4-Win32.zip) distributed on http://www.php.net/ include the necessary php4ts.lib import library, so it is not necessary to build the PHP4 source in this case: - Extract php-4.0.4.tar.gz (this will create a php-4.0.4 source tree) - Extract php-4.0.4-Win32.zip and configure PHP4 on your server as per the instructions in the file install.txt included in the zip file. - mkdir php-4.0.4\lib (i.e. 'mkdir lib' in the root of the source tree) - Copy php4ts.lib (from php-4.0.4-Win32.zip) to php-4.0.4\lib - Continue with the rest of the instructions below. Step 2: Build PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL ======= Review the mapscript\php3\makefile.vc and make any modifications required for your configuration. Make sure PHP_SOURCE_DIR points to where you installed the PHP source tree in step 1 above. Then to compile PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL: - Open a DOS prompt window - Run the VCVARS32.BAT script to initialize the VC++ environment variables. VCVARS32.BAT is automatically generated by the MSVC++ install procedure and should be located in the BIN sub-directory of your MSVC++ installation. - Then start the build with: nmake /f makefile.vc This will create the "PHP3_MAPSCRIPT.DLL" for PHP3, or "PHP_MAPSCRIPT.DLL" for PHP4. Step 3: Install PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL ======= PHP3_MAPSCRIPT.DLL is a regular PHP module, you should copy it to the same directory as the other PHP3_*.DLL modules that came with PHP. Then the module can be loaded in one of 2 ways: - Adding a "extension=php3_mapscript.dll" line to the PHP3.INI file will load it automatically for every PHP page. - The other possibility is to load the module only when needed using the following PHP call: dl("php3_mapscript.dll"); // for the PHP3 module or dl("php_mapscript.dll"); // for the PHP4 module You can test that the module is properly loaded by executing the phpinfo() command in a PHP page... the "MapScript" extension should be included in the list of extensions in the phpinfo() report. -------------------------- $Id$ -------------------------- mapserver-6.4.1/mapscript/php/scalebar.c0000644002461700001440000002717712261257215020043 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_scalebar; ZEND_BEGIN_ARG_INFO_EX(scalebar___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(scalebar___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(scalebar_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(scalebar_setImageColor_args, 0, 0, 3) ZEND_ARG_INFO(0, red) ZEND_ARG_INFO(0, green) ZEND_ARG_INFO(0, blue) ZEND_END_ARG_INFO() /* {{{ proto scalebar __construct() scalebarObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(scalebarObj, __construct) { mapscript_throw_exception("scalebarObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(scalebarObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = (php_scalebar_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("height", php_scalebar->scalebar->height) else IF_GET_LONG("width", php_scalebar->scalebar->width) else IF_GET_LONG("style", php_scalebar->scalebar->style) else IF_GET_LONG("intervals", php_scalebar->scalebar->intervals) else IF_GET_LONG("units", php_scalebar->scalebar->units) else IF_GET_LONG("status", php_scalebar->scalebar->status) else IF_GET_LONG("position", php_scalebar->scalebar->position) else IF_GET_LONG("postlabelcache", php_scalebar->scalebar->postlabelcache) else IF_GET_LONG("align", php_scalebar->scalebar->align) else IF_GET_OBJECT("color", mapscript_ce_color, php_scalebar->color, &php_scalebar->scalebar->color) else IF_GET_OBJECT("backgroundcolor", mapscript_ce_color, php_scalebar->backgroundcolor, &php_scalebar->scalebar->backgroundcolor) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_scalebar->outlinecolor, &php_scalebar->scalebar->outlinecolor) else IF_GET_OBJECT("label", mapscript_ce_label, php_scalebar->label, &php_scalebar->scalebar->label) else IF_GET_OBJECT("imagecolor", mapscript_ce_color, php_scalebar->imagecolor, &php_scalebar->scalebar->imagecolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(scalebarObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = (php_scalebar_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_LONG("height", php_scalebar->scalebar->height, value) else IF_SET_LONG("width", php_scalebar->scalebar->width, value) else IF_SET_LONG("style", php_scalebar->scalebar->style, value) else IF_SET_LONG("intervals", php_scalebar->scalebar->intervals, value) else IF_SET_LONG("units", php_scalebar->scalebar->units, value) else IF_SET_LONG("status", php_scalebar->scalebar->status, value) else IF_SET_LONG("position", php_scalebar->scalebar->position, value) else IF_SET_LONG("postlabelcache", php_scalebar->scalebar->postlabelcache, value) else IF_SET_LONG("align", php_scalebar->scalebar->align, value) else if ( (STRING_EQUAL("color", property)) || (STRING_EQUAL("backgroundcolor", property)) || (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("label", property)) || (STRING_EQUAL("imagecolor", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int scalebar.updateFromString(string snippet) Update a scalebar from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(scalebarObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_scalebar_object *php_scalebar; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = (php_scalebar_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = scalebarObj_updateFromString(php_scalebar->scalebar, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the scalebar object to string. */ PHP_METHOD(scalebarObj, convertToString) { zval *zobj = getThis(); php_scalebar_object *php_scalebar; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = (php_scalebar_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = scalebarObj_convertToString(php_scalebar->scalebar); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int scalebar.setImageColor(int red, int green, int blue) Set the imagecolor property of the scalebar. Returns -1 on error. */ PHP_METHOD(scalebarObj, setImageColor) { zval *zobj = getThis(); long red, green, blue; php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &red, &green, &blue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = (php_scalebar_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) RETURN_LONG(MS_FAILURE); php_scalebar->scalebar->imagecolor.red = red; php_scalebar->scalebar->imagecolor.green = green; php_scalebar->scalebar->imagecolor.blue = blue; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int scalebar.free() Free the object */ PHP_METHOD(scalebarObj, free) { zval *zobj = getThis(); php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = (php_scalebar_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_scalebar->color); MAPSCRIPT_DELREF(php_scalebar->backgroundcolor); MAPSCRIPT_DELREF(php_scalebar->outlinecolor); MAPSCRIPT_DELREF(php_scalebar->imagecolor); MAPSCRIPT_DELREF(php_scalebar->label); } /* }}} */ zend_function_entry scalebar_functions[] = { PHP_ME(scalebarObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(scalebarObj, __get, scalebar___get_args, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, __set, scalebar___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(scalebarObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, updateFromString, scalebar_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, setImageColor, scalebar_setImageColor_args, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_scalebar(scalebarObj *scalebar, parent_object parent, zval *return_value TSRMLS_DC) { php_scalebar_object * php_scalebar; object_init_ex(return_value, mapscript_ce_scalebar); php_scalebar = (php_scalebar_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_scalebar->scalebar = scalebar; php_scalebar->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_scalebar_object_destroy(void *object TSRMLS_DC) { php_scalebar_object *php_scalebar = (php_scalebar_object *)object; MAPSCRIPT_FREE_OBJECT(php_scalebar); MAPSCRIPT_FREE_PARENT(php_scalebar->parent); MAPSCRIPT_DELREF(php_scalebar->color); MAPSCRIPT_DELREF(php_scalebar->backgroundcolor); MAPSCRIPT_DELREF(php_scalebar->outlinecolor); MAPSCRIPT_DELREF(php_scalebar->imagecolor); MAPSCRIPT_DELREF(php_scalebar->label); /* We don't need to free the scalebarObj */ efree(object); } static zend_object_value mapscript_scalebar_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_scalebar_object *php_scalebar; MAPSCRIPT_ALLOC_OBJECT(php_scalebar, php_scalebar_object); retval = mapscript_object_new(&php_scalebar->std, ce, &mapscript_scalebar_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_scalebar->parent); php_scalebar->color = NULL; php_scalebar->backgroundcolor = NULL; php_scalebar->outlinecolor = NULL; php_scalebar->imagecolor = NULL; php_scalebar->label = NULL; return retval; } PHP_MINIT_FUNCTION(scalebar) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("scalebarObj", scalebar_functions, mapscript_ce_scalebar, mapscript_scalebar_object_new); mapscript_ce_scalebar->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/class.c0000644002461700001440000007625312261257215017373 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_class; zend_object_handlers mapscript_class_object_handlers; ZEND_BEGIN_ARG_INFO_EX(class___construct_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, class, classObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_addLabel_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, label, labelObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_removeLabel_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_getLabel_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_setExpression_args, 0, 0, 1) ZEND_ARG_INFO(0, expression) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_setText_args, 0, 0, 1) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_getStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_insertStyle_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_removeStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_moveStyleUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_moveStyleDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_deleteStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_getMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_setMetaData_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_removeMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_createLegendIcon_args, 0, 0, 2) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_drawLegendIcon_args, 0, 0, 5) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_ARG_INFO(0, dstX) ZEND_ARG_INFO(0, dstY) ZEND_END_ARG_INFO() /* {{{ proto void __construct(layerObj layer [, classObj class]) Create a new class instance in the specified layer.. */ PHP_METHOD(classObj, __construct) { zval *zobj = getThis(); zval *zlayer, *zclass = NULL; classObj *class; php_layer_object *php_layer; php_class_object *php_class, *php_class2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zlayer, mapscript_ce_layer, &zclass, mapscript_ce_class) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); if (zclass) php_class2 = (php_class_object *) zend_object_store_get_object(zclass TSRMLS_CC); if ((class = classObj_new(php_layer->layer, (zclass ? php_class2->class:NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } php_class->class = class; MAPSCRIPT_MAKE_PARENT(zlayer,NULL); php_class->parent = parent; MAPSCRIPT_ADDREF(parent.val); } /* }}} */ PHP_METHOD(classObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_class_object *php_class; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("name", php_class->class->name) else IF_GET_STRING("title", php_class->class->title) else IF_GET_LONG("type", php_class->class->type) else IF_GET_LONG("status", php_class->class->status) else IF_GET_DOUBLE("minscaledenom", php_class->class->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_class->class->maxscaledenom) else IF_GET_LONG("minfeaturesize", php_class->class->minfeaturesize) else IF_GET_LONG("numlabels", php_class->class->numlabels) else IF_GET_STRING("template", php_class->class->template) else IF_GET_STRING("keyimage", php_class->class->keyimage) else IF_GET_STRING("group", php_class->class->group) else IF_GET_LONG("numstyles", php_class->class->numstyles) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata) else IF_GET_OBJECT("leader", mapscript_ce_labelleader, php_class->leader, &php_class->class->leader) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(classObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_class_object *php_class; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); /* special case for "template" which we want to set to NULL and not an empty string */ if(Z_TYPE_P(value)==IS_NULL && !strcmp(property,"template")) { msFree(php_class->class->template); php_class->class->template = NULL; } else IF_SET_STRING("name", php_class->class->name, value) else IF_SET_STRING("title", php_class->class->title, value) else IF_SET_LONG("type", php_class->class->type, value) else IF_SET_LONG("status", php_class->class->status, value) else IF_SET_DOUBLE("minscaledenom", php_class->class->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_class->class->maxscaledenom, value) else IF_SET_LONG("minfeaturesize", php_class->class->minfeaturesize, value) else IF_SET_STRING("template", php_class->class->template, value) else IF_SET_STRING("keyimage", php_class->class->keyimage, value) else IF_SET_STRING("group", php_class->class->group, value) else if ( (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("leader", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("numstyles", property)) || (STRING_EQUAL("numstyles", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int addLabel(labelObj *label) Add a label to the class. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, addLabel) { zval *zobj = getThis(); zval *zlabel; php_class_object *php_class; php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zlabel, mapscript_ce_label) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_label = (php_label_object *) zend_object_store_get_object(zlabel TSRMLS_CC); status = classObj_addLabel(php_class->class, php_label->label); php_label->is_ref = 1; RETURN_LONG(status); } /* }}} */ /* {{{ proto int removeLabel(int index) Removes the label indicated and returns a copy, or NULL in the case of a failure. */ PHP_METHOD(classObj, removeLabel) { zval *zobj = getThis(); long index; labelObj *label; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((label = classObj_removeLabel(php_class->class, index)) == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_label(label, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int class.getLabel(int i) Returns a labelObj from the class given an index value (0=first label) */ PHP_METHOD(classObj, getLabel) { zval *zobj = getThis(); long index; labelObj *label = NULL; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((label = classObj_getLabel(php_class->class, index)) == NULL) { mapscript_throw_exception("Invalid label index." TSRMLS_CC); return; } /* Return class object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_label(label, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int updateFromString(string snippet) Update a class from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = classObj_updateFromString(php_class->class, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the class object to string. */ PHP_METHOD(classObj, convertToString) { zval *zobj = getThis(); php_class_object *php_class; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = classObj_convertToString(php_class->class); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setExpression(string exression) Set the expression string for a class object. */ PHP_METHOD(classObj, setExpression) { char *expression; long expression_len = 0; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &expression, &expression_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = classObj_setExpression(php_class->class, expression); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getExpressionString() Get the expression string for a class object. */ PHP_METHOD(classObj, getExpressionString) { zval *zobj = getThis(); php_class_object *php_class; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = classObj_getExpressionString(php_class->class); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setText(string text) Set the text string for a class object. */ PHP_METHOD(classObj, setText) { char *text; long text_len = 0; zval *zobj = getThis(); php_class_object *php_class; php_layer_object *php_layer; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(php_class->parent.val TSRMLS_CC); status = classObj_setText(php_class->class, php_layer->layer, text); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getTextString() Get the text string for a class object. */ PHP_METHOD(classObj, getTextString) { zval *zobj = getThis(); php_class_object *php_class; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = classObj_getTextString(php_class->class); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto styleObj getstyle(int index) return the style object. */ PHP_METHOD(classObj, getStyle) { long index; zval *zobj = getThis(); php_class_object *php_class; styleObj *style = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (index < 0 || index >= php_class->class->numstyles) { mapscript_throw_exception("Invalid style index." TSRMLS_CC); return; } style = php_class->class->styles[index]; MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int insertStyle(styleObj style) return MS_SUCCESS or MS_FAILURE. */ PHP_METHOD(classObj, insertStyle) { zval *zobj = getThis(); zval *zstyle = NULL; long index = -1; php_class_object *php_class; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zstyle, mapscript_ce_style, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_style = (php_style_object *) zend_object_store_get_object(zstyle TSRMLS_CC); RETURN_LONG(msInsertStyle(php_class->class, php_style->style, index)); } /* }}} */ /* {{{ proto styleObj removeStyle(int index) return the styleObj removed. */ PHP_METHOD(classObj, removeStyle) { zval *zobj = getThis(); long index; styleObj *style; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); style = msRemoveStyle(php_class->class, index); /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int moveStyleUp(int index) The style specified by the style index will be moved up into the array of classes. Returns MS_SUCCESS or MS_FAILURE. ex class->movestyleup(1) will have the effect of moving style 1 up to position 0, and the style at position 0 will be moved to position 1. */ PHP_METHOD(classObj, moveStyleUp) { long index; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = classObj_moveStyleUp(php_class->class, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int moveStyleDown(int index) The style specified by the style index will be moved down into the array of classes. Returns MS_SUCCESS or MS_FAILURE. ex class->movestyledown(0) will have the effect of moving style 0 up to position 1, and the style at position 1 will be moved to position 0. */ PHP_METHOD(classObj, moveStyleDown) { long index; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = classObj_moveStyleDown(php_class->class, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int deleteStyle(int index) Delete the style specified by the style index. If there are any style that follow the deleted style, their index will decrease by 1. */ PHP_METHOD(classObj, deleteStyle) { long index; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = classObj_deleteStyle(php_class->class, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto string getMetaData(string name) Return MetaData entry by name, or empty string if not found. */ PHP_METHOD(classObj, getMetaData) { zval *zname; zval *zobj = getThis(); php_class_object *php_class; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata); MAPSCRIPT_CALL_METHOD_1(php_class->metadata, "get", retval, zname); RETURN_STRING(Z_STRVAL_P(retval),1); } /* }}} */ /* {{{ proto int setMetaData(string name, string value) Set MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, setMetaData) { zval *zname, *zvalue; zval *zobj = getThis(); php_class_object *php_class; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zname, &zvalue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata); MAPSCRIPT_CALL_METHOD_2(php_class->metadata, "set", retval, zname, zvalue); RETURN_LONG(Z_LVAL_P(retval)); } /* }}} */ /* {{{ proto int removeMetaData(string name) Remove MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, removeMetaData) { zval *zname; zval *zobj = getThis(); php_class_object *php_class; zval *retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); CHECK_OBJECT(mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata); MAPSCRIPT_CALL_METHOD_1(php_class->metadata, "remove", retval, zname); RETURN_LONG(Z_LVAL_P(retval)); } /* }}} */ /* {{{ proto imageObj createLegendIcon(int width, int height) Return the legend icon. */ PHP_METHOD(classObj, createLegendIcon) { zval *zobj = getThis(); long width, height; imageObj *image = NULL; php_class_object *php_class; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(php_class->parent.val TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this class object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if ((image = classObj_createLegendIcon(php_class->class, php_map->map, php_layer->layer, width, height)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return an image object */ mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int drawLegendIcon(int width, int height, imageObj image, int dstX, int dstY) set the lengend icon in img. */ PHP_METHOD(classObj, drawLegendIcon) { zval *zobj = getThis(); zval *zimage; long width, height, dstX, dstY; int status = MS_FAILURE; php_class_object *php_class; php_image_object *php_image; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llOll", &width, &height, &zimage, mapscript_ce_image, &dstX, &dstY) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(php_class->parent.val TSRMLS_CC); if (!php_layer->parent.val) { mapscript_throw_exception("No map object associated with this class object." TSRMLS_CC); return; } php_map = (php_map_object *) zend_object_store_get_object(php_layer->parent.val TSRMLS_CC); if (!MS_RENDERER_PLUGIN(php_image->image->format)) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); mapscript_report_php_error(E_WARNING, "DrawLegendicon function is only available for renderer plugin drivers" TSRMLS_CC); RETURN_LONG(MS_FAILURE); } if ((status = classObj_drawLegendIcon(php_class->class, php_map->map, php_layer->layer, width, height, php_image->image, dstX, dstY)) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto string free() Free the object */ PHP_METHOD(classObj, free) { zval *zobj = getThis(); php_class_object *php_class; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_class->metadata); } /* }}} */ zend_function_entry class_functions[] = { PHP_ME(classObj, __construct, class___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(classObj, __get, class___get_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, __set, class___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(classObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, addLabel, class_addLabel_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, removeLabel, class_removeLabel_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getLabel, class_getLabel_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, updateFromString, class_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, setExpression, class_setExpression_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getExpressionString, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, setText, class_setText_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getTextString, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, getStyle, class_getStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, insertStyle, class_insertStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, removeStyle, class_removeStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, moveStyleUp, class_moveStyleUp_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, moveStyleDown, class_moveStyleDown_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, deleteStyle, class_deleteStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getMetaData, class_getMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, setMetaData, class_setMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, removeMetaData, class_removeMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, createLegendIcon, class_createLegendIcon_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, drawLegendIcon, class_drawLegendIcon_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_class(classObj *class, parent_object parent, zval *return_value TSRMLS_DC) { php_class_object * php_class; object_init_ex(return_value, mapscript_ce_class); php_class = (php_class_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_class->class = class; php_class->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_class_object_destroy(void *object TSRMLS_DC) { php_class_object *php_class = (php_class_object *)object; MAPSCRIPT_FREE_OBJECT(php_class); MAPSCRIPT_FREE_PARENT(php_class->parent); MAPSCRIPT_DELREF(php_class->metadata); MAPSCRIPT_DELREF(php_class->leader); /* We don't need to free the classObj */ efree(object); } static zend_object_value mapscript_class_object_new_ex(zend_class_entry *ce, php_class_object **ptr TSRMLS_DC) { zend_object_value retval; php_class_object *php_class; MAPSCRIPT_ALLOC_OBJECT(php_class, php_class_object); retval = mapscript_object_new_ex(&php_class->std, ce, &mapscript_class_object_destroy, &mapscript_class_object_handlers TSRMLS_CC); if (ptr) *ptr = php_class; MAPSCRIPT_INIT_PARENT(php_class->parent); php_class->metadata = NULL; php_class->leader = NULL; return retval; } static zend_object_value mapscript_class_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_class_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_class_object_clone(zval *zobj TSRMLS_DC) { php_class_object *php_class_old, *php_class_new; php_layer_object *php_layer; zend_object_value new_ov; php_class_old = (php_class_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(php_class_old->parent.val TSRMLS_CC); new_ov = mapscript_class_object_new_ex(mapscript_ce_class, &php_class_new TSRMLS_CC); zend_objects_clone_members(&php_class_new->std, new_ov, &php_class_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_class_new->class = classObj_clone(php_class_old->class, php_layer->layer); return new_ov; } PHP_MINIT_FUNCTION(class) { zend_class_entry ce; memcpy(&mapscript_class_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_class_object_handlers.clone_obj = mapscript_class_object_clone; MAPSCRIPT_REGISTER_CLASS("classObj", class_functions, mapscript_ce_class, mapscript_class_object_new); mapscript_ce_class->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/point.c0000644002461700001440000003513712261257215017413 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_point; ZEND_BEGIN_ARG_INFO_EX(point___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_setXY_args, 0, 0, 2) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_setXYZ_args, 0, 0, 3) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, z) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_distanceToPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_distanceToLine_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_ARG_OBJ_INFO(0, point2, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_distanceToShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_draw_args, 0, 0, 5) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_ARG_INFO(0, classIndex) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() /* {{{ proto point __construct() Create a new pointObj instance. */ PHP_METHOD(pointObj, __construct) { php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if ((php_point->point = pointObj_new()) == NULL) { mapscript_throw_exception("Unable to construct pointObj." TSRMLS_CC); return; } php_point->point->x = 0; php_point->point->y = 0; #ifdef USE_POINT_Z_M php_point->point->z = 0; php_point->point->m = 0; #endif } /* }}} */ PHP_METHOD(pointObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_DOUBLE("x", php_point->point->x) else IF_GET_DOUBLE("y", php_point->point->y) #ifdef USE_POINT_Z_M else IF_GET_DOUBLE("z", php_point->point->z) else IF_GET_DOUBLE("m", php_point->point->m) #endif else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(pointObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_DOUBLE("x", php_point->point->x, value) else IF_SET_DOUBLE("y", php_point->point->y, value) #ifdef USE_POINT_Z_M else IF_SET_DOUBLE("z", php_point->point->z, value) else IF_SET_DOUBLE("m", php_point->point->m, value) #endif else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int point.setXY(double x, double y, double m) 3rd argument m is used for Measured shape files. It is not mandatory. Set new point. Returns MS_FAILURE on error. */ PHP_METHOD(pointObj, setXY) { double x, y, m; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|d", &x, &y, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point->point->x = x; php_point->point->y = y; #ifdef USE_POINT_Z_M if (ZEND_NUM_ARGS() == 3) { php_point->point->m = m; } #endif RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int point.setXYZ(double x, double y, double z, double m) 4th argument m is used for Measured shape files. It is not mandatory. Set new point. Returns MS_FAILURE on error. */ PHP_METHOD(pointObj, setXYZ) { double x, y, z, m; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|d", &x, &y, &z, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point->point->x = x; php_point->point->y = y; #ifdef USE_POINT_Z_M php_point->point->z = z; if (ZEND_NUM_ARGS() == 4) { php_point->point->m = m; } #endif RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int point.project(projectionObj in, projectionObj out) Project the point. returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(pointObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_point_object *php_point; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_proj_in = (php_projection_object *) zend_object_store_get_object(zobj_proj_in TSRMLS_CC); php_proj_out = (php_projection_object *) zend_object_store_get_object(zobj_proj_out TSRMLS_CC); status = pointObj_project(php_point->point, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int point.distanceToPoint(pointObj) Calculates distance between two points. */ PHP_METHOD(pointObj, distanceToPoint) { zval *zobj_point2; zval *zobj = getThis(); php_point_object *php_point, *php_point2; double distance = -1; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobj_point2, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point2 = (php_point_object *) zend_object_store_get_object(zobj_point2 TSRMLS_CC); distance = pointObj_distanceToPoint(php_point->point, php_point2->point); RETURN_DOUBLE(distance); } /* }}} */ /* {{{ proto int point.distanceToLine(pointObj line_point, pointObj line_point2) Calculates distance between a point and a lined defined by the two points passed in argument. */ PHP_METHOD(pointObj, distanceToLine) { zval *zobj = getThis(); zval *zobj_line_point, *zobj_line_point2; php_point_object *php_point, *php_line_point, *php_line_point2; double distance = -1; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_line_point, mapscript_ce_point, &zobj_line_point2, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_line_point = (php_point_object *) zend_object_store_get_object(zobj_line_point TSRMLS_CC); php_line_point2 = (php_point_object *) zend_object_store_get_object(zobj_line_point2 TSRMLS_CC); distance = pointObj_distanceToLine(php_point->point, php_line_point->point, php_line_point2->point); RETURN_DOUBLE(distance); } /* }}} */ /* {{{ proto int distanceToShape(shapeObj shape) Calculates the minimum distance between a point and a shape. */ PHP_METHOD(pointObj, distanceToShape) { zval *zobj = getThis(); zval *zshape; php_point_object *php_point; php_shape_object *php_shape; double distance = -1; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); distance = pointObj_distanceToShape(php_point->point, php_shape->shape); RETURN_DOUBLE(distance); } /* }}} */ /* {{{ proto int point.draw(mapObj map, layerObj layer, imageObj img, string class_name, string text) Draws the individual point using layer. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(pointObj, draw) { zval *zobj = getThis(); zval *zmap, *zlayer, *zimage; char *text = NULL; long text_len = 0; long classIndex; int status = MS_FAILURE; php_point_object *php_point; php_map_object *php_map; php_layer_object *php_layer; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOOl|s", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer, &zimage, mapscript_ce_image, &classIndex, &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = (php_point_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_map = (php_map_object *) zend_object_store_get_object(zmap TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); if ((status = pointObj_draw(php_point->point, php_map->map, php_layer->layer, php_image->image, classIndex, text)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ zend_function_entry point_functions[] = { PHP_ME(pointObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(pointObj, __get, point___get_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, __set, point___set_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, setXY, point_setXY_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, setXYZ, point_setXYZ_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, project, point_project_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, distanceToPoint, point_distanceToPoint_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, distanceToLine, point_distanceToLine_args, ZEND_ACC_PUBLIC) PHP_MALIAS(pointObj, distanceToSegment, distanceToLine, point_distanceToLine_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, distanceToShape, point_distanceToShape_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, draw, point_draw_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_point(pointObj *point, parent_object parent, zval *return_value TSRMLS_DC) { php_point_object * php_point; object_init_ex(return_value, mapscript_ce_point); php_point = (php_point_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_point->point = point; if (parent.val) php_point->is_ref = 1; php_point->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_point_object_destroy(void *object TSRMLS_DC) { php_point_object *php_point = (php_point_object *)object; MAPSCRIPT_FREE_OBJECT(php_point); MAPSCRIPT_FREE_PARENT(php_point->parent); if (php_point->point && !php_point->is_ref) { pointObj_destroy(php_point->point); } efree(object); } static zend_object_value mapscript_point_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_point_object *php_point; MAPSCRIPT_ALLOC_OBJECT(php_point, php_point_object); retval = mapscript_object_new(&php_point->std, ce, &mapscript_point_object_destroy TSRMLS_CC); php_point->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_point->parent); return retval; } PHP_MINIT_FUNCTION(point) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("pointObj", point_functions, mapscript_ce_point, mapscript_point_object_new); mapscript_ce_point->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/cluster.c0000644002461700001440000002511412261257215017735 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_cluster; ZEND_BEGIN_ARG_INFO_EX(cluster___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster_setGroup_args, 0, 0, 1) ZEND_ARG_INFO(0, group) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster_setFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, filter) ZEND_END_ARG_INFO() /* {{{ proto outputformat __construct() clusterObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(clusterObj, __construct) { mapscript_throw_exception("clusterObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(clusterObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_DOUBLE("maxdistance", php_cluster->cluster->maxdistance) else IF_GET_DOUBLE("buffer", php_cluster->cluster->buffer) else IF_GET_STRING("region", php_cluster->cluster->region) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(clusterObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_DOUBLE("maxdistance", php_cluster->cluster->maxdistance, value) else IF_SET_DOUBLE("buffer", php_cluster->cluster->buffer, value) else IF_SET_STRING("region", php_cluster->cluster->region, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int updateFromString(string snippet) Update a cluster from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(clusterObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = clusterObj_updateFromString(php_cluster->cluster, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the cluster object to string. */ PHP_METHOD(clusterObj, convertToString) { zval *zobj = getThis(); php_cluster_object *php_cluster; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = classObj_convertToString(php_cluster->cluster); if (value == NULL) RETURN_STRING("", 1); RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setGroup(string group) Set the group expression string. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(clusterObj, setGroup) { char *group = NULL; long group_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &group, &group_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = clusterObj_setGroup(php_cluster->cluster, group)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string cluster.getGroupString() Return the cluster's group expression. Returns NULL on error. */ PHP_METHOD(clusterObj, getGroupString) { zval *zobj = getThis(); char *value = NULL; php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = clusterObj_getGroupString(php_cluster->cluster); if (value == NULL) { RETURN_NULL(); } RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setFilter(string filter) Set the filter expression string. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(clusterObj, setFilter) { char *filter = NULL; long filter_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filter, &filter_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ((status = clusterObj_setFilter(php_cluster->cluster, filter)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string cluster.getFilterString() Return the cluster's filter expression. Returns NULL on error. */ PHP_METHOD(clusterObj, getFilterString) { zval *zobj = getThis(); char *value = NULL; php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = (php_cluster_object *) zend_object_store_get_object(zobj TSRMLS_CC); value = clusterObj_getFilterString(php_cluster->cluster); if (value == NULL) { RETURN_NULL(); } RETVAL_STRING(value, 1); free(value); } /* }}} */ zend_function_entry cluster_functions[] = { PHP_ME(clusterObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(clusterObj, __get, cluster___get_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, __set, cluster___set_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, updateFromString, cluster_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, setGroup, cluster_setGroup_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, getGroupString, NULL, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, setFilter, cluster_setFilter_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, getFilterString, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_cluster(clusterObj *cluster, parent_object parent, zval *return_value TSRMLS_DC) { php_cluster_object * php_cluster; object_init_ex(return_value, mapscript_ce_cluster); php_cluster = (php_cluster_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_cluster->cluster = cluster; if (parent.val) php_cluster->is_ref = 1; php_cluster->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_cluster_object_destroy(void *object TSRMLS_DC) { php_cluster_object *php_cluster = (php_cluster_object *)object; MAPSCRIPT_FREE_OBJECT(php_cluster); MAPSCRIPT_FREE_PARENT(php_cluster->parent); /* We don't need to free the clusterObj */ efree(object); } static zend_object_value mapscript_cluster_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_cluster_object *php_cluster; MAPSCRIPT_ALLOC_OBJECT(php_cluster, php_cluster_object); retval = mapscript_object_new(&php_cluster->std, ce, &mapscript_cluster_object_destroy TSRMLS_CC); php_cluster->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_cluster->parent) return retval; } PHP_MINIT_FUNCTION(cluster) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("clusterObj", cluster_functions, mapscript_ce_cluster, mapscript_cluster_object_new); mapscript_ce_cluster->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/mapscript_error.c0000644002461700001440000000734712261257215021477 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" #include "zend_exceptions.h" #include "php_mapscript_util.h" #include #include "../../maperror.h" #define MAX_EXCEPTION_MSG 256 zend_class_entry *mapscript_ce_mapscriptexception; zval* mapscript_throw_exception(char *format TSRMLS_DC, ...) { va_list args; char message[MAX_EXCEPTION_MSG]; #ifdef ZTS va_start(args, TSRMLS_C); #else va_start(args, format); #endif vsprintf(message, format, args); va_end(args); return zend_throw_exception(mapscript_ce_mapscriptexception, message, 0 TSRMLS_CC); } zval* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...) { va_list args; char message[MAX_EXCEPTION_MSG]; errorObj *ms_error; ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "[MapServer Error]: %s: %s\n", ms_error->routine, ms_error->message); ms_error = ms_error->next; } #ifdef ZTS va_start(args, TSRMLS_C); #else va_start(args, format); #endif vsprintf(message, format, args); va_end(args); return mapscript_throw_exception(message TSRMLS_CC); } void mapscript_report_php_error(int error_type, char *format TSRMLS_DC, ...) { va_list args; char message[MAX_EXCEPTION_MSG]; #ifdef ZTS va_start(args, TSRMLS_C); #else va_start(args, format); #endif vsprintf(message, format, args); va_end(args); php_error_docref(NULL TSRMLS_CC, error_type, "%s,", message); } void mapscript_report_mapserver_error(int error_type TSRMLS_DC) { errorObj *ms_error; ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { php_error_docref(NULL TSRMLS_CC, error_type, "[MapServer Error]: %s: %s\n", ms_error->routine, ms_error->message); ms_error = ms_error->next; } } PHP_MINIT_FUNCTION(mapscript_error) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MapScriptException", NULL); mapscript_ce_mapscriptexception = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), "Exception" TSRMLS_CC); return SUCCESS; } mapserver-6.4.1/mapscript/php/symbol.c0000644002461700001440000003705312261257215017566 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_symbol; ZEND_BEGIN_ARG_INFO_EX(symbol___construct_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_INFO(0, symbolName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_setPoints_args, 0, 0, 1) ZEND_ARG_INFO(0, points) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_setImagePath_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_setImage_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_getImage_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, outputformat, outputFormatObj, 0) ZEND_END_ARG_INFO() /* {{{ proto void __construct(mapObj map, string symbolname) Create a new symbolObj instance. */ PHP_METHOD(symbolObj, __construct) { zval *zmap; char *symbolName; long symbolName_len = 0; int symbolId = -1; php_symbol_object *php_symbol; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zmap, mapscript_ce_map, &symbolName, &symbolName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *)zend_object_store_get_object(getThis() TSRMLS_CC); php_map = (php_map_object *)zend_object_store_get_object(zmap TSRMLS_CC); symbolId = msAddNewSymbol(php_map->map, symbolName); if (symbolId == -1) { mapscript_throw_mapserver_exception("Unable to construct symbolObj" TSRMLS_CC); return; } php_symbol->symbol = php_map->map->symbolset.symbol[symbolId]; MAPSCRIPT_MAKE_PARENT(zmap, NULL); php_symbol->parent = parent; MAPSCRIPT_ADDREF(zmap); } /* }}} */ PHP_METHOD(symbolObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_symbol_object *php_symbol; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("name", php_symbol->symbol->name) else IF_GET_LONG("type", php_symbol->symbol->type) else IF_GET_LONG("inmapfile", php_symbol->symbol->inmapfile) else IF_GET_DOUBLE("sizex", php_symbol->symbol->sizex) else IF_GET_DOUBLE("sizey", php_symbol->symbol->sizey) else IF_GET_LONG("numpoints", php_symbol->symbol->numpoints) else IF_GET_LONG("filled", php_symbol->symbol->filled) else IF_GET_STRING("imagepath", php_symbol->symbol->imagepath) else IF_GET_LONG("transparent", php_symbol->symbol->transparent) else IF_GET_LONG("transparentcolor", php_symbol->symbol->transparentcolor) else IF_GET_STRING("character", php_symbol->symbol->character) else IF_GET_LONG("antialias", php_symbol->symbol->antialias) else IF_GET_DOUBLE("anchorpoint_y", php_symbol->symbol->anchorpoint_y) else IF_GET_DOUBLE("anchorpoint_x", php_symbol->symbol->anchorpoint_x) else IF_GET_DOUBLE("maxx", php_symbol->symbol->maxx) else IF_GET_DOUBLE("minx", php_symbol->symbol->minx) else IF_GET_DOUBLE("miny", php_symbol->symbol->miny) else IF_GET_DOUBLE("maxy", php_symbol->symbol->maxy) else IF_GET_STRING("font", php_symbol->symbol->font) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(symbolObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_symbol_object *php_symbol; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("name", php_symbol->symbol->name, value) else IF_SET_LONG("type", php_symbol->symbol->type, value) else IF_SET_LONG("inmapfile", php_symbol->symbol->inmapfile, value) else IF_SET_DOUBLE("sizex", php_symbol->symbol->sizex, value) else IF_SET_DOUBLE("sizey", php_symbol->symbol->sizey, value) else IF_SET_LONG("filled", php_symbol->symbol->filled, value) else IF_SET_LONG("transparent", php_symbol->symbol->transparent, value) else IF_SET_LONG("transparentcolor", php_symbol->symbol->transparentcolor, value) else IF_SET_STRING("character", php_symbol->symbol->character, value) else IF_SET_LONG("antialias", php_symbol->symbol->antialias, value) else IF_SET_STRING("font", php_symbol->symbol->font, value) else IF_SET_DOUBLE("anchorpoint_y", php_symbol->symbol->anchorpoint_y, value) else IF_SET_DOUBLE("anchorpoint_x", php_symbol->symbol->anchorpoint_x, value) else IF_SET_DOUBLE("maxx", php_symbol->symbol->maxx, value) else IF_SET_DOUBLE("maxy", php_symbol->symbol->maxy, value) else IF_SET_DOUBLE("minx", php_symbol->symbol->minx, value) else IF_SET_DOUBLE("miny", php_symbol->symbol->miny, value) else if ( (STRING_EQUAL("numpoints", property)) || (STRING_EQUAL("imagepath", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int symbol.setpoints(array points) Set the points of the symbol ) */ PHP_METHOD(symbolObj, setPoints) { zval *zpoints, **ppzval; HashTable *points_hash = NULL; zval *zobj = getThis(); int index = 0, flag = 0, numelements = 0; php_symbol_object *php_symbol; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &zpoints) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *) zend_object_store_get_object(zobj TSRMLS_CC); points_hash = Z_ARRVAL_P(zpoints); numelements = zend_hash_num_elements(points_hash); if ((numelements == 0) || (numelements % 2 != 0)) { mapscript_report_php_error(E_WARNING, "symbol->setpoints : invalid array of %d element(s) as parameter." TSRMLS_CC, numelements); RETURN_LONG(MS_FAILURE); } for(zend_hash_internal_pointer_reset(points_hash); zend_hash_has_more_elements(points_hash) == SUCCESS; zend_hash_move_forward(points_hash)) { zend_hash_get_current_data(points_hash, (void **)&ppzval); if (Z_TYPE_PP(ppzval) != IS_DOUBLE) convert_to_double(*ppzval); if (!flag) { php_symbol->symbol->points[index].x = Z_DVAL_PP(ppzval); php_symbol->symbol->sizex = MS_MAX(php_symbol->symbol->sizex, php_symbol->symbol->points[index].x); } else { php_symbol->symbol->points[index].y = Z_DVAL_PP(ppzval); php_symbol->symbol->sizey = MS_MAX(php_symbol->symbol->sizey, php_symbol->symbol->points[index].y); index++; } flag = !flag; } php_symbol->symbol->numpoints = (numelements/2); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int symbol.getPointsArray() Returns an array containing the points of the symbol. Refer to setpoints to see how the array should be interpreted. */ PHP_METHOD(symbolObj, getPointsArray) { zval *zobj = getThis(); php_symbol_object *php_symbol; int index; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *) zend_object_store_get_object(zobj TSRMLS_CC); array_init(return_value); if (php_symbol->symbol->numpoints > 0) { for (index=0; index < php_symbol->symbol->numpoints; index++) { add_next_index_double(return_value, php_symbol->symbol->points[index].x); add_next_index_double(return_value, php_symbol->symbol->points[index].y); } } } /* }}} */ /* {{{ proto int symbol.setimagepath(char *imagefile) loads a new symbol image ) */ PHP_METHOD(symbolObj, setImagePath) { zval *zobj = getThis(); php_symbol_object *php_symbol; char *filename; long filename_len = 0; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *) zend_object_store_get_object(zobj TSRMLS_CC); status = msLoadImageSymbol(php_symbol->symbol, filename); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int setImage(imageObj image) Set image pixmap symbol */ PHP_METHOD(symbolObj, setImage) { zval *zimage; php_symbol_object *php_symbol; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *)zend_object_store_get_object(getThis() TSRMLS_CC); php_image = (php_image_object *)zend_object_store_get_object(zimage TSRMLS_CC); RETURN_LONG(symbolObj_setImage(php_symbol->symbol, php_image->image)); } /* }}} */ /* {{{ proto imageObj getImage(outputFormatObj outputformat) Get the symbol image */ PHP_METHOD(symbolObj, getImage) { zval *zoutputformat; imageObj *image = NULL; php_map_object *php_map; php_symbol_object *php_symbol; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zoutputformat, mapscript_ce_outputformat) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = (php_symbol_object *)zend_object_store_get_object(getThis() TSRMLS_CC); php_map = (php_map_object *) zend_object_store_get_object(php_symbol->parent.val TSRMLS_CC); php_outputformat = (php_outputformat_object *)zend_object_store_get_object(zoutputformat TSRMLS_CC); image = symbolObj_getImage(php_symbol->symbol, php_outputformat->outputformat); if (image == NULL) { mapscript_throw_exception("Unable to get the symbol image" TSRMLS_CC); return; } /* the outputformat HAS to be added to the map, since the renderer is now used by the current symbol */ if (msGetOutputFormatIndex(php_map->map, php_outputformat->outputformat->name) == -1) msAppendOutputFormat(php_map->map, php_outputformat->outputformat); mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ zend_function_entry symbol_functions[] = { PHP_ME(symbolObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(symbolObj, __get, symbol___get_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, __set, symbol___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(symbolObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, setPoints, symbol_setPoints_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, getPointsArray, NULL, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, setImage, symbol_setImage_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, getImage, symbol_getImage_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, setImagePath, symbol_setImagePath_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_symbol(symbolObj *symbol, parent_object parent, zval *return_value TSRMLS_DC) { php_symbol_object * php_symbol; object_init_ex(return_value, mapscript_ce_symbol); php_symbol = (php_symbol_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_symbol->symbol = symbol; php_symbol->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_symbol_object_destroy(void *object TSRMLS_DC) { php_symbol_object *php_symbol = (php_symbol_object *)object; MAPSCRIPT_FREE_OBJECT(php_symbol); MAPSCRIPT_FREE_PARENT(php_symbol->parent); /* We don't need to free the symbolObj */ efree(object); } static zend_object_value mapscript_symbol_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_symbol_object *php_symbol; MAPSCRIPT_ALLOC_OBJECT(php_symbol, php_symbol_object); retval = mapscript_object_new(&php_symbol->std, ce, &mapscript_symbol_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_symbol->parent); return retval; } PHP_MINIT_FUNCTION(symbol) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("symbolObj", symbol_functions, mapscript_ce_symbol, mapscript_symbol_object_new); mapscript_ce_symbol->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/php_regex.c0000644002461700001440000000622312261257215020235 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Regex wrapper * Author: Bill Binko * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************** * * $Log$ * Revision 1.2 2005/05/27 15:00:12 dan * New regex wrappers to solve issues with previous version (bug 1354) * */ /* we can't include mapserver.h, so we need our own basics */ #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #else #include #endif /*Need to specify this so that mapregex.h doesn't defined constants and doesn't #define away our ms_*/ #define BUILDING_REGEX_PROXY 1 #include "../../mapregex.h" /* regex_extra.h doesn't exist in PHP >=5.3 */ #include "php.h" #if ZEND_MODULE_API_NO < 20090626 #include "regex/regex_extra.h" #include "regex/regex.h" #else #include "php_regex.h" #endif MS_API_EXPORT(int) ms_regcomp(ms_regex_t *regex, const char *expr, int cflags) { /* Must free in regfree() */ regex_t* sys_regex = (regex_t*) malloc(sizeof(regex_t)); regex->sys_regex = (void*) sys_regex; return regcomp(sys_regex, expr, cflags); } MS_API_EXPORT(size_t) ms_regerror(int errcode, const ms_regex_t *regex, char *errbuf, size_t errbuf_size) { return regerror(errcode, (regex_t*)(regex->sys_regex), errbuf, errbuf_size); } MS_API_EXPORT(int) ms_regexec(const ms_regex_t *regex, const char *string, size_t nmatch, ms_regmatch_t pmatch[], int eflags) { /*This next line only works because we know that regmatch_t and ms_regmatch_t are exactly alike (POSIX STANDARD)*/ return regexec((const regex_t*)(regex->sys_regex), string, nmatch, (regmatch_t*) pmatch, eflags); } MS_API_EXPORT(void) ms_regfree(ms_regex_t *regex) { regfree((regex_t*)(regex->sys_regex)); free(regex->sys_regex); return; } mapserver-6.4.1/mapscript/php/result.c0000644002461700001440000001425312261257215017574 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_result; ZEND_BEGIN_ARG_INFO_EX(result___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, shapeindex) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(result___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(result___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto resultObj __construct() Create a new resultObj instance */ PHP_METHOD(resultObj, __construct) { long shapeindex; php_result_object *php_result; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &shapeindex) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_result = (php_result_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if ((php_result->result = resultObj_new()) == NULL) { mapscript_throw_exception("Unable to construct resultObj." TSRMLS_CC); return; } php_result->result->shapeindex = shapeindex; } /* }}} */ PHP_METHOD(resultObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_result_object *php_result; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_result = (php_result_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("shapeindex", php_result->result->shapeindex) else IF_GET_LONG("tileindex", php_result->result->tileindex) else IF_GET_LONG("classindex", php_result->result->classindex) else IF_GET_LONG("resultindex", php_result->result->resultindex) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(resultObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_result_object *php_result; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_result = (php_result_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (STRING_EQUAL("shapeindex", property)) || (STRING_EQUAL("tileindex", property)) || (STRING_EQUAL("resultindex", property)) || (STRING_EQUAL("classindex", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } zend_function_entry result_functions[] = { PHP_ME(resultObj, __construct, result___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(resultObj, __get, result___get_args, ZEND_ACC_PUBLIC) PHP_ME(resultObj, __set, result___set_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_result(resultObj *result, parent_object parent, zval *return_value TSRMLS_DC) { php_result_object * php_result; object_init_ex(return_value, mapscript_ce_result); php_result = (php_result_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_result->result = result; php_result->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_result_object_destroy(void *object TSRMLS_DC) { php_result_object *php_result = (php_result_object *)object; MAPSCRIPT_FREE_OBJECT(php_result); MAPSCRIPT_FREE_PARENT(php_result->parent); /* We don't need to free the resultObj */ efree(object); } static zend_object_value mapscript_result_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_result_object *php_result; MAPSCRIPT_ALLOC_OBJECT(php_result, php_result_object); retval = mapscript_object_new(&php_result->std, ce, &mapscript_result_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_result->parent); return retval; } PHP_MINIT_FUNCTION(result) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("resultObj", result_functions, mapscript_ce_result, mapscript_result_object_new); mapscript_ce_result->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/image.c0000644002461700001440000003237212261257215017342 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" #include "ext/standard/head.h" #include "main/php_output.h" zend_class_entry *mapscript_ce_image; ZEND_BEGIN_ARG_INFO_EX(image___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(image___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(image_pasteImage_args, 0, 0, 2) ZEND_ARG_INFO(0, srcImg) ZEND_ARG_INFO(0, transparentColorHex) ZEND_ARG_INFO(0, dstX) ZEND_ARG_INFO(0, dstY) ZEND_ARG_INFO(0, angle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(image_saveImage_args, 0, 0, 2) ZEND_ARG_INFO(0, filename) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_END_ARG_INFO() /* {{{ proto image __construct() imageObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(imageObj, __construct) { mapscript_throw_exception("imageObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(imageObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = (php_image_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("width", php_image->image->width) else IF_GET_LONG("height", php_image->image->height) else IF_GET_LONG("resolution", php_image->image->resolution) else IF_GET_LONG("resolutionfactor", php_image->image->resolutionfactor) else IF_GET_STRING("imagepath", php_image->image->imagepath) else IF_GET_STRING("imageurl", php_image->image->imageurl) else IF_GET_STRING("imagetype", php_image->image->format->name) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(imageObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = (php_image_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("imagepath", php_image->image->imagepath, value) else IF_SET_STRING("imageurl", php_image->image->imageurl, value) else IF_SET_STRING("imagetype", php_image->image->format->name, value) else if ( (STRING_EQUAL("width", property)) || (STRING_EQUAL("resolution", property)) || (STRING_EQUAL("resolutionfactor", property)) || (STRING_EQUAL("height", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int saveWebImage() Writes image to temp directory. Returns image URL. */ PHP_METHOD(imageObj, saveWebImage) { zval *zobj = getThis(); php_image_object *php_image; char *imageFile = NULL; char *imageFilename = NULL; char path[MS_MAXPATHLEN]; char *imageUrlFull = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = (php_image_object *) zend_object_store_get_object(zobj TSRMLS_CC); imageFilename = msTmpFilename(php_image->image->format->extension); imageFile = msBuildPath(path, php_image->image->imagepath, imageFilename); if (msSaveImage(NULL, php_image->image, imageFile) != MS_SUCCESS) { mapscript_throw_mapserver_exception("Failed writing image to %s" TSRMLS_CC, imageFile); return; } imageUrlFull = msBuildPath(path, php_image->image->imageurl, imageFilename); msFree(imageFilename); RETURN_STRING(imageUrlFull, 1); } /* }}} */ /* {{{ proto void pasteImage(imageObj Src, int transparentColor [[,int dstx, int dsty], int angle]) Pastes another imageObj on top of this imageObj. transparentColor is the color (0xrrggbb) from srcImg that should be considered transparent. Pass transparentColor=-1 if you don't want any transparent color. If optional dstx,dsty are provided then they define the position where the image should be copied (dstx,dsty = top-left corner position). The optional angle is a value between 0 and 360 degrees to rotate the source image counterclockwise. Note that if a rotation is requested then the dstx and dsty coordinates specify the CENTER of the destination area. NOTE : this function only works for 8 bits GD images. */ PHP_METHOD(imageObj, pasteImage) { long transparent=-1, dstx=0, dsty=0, angle=0; int angleSet=MS_FALSE; zval *zimage; zval *zobj = getThis(); php_image_object *php_image, *php_imageSrc; /*int oldTransparentColor, newTransparentColor=-1, r, g, b;*/ rendererVTableObj *renderer = NULL; rasterBufferObj rb; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|lll", &zimage, mapscript_ce_image, &transparent, &dstx, &dsty, &angle) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if (ZEND_NUM_ARGS() == 3) { mapscript_report_php_error(E_WARNING, "dstX parameter given but not dstY" TSRMLS_CC); } else angleSet = MS_TRUE; php_image = (php_image_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_imageSrc = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); if (!MS_RENDERER_PLUGIN(php_imageSrc->image->format) || !MS_RENDERER_PLUGIN(php_image->image->format)) { mapscript_throw_exception("PasteImage function should only be used with renderer plugin drivers." TSRMLS_CC); return; } #ifdef undef //USE_AGG if( MS_RENDERER_AGG(php_imageSrc->image->format)) msAlphaAGG2GD(php_imageSrc->image); if( MS_RENDERER_AGG(php_image->image->format)) msAlphaAGG2GD(php_image->image); #endif renderer = MS_IMAGE_RENDERER(php_image->image); memset(&rb,0,sizeof(rasterBufferObj)); renderer->getRasterBufferHandle(php_imageSrc->image, &rb); renderer->mergeRasterBuffer(php_image->image, &rb, 1.0, 0, 0, dstx, dsty, rb.width, rb.height); /* Look for r,g,b in color table and make it transparent. * will return -1 if there is no exact match which will result in * no transparent color in the call to gdImageColorTransparent(). */ /* if (transparent != -1) { r = (transparent / 0x010000) & 0xff; g = (transparent / 0x0100) & 0xff; b = transparent & 0xff; newTransparentColor = gdImageColorExact(php_imageSrc->image->img.gd, r, g, b); } oldTransparentColor = gdImageGetTransparent(php_imageSrc->image->img.gd); gdImageColorTransparent(php_imageSrc->image->img.gd, newTransparentColor); if (!angleSet) gdImageCopy(php_image->image->img.gd, php_imageSrc->image->img.gd, dstx, dsty, 0, 0, php_imageSrc->image->img.gd->sx, php_imageSrc->image->img.gd->sy); else gdImageCopyRotated(php_image->image->img.gd, php_imageSrc->image->img.gd, dstx, dsty, 0, 0, php_imageSrc->image->img.gd->sx, php_imageSrc->image->img.gd->sy, angle); gdImageColorTransparent(php_imageSrc->image->img.gd, oldTransparentColor);*/ RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int saveImage(string filename, mapObj map) Writes image object to specifed filename. If filename is empty then write to stdout. Returns MS_FAILURE on error. Second aregument oMap is not manadatory. It is usful when saving to other formats like GTIFF to get georeference infos.*/ PHP_METHOD(imageObj, saveImage) { zval *zobj = getThis(); zval *zmap = NULL; char *filename = NULL; long filename_len = 0; php_image_object *php_image; php_map_object *php_map; int status = MS_SUCCESS; /* stdout specific vars */ int size=0; void *iptr=NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO", &filename, &filename_len, &zmap, mapscript_ce_map) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = (php_image_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (zmap) php_map = (php_map_object *) zend_object_store_get_object(zmap TSRMLS_CC); if(filename_len > 0) { if ((status = msSaveImage((zmap ? php_map->map:NULL), php_image->image, filename) != MS_SUCCESS)) { mapscript_throw_mapserver_exception("Failed writing image to %s" TSRMLS_CC, filename); return; } RETURN_LONG(status); } /* no filename - read stdout */ /* if there is no output buffer active, set the header */ //handle changes in PHP 5.4.x #if PHP_VERSION_ID < 50399 if (OG(ob_nesting_level)<=0) { php_header(TSRMLS_C); } #else if (php_output_get_level(TSRMLS_C)<=0) { php_header(TSRMLS_C); } #endif if (MS_RENDERER_PLUGIN(php_image->image->format)) { iptr = (void *)msSaveImageBuffer(php_image->image, &size, php_image->image->format); } else if (php_image->image->format->name && (strcasecmp(php_image->image->format->name, "imagemap")==0)) { iptr = php_image->image->img.imagemap; size = strlen(php_image->image->img.imagemap); } if (size == 0) { mapscript_throw_mapserver_exception("Failed writing image to stdout" TSRMLS_CC); return; } else { php_write(iptr, size TSRMLS_CC); status = MS_SUCCESS; /* status = size; why should we return the size ?? */ msFree(iptr); } RETURN_LONG(status); } /* }}} */ zend_function_entry image_functions[] = { PHP_ME(imageObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(imageObj, __get, image___get_args, ZEND_ACC_PUBLIC) PHP_ME(imageObj, __set, image___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(imageObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(imageObj, saveWebImage, NULL, ZEND_ACC_PUBLIC) PHP_ME(imageObj, pasteImage, image_pasteImage_args, ZEND_ACC_PUBLIC) PHP_ME(imageObj, saveImage, image_saveImage_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_image(imageObj *image, zval *return_value TSRMLS_DC) { php_image_object * php_image; object_init_ex(return_value, mapscript_ce_image); php_image = (php_image_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_image->image = image; } static void mapscript_image_object_destroy(void *object TSRMLS_DC) { php_image_object *php_image = (php_image_object *)object; MAPSCRIPT_FREE_OBJECT(php_image); msFreeImage(php_image->image); efree(object); } static zend_object_value mapscript_image_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_image_object *php_image; MAPSCRIPT_ALLOC_OBJECT(php_image, php_image_object); retval = mapscript_object_new(&php_image->std, ce, &mapscript_image_object_destroy TSRMLS_CC); return retval; } PHP_MINIT_FUNCTION(image) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("imageObj", image_functions, mapscript_ce_image, mapscript_image_object_new); mapscript_ce_image->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/php_mapscript_util.c0000644002461700001440000001643612261257215022171 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer : Utility functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000-2005, DM Solutions Group * * 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. **********************************************************************/ #include "php_mapscript_util.h" #include "../../maperror.h" zend_object_value mapscript_object_new(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object) TSRMLS_DC) { zend_object_value retval; zval *temp; zobj->ce = ce; ALLOC_HASHTABLE(zobj->properties); zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0); //handle changes in PHP 5.4.x #if PHP_VERSION_ID < 50399 zend_hash_copy(zobj->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &temp, sizeof(zval *)); #else object_properties_init(zobj, ce); #endif retval.handle = zend_objects_store_put(zobj, NULL, (zend_objects_free_object_storage_t)zend_objects_free_object, NULL TSRMLS_CC); retval.handlers = &mapscript_std_object_handlers; return retval; } zend_object_value mapscript_object_new_ex(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object), zend_object_handlers *object_handlers TSRMLS_DC) { zend_object_value retval; zval *temp; zobj->ce = ce; ALLOC_HASHTABLE(zobj->properties); zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0); //handle changes in PHP 5.4.x #if PHP_VERSION_ID < 50399 zend_hash_copy(zobj->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &temp, sizeof(zval *)); #else object_properties_init(zobj, ce); #endif retval.handle = zend_objects_store_put(zobj, NULL, (zend_objects_free_object_storage_t)zend_objects_free_object, NULL TSRMLS_CC); retval.handlers = object_handlers; return retval; } int mapscript_extract_associative_array(HashTable *php, char **array) { zval **value; char *string_key = NULL; ulong num_key; int i = 0; for(zend_hash_internal_pointer_reset(php); zend_hash_has_more_elements(php) == SUCCESS; zend_hash_move_forward(php)) { zend_hash_get_current_data(php, (void **)&value); switch (zend_hash_get_current_key(php, &string_key, &num_key, 1)) { case HASH_KEY_IS_STRING: array[i++] = string_key; array[i++] = Z_STRVAL_PP(value); break; } } array[i++] = NULL; return 1; } /* This method returns an object property of a php class. If the object exists, it returns a reference to it, otherwise it creates it */ void mapscript_fetch_object(zend_class_entry *ce, zval* zval_parent, php_layer_object* layer, void *internal_object, zval **php_object_storage TSRMLS_DC) { parent_object p; // create the parent struct p.val = zval_parent; p.child_ptr = &*php_object_storage; MAKE_STD_ZVAL(*php_object_storage); if (ce == mapscript_ce_outputformat) mapscript_create_outputformat((outputFormatObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_color) mapscript_create_color((colorObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_rect) mapscript_create_rect((rectObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_class) mapscript_create_class((classObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_hashtable) mapscript_create_hashtable((hashTableObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_label) mapscript_create_label((labelObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_style) mapscript_create_style((styleObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_symbol) mapscript_create_symbol((symbolObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_labelcachemember) mapscript_create_labelcachemember((labelCacheMemberObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_labelcache) mapscript_create_labelcache((labelCacheObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_result) mapscript_create_result((resultObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_scalebar) mapscript_create_scalebar((scalebarObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_web) mapscript_create_web((webObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_legend) mapscript_create_legend((legendObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_querymap) mapscript_create_querymap((queryMapObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_grid) mapscript_create_grid((graticuleObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_referencemap) mapscript_create_referencemap((referenceMapObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_point) mapscript_create_point((pointObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_projection) mapscript_create_projection((projectionObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_line) mapscript_create_line((lineObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_shape) mapscript_create_shape((shapeObj*)internal_object, p, layer, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_layer) mapscript_create_layer((layerObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_cluster) mapscript_create_cluster((clusterObj*)internal_object, p, *php_object_storage TSRMLS_CC); else if (ce == mapscript_ce_labelleader) mapscript_create_labelleader((labelLeaderObj*)internal_object, p, *php_object_storage TSRMLS_CC); } mapserver-6.4.1/mapscript/php/line.c0000644002461700001440000003173312261257215017207 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_line; zend_object_handlers mapscript_line_object_handlers; ZEND_BEGIN_ARG_INFO_EX(line___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_add_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_set_args, 0, 0, 2) ZEND_ARG_INFO(0, index) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_addXY_args, 0, 0, 2) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_addXYZ_args, 0, 0, 3) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, z) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_point_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto line __construct() Create a new lineObj instance. */ PHP_METHOD(lineObj, __construct) { php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if ((php_line->line = lineObj_new()) == NULL) { mapscript_throw_exception("Unable to construct lineObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(lineObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numpoints", php_line->line->numpoints) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(lineObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (STRING_EQUAL("numpoints", property)) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int line.add(pointObj point) Adds a point to the end of a line */ PHP_METHOD(lineObj, add) { zval *zobj = getThis(); zval *zobj_point; php_line_object *php_line; php_point_object *php_point; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobj_point, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zobj_point TSRMLS_CC); status = lineObj_add(php_line->line, php_point->point); RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.addXY(double x, double y, double m) 3rd argument m is used for Measured shape files. It is not mandatory. Adds a point to the end of a line */ PHP_METHOD(lineObj, addXY) { zval *zobj = getThis(); pointObj point; double x, y, m = 0; int status = MS_FAILURE; php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|d", &x, &y, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); point.x = x; point.y = y; #ifdef USE_LINE_Z_M point.z = 0; point.m = m; #endif status = lineObj_add(php_line->line, &point); RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.addXYZ(double x, double y, double z, double m) 4th argument m is used for Measured shape files. It is not mandatory. Adds a point to the end of a line */ PHP_METHOD(lineObj, addXYZ) { zval *zobj = getThis(); pointObj point; double x, y, z, m = 0; int status = MS_FAILURE; php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|d", &x, &y, &z, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); point.x = x; point.y = y; #ifdef USE_LINE_Z_M point.z = z; point.m = m; #endif status = lineObj_add(php_line->line, &point); RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.project(projectionObj in, projectionObj out) Project the point. returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(lineObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_line_object *php_line; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_proj_in = (php_projection_object *) zend_object_store_get_object(zobj_proj_in TSRMLS_CC); php_proj_out = (php_projection_object *) zend_object_store_get_object(zobj_proj_out TSRMLS_CC); status = lineObj_project(php_line->line, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.point(int i) Returns point number i. First point is number 0. */ PHP_METHOD(lineObj, point) { zval *zobj = getThis(); php_line_object *php_line; long index; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (index < 0) || (index >= php_line->line->numpoints)) { mapscript_throw_exception("Point '%d' does not exist in this object." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_point(&(php_line->line->point[index]), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int line.set(int, index, pointObj point) Set the point values at the specified index */ PHP_METHOD(lineObj, set) { zval *zobj = getThis(); zval *zobj_point; long index; php_line_object *php_line; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO", &index, &zobj_point, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); if ( (index < 0) || (index >= php_line->line->numpoints)) { mapscript_throw_exception("Point '%d' does not exist in this object." TSRMLS_CC, index); return; } php_point = (php_point_object *) zend_object_store_get_object(zobj_point TSRMLS_CC); php_line->line->point[index].x = php_point->point->x; php_line->line->point[index].y = php_point->point->y; RETURN_LONG(MS_SUCCESS); } /* }}} */ zend_function_entry line_functions[] = { PHP_ME(lineObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(lineObj, __get, line___get_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, __set, line___set_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, add, line_add_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, addXY, line_addXY_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, addXYZ, line_addXYZ_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, project, line_project_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, point, line_point_args, ZEND_ACC_PUBLIC) PHP_MALIAS(lineObj, get, point, line_point_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, set, line_set_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_line(lineObj *line, parent_object parent, zval *return_value TSRMLS_DC) { php_line_object * php_line; object_init_ex(return_value, mapscript_ce_line); php_line = (php_line_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_line->line = line; if (parent.val) php_line->is_ref = 1; php_line->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_line_object_destroy(void *object TSRMLS_DC) { php_line_object *php_line = (php_line_object *)object; MAPSCRIPT_FREE_OBJECT(php_line); MAPSCRIPT_FREE_PARENT(php_line->parent); if (php_line->line && !php_line->is_ref) { lineObj_destroy(php_line->line); } efree(object); } static zend_object_value mapscript_line_object_new_ex(zend_class_entry *ce, php_line_object **ptr TSRMLS_DC) { zend_object_value retval; php_line_object *php_line; MAPSCRIPT_ALLOC_OBJECT(php_line, php_line_object); retval = mapscript_object_new_ex(&php_line->std, ce, &mapscript_line_object_destroy, &mapscript_line_object_handlers TSRMLS_CC); if (ptr) *ptr = php_line; php_line->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_line->parent); return retval; } static zend_object_value mapscript_line_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_line_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_line_object_clone(zval *zobj TSRMLS_DC) { php_line_object *php_line_old, *php_line_new; zend_object_value new_ov; php_line_old = (php_line_object *) zend_object_store_get_object(zobj TSRMLS_CC); new_ov = mapscript_line_object_new_ex(mapscript_ce_line, &php_line_new TSRMLS_CC); zend_objects_clone_members(&php_line_new->std, new_ov, &php_line_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_line_new->line = lineObj_clone(php_line_old->line); return new_ov; } PHP_MINIT_FUNCTION(line) { zend_class_entry ce; memcpy(&mapscript_line_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_line_object_handlers.clone_obj = mapscript_line_object_clone; MAPSCRIPT_REGISTER_CLASS("lineObj", line_functions, mapscript_ce_line, mapscript_line_object_new); mapscript_ce_line->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/shape.c0000644002461700001440000012154512261257215017361 0ustar tbonfortusers/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * 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. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_shape; ZEND_BEGIN_ARG_INFO_EX(shape___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_add_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, line, lineObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_line_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_contains_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_intersects_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_getPointUsingMeasure_args, 0, 0, 1) ZEND_ARG_INFO(0, measure) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_getMeasureUsingPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_getValue_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_INFO(0, fieldName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_buffer_args, 0, 0, 1) ZEND_ARG_INFO(0, width) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_containsShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_union_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_intersection_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_difference_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_symdifference_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_overlaps_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_within_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_crosses_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_touches_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_equals_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_disjoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_simplify_args, 0, 0, 1) ZEND_ARG_INFO(0, tolerance) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_topologyPreservingSimplify_args, 0, 0, 1) ZEND_ARG_INFO(0, tolerance) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_draw_args, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_distanceToPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_distanceToShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() /* {{{ proto shape __construct(int type) Create a new shapeObj instance. */ PHP_METHOD(shapeObj, __construct) { zval *zobj = getThis(); php_shape_object *php_shape; long type; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *)zend_object_store_get_object(zobj TSRMLS_CC); if ((php_shape->shape = shapeObj_new(type)) == NULL) { mapscript_throw_exception("Unable to construct shapeObj." TSRMLS_CC); return; } MAKE_STD_ZVAL(php_shape->values); array_init(php_shape->values); } /* }}} */ PHP_METHOD(shapeObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_STRING("text", php_shape->shape->text) else IF_GET_LONG("classindex", php_shape->shape->classindex) else IF_GET_LONG("index", php_shape->shape->index) else IF_GET_LONG("tileindex", php_shape->shape->tileindex) else IF_GET_LONG("resultindex", php_shape->shape->resultindex) else IF_GET_LONG("numlines", php_shape->shape->numlines) else IF_GET_LONG("numvalues", php_shape->shape->numvalues) else IF_GET_LONG("type", php_shape->shape->type) else IF_GET_OBJECT("bounds", mapscript_ce_rect, php_shape->bounds, &php_shape->shape->bounds) else IF_GET_OBJECT("values", NULL, php_shape->values, NULL) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(shapeObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_SET_STRING("text", php_shape->shape->text, value) else IF_SET_LONG("classindex", php_shape->shape->classindex, value) else IF_SET_LONG("index", php_shape->shape->index, value) else if ( (STRING_EQUAL("type", property)) || (STRING_EQUAL("numlines", property)) || (STRING_EQUAL("tileindex", property)) || (STRING_EQUAL("resultindex", property)) || (STRING_EQUAL("bounds", property)) || (STRING_EQUAL("values", property)) || (STRING_EQUAL("numvalues", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int shape.add(lineObj line) Adds a line (i.e. a part) to a shape */ PHP_METHOD(shapeObj, add) { zval *zobj = getThis(); zval *zline; php_shape_object *php_shape; php_line_object *php_line; int retval = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zline, mapscript_ce_line) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_line = (php_line_object *) zend_object_store_get_object(zline TSRMLS_CC); retval = shapeObj_add(php_shape->shape, php_line->line); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int shape.line(int i) Returns line (part) number i. First line is number 0. */ PHP_METHOD(shapeObj, line) { zval *zobj = getThis(); long index; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); if (index < 0 || index >= php_shape->shape->numlines) { mapscript_throw_exception("Line '%d' does not exist in this object." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_line(&(php_shape->shape->line[index]), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.contains(pointObj point) Returns true or false if the the point is in a polygone shape.*/ PHP_METHOD(shapeObj, contains) { zval *zobj = getThis(); zval *zpoint; php_shape_object *php_shape; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); if (!shapeObj_contains(php_shape->shape, php_point->point)) RETURN_FALSE; RETURN_TRUE; } /* }}} */ /* {{{ proto int shape.intersects(shapeObj shape) Returns true if the two shapes intersect. Else false.*/ PHP_METHOD(shapeObj, intersects) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (!shapeObj_intersects(php_shape->shape, php_shape2->shape)) RETURN_FALSE; RETURN_TRUE; } /* }}} */ /* {{{ proto int shape.project(projectionObj in, projectionObj out) Project a Shape. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(shapeObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_shape_object *php_shape; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_proj_in = (php_projection_object *) zend_object_store_get_object(zobj_proj_in TSRMLS_CC); php_proj_out = (php_projection_object *) zend_object_store_get_object(zobj_proj_out TSRMLS_CC); status = shapeObj_project(php_shape->shape, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int shape.getpointusingmeasure(double measure) Given a shape and a mesure, return a point object containing the XY location corresponding to the measure */ PHP_METHOD(shapeObj, getPointUsingMeasure) { zval *zobj = getThis(); double measure; pointObj *point = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &measure) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); point = shapeObj_getpointusingmeasure(php_shape->shape, measure); if (point == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.getpointusingmeasure(pointObj point) Given a shape and a point object, return a point object containing the XY location of the intersection between the point and the shape. The point return contains also the extrapolated M value at the intersection. */ PHP_METHOD(shapeObj, getMeasureUsingPoint) { zval *zobj = getThis(); zval *zpoint; pointObj *intersection = NULL; php_shape_object *php_shape; php_point_object *php_point; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); intersection = shapeObj_getmeasureusingpoint(php_shape->shape, php_point->point); if (intersection == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(intersection, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto string shape.getValue(layerObj layer, string fieldName) Returns value for specified field name. */ PHP_METHOD(shapeObj, getValue) { zval *zobj = getThis(); zval *zlayer; char *fieldName; long fieldName_len = 0; int i; php_layer_object *php_layer; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zlayer, mapscript_ce_layer, &fieldName, &fieldName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); if (php_shape->shape->numvalues != php_layer->layer->numitems) RETURN_STRING("", 1); for(i=0; ilayer->numitems; i++) { if (strcasecmp(php_layer->layer->items[i], fieldName)==0) { RETURN_STRING(php_shape->shape->values[i], 1); } } } /* }}} */ /* {{{ proto int shape.buffer(double width) Given a shape and a width, return a shape object with a buffer using underlying GEOS library*/ PHP_METHOD(shapeObj, buffer) { zval *zobj = getThis(); double width; shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &width) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); shape = shapeObj_buffer(php_shape->shape, width); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.convexhull() Given a shape, return a shape representing the convex hull using underlying GEOS library */ PHP_METHOD(shapeObj, convexhull) { zval *zobj = getThis(); shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); shape = shapeObj_convexHull(php_shape->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.boundary() Returns the boundary of the shape. Only available if php/mapscript is built with GEOS library.*/ PHP_METHOD(shapeObj, boundary) { zval *zobj = getThis(); shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); shape = shapeObj_boundary(php_shape->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.contains(shapeobj shape) Return true or false if the given shape in argument 1 is contained in the shape. Use3d underlying msGEOSContains GEOS library*/ PHP_METHOD(shapeObj, containsShape) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_contains_geos(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.Union(shapeobj shape) Return a shape which is the union of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, union) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); shape = shapeObj_Union(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.intersection(shapeobj shape) Return a shape which is the intersection of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, intersection) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); shape = shapeObj_intersection(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.difference(shapeobj shape) Return a shape which is the difference of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, difference) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); shape = shapeObj_difference(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.symdifference(shapeobj shape) Return a shape which is the symetrical difference of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, symdifference) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); shape = shapeObj_symdifference(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.overlaps(shapeobj shape) Return true if the given shape in argument 1 overlaps the shape. Else return false. */ PHP_METHOD(shapeObj, overlaps) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_overlaps(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.within(shapeobj shape) Return true if the given shape in argument 1 is within the shape. Else return false. */ PHP_METHOD(shapeObj, within) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_within(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.crosses(shapeobj shape) Return true if the given shape in argument 1 crosses the shape. Else return false. */ PHP_METHOD(shapeObj, crosses) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_crosses(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.touches(shapeobj shape) Return true if the given shape in argument 1 touches the shape. Else return false. */ PHP_METHOD(shapeObj, touches) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_touches(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.equals(shapeobj shape) Return true if the given shape in argument 1 is equal to the shape. Else return false. */ PHP_METHOD(shapeObj, equals) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_equals(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.disjoint(shapeobj shape) Return true if the given shape in argument 1 is disjoint to the shape. Else return false. */ PHP_METHOD(shapeObj, disjoint) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); if (shapeObj_disjoint(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.getcentroid() Given a shape, return a point object representing the centroid */ PHP_METHOD(shapeObj, getCentroid) { zval *zobj = getThis(); pointObj *point; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); point = shapeObj_getcentroid(php_shape->shape); if (point == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.getarea() Returns the area of the shape */ PHP_METHOD(shapeObj, getArea) { zval *zobj = getThis(); double area = 0; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); area = shapeObj_getarea(php_shape->shape); RETURN_DOUBLE(area); } /* }}} */ /* {{{ proto int shape.getlength() Returns the length of the shape */ PHP_METHOD(shapeObj, getLength) { zval *zobj = getThis(); double length = 0; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); length = shapeObj_getlength(php_shape->shape); RETURN_DOUBLE(length); } /* }}} */ /* {{{ proto int shape.getlabelpoint() Given a shape, return a point object suitable for labelling it */ PHP_METHOD(shapeObj, getLabelPoint) { zval *zobj = getThis(); pointObj *point; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); point = shapeObj_getLabelPoint(php_shape->shape); if (point == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto string shape.toWkt() Returns WKT representation of geometry. */ PHP_METHOD(shapeObj, toWkt) { zval *zobj = getThis(); char *wkt = NULL; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); wkt = msShapeToWKT(php_shape->shape); if (wkt) { RETVAL_STRING(wkt, 1); msFree(wkt); return; } RETURN_STRING("", 1); } /* }}} */ /* {{{ proto int shape.setBounds() Updates the bounds property of the shape. Must be called to calculate new bounding box after new parts have been added. Returns true if successful, else return false.*/ PHP_METHOD(shapeObj, setBounds) { zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); shapeObj_setBounds(php_shape->shape); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int shape.simplify(double tolerance) Given a shape and a tolerance, return a simplified shape object using underlying GEOS library */ PHP_METHOD(shapeObj, simplify) { zval *zobj = getThis(); double tolerance; shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &tolerance) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); shape = shapeObj_simplify(php_shape->shape, tolerance); if (shape == NULL) RETURN_NULL(); MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.topologypreservingsimplify(double tolerance) Given a shape and a tolerance, return a simplified shape object using underlying GEOS library */ PHP_METHOD(shapeObj, topologyPreservingSimplify) { zval *zobj = getThis(); double tolerance; shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &tolerance) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); shape = shapeObj_topologypreservingsimplify(php_shape->shape, tolerance); if (shape == NULL) RETURN_NULL(); MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.draw(mapObj map, layerObj layer, imageObj img) Draws the individual shape using layer. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(shapeObj, draw) { zval *zobj = getThis(); zval *zmap, *zlayer, *zimage; int status = MS_FAILURE; php_shape_object *php_shape; php_map_object *php_map; php_layer_object *php_layer; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer, &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_map = (php_map_object *) zend_object_store_get_object(zmap TSRMLS_CC); php_layer = (php_layer_object *) zend_object_store_get_object(zlayer TSRMLS_CC); php_image = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC); if ((status = shapeObj_draw(php_shape->shape, php_map->map, php_layer->layer, php_image->image)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto void shape.free() Free the object */ PHP_METHOD(shapeObj, free) { zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); MAPSCRIPT_DELREF(php_shape->bounds); } /* }}} */ /* {{{ proto int shape.distanceToPoint(pointObj point) Returns the distance from the point to shape. */ PHP_METHOD(shapeObj, distanceToPoint) { zval *zobj = getThis(); zval *zpoint; php_shape_object *php_shape; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_point = (php_point_object *) zend_object_store_get_object(zpoint TSRMLS_CC); RETURN_DOUBLE(msDistancePointToShape(php_point->point, php_shape->shape)); } /* }}} */ /* {{{ proto int shape.distanceToShape(shapeObj shape) Returns the distance from the shape to shape2. */ PHP_METHOD(shapeObj, distanceToShape) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape; php_shape_object *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = (php_shape_object *) zend_object_store_get_object(zobj TSRMLS_CC); php_shape2 = (php_shape_object *) zend_object_store_get_object(zshape TSRMLS_CC); RETURN_DOUBLE(msGEOSDistance(php_shape->shape, php_shape2->shape)); } /* }}} */ zend_function_entry shape_functions[] = { PHP_ME(shapeObj, __construct, shape___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(shapeObj, __get, shape___get_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, __set, shape___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(shapeObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, project, shape_project_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, add, shape_add_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, line, shape_line_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, contains, shape_contains_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, intersects, shape_intersects_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getPointUsingMeasure, shape_getPointUsingMeasure_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getMeasureUsingPoint, shape_getMeasureUsingPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getValue, shape_getValue_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, buffer, shape_buffer_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, convexhull, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, boundary, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, containsShape, shape_containsShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, union, shape_union_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, intersection, shape_intersection_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, difference, shape_difference_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, symdifference, shape_symdifference_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, overlaps, shape_overlaps_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, within, shape_within_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, crosses, shape_crosses_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, touches, shape_touches_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, equals, shape_equals_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, disjoint, shape_disjoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getCentroid, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getArea, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getLength, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getLabelPoint, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, toWkt, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, setBounds, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, simplify, shape_simplify_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, topologyPreservingSimplify, shape_topologyPreservingSimplify_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, draw, shape_draw_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, distanceToPoint, shape_distanceToPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, distanceToShape, shape_distanceToShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_shape(shapeObj *shape, parent_object parent, php_layer_object *php_layer, zval *return_value TSRMLS_DC) { php_shape_object *php_shape; int i; object_init_ex(return_value, mapscript_ce_shape); php_shape = (php_shape_object *)zend_object_store_get_object(return_value TSRMLS_CC); php_shape->shape = shape; MAKE_STD_ZVAL(php_shape->values); array_init(php_shape->values); if (php_layer) { if ((php_shape->shape->numvalues == php_layer->layer->numitems) || (php_shape->shape->numvalues == 0 && php_layer->layer->numitems == -1)) { for(i=0; ishape->numvalues; i++) { add_assoc_string(php_shape->values, php_layer->layer->items[i], php_shape->shape->values[i], 1); } } else { mapscript_throw_exception("Assertion failed, Could not set shape values: %d, %d" TSRMLS_CC, php_shape->shape->numvalues, php_layer->layer->numitems); return; } } if (parent.val) php_shape->is_ref = 1; php_shape->parent = parent; MAPSCRIPT_ADDREF(parent.val); } static void mapscript_shape_object_destroy(void *object TSRMLS_DC) { php_shape_object *php_shape = (php_shape_object *)object; MAPSCRIPT_FREE_OBJECT(php_shape); MAPSCRIPT_FREE_PARENT(php_shape->parent); MAPSCRIPT_DELREF(php_shape->bounds); MAPSCRIPT_DELREF(php_shape->values); if (php_shape->shape && !php_shape->is_ref) { shapeObj_destroy(php_shape->shape); } efree(object); } static zend_object_value mapscript_shape_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_shape_object *php_shape; MAPSCRIPT_ALLOC_OBJECT(php_shape, php_shape_object); retval = mapscript_object_new(&php_shape->std, ce, &mapscript_shape_object_destroy TSRMLS_CC); php_shape->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_shape->parent); php_shape->bounds = NULL; php_shape->values = NULL; return retval; } PHP_MINIT_FUNCTION(shape) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("shapeObj", shape_functions, mapscript_ce_shape, mapscript_shape_object_new); mapscript_ce_shape->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } mapserver-6.4.1/mapscript/php/nmake.opt0000644002461700001440000000174612261257215017734 0ustar tbonfortusers# # nmake.opt - MSVC++ configuration for the PHP/MapScript # # This VC++ makefile will build the PHP module PHP_MAPSCRIPT.DLL # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # ######################################################################## # Secition I: PHP Mapscript Options ######################################################################## #Use PHP4 flag when building with PHP4. Default is assumed to be PHP5 #PHP4=1 #name of the file that will be used when doing make install #it will be copied in the directory specified by the PHP_INSTALL_DLL_NAME = php_mapscript.dll !IFDEF PHP4 # Install directory for PHP4 PHP_INSTALL_DIR=c:\php\php4\extensions # PHP TS library for PHP4 PHP_TS_LIB_NAME=php4ts.lib !ELSE # Install directory for PHP5 #PHP_INSTALL_DIR=c:\php\php5\ext # PHP TS library for PHP5 PHP_TS_LIB_NAME=php5ts.lib !ENDIF mapserver-6.4.1/mapscript/mserror.i0000644002461700001440000000411712261257215017164 0ustar tbonfortusers/* =========================================================================== $Id$ Project: MapServer Purpose: MapScript exceptions Author: Umberto Unicoletti, unicoletti@prometeo.it Jerry Pisk, jerry.pisk@gmail.com Sean Gillies, sgillies@frii.com Tamas Szekeres, szekerest@gmail.com Note: Python exceptions are in mapscript/python C# exceptions are redefinied in mapscript/csharp This implementation truncates the error message length to MAX_ERROR_LEN since SWIG_exception does not allow to free memory allocated on the heap easily (szekerest) ============================================================================ */ #define MAX_ERROR_LEN 8192 %include exception.i %exception { errorObj *ms_error; $action ms_error = msGetErrorObj(); if (ms_error!=NULL && ms_error->code != MS_NOERR) { char ms_message[MAX_ERROR_LEN]; char* msg = msGetErrorString(";"); int ms_errorcode = ms_error->code; if (msg) { snprintf(ms_message, MAX_ERROR_LEN, msg); free(msg); } else sprintf(ms_message, "Unknown message"); msResetErrorList(); switch(ms_errorcode) { case MS_NOTFOUND: break; case -1: break; case MS_IOERR: SWIG_exception(SWIG_IOError ,ms_message); break; case MS_MEMERR: SWIG_exception(SWIG_MemoryError,ms_message); break; case MS_TYPEERR: SWIG_exception(SWIG_TypeError,ms_message); break; case MS_EOFERR: SWIG_exception(SWIG_SyntaxError,ms_message); break; case MS_CHILDERR: SWIG_exception(SWIG_SystemError,ms_message); break; case MS_NULLPARENTERR: SWIG_exception(SWIG_SystemError,ms_message); break; default: SWIG_exception(SWIG_UnknownError,ms_message); break; } } } mapserver-6.4.1/mapscript/README.txt0000644002461700001440000000303412261257215017014 0ustar tbonfortusers.. $Id$ MapServer Mapscript Modules =========================== Much of MapServer's functionality is accessible from Java, Perl, PHP, Python, Ruby, and Tcl. Mapscript is not a language like Javascript or Postscript. It is a loadable module that brings MapServer capabilities to your favorite high level programming language. PHP and SWIG Branches of Mapscript ---------------------------------- The mapscript family tree looks like this: :: MapServer /\ / \ / \ PHPMapScript \ SWIGMapScript PHP4 +----+-----+----+----+----+ | | | | | | Perl Python Ruby Java Tcl ... The Perl, Python, Ruby flavors are like brothers and sisters and the PHP3 module is like a very close cousin to them. The Java, Perl, Python, Ruby, and Tcl modules are generated using SWIG (http://www.swig.org) while the PHP3/PHP4 module is developed using the PHP C API without using SWIG. PHP3/PHP4 --------- Source code, detailed installation instructions, and module API are located under mapscript/php3. SWIG Mapscript -------------- Installation instructions are located in the individual languages directories such as mapscript/perl, mapscript/python. The shared API is documented in the file mapscript/doc/mapscript.txt. The main mapscript SWIG interface file is mapscript/mapscript.i. This file includes specific class interface files from mapscript/swiginc and language specific code from the language directories. mapserver-6.4.1/mapscript/tcl/0000755002461700001440000000000012261257215016100 5ustar tbonfortusersmapserver-6.4.1/mapscript/tcl/mapscript_wrap.html0000644002461700001440000013523612261257215022033 0ustar tbonfortusers mapscript_wrap.c

mapscript_wrap.c


Contents

mapscript::MS_VERSION = 3.4 (pre-release)

[ Constant : char * ]
logical control variables

mapscript::MS_TRUE = 1

[ Constant : int ]

mapscript::MS_FALSE = 0

[ Constant : int ]

mapscript::MS_ON = 1

[ Constant : int ]

mapscript::MS_OFF = 0

[ Constant : int ]

mapscript::MS_DEFAULT = 2

[ Constant : int ]

mapscript::MS_QUERY = 3

[ Constant : int ]

mapscript::MS_EMBED = 4

[ Constant : int ]

mapscript::MS_YES = 1

[ Constant : int ]

mapscript::MS_NO = 0

[ Constant : int ]
modes for searching (spatial/database)

mapscript::MS_SINGLE = 0

[ Constant : int ]

mapscript::MS_MULTIPLE = 1

[ Constant : int ]
General defines, not wrapable

mapscript::MS_FILE_MAP = MS_FILE_MAP

[ Constant : int ]

mapscript::MS_FILE_SYMBOL = MS_FILE_SYMBOL

[ Constant : int ]

mapscript::MS_INCHES = MS_INCHES

[ Constant : int ]

mapscript::MS_FEET = MS_FEET

[ Constant : int ]

mapscript::MS_MILES = MS_MILES

[ Constant : int ]

mapscript::MS_METERS = MS_METERS

[ Constant : int ]

mapscript::MS_NAUTICALMILES = MS_NAUTICALMILES

[ Constant : int ]

mapscript::MS_KILOMETERS = MS_KILOMETERS

[ Constant : int ]

mapscript::MS_DD = MS_DD

[ Constant : int ]

mapscript::MS_PIXELS = MS_PIXELS

[ Constant : int ]

mapscript::MS_POINT = MS_POINT

[ Constant : int ]

mapscript::MS_LINE = MS_LINE

[ Constant : int ]

mapscript::MS_POLYGON = MS_POLYGON

[ Constant : int ]

mapscript::MS_POLYLINE = MS_POLYLINE

[ Constant : int ]

mapscript::MS_RASTER = MS_RASTER

[ Constant : int ]

mapscript::MS_ANNOTATION = MS_ANNOTATION

[ Constant : int ]

mapscript::MS_NULL = MS_NULL

[ Constant : int ]

mapscript::MS_TRUETYPE = MS_TRUETYPE

[ Constant : int ]

mapscript::MS_BITMAP = MS_BITMAP

[ Constant : int ]

mapscript::MS_UL = MS_UL

[ Constant : int ]

mapscript::MS_LR = MS_LR

[ Constant : int ]

mapscript::MS_UR = MS_UR

[ Constant : int ]

mapscript::MS_LL = MS_LL

[ Constant : int ]

mapscript::MS_CR = MS_CR

[ Constant : int ]

mapscript::MS_CL = MS_CL

[ Constant : int ]

mapscript::MS_UC = MS_UC

[ Constant : int ]

mapscript::MS_LC = MS_LC

[ Constant : int ]

mapscript::MS_CC = MS_CC

[ Constant : int ]

mapscript::MS_AUTO = MS_AUTO

[ Constant : int ]

mapscript::MS_XY = MS_XY

[ Constant : int ]
arrangement matters for auto placement

mapscript::MS_TINY = MS_TINY

[ Constant : int ]

mapscript::MS_SMALL = MS_SMALL

[ Constant : int ]

mapscript::MS_MEDIUM = MS_MEDIUM

[ Constant : int ]

mapscript::MS_LARGE = MS_LARGE

[ Constant : int ]

mapscript::MS_GIANT = MS_GIANT

[ Constant : int ]

mapscript::MS_NORMAL = MS_NORMAL

[ Constant : int ]

mapscript::MS_HILITE = MS_HILITE

[ Constant : int ]

mapscript::MS_SELECTED = MS_SELECTED

[ Constant : int ]

mapscript::MS_INVERTED = MS_INVERTED

[ Constant : int ]

mapscript::MS_LOCAL = MS_LOCAL

[ Constant : int ]

mapscript::MS_SDE = MS_SDE

[ Constant : int ]

mapscript::MS_OGR = MS_OGR

[ Constant : int ]

mapscript::MS_GIF = MS_GIF

[ Constant : int ]

mapscript::MS_PNG = MS_PNG

[ Constant : int ]

mapscript::MS_JPEG = MS_JPEG

[ Constant : int ]

mapscript::MS_WBMP = MS_WBMP

[ Constant : int ]

mapscript::MS_FILE_DEFAULT = (MS_FILE_MAP)

[ Constant : int ]

1. class featureListNodeObj

[ created from struct featureListNodeObj ]

-shape

[ Member data: returns shapeObj * ]

-next

[ Member data: returns struct listNode * ]

2. class colorObj

[ created from struct colorObj ]

-red

[ Member data: returns int ]

-green

[ Member data: returns int ]

-blue

[ Member data: returns int ]

3. class queryObj

[ created from struct queryObj ]

-expression

[ Member data: returns expressionObj * ]
the expression to be matched

-template

[ Member data: returns char * ]

queryObj name layer

[ Constructor: returns queryObj * ]

rename obj {}

[ Destructor: returns void ]

setExpression string

[ Member : returns int ]

4. class shapeResultObj

[ created from struct shapeResultObj ]

-layer

[ Member data: returns int ]

-tile

[ Member data: returns int ]

-shape

[ Member data: returns int ]

-query

[ Member data: returns int ]

5. class queryResultObj

[ created from struct queryResultObj ]

-numlayers

[ Member data: returns int ]

-numresults

[ Member data: returns int ]

-numquerylayers

[ Member data: returns int ]

-currentlayer

[ Member data: returns int ]

-currenttile

[ Member data: returns int ]

-currentshape

[ Member data: returns int ]
allows for cursors-like access to results

queryResultObj name filename

[ Constructor: returns queryResultObj * ]

rename obj {}

[ Destructor: returns void ]

free

[ Member : returns void ]

save filename

[ Member : returns int ]

next

[ Member : returns shapeResultObj ]

6. class queryMapObj

[ created from struct queryMapObj ]

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-status

[ Member data: returns int ]

-style

[ Member data: returns int ]
HILITE, SELECTED or NORMAL

-color

[ Member data: returns int ]

7. class labelObj

[ created from struct labelObj ]

-font

[ Member data: returns char * ]

-type

[ Member data: returns enum MS_FONT_TYPE ]

-color

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]

-shadowcolor

[ Member data: returns int ]

-shadowsizex

[ Member data: returns int ]

-shadowsizey

[ Member data: returns int ]

-backgroundcolor

[ Member data: returns int ]

-backgroundshadowcolor

[ Member data: returns int ]

-backgroundshadowsizex

[ Member data: returns int ]

-backgroundshadowsizey

[ Member data: returns int ]

-size

[ Member data: returns int ]

-sizescaled

[ Member data: returns int ]

-minsize

[ Member data: returns int ]

-maxsize

[ Member data: returns int ]

-position

[ Member data: returns int ]

-offsetx

[ Member data: returns int ]

-offsety

[ Member data: returns int ]

-angle

[ Member data: returns double ]

-autoangle

[ Member data: returns int ]
true or false

-buffer

[ Member data: returns int ]
space to reserve around a label

-antialias

[ Member data: returns int ]

-wrap

[ Member data: returns char ]

-minfeaturesize

[ Member data: returns int ]
minimum feature size (in pixels) to label

-autominfeaturesize

[ Member data: returns int ]
true or false

-mindistance

[ Member data: returns int ]

-partials

[ Member data: returns int ]
can labels run of an image

-force

[ Member data: returns int ]
labels *must* be drawn

8. class webObj

[ created from struct webObj ]

-log

[ Member data: returns char * ]

-imagepath

[ Member data: returns char * ]

-imageurl

[ Member data: returns char * ]

-template

[ Member data: returns char * ]

-header

[ Member data: returns char * ]

-footer

[ Member data: returns char * ]

-empty

[ Member data: returns char * ]

-error

[ Member data: returns char * ]
error handling

-extent

[ Member data: returns rectObj * ]
clipping extent

-minscale

[ Member data: returns double ]

-maxscale

[ Member data: returns double ]

-mintemplate

[ Member data: returns char * ]

-maxtemplate

[ Member data: returns char * ]

9. class classObj

[ created from struct classObj ]

-color

[ Member data: returns int ]

-backgroundcolor

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]

-overlaycolor

[ Member data: returns int ]

-overlaybackgroundcolor

[ Member data: returns int ]

-overlayoutlinecolor

[ Member data: returns int ]

-symbol

[ Member data: returns int ]

-symbolname

[ Member data: returns char * ]

-overlaysymbol

[ Member data: returns int ]

-overlaysymbolname

[ Member data: returns char * ]

-size

[ Member data: returns int ]

-sizescaled

[ Member data: returns int ]

-minsize

[ Member data: returns int ]

-maxsize

[ Member data: returns int ]

-overlaysize

[ Member data: returns int ]

-overlaysizescaled

[ Member data: returns int ]

-overlayminsize

[ Member data: returns int ]

-overlaymaxsize

[ Member data: returns int ]

-label

[ Member data: returns labelObj * ]

-name

[ Member data: returns char * ]
used for legend labeling

classObj name layer

[ Constructor: returns classObj * ]

rename obj {}

[ Destructor: returns void ]

setExpression string

[ Member : returns int ]

setText layer string

[ Member : returns int ]

10. class labelCacheMemberObj

[ created from struct labelCacheMemberObj ]

-size

[ Member data: returns int ]
parameters that can vary for each label/feature

-angle

[ Member data: returns double ]

-string

[ Member data: returns char * ]

-featuresize

[ Member data: returns double ]

-layeridx

[ Member data: returns int ]
indexes

-classidx

[ Member data: returns int ]

-tileidx

[ Member data: returns int ]

-shapeidx

[ Member data: returns int ]

-point

[ Member data: returns pointObj * ]
label point

-poly

[ Member data: returns shapeObj * ]
label bounding box

-status

[ Member data: returns int ]
has this label been drawn or not

11. class markerCacheMemberObj

[ created from struct markerCacheMemberObj ]

-id

[ Member data: returns int ]
corresponding label

-poly

[ Member data: returns shapeObj * ]
marker bounding box (POINT layers only)

12. class labelCacheObj

[ created from struct labelCacheObj ]

-labels

[ Member data: returns labelCacheMemberObj * ]

-numlabels

[ Member data: returns int ]

-cachesize

[ Member data: returns int ]

-markers

[ Member data: returns markerCacheMemberObj * ]

-nummarkers

[ Member data: returns int ]

-markercachesize

[ Member data: returns int ]

freeCache

[ Member : returns void ]

13. class symbolSetObj

[ created from struct symbolSetObj ]

-filename

[ Member data: returns char * ]

-fontset

[ Member data: returns fontSetObj * ]
a pointer to the main mapObj version

-numsymbols

[ Member data: returns int ]

-symbol

[ Member data: returns symbolObj * ]

-imagecache

[ Member data: returns struct imageCacheObj * ]

-imagecachesize

[ Member data: returns int ]

14. class referenceMapObj

[ created from struct referenceMapObj ]

-extent

[ Member data: returns rectObj * ]

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-color

[ Member data: returns colorObj * ]

-outlinecolor

[ Member data: returns colorObj * ]

-image

[ Member data: returns char * ]

-status

[ Member data: returns int ]

15. class scalebarObj

[ created from struct scalebarObj ]

-imagecolor

[ Member data: returns colorObj * ]

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-style

[ Member data: returns int ]

-intervals

[ Member data: returns int ]

-label

[ Member data: returns labelObj * ]

-color

[ Member data: returns int ]

-backgroundcolor

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]

-units

[ Member data: returns int ]

-status

[ Member data: returns int ]
ON, OFF or EMBED

-position

[ Member data: returns int ]
for embeded scalebars

-transparent

[ Member data: returns int ]

-interlace

[ Member data: returns int ]

-postlabelcache

[ Member data: returns int ]

16. class legendObj

[ created from struct legendObj ]

-imagecolor

[ Member data: returns colorObj * ]

-label

[ Member data: returns labelObj * ]

-keysizex

[ Member data: returns int ]

-keysizey

[ Member data: returns int ]

-keyspacingx

[ Member data: returns int ]

-keyspacingy

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]
Color of outline of box, -1 for no outline

-status

[ Member data: returns int ]
ON, OFF or EMBED

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-position

[ Member data: returns int ]
for embeded legends

-transparent

[ Member data: returns int ]

-interlace

[ Member data: returns int ]

-postlabelcache

[ Member data: returns int ]

17. class layerObj

[ created from struct layerObj ]

-index

[ Member data: returns int ]

-classitem

[ Member data: returns char * ]
.DBF item to be used for symbol lookup

-class

[ Member data: returns classObj * ]
always at least 1 class

-numclasses

[ Member data: returns int ]

-name

[ Member data: returns char * ]
layer name, must be unique

-group

[ Member data: returns char * ]

-description

[ Member data: returns char * ]
layer title or description

-legend

[ Member data: returns char * ]
legend graphic

-status

[ Member data: returns int ]
layer status, either ON or OFF

-data

[ Member data: returns char * ]
layer data filename, including path

-type

[ Member data: returns enum MS_FEATURE_TYPE ]

-tolerance

[ Member data: returns double ]
search buffer for point and line queries (in toleranceunits)

-toleranceunits

[ Member data: returns int ]

-symbolscale

[ Member data: returns double ]
scale at which symbols are default size

-maxscale

[ Member data: returns double ]
layer is active only BELOW this scale value (<=)

-minscale

[ Member data: returns double ]
layer is active only ABOVE this scale value (>)

-labelminscale

[ Member data: returns double ]
annotation is active only BELOW this scale value (<=)

-labelmaxscale

[ Member data: returns double ]
annotation is active only ABOVE this scale value (>)

-maxfeatures

[ Member data: returns int ]

-offsite

[ Member data: returns int ]
offsite value for raster images

-transform

[ Member data: returns int ]
does this layer have to be transformed to file coordinates

-labelcache

[ Member data: returns int ]
on or off

-postlabelcache

[ Member data: returns int ]

-labelitem

[ Member data: returns char * ]
.DBF item to be used for text

-labelsizeitem

[ Member data: returns char * ]

-labelangleitem

[ Member data: returns char * ]

-tileitem

[ Member data: returns char * ]

-tileindex

[ Member data: returns char * ]
layer index file for tiling support

-projection

[ Member data: returns projectionObj * ]
projection information for the layer

-features

[ Member data: returns featureListNodeObjPtr ]
linked list so we don't need a counter

-connection

[ Member data: returns char * ]

-connectiontype

[ Member data: returns enum MS_CONNECTION_TYPE ]

layerObj name map

[ Constructor: returns layerObj * ]

rename obj {}

[ Destructor: returns void ]

getClass i

[ Member : returns classObj * ]

draw map img

[ Member : returns int ]

queryUsingPoint map point mode buffer

[ Member : returns queryResultObj * ]

queryUsingRect map rect

[ Member : returns queryResultObj * ]

queryUsingFeatures map results

[ Member : returns int ]

queryUsingShape map shape

[ Member : returns queryResultObj * ]

setProjection string

[ Member : returns int ]

addFeature shape

[ Member : returns int ]

classify string

[ Member : returns int ]

18. class mapObj

[ created from struct mapObj ]
structure for a map

-name

[ Member data: returns char * ]
small identifier for naming etc.

-status

[ Member data: returns int ]
is map creation on or off

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-layers

[ Member data: returns layerObj * ]

-numlayers

[ Member data: returns int ]
number of layers in mapfile

-labelcache

[ Member data: returns labelCacheObj * ]
we need this here so multiple feature processors can access it

-transparent

[ Member data: returns int ]

-interlace

[ Member data: returns int ]

-extent

[ Member data: returns rectObj * ]
map extent array

-cellsize

[ Member data: returns double ]
in map units

-units

[ Member data: returns enum MS_UNITS ]
units of the projection

-scale

[ Member data: returns double ]
scale of the output image

-shapepath

[ Member data: returns char * ]
where are the shape files located

-tile

[ Member data: returns char * ]
an optional tile name to use as well

-palette

[ Member data: returns paletteObj * ]
holds a map palette

-imagecolor

[ Member data: returns colorObj * ]
holds the initial image color value

-imagetype

[ Member data: returns int ]

-imagequality

[ Member data: returns int ]

-projection

[ Member data: returns projectionObj * ]
projection information for output map

-reference

[ Member data: returns referenceMapObj * ]

-scalebar

[ Member data: returns scalebarObj * ]

-legend

[ Member data: returns legendObj * ]

-web

[ Member data: returns webObj * ]

mapObj name filename

[ Constructor: returns mapObj * ]

rename obj {}

[ Destructor: returns void ]

getLayer i

[ Member : returns layerObj * ]

getLayerByName name

[ Member : returns layerObj * ]

addColor r g b

[ Member : returns int ]

getSymbolByName type name

[ Member : returns int ]

prepareQuery

[ Member : returns void ]

prepareImage

[ Member : returns gdImagePtr ]

draw

[ Member : returns gdImagePtr ]

drawQueryMap results

[ Member : returns gdImagePtr ]

drawLegend

[ Member : returns gdImagePtr ]

drawScalebar

[ Member : returns gdImagePtr ]

drawReferenceMap

[ Member : returns gdImagePtr ]

embedScalebar img

[ Member : returns int ]

embedLegend img

[ Member : returns int ]

drawLabelCache img

[ Member : returns int ]

nextLabel

[ Member : returns labelCacheMemberObj * ]

queryUsingPoint point mode buffer

[ Member : returns queryResultObj * ]

queryUsingRect rect

[ Member : returns queryResultObj * ]

queryUsingFeatures results

[ Member : returns int ]

queryUsingShape map shape

[ Member : returns queryResultObj * ]

setProjection string

[ Member : returns int ]

save filename

[ Member : returns int ]

mapscript::msSaveImage img filename transparent interlace

[ returns int ]

mapscript::msFreeImage img

[ returns void ]

mapscript::MS_NOERR = 0

[ Constant : int ]

mapscript::MS_IOERR = 1

[ Constant : int ]

mapscript::MS_MEMERR = 2

[ Constant : int ]

mapscript::MS_TYPEERR = 3

[ Constant : int ]

mapscript::MS_SYMERR = 4

[ Constant : int ]

mapscript::MS_REGEXERR = 5

[ Constant : int ]

mapscript::MS_TTFERR = 6

[ Constant : int ]

mapscript::MS_DBFERR = 7

[ Constant : int ]

mapscript::MS_GDERR = 8

[ Constant : int ]

mapscript::MS_IDENTERR = 9

[ Constant : int ]

mapscript::MS_EOFERR = 10

[ Constant : int ]

mapscript::MS_PROJERR = 11

[ Constant : int ]

mapscript::MS_MISCERR = 12

[ Constant : int ]

mapscript::MS_CGIERR = 13

[ Constant : int ]

mapscript::MS_WEBERR = 14

[ Constant : int ]

mapscript::MS_IMGERR = 15

[ Constant : int ]

mapscript::MS_HASHERR = 16

[ Constant : int ]

mapscript::MS_JOINERR = 17

[ Constant : int ]
empty search results

mapscript::MS_NOTFOUND = 18

[ Constant : int ]

mapscript::MS_SHPERR = 19

[ Constant : int ]

mapscript::MS_PARSEERR = 20

[ Constant : int ]

mapscript::MS_SDEERR = 21

[ Constant : int ]

mapscript::MS_OGRERR = 22

[ Constant : int ]

mapscript::MS_NUMERRORCODES = 23

[ Constant : int ]

mapscript::MESSAGELENGTH = 2048

[ Constant : int ]

mapscript::ROUTINELENGTH = 64

[ Constant : int ]

19. class errorObj

[ created from struct errorObj ]

-code

[ Member data: returns int ]

-routine

[ Member data: returns char * ]

-message

[ Member data: returns char * ]

mapscript::ms_error_set { errorObj * } mapscript::ms_error_get

[ Global : errorObj ms_error ]

mapscript::msSetError code message routine

[ returns void ]

mapscript::msWriteError stream

[ returns void ]

20. class rectObj

[ created from struct rectObj ]

-minx

[ Member data: returns double ]

-miny

[ Member data: returns double ]

-maxx

[ Member data: returns double ]

-maxy

[ Member data: returns double ]

rectObj name

[ Constructor: returns rectObj * ]

rename obj {}

[ Destructor: returns void ]

fit width height

[ Member : returns double ]

draw map layer img class_string label_string

[ Member : returns int ]

21. class pointObj

[ created from struct pointObj ]

-x

[ Member data: returns double ]

-y

[ Member data: returns double ]

pointObj name

[ Constructor: returns pointObj * ]

rename obj {}

[ Destructor: returns void ]

draw map layer img class_string label_string

[ Member : returns int ]

distanceToPoint point

[ Member : returns double ]

distanceToLine a b

[ Member : returns double ]

distanceToShape shape

[ Member : returns double ]

22. class lineObj

[ created from struct lineObj ]

-numpoints

[ Member data: returns int ]

-point

[ Member data: returns pointObj * ]

lineObj name

[ Constructor: returns lineObj * ]

rename obj {}

[ Destructor: returns void ]

get i

[ Member : returns pointObj * ]

add p

[ Member : returns int ]

23. class shapeObj

[ created from struct shapeObj ]

-numlines

[ Member data: returns int ]

-line

[ Member data: returns lineObj * ]

-bounds

[ Member data: returns rectObj * ]

-type

[ Member data: returns int ]

-classindex

[ Member data: returns int ]

-queryindex

[ Member data: returns int ]

-text

[ Member data: returns char * ]

shapeObj name type

[ Constructor: returns shapeObj * ]

rename obj {}

[ Destructor: returns void ]

get i

[ Member : returns lineObj * ]

add line

[ Member : returns int ]

draw map layer img class_string label_string

[ Member : returns int ]

setBounds

[ Member : returns void ]

copy dest

[ Member : returns int ]

contains point

[ Member : returns int ]

intersects shape

[ Member : returns int ]

mapscript::MS_SHP_POINT = 1

[ Constant : int ]

mapscript::MS_SHP_ARC = 3

[ Constant : int ]

mapscript::MS_SHP_POLYGON = 5

[ Constant : int ]

mapscript::MS_SHP_MULTIPOINT = 8

[ Constant : int ]

24. class DBFInfo

[ created from struct DBFInfo ]

-fp

[ Member data: returns FILE * ]

-nRecords

[ Member data: returns int ]

-nRecordLength

[ Member data: returns int ]

-nHeaderLength

[ Member data: returns int ]

-nFields

[ Member data: returns int ]

-panFieldOffset

[ Member data: returns int * ]

-panFieldSize

[ Member data: returns int * ]

-panFieldDecimals

[ Member data: returns int * ]

-pachFieldType

[ Member data: returns char * ]

-pszHeader

[ Member data: returns char * ]

-nCurrentRecord

[ Member data: returns int ]

-bCurrentRecordModified

[ Member data: returns int ]

-pszCurrentRecord

[ Member data: returns char * ]

-bNoHeader

[ Member data: returns int ]

-bUpdated

[ Member data: returns int ]

getFieldName iField

[ Member : returns char * ]

getFieldWidth iField

[ Member : returns int ]

getFieldDecimals iField

[ Member : returns int ]

getFieldType iField

[ Member : returns DBFFieldType ]

mapscript::FTString = FTString

[ Constant : int ]

mapscript::FTInteger = FTInteger

[ Constant : int ]

mapscript::FTDouble = FTDouble

[ Constant : int ]

mapscript::FTInvalid = FTInvalid

[ Constant : int ]

25. class shapefileObj

[ created from struct shapefileObj ]

-source

[ Member data: returns char * ]
full path to the shapefile data

-hSHP

[ Member data: returns SHPHandle * ]
.SHP/.SHX file pointer

-type

[ Member data: returns int ]
shape type

-numshapes

[ Member data: returns int ]
number of shapes

-bounds

[ Member data: returns rectObj * ]
shape extent

-hDBF

[ Member data: returns DBFHandle ]
.DBF file pointer

shapefileObj name filename type

[ Constructor: returns shapefileObj * ]

rename obj {}

[ Destructor: returns void ]

get i shape

[ Member : returns int ]

getTransformed map i shape

[ Member : returns int ]

getExtent i rect

[ Member : returns void ]

add shape

[ Member : returns int ]

mapscript::DBFOpen pszDBFFile pszAccess

[ returns DBFHandle ]

mapscript::DBFCreate pszDBFFile

[ returns DBFHandle ]

mapscript::DBFGetFieldCount psDBF

[ returns int ]

mapscript::DBFGetRecordCount psDBF

[ returns int ]

mapscript::DBFAddField hDBF pszFieldName eType nWidth nDecimals

[ returns int ]

mapscript::DBFGetFieldInfo psDBF iField pszFieldName pnWidth pnDecimals

[ returns DBFFieldType ]

mapscript::DBFReadIntegerAttribute hDBF iShape iField

[ returns int ]

mapscript::DBFReadDoubleAttribute hDBF iShape iField

[ returns double ]

mapscript::DBFReadStringAttribute hDBF iShape iField

[ returns char * ]

mapscript::DBFWriteIntegerAttribute hDBF iShape iField nFieldValue

[ returns int ]

mapscript::DBFWriteDoubleAttribute hDBF iShape iField dFieldValue

[ returns int ]

mapscript::DBFWriteStringAttribute hDBF iShape iField pszFieldValue

[ returns int ]

mapscript::DBFClose hDBF

[ returns void ]
mapserver-6.4.1/mapscript/tcl/README0000644002461700001440000001467012261257215016770 0ustar tbonfortusersMapscript Tcl Interface WHAT It's a Tcl interface for Mapserver. You can write Tcl scripts to generate maps, read/write shapefiles, etc. VERSION Mapscript 1.1 is built for Mapserver 3.5 + INSTALL A simple 'configure' script and Makefile is included. The configure is hand built, rather than being derived from GNU autoconf. Normally you can just type: configure make make install to build and install the interface. Three configure options are supported: configure --with-tcl=[dir] --with-swig=[dir] --with-linker-cc --with-tcl=[dir] specify the directory where you installed Tcl, the default is /usr/local. 'configure' looks for $dir/lib/tclConfig.sh for Tcl configure info. --with-swig=[dir] specify the directory where you installed Swig, the default is /usr/local. 'configure' looks for $dir/include/swig.h and $dir/lib/libswig.a. --with-linker-cc use the compiler command as the front-end for linking, if not already so. See 'COMPILE PROBLEMS' below. ** Mapserver source code is presumed to be two directory levels above this directory, and uses various .h files from Mapscript, along with ../mapscript.i. ** Mapscript/Tcl normally builds as a Tcl stubbed dynamic library. The makefile includes a target 'nostublib' if you want to build with a Tcl version dependent library (not recommended). ** Tested with Tcl/Tk version 8.3.2, and Swig version 1.1-883 REQUIREMENTS You must have Tcl (tcl.sourceforge.net) installed and optionally, Swig installed also (www.swig.org). The current mapscript.i Swig interface definition file is designed for Swig 1.1 versions. Newer versions of Swig may require mapscript.i changes. You should have Tcl 8.3 or greater installed, as the Makefile normally builds with the Tcl dynamic stubs library. Tcl 8.3.2 (or current release) is recommended. Additionally, you may want the Img Tcl extension to support upcoming Mapserver images (PNG, JPG, etc.) See the NOTES section below for more information. COMPILE PROBLEMS Some users have reported link or runtime errors, most notably when mapscript_wrap.c is compiled with gcc, but using ld to link the shared library. If you experience this problem, try re-running the configure script, adding the '--with-linker-cc' option to the configure command line. For users without Swig installed, a pre-built mapscript_wrap.c is available. 'make useprebuilt' will unpack the pre-built mapscript_wrap.c. If you get runtime errors reporting missing symbols, check the Mapscript/Tcl shared library for shared libraries it may be dependent upon. In Linux, Solaris (and possibly other unix systems) try this: ldd libMapscript*.* Note which libraries are unresolved. Find the directories which contain the libraries that are unresolved, and add those directories to your LD_LIBRARY_PATH environment variable, or whichever environment variable is appropriate for your system: $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/other/required/dirs Add this to your .profile or .cshrc so you won't have to set this each time you login. On some systems (Linux, et.al), a /etc/ld.so.conf file and 'ldconfig' program will set system-wide default library directory paths. WINDOWS See the ./win directory. You should first install Tcl 8.3.2. Then, run the 'setup.tcl' file to install Mapscript/Tcl. You can double-click on the 'setup.tcl' file from Windows explorer, or 'start setup.tcl' from a DOS box. To rebuild the DLL, see the file 'README.ms-mingw' and 'ms-mingw.tar.gz'. The DLL provided was built with the Mingw compiler, as a cross compiler hosted on Linux. You should be able to rebuild the DLL on any Unix box, or with a little work, using Mingw or Cygwin compiler & tools on Windows. No Microsoft or Borland makefiles are provided. Feel free to donate one(s). You can use the popular 'WinZip' program to unpack tar.gz files on Windows (http://www.winzip.com), or use gunzip and tar from the Cygwin tools (http://sources.redhat.com/cygwin/). DOCS Swig generated documentation, plus and additional doc page for Tcl coded helper functions are available as HTML. EXAMPLES See the ./examples directory. shpinfo.tcl - print rudimentary info about a shape file. MAPSERVER WORKBENCH MapServer Workbench is a set of tools written in Tcl/Tk with the Mapscript/Tcl extension, and is available separately. The Workbench currently consists of: msappwiz.tcl -wizard to create mapserver application mapfiles msedit.tcl -tree-structured mapfile editor msexplorer.tcl -view, zoom, and query mapfiles msshapex.tcl -view shapefile information and .dbf attributes MapServer Workbench tools run under Unix or Windows. For more information and to download MapServer Workbench: http://msworkbench.sourceforge.net http://sourceforge.net/projects/msworkbench/ http://www.nyx.net/~tpoindex/gis NOTES e.g., the "SWIG_STUB_HACK" Building Tcl extensions that are not dependent on a particular version of Tcl is the preferred method. Prior to Tcl 8.1, an extension had to be linked against a version dependent Tcl libarary. Extensions had to be recompiled and relinked when newer versions of Tcl were installed. Beginning with Tcl 8.1, the 'stub' library was introduced to facilitate version independent extensions. The stub library is a table of pointers to Tcl functions, that are initialized at run time, so extensions compiled for one version of Tcl don't have to be recompiled. A call to Tcl_InitStubs() is required before using any Tcl function in an extension, and we link to libtclstub8.3.a, instead of the entire Tcl library. Swig 1.1-883 doesn't initialize the stub table by calling Tcl_InitStubs(), so we must do it ourselves. Normally, we use the Swig directive '%init' to include the call to Tcl_InitStubs. However, we also prefer that the new Mapscript commands reside in their own namespace, by using the Swig option '-namespace'. Unfortunately, Swig generates a call to Tcl_Eval() before the %init code is included in the wrapped .c file. We work around this problem for Mapscript by some crusty use of the C preprocessor. Just before the Tcl_Eval call in the wrapped .c file, Swig also includes an bit of code that allows use the [incr Tcl] object system. The makefile passes command line C preprocessor defines to subvert this bit of code for our use. Thus, we are able to call the Tcl_InitStub function before Tcl_Eval is called. See the Makefile macro "SWIG_STUB_HACK". WHO Tom Poindexter tpoindex@nyx.net http://www.nyx.net/~tpoindex/ mapserver-6.4.1/mapscript/tcl/pkgIndex.tcl0000644002461700001440000000054012261257215020354 0ustar tbonfortusers# pkgIndex.tcl for mapscript # # load shared library, and source supplementaly ref procs package ifneeded Mapscript 1.1 " load [list [file join $dir libMapscript11[info sharedlibextension]]] # source the object reference helpers and convenience procs source [list [file join $dir mapscriptsupp.tcl]] package provide Mapscript 1.1 " mapserver-6.4.1/mapscript/tcl/win/0000755002461700001440000000000012261257215016675 5ustar tbonfortusersmapserver-6.4.1/mapscript/tcl/win/README.ms-mingw0000644002461700001440000001050012261257215021306 0ustar tbonfortusersMapserver and Mapscript/Tcl for Windows These are the steps I have made to compile Mapserver and Mapscript/Tcl for Windows. My build environment is the Mingw (Minimalist GNU for Windows) compiler and toolchain, hosted on Linux/Unix. You probably want to use the pre-compiled DLL, if at all possible. Things get ugly after this...... First, make a new directory to hold everthing we will need. mkdir ms_win cd ms_win Unpack the ms-mingw.tar.gz in that directory: gunzip -c ../ms-mingw.tar.gz | tar xf - Next, you'll need the Mingw compiler and toolchain, compiled as a cross compiler, hosted on your Linux or Unix platform. Mo DeJong has written a shell script to download, compile, and install *all* of the compiler, toolchain, and Mingw libraries. The script is in ms-mingw/mingw-xcc.sh I have set the script to install the tools into /opt/mingw. If you want to change this, you'll need to also change the 'build' shell script. The mingw-xcc.sh script uses the 'wget' program to fetch files via ftp (ftp://ftp.gnu.org/gnu/wget/). cd ms-mingw sh mingw-xcc.sh cd .. Next, get *fresh* sources of all of the required MapServer packages, and unpack in the ms_win directory. Your 'ms_win' directory should look like this after unpacking all of the sources: README.ms-mingw install ms-mingw/ tcl8.3.2/ build jpeg-6b/ proj-4.4.2/ tiff-v3.5.5/ freetype-1.3.1/ mapserver/ regex-0.12/ zlib-1.1.3/ The 'ms-mingw' directory contains directories for each of the components we will be building. Each directory consists of a Makefile for Mingw as a cross compiler, and a 'build' script to copy the Makefile into the source directories (as above), and make the libraries. Software locations: mingw: http://www.mingw.org The mingw-xcc.sh script will grab things for you. There's a lot of info on the Mingw compiler and its use as a cross compiler at the site. proj: http://www.remotesensing.org/proj/ Get version 4.4.2 zlib: http://www.info-zip.org/pub/infozip/zlib/ Get version 1.1.3 jpeg: ftp://ftp.uu.net/graphics/jpeg/ Get version 6b. tiff: http://www.libtiff.org/ Get version 3.5.5 freetype: http://www.freetype.org Get version 1.3.1 NOTE!!! I have found the the freetype-1.3.1.tar.gz file contains source files with dos style end of line characters (cr-lf). This will likely confuse gcc. The easy way to convert into normal unix-style text files is to get the freetype-1.3.1.zip, and use 'unzip -a freetype-1.3.1' to unpack it, converting the files to use lf only. Rename the 'freetype' directory to 'freetype-1.3.1'. regex: ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz mapserver: http://mapserver.gis.umn.edu/dload.html Get the 'nightly' CVS builds for 3.4 (beta), nightly.tar.gz. We will also use the GD 1.2 and GDFT libraries that come with Mapserver. As a side effect, we will also build an executable, mapserv.exe. tcl: http://dev.scriptics.com Get version 8.3.2 We will only be building 'libtclstub83.a', not the entire Tcl library. Also get 'tcl832.exe' and install it on your Windows machine(s) if you don't already have it. For best results, let the installer place Tcl in 'C:\Program Files\Tcl'. Build everything: Use the build script in this directory. (change the values of 'mingwbin' and 'mingwxcc' if needed.) sh build Install: You probably have to be root to write into /c. sh install Or, you can ftp the files over to your windows box and use the 'setup.tcl' installer. Notes: Building for Windows is a royal pain in the ***! The biggest problem is building the various libraries the 'right' way, i.e, as DLL files. This requires a majic Windows macro to export the symbols for the DLL, but another majic macro for code that uses the symbols in a DLL. For software originally not designed to be portable across Unix and Windows, this requires changing alot of source files. Examples of software that is written for portability: zlib, tcl Examples of software that is not: proj, mapserver The alternative: compile the source library code, and bundling it into a standard library file, e.g., libz.a, libjpeg.a, libttf.a, etc. We then take all of the libraries and create our final DLL, libMapscript.dll. The downside is that we're not allowing any reuse of the libaries, but the upside is we don't have to change much exisiting code. I do this method. mapserver-6.4.1/mapscript/tcl/win/ms-mingw.tar0000644002461700001440000024000012261257215021137 0ustar tbonfortusersREADME.ms-mingw0100644000421500037440000001050007225405766013601 0ustar tpoindexsybcipsMapserver and Mapscript/Tcl for Windows These are the steps I have made to compile Mapserver and Mapscript/Tcl for Windows. My build environment is the Mingw (Minimalist GNU for Windows) compiler and toolchain, hosted on Linux/Unix. You probably want to use the pre-compiled DLL, if at all possible. Things get ugly after this...... First, make a new directory to hold everthing we will need. mkdir ms_win cd ms_win Unpack the ms-mingw.tar.gz in that directory: gunzip -c ../ms-mingw.tar.gz | tar xf - Next, you'll need the Mingw compiler and toolchain, compiled as a cross compiler, hosted on your Linux or Unix platform. Mo DeJong has written a shell script to download, compile, and install *all* of the compiler, toolchain, and Mingw libraries. The script is in ms-mingw/mingw-xcc.sh I have set the script to install the tools into /opt/mingw. If you want to change this, you'll need to also change the 'build' shell script. The mingw-xcc.sh script uses the 'wget' program to fetch files via ftp (ftp://ftp.gnu.org/gnu/wget/). cd ms-mingw sh mingw-xcc.sh cd .. Next, get *fresh* sources of all of the required MapServer packages, and unpack in the ms_win directory. Your 'ms_win' directory should look like this after unpacking all of the sources: README.ms-mingw install ms-mingw/ tcl8.3.2/ build jpeg-6b/ proj-4.4.2/ tiff-v3.5.5/ freetype-1.3.1/ mapserver/ regex-0.12/ zlib-1.1.3/ The 'ms-mingw' directory contains directories for each of the components we will be building. Each directory consists of a Makefile for Mingw as a cross compiler, and a 'build' script to copy the Makefile into the source directories (as above), and make the libraries. Software locations: mingw: http://www.mingw.org The mingw-xcc.sh script will grab things for you. There's a lot of info on the Mingw compiler and its use as a cross compiler at the site. proj: http://www.remotesensing.org/proj/ Get version 4.4.2 zlib: http://www.info-zip.org/pub/infozip/zlib/ Get version 1.1.3 jpeg: ftp://ftp.uu.net/graphics/jpeg/ Get version 6b. tiff: http://www.libtiff.org/ Get version 3.5.5 freetype: http://www.freetype.org Get version 1.3.1 NOTE!!! I have found the the freetype-1.3.1.tar.gz file contains source files with dos style end of line characters (cr-lf). This will likely confuse gcc. The easy way to convert into normal unix-style text files is to get the freetype-1.3.1.zip, and use 'unzip -a freetype-1.3.1' to unpack it, converting the files to use lf only. Rename the 'freetype' directory to 'freetype-1.3.1'. regex: ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz mapserver: http://mapserver.gis.umn.edu/dload.html Get the 'nightly' CVS builds for 3.4 (beta), nightly.tar.gz. We will also use the GD 1.2 and GDFT libraries that come with Mapserver. As a side effect, we will also build an executable, mapserv.exe. tcl: http://dev.scriptics.com Get version 8.3.2 We will only be building 'libtclstub83.a', not the entire Tcl library. Also get 'tcl832.exe' and install it on your Windows machine(s) if you don't already have it. For best results, let the installer place Tcl in 'C:\Program Files\Tcl'. Build everything: Use the build script in this directory. (change the values of 'mingwbin' and 'mingwxcc' if needed.) sh build Install: You probably have to be root to write into /c. sh install Or, you can ftp the files over to your windows box and use the 'setup.tcl' installer. Notes: Building for Windows is a royal pain in the ***! The biggest problem is building the various libraries the 'right' way, i.e, as DLL files. This requires a majic Windows macro to export the symbols for the DLL, but another majic macro for code that uses the symbols in a DLL. For software originally not designed to be portable across Unix and Windows, this requires changing alot of source files. Examples of software that is written for portability: zlib, tcl Examples of software that is not: proj, mapserver The alternative: compile the source library code, and bundling it into a standard library file, e.g., libz.a, libjpeg.a, libttf.a, etc. We then take all of the libraries and create our final DLL, libMapscript.dll. The downside is that we're not allowing any reuse of the libaries, but the upside is we don't have to change much exisiting code. I do this method. build0100644000421500037440000000113207225404613012175 0ustar tpoindexsybcips # change these two defs if your Mingw cross compiler is somewhere else mingwbin=/opt/mingw/bin mingwxcc=i386-mingw32msvc- export mingwbin mingwxcc (cd ms-mingw/zlib-1.1.3 ; sh build) (cd ms-mingw/jpeg-6b ; sh build) (cd ms-mingw/tiff-v3.5.5 ; sh build) (cd ms-mingw/freetype-1.3.1 ; sh build) (cd ms-mingw/gd-1.2 ; sh build) (cd ms-mingw/gdft ; sh build) (cd ms-mingw/proj-4.4.2 ; sh build) (cd ms-mingw/regex-0.12 ; sh build) (cd ms-mingw/mapserver ; sh build) (cd ms-mingw/tcl-8.3.2 ; sh build) (cd ms-mingw/mapscripttcl ; sh build) install0100644000421500037440000000045007225156531012551 0ustar tpoindexsybcips#!/bin/sh destdir=/c/progra~1/tcl/lib/MapscriptTcl1.0 if [ ! -d $destdir ] ; then mkdir $destdir fi cd mapserver/mapscript/tcl cp libMapscript.dll $destdir cp mapscriptsupp.tcl $destdir cp pkgIndex.tcl $destdir cp mapscript_wrap.html $destdir cp mapscriptsupp.html $destdir ms-mingw/0040755000421500037440000000000007225406434012722 5ustar tpoindexsybcipsms-mingw/gd-1.2/0040755000421500037440000000000007225405166013613 5ustar tpoindexsybcipsms-mingw/gd-1.2/build0100644000421500037440000000020307225405157014625 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver/gd-1.2 cd ../../mapserver/gd-1.2 make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/gd-1.2/Makefile.MinXCC0100644000421500037440000000266307220263750016333 0ustar tpoindexsybcips#Depending on your system, you will need to modify this makefile. #If you do not have gcc, change the setting for CC, but you must #use an ANSI standard C compiler (NOT the old SunOS 4.1.3 cc #compiler; get gcc if you are still using it). #If the ar command fails on your system, consult the ar manpage #for your system. MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CFLAGS = -O LIBS = -L./ -lgd -lm all: libgd.a old: libgd.a gddemo giftogd webgif gddemo: gddemo.o libgd.a gd.h gdfonts.h gdfontl.h $(CC) gddemo.o -o gddemo $(LIBS) giftogd: giftogd.o libgd.a gd.h $(CC) giftogd.o -o giftogd $(LIBS) libgd.a: gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \ gd.h gdfontt.h gdfonts.h gdfontmb.h gdfontl.h gdfontg.h rm -f libgd.a $(AR) rc libgd.a gd.o gdfontt.o gdfonts.o gdfontmb.o \ gdfontl.o gdfontg.o gd.dll: gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \ gd.h gdfontt.h gdfonts.h gdfontmb.h gdfontl.h gdfontg.h $(DLLWRAP) --output-lib=libgd.a --dllname=gd.dll --output-def=gd.def \ --dlltool=$(DLLTOOL) --export-all-symbols --driver-name=$(CC) \ gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o webgif: webgif.o libgd.a gd.h $(CC) webgif.o -o webgif $(LIBS) clean: rm -f *.o *.a gddemo giftogd webgif ms-mingw/freetype-1.3.1/0040755000421500037440000000000007225405132015175 5ustar tpoindexsybcipsms-mingw/freetype-1.3.1/Makefile.MinXCC0100644000421500037440000000470507220311561017715 0ustar tpoindexsybcips# This file is part of the FreeType project. # # It builds the library for MinGW32 gcc under Win9x. # # You will need a port of GNU make; the MinGW32 port works. # # Use this file while in the lib directory with the following statement: # # make -f arch/win32/Makefile.Min # # # When compared to the other Makefiles for gcc, there is a difference # here, because COMMAND.COM on Win 9x is not able to process more than # 126 characters. So the command line for ar use the * shell character. # # This is not as safe as normal, because unnecessary files may be # included by mistake in the library. # The normal behaviour can be restored by defining NON_LIMITED_SHELL=1 ARCH = arch/win32 FT_MAKEFILE = $(ARCH)/Makefile.MinXCC MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool ifdef DEBUG CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend else CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend endif TTF_DEFS = -D__WIN32__ -D__WIN32DLL__ -DWIN32 -D_WIN32 -D_MT -D_DLL TTFILE = ./ttfile.c TTMEMORY = ./ttmemory.c TTMUTEX = ./ttmutex.c PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ extend/ftxgsub.c extend/ftxgpos.c extend/ftxgdef.c \ extend/ftxopen.c extend/ftxerr18.c OBJS_X = $(SRC_X:.c=.o) SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ ttgload.c ttinterp.c ttload.c ttobjs.c \ ttraster.c ttextend.c $(PORT) OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) SRC_S = $(ARCH)/freetype.c OBJ_S = $(SRC_S:.c=.o) OBJS_S = $(OBJ_S) $(OBJS_X) %.o: %.c $(CC) $(CFLAGS) $(TTF_DEFS) -c -o $@ $< .PHONY: all debug clean distclean depend all: $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=$(OBJS_S) OBJ_LOC=$(ARCH) libttf.a libttf.a: $(LIB_FILES) rm -f libttf.a $(AR) cr libttf.a $(OBJS_S) ttf.dll: $(LIB_FILES) $(DLLWRAP) --output-lib=libttf.a --dllname=ttf.dll \ --def=ttf.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ $^ $(OBJ_S): $(SRC_S) $(SRC_M) clean: -rm *.o -rm extend\*.o -rm $(subst /,\,$(ARCH)\*.o) -rm response distclean: clean -rm dep.end -rm libttf.a depend: $(SRS_S) $(SRC_M) $(SRC_X) $(CC) -E -M $^ > dep.end ifeq (dep.end,$(wildcard dep.end)) include dep.end endif # end of Makefile.Min ms-mingw/freetype-1.3.1/build0100644000421500037440000000023507225405130016212 0ustar tpoindexsybcipscp Makefile.MinXCC ../../freetype-1.3.1/lib/arch/win32 cd ../../freetype-1.3.1/lib make -f arch/win32/Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/mingw-xcc.sh0100755000421500037440000000700707225406434015156 0ustar tpoindexsybcips#!/bin/sh # This is a buildscript for a cross mingwin compiler. # You should be able to just run it once you set # the correct src, build, and install dirs #SRCDIR=${HOME}/project/Xmingwin #BUILDDIR=${HOME}/project/build/Xmingwin #PREFIX=${HOME}/project/install/Xmingwin SRCDIR=/opt/mingw/src BUILDDIR=/opt/mingw/build PREFIX=/opt/mingw #TARGET=i386-pc-mingw32 # Mumit suggested changing this target name to i386-mingw32msvc TARGET=i386-mingw32msvc TARGET_ALIAS=i386-mingw32msvc # The install location's bin dir must be on the path PATH=$PREFIX/bin:$PATH BASE_URL=ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/snapshots/gcc-2.95.2-1 BINUTILS=binutils-19990818 BINUTILS_TAR=${BINUTILS}-1-src.tar.gz GCC=gcc-2.95.2 GCC_TAR=${GCC}-1-src.tar.gz MINGWSRC_ZIP=mingw-20000203.zip MSVCRT_ZIP=mingw-msvcrt-20000203.zip # If the files are not in the src directory, download them now mkdir -p $SRCDIR cd $SRCDIR for f in $BINUTILS_TAR $GCC_TAR $MINGWSRC_ZIP $MSVCRT_ZIP; do if test ! -f ${f} ; then echo "wget ${BASE_URL}/${f}" wget ${BASE_URL}/${f} if test ! -f ${f} ; then echo "Could not download ${BASE_URL}/${f}" exit 1 fi else echo "Found ${f} in the srcdir $SRCDIR" fi done echo "--- install binary cross libs and includes" mkdir -p $PREFIX cd $PREFIX if test ! -d $TARGET_ALIAS ; then unzip -o $SRCDIR/$MSVCRT_ZIP fi if test ! -d $TARGET_ALIAS ; then echo "error extracting $MSVCRT_ZIP, target alias dir $SRCDIR/$TARGET_ALIAS not found" exit 1 fi if test $TARGET_ALIAS != $TARGET ; then ln -s $TARGET_ALIAS $TARGET fi echo "--- compile and install binutils" cd $SRCDIR if test ! -d $BINUTILS ; then echo "extracting $BINUTILS_TAR in $SRCDIR" tar -xzf $BINUTILS_TAR if test ! -d $BINUTILS ; then echo "error extracting $BINUTILS_TAR, could not find $SRCDIR/$BINUTILS dir" exit 1 fi fi mkdir -p $BUILDDIR/binutils-$TARGET cd $BUILDDIR/binutils-$TARGET if test ! -f Makefile ; then echo "running ./configure for binutils, output saved in configure.log" $SRCDIR/$BINUTILS/configure -v --prefix=$PREFIX --target=$TARGET \ &> configure.log fi echo "running \"make\" for binutils, output saved in make.log" make all &> make.log echo "running \"make install\" for binutils, output saved in make_install.log" make install &> make_install.log echo "--- compile and install gcc" cd $SRCDIR if test ! -d $GCC ; then echo "extracting $GCC_TAR in $SRCDIR" tar -xzf $GCC_TAR if test ! -d $GCC ; then echo "error extracting $GCC_TAR, could not find $SRCDIR/$GCC dir" exit 1 fi fi mkdir -p $BUILDDIR/gcc-$TARGET cd $BUILDDIR/gcc-$TARGET if test ! -f Makefile ; then echo "running ./configure for gcc, output saved in configure.log" $SRCDIR/$GCC/configure -v --prefix=$PREFIX --target=$TARGET \ --with-gnu-as --with-gnu-ld \ &> configure.log fi # work around gcc bug? #cd gcc ; make installdirs ; cd - #echo "running \"make cross\" for gcc, output saved in make.log" echo "running \"make\" for gcc, output saved in make.log" #NOTE: We seem to need to run make cross not make all here #make cross &> make.log #FIXME: we seem to need to run make 2 times, not sure where the bug is. make all &> make1.log make all &> make2.log echo "running \"make install\" for gcc, output saved in make_install.log" make install &> make_install.log echo "Done!" echo "" echo "Your mingwin cross compilers are installed in $PREFIX" echo "The c++ compiler is called $TARGET-c++ or $TARGET-g++" echo "The c compiler is called $TARGET-gcc" echo "You may need to add $PREFIX/bin to your PATH" ms-mingw/tiff-v3.5.5/0040755000421500037440000000000007225405345014506 5ustar tpoindexsybcipsms-mingw/tiff-v3.5.5/Makefile.MinXCC0100644000421500037440000000722707220312242017217 0ustar tpoindexsybcips# $Header: /cvsroot/osrs/libtiff/libtiff/Makefile.lcc,v 1.1.1.1 1999/07/27 21:50:27 mike Exp $ # # Tag Image File Format Library # # Copyright (c) 1988-1997 Sam Leffler # Copyright (c) 1991-1997 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # INSTALL=install NULL= MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool NATIVE_CC = gcc IPATH= -I. -I../../jpeg-6b -I../../zlib-1.1.3 ILIBS= -L../../jpeg-6b -ljpeg -L../../zlib-1.1.3 -lz CONF_LIBRARY=\ ${NULL} COPTS= -O6 -DNDEBUG -DJPEG_SUPPORT CFLAGS= ${COPTS} ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ fax3sm_winnt.c \ tif_aux.c \ tif_close.c \ tif_codec.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_luv.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_predict.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_win32.c \ tif_write.c \ tif_zip.c \ ${NULL} OBJS= tif_fax3.o \ fax3sm_winnt.o \ tif_aux.o \ tif_close.o \ tif_codec.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_luv.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_predict.o \ tif_print.o \ tif_read.o \ tif_swab.o \ tif_strip.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_win32.o \ tif_write.o \ tif_zip.o \ ${NULL} ALL= tiffrnb.lib all: version.h libtiff.a tiff.dll: version.h ${OBJS} $(DLLWRAP) --output-lib=libtiff.a --dllname=tiff.dll \ --output-def=tiff.def --def=libtiff.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ ${OBJS} ${ILIBS} libtiff.a: ${OBJS} rm -f libtiff.a ${AR} cr libtiff.a $(OBJS) ${OBJS}: tiffio.h tiff.h tiffcomp.h tiffiop.h tiffconf.h tif_fax3.o: tif_fax3.c fax3sm_winnt.c t4.h tif_fax3.h version.h: ${NATIVE_CC} -o mkversion ${CFLAGS} mkversion.c rm -f version.h; ./mkversion version.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} mkg3states mkg3states.o g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} ms-mingw/tiff-v3.5.5/build0100644000421500037440000000021107225405344015516 0ustar tpoindexsybcipscp Makefile.MinXCC ../../tiff-v3.5.5/libtiff cd ../../tiff-v3.5.5/libtiff make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/gdft/0040755000421500037440000000000007225405172013644 5ustar tpoindexsybcipsms-mingw/gdft/Makefile.MinXCC0100644000421500037440000000247707220264436016374 0ustar tpoindexsybcips#Depending on your system, you will need to modify this makefile. #If you do not have gcc, change the setting for CC, but you must #use an ANSI standard C compiler (NOT the old SunOS 4.1.3 cc #compiler; get gcc if you are still using it). #If the ar command fails on your system, consult the ar manpage #for your system. MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool GD_INC = -I../gd-1.2 GD_LIB = -L../gd-1.2 -lgd GD = -DUSE_GD_1_3 TTF_INC = -I../../freetype-1.3.1/lib TTF_LIB = -L../../freetype-1.3.1/lib -lttf TTF = -DUSE_TTF LEX = flex XTRALIBS = -lm CFLAGS = -O2 $(GD) $(GD_INC) $(TTF) $(TTF_INC) LDFLAGS = $(XTRALIBS) $(GD_LIB) $(TTF_LIB) RM= /bin/rm -f OBJS= gdkanji.o gdcache.o gdttf.o # # --- You shouldn't have to edit anything else. --- # .c.o: $(CC) -c $(CFLAGS) $< all: libgdft.a gdft.dll: $(OBJS) $(DLLWRAP) --output-lib=libgdft.a --dllname=gdft.dll \ --output-def=gdft.def \ --dlltool=$(DLLTOOL) --export-all-symbols --driver-name=$(CC) \ $(OBJS) $(TTF_LIB) lib: libgdft.a libgdft: libgfft.a libgdft.a: $(OBJS) rm -f libgdft.a $(AR) cr libgdft.a $(OBJS) clean: rm -f libgdft.a *.o ms-mingw/gdft/build0100644000421500037440000000017707225405171014667 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver/gdft cd ../../mapserver/gdft make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/jpeg-6b/0040755000421500037440000000000007225405176014156 5ustar tpoindexsybcipsms-mingw/jpeg-6b/Makefile.MinXCC0100644000421500037440000002755507220264452016704 0ustar tpoindexsybcips# Makefile for Independent JPEG Group's software # This makefile is suitable for Unix-like systems with ANSI-capable compilers. # If you have a non-ANSI compiler, makefile.unix is a better starting point. # Read installation instructions before saying "make" !! # The name of your C compiler: MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool # You may need to adjust these cc options: CFLAGS= -O6 # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via -D switches here. # Link-time cc options: LDFLAGS= # To link any special libraries, add the necessary -l commands here. LDLIBS= # Put here the object file name for the correct system-dependent memory # manager file. For Unix this is usually jmemnobs.o, but you may want # to use jmemansi.o or jmemname.o if you have limited swap space. SYSDEPMEM= jmemnobs.o # miscellaneous OS-dependent stuff # linker LN= $(CC) # file deletion command RM= rm -f # library (.a) file creation command # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ jquant2.c jutils.c jmemmgr.c # memmgr back ends: compile only one of these into a working library SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c # source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ coderules.doc filelist.doc change.log MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ makvms.opt CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ jconfig.vms CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ testimgp.jpg DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ jfdctint.o # decompression library object files DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for sample applications (excluding library files) COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ cdjpeg.o DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ cdjpeg.o TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o all: libjpeg.a jpeg.dll: $(LIBOBJECTS) $(DLLWRAP) --output-lib=libjpeg.a --dllname=jpeg.dll \ --output-def=jpeg.def \ --dlltool=$(DLLTOOL) --export-all-symbols --driver-name=$(CC) \ $(LIBOBJECTS) allold: libjpeg.a cjpeg djpeg jpegtran rdjpgcom wrjpgcom libjpeg.a: $(LIBOBJECTS) $(RM) libjpeg.a $(AR) cr libjpeg.a $(LIBOBJECTS) cjpeg: $(COBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.a $(LDLIBS) djpeg: $(DOBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.a $(LDLIBS) jpegtran: $(TROBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.a $(LDLIBS) rdjpgcom: rdjpgcom.o $(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.o $(LDLIBS) wrjpgcom: wrjpgcom.o $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.o $(LDLIBS) jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 clean: $(RM) *.o cjpeg djpeg jpegtran libjpeg.a rdjpgcom wrjpgcom $(RM) core testout* test: cjpeg djpeg jpegtran $(RM) testout* ./djpeg -dct int -ppm -outfile testout.ppm testorig.jpg ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg ./cjpeg -dct int -outfile testout.jpg testimg.ppm ./djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm ./jpegtran -outfile testoutt.jpg testprog.jpg cmp testimg.ppm testout.ppm cmp testimg.bmp testout.bmp cmp testimg.jpg testout.jpg cmp testimg.ppm testoutp.ppm cmp testimgp.jpg testoutp.jpg cmp testorig.jpg testoutt.jpg jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcphuff.o: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jfdctflt.o: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jfdctfst.o: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.o: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.o: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.o: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.o: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.o: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemmac.o: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.o: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.o: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h jpegtran.o: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h rdjpgcom.o: rdjpgcom.c jinclude.h jconfig.h wrjpgcom.o: wrjpgcom.c jinclude.h jconfig.h cdjpeg.o: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdcolmap.o: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdswitch.o: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.o: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h rdppm.o: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.o: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.o: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.o: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.o: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.o: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdbmp.o: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrbmp.o: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdrle.o: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrrle.o: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h ms-mingw/jpeg-6b/build0100644000421500037440000000021107225405175015166 0ustar tpoindexsybcipscp Makefile.MinXCC ../../jpeg-6b cd ../../jpeg-6b cp jconfig.vc jconfig.h make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/mapserver/0040755000421500037440000000000007225405211014716 5ustar tpoindexsybcipsms-mingw/mapserver/Makefile.MinXCC0100755000421500037440000001521707220445065017452 0ustar tpoindexsybcips# Run ./configure in the main MapServer directory to turn this Makefile.in # into a proper Makefile # # mpatrol runtime memory debugger # MPATROL= MPATROL_INC= MPATROL_LIB= # # If you want to ignore missing datafile errors uncomment the following # line. This is especially useful with large tiled datasets that may not # have complete data for each tile. # #IGNORE_MISSING_DATA=-DIGNORE_MISSING_DATA IGNORE_MISSING_DATA = -DIGNORE_MISSING_DATA # # Apparently these aren't as commonplace as I'd hoped. Edit the # following line to reflect the missing functions on your platform. # # STRINGS=-DNEED_STRCASECMP -DNEED_STRNCASECMP -DNEED_STRDUP STRINGS= # Freetype distribution (TrueType font support). Available at http://www.freetype.org/. (RECOMMENDED) TTF_LIB= -Lgdft -lgdft -L../freetype-1.3.1/lib -lttf TTF_INC= -Igdft -I../freetype-1.3.1/lib TTF= -DUSE_TTF MAKE_GDFT= MAKE_GDFT_CLEAN= # Proj.4 distribution (cartographic projection routines). Not required for normal use. (EXPERIMENTAL) PROJ_INC= -I../proj-4.4.2/src PROJ_LIB= -L../proj-4.4.2/src -lproj PROJ= -DUSE_PROJ # GD distribution (graphics library GIF and/or PNG support). (REQUIRED) # # - Version 1.2 is included and writes LZW GIF (-DUSE_GD_1_2). # - Versions 1.3 to 1.5 write non-LZW GIF (-DUSE_GD_1_3). # - Versions 1.6 and greater write PNG (-DUSE_GD_1_6). Add -lpng -lz to GD_LIB line. # # If you're not using the 1.2 version included in the MapServer distribution # then comment out the MAKE_GD and MAKE_GD_CLEAN entries. # GDFONT_OBJ=gd-1.2/gdfontt.o gd-1.2/gdfonts.o gd-1.2/gdfontmb.o gd-1.2/gdfontl.o gd-1.2/gdfontg.o GD_INC= -Igd-1.2 GD_LIB= -Lgd-1.2 -lgd GD= -DUSE_GD_1_2 MAKE_GD= MAKE_GD_CLEAN = # TIFF distribution (raster support for TIFF and GEOTIFF imagery). (RECOMMENDED) TIFF_INC= -I../tiff-v3.5.5/libtiff TIFF_LIB= -L../tiff-v3.5.5/libtiff -ltiff TIFF= -DUSE_TIF # JPEG distribution (raster support for grayscale JPEG images, INPUT ONLY). JPEG_INC= -I../jpeg-6b JPEG_LIB= -L../jpeg-6b -ljpeg JPEG= -DUSE_JPEG # EPPL7 Support (this activates ERDAS as well) Included in the distribution. Probably the best raster alternative if # you've got EPPL7 laying around. See http://www.lmic.state.mn.us/ for more information. (RECOMMENDED) EPPL= -DUSE_EPPL EPPL_OBJ= epplib.o # ESRI SDE Support. You MUST have the SDE Client libraries and include files # on your system someplace. The actual SDE server you wish to connect to can # be elsewhere. SDE= SDE_LIB= SDE_INC= # Optional OGR Support. OGC Simple Feature inspired interface for vector # formats. See http://gdal.velocet.ca/projects/opengis/ OGR= OGR_LIB= OGR_INC= # # UofMN GIS/Image Processing Extension (very experimental) # #EGIS=-DUSE_EGIS #EGIS_INC=-I./egis/errLog -I./egis/imgSrc -I./egis #EGIS_LIB=-L./egis/errLog -lerrLog -L./egis/imgSrc -limgGEN -L./egis -legis #MAKE_EGIS=egis #MAKE_EGIS_CLEAN=egis_clean # # IMPORTANT NOTE ABOUT REGEX FOR PHP_MAPSCRIPT USERS: # # In order to compile the PHP_MAPSCRIPT module, we have to make MapServer # uses the same version of the REGEX library that PHP was compiled with: # REGEX_OBJ= ../regex-0.12/regex.o REGEX_INC= -I../regex-0.12 # # Pick a compiler, etc. Flex and bison are only required if you need to modify the mapserver lexer (maplexer.l) or expression parser (mapparser.y). # MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar cr DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CXX = $(CC) RANLIB= true LEX= flex YACC= bison XTRALIBS= -lm RUNPATHS= CFLAGS= -O2 $(IGNORE_MISSING_DATA) $(STRINGS) $(EPPL) $(PROJ) $(TTF) \ $(TIFF) $(JPEG) $(GD) $(SDE) $(OGR) $(MPATROL) $(GD_INC) $(PROJ_INC) $(TTF_INC) \ $(TIFF_INC) $(JPEG_INC) $(EGIS_INC) $(SDE_INC) $(REGEX_INC) $(MPATROL_INC) LDFLAGS= $(RUNPATHS) -L. -lmap $(GD_LIB) $(TTF_LIB) $(TIFF_LIB) $(PROJ_LIB) \ $(JPEG_LIB) $(EGIS_LIB) $(SDE_LIB) $(OGR_LIB) $(MPATROL_LIB) $(XTRALIBS) RM= /bin/rm -f OBJS= mapbits.o maphash.o mapshape.o mapxbase.o mapparser.o maplexer.o maptree.o mapsearch.o mapstring.o mapsymbol.o mapfile.o maplegend.o maputil.o mapscale.o mapquery.o maplabel.o maperror.o mapprimitive.o mapproject.o mapraster.o mapsde.o mapogr.o $(EPPL_OBJ) $(REGEX_OBJ) # # --- You shouldn't have to edit anything else. --- # .c.o: $(CC) -c $(CFLAGS) $< -o $@ all: $(MAKE_GD) $(MAKE_EGIS) $(MAKE_GDFT) libmap.a shp2img legend \ mapserv shptree shptreevis shptreetst scalebar sortshp perlvars gd:: cd gd-1.2; make; cd .. gdft:: cd gdft; make; cd .. egis:: cd egis/errLog; make; cd .. cd egis/imgSrc; make; cd .. cd egis; make; cd .. php3_mapscript:: cd mapscript/php3; make; cd ../.. maplexer.o: maplexer.c map.h mapfile.h maplexer.c: maplexer.l $(LEX) -Pmsyy -i -omaplexer.c maplexer.l mapparser.o: mapparser.c map.h mapparser.c: mapparser.y $(YACC) -p msyy -d -omapparser.c mapparser.y mapogr.o: mapogr.cpp $(CXX) -c $(CFLAGS) $(OGR_INC) mapogr.cpp -o mapogr.o lib: libmap.a libmap: libmap.a libmap.a: map.h $(OBJS) map.h $(AR) libmap.a $(OBJS) $(RANLIB) libmap.a shp2img: libmap.a shp2img.o map.h $(CC) $(CFLAGS) shp2img.o $(LDFLAGS) -o shp2img sym2img: libmap.a sym2img.o map.h $(CC) $(CFLAGS) sym2img.o $(LDFLAGS) -o sym2img legend: libmap.a legend.o map.h $(CC) $(CFLAGS) legend.o $(LDFLAGS) -o legend scalebar: libmap.a scalebar.o map.h $(CC) $(CFLAGS) scalebar.o $(LDFLAGS) -o scalebar mapserv: mapserv.h libmap.a mapserv.o cgiutil.o map.h $(CC) $(CFLAGS) mapserv.o cgiutil.o $(LDFLAGS) -o mapserv shpindex: libmap.a shpindex.o map.h $(CC) $(CFLAGS) shpindex.o $(LDFLAGS) -o shpindex shptree: libmap.a shptree.o map.h $(CC) $(CFLAGS) shptree.o $(LDFLAGS) -o shptree shptreevis: libmap.a shptreevis.o map.h $(CC) $(CFLAGS) shptreevis.o $(LDFLAGS) -o shptreevis shptreetst: libmap.a shptreetst.o map.h $(CC) $(CFLAGS) shptreetst.o $(LDFLAGS) -o shptreetst sortshp: sortshp.o $(CC) $(CFLAGS) sortshp.o $(LDFLAGS) -o sortshp perlvars: touch perlvars pwd > perlvars echo $(IGNORE_MISSING_DATA) $(STRINGS) $(EPPL) $(PROJ) $(TTF) $(TIFF) $(JPEG) $(GD) $(SDE) $(OGR) >> perlvars echo -I. $(PROJ_INC) $(GD_INC) $(TTF_INC) $(TIFF_INC) $(JPEG_INC) $(SDE_INC) $(OGR_INC) >> perlvars echo $(LDFLAGS) >> perlvars gd_clean: cd gd-1.2; make clean; cd .. gdft_clean: cd gdft; make clean; cd .. egis_clean: cd egis/errLog; make clean; cd .. cd egis/imgSrc; make clean; cd .. cd egis; make clean; cd .. php3_mapscript_clean:: cd mapscript/php3; make clean; cd ../.. clean: $(MAKE_GD_CLEAN) $(MAKE_GDFT_CLEAN) $(MAKE_EGIS_CLEAN) rm -f libmap.a *.o shp2img mapserv legend shptree shptreevis shptreetst scalebar sortshp perlvars sorta-clean: rm -f *.o ms-mingw/mapserver/build0100644000421500037440000000016407225405211015736 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver cd ../../mapserver make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/zlib-1.1.3/0040755000421500037440000000000007225405353014317 5ustar tpoindexsybcipsms-mingw/zlib-1.1.3/Makefile.MinXCC0100644000421500037440000001302507220422642017030 0ustar tpoindexsybcips# Makefile for zlib # Copyright (C) 1995-1998 Jean-loup Gailly. # For conditions of distribution and use, see copyright notice in zlib.h # To compile and test, type: # ./configure; make test # The call of configure is optional if you don't have special requirements # If you wish to build zlib as a shared library, use: ./configure -s # To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: # make install # To install in $HOME instead of /usr/local, use: # make install prefix=$HOME MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CFLAGS=-O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-g -DDEBUG #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ # -Wstrict-prototypes -Wmissing-prototypes LDFLAGS=-L. -lz LDSHARED=$(CC) CPP=$(CC) -E VER=1.1.3 LIBS=libz.a SHAREDLIB=libz.so RANLIB=true TAR=tar SHELL=/bin/sh prefix = /usr/local exec_prefix = ${prefix} libdir = ${exec_prefix}/lib includedir = ${prefix}/include OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o OBJA = # to use the asm code: make OBJA=match.o TEST_OBJS = example.o minigzip.o DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \ algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \ contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \ contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \ contrib/asm[56]86/*.S contrib/iostream/*.cpp \ contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \ contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \ contrib/delphi*/*.??? all: libz.a z.dll: $(OBJS) $(DLLWRAP) --output-lib=libz.a --dllname=z.dll \ --output-def=z.def --export-all-symbols \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ $(OBJS) allold: example minigzip test: all @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ echo hello world | ./minigzip | ./minigzip -d || \ echo ' *** minigzip test FAILED ***' ; \ if ./example; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; \ fi libz.a: $(OBJS) $(OBJA) rm -f libz.a $(AR) cr libz.a $(OBJS) $(OBJA) match.o: match.S $(CPP) match.S > _match.s $(CC) -c _match.s mv _match.o match.o rm -f _match.s $(SHAREDLIB).$(VER): $(OBJS) $(LDSHARED) -o $@ $(OBJS) rm -f $(SHAREDLIB) $(SHAREDLIB).1 ln -s $@ $(SHAREDLIB) ln -s $@ $(SHAREDLIB).1 example: example.o $(LIBS) $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) minigzip: minigzip.o $(LIBS) $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) install: $(LIBS) -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi cp zlib.h zconf.h $(includedir) chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h cp $(LIBS) $(libdir) cd $(libdir); chmod 755 $(LIBS) -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \ rm -f $(SHAREDLIB) $(SHAREDLIB).1; \ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \ (ldconfig || true) >/dev/null 2>&1; \ fi # The ranlib in install is needed on NeXTSTEP which checks file times # ldconfig is for Linux uninstall: cd $(includedir); \ v=$(VER); \ if test -f zlib.h; then \ v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \ rm -f zlib.h zconf.h; \ fi; \ cd $(libdir); rm -f libz.a; \ if test -f $(SHAREDLIB).$$v; then \ rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \ fi clean: rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \ _match.s maketree distclean: clean zip: mv Makefile Makefile~; cp -p Makefile.in Makefile rm -f test.c ztest*.c contrib/minizip/test.zip v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ zip -ul9 zlib$$v $(DISTFILES) mv Makefile~ Makefile dist: mv Makefile Makefile~; cp -p Makefile.in Makefile rm -f test.c ztest*.c contrib/minizip/test.zip d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ rm -f $$d.tar.gz; \ if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ files=""; \ for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ cd ..; \ GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ if test ! -d $$d; then rm -f $$d; fi mv Makefile~ Makefile tags: etags *.[ch] depend: makedepend -- $(CFLAGS) -- *.[ch] # DO NOT DELETE THIS LINE -- make depend depends on it. adler32.o: zlib.h zconf.h compress.o: zlib.h zconf.h crc32.o: zlib.h zconf.h deflate.o: deflate.h zutil.h zlib.h zconf.h example.o: zlib.h zconf.h gzio.o: zutil.h zlib.h zconf.h infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h infcodes.o: zutil.h zlib.h zconf.h infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h inffast.o: zutil.h zlib.h zconf.h inftrees.h inffast.o: infblock.h infcodes.h infutil.h inffast.h inflate.o: zutil.h zlib.h zconf.h infblock.h inftrees.o: zutil.h zlib.h zconf.h inftrees.h infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h minigzip.o: zlib.h zconf.h trees.o: deflate.h zutil.h zlib.h zconf.h trees.h uncompr.o: zlib.h zconf.h zutil.o: zutil.h zlib.h zconf.h ms-mingw/zlib-1.1.3/build0100644000421500037440000000016607225405350015336 0ustar tpoindexsybcipscp Makefile.MinXCC ../../zlib-1.1.3 cd ../../zlib-1.1.3 make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/proj-4.4.2/0040755000421500037440000000000007225405220014327 5ustar tpoindexsybcipsms-mingw/proj-4.4.2/Makefile.MinXCC0100644000421500037440000000443407220430037017050 0ustar tpoindexsybcips MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool azimuthal = \ PJ_aeqd.o PJ_gnom.o PJ_laea.o PJ_mod_ster.o \ PJ_nsper.o PJ_nzmg.o PJ_ortho.o PJ_stere.o conic = \ PJ_aea.o PJ_bipc.o PJ_bonne.o PJ_eqdc.o \ PJ_imw_p.o PJ_lcc.o PJ_mpoly.o PJ_poly.o \ PJ_rpoly.o PJ_sconics.o cylinder = \ PJ_cass.o PJ_cc.o PJ_cea.o PJ_eqc.o \ PJ_gall.o PJ_labrd.o PJ_lsat.o PJ_merc.o \ PJ_mill.o PJ_ocea.o PJ_omerc.o PJ_somerc.o \ PJ_tcc.o PJ_tcea.o PJ_tmerc.o misc = \ PJ_airy.o PJ_aitoff.o PJ_august.o PJ_bacon.o \ PJ_chamb.o PJ_hammer.o PJ_lagrng.o PJ_larr.o \ PJ_lask.o PJ_nocol.o PJ_ob_tran.o PJ_oea.o \ PJ_tpeqd.o PJ_vandg.o PJ_vandg2.o PJ_vandg4.o \ PJ_wag7.o pj_latlong.o pseudo = \ PJ_boggs.o PJ_collg.o PJ_crast.o PJ_denoy.o \ PJ_eck1.o PJ_eck2.o PJ_eck3.o PJ_eck4.o \ PJ_eck5.o PJ_fahey.o PJ_fouc_s.o PJ_gins8.o \ PJ_gn_sinu.o PJ_goode.o PJ_hatano.o PJ_loxim.o \ PJ_mbt_fps.o PJ_mbtfpp.o PJ_mbtfpq.o PJ_moll.o \ PJ_nell.o PJ_nell_h.o PJ_putp2.o PJ_putp3.o \ PJ_putp4p.o PJ_putp5.o PJ_putp6.o PJ_robin.o \ PJ_sts.o PJ_urm5.o PJ_urmfps.o PJ_wag2.o \ PJ_wag3.o PJ_wink1.o PJ_wink2.o support = \ aasincos.o adjlon.o bch2bps.o bchgen.o \ biveval.o dmstor.o mk_cheby.o pj_auth.o \ pj_deriv.o pj_ell_set.o pj_ellps.o pj_errno.o \ pj_factors.o pj_fwd.o pj_init.o pj_inv.o \ pj_list.o pj_malloc.o pj_mlfn.o pj_msfn.o \ pj_open_lib.o pj_param.o pj_phi2.o pj_pr_list.o \ pj_qsfn.o pj_strerrno.o pj_tsfn.o pj_units.o \ pj_zpoly1.o rtodms.o vector1.o pj_release.o \ geocent.o pj_transform.o pj_datum_set.o pj_datums.o \ pj_apply_gridshift.o emess.o nad_cvt.o nad_init.o \ nad_intr.o LIBOBJ = $(support) $(pseudo) $(azimuthal) $(conic) $(cylinder) $(misc) EXESRC = proj.c gen_cheb.c p_series.c CFLAGS = -I. -O6 all: libproj.a proj.exe proj.dll: $(LIBOBJ) $(DLLWRAP) --output-lib=libproj.a --dllname=proj.dll \ --output-def=proj.def --export-all-symbols \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ $(LIBOBJ) -lm libproj.a: $(LIBOBJ) rm -f libproj.a $(AR) cr libproj.a $(LIBOBJ) proj.exe: $(EXESRC) libproj.a $(CC) -I. -o proj.exe -mwindows -mconsole $(EXESRC) -L. -lproj -lm clean: rm *.o *.a *.dll ms-mingw/proj-4.4.2/build0100644000421500037440000000017607225405217015360 0ustar tpoindexsybcipscp Makefile.MinXCC ../../proj-4.4.2/src cd ../../proj-4.4.2/src make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/tcl-8.3.2/0040755000421500037440000000000007225406576014161 5ustar tpoindexsybcipsms-mingw/tcl-8.3.2/build0100644000421500037440000000043507225406576015202 0ustar tpoindexsybcips# make gcc tcl stub lib # now configure and build the stub lib to .a format cd ../../tcl8.3.2/win CC=$mingwbin/${mingwxcc}gcc ./configure --enable-gcc make MINGWBIN=$mingwbin MINGWXCC=$mingwxcc AR=$mingwbin/${mingwxcc}ar \ RANLIB=$mingwbin/${mingwxcc}ranlib libtclstub83.a ms-mingw/regex-0.12/0040755000421500037440000000000007225405223014405 5ustar tpoindexsybcipsms-mingw/regex-0.12/Makefile.MinXCC0100644000421500037440000000061007220432746017124 0ustar tpoindexsybcipsMINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CFLAGS=-O6 -DHAVE_STRING_H OBJS = regex.o all: libregex.a libregex.a: $(OBJS) rm -f libregex.a $(AR) cr libregex.a $(OBJS) clean: rm -f *.o *.a ms-mingw/regex-0.12/build0100644000421500037440000000016707225405223015430 0ustar tpoindexsybcipscp Makefile.MinXCC ../../regex-0.12 cd ../../regex-0.12 make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/mapscripttcl/0040755000421500037440000000000007225410213015415 5ustar tpoindexsybcipsms-mingw/mapscripttcl/Makefile.MinXCC0100644000421500037440000000574107225410213020141 0ustar tpoindexsybcips# # Makefile.MinXCC for mapscript Tcl interface # Tom Poindexter, tpoindex@nyx.net # # The name of your C compiler: MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool DLTARGET = libMapscript PACKAGEDIR = MapscriptTcl1.0 TCL_PREFIX = /c/progra~1/tcl TCL_EXEC_PREFIX = $(TCL_PREFIX)/lib TCL_CC = $(CC) TCL_SHLIB_SUFFIX = .dll TCL_SHLIB_CFLAGS = -D_MSC_VER -D_WIN32 -D__WIN32__ -DWIN32 -D_WINDOWS \ -mno-cygwin TCL_LIB_SPEC = -L../../../tcl8.3.2/win -ltcl83 TCL_SHLIB_LD = $(DLLWRAP) TCL_LD_SEARCH_FLAGS = TCL_STUB_LIB_SPEC = -L../../../tcl8.3.2/win -ltclstub83 TCL_LIBS = TCL_DBGX = LIB_RUNTIME_DIR = MAPSERVERHOME = ../.. MAPSERVERDEFS = -DIGNORE_MISSING_DATA -DUSE_EPPL -DUSE_PROJ -DUSE_TTF \ -DUSE_TIF -DUSE_JPEG -DUSE_GD_1_2 MAPSERVERINCS = -I../.. -I../../../proj-4.4.2/src -I../../gd-1.2 \ -I../../gdft -I../../../freetype-1.3.1/lib \ -I../../../tiff-v3.5.5/libtiff -I../../../jpeg-6b \ -I../../../regex-0.12 MAPSERVERLIBS = -L../.. -lmap \ -L../../gdft -lgdft \ -L../../gd-1.2 -lgd \ -L../../../freetype-1.3.1/lib -lttf \ -L../../../tiff-v3.5.5/libtiff -ltiff \ -L../../../jpeg-6b -ljpeg \ -L../../../proj-4.4.2/src -lproj \ -L../../../regex-0.12 -lregex \ -lm SWIG_STUB_HACK = -DUSE_TCL_STUBS -DITCL_NAMESPACES -DItcl_Namespace=int \ -D"spaceId=ISPCID;Tcl_InitStubs(interp,\"8.1\",0)" all: stublib stublib: mapscript_wrap.o dllEntry.o mapscripttcl.def $(DLLWRAP) -s -mwindows -Wl,-e,_DllMain@12 -mno-cygwin \ --dllname=$(DLTARGET)$(TCL_SHLIB_SUFFIX) \ --def=mapscripttcl.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ dllEntry.o mapscript_wrap.o \ $(TCL_STUB_LIB_SPEC) $(MAPSERVERLIBS) $(TCL_LIBS) mapscript_wrap.o: mapscript_wrap.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ $(SWIG_STUB_HACK) \ mapscript_wrap.c dllEntry.o: dllEntry.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) dllEntry.c mapscripttcl.def: dllEntry.o mapscript_wrap.o $(DLLTOOL) --export-all --exclude-symbols DllMain@12 --output-def $@ \ dllEntry.o mapscript_wrap.o nostublib: mapscripttcl.def mapscript_wrap.o dllEntry.o $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript_wrap.c $(DLLWRAP) -s -mwindows -Wl,-e,_DllMain@12 -mno-cygwin \ --dllname=$(DLTARGET)$(TCL_SHLIB_SUFFIX) \ --def=mapscripttcl.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ dllEntry.o mapscript_wrap.o \ $(TCL_LIB_SPEC) $(MAPSERVERLIBS) $(TCL_LIBS) mapscript_wrap.c: swig -tcl8 -dnone -namespace $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript.i clean: rm -f *.o *.so *.dll *.a ms-mingw/mapscripttcl/dllEntry.c0100644000421500037440000000133407220672620017363 0ustar tpoindexsybcips/* * dllEntry.c -- * * This procedure provides the entry point for the dll * */ #include #if defined(_MSC_VER) || defined(__GNUC__) #define DllEntryPoint DllMain #endif /* *---------------------------------------------------------------------- * * DllEntryPoint -- * * This routine is called by gcc, VC++ or Borland to invoke the * initialization code for Tcl. * * Results: * TRUE. * * Side effects: * None. * *---------------------------------------------------------------------- */ BOOL APIENTRY DllEntryPoint ( HINSTANCE hInst, /* Library instance handle. */ DWORD reason, /* Reason this function is being called. */ LPVOID reserved) /* Not used. */ { return TRUE; } ms-mingw/mapscripttcl/build0100644000421500037440000000030107225405204016432 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver/mapscript/tcl cp dllEntry.c ../../mapserver/mapscript/tcl cd ../../mapserver/mapscript/tcl make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc mapserver-6.4.1/mapscript/tcl/win/setup.tcl0000644002461700001440000000110212261257215020533 0ustar tbonfortusers# install mapscript/tcl set tclhome [file dirname $tcl_library] set mslib $tclhome/MapscriptTcl1.0 if {! [file isdirectory $mslib]} { file mkdir $mslib } file copy -force libMapscript.dll $mslib file copy -force ../pkgIndex.tcl $mslib file copy -force ../mapscriptsupp.tcl $mslib catch {file copy -force ../mapscriptsupp.html $mslib} catch {file copy -force ../mapscript_wrap.html $mslib} wm title . "Mapscript/Tcl Installer" label .l -text "Mapscript/Tcl Installation is complete." button .b -text Ok -command exit pack .l .b -side top -padx 30 -pady 30 mapserver-6.4.1/mapscript/tcl/mapscriptsupp.tcl0000644002461700001440000001142012261257215021514 0ustar tbonfortusers# mapscriptsupp.tcl # # define procs to invoke object methods using an object pointer # tom poindexter, nov 2000, tpoindex@nyx.net # # e.g. shapeObj method arg arg ... # can be invoked on a shapeObj pointer as: # shapeObjRef $shapeObjPointer method arg arg ... # # convenience procedures: # getDBFNames $DBFHandle :returns list of field names # getDBFTypes $DBFHandle :returns list of field types # getDBFValues $DBFHandle $rec :returns list of field values # getQueryInfo $mapPtr $layerPtr :return "field value" from query # fix SWIG error # some swig versions don't handle namespaces when generating shadow objects # mapscript just has one - ms_error # if {![string length [info commands ::mapscript::ms_error]]} { catch { ::mapscript::errorObj ::mapscript::ms_error -this [::mapscript::ms_error_get] } } # # now define object helper procs # namespace eval ::mapscript { proc _mapscript_init_ {} { set code { proc OBJECTRef {ptr method args} { # check ptr for correct object type #if {! [regexp {_[^_]*_OBJECT_p} $ptr]} { # error "OBJECTRef pointer \"$ptr\" has wrong object class" #} # check for configure/cget/delete commands set member "" set delete "" switch -- $method { configure { set command _set set member _[string range [lindex $args 0] 1 end] set args [lrange $args 1 end] } cget { set command _get set member _[string range [lindex $args 0] 1 end] set args "" } delete { set delete delete_ set command "" set args "" } default { set command _$method } } # check of existence of command if {! [string length \ [info command ::mapscript::${delete}OBJECT${member}${command}]]} { error "OBJECT does not have method named \"$method\", or \ a member named \"$member\"" } # invoke command return [uplevel "::mapscript::${delete}OBJECT${member}${command} \ $ptr $args"] } } foreach obj {classObj colorObj errorObj featureListNodeObj itemObj \ labelCacheMemberObj labelCacheObj labelObj layerObj \ legendObj lineObj mapObj markerCacheMemberObj pointObj \ projectionObj queryMapObj rectObj referenceMapObj \ resultCacheMemberObj resultCacheObj scalebarObj shapeObj \ shapefileObj symbolSetObj webObj \ DBFInfo} { regsub -all OBJECT $code $obj proc_code eval $proc_code } } # run the help proc initialization, then get rid of it _mapscript_init_ rename _mapscript_init_ {} # # now create convenience procs # proc getDBFNames {dbf} { set n [msDBFGetFieldCount $dbf] set names "" for {set i 0} {$i < $n} {incr i} { lappend names [DBFInfoRef $dbf getFieldName $i] } return $names } proc getDBFTypes {dbf} { set n [msDBFGetFieldCount $dbf] set types "" for {set i 0} {$i < $n} {incr i} { set t [DBFInfoRef $dbf getFieldType $i] switch $t \ $::mapscript::FTString {set t string} \ $::mapscript::FTInteger {set t integer} \ $::mapscript::FTDouble {set t double} \ default {set t invalid} lappend t [DBFInfoRef $dbf getFieldWidth $i] lappend types $t } return $types } proc getDBFValues {dbf rec} { set n [msDBFGetFieldCount $dbf] set r [msDBFGetRecordCount $dbf] if {$rec >= $r || $rec < -1} {return ""} set values "" for {set i 0} {$i < $n} {incr i} { switch [DBFInfoRef $dbf getFieldType $i] \ $::mapscript::FTString { set t [msDBFReadStringAttribute $dbf $rec $i] } \ $::mapscript::FTInteger { set t [msDBFReadIntegerAttribute $dbf $rec $i] } \ $::mapscript::FTDouble { set t [msDBFReadDoubleAttribute $dbf $rec $i] } \ default {set t ""} lappend values $t } return $values } proc getQueryInfo {mapPtr layerPtr} { layerObjRef $layerPtr open [mapObjRef $mapPtr cget -shapepath] set rescachePtr [layerObjRef $layerPtr cget -resultcache] set numResults [resultCacheObjRef $rescachePtr cget -numresults] for {set i 0} {$i < $numResults} {incr i} { set resmemPtr [layerObjRef $layerPtr getResult $i] set shpIdx [resultCacheMemberObjRef $resmemPtr cget -shapeindex] set tileIdx [resultCacheMemberObjRef $resmemPtr cget -tileindex] set shpPtr [shapeObj -args $mapscript::MS_SHAPE_NULL] set rc [layerObjRef $layerPtr getShape $shpPtr $tileIdx $shpIdx] set numValues [shapeObjRef $shpPtr cget -numvalues] set pairs "" for {set j 0} {$j < $numValues} {incr j} { lappend pairs [layerObjRef $layerPtr getItem $j] \ [shapeObjRef $shpPtr getValue $j] } # delete the temporary shpPtr catch {rename $shpPtr {}} } layerObjRef $layerPtr close return $pairs } } ;#end of namespace command mapserver-6.4.1/mapscript/tcl/examples/0000755002461700001440000000000012261257215017716 5ustar tbonfortusersmapserver-6.4.1/mapscript/tcl/examples/shpinfo.tcl0000755002461700001440000000136212261257215022075 0ustar tbonfortusers#!/usr/local/bin/tclsh8.3 # if running a test before install, include directory to find package lappend auto_path [pwd]/.. package require Mapscript array set types { 1 point 3 arc 5 polygon 8 multipoint } set file $argv if {! [file isfile $file.shp]} { puts "shapefile \"$file\" not found" puts "usage: $argv0 " exit } mapscript::shapefileObj shp1 $file -1 puts "\nShapefile $file:\n" puts "\ttype: $types([shp1 cget -type])" puts "\tnumber of features: [shp1 cget -numshapes]" set rectPtr [shp1 cget -bounds] puts "\tbounds: ([mapscript::rectObjRef $rectPtr cget -minx],[mapscript::rectObjRef $rectPtr cget -miny]) ([mapscript::rectObjRef $rectPtr cget -maxx],[mapscript::rectObjRef $rectPtr cget -maxy])" mapserver-6.4.1/mapscript/tcl/configure0000755002461700001440000001076212261257215020015 0ustar tbonfortusers#!/bin/sh # not a normal autoconf configure script # grab the file ../../perlvars that mapserver made for the perl mapscript # build, and use gcc and ld flags if [ ! -f ../../perlvars ] ; then echo "you must build MapServer first." exit fi MAPSERVERHOME=`head -1 ../../mapscriptvars | tail -1` MAPSERVERDEFS=`head -2 ../../mapscriptvars | tail -1` MAPSERVERINCS=`head -3 ../../mapscriptvars | tail -1` MAPSERVERLIBS=`head -4 ../../mapscriptvars | tail -1` # make sure link to mapscript.i exists if [ ! -f mapscript.i ] ; then ln -s ../mapscript.i mapscript.i fi # check for --with-tcl= and/or --with-swig= with_tcl=/usr/local with_swig=/usr/local with_linker_cc=no for arg in $* do case $arg in --help) echo "mapscript tcl configure options:" echo "--with-tcl=dir where to find tcl (lib/tclConfig.sh)" echo "--with-swig=dir where to find swig (include/swig.h)" echo "--with-linker-cc use the compiler as linker front-end \ (see README)" exit ;; --with-tcl=*) save_if=$IFS IFS== set -- $arg with_tcl=$2 IFS=$save_ifs ;; --with-swig=*) save_if=$IFS IFS== set -- $arg with_swig=$2 IFS=$save_ifs ;; --with-linker-cc) with_linker_cc=yes ;; esac done # look for Tcl configs echo "looking for Tcl in $with_tcl" if [ ! -f $with_tcl/lib/tclConfig.sh ] ; then echo "can not find tclConfig.sh in $with_tcl" exit fi echo " found lib/tclConfig.sh in $with_tcl" # look for swig echo "looking for Swig in $with_swig" if [ ! -f $with_swig/include/swig.h ] ; then echo "can not find swig.h in $with_swig/include" echo "using pre-built swig tcl interface" # mapscript_wrap.c included in package else echo " found include/swig.h in $with_swig" fi SWIGDIR=$with_swig # source the tcl Configs . $with_tcl/lib/tclConfig.sh echo "tcl version = $TCL_VERSION" # if --with-linker-cc option set, then change ld command to use TCL_CC if test "$with_linker_cc" = "yes" ; then # get cc command, without any options that may be present eval set -- $TCL_CC cc="$1" # get any linker command options eval set -- $TCL_SHLIB_LD shift # build the new command using cc and linker options TCL_SHLIB_LD="$cc $*" fi # ugh. Tcl's tclConfig.sh only provides TCL_LD_SEARCH_FLAGS appropriate for # use with 'cc'. if 'ld' is the shared library loader, the flags # might be wrong, try to fix. this problem is often found on # Solaris, HP-UX, IRIX, {Free,Open,Net}BSD, OSF, Dec/Compaq Unix # first, get the shared lib loader command, should be ld or *cc eval set -- $TCL_SHLIB_LD ldcmd=`basename $1` if test "$ldcmd" = "ld" ; then # this machine uses ld, now see if a flag begins with -Wl newarg="" eval set -- $TCL_LD_SEARCH_FLAGS space="" for arg in $* do case $TCL_LD_SEARCH_FLAGS in -Wl*) # yep, here's our problem child # strip off first arg, change "," to " " via sh set hack IFSsave="$IFS" IFS="," eval set -- $arg IFS="$IFSsave" shift arg="$*" ;; *) newarg="$newarg$space$arg" ;; esac space=" " done TCL_LD_SEARCH_FLAGS="$newarg" fi # also check for Solaris loader flags '-z text', which causes unresolved # link errors, because we're mixing -fPIC code (mapscript_wrap.o) with # non -fPIC code (libmap.a, etc.) the resulting libMapscript.so will be # mixed, so don't cause the link to fail. TCL_SHLIB_LD=`echo $TCL_SHLIB_LD | sed -e 's/-z text//'` # fix up LIB_RUNTIME_DIR for those systems that leave it out if test -z "$LIB_RUNTIME_DIR" ; then LIB_RUNTIME_DIR=$with_tcl/lib fi # create our Makefile echo "creating Makefile" sed -e "s%@MAPSERVERHOME@%$MAPSERVERHOME%g" \ -e "s%@MAPSERVERDEFS@%$MAPSERVERDEFS%g" \ -e "s%@MAPSERVERINCS@%$MAPSERVERINCS%g" \ -e "s%@MAPSERVERLIBS@%$MAPSERVERLIBS%g" \ -e "s%@TCL_PREFIX@%$TCL_PREFIX%g" \ -e "s%@TCL_EXEC_PREFIX@%$TCL_EXEC_PREFIX%g" \ -e "s%@TCL_CC@%$TCL_CC%g" \ -e "s%@TCL_DEFS@%$TCL_DEFS%g" \ -e "s%@TCL_SHLIB_SUFFIX@%$TCL_SHLIB_SUFFIX%g" \ -e "s%@TCL_SHLIB_CFLAGS@%$TCL_SHLIB_CFLAGS%g" \ -e "s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g" \ -e "s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g" \ -e "s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g" \ -e "s%@TCL_STUB_LIB_SPEC@%$TCL_STUB_LIB_SPEC%g" \ -e "s%@TCL_LIBS@%$TCL_LIBS%g" \ -e "s%@LIB_RUNTIME_DIR@%$LIB_RUNTIME_DIR%g" \ -e "s%@TCL_DBGX@%$TCL_DBGX%g" \ -e "s%@SWIGDIR@%$SWIGDIR%g" \ Makefile mapserver-6.4.1/mapscript/tcl/mapscriptsupp.html0000644002461700001440000000754012261257215021706 0ustar tbonfortusers mapscript_supp.c

mapscriptsupp.tcl


Mapscript Supplemental Procedures

  • 1. proc mapscript::classObjRef
  • 2. proc mapscript::colorObjRef
  • 3. proc mapscript::errorObjRef
  • 4. proc mapscript::featureListNodeObjRef
  • 5. proc mapscript::itemObjRef
  • 6. proc mapscript::labelCacheMemberObjRef
  • 7. proc mapscript::labelCacheObjRef
  • 8. proc mapscript::labelObjRef
  • 9. proc mapscript::layerObjRef
  • 10. proc mapscript::legendObjRef
  • 11. proc mapscript::lineObjRef
  • 12. proc mapscript::mapObjRef
  • 13. proc mapscript::markerCacheMemberObjRef
  • 14. proc mapscript::pointObjRef
  • 15. proc mapscript::projectionObjRef
  • 16. proc mapscript::queryMapObjRef
  • 17. proc mapscript::rectObjRef
  • 18. proc mapscript::referenceMapObjRef
  • 19. proc mapscript::resultCacheMemberObjRef
  • 20. proc mapscript::resultCacheObjRef
  • 21. proc mapscript::scalebarObjRef
  • 22. proc mapscript::shapeObjRef
  • 23. proc mapscript::shapefileObjRef
  • 24. proc mapscript::symbolSetObjRef
  • 25. proc mapscript::webObjRef
  • 26. proc mapscript::DBFInfoRef

Usage

These procedures allow methods to be invoked on object references (i.e., pointers), without having to convert a reference into an object. A valid object reference is required; procedures check for valid object types.

General syntax:

objectRefProc $objectPtr args

Sample:

set map [mapscript::mapObj -args $mapFile]
set rectPtr [$map cget -extent]
set minx [mapscript::rectObjRef $rectPtr cget -minx]
set miny [mapscript::rectObjRef $rectPtr cget -miny]

Notes: each of the objectRef procedures is just a shortcut to invoke a SWIG generated method name. Method names of:

  • cget
  • configure
  • delete
invoke that object's cget, configure, and delete method respectively.

Example:

mapscript::rectObjRef $rectPtr cget -minx
is equivalent to:
mapscript::rectObj_minx_get $rectPtr

Mapscript Convenience Procedures

  • 1. proc mapscript::getDBFNames
  • 2. proc mapscript::getDBFTypes
  • 3. proc mapscript::getDBFValues
  • 4. proc mapscript::getQueryInfo

Usage

mapscript::getDBFNames DBFInfo_handle
getDBFNames returns a list of field names from a DBF file handle. The DBFInfo_handle must be a valid DBFInfo handle returned from the DBFInfo constructor.

mapscript::getDBFTypes DBFInfo_handle
getDBFTypes returns a list of field types and lengths from a DBF file handle. The DBFInfo_handle must be a valid DBFInfo handle returned from the DBFInfo constructor. Each list element is itself a list of field type and field length. Valid field types are returned as: string, integer, and double.

mapscript::getDBFValues DBFInfo_handle record_number
getDBFValues returns a list of field values from a DBF file handle. The DBFInfo_handle must be a valid DBFInfo handle returned from the DBFInfo constructor. Record_number is the record number of the row to fetch.

mapscript::getQueryInfo mapObj_pointer layerObj_pointer
getQueryInfo returns a list of name-value pairs from a layer that map query has generated. mapObj_pointer and queryObj_pointer must be valid mapObj and layerObj pointers.


See also

See mapscript_wrap.html for the full Mapscript Tcl interface.

Note also that the Mapscript objects described in mapscript_wrap.html are defined in the mapscript namespace.

Tom Poindexter
tpoindex@nyx.net
mapserver-6.4.1/mapscript/tcl/Makefile.in0000644002461700001440000000601612261257215020150 0ustar tbonfortusers# # Makefile.in for mapscript Tcl interface # Tom Poindexter, tpoindex@nyx.net # DLTARGET = libMapscript11 PACKAGEDIR = MapscriptTcl1.1 # Note: also change 'package provide' version in pkgIndex.tcl !! SWIGINC = -I@SWIGDIR@/include SWIGLIB = -L@SWIGDIR@/lib SWIGLIB_SPEC = -lswig TCL_PREFIX = @TCL_PREFIX@ TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@ TCL_CC = @TCL_CC@ TCL_DEFS = @TCL_DEFS@ TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@ TCL_SHLIB_CFLAGS = @TCL_SHLIB_CFLAGS@ TCL_LD_SEARCH_FLAGS = @TCL_LD_SEARCH_FLAGS@ TCL_SHLIB_LD = @TCL_SHLIB_LD@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_LIBS = @TCL_LIBS@ LIBS = @TCL_LIBS@ TCL_DBGX = @TCL_DBGX@ LIB_RUNTIME_DIR = @TCL_EXEC_PREFIX@/lib:@TCL_EXEC_PREFIX@/lib/$(PACKAGEDIR):@TCL_PREFIX@/lib:@MAPSERVERHOME@ MAPSERVERHOME = @MAPSERVERHOME@ MAPSERVERDEFS = @MAPSERVERDEFS@ MAPSERVERINCS = @MAPSERVERINCS@ MAPSERVERLIBS = @MAPSERVERLIBS@ # ugly alert! # see the README for this hack SWIG_STUB_HACK = -DUSE_TCL_STUBS -DITCL_NAMESPACES -DItcl_Namespace=int \ -D"spaceId=spcid;Tcl_InitStubs(interp,\"8.1\",0)" all: stublib stublib: mapscript_wrap.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ $(SWIG_STUB_HACK) \ mapscript_wrap.c $(TCL_SHLIB_LD) -o $(DLTARGET)$(TCL_SHLIB_SUFFIX) mapscript_wrap.o \ $(TCL_LD_SEARCH_FLAGS) \ $(TCL_STUB_LIB_SPEC) \ $(TCL_LIBS) \ -L$(MAPSERVERHOME) $(MAPSERVERLIBS) mapscript_wrap.c: swig -tcl8 -dhtml -namespace $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript.i nostublib: mapscript_wrap.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript_wrap.c $(TCL_SHLIB_LD) -o $(DLTARGET)$(TCL_SHLIB_SUFFIX) mapscript_wrap.o \ $(TCL_LD_SEARCH_FLAGS) \ $(TCL_LIB_SPEC) \ $(TCL_LIBS) \ -L$(MAPSERVERHOME) $(MAPSERVERLIBS) $(DLTARGET)$(TCL_SHLIB_SUFFIX): mapscript_wrap.o install: $(DLTARGET)$(TCL_SHLIB_SUFFIX) -mkdir $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp $(DLTARGET)$(TCL_SHLIB_SUFFIX) $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) chmod +x \ $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR)/$(DLTARGET)$(TCL_SHLIB_SUFFIX) cp pkgIndex.tcl $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp mapscriptsupp.tcl $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp mapscriptsupp.html $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp mapscript_wrap.html $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) useprebuilt: gunzip -c mapscript_wrap.c.gz >mapscript_wrap.c prebuilt: mapscript_wrap.c gzip -cf mapscript_wrap.c >mapscript_wrap.c.gz tar: if test ! -f mapscript_wrap.c.gz ; then \ gzip -cf mapscript_wrap.c >mapscript_wrap.c.gz; fi rm -f mapscript_wrap.c (cd ..; tar cf mapscript-tcl.tar tcl ) gzip -f ../mapscript-tcl.tar clean: rm -f *.o core *.so distclean: clean rm -f Makefile reallyclean: distclean rm -f mapscript_wrap.* mapserver-6.4.1/mapscript/csharp/0000755002461700001440000000000012261257215016576 5ustar tbonfortusersmapserver-6.4.1/mapscript/csharp/config/0000755002461700001440000000000012261257215020043 5ustar tbonfortusersmapserver-6.4.1/mapscript/csharp/config/AssemblyInfo.cs0000644002461700001440000001050612261257215022767 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapScript CSharp Assembly Information * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System.Reflection; using System.Runtime.CompilerServices; using System.Security; // // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. // [assembly: AssemblyTitle("mapscript")] [assembly: AssemblyDescription("MapScript C# Library")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.*")] // // In order to sign your assembly you must specify a key to use. Refer to the // Microsoft .NET Framework documentation for more information on assembly signing. // // Use the attributes below to control which key is used for signing. // // Notes: // (*) If no key is specified, the assembly is not signed. // (*) KeyName refers to a key that has been installed in the Crypto Service // Provider (CSP) on your machine. KeyFile refers to a file which contains // a key. // (*) If the KeyFile and the KeyName values are both specified, the // following processing occurs: // (1) If the KeyName can be found in the CSP, that key is used. // (2) If the KeyName does not exist and the KeyFile does exist, the key // in the KeyFile is installed into the CSP and used. // (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. // When specifying the KeyFile, the location of the KeyFile should be // relative to the project output directory which is // %Project Directory%\obj\. For example, if your KeyFile is // located in the project directory, you would specify the AssemblyKeyFile // attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] // (*) Delay Signing is an advanced option - see the Microsoft .NET Framework // documentation for more information on this. // [assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyFile("mapscript.snk")] [assembly: AssemblyKeyName("")] // The AllowPartiallyTrustedCallersAttribute requires the assembly to be signed with a strong name key. // This attribute is necessary since the control is called by either an intranet or Internet // Web page that should be running under restricted permissions. [assembly: AllowPartiallyTrustedCallers] // Use the .NET Framework 2.0 transparency rules (level 1 transparency) as default #if (CLR4) [assembly: SecurityRules(SecurityRuleSet.Level1)] #endifmapserver-6.4.1/mapscript/csharp/config/mapscript_csharp.dll.config0000644002461700001440000000013112261257215025341 0ustar tbonfortusers mapserver-6.4.1/mapscript/csharp/README0000644002461700001440000003305512261257215017464 0ustar tbonfortusers-- $Id$ The most recent version of this document can be found on http://mapserver.gis.umn.edu/docs/howto/mapscriptcscompile 1. Compilation ============== Before compiling C# mapscript you should compile mapserver with the options for your requirements. For more information about the compilation of mapserver please see `Win32 Compilation and Installation `__ . It is highly recommended to minimize the library dependency of your application, so when compiling mapserver enable only the features really needed. To compile the C# binding SWIG 1.3.27 or later is required. 1.1 Win32 compilation targeting the MS.NET framework 1.1 -------------------------------------------------------- You should compile mapserver, mapscript and all of the subsequent libraries using Visual Studio 2003. Download and uncompress the latest SWIGWIN package that contains the precompiled swig.exe Open the Visual Studio .NET 2003 Command Prompt and step into the /mapscript/csharp directory Edit makefile.vc and set the SWIG variable to the location of your swig.exe Use :: nmake -f makefile.vc to compile mapscript.dll and mapscript_csharp.dll. 1.2 Win32 compilation targeting the MS.NET framework 2.0 -------------------------------------------------------- You should compile mapserver, mapscript and all of the subsequent libraries using Visual Studio 2005. Download and uncompress the latest SWIGWIN package that contains the precompiled swig.exe Open the Visual Studio 2005 Command Prompt and step into the /mapscript/csharp directory Edit makefile.vc and set the SWIG variable to the location of your swig.exe Use :: nmake -f makefile.vc to compile mapscript.dll and mapscript_csharp.dll. 1.3 Win32 compilation targeting the MONO framework -------------------------------------------------- Before the compilation you should download and install the recent mono Win32 setup package (eg. mono-1.1.13.2-gtksharp-2.8.1-win32-1.exe) Edit makefile.vc and set the CSC variable to the location of your mcs.exe. Alternatively you can define :: MONO = YES In your nmake.opt file. You should use the same compiler for compiling mapscript as the compiler has been used for the mapserver compilation. To compile mapscript open the Command Prompt supplied with your compiler and use :: nmake -f makefile.vc to compile mapscript.dll and mapscript_csharp.dll. 1.4 Alternative compilation methods on Windows ---------------------------------------------- Beginning from mapserver 4.8.3 you can invoke the C# compilation from the mapserver directory by uncommenting DOT_NET in nmake.opt :: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # .NET/C# MapScript # ---------------------------------------------------------------------- # .NET will of course only work with MSVC 7.0 and 7.1. Also note that # you will definitely want USE_THREAD defined. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #DOT_NET = YES and invoking the compilation by :: nmake -f makefile.vc csharp You can also use :: nmake -f makefile.vc install for making the compilation an copying the targets into a common output directory. 1.5 Testing the compilation --------------------------- For testing the compilation and the runtime environment you can use :: nmake -f makefile.vc test within the csharp directory for starting the sample applications compiled previously. Before making the test the location of the corresponding libraries should be incuded in the system PATH. 1.6 Linux compilation targeting the MONO framework -------------------------------------------------- Before the compilation you should download and install the recent mono Linux package. Some distributions have precompiled binaries to install, but for using the latest version you might want to compile and install it from the source. Download and uncompress the latest SWIG release. You should probably compile it from the source if precompiled binaries are not available for your platform. Before compiling mapscript mapserver should be configured and compiled. Beginning from mapserver 4.8.2 during configuration the mapscript/csharp/Makefile will be created according to the configuration options. Edit this file and set the SWIG and CSC for the corresponding executable pathes if the files could not be accessed by default. To compile at a console step into the /mapscript/csharp directory use :: make to compile libmapscript.so and mapscript_csharp.dll. For testing the compilation and the runtime environment you can use :: make test for starting the sample applications compiled previously. 1.7 OSX compilation targeting the MONO framework ------------------------------------------------ Beginning from 4.10.0 the csharp/Makefile supports the OSX builds. Before making the build the recent MONO package should be installed on the system. Before compiling mapscript mapserver should be configured and compiled. Beginning from mapserver 4.8.2 during configuration the mapscript/csharp/Makefile will be created according to the configuration options. Edit this file and set the SWIG and CSC for the corresponding executable pathes if the files could not be accessed by default. To compile at a console step into the /mapscript/csharp directory use :: make to compile libmapscript.dylib and mapscript_csharp.dll. For testing the compilation and the runtime environment you can use :: make test for starting the sample applications compiled previously. To run the applications mapscript_csharp.dll.config is needed along with the mapscript_csharp.dll file. This file is created during the make process 2. Installation =============== The files required for your application should be manually installed. It is highly recommended to copy the files into the same folder as the executable resides. 3. Known issues =============== 3.1 Visual Studio 2005 requires a manifest file to load the CRT native assembly wrapper --------------------------------------------------------------------------------------- If you have compiled mapserver for using the CRT libraries and you are using the MS.NET framework 2.0 as the execution runtime you should supply a proper manifest file along with your executable, like: :: UMOlhUBGeKRrrg9DaaPNgyhRjyM= This will inform the CLR that your exe depends on the CRT and the proper assembly wrapper is to be used. If you are using the IDE the manifest file could be pregenerated by adding a reference to Microsoft.VC80.CRT.manifest within the /Microsoft Visual Studio 8/VC/redist/x86/Microsoft.VC80.CRT directory. 3.2 Manifests for the dll-s must be embedded as a resource ---------------------------------------------------------- According to the windows makefile the mapscript compilation target (mapscript.dll) is linked with the /MD option. In this case the VS2005 linker will generate a manifest file containing the unmanaged assembly dependency. The sample contents of the manifest file are: :: Like previously mentioned if you are creating a windows application the common language runtime will search for a manifest file for the application. The name of the manifest file should be the same as the executable appendend with the .manifest extension. However if the host process is not controlled by you (like web mapping applications using aspnet_wp.exe as the host process) you will not be certain if the host process (.exe) will have a manifest containing a reference to the CRT wrapper. In this case you may have to embed the manifest into the dll as a resource using the mt tool like: :: mt /manifest mapscript.dll.manifest /outputresource:mapscript.dll;#2 the common language runtime will search for the embedded resource and load the CRT assembly properly. Normally it is enough to load the CRT with the root dll (mapscript.dll), but it is not harmful embedding the manifest into the dependent libraries as well. 3.3 Issue with regex and Visual Studio 2005 ------------------------------------------- When compiling with Microsoft Visual Studio 2005 variable name collision may occur between regex.c and crtdefs.h. For more details see: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1651 3.4 C# mapscript library name mapping with MONO ----------------------------------------------- Using the mapscript interface created by the SWIG interface generator the communication between the C# wrapper classes (mapscript_csharp.dll) and the C code (mapscript.dll) takes place using platform invoke like: :: [DllImport("mapscript", EntryPoint="CSharp_new_mapObj")] public static extern IntPtr new_mapObj(string jarg1); The DllImport declaration contains the library name, however to transform the library name into a file name is platform dependent. On Windows the library name is simply appended with the .dll extension (mapscript.dll). On the Unix systems the library file name normally starts with the lib prefix and appended with the .so extension (libmapscript.so). Mapping of the library name may be manually controlled using a dll.config file. This simply maps the library file the DllImport is looking for to its unix equivalent. The file normally contains the following information (mapscript_csharp.dll.config): :: and with the OSX builds: :: The file should be placed along with the corresponding mapscript_csharp.dll file, and created by default during the make process. For more information see: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1596 http://www.mono-project.com/Interop_with_Native_Libraries 3.5 Localization issues with MONO/Linux --------------------------------------- According to http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1762 mapserver may not operate equally well on different locale settings. Especially when the decimal separator is other than "." inside the locale of the process may cause parse errors when the mapfile contains float numbers. Since the MONO process takes over the locale settings of the environment it is worth considering to set the default locale to "C" of the host process, like: :: LC_ALL=C mono ./drawmap.exe ../../tests/test.map test_csharp.png 4. Most frequent errors ======================= This chapter will summarize the most frequent problems the user can run into. The issues were collected mainly from the -users list and the IRC. 4.1 Unable to load dll (mapscript) ---------------------------------- You can get this problem on Windows and in most cases it can be dedicated to a missing or an unloadable shared library. The error message talks about mapscript.dll but surely one or more of the dll-s are missing that libmap.dll depends on. So firstly you might want to check for the dependencies of your libmap.dll in your application directory. You can use the Visual Studio Dependency Walker to accomplish this task. You can also use a file monitoring tool (like SysInternal's filemon) to detect the dll-s that could not be loaded. I propose to store all of the dll-s required by your application in the application folder. If you can run the drawmap C# sample application with your mapfile your compilation might be correct and all of the dlls are available. You may find that the mapscript C# interface behaves differently for the desktop and the ASP.NET applications. Although you can run the drawmap sample correctly you may encounter the dll loading problem with the ASP.NET applications. When creating an ASP.NET project your application folder will be '\Inetpub\wwwroot\[YourApp]\bin' by default. The host process of the application will aspnet_wp.exe or w3wp.exe depending on your system. The application will run under a different security context than the interactive user (under the context of the ASPNET user by default). When placing the dll-s outside of your application directory you should consider that the PATH environment variable may differ between the interactive and the ASPNET user and/or you may not have enough permission to access a dll outside of your application folder. 5. Bug reports ============== If you find a problem dedicated to the mapscript C# interface feel free to file a bug report to BugZilla. mapserver-6.4.1/mapscript/csharp/CMakeLists.txt0000644002461700001440000000650212261257215021341 0ustar tbonfortusersFIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PROGRAM (CSHARP_COMPILER NAMES csc gmcs gmcs2) IF (CSHARP_COMPILER) MESSAGE(STATUS "Found CSharp compiler: ${CSHARP_COMPILER}") ELSE (CSHARP_COMPILER) MESSAGE(FATAL_ERROR "Could not find csharp compiler") ENDIF (CSHARP_COMPILER) if (WIN32) if (NOT MSVC71) if (CMAKE_CL_64) set(PLATFORM_TARGET /platform:anycpu) else(CMAKE_CL_64) set(PLATFORM_TARGET /platform:x86) endif(CMAKE_CL_64) set (KEYFILE_SPEC /keyfile:${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\mapscript.snk) endif (NOT MSVC71) if (MSVC10) set(PLATFORM_TARGET ${PLATFORM_TARGET} /define:CLR4) endif (MSVC10) endif(WIN32) MARK_AS_ADVANCED(CSHARP_COMPILER) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/csharp) SET (CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}") SET( CMAKE_SWIG_FLAGS -namespace OSGeo.MapServer ${MAPSERVER_COMPILE_DEFINITIONS} -DWIN32) SWIG_ADD_MODULE(csharpmapscript csharp ../mapscript.i) set_target_properties(csharpmapscript PROPERTIES OUTPUT_NAME "mapscript") SWIG_LINK_LIBRARIES(csharpmapscript ${MAPSERVER_LIBMAPSERVER}) ADD_CUSTOM_COMMAND(TARGET csharpmapscript WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} POST_BUILD COMMAND copy /Y ..\\..\\..\\mapscript\\csharp\\mapscript.snk COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /t:library /out:mapscript_csharp.dll ${KEYFILE_SPEC} *.cs ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\config\\AssemblyInfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:shpdump.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\shpdump.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:drawmap.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmap.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:shapeinfo.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\shapeinfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:drawquery.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawquery.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:getbytes.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\getbytes.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:HTMLtemplate.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\HTMLtemplate.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:RFC24.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\RFC24.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirect.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirectPrint.cs COMMENT "Compiling c# source files" ) #get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_csharpmapscript_REAL_NAME} LOCATION) #install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION lib) mapserver-6.4.1/mapscript/csharp/Makefile.vc0000755002461700001440000000677612261257215020670 0ustar tbonfortusers# # makefile.vc - MSVC++ makefile for the C#/MapScript extension # # This VC++ makefile will build the PHP module CSHARP_MAPSCRIPT.DLL # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # # Flag indicating to the option files that this is the build of C#/MapScript !INCLUDE ../../nmake.opt # Be aware when setting different options for libmap.dll and mapscript.dll (Bug 1476) # To change the options for mapscript.dll uncomment the following line # otherwise the options of nmake.opt will be used #OPTFLAGS = /nologo /Zi /MD $(WARNING_LEVEL) $(DEBUG) BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 #LDFLAGS = /NODEFAULTLIB:msvcrt /NODEFAULTLIB:libcd /dll $(LDEBUG) LDFLAGS = /dll $(LDEBUG) CFLAGS = $(BASE_CFLAGS) $(MS_CFLAGS) -I../.. CC= cl LINK= link !IFDEF MS_DEBUG CSDEBUG = /debug:full !ELSE CSDEBUG = !ENDIF !IFDEF MONO CSC = mcs !ELSE !IF $(MSVC_VER) >= 1400 !IFDEF WIN64 CSC = csc /platform:anycpu $(CSDEBUG) !ELSE CSC = csc /platform:x86 $(CSDEBUG) !ENDIF !ELSE CSC = csc $(CSDEBUG) !ENDIF !ENDIF !IF $(MSVC_VER) >= 1600 CSC = $(CSC) /define:CLR4 !ENDIF #SWIG = swig !IFDEF DLLBUILD MS_LIBS = ../../mapserver_i.lib $(EXTERNAL_LIBS) !ELSE MS_LIBS = $(EXTERNAL_LIBS) ../../mapserver.lib !ENDIF # # The rest of the file should not have to be edited... # MAPSCRIPT_OBJS = mapscript_wrap.obj MAPSCRIPT_DLL = mapscript.dll CSHARP_DLL = mapscript_csharp.dll default: all all: interface $(MAPSCRIPT_DLL) $(CSHARP_DLL) sign: sn -k mapscript.snk interface: ../mapscript.i $(SWIG) -csharp -namespace OSGeo.MapServer $(MS_DEFS) -DWIN32 -o mapscript_wrap.c ../mapscript.i .c.obj: $(CC) $(CFLAGS) /DCOMPILE_DL=1 /c $*.c /Fo$*.obj $(MAPSCRIPT_DLL): $(MAPSCRIPT_OBJS) $(LINK) $(LDFLAGS) /out:$(MAPSCRIPT_DLL) $(MAPSCRIPT_OBJS) $(MS_LIBS) if exist $(MAPSCRIPT_DLL).manifest mt -manifest $(MAPSCRIPT_DLL).manifest -outputresource:$(MAPSCRIPT_DLL);2 $(CSHARP_DLL):: $(CSC) $(CSFLAGS) /t:library /out:mapscript_csharp.dll *.cs config\AssemblyInfo.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:shpdump.exe examples\shpdump.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:drawmap.exe examples\drawmap.cs # $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:inline.exe examples\inline.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:shapeinfo.exe examples\shapeinfo.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:drawquery.exe examples\drawquery.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:getbytes.exe examples\getbytes.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:HTMLtemplate.exe examples\HTMLtemplate.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:RFC24.exe examples\RFC24.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe examples\drawmapDirect.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe examples\drawmapDirectPrint.cs test: !IFDEF MONO mono shpdump.exe ../../tests/point.shp mono shapeinfo.exe ../../tests/point.shp # mono inline.exe aggpng24 inline_test.png mono getbytes.exe ../../tests/test.map test_csharp2.png mono RFC24.exe ../../tests/test.map !ELSE shpdump ../../tests/point.shp shapeinfo ../../tests/point.shp # inline png24 inline_test.png getbytes ../../tests/test.map test_csharp2.png RFC24.exe ../../tests/test.map !ENDIF clean: del *.obj del *.dll del *.lib del *.pdb del *.exp del *.ilk del *.cs del *.c del *.exe del *.manifest mapserver-6.4.1/mapscript/csharp/examples/0000755002461700001440000000000012261257215020414 5ustar tbonfortusersmapserver-6.4.1/mapscript/csharp/examples/drawmapDirect.cs0000644002461700001440000000721612261257215023537 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to draw the map directly onto a GDI * device context. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using System.Drawing; using System.Drawing.Imaging; using OSGeo.MapServer; ///

/// A C# based mapscript example to draw the map directly onto a GDI device context. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMapDirect {mapfile} {outfile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); mapObj map = new mapObj(args[0]); Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); for (int i = 0; i < map.numlayers; i++) { Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); } try { // Create the output format outputFormatObj of = new outputFormatObj("CAIRO/WINGDI", "cairowinGDI"); map.appendOutputFormat(of); map.selectOutputFormat("cairowinGDI"); Bitmap mapImage = new Bitmap(map.width, map.height, PixelFormat.Format32bppRgb); using (Graphics g = Graphics.FromImage(mapImage)) { IntPtr hdc = g.GetHdc(); try { // Attach the device to the outputformat for drawing of.attachDevice(hdc); // Drawing directly to the GDI context using (imageObj image = map.draw()) { }; } finally { of.attachDevice(IntPtr.Zero); g.ReleaseHdc(hdc); } } mapImage.Save(args[1]); } catch (Exception ex) { Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); Console.WriteLine( "\nHelpLink ---\n{0}", ex.HelpLink ); Console.WriteLine( "\nSource ---\n{0}", ex.Source ); Console.WriteLine( "\nStackTrace ---\n{0}", ex.StackTrace ); Console.WriteLine( "\nTargetSite ---\n{0}", ex.TargetSite ); } } } mapserver-6.4.1/mapscript/csharp/examples/HTMLtemplate.cs0000644002461700001440000000442712261257215023252 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to show the usage of HTML templates. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using OSGeo.MapServer; /// /// A C# based mapscript example to show the usage of HTML templates. /// class HTMLTemplate { public static void usage() { Console.WriteLine("usage: HTMLTemplate {mapfile} {templatefile} {outdir}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length < 3) usage(); mapObj map = new mapObj(args[0]); map.legend.template = args[1]; map.web.imagepath = args[2]; map.web.imageurl = ""; string str = null; string[] names = null, values = null; names = new string[] {"map"}; values = new string[] { args[0] }; str = map.processLegendTemplate(names, values); Console.Write(str); } } mapserver-6.4.1/mapscript/csharp/examples/shpdump.cs0000644002461700001440000000526612261257215022434 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based based mapscript example to dump information from * a shapefile. * Author: Tamas Szekeres, szekerest@gmail.com * Yew K Choo, ykchoo@geozervice.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using OSGeo.MapServer; /// /// A C# based mapscript mapscript to dump information from a shapefile. /// class ShapeDump { public static void usage() { Console.WriteLine("usage: shpdump {shapefile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length != 1) usage(); shapefileObj sf_obj = new shapefileObj(args[0],-1); shapeObj s_obj = new shapeObj(-1); for (int i=0; i /// A C# based mapscript mapscript example to create an image given a mapfile. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMap {mapfile} {outfile} {imagetype optional}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); mapObj m_obj = new mapObj(args[0]); if (args.Length >= 3) { Console.WriteLine("Setting the imagetype to " + args[2]); m_obj.setImageType(args[2]); } Console.WriteLine ("# Map layers " + m_obj.numlayers + "; Map name = " + m_obj.name); for (int i=0; i /// A C# based mapscript example to use the arribute query an highlight the results. /// class DrawQuery { public static void usage() { Console.WriteLine("usage: QueryMap {mapfile} {query string} {outfile} {-zoom}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 3 || args.Length > 4) usage(); bool ZoomToResults = (args.Length == 4 && args[3] == "-zoom"); mapObj map = new mapObj(args[0]); Console.WriteLine ("# Map layers " + map.numlayers + "; Map name = " + map.name); QueryByAttribute(args[1], map, ZoomToResults); map.querymap.status = mapscript.MS_ON; map.querymap.color.setRGB(0,0,255); map.querymap.style = (int)MS_QUERYMAP_STYLES.MS_HILITE; try { imageObj image = map.drawQuery(); image.save(args[2],map); } catch (Exception ex) { Console.WriteLine( "QueryMap: ", ex.Message ); } } private static bool IsLayerQueryable(layerObj layer) { if ( layer.type == MS_LAYER_TYPE.MS_LAYER_TILEINDEX ) return false; if(layer.template != null && layer.template.Length > 0) return true; for(int i=0; i 0) return true; } return false; } public static void QueryByAttribute(string qstring, mapObj map, bool zoomToResults) { Console.WriteLine("\nPerforming QueryByAttribute:"); try { layerObj layer; rectObj query_bounds = null; for (int i = 0; i < map.numlayers; i++) { layer = map.getLayer(i); if (layer.connection != null && IsLayerQueryable(layer)) { Console.WriteLine("Layer [" + i + "] name: " + layer.name); BuildQuery(layer, qstring); // zoom to the query results using (resultCacheObj results = layer.getResults()) { if (results != null && results.numresults > 0) { // calculating the extent of the results if (query_bounds == null) query_bounds = new rectObj(results.bounds.minx, results.bounds.miny, results.bounds.maxx, results.bounds.maxy,0); else { if (results.bounds.minx < query_bounds.minx) query_bounds.minx = results.bounds.minx; if (results.bounds.miny < query_bounds.miny) query_bounds.miny = results.bounds.miny; if (results.bounds.maxx > query_bounds.maxx) query_bounds.maxx = results.bounds.maxx; if (results.bounds.maxy > query_bounds.maxy) query_bounds.maxy = results.bounds.maxy; } } } } } // setting the map extent to the result bounds if (query_bounds != null) { if (zoomToResults) { map.setExtent(query_bounds.minx, query_bounds.miny, query_bounds.maxx, query_bounds.maxy); map.scaleExtent(1.2, 0, 0); // increasing the visible area Console.WriteLine("Current map scale: 1:" + (int)map.scaledenom); } } else Console.WriteLine("The query returned 0 results ..."); } catch (Exception e) { Console.WriteLine("QueryByAttribute: " + e.Message); } } private static void BuildQuery(layerObj layer, string qstring) { if (layer != null && layer.map != null) { /*layer.open(); string qs = ""; string att = ""; for (int i=0; i < layer.numitems; i++) { if (qs == "") { qs = "("; att = layer.getItem(i); } else { qs += " OR "; } qs += "'[" + layer.getItem(i) + "]'='" + qstring + "'"; } qs += ")"; layer.close();*/ string qs = qstring; string att = null; Console.WriteLine("Query string: " + qs); try { layer.queryByAttributes(layer.map, att, qs, 1); } catch (Exception e) { Console.WriteLine("BuildQuery: " + e.Message); } } } } mapserver-6.4.1/mapscript/csharp/examples/drawmapDirectPrint.cs0000644002461700001440000001054512261257215024553 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to draw the map directly onto a GDI * printing device context. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using System.Drawing; using System.Drawing.Printing; using OSGeo.MapServer; /// /// A C# based mapscript example to draw the map directly onto a GDI printing device context. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMapDirectPrint {mapfile} {printername}"); System.Environment.Exit(-1); } static mapObj map; public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); map = new mapObj(args[0]); Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); for (int i = 0; i < map.numlayers; i++) { Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); } try { PrintDocument doc = new PrintDocument(); doc.PrintPage += new PrintPageEventHandler(doc_PrintPage); // Specify the printer to use. doc.PrinterSettings.PrinterName = args[1]; doc.Print(); } catch (Exception ex) { Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); Console.WriteLine( "\nHelpLink ---\n{0}", ex.HelpLink ); Console.WriteLine( "\nSource ---\n{0}", ex.Source ); Console.WriteLine( "\nStackTrace ---\n{0}", ex.StackTrace ); Console.WriteLine( "\nTargetSite ---\n{0}", ex.TargetSite ); } } static void doc_PrintPage(object sender, PrintPageEventArgs e) { // Create the output format outputFormatObj of = new outputFormatObj("CAIRO/WINGDIPRINT", "cairowinGDIPrint"); map.appendOutputFormat(of); map.selectOutputFormat("cairowinGDIPrint"); map.resolution = e.Graphics.DpiX; Console.WriteLine("map resolution = " + map.resolution.ToString() + "DPI defresolution = " + map.defresolution.ToString() + " DPI"); // Calculating the desired image size to cover the entire area; map.width = Convert.ToInt32(e.PageBounds.Width * e.Graphics.DpiX / 100); map.height = Convert.ToInt32(e.PageBounds.Height * e.Graphics.DpiY / 100); Console.WriteLine("map size = " + map.width.ToString() + " * " + map.height.ToString() + " pixels"); IntPtr hdc = e.Graphics.GetHdc(); try { // Attach the device to the outputformat for drawing of.attachDevice(hdc); // Drawing directly to the GDI context using (imageObj image = map.draw()) { }; } finally { of.attachDevice(IntPtr.Zero); e.Graphics.ReleaseHdc(hdc); } e.HasMorePages = false; } } mapserver-6.4.1/mapscript/csharp/examples/getbytes.cs0000644002461700001440000000532712261257215022600 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to show the usage of * imageObj.getBytes. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using System.Drawing; using System.IO; using OSGeo.MapServer; /// /// A C# based mapscript example to show the usage of imageObj.getBytes. /// class GetBytes { public static void usage() { Console.WriteLine("usage: getbytes {mapfile} {outfile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length < 2) usage(); try { mapObj map = new mapObj(args[0]); using(imageObj image = map.draw()) { // solution 1 Console.WriteLine ("Drawing map: '" + map.name + "' using imageObj.getBytes"); byte[] img = image.getBytes(); using (MemoryStream ms = new MemoryStream(img)) { Image mapimage = Image.FromStream(ms); mapimage.Save(args[1]); } // solution 2 Console.WriteLine ("Drawing map: '" + map.name + "' using imageObj.write"); using (FileStream fs = File.Open("_" + args[1], FileMode.OpenOrCreate, FileAccess.ReadWrite)) { image.write(fs); } } } catch (Exception ex) { Console.WriteLine( "GetBytes: ", ex.Message ); } } } mapserver-6.4.1/mapscript/csharp/examples/shapeinfo.cs0000644002461700001440000000470112261257215022721 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based based mapscript example to dump information from * a shapefile. * Author: Tamas Szekeres, szekerest@gmail.com * Yew K Choo, ykchoo@geozervice.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using System.Collections; using OSGeo.MapServer; /// /// A C# based mapscript mapscript to dump information from a shapefile. /// class ShapeInfo { public static void usage() { Console.WriteLine("usage: shapeinfo {shapefile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length != 1) usage(); Hashtable ht = new Hashtable(); ht.Add(1,"point"); ht.Add(3,"arc"); ht.Add(5,"polygon"); ht.Add(8,"multipoint"); shapefileObj shpObj = new shapefileObj(args[0],-1); Console.WriteLine ("ShapeType = " + ht[shpObj.type]); Console.WriteLine ("Num shapes = " + shpObj.numshapes); Console.WriteLine ("(xmin, ymin) = (" + shpObj.bounds.minx + "," + shpObj.bounds.miny + ") (xmax, ymax) = (" + shpObj.bounds.maxx + "," + shpObj.bounds.maxy + ")"); } }mapserver-6.4.1/mapscript/csharp/examples/RFC24.cs0000644002461700001440000003471112261257215021531 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Tests for RFC24 implementation. * (http://mapserver.gis.umn.edu/development/rfc/ms-rfc-24/). * Author: Tamas Szekeres, szekerest@gmail.com * Umberto Nicoletti, umberto.nicoletti@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using OSGeo.MapServer; /** *

Title: Mapscript RFC24 tests.

*

Description: Tests for RFC24 implementation. (http://mapserver.gis.umn.edu/development/rfc/ms-rfc-24/)

* @author Umberto Nicoletti (umberto.nicoletti@gmail.com) */ class RFC24 { string mapfile; int fails = 0; public static void Main(string[] args) { new RFC24(args[0]).run(); } public RFC24(string mapfile) { this.mapfile=mapfile; } public void run() { Console.WriteLine("Running RFC24"); testLayerObj(); testLayerObjDestroy(); testClassObj(); testClassObjDestroy(); testInsertLayerObj(); testInsertLayerObjDestroy(); testRemoveLayerObj(); testInsertClassObj(); testInsertClassObjDestroy(); testRemoveClassObj(); testGetLayerObj(); testGetLayerObjDestroy(); testGetLayerObjByName(); testGetLayerObjByNameDestroy(); testGetClassObj(); testGetClassObjDestroy(); try { testStyleObj(); } catch (Exception e) { Console.WriteLine("\t- testStyleObj exception:" + e.Message); } testStyleObjDestroy(); try { testInsertStyleObj(); } catch (Exception e) { Console.WriteLine("\t- testInsertStyleObj exception:" + e.Message); } testInsertStyleObjDestroy(); testRemoveStyleObj(); try { testGetStyleObj(); } catch (Exception e) { Console.WriteLine("\t- testGetStyleObj exception:" + e.Message); } testGetStyleObjDestroy(); try { testlegendObj(); } catch (Exception e) { Console.WriteLine("\t- testlegendObj exception:" + e.Message); } try { testreferenceMapObj(); } catch (Exception e) { Console.WriteLine("\t- testreferenceMapObj exception:" + e.Message); } try { testwebObj(); } catch (Exception e) { Console.WriteLine("\t- testwebObj exception:" + e.Message); } try { testqueryMapObj(); } catch (Exception e) { Console.WriteLine("\t- testqueryMapObj exception:" + e.Message); } try { testmapObjHashTable(); } catch (Exception e) { Console.WriteLine("\t- testmapObjHashTable exception:" + e.Message); } try { testsymbolSetObj(); } catch (Exception e) { Console.WriteLine("\t- testsymbolSetObj exception:" + e.Message); } try { testimageObj(); } catch (Exception e) { Console.WriteLine("\t- testimageObj exception:" + e.Message); } if (fails > 0) Console.WriteLine("\n " + fails + " tests were FAILED!!!\n"); Console.WriteLine("Finished RFC24"); } public void testlegendObj() { mapObj map=new mapObj(mapfile); legendObj legend = map.legend; legend.template = "This is a sample!"; map=null; gc(); assert(legend.template == "This is a sample!", "testlegendObj"); } public void testmapObjHashTable() { mapObj map=new mapObj(mapfile); hashTableObj configoptions = map.configoptions; configoptions.set("key", "test value"); map=null; gc(); assert(configoptions.get("key", "") == "test value", "testmapObjHashTable"); } public void testsymbolSetObj() { mapObj map=new mapObj(mapfile); symbolSetObj symbolset = map.symbolset; symbolset.filename = "filename"; map=null; gc(); assert(symbolset.filename == "filename", "testsymbolSetObj"); } public void testreferenceMapObj() { mapObj map=new mapObj(mapfile); referenceMapObj refmap = map.reference; refmap.markername = "This is a sample!"; map=null; gc(); assert(refmap.markername == "This is a sample!", "testreferenceMapObj"); } public void testwebObj() { mapObj map=new mapObj(mapfile); webObj web = map.web; web.template = "This is a sample!"; map=null; gc(); assert(web.template == "This is a sample!", "testwebObj"); } public void testqueryMapObj() { mapObj map=new mapObj(mapfile); queryMapObj querymap = map.querymap; querymap.color.setHex( "#13ba88" ); map=null; gc(); assert(querymap.color.toHex() == "#13ba88", "testqueryMapObj"); } public void testimageObj() { mapObj map=new mapObj(mapfile); imageObj image = map.draw(); outputFormatObj format = image.format; format.setOption( "INTERLACE", "OFF"); map=null; gc(); assert(format.getOption("INTERLACE", "") == "OFF", "testimageObj"); } public void testLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(map); map=null; gc(); assertNotNull(newLayer.map, "testLayerObj"); assert(newLayer.refcount == 2, "testLayerObj refcount"); } public void testLayerObjDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(map); layerObj reference = map.getLayer(map.numlayers-1); assert(newLayer.refcount == 3, "testLayerObjDestroy precondition"); newLayer.Dispose(); // force the destruction for Mono on Windows because of the constructor overload newLayer = null; gc(); assert(reference.refcount == 2, "testLayerObjDestroy"); } public void testInsertLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,-1); map=null; gc(); assertNotNull(newLayer.map, "testInsertLayerObj"); assert(newLayer.refcount == 2, "testInsertLayerObj refcount"); } public void testInsertLayerObjDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,0); layerObj reference = map.getLayer(0); assert(newLayer.refcount == 3, "testInsertLayerObjDestroy precondition"); newLayer.Dispose(); // force the destruction for Mono on Windows because of the constructor overload newLayer=null; gc(); assert(reference.refcount == 2, "testInsertLayerObjDestroy"); } public void testRemoveLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,0); map.removeLayer(0); map=null; gc(); assert(newLayer.refcount == 1, "testRemoveLayerObj"); } public void testGetLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayer(1); map=null; gc(); assertNotNull(newLayer.map, "testGetLayerObj"); assert(newLayer.refcount == 2, "testGetLayerObj refcount"); } public void testGetLayerObjDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayer(1); layerObj reference = map.getLayer(1); assert(newLayer.refcount == 3, "testGetLayerObjDestroy precondition"); //newLayer.Dispose(); // force the destruction needed for Mono on Windows newLayer=null; gc(); assert(reference.refcount == 2, "testGetLayerObjDestroy"); } public void testGetLayerObjByName() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayerByName("POLYGON"); map=null; gc(); assertNotNull(newLayer.map, "testGetLayerObjByName"); assert(newLayer.refcount == 2, "testGetLayerObjByName refcount"); } public void testGetLayerObjByNameDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayerByName("POLYGON"); layerObj reference=map.getLayerByName("POLYGON"); assert(newLayer.refcount == 3, "testGetLayerObjByNameDestroy precondition"); //newLayer.Dispose(); // force the destruction needed for Mono on Windows newLayer=null; gc(); assert(reference.refcount == 2, "testGetLayerObjByNameDestroy"); } public void testClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(layer); map=null; layer=null; gc(); assertNotNull(newClass.layer, "testClassObj"); assert(newClass.refcount == 2, "testClassObj refcount"); } public void testClassObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(layer); classObj reference=layer.getClass(layer.numclasses-1); assert(newClass.refcount == 3, "testClassObjDestroy precondition"); newClass.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; newClass=null; gc(); assert(reference.refcount == 2, "testClassObjDestroy"); } public void testStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle=new styleObj(classobj); map=null; layer=null; classobj=null; gc(); assert(newStyle.refcount == 2, "testStyleObj"); } public void testStyleObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle=new styleObj(classobj); styleObj reference=classobj.getStyle(classobj.numstyles-1); assert(newStyle.refcount == 3, "testStyleObjDestroy"); newStyle.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; classobj=null; newStyle=null; gc(); assert(reference.refcount == 2, "testStyleObjDestroy"); } public void testInsertClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,-1); assertNotNull(newClass.layer, "testInsertClassObj precondition"); map=null; layer=null; gc(); assertNotNull(newClass.layer, "testInsertClassObj"); assert(newClass.refcount == 2, "testInsertClassObj refcount"); } public void testRemoveClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,0); layer.removeClass(0); map=null; layer=null; gc(); assert(newClass.refcount == 1, "testRemoveClassObj"); } public void testInsertClassObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,0); classObj reference = layer.getClass(0); assert(newClass.refcount == 3, "testInsertClassObjDestroy precondition"); newClass.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; newClass=null; gc(); assert(reference.refcount == 2, "testInsertClassObjDestroy"); } public void testInsertStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle = new styleObj(null); classobj.insertStyle(newStyle,-1); assert(newStyle.refcount == 2, "testInsertStyleObj precondition"); map=null; layer=null; classobj=null; gc(); assert(newStyle.refcount == 2, "testInsertStyleObj"); } public void testRemoveStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle = new styleObj(null); classobj.insertStyle(newStyle,0); classobj.removeStyle(0); map=null; layer=null; classobj=null; gc(); assert(newStyle.refcount == 1, "testRemoveStyleObj"); } public void testInsertStyleObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle = new styleObj(null); classobj.insertStyle(newStyle,0); styleObj reference = classobj.getStyle(0); assert(newStyle.refcount == 3, "testInsertStyleObjDestroy precondition"); newStyle.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; classobj=null; newStyle=null; gc(); assert(reference.refcount == 2, "testInsertStyleObjDestroy"); } public void testGetClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=layer.getClass(0); map=null; layer=null; gc(); assertNotNull(newClass.layer, "testGetClassObj"); assert(newClass.refcount == 2, "testGetClassObj refcount"); } public void testGetClassObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=layer.getClass(0); classObj reference = layer.getClass(0); assert(newClass.refcount == 3, "testGetClassObjDestroy precondition"); map=null; layer=null; newClass=null; gc(); assert(reference.refcount == 2, "testGetClassObjDestroy"); } public void testGetStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj style=classobj.getStyle(0); map=null; layer=null; classobj=null; gc(); assert(style.refcount == 2, "testGetStyleObj"); } public void testGetStyleObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj style=classobj.getStyle(0); styleObj reference=classobj.getStyle(0); assert(style.refcount == 3, "testGetStyleObjDestroy precondition"); map=null; layer=null; classobj=null; style=null; gc(); assert(reference.refcount == 2, "testGetStyleObjDestroy"); } public void gc() { for (int i=0; i<100; i++) { GC.Collect(); GC.WaitForPendingFinalizers(); } } public void assertNotNull(object o, string test) { if ( o != null ) Console.WriteLine("\t- "+test+" PASSED"); else { Console.WriteLine("\t- "+test+" FAILED"); ++fails; } } public void assert(bool val, string test) { if ( val ) Console.WriteLine("\t- "+test+" PASSED"); else { Console.WriteLine("\t- "+test+" FAILED"); ++fails; } } } mapserver-6.4.1/mapscript/csharp/examples/inline.cs0000644002461700001440000001301312261257215022217 0ustar tbonfortusers/****************************************************************************** * $Id: shapeinfo.cs 7418 2008-02-29 00:02:49Z nsavard $ * * Project: MapServer * Purpose: A C# based based mapscript example to dump information from * a shapefile. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ using System; using System.Collections; using OSGeo.MapServer; /// /// A MapScript application for creating inline layers with annotations. /// class Inline { public static void usage() { Console.WriteLine("usage: inline [outformat] [outfile]"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length < 2) usage(); // creating a new map from scratch mapObj map = new mapObj(null); // adding a layer layerObj layer = new layerObj(map); layer.type = MS_LAYER_TYPE.MS_LAYER_POINT; layer.status = mapscript.MS_ON; layer.connectiontype = MS_CONNECTION_TYPE.MS_INLINE; // define the attribute names from the inline layer layer.addProcessing("ITEMS=attribute1,attribute2,attribute3"); // define the class classObj classobj = new classObj(layer); classobj.template = "query"; // making the layer queryable // setting up the text based on multiple attributes classobj.setText("('Shape:' + '[attribute1]' + ' Color:' + '[attribute2]' + ' Size:' + '[attribute3]')"); // define the label classobj.label.outlinecolor = new colorObj(255, 255, 255, 0); classobj.label.force = mapscript.MS_TRUE; classobj.label.size = (double)MS_BITMAP_FONT_SIZES.MS_MEDIUM; classobj.label.position = (int)MS_POSITIONS_ENUM.MS_LC; classobj.label.wrap = ' '; // set up attribute binding classobj.label.setBinding((int)MS_LABEL_BINDING_ENUM.MS_LABEL_BINDING_COLOR, "attribute2"); // define the style styleObj style = new styleObj(classobj); style.color = new colorObj(0, 255, 255, 0); style.setBinding((int)MS_STYLE_BINDING_ENUM.MS_STYLE_BINDING_COLOR, "attribute2"); style.setBinding((int)MS_STYLE_BINDING_ENUM.MS_STYLE_BINDING_SIZE, "attribute3"); Random rand = new Random((int)DateTime.Now.ToFileTime()); ; // creating the shapes for (int i = 0; i < 10; i++) { shapeObj shape = new shapeObj((int)MS_SHAPE_TYPE.MS_SHAPE_POINT); // setting the shape attributes shape.initValues(4); shape.setValue(0, Convert.ToString(i)); shape.setValue(1, new colorObj(rand.Next(255), rand.Next(255), rand.Next(255), 0).toHex()); shape.setValue(2, Convert.ToString(rand.Next(25) + 5)); lineObj line = new lineObj(); line.add(new pointObj(rand.Next(400) + 25, rand.Next(400) + 25, 0, 0)); shape.add(line); layer.addFeature(shape); } map.width = 500; map.height = 500; map.setExtent(0,0,450,450); map.selectOutputFormat(args[0]); imageObj image = map.draw(); image.save(args[1], map); //perform a query layer.queryByRect(map, new rectObj(0, 0, 450, 450, 0)); resultObj res; shapeObj feature; using (resultCacheObj results = layer.getResults()) { if (results != null && results.numresults > 0) { // extracting the features found layer.open(); for (int j = 0; j < results.numresults; j++) { res = results.getResult(j); feature = layer.getShape(res); if (feature != null) { Console.WriteLine(" Feature: shapeindex=" + res.shapeindex + " tileindex=" + res.tileindex); for (int k = 0; k < layer.numitems; k++) { Console.Write(" " + layer.getItem(k)); Console.Write(" = "); Console.Write(feature.getValue(k)); Console.WriteLine(); } } } layer.close(); } } } }mapserver-6.4.1/mapscript/csharp/mapscript.snk0000644002461700001440000000112412261257215021313 0ustar tbonfortusers$RSA2gËäæ ¤Èmà/d]?gÕVX~?Í7ê½É0D4à;àkz(S̸/î1`±ÆF±DIÂ%&nἡ …k”ÀxúS,•y?Fws_æh=“öZ!–€†¤Åíûnï£]"•ôˆe·?Ä„aÈJþãMÕ¸ÊØuÂ3 „Ô*-þ¾@MÐû˜ šq”!èNzÃéàkøÙ E“¨Ú ŠÒ‹#ÇÛ€åЃ¦êLòjžyЃýëÏÁBŒ¼Õ2MŽâ‰o&n»÷y¼¯ø&ÈPáÄs”b™ß$sîÎç.’‰ ß{à¸= 0x010329 //#define ALLOW_INNER_EXCEPTIONS //#endif %ignore fp; /****************************************************************************** * Implement Equals and GetHashCode properly *****************************************************************************/ %typemap(cscode) SWIGTYPE %{ public override bool Equals(object obj) { if (obj == null) return false; if (this.GetType() != obj.GetType()) return false; return swigCPtr.Handle.Equals($csclassname.getCPtr(($csclassname)obj).Handle); } public override int GetHashCode() { return swigCPtr.Handle.GetHashCode(); } %} /****************************************************************************** * Module initialization helper (bug 1665) *****************************************************************************/ %pragma(csharp) imclasscode=%{ protected class $moduleHelper { static $moduleHelper() { $module.msSetup(); } ~$moduleHelper() { //$module.msCleanup(); } } protected static $moduleHelper the$moduleHelper = new $moduleHelper(); %} /****************************************************************************** * C# exception redefinition *****************************************************************************/ #ifdef ALLOW_INNER_EXCEPTIONS %exception { errorObj *ms_error; $action ms_error = msGetErrorObj(); if (ms_error != NULL && ms_error->code != MS_NOERR) { if (ms_error->code != MS_NOTFOUND && ms_error->code != -1) { int ms_errorcode = ms_error->code; while (ms_error!=NULL && ms_error->code != MS_NOERR) { char* msg = msAddErrorDisplayString(NULL, ms_error); if (msg) { SWIG_CSharpException(SWIG_SystemError, msg); free(msg); } else SWIG_CSharpException(SWIG_SystemError, "MapScript unknown error"); ms_error = ms_error->next; } msResetErrorList(); return $null; } msResetErrorList(); } } #else %exception { errorObj *ms_error; $action ms_error = msGetErrorObj(); if (ms_error != NULL && ms_error->code != MS_NOERR) { if (ms_error->code != MS_NOTFOUND && ms_error->code != -1) { char* msg = msGetErrorString(";"); if (msg) { SWIG_CSharpException(SWIG_SystemError, msg); free(msg); } else SWIG_CSharpException(SWIG_SystemError, "MapScript unknown error"); msResetErrorList(); return $null; } msResetErrorList(); } } #endif /****************************************************************************** * typemaps for string arrays (for supporting map templates) *****************************************************************************/ %pragma(csharp) imclasscode=%{ public class StringArrayMarshal : IDisposable { public readonly IntPtr[] _ar; public StringArrayMarshal(string[] ar) { _ar = new IntPtr[ar.Length]; for (int cx = 0; cx < _ar.Length; cx++) { _ar[cx] = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(ar[cx]); } } public virtual void Dispose() { for (int cx = 0; cx < _ar.Length; cx++) { System.Runtime.InteropServices.Marshal.FreeHGlobal(_ar[cx]); } GC.SuppressFinalize(this); } } %} %typemap(imtype, out="IntPtr") char** "IntPtr[]" %typemap(cstype) char** %{string[]%} %typemap(in) char** %{ $1 = ($1_ltype)$input; %} %typemap(out) char** %{ $result = $1; %} %typemap(csin) char** "new $modulePINVOKE.StringArrayMarshal($csinput)._ar" %typemap(csout, excode=SWIGEXCODE) char** { $excode throw new System.NotSupportedException("Returning string arrays is not implemented yet."); } %typemap(csvarin, excode=SWIGEXCODE2) char** %{ set { $excode throw new System.NotSupportedException("Setting string arrays is not supported now."); } %} /* specializations */ %typemap(csvarout, excode=SWIGEXCODE2) char** formatoptions %{ get { IntPtr cPtr = $imcall; IntPtr objPtr; string[] ret = new string[this.numformatoptions]; for(int cx = 0; cx < this.numformatoptions; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr))); ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr); } $excode return ret; } %} %typemap(csvarout, excode=SWIGEXCODE2) char** values %{ get { IntPtr cPtr = $imcall; IntPtr objPtr; string[] ret = new string[this.numvalues]; for(int cx = 0; cx < this.numvalues; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr))); ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr); } $excode return ret; } %} /****************************************************************************** * typemaps for outputFormatObj arrays *****************************************************************************/ %typemap(ctype) outputFormatObj** "void*" %typemap(imtype) outputFormatObj** "IntPtr" %typemap(cstype) outputFormatObj** "outputFormatObj[]" %typemap(out) outputFormatObj** %{ $result = $1; %} %typemap(csout, excode=SWIGEXCODE) outputFormatObj** { IntPtr cPtr = $imcall; IntPtr objPtr; outputFormatObj[] ret = new outputFormatObj[this.numoutputformats]; for(int cx = 0; cx < this.numoutputformats; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr))); ret[cx] = (objPtr == IntPtr.Zero) ? null : new outputFormatObj(objPtr, false, ThisOwn_false()); } $excode return ret; } %typemap(csvarout, excode=SWIGEXCODE2) outputFormatObj** %{ get { IntPtr cPtr = $imcall; IntPtr objPtr; outputFormatObj[] ret = new outputFormatObj[this.numoutputformats]; for(int cx = 0; cx < this.numoutputformats; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr))); ret[cx] = (objPtr == IntPtr.Zero) ? null : new outputFormatObj(objPtr, false, ThisOwn_false()); } $excode return ret; } %} /****************************************************************************** * gdBuffer Typemaps and helpers *****************************************************************************/ %pragma(csharp) imclasscode=%{ public delegate void SWIGByteArrayDelegate(IntPtr data, int size); %} %insert(runtime) %{ /* Callback for returning byte arrays to C# */ typedef void (SWIGSTDCALL* SWIG_CSharpByteArrayHelperCallback)(const unsigned char *, const int); /* Default callback interface */ static SWIG_CSharpByteArrayHelperCallback SWIG_csharp_bytearray_callback = NULL; %} %typemap(ctype) SWIG_CSharpByteArrayHelperCallback %{SWIG_CSharpByteArrayHelperCallback%} %typemap(imtype) SWIG_CSharpByteArrayHelperCallback %{SWIGByteArrayDelegate%} %typemap(cstype) SWIG_CSharpByteArrayHelperCallback %{$modulePINVOKE.SWIGByteArrayDelegate%} %typemap(in) SWIG_CSharpByteArrayHelperCallback %{ $1 = ($1_ltype)$input; %} %typemap(csin) SWIG_CSharpByteArrayHelperCallback "$csinput" %csmethodmodifiers getBytes "private"; %ignore imageObj::getBytes(); %extend imageObj { void getBytes(SWIG_CSharpByteArrayHelperCallback callback) { gdBuffer buffer; buffer.owns_data = MS_TRUE; buffer.data = msSaveImageBuffer(self, &buffer.size, self->format); if( buffer.data == NULL || buffer.size == 0 ) { msSetError(MS_MISCERR, "Failed to get image buffer", "getBytes"); return; } callback(buffer.data, buffer.size); msFree(buffer.data); } } %ignore imageObj::write; %typemap(cscode) imageObj, struct imageObj %{ private byte[] gdbuffer; private void CreateByteArray(IntPtr data, int size) { gdbuffer = new byte[size]; Marshal.Copy(data, gdbuffer, 0, size); } public byte[] getBytes() { getBytes(new $modulePINVOKE.SWIGByteArrayDelegate(this.CreateByteArray)); return gdbuffer; } public void write(System.IO.Stream stream) { getBytes(new $modulePINVOKE.SWIGByteArrayDelegate(this.CreateByteArray)); stream.Write(gdbuffer, 0, gdbuffer.Length); } %} %csmethodmodifiers processTemplate "private"; %csmethodmodifiers processLegendTemplate "private"; %csmethodmodifiers processQueryTemplate "private"; %typemap(cscode) mapObj, struct mapObj %{ public string processTemplate(int bGenerateImages, string[] names, string[] values) { if (names.Length != values.Length) throw new ArgumentException("Invalid array length specified!"); return processTemplate(bGenerateImages, names, values, values.Length); } public string processLegendTemplate(string[] names, string[] values) { if (names.Length != values.Length) throw new ArgumentException("Invalid array length specified!"); return processLegendTemplate(names, values, values.Length); } public string processQueryTemplate(string[] names, string[] values) { if (names.Length != values.Length) throw new ArgumentException("Invalid array length specified!"); return processQueryTemplate(names, values, values.Length); } %} %typemap(ctype) gdBuffer %{void%} %typemap(imtype) gdBuffer %{void%} %typemap(cstype) gdBuffer %{byte[]%} %typemap(out, null="") gdBuffer %{ SWIG_csharp_bytearray_callback($1.data, $1.size); if( $1.owns_data ) msFree($1.data); %} // SWIGEXCODE is a macro used by many other csout typemaps #ifdef SWIGEXCODE %typemap(csout, excode=SWIGEXCODE) gdBuffer { $imcall;$excode return $modulePINVOKE.GetBytes(); } #else %typemap(csout) gdBuffer { $imcall; return $modulePINVOKE.GetBytes(); } #endif %pragma(csharp) imclasscode=%{ protected class SWIGByteArrayHelper { public delegate void SWIGByteArrayDelegate(IntPtr data, int size); static SWIGByteArrayDelegate bytearrayDelegate = new SWIGByteArrayDelegate(CreateByteArray); [DllImport("$dllimport", EntryPoint="SWIGRegisterByteArrayCallback_$module")] public static extern void SWIGRegisterByteArrayCallback_mapscript(SWIGByteArrayDelegate bytearrayDelegate); static void CreateByteArray(IntPtr data, int size) { arraybuffer = new byte[size]; Marshal.Copy(data, arraybuffer, 0, size); } static SWIGByteArrayHelper() { SWIGRegisterByteArrayCallback_$module(bytearrayDelegate); } } protected static SWIGByteArrayHelper bytearrayHelper = new SWIGByteArrayHelper(); [ThreadStatic] private static byte[] arraybuffer; internal static byte[] GetBytes() { return arraybuffer; } %} %insert(runtime) %{ #ifdef __cplusplus extern "C" #endif #ifdef SWIGEXPORT SWIGEXPORT void SWIGSTDCALL SWIGRegisterByteArrayCallback_$module(SWIG_CSharpByteArrayHelperCallback callback) { SWIG_csharp_bytearray_callback = callback; } #else DllExport void SWIGSTDCALL SWIGRegisterByteArrayCallback_$module(SWIG_CSharpByteArrayHelperCallback callback) { SWIG_csharp_bytearray_callback = callback; } #endif %} /* Typemaps for pattern array */ %typemap(imtype) (double pattern[ANY]) "IntPtr" %typemap(cstype) (double pattern[ANY]) "double[]" %typemap(in) (double pattern[ANY]) %{ $1 = ($1_ltype)$input; %} %typemap(csin) (double pattern[ANY]) "$csinput" %typemap(csvarout, excode=SWIGEXCODE2) (double pattern[ANY]) %{ get { IntPtr cPtr = $imcall; double[] ret = new double[patternlength]; if (patternlength > 0) { System.Runtime.InteropServices.Marshal.Copy(cPtr, ret, 0, patternlength); } $excode return ret; } set { IntPtr cPtr = $imcall; if (value.Length > 0) { System.Runtime.InteropServices.Marshal.Copy(value, 0, cPtr, value.Length); } patternlength = value.Length; $excode } %} %typemap(csvarin, excode="") (double pattern[ANY]) %{$excode%} /* Typemaps for device handle */ %typemap(imtype) (void* device) %{IntPtr%} %typemap(cstype) (void* device) %{IntPtr%} %typemap(in) (void* device) %{ $1 = ($1_ltype)$input; %} %typemap(csin) (void* device) "$csinput" /****************************************************************************** * Preventing to take ownership of the memory when constructing objects * with parent objects (causing nullreference exception, Bug 1743) *****************************************************************************/ %typemap(csconstruct, excode=SWIGEXCODE) layerObj(mapObj map) %{: this($imcall, true, map) { $excode } %} %typemap(csconstruct, excode=SWIGEXCODE) classObj(layerObj layer) %{: this($imcall, true, layer) { $excode } %} %typemap(csconstruct, excode=SWIGEXCODE) styleObj(classObj parent_class) %{: this($imcall, true, parent_class) { $excode } %} %typemap(csout, excode=SWIGEXCODE) classObj* getClass, layerObj* getLayer, layerObj *getLayerByName, styleObj* getStyle { IntPtr cPtr = $imcall; $csclassname ret = (cPtr == IntPtr.Zero) ? null : new $csclassname(cPtr, $owner, ThisOwn_false());$excode return ret; } mapserver-6.4.1/mapscript/csharp/Makefile.in0000644002461700001440000000571412261257215020652 0ustar tbonfortusers# $Id$ # # Run ./configure in the main MapServer directory to turn this Makefile.in # into a proper Makefile # # If you want to ignore missing datafile errors uncomment the following # line. This is especially useful with large tiled datasets that may not # have complete data for each tile. # #IGNORE_MISSING_DATA=-DIGNORE_MISSING_DATA IGNORE_MISSING_DATA = @IGNORE_MISSING_DATA@ # # If you want to use shape Z and M parameter this option must be set. # It's OFF by default. # #USE_POINT_Z_M=-DUSE_POINT_Z_M USE_POINT_Z_M = @USE_POINT_Z_M@ # # Apparently these aren't as commonplace as I'd hoped. Edit the # following line to reflect the missing functions on your platform. # # STRINGS=-DNEED_STRCASECMP -DNEED_STRNCASECMP -DNEED_STRDUP -DNEED_STRLCAT STRINGS= @STRINGS@ # # Flags. # XTRALIBS= @XTRALIBS@ RUNPATHS= @RPATHS@ FLAGS = @DEBUG_FLAGS@ @ALL_ENABLED@ @ALL_INC@ $(STRINGS) $(IGNORE_MISSING_DATA) $(USE_POINT_Z_M) CCFLAGS = @CFLAGS@ $(FLAGS) # Link flags and shared libs only SUP_LIBS = @ALL_LIB@ # STATIC_LIBS is full filename with path of libs that will be statically linked STATIC_LIBS= $(GD_STATIC) LDFLAGS= $(RUNPATHS) -L../.. -lmapserver $(SUP_LIBS) $(STATIC_LIBS) LIBMAPSCRIPT_SHARED= libmapscript.@SO_EXT@ LD_SHARED= @LD_SHARED@ # END OF CONFIGURE---- # # SWIG Stuff # SWIG= swig # # CSHARP Stuff # CSC= mcs CC= @CC@ # # --- You shouldn't have to edit anything else. --- # all: interface mapscript_so mapscript_csharp sign: sn -k mapscript.snk interface: ../mapscript.i $(SWIG) -csharp -namespace OSGeo.MapServer $(FLAGS) -o mapscript_wrap.c ../mapscript.i mapscript_so: mapscript_wrap.c $(CC) -fpic -c $(CCFLAGS) mapscript_wrap.c $(LD_SHARED) mapscript_wrap.o -o $(LIBMAPSCRIPT_SHARED) $(LDFLAGS) mapscript_csharp:: $(CSC) /t:library /out:mapscript_csharp.dll *.cs config/AssemblyInfo.cs $(CSC) /r:mapscript_csharp.dll /out:shpdump.exe examples/shpdump.cs $(CSC) /r:mapscript_csharp.dll /out:shapeinfo.exe examples/shapeinfo.cs $(CSC) /r:mapscript_csharp.dll /out:drawmap.exe examples/drawmap.cs $(CSC) /r:mapscript_csharp.dll /out:inline.exe examples/inline.cs $(CSC) /r:mapscript_csharp.dll /out:drawquery.exe examples/drawquery.cs $(CSC) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:getbytes.exe examples/getbytes.cs $(CSC) /r:mapscript_csharp.dll /out:HTMLtemplate.exe examples/HTMLtemplate.cs $(CSC) /r:mapscript_csharp.dll /out:RFC24.exe examples/RFC24.cs dll_config: Makefile rm -rf mapscript_csharp.dll.config echo "" >> mapscript_csharp.dll.config echo "" >> mapscript_csharp.dll.config echo "" >> mapscript_csharp.dll.config clean: rm -rf edu *.o *.c *.cs *.@SO_EXT@ *.dll *.dll.config test: LC_ALL=C mono ./shpdump.exe ../../tests/point.shp LC_ALL=C mono ./shapeinfo.exe ../../tests/point.shp LC_ALL=C mono ./inline.exe png24 inline_test.png LC_ALL=C mono ./getbytes.exe ../../tests/test.map test_csharp2.png LC_ALL=C mono ./RFC24.exe ../../tests/test.map mapserver-6.4.1/mapscript/csharp/swig_csharp_extensions.i0000644002461700001440000002005212261257215023537 0ustar tbonfortusers /****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Fix for the SWIG Interface problems (early GC) * and implementing SWIGTYPE *DISOWN * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 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. *****************************************************************************/ // Ensure the class is not marked BeforeFieldInit causing memory corruption with CLR4 %pragma(csharp) imclasscode=%{ static $imclassname() { } %} %typemap(csout, excode=SWIGEXCODE) SWIGTYPE { /* %typemap(csout, excode=SWIGEXCODE) SWIGTYPE */ $&csclassname ret = new $&csclassname($imcall, true, null);$excode return ret; } %typemap(csout, excode=SWIGEXCODE, new="1") SWIGTYPE & { /* typemap(csout, excode=SWIGEXCODE, new="1") SWIGTYPE & */ $csclassname ret = new $csclassname($imcall, $owner, ThisOwn_$owner());$excode return ret; } %typemap(csout, excode=SWIGEXCODE, new="1") SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) { /* %typemap(csout, excode=SWIGEXCODE, new="1") SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) */ IntPtr cPtr = $imcall; $csclassname ret = (cPtr == IntPtr.Zero) ? null : new $csclassname(cPtr, $owner, ThisOwn_$owner());$excode return ret; } %typemap(csvarout, excode=SWIGEXCODE2) SWIGTYPE %{ /* %typemap(csvarout, excode=SWIGEXCODE2) SWIGTYPE */ get { $&csclassname ret = new $&csclassname($imcall, $owner, ThisOwn_$owner());$excode return ret; } %} %typemap(csvarout, excode=SWIGEXCODE2) SWIGTYPE & %{ /* %typemap(csvarout, excode=SWIGEXCODE2) SWIGTYPE & */ get { $csclassname ret = new $csclassname($imcall, $owner, ThisOwn_$owner());$excode return ret; } %} %typemap(csvarout, excode=SWIGEXCODE2) SWIGTYPE *, struct SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) %{ /* %typemap(csvarout, excode=SWIGEXCODE2) SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) */ get { IntPtr cPtr = $imcall; $csclassname ret = (cPtr == IntPtr.Zero) ? null : new $csclassname(cPtr, $owner, ThisOwn_$owner());$excode return ret; } %} %typemap(csout, excode=SWIGEXCODE) SWIGTYPE *& { /* %typemap(csout, excode=SWIGEXCODE) SWIGTYPE *& */ IntPtr cPtr = $imcall; $*csclassname ret = (cPtr == IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner, ThisOwn_$owner());$excode return ret; } // Proxy classes (base classes, ie, not derived classes) %typemap(csbody) SWIGTYPE %{ /* %typemap(csbody) SWIGTYPE */ private HandleRef swigCPtr; protected bool swigCMemOwn; protected object swigParentRef; protected static object ThisOwn_true() { return null; } protected object ThisOwn_false() { return this; } internal $csclassname(IntPtr cPtr, bool cMemoryOwn, object parent) { swigCMemOwn = cMemoryOwn; swigParentRef = parent; swigCPtr = new HandleRef(this, cPtr); } internal static HandleRef getCPtr($csclassname obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } internal static HandleRef getCPtrAndDisown($csclassname obj, object parent) { if (obj != null) { obj.swigCMemOwn = false; obj.swigParentRef = parent; return obj.swigCPtr; } else { return new HandleRef(null, IntPtr.Zero); } } internal static HandleRef getCPtrAndSetReference($csclassname obj, object parent) { if (obj != null) { obj.swigParentRef = parent; return obj.swigCPtr; } else { return new HandleRef(null, IntPtr.Zero); } } %} // Derived proxy classes %typemap(csbody_derived) SWIGTYPE %{ /* %typemap(csbody_derived) SWIGTYPE */ private HandleRef swigCPtr; internal $csclassname(IntPtr cPtr, bool cMemoryOwn, object parent) : base($modulePINVOKE.$csclassnameUpcast(cPtr), cMemoryOwn, parent) { swigCPtr = new HandleRef(this, cPtr); } internal static HandleRef getCPtr($csclassname obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } internal static HandleRef getCPtrAndDisown($csclassname obj, object parent) { if (obj != null) { obj.swigCMemOwn = false; obj.swigParentRef = parent; return obj.swigCPtr; } else { return new HandleRef(null, IntPtr.Zero); } } internal static HandleRef getCPtrAndSetReference($csclassname obj, object parent) { if (obj != null) { obj.swigParentRef = parent; return obj.swigCPtr; } else { return new HandleRef(null, IntPtr.Zero); } } %} // Typewrapper classes %typemap(csbody) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{ /* %typemap(csbody) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) */ private HandleRef swigCPtr; internal $csclassname(IntPtr cPtr, bool futureUse, object parent) { swigCPtr = new HandleRef(this, cPtr); } protected $csclassname() { swigCPtr = new HandleRef(null, IntPtr.Zero); } internal static HandleRef getCPtr($csclassname obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } %} %typemap(csfinalize) SWIGTYPE %{ /* %typemap(csfinalize) SWIGTYPE */ ~$csclassname() { Dispose(); } %} %typemap(csconstruct, excode=SWIGEXCODE) SWIGTYPE %{: this($imcall, true, null) {$excode } %} %typemap(csdestruct, methodname="Dispose", methodmodifiers="public") SWIGTYPE { lock(this) { if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { swigCMemOwn = false; $imcall; } swigCPtr = new HandleRef(null, IntPtr.Zero); swigParentRef = null; GC.SuppressFinalize(this); } } %typemap(csdestruct_derived, methodname="Dispose", methodmodifiers="public") TYPE { lock(this) { if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { swigCMemOwn = false; $imcall; } swigCPtr = new HandleRef(null, IntPtr.Zero); swigParentRef = null; GC.SuppressFinalize(this); base.Dispose(); } } %typemap(csin) SWIGTYPE *DISOWN "$csclassname.getCPtrAndDisown($csinput, ThisOwn_false())" %typemap(csin) SWIGTYPE *SETREFERENCE "$csclassname.getCPtrAndSetReference($csinput, ThisOwn_false())" %pragma(csharp) modulecode=%{ /* %pragma(csharp) modulecode */ internal class $moduleObject : IDisposable { public virtual void Dispose() { } } internal static $moduleObject the$moduleObject = new $moduleObject(); protected static object ThisOwn_true() { return null; } protected static object ThisOwn_false() { return the$moduleObject; } [DllImport("$dllimport", EntryPoint="SetEnvironmentVariable")] public static extern int SetEnvironmentVariable(string envstring); %} %insert(runtime) %{ #ifdef __cplusplus extern "C" #endif #ifdef SWIGEXPORT SWIGEXPORT int SWIGSTDCALL SetEnvironmentVariable(const char *envstring) { return putenv(envstring); } #else DllExport int SWIGSTDCALL SetEnvironmentVariable(const char *envstring) { return putenv(envstring); } #endif %} mapserver-6.4.1/mapscript/java/0000755002461700001440000000000012261257215016237 5ustar tbonfortusersmapserver-6.4.1/mapscript/java/makefile.vc0000644002461700001440000000534112261257215020351 0ustar tbonfortusers # # SWIG Stuff # #SWIG_HOME="D:\swig\SWIG-1.3.23\" <- should get this from ..\..\nmake.opt #SWIG=$(SWIG_HOME)\swig !INCLUDE ..\..\nmake.opt MS_LIB = mapscript.lib MS_LIB_DLL = mapscript_i.lib # # Java Stuff #JAVA_HOME = "C:\Progra~1\Java\jdk1.5.0" <- should get this from ..\..\nmake.opt JAVADOC=$(JAVA_HOME)\bin\javadoc JAVAC=$(JAVA_HOME)\bin\javac JAVA=$(JAVA_HOME)\bin\java JAR=$(JAVA_HOME)\bin\jar JAVA_INCLUDE=-I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32 CC= cl /MD LINK= link MS_DLL = javamapscript.dll BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 LDFLAGS = /NODEFAULTLIB:"MSVCRTD" /NODEFAULTLIB:libcd /NODEFAULTLIB:libcmtd /NODEFAULTLIB:msvcrtd /NODEFAULTLIB:LIBC /DEBUG all: interface_release mapscript_java mapscript_lib mapscript_jar interface_release: -md edu\umn\gis\mapscript $(SWIG) -java -package edu.umn.gis.mapscript -outdir edu/umn/gis/mapscript -o mapscript_wrap.c ../mapscript.i mapscript_java: $(JAVAC) edu\umn\gis\mapscript\*.java mapscript_wrap: $(CC) $(BASE_CFLAGS) $(MS_CFLAGS) $(JAVA_INCLUDE) /c mapscript_wrap.c /Fomapscript_wrap.obj .c.obj: $(CC) $(BASE_CFLAGS) $(MS_CFLAGS) $(JAVA_INCLUDE) /c $*.c /Fo$*.obj mapscript_lib: mapscript_wrap.obj link /dll /debug \ mapscript_wrap.obj $(EXTERNAL_LIBS) ..\..\mapserver_i.lib $(LDFLAGS) /def:..\..\mapserver.def \ /out:$(MS_DLL) /implib:$(MS_LIB_DLL) if exist $(MS_DLL).manifest mt -manifest $(MS_DLL).manifest -outputresource:$(MS_DLL);2 mapscript_javadoc: $(JAVADOC) -d doc -sourcepath edu/umn/gis/mapscript/*.java mapscript_jar: $(JAR) cf mapscript.jar edu test: $(JAVAC) -classpath ./mapscript.jar -d examples\ examples\*.java $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. DumpShp ../../tests/point.shp $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. ShapeInfo ..\..\tests\point.shp ..\..\tests\point.dbf $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. DrawMap ..\..\tests\test.map .\map.png $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. RFC24 ..\..\tests\test.map threadtests: $(JAVAC) -cp ./mapscript.jar -d tests/threadtest/ tests/threadtest/*.java @echo "-------------------------------------------------------------------------" @echo " You can use your own map! Copy the following command in your shell" @echo " and change the file to the map file (the last argument)" @echo "-------------------------------------------------------------------------" $(JAVA) -cp tests/threadtest/;./mapscript.jar -Djava.library.path=. MapTest -t 10 -i 5 ../../tests/test.map clean: -del *.obj -del *.lib -rmdir /s /q edu del $(MS_DLL) del $(MS_DLL).manifest del mapscript_wrap.c del mapscript.jar del *.ilk del *.pdb del *.exp mapserver-6.4.1/mapscript/java/run_test.sh0000755002461700001440000000453512261257215020450 0ustar tbonfortusers#!/bin/sh -ex JAVA=${JAVA_HOME}/bin/java JAVAC=${JAVA_HOME}/bin/javac ${JAVAC} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -d examples/ examples/RFC24.java examples/ConnPool.java examples/DrawMap.java examples/DumpShp.java examples/MakePoint.java examples/QueryByAttribute.java examples/ShapeInfo.java examples/WxSTest.java examples/Metadata.java examples/RunTimeBuiltWMSClient.java examples/WxSTestNoThread.java ${JAVAC} -encoding utf8 -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -d examples/ examples/QueryByAttributeUnicode.java ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} DumpShp ../../tests/point.shp ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} ShapeInfo ../../tests/point.shp ../../tests/point.dbf ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} DrawMap ../../tests/test.map ./map.png ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} ConnPool ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} QueryByAttribute ../../tests/test.map ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} WxSTest ../../tests/test.map ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} WxSTestNoThread ../../tests/test.map ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} RFC24 ../../tests/test.map LC_ALL=en_US.UTF-8 ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} QueryByAttributeUnicode data/subset-umlauts.map ${JAVAC} -cp ${JAVA_MAPSCRIPT_SO}/mapscript.jar -d tests/threadtest/ tests/threadtest/*.java #------------------------------------------------------------------------- # You can use your own map! Copy the following command in your shell # and change the file to the map file (the last argument) #------------------------------------------------------------------------- ${JAVA} -Djava.library.path=${JAVA_MAPSCRIPT_SO} -classpath tests/threadtest/:${JAVA_MAPSCRIPT_SO}/mapscript.jar MapTest -t 50 -i 5 ../../tests/test.map mapserver-6.4.1/mapscript/java/.gitignore0000644002461700001440000000001012261257215020216 0ustar tbonfortusers*.class mapserver-6.4.1/mapscript/java/data/0000755002461700001440000000000012261257215017150 5ustar tbonfortusersmapserver-6.4.1/mapscript/java/data/utf-subset.shx0000644002461700001440000000016412261257215021776 0ustar tbonfortusers' :è’zþp?ùIA•þk©F¶TA'Jøº_JAt¨Û?,UA2ttHAhmapserver-6.4.1/mapscript/java/data/emptymap.map0000644002461700001440000000014112261257215021477 0ustar tbonfortusersMAP NAME "Niedersachsen" EXTENT 3400000 5700000 3700000 6000000 SIZE 500 500 END mapserver-6.4.1/mapscript/java/data/iso-subset.dbf0000644002461700001440000000045712261257215021730 0ustar tbonfortusers_WKREIS_KENNCKREIS_NAMEC<EWN 07337 Südliche Weinstraße 109375 07339 Mainz-Bingen 194156mapserver-6.4.1/mapscript/java/data/iso-subset.shp0000644002461700001440000026555012261257215021776 0ustar tbonfortusers' µ´è’zþp?ùIA•þk©F¶TA'Jøº_JAt¨Û?,UAté-â JA•þk©F¶TAÄTJA儽ÅÏÛTAm ¸»}CJ/JAïX^/½TA»ÕºN/JA:L¸ ½TA¥TæN/JA¢\¯ù÷¼TA7HSôN/JAÁ ó¼TA˜µ—³X/JA9鸻üTAáZº^/JAóEV ¼TAj\’`/JAÍ…â—¼TAié¯\/JAôÜç¼TA²QYrZ/JA^Ú[Œ¼TA·;ÕX/JA˜²®‰¼TAÞV/JAßèyƒ¼TA!æËV/JAöÏY¼TAÿÀak/JAÒ®Wµ<¼TAÎHcN/JA>tv.¼TA;"0 W/JAæ–˜Q"¼TAóþàÉd/JA«Â…%¼TA<\^Bj/JAۇا¼TA‰ÛÓæw/JA<0jÔ¼TAkÎÜÝ~/JA`ͼTAÆr/JA¦µ¼TAÑ®›{z/JA$Àq-í»TAÚî±™/JA´²™Xæ»TA;¹pcŽ/JA¡§^ëá»TAe.™Ž/JAÔ§ú¬Ý»TAk°‘/JA|Ý’§Æ»TAíÐ /JAãCºpÁ»TAi ,’/JAº s„i»TAÈðÔ¬/JA´»Çæ%»TAÅw‡Ä½/JA|Q_ »TA¼z·è×/JAAÖ2ëºTA u>æ/JAhhIb׺TAÎøEþé/JA +0=κTA„`Sç/JAÒ¸µ½ºTA³E³æ/JA`µ6—ºTA|æ•Éì/JAßÄ[~ºTAâÆ¡Æï/JAÅ8nºTA bœù/JAe{Ñ‚VºTA£#WR0JAM•¹Ì)ºTA\¬Wµ0JAŸÝ’C$ºTAëhPÄ0JAÊÈá" ºTA =ë/0JAò.5ñ¹TAF»ì/JAÄ&»Ù¹TA+uï’Ü/JA†W¢¹TAa ÚkÜ/JAxTw–¹TAc«ø/JA?à‹®[¹TA>ô- ù/JA¯2%`H¹TAÂà±öÓ/JA@ž§%¹TAa§ îÊ/JA2 )ǹTAQݯ•Ç/JA›,.sù¸TA .ñÇ/JAà¬AظTA\BòÁÊ/JAÄ¿Ã^ǸTA!ŒÒ/JATßJµ¸TA=?nÙ/JAÖ8~¸TA|æ(èÙ/JA`¢ ¬„¸TAÜÚ!—Ø/JA²Ä¡d¸TAéú¬Ê/JAónB–-¸TA‘Süî‘/JAlT(ê¸TA@dk‚y/JAA; ˜ô·TAcørnc/JAá•÷ÑÝ·TAu£«r/JA|ë`Ù·TAJ¦F,/JA öu‘¹·TA.çÕ /JAQ!l㤷TA-§v¶.JA—u_#ƒ·TAg$™²¥.JAV›ÁžZ·TAáÑÖ§.JA×-ÕMG·TA”úØ®.JAjmþ/!·TA¢O%ެ.JAÚ³ ·TA}‚¤é©.JAg±Þù¶TAy‚ž¶.JAs>ð¶TAª`y%Ä.JA‘…ž[ç¶TAÀròúß.JAŠB…ͶTA¦I=/JA ì+ ¥¶TAç‰ä¥/JA ÐHŸ¶TAñ¸8ÿ.JA¿ ½Œ¶TA¬ÀöŒÿ.JAqcÂvo¶TA½Ahë /JAë:Ïœh¶TAš#Zö.JAšÐ` Z¶TA ìu2é.JA•þk©F¶TAþ¿µã.JAL¨=P¶TA{É"Þ.JA§ źT¶TA–©¾ Ö.JAq©|bX¶TAwiÎ.JAXµE™Y¶TAŨ².JAqŒ¾)V¶TAp?™N£.JA@—¼&V¶TAkƒt–.JA[Ý*W¶TAÌÅY.JA4•ÿY¶TAA×9‡.JApôñ[¶TAã68ƒ.JAkÌ&_¶TA¤9oùˆ.JAX¼d¶TA/+5‰.JAsÒWh¶TAе.JAuí±m¶TA»ÇÇ?k.JA£SˆLm¶TA\¦É `.JA‡94ýr¶TAaêâV[.JA禣x¶TA';AAl.JA`@ÏÎy¶TAkØ}‘s.JAÚ)ž|¶TA~2çi‚.JA{ݸ’¶TAŠÒÓ®}.JAí»™¶TA)”q.JA72#Ι¶TAÓÑp.JAÊ¡¶TAxas.JARŒ½œ¤¶TASÁäßy.JAcYîD¦¶TA>Œróy.JAw±I5¬¶TAÜl±j.JA­ÜŲ¶TAlõ0e.JA9ŠúUº¶TAÑ“àÐZ.JAug‘ÞÀ¶TA€ ˜™`.JAÝâ9|ʶTAhš]-K.JA˜~=Þ¶TAŽÉH.JAÁ…œ å¶TAlC«îH.JAÙOÿé¶TAÙšØM.JAf`ïï¶TAªêå=.JAmáïÑö¶TA½|±Z/.JA\eø¶TA<;+‰.JAWNW>ú¶TA¸Æëï-JAJgDè·TAhK¶è-JAMA]=·TAqâ©úß-JA½Â‰? ·TA½ä9`Ö-JAñ(·TAf*(Ç-JAùÀ«Ë·TA2g÷»-JA¯×g ·TA^àNé¢-JAçjÓm·TAl œÞ…-JAµÆ«Â·TA.rþz-JA;{y÷·TAždAx-JAî"² ·TA“Fq-JAüÎÕ"·TAFk¦i-JA) ²ƒ#·TAØÏÞs_-JAëÏúT&·TA4‡BP-JA·ˆ.·TA÷I-JAã±iº3·TA¿ªpÁB-JAÏð4Ž:·TArý<ˆ<-JAúŸNqI·TA¿ÔÌ/-JAr–…æQ·TAb²¾,-JA·:P\·TA×Ì–%-JAs\N%c·TAÅu¤Q#-JAjÃà j·TAd¯±-JAw%*p·TAn5Je-JA-&öv·TAâo-JAýù1Â{·TA÷û{¶-JA{T¤„·TAS­FI-JA±Ê¾‡·TAîÓyÚù,JAÄe%…·TA`ÕÔæ,JA/$þƒ·TAxÃ?Û,JA›ãô†·TAæA¸Ì,JA@³ú‚·TA;‹(Ç,JA}Jñõˆ·TA)q]¾,JA‚o» ·TAUvÕ›µ,JAh–’·TA„(2B¯,JA™·TAåíÖ\«,JAZ_`¢·TA:\%‡«,JAPü1­·TAùx˜›,JA”ÍAC··TA¥`‚,JA¤ÃØÅ·TAÊÚ´g,JAuä– Ø·TAœ×¸¢O,JAѺÜ·TAúž,=I,JAPvÃß·TAÖùH,JAÄScå·TAü6ª?,JA©Ç^uç·TA¬- ,JA¬Oõè·TA†ýÿ+JA…-åâ·TA“QÕ©ø+JA¿žúÜ·TAKÔ4ò+JAz¶mÛ·TA’¶%æ+JAaIˆÒÛ·TA© dëÞ+JAÙâ NÞ·TA3T ÉÃ+JAÖÜ‚ð·TA¨ÿJ¼+JA»5Cvò·TA´ÎÜŒ¸+JAh¼¾ñ·TA¶ñÌ¡+JA>Õæ0â·TAÈûΙ+JABq$yë·TA¨Ò‘+JA¥ í·TAŸÿ¦—+JAG¾]ø·TAñÙ'oŒ+JA@_¦(ý·TA`çJjˆ+JAÜÞ›Ÿÿ·TA³—–{+JAÎ.ŒK¸TA‘Þäq+JA ’X¸TA.õþp+JAÆd]äú·TAoCñ`+JAwÜ“Sý·TAöiüÙT+JAl‘®Óý·TA‹yðüK+JA‡´Jü·TAÑâ¾C+JA-c|ù·TAP7Ñ8+JAÂÔfú·TA °H 3+JA, 1ý·TAYÙ¬4+JA"áTðÿ·TA0ð0í?+JAë qõý·TA&“ÄD+JAQƒ^¸TAxÑëæH+JA¬ÅŠ´¸TAl[-+JAO¸TAm…“%+JAäošŒ ¸TAgÇÔ·+JA8GìϸTA+JA]\×=¸TAxÃÖ+JAˆ´ôò¸TAÅÔƒÒ+JA)ã È¸TA  +JAˆ¬¦g¸TAËÁ|Ùþ*JAd¤¸TA·ï¼û*JA;0­! ¸TAœ Œóí*JA0¸™Ã¸TAO"U3á*JA´Ñ¥¸TA«nŽøÕ*JAÆ0ïy¸TAêýó°*JA2ˆós¸TAYüšž*JAFü\_¸TA:Oꦄ*JA•`¸TA’ôÓ8z*JA`>Þg¸TAûçõÕg*JAÌz!¸TAÐë ]Q*JA¦À9%¸TA¥‹§ËG*JA.!g¦+¸TAz%Ùé>*JA8ºr!,¸TAq¥\Ð3*JA‚X±m5¸TA‘¸/*JA ?<¸TAµ=´(*JA!#LA¸TA‰Ns!*JAëmA¸TAE¯P‡*JATÐ6„?¸TA0ùÁZ*JAþs¬G¸TA‘˜*JAÂ÷îI¸TA6ª*JAJ¦¬iP¸TA„÷oH*JAx©ÞP¸TA.ɼ *JAس¥M¸TAæ»Þ{*JA-i_±M¸TAdbh}*JAs»O¸TAUNàþ÷)JA2ó]Ç[¸TAx‡·òë)JAþˆ×Y¸TA}ÎÔÛ)JA —ZX¸TAŠn Î)JA0õ S¸TAè›R(Å)JA[æÄR¸TA§`[¼¾)JA¹ï úS¸TAõFø÷±)JAòüi\¸TAn.®)JA"ÓÃa¸TAL üȯ)JACV÷h¸TAÒÕ{¤)JAmž„rg¸TAQl•¦i)JA-ƒ²qf¸TAÞÝ ¼d)JAL°_¸TAÝåzua)JAE‘o^¸TAõ#:Z)JAï/T_¸TAHcüÐS)JAÃaö`¸TAÁÌäO)JAÖÓtg¸TA®œ@J)JA>K~g¸TAa+Q4)JAù†–µ\¸TA¶öm+)JAöçz™[¸TA7¼êž")JA™¼¥]¸TA|=¡D)JAµ)©@c¸TA ®{-)JAR2íMc¸TAsS )JAi¬`¸TA>ËY<ó(JA¢ü•7b¸TAå;s}å(JAm•ß¶`¸TAåsÊ(JAª-ÕÄ^¸TA›Zû ±(JA0(Z¸TAͤçE’(JA`GW Z¸TAñ¿K‚(JA7VíY¸TAV[ŽLï¹TAÝt”&JAu”¶°Ý%JA/T~œA¹TA?Ó¨ºÙ%JA‹B³ÑD¹TAÅLå%JAô2léE¹TAB3:,í%JA“ˆªßN¹TA©¤7׿%JAýÙR¹TA9¹výÕ%JAd½JÐU¹TAæÕ •Ë%JA•öÒŸV¹TA’iA²Æ%JAÎ…ÀU¹TA¤#^ÛÅ%JAÕÇ5PR¹TAЋõÍ%JAÚŸÉÏM¹TAl.‹dÏ%JA v¹TA}!o=Ú$JAñRíIw¹TAdÈÈÏ$JA‰q!|¹TA`~ü³É$JAPod7‚¹TABBê-Â$JASéˉ¹TA5«X¹$JAùÔÞZ¹TA£ˆX²«$JAq÷q¹TAY³`ÃŽ$JAIÿ]Õ‹¹TA°Ÿšžz$JA @óHŒ¹TAFs€j$JAÍ?ֱйTAúÿ¦a$JA‘I’‡¹TAD~áóC$JAÜ£޹TA$A6$JAÖ)!–¹TAö~:Ã#$JAJ©1¹TA¸‡$JA‰”Lª‡¹TAÿQõ#JA0'÷>‰¹TA$‚©lã#JAZQ¢‹Œ¹TAÆ&Ø#JAsç~船TA©¼D¦Í#JAÐÖ¿,€¹TAKMÄŠÁ#JA¿Þz\y¹TAÉ_5þ¿#JA7³†S¹TAK+Ÿx±#JA¡²Œ"~¹TA%_•’œ#JA…qh¾}¹TAhÎqV™#JAW§“n{¹TA°x­[#JAþŠx¹TAѹr4®#JAÚZa^w¹TA0><²#JA¿Êãr¹TAÂ:þË’#JA¢Ci¹TAÜ­¬õ‰#JAZÚo¹TAuм~#JAæ7 ”p¹TA€Vî¥v#JA%¹6Xm¹TA@,Sg#JAŠ3öd¹TAˆXAê\#JA2¿‰6h¹TA ¼ç-G#JAŒJèÓg¹TAe|«RB#JA˜܆e¹TA¦éè?#JAñ(d_¹TAªÖ`Þ?#JAšÂ5ä[¹TAº¥!JAÞÝó›¹TAl þ¶!JAaaQ¤¹TA…r­·!JA¥6ǃ©¹TAÑH„=²!JA@JÖ“­¹TA]êåY¥!JAUuÿ¯¹TAãäI•!JA,á´¹TAžFЊ!JAõù¦¯¹TA-&™{!JAR1´¹TAàS«Kd!JAE¼Ž`½¹TASwYK\!JArpÏŹTAèš«$z!JA’J"”Ö¹TAgý>Ž!JA“êñ]Ó¹TAËg1Y–!JAÅG¹8ܹTA—(éö—!JAº´ÿÔá¹TA(»5—!JA&n_uç¹TAJs’!JA~u$ñ¹TA+gÃo‚!JAš•ºTA¦Xiño!JA§èò)ÿ¹TAοùîg!JA·bGºTA/t\¿`!JAºý­ ºTA£VWže!JAòéÆâºTA;ç)X!JAšSºTAM@QºL!JAæ›)ºTAs~°Rf%ºTA}›¶I!JA=±„?ºTA^ilK!JACq´+OºTAA»I!JAGüÏWºTA†‹;hC!JA@ǰXXºTA¦åŠ“6!JA¼— kVºTAFXÿ JABKn¨KºTAÇŸ'æ JAñDU!JºTAíFê_Ì JAÕæðJºTA”‹ªÌ¥ JA.מbUºTAñ Žˆ JA‚ÿÊ)cºTA¬·­ù JAŸA³…ºTAmd.ƒ– JA}«ûu—ºTAº›¿— JAýœ@‡šºTAYŸ¡k• JAÉcsÉ¥ºTAÊÕn¤ JA|‡áѳºTApÑï‡ JAáÝE¾ÄºTA{-ºö JAŪ_ÈкTA¨U×/ JA‰v'¾ØºTAú´a € JAu*àºTAW¦„ JA AIíºTAª`cƒ JAõ \íôºTA{­Æ^{ JAŸ…yXûºTA«¤ßè\ JAO7Ó »TA±±6âD JAQP…»TA$z LõJAÛh¿£»TA_ÚjêJA^Ä …»TA$·ÑJAîšC¼»TA8­ãY³JAŽep.»TAÓf‡¢JA¹¬»TA<‰IG,JAQUm »TA*ŸkJAG|à"»TAcj ] JA'Ìu¸5»TAWÅ w$JA§$ô@»TA¼SÁ+JAZ:T I»TAkœ°8JAð(%ÈS»TAí´ JA>v:¼Z»TAb†R JAï#J^»TA ÕrïJAß…2\^»TA}j%êJAü.ëÊh»TA¡|N\ØJALÌ,¨i»TA¬ÀãjÔJAw¶¾q»TA%|²½ÆJA=+¢}t»TAoÖõÕ­JAB;<Ôu»TA˜ -ñkJAîµ-X~»TA7€!aJA²ù3™»TA~KOJAUèØŠ»TAy´›8JA¬xÁ>»TAŸxÈJAm¯ª—»TA‹¿s‘JAvX§»TAå tJA`YQª¶»TA¤Ht$JAÒ#ôÀ¾»TA}qÒJA„¿ßÌ»TAÓ|`ÑJA4£¦îØ»TAyqªŽJAu¯ˆÝ»TAlÔJ–­JA–å¼TAªê̺œJAs»@=¼TAý‚ÿ°¡JAÝ4‚*¼TAKíp© JANn`:.¼TA|X>‰žJAýÅ5¼TANë?¤JAÖˆú@¼TAF=öJAé#à Q¼TA(›•ŸJA[s†[¼TA#[‡IJAùžšŠb¼TAÐòÇÜšJAW“˜ûi¼TA¾ÇˆJAÚTK©{¼TAÅ%4Î0JAªõv™v¼TAÞÐ|ë7JAœÝ(Zc¼TAMK*"JAÉŽb¼TAOqÿæJAL¯Bß]¼TAɉ$ÎJAƒð޲‘¼TAŒyJ#ÊJA-” .–¼TAE§‡z¬JA<`k¡¼TA>ã×qJAgtg¨¼TAô[Ý1dJAœgòÿ«¼TA×õTJAOç|6³¼TAröñ…JJA¨ÉÆw¶¼TAµ×ÕFJA±IÓ»¼TAeîEkùJARf¦CÀ¼TAû:ïJAâ¹íÁ¼TA"å‚–’JA¨ RüTAm¡%ùvJAWYdž¼TAïTë¾wJA{‘,—¼TAt[Jz€JAoí˜^ˆ¼TAêF†JAƒ7=|¼TAëïï[ˆJA_ìŸ@r¼TA®WÚ…JAû‹Ó)d¼TAþí1¿}JA†í$Z¼TAÆÌ­)JAé<5‘¼TA‚'¥JAwæk« ¼TAÊö½dðJA'|„ú»TAþ3—ÅÝJA©ýsHí»TAÉѵÕJAõS¨ æ»TA‹Æ”ÇJApx§Ñ»TA<Ž_ÁJAÅÆ»TA¡Û›³JA‰ ˜·»TA¢5|²ªJA/°»TAP%¡ªJAN½Ä³¨»TAÁhö¬JAj4(Ö™»TAªoC«JA0ú|M»TA÷K—¥JA¤¸r߉»TAD)!ŠJAbÁáw»TA÷Wo€JAƤ6lq»TAõ¶c|JAxqtÔk»TAìüó²zJA[;b»TA ðe0tJA~òfU»TAŒœ3ÆdJA©MOÐE»TA¡›|GZJAëømþ>»TA44þcQJAì\8X;»TAî+=|@JAc “À7»TAü§Ð¼&JAÛ(Ê_3»TA6Š\JA Ð-»TA­Nl üJA:µ|ç'»TAk×tÔJAH›7»TA"÷¥¾JA¡±…?»TA„œk½±JAíh ûºTAG_m¢JA|‰…÷ºTA L>KŽJAEþ¾póºTAN¢_JA¯¾ðdòºTAÀÀ24JA"ÓâîºTAôÝð„&JAOtîºTAå"þ JAÕÙxèºTAsìoèJA8QÇÚºTA _œ€äJA´fÂߺTA]^ÖWåJA„h)ÐçºTA¼‡ïJAi mõºTAÕÅejúJAϸ ±»TAB2ª~þJA¬¢žž»TAñ¶éDïJAð)ß²»TA_ 1ÛàJAqµÃ\»TA\3Ô‹ÑJAoñHÊ»TAò°™ÅJAÈ'¦»TAøÇ‰µJAÀ´[ »TA#•´û«JA–WO6,»TAGî?[žJA‡ÐÈC4»TAÙ²-Œ‰JA¯ZÚ”C»TAÅíýƒJAØ5¾L»TAøú GƒJA±ïÐùU»TAƒ/·r‹JAѸne»TAÍp¦JALÕÐìa»TA*üƒøôJAh¶Z»TA ¿ë&÷JAþöçØ`»TAFJùJAÃ_AYf»TAt;hÍúJADÖp»TA–}Z7JA¡`ä‚»TA³)u5JAm;9ÑŒ»TAW1(JA\DZ»TAs‹ØJAjxج»TAC]¿§àJA¡E²Â ¼TAÖü |ÝJA2#ÈD¼TA#Ä@/ßJAåV¼TAÍ:˜«ÙJAL’ Ž-¼TA'ÕžÂJA"ŠŽëN¼TA…ÈN°JAk#|´f¼TAˆå&¡JA“Û)`r¼TAµÎ6[˜JAíädz¼TA+, t˜JA®͆¼TA?¶ä’JA~Wú8¼TA Ì\*ŽJA>­ïš¼TAàßR~JAú7Ž ¼TAªÙ9]JA’NO¦¼TA§J÷JJAxiJ ¼TA„^ܸ JArœUX–¼TAª’íÈûJAÀì1•¼TA7‡›+îJA=¬, ˜¼TA$cðæJAßIÄÔ–¼TAK )½ÎJA¼ÁŠC¼TA=Í­ö¸JAÔ·xX…¼TAϬ»¦©JA0 J'€¼TA[@qB’JA|‰˜z¼TALÚŽtlJA“^~ u¼TAÜ`ße\JA-3t¼TA¨ëcPJAÁù¦fz¼TA™îÖµJA¬]¸f¼TA<-Ùo JAö¹Ã‹]¼TAàþ±öJAJA·E¼TA† úíJA뺒°<¼TAp$ûîìJA šœO4¼TA¦JÆKïJAwì¬.¼TA³ØžnöJApd%¼TAE#7/JAœÐíÔ¼TAù€ŠJAOŒ£"ÿ»TA–oŒ€!JA±Ü"õ»TAïzBk!JAÇpÿí»TA¹JA&ÝXÞá»TAyH@ÆJA¤°¡Ù»TA6"1üJA ô¹­Ì»TAo0 õôJAÐI Ì»TA 4N ÌJAëÜódÚ»TA¯}jºJAç_/¡á»TAí¾‘Ã°JAŠÂ#ä»TA_XÒ‡JA ÚæAè»TAA­\tuJAâ`F‡ì»TAúÊ»ÚUJAj2¼TA¼É¥6;JAÉŸÿ„0¼TA[&o JAŸWÅJ9¼TAŒ: IÇJA®nu•F¼TA6úc´JA6q,ûS¼TAÆ©€JAG£‚¼TA =rª†JAQÉÙÝŽ¼TAƒ&'±†JA°édùª¼TA™÷m»ˆJAÄ‘þι¼TA^Ž$›JA”yõ¤Ñ¼TAqrl¢JAÿ9aæ¼TA¤—¥JAÃkz•è¼TAqÜ#R«JAÉTï¼TA„³“®JAëòìŸö¼TAEg#‹¯JA‡Mv{½TA¥ŠL-®JA×4'½TA Vë³°JA©dRn2½TAþsû¼JAÝ´vP½TAßW_¨¾JAË*ø©W½TAÑë°Ä¿JA!kj}½TA…ClÃJAqò±‚½TA$?'-ÏJA+S½TAD%¡ñJArű ½TAɹ JAéëz™¬½TAE‰EkJA¬ÓÕ³½TA—Nf $JAbp¦ÙýTA¢ *JAtÖ÷àͽTAt *ž.JAÜ*sxÓ½TAéA§.JAdãF>ؽTA~OUª;JAóÚ”÷é½TA¢Œ¡P|JA ˜O÷¾TAz©Sþ«JAúêd";¾TAÓÙ’°JA<“A¾TAà÷ó»±JAg÷~ÂF¾TAÕW¨²JAáº×DS¾TA†ݵJAµ® ÚV¾TA¬ ¶ò¹JA_ê&Z¾TAk¨XÕJAÄpFBe¾TAøìßJA`üë;k¾TAQÖ 5ïJAר9y¾TA‡ðÝVJAs/lò¢¾TA{fSÓJAèUm…¨¾TAj žÞ JAŒý=«¾TAׂ±$JA êU­¾TA{K¹4JAѾG\±¾TAl¶q6JAn±µ¾TA¤"‹D+JA4å¾¾TA ±â(JAOàŸÂ¾TA嘊*JA`3ÓɾTA/-‡+JA޽Ÿ²Ü¾TAl×.1JA±¸Çuå¾TAúô9Ø2JA2Ìë¾TAGþ–4JA€eÔ-û¾TAÚHç7JA¦<,ý¿TAõðø–1JAi+d} ¿TA À¡}!JAvýˆ¿TA3bJAìºLÀ¿TA…òYâJA˜"èÛ!¿TA¢Q”ÆJAT^.¿TA>–+©§JAÊêH¶7¿TA· jüMJAS¹¶([¿TAîà yJAlŠ—š¿TAje†{JA8è`£¿TAï4UxJAÇ(¦¿TAÞðÈkJA¥i«¿TAsëâJAuQ¬†È¿TA€MûK%JAN’à¿TAÂÑ[m:JAiBÌý¿TA5ò?¼EJAïpyÀTA ¾u@mJAqÇuÀTA¸Ì`ŸJAfBOåAÀTAa ´ ¥JAú0 GÀTAiN΀§JA¹çAVLÀTAû¨¥JA·´PÀTA˜@ŒŸJAMWFÆTÀTA_þfO”JA*y²òYÀTA€äèJAÊ`ÀTAf)xFtJAæ “ºcÀTA{TlJA&3ØàhÀTAè6Ç^JA^Z@xÀTA*0ߎJAaY‡VsÀTAù°,¤¨JAÅÀ–uÀTA+­|.ÃJAÆ¥ÁTA§˜&QãJAJCTr\ÁTAIÑ•âJA&fbÁTA¬DâéJA’è»ëhÁTAÖm2\JAðGAÁTAiîAÒ3JA‹@Zc’ÁTAõMºÐJAv,0(ªÁTA0¿ÙJA~bˆ¹ÁTAee¯JA(½vÐÁTAb¯‰¸îJAÊxxSÍÁTAÏOpó·JAo·ÃÌÁTA4àºb¢JAçL‹ ÖÁTAÊn á˜JA¹"}ÞÁTA¥-xJAÑëŒÂTAÜò¤aJA#8Ü'ÂTArÑq xJA¹Ý+QÂTA·¦}‡JAبþpÂTA8ØìJA!k>ÂTAìE?œJA*ÃTARKRNJAc²!<ÃTA x~+îJAr©–N<ÃTAB]üdÅJA”‰é#&JAnÝ0ÃTA¾@ ¤ÆJAÒJäaVÃTAmÜÖMJA]- %gÃTA4Ä_“JAÐ(;gÃTA¤`@isJA78©VgÃTA‰ŒÅ?PJA©l%Ð`ÃTAOå"p+JAv¢ÚŠWÃTA‹)šhJAʬlFÃTAÄΧRáJAYw35ÃTAøèþé×JAOÑ0ÃTAê÷áÄJAÌ¡n7ÃTA}xaÔ‰JAE¥óVÃTA²mˆ6|JAw~JATò¬&¤ÃTAõJ,~JA¡{»‹§ÃTAè,0}JA4ŽÃÃTA¢6„$yJA‚êx&òÃTA”¥GÏVJAL%]ºÄTAO@ÁJA ÄTA¾~øµóJAßÄ'ÄTAu–ìJAá–M/ÄTAFÓ”\ÁJA1R6›kÄTA1Ÿ7¬JA$Ÿ©ŽÄTAì㌧JAp1é—ÄTAÞÆ:£JA#†-¶ÄTARV;èJAÕ‡iÇÄTAßnl(¢JA³ aÕÄTAº®é¶JA ZrÙÄTA™î×nJA« ÷LÝÄTA°še:@JA‹û7NàÄTAÎ:á¤JAü«KåÄTAÜ™]îJA©ïíÄTAÄfµ¼JAUص£øÄTAvXD¼JAÛ …ÞÅTA›2KŸJA±}4,ÅTAcåü ¦JAÇi»ãAÅTAL.¹·¯JAt¥WÒOÅTA|JZßÀJA¢5TÐ_ÅTA£íWÇJADùâ bÅTAð›ÎJA³ûkcÅTA)ÖW JA£„!eÅTAV`tõJAÑX¦iÅTA?¥opJAtí*‡kÅTAÍÙPæ JAÚ÷£†xÅTAH–ƒÃ²JA¨ÎåPƒÅTAÜ/-oÎJAdz Ò”ÅTAÂ! WØJA£ÀVÚ¢ÅTA4ËwÝJA¯ÑͱµÅTA•lü9âJAzØJ<ÃÅTA‚åJAQõ”aËÅTAAŠXÚJA'G&TêÅTA´âæJAxëvóÅTA."ÁJAðxÆTAvárJABÞËæ!ÆTA7!¸ÞJA­M&ÆTA•¹k¾ïJA¡ø× 8ÆTA­iOêJAѬãÆIÆTAAÅE©éJAn®8çKÆTAð~KJA®ÌÆðkÆTA,áÆwJA¤óÊlÆTA7\ÈJA.žvÆTAË&YwJAêšLO…ÆTA'®uJAѲ›ÆTA<öX‚JAJÅ;„¯ÆTAûN뽂JA‡0ºÆTA%†kœ{JA‰oŸßÂÆTA0TyJA·Þ­ÉÆTA¡ŽgJAWNøÒÆTA OçˆJAù²#ÞÆTA¼½‰‰JAàÌ7/äÆTA8Œ¹‚JAÊbsÞëÆTAH2qJAÄŽ(ˆóÆTA¾7ˆ fJA¢UJŽùÆTA¦X5UJAº ûIýÆTATþDUJA&zxÇTA+i †JA/ÏdÄÇTA ¤Æ’JA8 šþÇTA+@èé–JA ÝR"ÇTAÂ¥™˜JARÃDÎ6ÇTA4´5ޝJA~>ßË>ÇTA´D½ØJA·‡emKÇTAÕlR*ùJAÙpN[ÇTAvÂÂŽJA‚Fî°aÇTAXurYJAÈsYlÇTAÄ;¹’JA@át5xÇTA؇áE JAÕo¸ÇTAŒÂMJA=‰U‰dÇTA¯‹Ú•JAµƒwUÇTA@Yø¹JAºˆwÿOÇTAy êJAíàgJÇTAhòlÑJAoþ.rHÇTA5%@JAgôÄEÇTA ÑD^JAä!>)ÇTAdóDêbJAƒ¿í $ÇTAð_°GVJAÉgÒÐÆTAqMÙŒJAú½4OÉÆTAx(5b£JA»Ú|ÌÆTAÆTAš0AæJAó(†þÅTA¤ÀêôJA†–Š<ûÅTA'ÌoýJAÝßýÅTAo‚ë­7JAŸÝ¦õÆTA¾b± JAlšúÃÆTA¦3ÐÄJAׇø2ÆTAõ˜!{JAiÒÌGÆTAÖI"JAoÝOÆTAT&Æ5JAÎã-Ž\ÆTAsãRLJA¡àÆçhÆTA@YbJAb—Ö§qÆTA¼ì¨îkJA§tutÆTAâ+ÛJA{’Ë—yÆTA¹»ä»JAì× „ÆTA˜†€ö¿JAÎgb^‰ÆTAµEmNJAuͦ’ÆTAqfM˜JA†¨BÁ“ÆTAŒ{ò;2JAÓ}Ë¥ÀÆTA"uOÊöJA‡&ò#ÂÆTAqªº‚ÎJAÑŸ¸¾ÆTAö³8wÂJAÑiþÒÀÆTAÒ÷èO³JA®_'wÈÆTAS5²4°JA)ËÅFÏÆTA¶ø‚î±JAâ‰ÇÔÆTAý¾-n´JAžª±íÜÆTA¬À·l¾JA\è,òÆTA=|@?àJA¬£'æôÆTA" úJAÖ{løÆTAœûdîJA‡ŠûÆTAþ´ÙJAŒ8gÄ ÇTA(Íÿq$JAw ¼ŽÇTA–ݨPJAÍäïOÇTAx+¾ûXJAßÐåÜbÇTAe¾jJAǤ5iÇTAÎñSòJAz³uÇTA~ŽË²JAI™'NƒÇTAÌ~wÍJAzDL’ÇTA”ØÀaìJAþ½­¥ÇTA#H{ýJAŒ`©³ÇTA iÎÛJAÇÂâ¾ÇTA]÷vTJAâé¾ÇTAã5W eJA¯õè|ÎÇTA`8Éa…JAÇ7uèÇTAÀUb…‰JAâ6ÛéðÇTANM§(”JAùÅ/ þÇTAÏõÚ¢JA¸G0Ë ÈTA-sSá¯JA)MuÈTA½êtÏçJA/ I5ÈTA¼ µ¤ñJAK7u@ÈTA—oŠ/¿JA’ôÏ#OÈTA­* ÄJAKMlVÈTA00\ÙÅJAòƒ¢]^ÈTAÃ5zÀJA«U=nÈTAå¯ÃJAÑŠ—¸uÈTA]á{`ÒJA:›¨{ÈTAû«˜ÖJA?pr†ÈTA‡–¶áÕJAÉ ëŒÈTA,|yp˜JA”vô‹¬ÈTA¶E„¾JAÅWIFÈÈTA¢ÄGºÏJAdáÔÈTA‹Ñ JA£§ŠÉTA¢?çw÷JAB” ÉTAœ÷2ýJA´f¸ï"ÉTAß)íÿ JAŒìr˜,ÉTA”DJJA ‘ÝeÉTAÎi­JJA§ü—!ÉTA"$MJAíS?¾8ÉTA¹WRÎ^JA ÛѼ:ÉTAO÷(£JA‹}´;?ÉTAÁ¸å¥JA˾VÉTAŠ'î ¢JA´&úΞÉTAº”‹¡JAí}1§ÉTAû{¦`£JA\åýL·ÉTAuNŒóÏJA*ãFlÎÉTAtôÒ·JAs©lÞÖÉTA?Ë:1§JAö`œÜÉTA'wajJA'x6ìÉTA±*-ô3JA»‚AýÉTAØdfMïJA: çÊTA[ZçJA=±êRÊTA‡2SÁ×JA,]Úû=ÊTA!ÙǃÉJA(•ïLÊTAÔ7lJAÈÉ×KoÊTA:E'W€JATá"|ÊTAuOÊ>cJAuË ‹¤ÊTA$Ƶ¾JJA‡ñ¤ß¿ÊTAH'ÂÅ;JA4z«ÜÒÊTAœšâÀ,JAöõÑáÊTA9i¹9$JA€€?ïÊTA¾ œ‡"JA¤þéñÊTAmD<JA¤ú:HËTAC2 "JAÉfQËTAõêFJAÐ(ËTA¼”ïQýJAFødËTAÔ—y6ÝJA´Û^ËTAØàÁ™JA‹ÖÔËTAœÍ‹{:JAü§Ûœ-ËTA‰JAæu¡]/ËTAˆË„ýJA{ƒP4ËTAÓ¸‘‹ÄJA Ø÷ø8ËTA›kP¿§JAôs¬¶@ËTAgzx?JA·Nv1ËTAf6:ùJA®Æl76ËTA2!ˆçJAúY¸T4ËTA}Ý"ÔÑJA*†+¨5ËTA¾R¸äJAJõ\¿LËTAˆ…LÅñJAgC²UZËTAv­  JATÝ…WbËTAö¶T*JAo4FmËTAŽK¹W?JAI2XuËTAG5UJA/º€ËTAÔ_úNnJAžœNmŠËTAaáp~JAÕ$”ÃŽËTAa¯å8œJA¤ñj•ËTAP`|CµJAP4ëlËTAåöìJAÈþí¬ËTA¢3JAM!{»ËTAÎàï„VJAìd `ÁËTAÞó÷ýŸJAqÙµØËTAâ™.Ô½JA–êáËTA’Ý/#âJA6¨ ºéËTA">ÿJAùµO;íËTAÈváVJAf;WúËTAœ¶:‡JAæt¾æÌTA×ĵI°JA©Fµ ÌTA 3P ÊJA4ÆisÌTA°'°ÊäJAþ|{ŸÌTAŽ~&0JA<ŸçÇ?ÌTAu=L FJA?=ÚHÌTA­–:wJA?öBÑOÌTA$¦~†JAHÊó¼SÌTAïðfºJAÁ~F kÌTA|_ûwÏJA^ç’âsÌTAþ2ͦßJAÕ­u÷xÌTAòlxùJAýVg~ÌTAih'JA˜4,Á‚ÌTAá¼YÖJAìθŒÌTA8ÙúJA©¥ŽÌTAÕ”QâJAg­ì “ÌTA á_·JA6ÏþÁŸÌTAœˆJA™xõR¢ÌTAMŒµ•mJA¡ËÕ¢ÌTA9,óyjJAÓþ×»§ÌTAjÈKñ^JAxÃÌTAttãEXJAŠÆŽ?ÍTA¤O* JAFômE<ÍTAGQøªàJAPÓX™7ÍTAúT.©JA{<7®0ÍTA)‹;²yJAjmO-ÍTAG NRJA¢ Îå+ÍTAèÒWJA°=Óõ+ÍTAwïÌ"äJAMVúL)ÍTAÿ'(¬ÏJAéh;X>ÍTA6¶©_ÂJAé4!7QÍTAI×5/´JA†>)#\ÍTA"%•JA£—®jÍTA™âp šJAð ÔmÍTA™´ñLÔJAg—|E…ÍTAc¶Ú€ÝJA/sw~–ÍTA`)_…ëJAŽ˜l¨ÍTA¼²f JAeüÔ¹ÄÍTA ÐÖˆJA¥†µÒÍTA'v8(#JA^RÝÍTAv\Ô/JAнïûÍTAdé87JAw`ϯÎTAÇS«FJAù¸¼è ÎTAý¯ýêJAsÞUaNÎTAnÊoq¾JAO¶;dÎTA´`‚ZJAu9†¨‰ÎTAsg(ÿJAÄe…Þ³ÎTAyON"JA $žÖ¿ÎTAŸ­FÏ/JAn¿½ÆÎTA‡‘z8JA¿þËÎTAò×60JAºúÖÎTAÎ5í8-JA:6_õÙÎTA2Zõ©*JAm_ÝÎTATxq@AJAؼá‚âÎTAÜ|k JA@ÞãûÎTA®ÄMD JAB¶ä¯ÏTA/HJAî€õÌ+ÏTAþpŽJAÜ÷3UÏTA£”_JAmF,…nÏTA”Ý´wìJA^,rñ“ÏTAj3ÞçJA9’¬ËžÏTA„¶] ÙJAKÜ\±³ÏTAîx_–ÓJA/p{b½ÏTAÑ6ø²ËJAˆ™]ÎÃÏTA’fÀJA}B7‚ÉÏTAws…z¥JA×l@†ÔÏTAcbõ.‡JAž uJÞÏTAAð©UJA‘d…ôêÏTA<¬¥1JAN ƒòÏTAç9_ÌJA"Z^ ùÏTAkR_¤üJAzÔGIòÏTAâLíöJA°àríÏTAëª(ŒçJAJÇ7çÏTA}S•ÌJAÀqÒàÏTAgî*¿JA#Çc$ÜÏTA±ä“9‹JAú+¼J¾ÏTAêŽ`‡uJAËܼÏTADÇÞïNJAZòq»ÏTAÅùyÜ6JAôÚ0]¼ÏTA¸Ôw8JAôZ ÂÏTAÀ)h<ùJA$ú)ðÅÏTA9à•ëJA¢ÒJ[ÆÏTA!ÀªÒJA ÄMDÅÏTATPÕÁJA||5=ÆÏTA“«Èa¯JAvhsÉÏTA¶woí‰JAHý ÔÏTA<Í`]JAMý|=ÛÏTAÅø‚?JAIèéeáÏTAó,Y&JA;úqPîÏTA ` zJAq‚ÓØúÏTAi¯^ JAƒ©{ÒîÏTAkñIR JA‚ØâÏTA=ŠÆoJAÉ+3ÝÏTA¥m\JACk:ëÏÏTAÑèUk JA¨F4ò¿ÏTA+±-?JA²¥¹ÏTA¢~#õæJA³ƒ#«¯ÏTAXÈ@ÆÊJAÊ"fÿªÏTA\+Ü©JA†T ¨©ÏTAÔ·tZ“JAc4"ªÏTAµÔ¾mzJA]6À2¨ÏTAa¬±é_JAa†þ¦§ÏTAqå e=JAƒ¢ø¨ÏTA+!þ*JA²³L¶¬ÏTAÝaQ_JA‡Ç®ÏTAÖm$pJAµì¬ÏTAÚT}»JA[Ɇ²ÏTA׋n,|JA-]§¶ÏTAüc \JA2Ç@5¶ÏTA%½íƒAJA黡дÏTA>$gñJA?ÕÃÈÞÏTAŠê ¦ØJA­{ëÏTAHÿçìÀJA3 ÂDýÏTA[:)V¼JA—IÐTAŽ‚º¿JAU§ý¥ÐTAÑö¿JAØEÔ ?ÐTAFÄ'³ºJA‚ѳRÐTA¦i¹JAÑTAKÙfÙ(JAÞÕ2RÑTAB«ÖM/JAÃwøÑTA`Ï“.JA¤¡•ÑTA¤ë%J JA.?S ÑTAºz6JA-f.Q'ÑTA¥áÃ,JANè4FÑTAíê¶JAp3QNÑTAU¨oôJA«Ï< VÑTA’ª*æJAŠZŒ`ÑTAäe ÌJAñ|ÏìqÑTA"¸žo¿JANË‹{ÑTAØè@h°JAÖ§‡È‰ÑTA&N£JA€ïËm“ÑTA< å2“JAðeæðÑTAð2j@‡JA( |¢ÑTAkŸ÷zJAF¦¡«§ÑTA8 ƈjJAöxo>¬ÑTAôŽVSJAjEÒðÑTA/5‡:JA… ›!´ÑTAóTt§JA¯0MA¶ÑTA¨*áJA²Þ(ø¹ÑTA 5øÛJAÏ0·Ù½ÑTA“9JÇJA¬g'…ÃÑTAñtX»JA¸Ã;ÉÑTA1¿Oi³JAñªË|ÎÑTA3ŒqJA?¥ÞtåÑTAšÓN$“JA(‹S”ëÑTAt(À„JAÁ|ÑqîÑTA/vyaJAw‘²ÈñÑTA/[¡âGJANçA(õÑTA@´K"JAl%øüÑTAˆ®JAuÜd@ÒTA;^á>æJA$5ÒTA ^®`ÅJAãýƒÉÒTAüák¡JA*/U¹ ÒTABõ‹ƒlJAÚ?õäÒTAÞKàÇ7JAÆ£mÒTAS0šJA„­‚ó"ÒTAujœˆØJArž°À'ÒTAs!‚³ÃJA7Á‰+ÒTAQª¼üªJAW?¯^0ÒTAcE¾JAÎ Ùä5ÒTA-LûEAJAê;ÒTAꃾ¢#JAÎ÷Â>ÒTA®í9«ÿJA¨P¨ÕGÒTA€Îo»JAL<ß[ÒTAwÁ.YªJAÓÜ ]bÒTA¯¢:­ŽJAíÝCUsÒTAd„ûÜ~JA‘`h²~ÒTAr,rJA;N†ÒTAiö?,jJA¹Í0†ÒTA#6ž[JAè— ¹ÒTAiòx+8JAà -×{ÒTA™ìóÇêJA/¸- lÒTAþŠ@%ÔJA³¢G)eÒTAEèC®JA,ûö\ÒTAÒŸvPˆJA®ý¶çQÒTA©{ÔpJAJM LÒTA)‡ ZbJA•ıGÒTAìþß[JAU 6#DÒTA{ÊfyTJA¼x—Ž<ÒTAƒ‘qEJAŠÏ3ÒTAK)qÔ4JA—zt‚+ÒTA˜‡OËJAqð®Æ$ÒTAHN7JAaµÀ ÒTA“o gÎJAvïÕmÒTAÜ/7¾JAÂ.ÒTA ‚½JA.UðÑTA6¾TIlJAR“KèÑTAáÊL33JAwѤ¾ÑTAØÄ[i$JA¿{¯ÑTAÆ\<±"JAå‘?µ¨ÑTA²K¿MJAÄ%äÖ¡ÑTA˜¯“MJA™²Ú}”ÑTArŒ|&„ JAФI…ÑTAÒÿQ-R JAeF‚ÄoÑTA¾à`6 JA…]oÍzÑTA2ýcÚ JAçà fÑTAé-â JA˜Öw¢—ÑTA:™{­ JA¥z¼b¤ÑTAÂä¡ JA´B¾.©ÑTA½UÖ$ JA ݆¿´ÑTA5€HpE JA;¼ áßÑTA_tºR JAÉŠ íÑTAm«Øh JAëî¨ÒTAå8ö´m JA6D"ÉÒTA2áæîv JAëë+ù$ÒTA—T1w JA«gßY-ÒTA3¾Ûls JA¡kTJ6ÒTA1ô9În JAÅgM_<ÒTAU1}h JAª[ŒX@ÒTASUsg JAv¸WcDÒTAaº·h JA¶Ïï2OÒTA¯šo JAŒ®ŸœUÒTAÇ}-²s JA Û¿íYÒTAÿÊY±v JA¸tUÉlÒTA£'A2| JAê®í„ÒTAînig† JA»p ˜ÒTA9MN`‡ JA;©µ©ÒTAž‹>… JA\N*¦ÒTAGrèï~ JA/#ÄüªÒTAÏq¿\~ JAòk4²ÒTAràå€ JAõ¢å£¶ÒTA÷$äLˆ JA'Ò¡¼ÒTA€#Ç’ JAu‹Í,ÂÒTAfåâ JAJþi«ÕÒTAp»ÊÁ­ JA¹§*wèÒTAÔV‚® JAŒ†vDñÒTA»>ò¦ JAy N^÷ÒTAk󮦠 JASt¦rûÒTA¬¥'3– JAžÚÓTA»‹€ JA+0ƒLÓTA€»} JA„ €ZÓTA›PI0‚ JAøCþtƒÓTA•Ûãê JAœÃ:sÏÓTAwÔ##JAZóóùÓTAY³,ÀJA7¹~ &ÔTAàï^ÔTA¸+ˆvúJAÄ)ÛÏHÔTA-—Ú +JA]ÔTAB¡#vJA¾žÿysÔTA¯K=úJARÁé«ÔTA篾ÔTA¢ºðLBJAl¹—äÔTA)§à&¢JA0¼VõÔTA-Ó_9JA9SúÇ ÕTAÉmKJAš3> ÕTA @FZ«JAĺŸ- ÕTA°tËJAT}ÏÕTA'ïDøJARpÁÕTA+§¶ú@JAdoÊ"ÕTA¾#YlJA£U  'ÕTAö%ÍJAa+˸ÜÔTA‘ß±éJA(©@ùàÔTAò4“2 JANÙO?ëÔTAéNØ›$JAЙmóÔTAÀB 5DJA’ OÕTA7µ­rJAøïAk ÕTA¢ÛYEJAi°+¾1ÕTA §o7JA•аKÕTAúXD9+JAíHx¤QÕTA0½™‚JA“Æš¿yÕTAëªSs˜JAŸ]©>ƒÕTA‡©ÿøJAufHòzÕTA ieJA$E–ŽÕTA~ée$JAv9Ø­ÕTAÓ[(JA¼–Ô½ÕTA”à@Ý/JAÔÇÄ7ÎÕTAßn‡b@JA‚sÇHæÕTAô¼´ ©JAÌP™vÔÕTA³#Å?ÀJAj\ÎÕTAcX¶JA㛜v³ÕTAb©:JAf_ÒËÕTA.C™=&JAõIÎÕÕTAìnŘ1JA +JÅÛÕTA—ŠÓ!DJAÃúˆ¯áÕTAûˆå=TJAp1óäÕTA ©¥GlJAày«òãÕTA4 ‡ƒJAšUÃÄáÕTAíÕfô•JAY RáÕTAÐzN²JA±?:#ãÕTAœD»®™JA£·GÑÕTAWôIY–JAæØÌÕTAÀÚ¢“–JA«ñÝ­ÕTAÂe¨#½JAœxz%°ÕTAâ! ŽËJAþêk²ÕTAU¹]f JA«ÝqµÕTAáçØ¥AJA«¶â„»ÕTA*ã'JA˜ìÒ9ÁÕTA¼”Í’JA«ÛˆÁÕTA?Ì™›JAÍ×·ß¿ÕTAwôG ©JApÌU(ºÕTAÑ[MäJA†ÎS€§ÕTA VNÕüJA:uVH¡ÕTA‘&¼,#JAã/ì{™ÕTAá„Ê1SJAÔ¢(ä’ÕTAFTãibJA¿ÕTA¸—¾|JAœW̉ÕTAœ¹b•tJA³#n¤‚ÕTAú¹–spJAzkº{ÕTAú÷v¶nJA‚ÃhsÕTAŸ1[oJA—‹ÇlÕTATömÖtJAyU„dÕTA·2›vJAÙüduZÕTAöBï†JA(35SÕTA¡³”ÉŠJAçJøóIÕTAbÉ¢ ‰JA¦î•AÕTA[m Ç€JA×òÀù5ÕTAÖèî³eJA¹äWÕTAq4þ0ZJA’´5hÕTA(úÏVJAyÝ3ýÔTATæ¾lWJA^жÍòÔTAG$¾OSJAü˜`îÔTAáIpFJA(¢sìÔTAvV"JA—FÓÚëÔTAÌÆ@ÍëJABÌKíÔTA! eµJA%Ø 5õÔTA7Yg*†JA6 øÔTA¾fmJAÄj×"ýÔTA^Ù¯â;JA {Ç¢ ÕTA!/BÐJA—墪ÕTAˆ¯ð$øJA5–~!ÕTAþ¢^hêJAážWàÕTA:tÇJABŸ;ÕTAñïÄiJA‰w¥ªÕTAÌU )ˆJA ‰ÕTAgPX•}JAjqÿÔTA8[ÊyyJAù˜ŒùÔTA™N{xJA˜{ÀðÔTAã>MµyJA—ß:EÜÔTA“åósJAåÏÚCÖÔTA?4IØkJAslõÑÔTA^A^JAJgÀÊÔTAΣSL?JAÔ9‡ºÔTAÛ8 µ(JAKæ ³ÔTA5úùéÛJAÈËæéÔTAHï€JA^ KÖÔTA£öÚïxJAòCÓÔTA3ÞwJAÛ¿åôËÔTAY.ÅèrJA´û™ÃÔTA,s+‰gJAt»5»ÔTA÷ÐíXJA2Òü?³ÔTA§GJJA˼G©ÔTAºÈäJAJAþû ÔTAÚ$¿5JAª×‡TÔTAZÂzq(JAyUIªwÔTA:ºŒ*JA3oÖhÔTA°> ÷2JAöróSÔTA´"’A=JAsêKÔTA¡ÏmêUJA Th@ÔTAy¨v:lJA ÷;û9ÔTA•5[JA®ãP2ÔTA¹Îú­‰JA„ 2,ÔTAákåΖJAÞ€ê°ÔTA[ëJAb¬­Û ÔTA¿4Ÿ¢JAQ[g6ÔTAÇºæ ­JAK$“ÔTAéP&ˆßJA‹7”rÔTAÚŠêRìJAc“ÄÔTAê&d°öJAkÔTïÿÓTA!^+JAŒÍ¯ûÓTAÝ0b»JA\£VDôÓTAêÌ’JA„ð4ìÓTAÚhynJAûåÓTA3K’®ÿJAÝ/býÞÓTA¨4JAkÞy[ÙÓTA ‚ JAûèQƒÒÓTAS8ñ9;JAÞw@Ç»ÓTAFu+uYJAy’i®ÓTA3ÄcJAý†-­ÓTA*=Ä~mJAÇOeE®ÓTA¶ükg‡JA–>p¹ÓTA䆲¦JA#LŠÂÓTAÈm'q½JA$õ!*ÇÓTAGg‰YÚJAÁ\Ø?ÊÓTAáðfJA=¸¶ÐÓTAxEJAä‰åÑÓTAA"õ-JAaÂheÏÓTAÚ÷§ÛAJA|*zÊÓTAÌûƒ‹VJAHæóÁÓTAÐU&¹aJA’Æ_¾ÓTA{,²SwJAÑTs¹ÓTA¶‹ …†JAK+ùS·ÓTA;}ÊU„JA,;ݤ™ÓTAãd‡–{JAñëíqÓTA¶°z}JA¦I ¨VÓTAð˜n+}JAá f¤FÓTAîÜЯÔJAÓÜÐ-"ÓTAÁšŸoéJA4¾#ÓTAW©ÀJA¤NÚÓTAÐßH(JA³´KˆýÒTA»‹_/JA´Q–ØõÒTAºW¥þ6JA`ª'àÒTA$/Þá“JAèݨ×ÒTAÞåWÚ”JAú)ð³ÒTAÚŒÒõøJAªQ@b©ÒTAæ!&g JAa·Ò<§ÒTA'€’ JA”ñÍœÒTA‰‘±ˆ JAœn¯­‘ÒTA‚JK JAΚr•‘ÒTADûµß' JAA‘ƒ‘ÒTAM8\N JAVYWÒTA| I/Ö JA)ßrºœÒTA&äÕ½ö JAaË¥(´ÒTA-ŠØ!JA&Ü-ÂÒTAPÒ0É!JA¿¤ÎÔÒTAGÔY!JAƒ°‰ÚÒTAõyñj1!JAgE·åÒTA¼Á:ýC!JAL.i‡ëÒTAáiÏ]!JAúS„óÒTAŒÒ®÷y!JAè„‚†øÒTA´Çæâ£!JAA‹&lÓTA÷ÑyÏ!JA&¹¤;ÓTA‰×÷!JA_û[¿ÓTAJ‹kÒ!JAÔ[¯Â.ÓTA¯)˜T!JAØnd2IÓTA! _Ì6!JAïcÂ7]ÓTAªÛѺ&!JAX>ïO[ÓTAVýª@!JA$ @p[ÓTAîQZá½ JA÷Æu –ÓTAÃpm² JApv¢ÓTA <Lª JA^¸¯ÓTAu»‘Ù¨ JA¾Ä÷¶ÓTAº&†Hš JAÙ­½úÛÓTAg0×” JAðC«åÓTAû“’ JA8ܾ£íÓTA!Ð"“ JA–æè†ÔTA-Äœ JA|K ÔTA6îæ¨ JA¦¢]ùÔTAN+Tëµ JAŒÃލÔTAëÁqäÀ JAjo:ÔTAÇ1˜ª JA§í¯ŠBÔTA‡žù« JAy¾ŒÒaÔTAú/óØ© JAuœõqÔTAÉt0­ JAåÔûwÔTA„Ì· JA7[OáÔTA²Mh» JA+ì‰ÔTAJEq JAž q}ÔTA"½ŸÈ JAÞ{ŸP’ÔTAw9sÏ JAÞÓ6z™ÔTAmA¨ÊÓ JAŸ¼ªÔTAÇ:OÔ JA§¯éµÔTA¤”%ŒÎ JAœcÔѾÔTAà°#Å JA@rÊÔTAÚÖѯ JAN.UÆÛÔTA'¬§0­ JA³r‹»áÔTAú g¨ JAF‘|ŠíÔTAG£ü¡ JArC3‚ÿÔTAÊIÄ¢ JA¬*øfÕTAƒQéL¦ JA„¢X-ÕTAÚ7=± JA¼kÁ\ÕTALkè® JAß³œd,ÕTAjYÖ¯ JAϘV5ÕTAu1.³ JAÌÛ#§=ÕTA6›§¾ JAxøûIÕTA žËÊ JAÙ§ËPÕTA¹ÛT…Ø JAåÛ}yUÕTA-†C8ê JACåœ7XÕTAn˜Ìºð JA” 4\ÕTAcZô JANæoÍaÕTA{É=iõ JA™¬¸Ç‚ÕTA—ÆBô JA¹BKÊÕTA¶o‘¶ë JA¬X6B«ÕTAˆn©æ JAÖ·û?ÈÕTAn¥5üæ JA63˜ÛÕTA ñ2ð JA{¥nïÕTA“ÿv‡ù JAöi æ ÖTAl±¦$!JAfW…ÖTAÇ¡Rÿ JA†0Rï#ÖTAùFƒü JAºø¸—+ÖTA‘Ö³cõ JAs—ºÖ0ÖTAÃX4Aê JA3nŠC5ÖTAmg•Ó JAÃcæX9ÖTAM>aË JAºþC<ÖTA¡ç“öÇ JA}Õºä?ÖTAÚáöÆ JA¾ŒDFÖTA}— ÔÊ JAÊ£±XÖTAýV‰õÎ JAÒÂ"_ÖTAYÚÌDÖ JA+Z±!eÖTA!{»¡ï JAÒâM¤€ÖTAÍëßqÐ JAãmÔâ„ÖTA[ZÛ7z JANÕÄv˜ÖTArI]S6 JA;®œ¬§ÖTAu ® JAò'¤n­ÖTAÖn1÷JAmc ý³ÖTAã#ïÐJABƒkпÖTAÇì1ºÅJA¶úÔPÀÖTAç—äE~JA·zç»ÖTAY¾ ZJAPùp´ÖTA㞬BJAåÐ!®ÖTAmÏÄ2JA`oôħÖTA&ÎÆ$JA_¢¡>¢ÖTAr²]¯JA²P²F–ÖTAñ#áàJA“@¤æ‚ÖTAMõHóµJA©m‹¡pÖTAë¨õrJA0”PÖTAO  eJAM}¥KÖTA…çbÕQJA™O20JÖTAòó –:JA:úíIÖTA6(˜‘JAðJêKOÖTA°6ºãJA) 5ÔMÖTA ÷nîJAÁúMÖTADÄ?ÎJACE›GÖTAXH3h°JA‚Ê%<ÖTA›÷uy§JA ›.9ÖTAX¾ŒB JA›êCÎ7ÖTA”r—JANέJ8ÖTAj²ô@ŒJAz ö9ÖTAÊÝiJA’Ìã@ÖTA*ª&YJAPš•ŸFÖTAdš²CJAÚq/+QÖTACÇ3JAžÍÎØ\ÖTAçˆI1+JAI:­ödÖTA¯óÿÁ%JA+™amÖTAIÚ[#%JAp\z0vÖTAyS|(JA‰&:~ÖTA(¸Ý1<JA§;@—–ÖTA2FJAòZ¼$ªÖTA§2öLJAp´’f½ÖTAfþQJA¢>çjÃÖTA•aMJA¸ÆY$ÓÖTAX*|ïOJAï‰^ ïÖTA³¼ÂOJAw|_@ ×TArQ”ãPJAeôÕ×TA½a—NJAÀÒvR#×TAÔ¦ÇGHJA~Ó¥'*×TA=N7ùJAìøDS×TA©€}fJA ö+kd×TAç¶e{êJAÜ¢R×TAi åJA] M×TA.µŽêâJAyý»"¨×TA—@äJA¾v@¸×TA@o•¹æJAàü~}Å×TA›Û€3ïJAÒ;ã××TA#šæúJAÆA>³ì×TA3ƒÂ…JA¢ÛB—ÿ×TA‘…'¹JAü:÷ ØTA-µøÅ JA ,(ÒØTAHÀ*xJAÑ‹ë,ØTA÷ï¥ðJAK`5öCØTA¿.aËìJAÄ(¤MØTAâ_Ý’êJAÎ= XØTAäØŠëJAeQ]_ØTA!PöîJA º$hØTA¦ZuöJAÅ…uYuØTAÄmîùJA/¡]רTA«ÞÕÿJATGäØTAÍ»£JA…«K•ØTAz¨\JAܰ¿pØTA±¯m¤,JAEªhí¦ØTAˆ±»=JAô¬]Þ®ØTA$ùüIJAq[ضØTAuÚjQJA/û­qÀØTAaåÅ‹QJA*Qý£ÅØTA-{ú5KJAüÅÃ'ÌØTAÿ–!§AJA Ì@ÐØTAD@Ö 1JAƒ(ÕØTA4†àä,JA1lè3ÙØTAC.Ì)JA²Ý¶–ߨTAÝÀ)JA訽£åØTA¶Ä+¯+JAõ-Ê®íØTA'®§0JAJÆž±óØTA7tgIJA¹u…4ÙTAtÜØ¹LJArq:ÙTAè†LJAG¶qÙTA çDJA¸#²_!ÙTA±ÍR„;JA Í÷l-ÙTAÓP~I9JAöô™„7ÙTAL+;JA-–¸»@ÙTA¢¾¶8DJAA=œMÙTAµ¨£¡PJA_%áKYÙTA>€ÂSJAµ·—YÙTA„eQ>^JAÀ0?XÙTANJÔðkJA€¦ÿXÙTAj¢ß¥ŠJAØ\–©]ÙTA8Á,JAÔ±/Î^ÙTAãx²JAG;_ÙTA.ƒV=¾JAO¨maÙTA¼ÉÈJAX¶­ÍcÙTAd[£.ÔJA!klÙTA8ÜðÜJAMàÀ‹vÙTARCÙìJA ¶°ƒÙTAÞ_†4ôJAׂc«‡ÙTAMâ@üJAñ7vˆÙTA¢”# JA`›°À†ÙTADù6JA¼t1K…ÙTAÎùvéGJA¦)†ÙTAï?SJAº:Öõ‡ÙTAIz`[JA‹õµ‹ÙTAl•QÝyJA0zh®ÙTAœMX‚JAñMs³ÙTAÈ_ˆŒJAF’ÛéµÙTAZVöÑ—JAÕÃö®¶ÙTAe#G® JA* Ž2¶ÙTA]¤ýà«JArg^ƒ²ÙTA?,ÎJA:#> ÙTA ·ŸPÙJAŒ±ûœÙTA°ë†-êJAžI'mšÙTA©Lâ°øJA«ášÙTA>ûì5JA¡é›ÙTA"5§ŽJAv¡¤ÔÙTAà=_}JA­Û\l·ÙTAõõçóµJAz¢aÂÙTAЮÓÏJA×~T¨ÆÙTAá–íSâJA0b=ôÆÙTA¡(¿ÉðJAæèaCÅÙTAÂ3'kþJAoœv#ÁÙTAifØ‘ JA{Ô,¸ÙTA[1Ì$ JA âD%´ÙTA¥…x;+ JAŸ M­³ÙTA{eKP3 JAAÖGx´ÙTAj¾ó@@ JA.g±ü·ÙTA­…‹fY JA=åJ¹ÀÙTA  JAÖ8áŠÌÙTATǘ׵ JA Ú¾ÞÙTAZ¶Pû JAÊ2ÃßÙTAèU Á JA4€(®àÙTA‰éB2Ò JAn>3èÙTA´c!ä JAD4móÙTAÊáQ!JA…ÚTAyèœA!JAQ×ÔõÚTAŒ|¯È!JAÕè`q ÚTA.È,¹%!JAàÊ.ÚTA™:lÓ&!JAp„ˆ=ÚTAâMó*!JA%1ÃnAÚTAÊJÀ<.!JA|ê:EÚTAãÚ'7!JAós‡ºIÚTA{P@!JA±Ð®KÚTAÂçïL!JA̰M˜KÚTAöˆv a!JA9ß»IÚTAiàƒ}!JA!J„OCÚTALC¨³–!JAÙ‰žÁ:ÚTA]°ž!JAɺ …7ÚTAo`S¥!JAÿr3ÚTA )q›ª!JAŠˆ@É-ÚTA™7§îê!JA~è£+ÚTA,ÄÔûò!JA׉8b+ÚTA äÚ÷!JAŒwg4,ÚTA‡‰”³ü!JABª/ÚTAgwØ"JA¡›ù24ÚTAuâf "JAA›LÚTAÞF>€"JA2I©8XÚTA¸ÒáT"JAÎ<,wjÚTA|8öPh"JA‡-;qÚTA|Y\"JA܉ä{ÚTAY_!“"JAtñ%|ˆÚTA× m2™"JA8$N^ŒÚTA¢uúÅ"JApM5°¦ÚTA¾Fþ¾Ó"JAá¿’3ªÚTA Ö?på"JA*HÓªÚTA-@&#JA>“:¤ªÚTA…óŸC#JAZ{b¨ÚTAÅþQŸ`#JAý¨ÚTA0ŽÁEj#JAƒC6Ò©ÚTA[(ŸÕt#JA6[­ÚTARý…1|#JAŠœ¨í²ÚTAÎCå$#JA±üB„¸ÚTAˆ9rЇ#JAEß”eÃÚTAË8Bsm#JAH üÏÚTAþV.f#JAýF}ÎÔÚTAÜblî_#JAŒTáØÚTA~±Ö\#JAÉ»ïÜÚTAÁ!\#JA}iëHáÚTA¼ÌÌ•^#JA ¬A’æÚTAÍ6 $e#JAÎZ²’ìÚTAUoLv‚#JA*#ØüÚTA!tM{#JAõU¾ÛTA,¾ª‚#JA5 &ÛTAê`›™‡#JAÛ§Ëz ÛTAQ6uõŠ#JA,’ÛTAz—¸Œ#JA< úÛTA~%²‰#JA'»š,ÛTAÍž‰#JA˜fû60ÛTA‚­;“ƒ#JA?á s5ÛTAf>[ím#JAÊ %¤;ÛTA÷LpO#JA0ÞO AÛTAÿ¤HD#JA¼`QFÛTAÑ5ŒÆB#JAŽ+ÈJÛTAª*‡°C#JAj¼ePÛTA’ ËK#JA6Õ±TÛTAq±V'W#JA‹lÊSXÛTA >c#JAê­›iYÛTAïÿKo#JA¤Â¹–XÛTAŽ9ŠX{#JAÅ^¡êVÛTA«+_-«#JA¤"„·fÛTAí—×£©#JAàÆÂjÛTAÐIb£Ø#JAG-DÖ{ÛTA~Ý ªé#JAÍz\ƒÛTAþ½™Tó#JAÈ[hKƒÛTA«;[†û#JA(°µ‰ÛTA>$+£$JA±I¦ÛTA¢¾]¥$JAn}šð±ÛTAœ*úT)$JAôn±¯ÛTA…^…c2$JAÎzº†¯ÛTAe†›{A$JAìlH]®ÛTAk„Q$JAc4 d«ÛTA¿Z4ák$JAªE]Ò ÛTAáb¬ms$JAFoõ5£ÛTAÈO¢ªy$JAzÞ//¥ÛTAÉk#‡$JA ôÓÙ™ÛTAŽç¦Ï“$JA×…ŽÛTAÛþÐç–$JAóô¡º‰ÛTA“•l˜$JAÛTAïÐ&§$JA4g<ÛTAèH:T²$JAPV§þ@ÛTAõ‹1¿µ$JAgõtBÛTAuhWÔ$JAÃÍú@ÛTAÓ½ê$JAì ˆBÛTAaÉXÿ$JAD’§FÛTA]0H %JA”×]JÛTAŒ±ÿ%JAÐÅ“,QÛTAÇM%ò&%JA¤ƒæ[ÛTA¥ˆiü/%JA”{~eÛTA›KT3%JAZyÇðkÛTAÔgO^<%JAÇWˆuÛTA‹ÕÙPA%JAJäd|ÛTAsIC%JA*‚ÛTAòd„E%JAþz+…ÛTA ¤[ÝL%JA뮢lŠÛTA©a¡LP%JAcj¥•ÛTAߘeT%JAM9™ÛTAæ,¥ßZ%JAÍfà\œÛTA›Ywi%JAP -!ŸÛTAï™Wv%JA?+}äŸÛTA»Âé¤%JA¾Þh¡ÛTA¥ò‡“%JA¡ ÐY©ÛTAÖùÛH¡%JA;ÐBJ­ÛTAw§aKÏ%JA'¶M|·ÛTAÇêP &JAÑvá%ÀÛTA[Ã)1&JA4¥ô ÅÛTAmV׿O&JA儽ÅÏÛTA]xñ|U&JA*c!ÌÛTA‚Íüw]&JA'àªMÇÛTA…î¼£V&JA@“Õ–¯ÛTAZ7T&JAœ’‡¥ÛTAÄjבP&JAz××ÛTA» ì#L&JAF—+ÛTAð‰Ì J&JA¾å—‚ÛTA NƒëK&JAðÝqÛTAÛŽ$“S&JAÙ—â’eÛTA9„‚d&JAHErUÛTA*n&JA‘ä‹éNÛTA &1`w&JA*Ó/JÛTAÇGƉ&JASìüFÛTA¡c6Ö¥&JA&àô’DÛTA_îmuï&JA1<ÛTA.oQ­þ&JA{2˜9ÛTA ÛÃÝ 'JA÷2‰}5ÛTAÃÅYR'JA}œ+Â-ÛTAÜ·Î=,'JA”¤V¤!ÛTAuô-Ô5'JAï:ÛTAZý›ªB'JA[x›ÛÛTA]XT'JAYóa®ÛTA¬i­Ó—'JA­ùå!ÛTAš^ÆE¦'JAnV´GÛTAÊü†ç»'JA5Þ•›ÛTA A(JAǽš6ðÚTA±q1G(JA®êÚTA¥´¢9(JAt‚,{ÝÚTAHº´M(JA"/SÛÚTAÞ¹N¥b(JA °NÛÚTAkGÎÏr(JAëï˜ÞÚTAIùz(JA’AsÝÞÚTA«¬:±‡(JAYT£FÛÚTAÃC\s (JAƒ%ÑÚTA_˜é"¾(JA,L’ÈÚTAœpC†)JAª9Y³ÚTAêq,é)JAò!l³¯ÚTAŸ@ *)JAh¦}•ÚTAtÕØ4)JAœâZs‹ÚTA̪7)JAˆË<„ÚTAbFSs/)JA\%Dx‚ÚTADà )JAþþ…|ÚTAu¸³ü )JAÖw4·qÚTAïýN¢Ø(JAøÃâ{VÚTA,µq(JAÍf¸Ÿ,ÚTA¸Qa>N(JAÇÉÚTA6 ö@)(JAºß·LõÙTAœ&Y(JAµA¾ñÙTA·à?šØ'JAc?%SäÙTA I¼Ò'JAIc¬FßÙTA‰¬kÒÒ'JAd•ò±ØÙTAwÙ YÕ'JAÎ=ÏÙTA¥-ºãÜ'JAOZÞ¼ÙTAKƒ*ØØ'JA,JA3æWË~ÙTA),Of,JA™°owÙTAöû”Æ|,JA£ >rÙTA³‘”,JAª-ƒ•kÙTA¥:¼,JAwxš^ÙTAӂ΋æ,JAªÉNPÙTA;ˆ„0ð,JAª ?„MÙTA´j:÷,JAÖÑ”MÙTAC»Y-JAùÑ­¡QÙTA*¶o -JAxˆYQÙTA»u0-JAö>ÏNÙTA“еö?-JA§ÝMÙTA‘t­ÉM-JAÉÐ’/LÙTA!¥>Ãa-JAP |LÙTAÍyÖól-JAÕ@ДMÙTAÿ—´·-JA [Æ%XÙTAC&aÓ-JA§åùªYÙTA¼ŠæIð-JA5ÊåÕVÙTAÎúÔ¨<.JA?u½Àš.JAÂiÐ’ÙTAOª)«.JA(êœ|!ÙTAÆ‹šC».JA{­:<"ÙTA!„hË.JAˆŠÑ!ÙTA°…AØ.JA Ií•"ÙTANªSÏê.JA¿[3Â%ÙTA¨‹ÕÝò.JAU Q¹'ÙTA]¥Xú.JA_"à#ÙTA>/…ÿ.JA7ª•ÙTAÆ\x#/JAVÀ¶û$ÙTAN~&B+/JAՠ‚$ÙTAY´i4/JAÑQLQ ÙTA«01|;/JA0CEŸÙTAt1„(Q/JAÎ5 ÿØTA®¬T/JAà‹èØTAÂL±Z/JA${ÏæØTA'¯-q/JA —IåØTA_(!)|/JAíèbæØTA? —½/JA ƒþ²ïØTA͵a)˜/JAŠôØTAçQ·<¸/JAuÜÞ“ÿØTAĶºâè/JA­LoC ÙTAÉ<‚xù/JAœHZ©ÙTAmï'0JA¸ñHîÙTAg«æ10JA²ËkÙTA£;ÊÏE0JAÛL„ŽÙTA÷ox8u0JA„Œ-)0ÙTAV­íü0JA¥“@ÒFÙTAªìź0JAÔ«fcUÙTAÇO.Î0JAÏ…CÿZÙTA3´ ã0JAkù O]ÙTA)S™ø0JA†Cp\ÙTA¸1JAÛÂÿVÙTAËxò§41JAú5<úVÙTA›jh1JA2fÐ\ÙTA;9§œ1JA—•ÅëcÙTA„ë0¯1JAŽkåùdÙTAÖýl¶1JA•ëœdÙTA2@:Ã1JA –ŠV_ÙTA,ªl™Í1JA£A§|XÙTA»Õ1JA2BKÍPÙTASþzYæ1JA¥ÅžHÙTAÄ•ÇZö1JAŽ‚;šBÙTALÁJ 2JAÿç“q?ÙTAÞ3ÏF2JAç>V=ÙTA +•þ$2JAÒì<ÙTA›”U]@2JAs†êÙ<ÙTAÎhÉåV2JA¤WN>ÙTA/îÖ¡l2JA×gãG>ÙTA£)Fˆy2JA´E =ÙTAls–3‡2JAèËž:ÙTA«è…n’2JAƒãT°7ÙTAŽˆ±F£2JAò_0ÙTAtzdóÝ2JA_ø,ÙTA:8 â3JAae ÙTA­ªØTN3JAðpƒgñØTAÉCiHv3JA•7ŒâØTAˆÔæ{3JA±s YãØTA/›ºÐ’3JA$‘b~æØTAÚ(Ú¬¾3JAG¥  éØTA}ÙÉÓû3JAX,”éØTA“KcD4JA(«wîØTAˆ|gT4JA“¹Ô3èØTA¡üBx4JAfÙרTAçx …4JAùGÆáÎØTAvâ™4JA›?‘ðÃØTA~åJ¤4JA”¹øw¾ØTAé´…†¯4JA—í½ØTA‘¶Pâ½4JA8.2l·ØTAÎ~\45JA2$£J“ØTA¢ ÿ:5JABù=ŽØTA¦ÈóM5JA`ÓÝ¨ŠØTA3½ïg5JA%^\ØTA>´¯A“5JAôó…}ØTAöˆi´5JAW‘.çgØTAJ.þ¼5JAÓwfÒ\ØTAÊÈ(tÆ5JAÿ}ÎêMØTA¢+!5×5JA184>NØTA¬»\ú5JAõ@æ˜RØTA±fœ6JA3 j³_ØTAÿ=üü6JAÞwÉ:gØTA«ßÂÃ&6JAÙö CkØTA¿†>26JAé\Ø9oØTA‚Ë):6JA@®jXpØTAy$þB6JAÚ“¶ùoØTA‹g L6JA…ªi=iØTA¯“¹u7JA%‘PÞ`ØTA„|þ7JA%#`ØTA Ãÿ7JAâÏ vdØTAgS­A7JAø¾‡JsØTA4L;>%7JA¯ïzØTAN©=7JAqº„{ØTA&£I07JAËÂ%ž}ØTA]˜7JAœMÂ'}ØTAU€Ùi¢7JAm $|ØTAD,h¸7JA ó1xØTA1Û$L8JAvù/nØTAií Ù"8JA.0æágØTALsõÀ>8JA™¾´^ØTA­?_C8JAÀ¬@ƒ]ØTAøEH8JAP:úƒZØTA +K'T8JAbnSØTA‰ãM^8JAšk߬OØTAÈZ^Êg8JAµ7OGØTAò3šY€8JAàåô=ØTA„æÑœ8JAdl53ØTA œ)Ä8JA¦ù!I1ØTAˆ:‘6Ì8JA½¸ 0ØTA[Œë8JAS/ê,ØTAÁ¥Þ·'9JA>Ó:!ØTAž‹ñ29JA¬¥AØTAgr¥v79JAÄ!ÎaØTAË\´À‹9JAù¤bØTA0Ê–Ÿ9JA:'FØTAÉóWâÞ9JA1F¤„"ØTA£-¹á9JA‹M±$ØTA¢Ý–Âð9JA„öfr&ØTA‰H:JA¦®½f2ØTAºŽ+„#:JA9yˆ 4ØTAC¨SÔK:JA/¢°6ØTA×Rr€^:JA"a‰7ØTA~$„k:JAJžk8ØTAf"‡€:JA· ý™6ØTAé#p„:JAêÝB6ØTA¥¦MhŽ:JAôXƒ‘5ØTA½Ø ××:JA‹œžü3ØTAßw ç:JA|oAO2ØTAi¦ÑÎê:JApqnŸIØTAÞ±6¡H;JAÖ¶šŒTØTAb6i ;JAÛã¬[ØTAÆê¤.°;JAÎþNªcØTAÆÎ2(è;JA\1ü¾mØTA8F.Ëï;JAƒl‘[ØTAÅ$(…ŽJA¯=Ì^ØTAÇ'ÁE>JAù.9bØTA…vŠJ>JAÖ„úMbØTA•ÇôIT>JAYü(dØTAgŒ—>JA·rjpØTAáà›>JAÐZïkØTAªû!ü¥>JAƒÍÉQØTA Û–­>JAøYº¤CØTA­™0¹µ>JA7…ÂÎ.ØTAMyW¾>JA.x3#ØTA0Å­¼>JAd¸ç%ØTANyü?JA¸P4 ØTA+äï7?JA]˜•!ØTAn '­5?JA#Ù.ØTAŒ³ÎÊ?JAl|ôï4ØTAi.‹â@JA›Y¶9ØTA‹‰)¼N@JA¶kv==ØTAÐõS©P@JA+%–ØTAR}„~~@JA+‚÷ØTA?™'“‡@JA€fèÏØTA›)òûˆ@JA?KŸñ×TA\-‘‰@JA‘X5¦ç×TA ¯§lÇ@JAÒrUé×TAy¬ëjÊ@JA> Éá×TAË0UnAJA#Äê×TA›ûß’åAJAqxì×TA¸Æ¡MbBJAjV²^ð×TAµ<JdBJA./:sà×TAEÚîhBJAo¢bÝÔ×TAE[pBJAc—Q¡È×TAù䤿rBJA§I¡Ã×TA:ª…BJA— ¿§×TAOŽÓ…BJAÓK »¥×TAíÒ¹-‹BJAì–¶’×TAÚ’—BJAl·’)g×TAex2ˤBJAÉÅÝM6×TA°cÕu¤BJAïâÓ—óÖTA"»¬ù¢BJA‹¶ÑvÌÖTAÚÏËx1BJAKû&;ÎÖTAÉ'¿*BJA ž¸ËÖTAîšc(BJA„Ç êÇÖTA¶€¾œ"BJA¹íè«ÖTA¸ %¢BJAA†owŒÖTAAÜBJAÁepˆÖTAÞÝ«BJA6¶(ëˆÖTA|`€JBJAæ*MëŒÖTAò’‡ýAJAð&,ÖTAÛ“ŽóAJAøÈ‰ÖTAv®:ðAJA'F £‚ÖTAúBêðAJAoZ>½{ÖTAÅž0÷AJA%ÍãnÖTAD0‚ñþAJAfq¸woÖTA®kÇ-BJAT ,pÖTAQ®ÈRBJAÑ«ëÇqÖTA ¥£pBJA“¦1iqÖTA¶³Pm´BJA¼—ÛkÖTA3¡4÷¼BJA‡äyÓmÖTA¿º ßBJA/c1omÖTA—$¦CJAÙ(‚oÖTA õ:SCJAäT~³qÖTAçèµ5mCJAŒÒxtÖTAïÍŠ‹ÂCJA¥·ª€ÖTAÌh$‹ÎCJAiÙžo€ÖTA5R$ éCJA—ƒ}ãÖTAðŒÖ DJA©JpV‡ÖTAVw„DJAE)´!ˆÖTA9ôBÄ#DJA!à‡ÖTAœ’û>DJA ®VáƒÖTAú¸<§DJAß"ªÙ}ÖTAß)œ—DJA¹¼QP|ÖTAÇ[ÔEJAò×hÖTAísª-EJAæd¬æeÖTA @+íLEJAëð1ädÖTAÏ%Šd_EJAª ¥eÖTAŠ–»rEJA¶*©hhÖTAŠ·ê;­EJAöQaÖTAkãEJAC9Þ9dÖTA‘ì9BàEJA½ðo~ÖTAœìÍbÏEJA3 'DÖTAþÁtÏEJAõËÂÖTAžÈ‚çEJA³R”‚ÖTAí0DFJAöTlbÖTAïƒ [FJA2·qXÖTAM©p13GJA.Wàs ÖTAsR0˜GJA½Ú¤a©ÖTAð$pÓÑGJAàáû®ÖTAíÍšÿGJA´p*à±ÖTA|™HJA8—×C³ÖTA­æÙ[#HJAÁ ¶³ÖTAo£$±&HJA”;è³ÖTAPìýJŒHJAmi/ÈÖTAÆiÂHJAåibÕÖTAVf+¥ÓHJAÃf>±ØÖTAIFТIJAè ¿ßÖTA4^õ(4IJAØ7ÙæÖTAâ £¡WIJAlpb^èÖTAåŸKeIJA€jMèÖTA:SSmIJA  {íåÖTAgÂþIJADœø»ËÖTA4܇IJAˆòè ÇÖTA sϺ’IJA*ØA6»ÖTA$a›¨–IJAÝ–¹´ÖTA¬Ï7˜IJAÌ¡{é«ÖTAï2v·IJAñ›u›ÖTAãèÕ ÂIJAÏX†S‡ÖTA\­ ŽÕIJAð”Æ|ÖTAêÀltÝIJA1½ÁSvÖTA¸WùŽçIJAÙ=RgÖTAX]ÌtìIJAR¢*5[ÖTAÌ !œïIJAÚ`[ÖTAÚÄžõIJAÍÀ {[ÖTAÒ‰éæ JJA nCiaÖTA@±í%JJAªŒnÖTA'v—5JJA.ùóvÖTAV˜BJJAƒLšÄ{ÖTAm¼deLJJAZR4}ÖTAe¢¦tYJJA‰žc3~ÖTAí–ÆÀzJJA…(€ÖTAøIg‰JJA ã⼂ÖTAÍP5C³JJA·X¾‰ÖTAo¡lãÆJJAðjX‹ÖTANL»ÕJJA þb“‰ÖTA«ŒîJJA­€ÑE†ÖTA¬©c KJAPt…†ÖTA7¨h4KJA6­dn‰ÖTAçYå_KJAQnŸŒÖTAüçéˆKJAÁëo·‘ÖTAR,g”KJA21g’ÖTAbHÔÔKJA˜lõ{•ÖTAÓâ•_çKJA\ÃéÅ–ÖTAn——XLJA»ú,žÖTA ´©ë7LJAQÒ‹”¢ÖTAhqx‡dLJAï‰2„¨ÖTA M;‚LJAÕ?ÅW²ÖTA²N‘z LJA~¾»ÖTAGÖ»LJA£C.cÀÖTAÅ$ú¥íLJAd×ÈÖTA°7þSMJA\¼„žÎÖTA©»“®+MJA;¶\ÓÖTA䉒"EMJAËÓfÁØÖTA^zcMJA¤æ¶íßÖTAPØü?‡MJA¡ >èÖTA˜w…•MJAAQwSçÖTAI¥sŵMJA­lbçÖTA9ùÏMJAd+)mèÖTAð ÝæMJA,Wä=ìÖTA"Û<}NJA’@@…ìÖTAÚ‹%W+NJAˆš†nøÖTAÍ¥zTENJAÌ:ÇþÖTAK TXNJA(10×TAMÁ©ªbNJA·¯±B×TAÊŠ ©‚NJA*«¦å ×TA˜É`¸NJAaZ×TAl€¥ÀNJA(¹v|×TA–•láþNJAω4×TA4÷8i?OJARÅ×ê×TAE‰e²gOJA ^×TAT©sh­OJA Š'×TAi$â×OJAÎ,×TAÈß™íPJAiqi4×TAÞoUPJA¨Èãä<×TAÝ^ËPJAóA×TAjæÍû³PJA¨w¥ªC×TA·$ŒˆÝPJA9ü"F×TAâ»ÄÔQJAO[mçF×TAŸò†pQJAXÓ%¢H×TAýEŒÆhQJAŸ†‡Z×TAâFbQJAþ˜¦lj×TAqÆ[[GQJA,'Ì«×TA‰!xÉGQJA’D6®×TAz)¢ÖTA[èz±RJA¥avq’ÖTA&9ŸSJAL?yÂWÖTAÎÔSJA)ÏLÖTAm޼¡XSJA˜à+úcÖTAóª3ØcSJAòyr§bÖTAnþÓkSJAµ¨Ü cÖTAD›uuSJA±/N`ÖTA€ÑýzSJAƒó$Ã[ÖTAÓïLLrSJALˆdAÖTA›ö@AsSJAðÀÐ:ÖTAæsSJA@œmÌ*ÖTA‡t‡sSJA‡ÅÄ&ÖTA&…)ÅoSJA—”KsÖTA iéroSJA³Ú0 ÖTAgBœ¶mSJA#bQ ÖTAÍ_ö_kSJAÅâBÖTAuoMeSJAÕn.&ÖTA¦“ubSJA{Q¼@ÖTAãLCÉISJAbè öÕTAথüFSJAòä±ôÕTA­®?SJA§Vé‡ïÕTA7_1?9SJA‘æ?²ìÕTAÝ•fÈ2SJA……¥ûëÕTAœŽ#À.SJA‡ÊÒéÕTA åJ,SJA¾ð…÷åÕTAmŽêSJAèp/ÝÕTA’ÑNSJAŽnØMÜÕTArÓoZ SJA1°#“ÕÕTA%¸ýeíRJAºxÒÕTAlúéââRJA =äÎÕTAwWkØRJAbk½’ÌÕTARLIÎRJAÕ™MÌÕTAÌîøœËRJAÔ0ö4ÌÕTA?j%M¼RJAÞŸiÉÕTAyïi ¤RJA&àæÞ¿ÕTA™ ã¶„RJASõкÕTA²xilyRJAó ýµÕTA_GRJAü'<·«ÕTA‰œMa7RJAaXš—¦ÕTAæ $,RJAÀ>z¥ÕTA_´óÿ#RJA€UêwŸÕTAã„_RJAŸËÕTAgW!çRJA…fò‚›ÕTAq_RJAýÐÕ‘ÕTA54wÑöQJAƒ…!ÕTA(D³OßQJAŸAg‚ÕTA Õ‹ÑQJA²µÁ~ÕTAc™Ðè¢QJAÙ ûŽrÕTAGtµÄ†QJA`v¡;nÕTA«U]ýxQJAOÄPë©hPJAå»_kíÔTAÔ”7à>PJAÀåQ^âÔTA1ÿ1è1PJAâ¾íÞÔTAD1¦ó+PJA»#¯ÝÔTA£}޲PJA¯ÙÔTAì°½ïOJAº!FàÑÔTAÂÛ%âOJA¶ÈëçÍÔTAŽžæ:ÑOJA(&‘ÍÊÔTA“ãÅOJA]¿\’ÇÔTAcB¾ß±OJA÷i“¡ÃÔTA†•!”OJAL˸÷ºÔTAóÎoOJAx½í³ÔTAI–a bOJA9²Œ±ÔTA–+rõAOJA|„ÊB¯ÔTAÞmÙÃ6OJAË/i ®ÔTA$˜eþNJAÒº7»§ÔTAòOq2µNJA!ʲŸÔTA¿æxó¥NJAYc{ÔTA½QÒÞŸNJAu‚œÔTAEò×NJA©ø3œÔTAœ¸5î–NJABEžÔTAÈòC”NJA¼pJiÔTA¹‹‹GNJA·kúqŸÔTAx?º‡NJA%Ôè»ÔTAßè)RƒNJAí‘ÊÔTAj´¹m|NJA^_‰SÉÔTAð´ÙnqNJA„C“ÇÔTAÛcNJA\›7òÅÔTAPM_NJAn:MoÅÔTA¤oT]VNJA/„‹CÅÔTAU¦PdENJAå×XÐÄÔTA/3â$NJAùkÃÔTA¾;|ÎMJAükÄ`¾ÔTAW¢Ö¨ÉMJAÍÏV0¾ÔTA¾ˆª¸¸MJA~À5½½ÔTABƒ©™¯MJA>fyã½ÔTAª1-MJA™ZØ/¾ÔTAmÏY—MJA³ãå½ÔTAHtJˇMJA½`¨½ÔTAdPÞ„MJAÈ&Ò¼ÔTA6‰xMJA.e›»ÔTAÞ{ÜnMJAƒlºÔTAzg*ÝTMJAî¢üºµÔTAÎAä°MJA9FµªÔTAèIâQñLJAEEGk¨ÔTA×wýºLJA>(ÉÅŸÔTAôx LJAO>·‰ÔTA Ó€LJA9Û_?žÔTAr£S`zLJAeP }žÔTAˆ™@½lLJA˜¶% ÔTAr¿€&WLJAî»)¥ÔTAŠZúKLJAA¥ÔTAr*Ž8>LJAáŒJú£ÔTAÈR"6LJA¸ji¢ÔTAF~DÌ.LJAJ° •ÔTAi L“LJA>u’ÔTAN„å LJAwäåŽÔTAnîX7ÿKJAyŽZ†ŒÔTAÄŸ«FâKJA¨Žx¢ˆÔTAÅMKJAÉF§ÍƒÔTAOô5šŒKJAeé¦VbÔTA6×ôzKJA(Ë«_ÔTAð2ê]KJAWBÇ[ÔTAγ‹>KJAQÓ™[ÔTAUZ–I+KJAƒ‘•YÔTA êKJAöýÑTÔTAÝÝÅûbJJAc":C@ÔTAÀŸºVJJA8ΗO>ÔTAxçÇ@MJJAìî=ÔTA_ÓÊ*5JJAì*ÍTAä)¼EJAjÏh>ÍTAep0C£EJAÍ%¦¢>ÍTAL¯è‡EJA•V<ÍTANSãYEJA€7I6ÍTALEÅÌIEJA2óL”2ÍTA¹^ºÒDJAWD´àÍTA”ÞôËDJAŠëõEÍTA½óã°DJAyä/œøÌTA˜Ió+ŸDJAôFZ÷ÌTA![Èâ‡DJAù¾×eøÌTAߘõ~DJAcú'õÌTAl`>DJAceWìÌTA x‹…DJA°ô_¯äÌTAtv2ËDJA$Ø?ÚÌTA¦?ý[©DJAt¨B‹ˆÌTA\_µËDJAÁLçáGÌTApòáòÍDJA‘%å CÌTAÃæçeÑDJA/Í•· ÌTA^€ŸDJA¬´ÌTAÆÍãSªDJAk\ÜúðËTA¢¸[¦±DJA¦1*”ÕËTAמB[ÄDJAdi!M…ËTA¹Wϯ²DJAz¿D‹„ËTA\ "\DJA9a“‰€ËTAUÀô2eDJAeVYOñÊTAl2•iDJA*J¹ª¬ÊTA=€XƒDJAG8”ÉTA#ÅD_DJAÜíY’ÉTAHƒg{DJA¯¿vˆŽÉTAmÄÚ}DJA€Ã#ÏRÉTAYL‹DJAÞ_)ÅNÉTA/ÃÆ`„DJA®Ö'MÉTA”Ф“DJA†·v.MÉTAËèöâ–DJA$h>hJÉTA0bZØ“DJA¥_³?ÉTA-ÕDJA óÆ>ÉTAF6VuDJA¤êŒ˜>ÉTA<“ìnDJA©ÕÇ=ÉTAΈ«ÎkDJAÉ¢WÀ7ÉTA`qÂkgDJA|C¡:ÉTAŒ¸ß4iDJAH7ûb ÉTA”êCqDJAãÛ ÉTA #ÖzDJAâoò ÉTA¡Ñ¶DJAj·ÔP ÉTA%Ï4‡DJA¹p,¬ÈÈTAA$ÖiEJAÑ™lÚÈTA t 6EJADIfÚÈTA'¸lEJAkâ! ×ÈTAJ5`EJAQD“ÑÈTA®º1oEJAÄ@ ÌÈTAà'5M!EJA «ÌÈTAj[BqEJA r+&ãÈTASE)’EJAÂÞ[PåÈTAúÀþßEJADãÖÄìÈTA7ü‘¯*FJAQxÚëÈTA%4Ž3FJA’®ÌRêÈTAˆ!‘ÍDFJAx/­ÏÈTAŸ©1¬IFJAœgxÍÈTA ØÈkaFJAZ­ÈTA®p»„¨FJA%×Ë×ÈTAéà/BIJA°iQ/ØÈTAÝQ ±›IJAfÍíÈTAˆ–¬¿IJA>ùZìÈTAJé$JJA™½[öÈTA5r ,JJAT{ÙöÈTA£÷0JJAÙV²¨õÈTAüFJAByÊ êÃTAÊ‘½ß4FJA‘sâðÃTAâLüFJA·TÉ¿øÃTAŠHêôEJAœþ‚é ÄTAU;ìEJA/ªƒ'ÄTAÀfz+çEJAx•¬ÄTAÎI§°ÌEJAššfÐ ÄTABo2á·EJAv¶ ÄTA\pŠÊ£EJAe«ƒ° ÄTA$€…†EJAe)ÝêÄTAò†á~EJAÈZÀƒÄTAt—"~EJAP.BÄTA‚gŸ`šEJA{9ÿÂÃTA¹å‡#¡EJAP‚S­ÃTAZH¡EJAù{©†4ÃTAÙiù…EJA|8!25ÃTA¡ULEJAtæ;ÃTAÚÄÃDEJA¸Œ t9ÃTAûBp8CEJAMìkn5ÃTA†C¾>EJAd<íçÂTAÏkš”;EJAÈlDãÂTA¥ ´2EJAï?ÃãÂTAûÞì…EJAغîñæÂTA…)¦ÇDJA)ЉïÂTAÏo|‚¦DJAgµi-öÂTAˆÒ±\£DJAÁ ‚sõÂTA’N»šžDJALêðÂTA¾hu›DJAä·æìÂTAeT7y—DJA:ÄìÂTA½òòyDJAjÕ!:óÂTA¯‡a]DJAU¹íî÷ÂTAeF™ JDJA"-¬BúÂTA©ç®)DJA“›\ÏûÂTAüÆCJA°|ôåûÂTA¦@y“~CJAöêÌüÂTAB½ijCJAž;ŽÿÂTAħeCJAX€Õ·üÂTAXj¥oCJA4ÙãÂTAU` wCJA0«µ¨ÈÂTAØÆ yCJAî\ÆoÁÂTA¥Y4CJAE½l·ÂTA™•›ƒCJA°FÒµÂTAy‰º †CJAõÄ7´ÂTAÅ£ í†CJAÙ$…Y±ÂTA6?©ÒCJAÖKmtÂTA¹DdôCJA_ÌÚ†_ÂTA·YÈ—ŽCJA×é5ÄZÂTAÑ7 ‡CJArYáÂTACåjsCJA-|ÂTAø{‡eCJAŸÿÁŠ'ÂTAZ|G¿WCJAR~†Ï,ÂTAÀ€ˆ÷ACJAI†¾0ÂTA¶eÔ"1CJA ¥ÞH.ÂTAƒŠ[Ý%CJAxa©.ÂTAh¢PCJA~ƒ'2ÂTA›;cåBJAä7 p8ÂTA˜kÅoÈBJAQuÛµ:ÂTA oƒÛ˜BJAy*ÂqCÂTA€ €£KBJAå‹A„AÂTA¬; š?BJAh°êåAÂTA¤ˆ²BJA$YkKÂTAŸ`ùù¿AJA4ÀÚ•gÂTAV…f–¹AJA¼Û;¦kÂTA&ýÙ·AJAŽQ(oÂTAÈîÅ»AJA¦@ŠxxÂTA×^ìu¸AJA3·Wq€ÂTAù¾š³AJA˜Ñbè‚ÂTAŠ‚c£AJAÒ+c†ÂTAø!~‹’AJA¥CÂTA4µ3{AJAªRÖ¸–ÂTAÓH¡ÖYAJA‘“Ú¥ÂTA';q0CAJAÙø¬ÂTAdŒ=AJA¬jb$¶ÂTA«BtzAJA[m¹ÂTA^‡VfÕ@JAÜâ þËÂTAU­<¤®@JA7g¼JØÂTAß_ß„@JAÖ:[ðæÂTAå#‡›€@JA¥0©féÂTAŸh1òš@JAi[JôÂTA/¬ì&®@JAsarúÂTA£„ÌË@JAePx‹ÃTAËýcÏ@JA:™ˆ‚!ÃTA“’‡xÊ@JANسy'ÃTA2O„Ä@JA“ümD*ÃTAÉ =÷ž@JAÔ¼•Ä/ÃTA)´ œ<@JAêÔO@ÃTAt&è‘é?JAŸ:BwRÃTAžâ\ ?JA;0²¬hÃTAeF9Gn?JAC¦hÃTAEI<ƒþ>JA²ñ[eÃTA…Ëü>JA܉­ÊgÃTAã¼?JA?Û,¡ÃTAçý†`?JA•œÉæ®ÃTA“¡?JAI‡²ÃTAîaHÝû>JA  ³ÃTAh½bí>JAÁÒ혳ÃTAòWÚ)±>JAÐý]2®ÃTA×L)­>JAŽ"2ϯÃTA°¼Â’²>JAк´¤ÀÃTA}‘tLÂ>JA4U=ÕÃTA;9‡GÂ>JAaó)ÙÃTAÖ§j½>JA›É“4ÛÃTA=k„L¨>JAL¬ÇôéÃTAD[h”>JA‡¡N…õÃTA8]_SP>JA>¥_ÄTA7÷( I>JAµÖº+ÄTAˆH­E>JAÕ!^‘ÄTAoeí@>JA6jrÄTATïiÙ4>JA¸Â{´ÄTAñN4(>JAJPé ÄTA;Ö@W>JA\"Hó ÄTA¬o™ü=JA!áNû ÄTAX%jìò=JA2eô„ ÄTAæÆ,í=JAú&ÇÄTA®ó×é=JA‚RÄ ÄTAtŠwöä=JAÓÔÇŒ#ÄTArà‡YÛ=JAÈ÷ -#ÄTAžJI×=JA¡ %ÄTA¾Íß}«=JA‡M³&‚ÄTAJð'±„=JA½s&¶ÌÄTAÌÈ+©ˆ=JAåQDúÏÄTA¡ P—=JA\>ÞÒÄTA5ÐŒ=JAc¤e®ÓÄTA,ŸXiÖ=JASÉV ßÄTA‰ÝÅ=JA71TÃÅTAKgÔÁ=JARˆ@`ÅTAÙ0 º=JAžV2OÅTA!™#ZŸ=JA¡Û bÅTAÊBÏG—=JA¢i×>þÄTAaǹ„=JAŸ¶üÄTA‚Ùv×|=JAÊ’PûÄTA¬À$g=JAFÈøÄTA¢½RZ=JAIQæ3 ÅTAÝAÊÑU=JAŽ–` ÅTA޵8^/=JA¯åPÅTA'cI¹.=JA;f>ÅTA§N‹-,=JAé$›M ÅTA'CýÃ!=JAvâÛ)ÅTAcsô#âà?Dx9JA‰iÔ ÄTAëV^ûp9JAÓB}ÄTAÔ0Ádg9JA8Œø±ÄTAþÀ}Z9JA#1+ÄTAØüÐ1G9JAl(YÄTA¸7&39JAã³[ÄTAñêQ9JAª*ÄTAòŠ;í8JAJ1×@ÄTAójÁöÙ8JA3›«EÄTA`­Â8JA¸·¥ÄTAá[S¶8JAÇaÓJ ÄTA1ˆ·í¨8JA3ÛÉ ÄTAºÙ0˜8JA^°UwÄTAˆÑl†8JA" •ÄTAêZò;ƒ8JA…¶ÄTA¶Š¶Ö|8JAt‘ ÄTAêker8JA6Fˆl ÄTAyŸ]j8JA Xa"ÄTA^§Éd8JAÓ^5(ÄTAbr%Y8JA].K-ÄTA@€ÍõO8JA¥Ÿˆl0ÄTAVHþMF8JA¥÷Ÿ¼/ÄTA—á?C8JA¡úˆ4ÄTA5* ¨88JAñT:ÄTA<¤?9.8JA4Ðã8ÄTAlo¼>&8JA¾5ŒŽ>ÄTA6>Ï8JAØ¡C/@ÄTA´lv8JAÆR´`?ÄTAÏÊ8JAD‹:ÄTAÀyq" 8JAW—ÀùDÄTA:T…8JAÝ&ç¦JÄTAV¹zì7JA:mbãSÄTA†ùºã7JA6¢´AbÄTAÔäˆvØ7JACÍà¾bÄTA˜›'Ü7JAÅ9À~gÄTAÀ¥¾×7JA¢µ×âmÄTAD¥âNÍ7JA·Žx‰oÄTA§NªÇ7JAÿ¶SrÄTA\%ˆ¯7JAŒñžqÄTAŠÄ厯7JA#A=wÄTA°ÿøª7JA@Jä-yÄTAV·_Å¢7JAŒŽí xÄTA4k!™7JAýüxÄTA­]„“7JA!uavÄTA›ýH2€7JAr^DµuÄTA‘?L4|7JAlHâ£wÄTAÃ,4es7JAn[ÒrzÄTAàe¹çd7JAVV‹Ý|ÄTAœìæX7JA€É~ÄTAÀ3T7JAWP¯~ÄTAÓ]ÔL7JA•€`˜~ÄTAøG8G7JA|PUËÄTA®öÒ@7JAÑ{ƒÄTA]ä³Ä07JA·LŽ‹…ÄTAÂç”T"7JAa°N´ˆÄTASž 7JAÍõª-‡ÄTA&"Ò7JAþ¯.bŠÄTAc¾ŠN7JA4-U[ŒÄTAí© M7JA¸HÄTAö%O7JA>䫺˜ÄTAÑ·Qá6JA2L^šÄTAË_õ(â6JArŽ¿¦ÄTAÉ–Ê6JA¼= ÖœÄTA©Sü[´6JA¡'ßžÄTAë!>˜6JA°Åâ˜ÄTA[ÛšŽ6JAìž[ð˜ÄTAb‡£]6JA[OÄTAü+q_6JAî|Ü>sÄTAø¡Õ[Y6JAª qb^ÄTA­é!V6JAá×RÄTA/n÷ U6JA"ñnU*ÄTAÔ ÙÊE6JAf¨7*+ÄTAïJ|86JAåAt/ÃTA´ÌnÃK6JAºb„¸0ÃTAlº±Š_6JA7Ýx®íÂTAçÙ°“`6JA„köËèÂTAÜ®$§q6JAuUº˜ÂTA"£*›6JANiqÇÁTA6€n‡ 6JAÑ m‘ÁTAs‹‹T¥6JAMÔ Ã‰ÁTAO¹'ñ£6JA ÇoyÁTA±ñ¼œ£6JA§{÷¹uÁTA&´´u6JA^«^ÁTAÂXÞW6JA¤\g.NÁTA§¤•P6JA]½ÊgCÁTAðzú-6JAŠ¡#6ÁTARžf¿ 6JAYA”h)ÁTAotJÿ5JAwRKt'ÁTAà“ëã5JA^¨0Û+ÁTAöí¬Zµ5JA®©íZ.ÁTA›7¿z5JAv—5ÁTA¯ ‚Å5JAŒ‚e ÁTA?:Cc5JAK!sõÁTAœ†¥n5JAq£9ÇÁTAÔ·=ŠÈ4JA1ã“ÁTA™q³µ4JA/Ñ yÁTAÓ¨{4JAé2Ê|ÁTAl’{zw4JAð\GÁTAÇÊs4JAµ•^˜ÁTAJ7yóf4JAˆäõÁTAÆY‚ß94JAvÍcÁTA¬âv`ú3JAv4ÃÁTA»Wáä3JA.‹ƒÌ ÁTAŽnö˜ì3JAÎbö[ÁTA¾såW4JA;‘…ÊýÀTAµÝ 4JAV [ZíÀTAÓPë9õ3JAÓÆñÁÀTA>ŸñCê3JA&®¸”ÀTAΛ0hÝ3JAÜW‘_”ÀTAQUFžà3JAó„öñVÀTAFz¡§Ó3JAµ™VÀTA¾ËmeÚ3JAˆ…t91ÀTAx\¢Ü3JA—iº`$ÀTAf½*4JArÁ‘5(ÀTAþƒ!4JA)Vò¿TA”6(‘ù3JA/æ»ì¿TAÛlIâ4JA Ù·¿TAû¾]ó4JAãQ…0¶¿TA{‰# 4JAÔ:8V•¿TA_b¸„3JAº½”˜¿TA:IYTz3JAb‰Þ¿TAg½\ÎF3JA|…|!Û¿TA¯”> -3JA$È>ØØ¿TAóA3JAT‹]Õ¿TA¢¢µï2JAaaE‡Ë¿TAD§=Ð2JAð~ÄiÆ¿TA¤'*ß“2JA¹2À¿TAE¼Z2JAh̾¿TAš;áæ(2JAÜòiâ¿¿TA8An£ž1JAúÆ¿TAÍ5ƒ%1JAô+/nÆ¿TAM#ÊM1JAQwʡƿTA/Oúªi1JA¯mÚ“¿TAa{«âf1JA”ܰ?Ž¿TAOÎñE1JA.#ãJ¿TAÔÃßþ71JAƒÔð8¿TA¹Ñ0*1JAŽñçî,¿TA°6ƒT1JA#rù¿TAáèT¬ø0JA†dK¿TA!rò×Þ0JAxŽ›c ¿TA³=òÍ0JANÑ-¿TAæ,Û À0JA³'ž ü¾TAiů0JA«œ ð¾TAÕ³T¤0JA؉ä¾TA=8à¢0JAø¥·~á¾TAèÝ?ʘ0JAýœ†Ï¾TA 1ö—0JA Òu̾TAFßž“0JA šü¸¾TA¨½D0JAf°–?¯¾TA‹¸ƒ¨…0JAV€œp¾TAÙ›þY0JAñôh+¾TAÂA„yÔ/JAd4£0/¾TAÖÞ9ìB/JA ú1¾TAÄZæ¨/JA†Ù2¾TARn-².JAðHeU7¾TAM©ÆBh.JA*›B#<¾TA‚ÄX˜1.JAt‘&K@¾TAAæ‘'ò-JAÉcOÚH¾TA¤Øˆ°U-JAF™Þ]¾TAÆÅކD-JAÁ9Çè½TAô±RþR-JA.Êé½TA?ä÷zG-JA‚½ÿM¥½TA¯2ˆE-JAý4l½TA§xF-JA,0À<½TAèâHÎL-JAõz_½TAÅ’9ÜO-JA¬__S½TAÜñŸË`-JA]Û²_S½TAÚÐí`-JAa?†Š½TAè¾ xm-JA˜ÛÌÞ½TA+®8n-JAmžÆ½TAg%;Us-JA¬¹êdî¼TA£ 6€-JA÷§)ï¼TA®»‹É-JA Š ø¼TAp@Èþ-JAð–½TA’‡Íç0.JA„m&½TANjÊ´W.JAëô(5½TAÊE6)s.JAg°Ö¨½TA›® I‡.JA hJb½TAò¥,¶.JA³†0V½TA ëVÖ±.JA@U¤p½TA¶ùÉ.JA)E»½TA'³Š â.JA×w£Ã½TA™€Lö.JAÑ¢ºé½TA(Û–³/JAÚþÍY"½TA?ôÌÎ%/JA_U"½TA­ÉC/JAš*S¦,½TA’£šûD/JA¾14,-½TA¸»}CJ/JAïX^/½TA-:‚™>JA“DœšÈTAÊ}Pž>JA=Ÿ&xÈTA ½lù>JAe1bÈTAdµ£ü>JA9³ÈTAì”Pø>JAF)7ÈTA5|°Ÿð>JALÕx(bÈTAóggyè>JAý*æmŽÈTA§rÅ‚è>JAd4Š·‘ÈTA\¨;Iá>JA#’ÈTAuN³>JAÆo»ÈTABÕü¦>JA×ÝgïÈTA¦·‰¿…>JA™”¬DÉTABò¸…>JA"|ÛGÉTA3³|çˆ>JAÐaç JÉTAYyöÇó>JAŸV\m}ÉTA¹–¼ó>JAQ¼[/€ÉTAÿλð>JAW¤‚ÉTAd46mì>JA†Òý)†ÉTA=V£Ìî>JAÇ1’*ˆÉTAÕ 2½?JAÜv;›ÉTA½x9à?JA{W/i ÉTA‚`©ž?JA^Þy¾ÉTAÿÇnDó>JA `R ÊTAôÐA÷>JA­äÝ÷ÊTAùpå?JA·{ {ÊTAÀ+|«?JAîÚ} ÊTA^;k?JAØ=&ÊTAË8?JAOw¿-ÊTA œÙ (?JAm¥R(_ÊTA†Ÿ˜ ?JA~—ÄÊTA-ïVµ?JAz†”ÛÝÊTAÓ;Ëp ?JAü_õ,ËTAÂ0Éà ?JA;Où,ËTA\È M£>JA¼¼m®,ËTAc• >JAÛû5ËTA²¹¸!>JA%,š4ËTAo®]V>JA½ó•`-ËTA(ÿ‰VÓ=JA¿V.-ËTA¸ƒvÒ=JA¸ÂyÒ4ËTA "VÂ=JAJ®;e6ËTAåQ¸>Ã=JA¤v;{lËTAû»=JAØ’_ÇrËTA†ÀßÀ=JAr°ô¡ËTAüŠ´k¬=JAoŸÕÞËTA wäª=JAFPwãËTA3ÕºÙ=JAPb“ßïËTAËbÀ#Ë=JA}õÌTA?ÛÙEÉ=JAy–ÌTAÂi}´¿=JA£«§ ÌTAé†ê=JA™ÌTAYAdäß=JAºF_ ;ÌTAì«;ï=JAqœû>ÌTA)ç´ö=JAZK2/JÌTA­ò¡•ÿ=JAœ=‚*NÌTAší]œ1>JAJÓÇ9WÌTA`BÙV>JAܶ(×aÌTAÉï¾àƒ>JA›±JcÌTA!½¬C—>JA!N1^fÌTA‡Û¢¦>JA;Ø)kÌTAº¬È>JA+…œ°|ÌTAŠÁÜ>JAó†‚ÌTA~P~hã>JAe"@ð†ÌTAG¿é>JA¼´JÉ‹ÌTAA_Óò>JAÖýÌTAÞc ¾ÿ>JA"`à’ÌTAií±?JAo7Êi˜ÌTAG;n85?JA*ŸOç§ÌTAöÄ—T=?JAŠ>ð_­ÌTAY:ðäP?JAùqPºÌTAî‚eæa?JAPeè׿ÌTAXÒOlh?JAÿÏÚÅÌTA™\9Ýx?JAˆ¿¼CÞÌTAGÿùEN?JA®¢xçÜÌTA ,šúM?JAKùÌTA×±Íw™>JAíIþäÌTAk3 g>JAòþòÝÌTA`\œŽ°=JA¦V­SÄÌTAgèâž=JAPVØiÂÌTA$Á(uZ=JAó"ÁÌTAü¬u=JA C¾½ÌTA û*ÖNÏTAÉ “š\3JArHÏTAòI|Ò½0JAþFdóRÏTA²×”ai0JAÄÑÓgRÏTA&9i0JAÍ¢w!'ÏTA}kri0JAèŽ ÏTAA'0JAGô§½ÏTAS ~£{0JA+´¹é ÏTA”Ñ’0JA¡œ¬ ÏTA'ÔyÀ*0JA¥NªîÎTAðTM»ç/JAÈ)tâÎTA’;ìb‰/JA¢Z«ÝÓÎTA­FI/JAÒSê½ÎTAôð{·/JAϤ£ŽœÎTA^¥;jø.JA8'Í›ÎTAÖ^oÁÑ.JA]àv5ÎTAôÉíÄ.JAöI!ŸŸÎTA¼bß½¹.JA$¥¸£ÎTA×Ãi3°.JAþrj•¬ÎTAAäÛ¦.JA_ÿ)ö¬ÎTA§Ý¥/™.JA®¸+èŒÎTA&íH{f.JAHâ¨×‹ÎTAebéìg.JA]6mpÎTA!;‰_.JAÇ Ä4xÎTAÃz«5.JAÃŒnÎTAo Î.JA j¼ÕPÎTAÝÌDÿ-JAm5¾kLÎTA“[› .JAÄñhû+ÎTA¨<±œ.JAy©h'ÎTA4 >$.JAÔT©æÎTAíÁ36û-JAp)V}ÎTA"V<†.JA¾O°ùÍTA` uïõ-JAfÞÌ»÷ÍTAB¡.JA©xúÝÍTA@d<.JAôïÝÍTA‡Oó¢6.JAé$Ô[ ÍTA-Nè¦G.JAp©(HsÍTAD£{lN.JA¯ `TÍTA†äçR.JAÈ? Ü=ÍTAÍ2Ž5Y.JA^ £/6ÍTA í[9a.JAº5ùT ÍTAŒ«–Uc.JA‡qÂþÌTAýù@.JA>3#ÛÿÌTAÂÅP4ƒ.JAwêÌTABev«.JAG<æÚêÌTA‹÷Vµ.JARE:ÀìÌTAFS; µ.JA*††êÌTA7p+µ.JAÏVWçÌTAï=žµ.JAòbCÖÌTAü ».JA×A°.ÐÌTA壗±á.JA½¼mÊÌTAñúmPè.JAq__ÈÌTAŽHÊý.JAY¬sÁÌTA’·ŽI/JA‡èl$¾ÌTAKø¸¬ /JA‚Àæ=¶ÌTAKÿ{} /JArN¦ÌTAÎEýÄ /JAÕ¹4cxÌTAlª/JADKõsÌTAœÖŠ/JAƒù´nÌTAÇž_`ô.JAÝÝUSjÌTAîè<ÌTA_FSŸ4,JAÛy&'9ÌTA5n#¹,JA Xcv4ÌTAJŽ®ù+JA]š¢2ÌTAè'åº+JAù¢/ÌTAÈalÐÅ+JA¦U?¯ÌTA¤SƒîÙ+JA—ß³ŽÌTArá+JAŠ›vúËTAûËKå+JA²Ü<ÑíËTAoX3”ü+JA"HÃÆíËTAø_úÄþ+JA.TÊ'ÎËTAZOã í+JAî*ìOÍËTAñ¤Çê+JAméh_ÓËTAå·… É+JAb†È™ÎËTA¢ ùËÅ+JAø0À&ÈËTAG4 ¬+JA6OÙ¼ÁËTA7Ô¦=“+JAï<ãì¾ËTA[­mõw+JA|øÉCÀËTA3%mïg+JAñÆkJÄËTAšéâW+JAÅ šàÅËTAÐg”(+JAC˰DÄËTA>,tp +JAœ·ÄGÃËTAV rÁ+JAk¯ÿo¾ËTA„jÜãk*JAV"Uì­ËTAtžN9f*JAuF­§ËTA Híåa*JA$ >|ËTA£°˜“*JA¯@kŒyËTAËRÖ*JAoÞ¿Ã’ËTA;• ø)JAVÑÔß’ËTA®€?Ó)JAüþ†V•ËTAøHpš±)JA ¸A_™ËTAg´sö¼)JA+ÇÊk©ËTAØlʱ)JAû9 ‚«ËTA;Iç”)JA²†·ë­ËTAcMÑt)JAQHº˜­ËTAQúá(JA±ËTAѩЮÊ(JAÝ!±ËTAÝUžÅ©(JA¬ï”k¦ËTAqJ­‰–(JAq;V.§ËTA\m³®u(JA™öz¬ËTA,Ú#sf(JAÇÑ&ú¨ËTAž6kb(JAÚÜù¤ËTA k^f(JA,ÖEvœËTAB€ÿ‹(JA|NY5…ËTAŽc潃(JAè2dtËTAvx-Ep(JAä+@áWËTAÊâ}Þ¾(JA(V¢ÏYËTAí ;¸(JAd Ùé>ËTAC9ÙC)JA¡ÛÆ5<ËTA(Ž˜})JAªÄE$:ËTA¬®N©)JAÔü¦9ËTA¯nã)JA)´ð¾8ËTAlÿà{û)JA'¹Üª4ËTAø1¶X*JAçy \EËTAöµDer*JA¢!FHËTAÒ{iã*JATtw…CËTA:¦»+JAh¯)ýBËTA¸·Üã2+JACHV€DËTAÛ§ãF+JAgÏØ<ËTAD.Îs½+JAIŠà#ËTA«é@Û+JA0CžŠ ËTAs ¼Ð],JAÇ?1$ËTA–0®e¼,JA’a€ËTA 5â,JA¶|ç ËTA·PÃê-JA•ÎËTAŽt7|s-JAÆyé¤"ËTA¼Ï©|¨-JA¢ç*ËTAqÆ1ªª-JAõ&rTËTAŠ ×-JAåØ4™ËTA˜T¼Þ-JAÇa‰ËTAô{Î-JA"&ÉæÊTAÀÛ'Ã-JAÄg®•×ÊTAóví?®-JA:ÓäøÏÊTA–ðkФ-JA¸ûŸ]ÄÊTAù †U¥-JAŽ_&½ÊTAõ¨²³-JAˆ=«µÊTA1H£¿-JAç𴢪ÊTA~Æ’ÉÆ-JA¹­¦–ÊTA½c/;á-JADÇDå”ÊTA~'ä!.JA5L‚–ÊTA5Žÿ“I.JAžL‰—ÊTA7|Óµ.JA‡ÍS›ÊTA9ê/JA¢p3›ÊTAm«B3À/JAþrv•ÊTAíºfò¿/JA>ÉhÊTAëÄu/JAÄbðjÊTA] >Òž/JAm"ª UÊTAîÔ¡/JAgòèž%ÊTA2{·ï;/JA*„Rý&ÊTAêÄ´'/JAÔa°ÊTAæ÷/JAÍÚ=|òÉTA™ói /JAŠzWèòÉTA‘}ƺý.JAó äÉTA[|¶Iï.JA5ÒõäÉTAPo¯cì.JA<–Œ4àÉTA‘#ÐÖÛ.JAÙF ^ÅÉTAÜcõˆ´.JA‘ëÅiÇÉTALZÌÒ.JA¾£¢ÉTA¾qf* .JA(ýw‘šÉTA $ɸ.JAg½Ž?oÉTAO ¥Ð.JAÑøéOLÉTA®wߨ.JA8¿%ùAÉTAW„Mì.JA\èÆ)ÉTAtkWsð.JA*žæ$ÉTA(QÓ.JA¿á¯ÉTAõžÛ.JA²dq ÉTA‘q¿ÒÝ.JAÒ46ˆÉTAÏO±ù-JAÏö³åÈTAì§­ù-JA5ºíàÈTAž~Ïd¥-JAxËAhÛÈTAì½>ê™-JAø*&À¹ÈTA!N×=x-JAXØÉ˜ºÈTAb—)Û]-JA߯SÈTAïLÀ§v-JA#úÌHÈTAhM5ôt-JAÿ¼ÐÇ6ÈTAAZ$¤–-JABPÄ[6ÈTAÂà”-JA 5÷ŒÈTA#ÌLŠã-JA|-høÈTA:Á£|ã-JA©Êa:ÈTAʦÁ%ý-JAÐØŒrÈTA þÁ:.JAÉÇ„ÈTAΫgú-JAq¢±òáÇTAy,=a.JAV+\´ëÇTAU/‰ôe.JA¿>ôæØÇTA“ìh.JA0³…Ò´ÇTAJL®×.JALM·ÇTA?dÐ…ß.JAÈfÌ5šÇTAgk»¡÷.JA{áY|šÇTA÷èǨù.JAìa×xbÇTAWeoÿ.JA…úÆ­_ÇTAsÝã­ /JA3Æ×ZÇTAË*z^ö.JA=Õ0ò<ÇTAYRò/JA Mû8ÇTAú ]//JAŒä„2ÇTAúßnM*/JA›§·-ÇTA0MŽËR/JA\Šžû*ÇTAààñ¾U/JẢÖ<3ÇTAxØÐQl/JAŠ-‚Ó1ÇTAý0Æ—n/JAÝ%ÜÓ:ÇTAä§Û­q/JAvxœ@ÇTA7'Î^Ÿ/JAAZ†ž?ÇTALWq›Ÿ/JAD£­9ÇTA~>0£÷/JA”ù89ÇTAm«ßwù/JA±çS¬-ÇTAvÍI¢!0JA’dˆ 3ÇTA¿>üïV0JA‹0ñã:ÇTAúêžx0JAÓé<ÇTAíKλ°0JAãÂF-@ÇTAØM½Ë0JAvYBÇTA=€Zñ0JA“p@¹EÇTASw‚—ñ0JAϸ^È?ÇTAuޱù1JAá –@ÇTAœeÛØP1JAôÍÇ,BÇTAø>n¯­1JAóÌ>ÇTAÇÒsÑ1JA27Ã'=ÇTA>Ç (2JAnç,Å@ÇTA½e_'f2JA<ßÞ]CÇTA¸FTŒ2JAþIùÕ=ÇTA›Ç8¥2JA(¦«éMÇTA® 1”²2JAkÊêXÇTAQ„$g¯2JAküFcÇTA/Djmœ2JAõ{Á“ÇTAãaEâ’2JAªŠ8 ÇTAuSÚHÒ2JAÓåÂ( ÇTA望!Ó2JAðy躭ÇTA46d3JA^‘‚C­ÇTAÀÖ@…3JA·yÉBÁÇTA*Ï]ë2JA<’§¼ÁÇTAµ öoë2JA®‡þÎÇTA­ÉO33JAãxÂÎÇTAšV3JA«äKÈTA÷é‚È3JAö^- ÈTAO+â3JA±ÅîBÈTA­ÊHë3JAy1[ÈTA˜’ßIì3JAGvzÐ]ÈTA>r‹û3JA°Øg]ÈTAúy:GÑ3JAÇn*  ÈTA¼úY'4JAY3CµÈTAòë‡^4JAnYÚà¿ÈTAÜë94JAÛ•²ËÈTAáží‡4JAóz™pÝÈTAQbSon4JAá´ãƒýÈTA^x‰oÜ4JAmÁ«ŸÉTAö óú4JAòLýÉTA›àõ\å4JA»Fò8JAʱûûÙÈTAÛ·µ-g9JA•ìîôÈTAëÚè|9JAºz#øÈTAmK59JAƒÚÇSýÈTAªc¤¦9JAÐVß]ÉTAõ›Ö¥9JAÇT%ÿ ÉTAÀéC>Ã9JAhh­j ÉTATɰ:JAjòuÉTA à‘!:JA…¹€”ÉTAjN”^$:JA;ë5˜ÉTA¬&ý&:JAÜ“/#ÉTAN$>œ):JARÎâ&ÉTA“†ê©:JA:™½:ÉTAƒ‡ãù:JAr“r6>ÉTA¤µ/µ;JA¡“Î?ÉTAf|‡G ;JAŠ*j?ÉTAÓ<ÅQ#;JAD]_AÉTA>Ÿtt+;JA¦ÄøêBÉTAbJ@j0;JAí`óCÉTAÿYž7<;JA>ÓÊ7FÉTAÝñ¥‘=;JA¨9(ìBÉTAaìX?;JAØÂZ>ÉTAçe_B;JAÀóز6ÉTAvM,H;JAˆë`(ÉTAÚ  ¹Q;JA«¶\¬ÉTA“4ºá\;JAƒöÖÉTA|2ãd;JAçѶ7 ÉTAÒéjFk;JAçJAÖ¹ÙlÈTAká“Ô!>JA&|-jÈTAyÊ?ÿ9>JA›˜ÆÉcÈTAæ³G3N>JArd k]ÈTA›qñh>JA°2,+OÈTAmCJ>JASoC<ÈTAê&>JA£2‡Ç/ÈTA"¯ûk’>JA7Œ(ÈTAjO)”>JA¶æ?gÈTA-:‚™>JA“DœšÈTAAh’zþp?ùIAGrsxUA'Jøº_JAt¨Û?,UA*¯8ùÝ&JAMcþUAêž2Ñ&JA%Ót5UAr¡„:Í&JAÍÿÜGUA ÒS/‘&JA.9u UA/vƺ&JAౘ(ßUA)}yëÎ&JA¥ ¶ÄUAàI··&JAbàçI·UAéc}±&JALt²UA½‚Ÿ«&JAÞÐ ®UA E]¥&JA«ovÕ©UAº£Œ¡&JAÄWÎþ¦UA²Êé(œ&JAèã#£UAØ 6š&JAUil¡UA:&€&JAÙJ¹eŽUAhD÷Vs&JApu{‡UA-z!z&JA3ä}o€UAÖçô'b&JA§lÝÂsUAþ ’&JAH^~WKUAHO ט&JA£B!þEUA±™o£&JAW©Š=UA–ÿß»&JAyXÔ,UA⺔Ð&JA’³;"UA(‘/¤È&JAr——UA—À °&JA`jÉæUAA:®«ž&JAL 0UAŠ1yAD&JAÎÈbeóUA€?ÿ›Ë%JA‚7fÈUAoµƒ“j%JAFO£TßUA?o0V%JAÔè;ÍÚUAkÁd%JAE‘ÜUA~Ü$JA»³ÉUA®™Ò–‘$JAg-’²UA' G$JA5+ë™UAì8W?$JAas‡j±UAýŒŒÝ8$JA–‡•‘¿UA±e¨"$JAÅò ÀUA9l¨Í#JAǬÎwÁUA1ô2Ë#JAé“sËâUAõS:hØ#JA½YÔ¸ùUA“mêxã#JA);ÈûUAúÍç#JAS‚FáUAœÆ‘ê#JAnO€É&UA…¥vQæ#JAˆ£*2UAÜIPä#JA˜z Ÿ;UAýÎÃÔ#JA 7\x<UAŽ`ÄÉ#JAu’f=UA€æ…“#JAï$¸7UA¶’ã—#JAx'¬.UAÉŽÏË#JA~›6C*UAJß.š #JAÖ›®6UAFÑd„"JA‡p‡íUA ¿e©n"JAŒ“ÿåUAó"JAOøE“UA>e[ù!JA ú}«£UAœmsù!JAÔM ŽËUAÅPÑèô!JA&ËÊÄÎUA®û4}o!JAg$’ìØUA£¼½wm!JAx û¢áUAñ—ƒûõ JAX™“éUAí“ÞþK!JA±~“>yUAÇ{ÆN!JAׯæØ~UA•ß~—”!JAdÆsnUA¾6½±¥!JA‘Šž’kUA8XM*¯!JAPpöýlUAC"¥ÆÃ!JAÞ¥xˆUAª*8k"JAÀ˧ƒUA2aq$"JA@0A¶UA\×ño"JAíÄ0sUAgî2 Š"JAe3øatUA“`”"JAk-ÙtUAï†3W‹"JA3#€}UAj„î"JAÁ¬‡UAyE([l"JA>,UA\d‚b"JAâ!˜UAëÿ‘Jd"JAí%%´²UAÅ4ý(Z"JA€Z)âÇUAߢɋT"JAFP]ØUAz=ÒŠ"JA†@‰*õUA¢‰.•"JA;t9ùUAi^(¥ª"JAùÌ£íUA[á°ã"JA6-[UAx%?Yn#JA­pÝ?UA3÷##JAï匡UAϵÞ²"JA§ùUA㧯"JAð…>ªûUAîvsߪ"JAðD‡ÿUA…ϧ^"JAßOõù4UAâTŒù4"JAóÊÉoRUA;é="JA­àñÄUUAÿ H"JAMÏßYUA°,Zë"JAºX€UAªv="JAt± ˜UAs.àÈì!JAú)Y±UA“n[yù!JAz£·UA:è^âå!JA]×°ÉUAFcß…â!JAïHÕÑUAí™sòÝ!JAùíÚUA™H²!JAcd¹ÿUA§"O;¢!JA"ÝüUAC_œ8Q!JAÜý¯BUAk*]D!JA䆛MUAã“Ds4!JAà s™YUAã~]Éð JAßoŸUA9ì§õŠ JArqV›ÅUArÖ½J{ JA -˜ ÎUAW<Ëk> JA•û¡lñUAñ“Ì JAIza‹UAÕùêáJARO| $UA6åTÕJAò™¼ UAü•ëÿÅJAüúõUAäø~,gJAWûUA$Žu#JA.R¢«UA\}nûJA9/T=UA¿ *ZJA®+DÃÇUAÑË)UJA÷Ó)=ÊUA%ó^9EJA$uÑUAÒ窆öJA—ÛºUA'ÿùôJAF m«UAпiãJA»Þ‚UA[__qÕJAØÎıUA[øãÝJA‚È_0UAÈ'­³ƒJA€â¶8UAi_¼“uJAu‘ç=UA˜í´ÊhJAÛÔ1CUA(3+|JA#O½PUA¬´è~„JA·Ðs2]UAŠss‡JAŒ§jXlUA7VćJAÛv‡ïtUA°¡(…JA…OuåUA~Awì€JAdË©³UA^I{JA?'˜•UA eÊ;dJAe:º §UA‘È‚l]JAÔsà«UA‚Ëá\JA´w­UA|è¾îSJACI³µUA®pù»&JA(”éüÙUAgü¹–%JA‹ÙÍXåUA/M^,JAh)~z!UAm@ίJA™æät>UA®ú0¹JA ˆÿ°mUAqº JA¡VóBUAl’ÐúJA}ûw®UAúmaÛJA§é¯áÆUAƒ¨†ÈJA¦ÀÇÞUAt•½JA ý²íôUAš5_ ·JA¥ŒqUAÄf”Û²JARGXcUAó`Ø®¯JAÛ46µFUAÝÄ ¬JA.ÿ`UArJ0°JA¼·#tjUAL‘Ó~¯JAÀsI¿mUA~£ŽQ·JAÕ’ùþyUAeû9©·JAÚi“D‚UAÓ±"]±JAØ Ý)ŠUAŸ&™¡JAÐÊÇæ–UAº4£ç‡JADuƒI£UA{È#JAȇ«¥UAOd…“xJAYPœ;©UA‡ÚžmJAvÛÉ8«UA X¹ìKJALÝ0®UAvÉ =JA j2±UA›6B/JA^’±´UAfU™hJAš¹øÊ¹UAkÞ JA=rÂUAz¸öÎýJA{6­ÈUAþT•,òJAö’U…ÒUAk¢_çJAì·HàUAºÊ ÅâJA‘¨5eêUA”šûÞJAÇ1‰öUA¸@ïâßJAEV,UA,ˆö¿äJAJ@UAç÷ާðJA’ßzUA¸6kJAê ˆ1UAsâ³-:JA,MÛUUAÚŸ½kLJA‚vÃcUA<”2QJA°„÷¥kUA ©}PJAIýtUAúµ@)DJA#Û°†UA~Ç~8JA~Ô*+‘UA܃(à,JAƒB¯ï—UAÉJJAy2Õ¸ŸUAfˆ÷JACOʵ§UAº@æJA `‹«UA£2ãùÙJA<”…d®UAœµòÒJAxW±UAÏQV$¹JAxŸï-¸UA‡ ˜u‰JAl€ƒªÃUA˧ÚnJAûV*ÉUA‹ $-;JAóÝvÿÍUAir¡é"JAc>õ‘ÑUA@‡óJA ÿcCÖUA©í™JAÓ}ÕÿÚUA¶¹:ÕÿJA’¶jwàUAZñ3æJAºÝ¨õUA’ERÔJAB¬ñUAMl¢ÖÈJA‡}* UAêÀ¶´JAÚ‰q3UA·9¿­JAñ»:UA¨o×¢JAx*›¾BUA4{’JAx.OñLUAªG¤‚JA·–UAéÅxUJAN†˜UAž†´ÍñJA¥ÑSIœUAÜåŸßJAÐÛÑŸUAxÉJAͺ"ŸUA¦òÒ±¶JA9õ€uÅUAªô JA2]!ÎUAê={c~JAÏ“ÎUA68KÙ[JAš9p±ÊUAؾæ.=JAß8ÚöÂUAƯÛÝ(JA–¶3­ÇUAx\Þæ!JAJåÊUA, È JA»Ã‡œÐUAÅáoíýJAÊÚöŽÓUA4í€íJAHë¦ÖUAff¼µJAFÍUAùç^a–JAu¾Ô°ÌUA®Û‘(~JAÚ›'ÓUAa‘ñôpJAcÀˆßUA믙\JA5&àUA¢Ÿ._JAJœÒ„îUAþy™ôXJAjòýŒóUAô*#î?JAFæìãùUAv'û"JAšQ §üUA„¦CYJA«Ö¾üUAJlšðJA°¨¸§UA·³DÚJAÏh%R UAàIÁ ¿JAMÇ©–UAY?ao½JAUA>Åq·JA(í©_UAüò”JAàgM³#UA4|JAh¡t*UAñ7tnJAvI§ž+UAÁÇ£JAIA&gUAìÝYäJAÈé.2UA+„åÞjJAQtbDUA7 dJA”5-})UAÕ~P4YJA(®7UA<4å»bJAaÓ9u?UA2sÓ+LJAd#€†MUA^d 7JACôUUAVÒ"JA“^UAö- ï8JAe1hUA·ß+*JA¹jcˆqUAª¿×2JA+¸ ÑuUAuÛ3z?JA*ò€k~UAïÍÍo-JAv\‹H}UA­èa¶JA&LîuUA=Ì îJA¡ÇQr„UA=z¡ÙJAsÇ TƒUAÑR7²JAèi,'oUA¢bó0‘JAgÚçgUA' JAÏ ?eUAYØ–Ý JA;7™›nUAÁ®sj JA1UAfªgó JA¹ŠUA²÷Ö JA—˜–UA…—4²² JA‘ôºí£UAlt[ø¤ JA„÷Š©UAVÝæ·… JAÏ•P²UA±}!°A JAóÆ•M¾UAù¼©6 JA¶UA3øA<& JAÈ93¥¹UAŽ÷V÷ JAíÒžÐÀUAÏðÊÑ JAÉe“ÑÉUAäUÍaº JAbþ„çÐUAöFî± JA]0NuÒUA½èÁ£ JA€D¾9ÕUAÛ"e JAò…+zÖUAà€yŠQ JAßfPÝØUAã[@ JA\ô OÞUAôzÚ, JA­‰ åUA{uj JAÚ•¸\ðUAð/îž JA‹þ’úUA1ú» JA¥›ß] UAÔ(x%ÞJA&ì§ UAΫk–ÎJAž¥¼­% UAs†q²JAž)wÝ- UA…ëµñ—JA5ZMg< UA0'Vƒ†JA+ÿ£t> UAvúî+JANÄ"m UA$¡qJAèD© UANІ5ÌJAé“Lï!UAH)âËJAòfLÃ#!UAÑ“˜KÊJAˆÆDE'!UAK§5±ÉJA¡~ÅÆ*!UA|F¹OÉJAÍÎG.!UAÜ\ÉJA?g­1!UA,døÈJA5­5!UA*ªóÿÈJAx=Ù’8!UA¡#ÉJA¡°÷;!UA§ü³BÉJA-Yœw?!UAÍЇÉJA¦¡G÷B!UA5#ÀÉJAwD5’F!UAi¶Y ÊJA[×J!UA‚¡ðVÊJA\>p‘M!UAµ"f—ÊJA¹À$Q!UA¡aáåÊJA/bä«T!UA¾ÏV&ËJA9ç˜+X!UA{5ÌfËJA’mM«[!UAØî ÌJAµ‡ ái!UA˜ûñ²ÉJA£ l!UAOfZHÄJAá4w!UAñÁ9 ÂJA.ûy!UAd|Ì6ºJA£³ƒ!UAÑ\â®JA-Ôw!UAg{¢œJAˆ®Þ[ž!UA{ˆA ‘JA±ÎQâ³!UA’ _‚JA{¾EÏ!UAÝ”a&vJA×ʾ'þ!UAÑh 'JAæù».ò!UA'WÌ7×JA5,m$ê!UAºÛ°JA »ä!UA£+N2¥JAÛ½åPô!UAœ¼{¦œJA?d÷¸ý!UAW(›JA7b@"UAOŠ L¢JAÄ}€"UAÆû] JAúMf"UAS\Íæ‡JAÊJËE5"UAlå…=uJAVÿ«C"UAiËŽú`JA 6±çO"UAþªyXJAI°6©]"UA-s3bKJAã'G}"UAkqÒ'>JARe4¹†"UA²u ò0JAÍÚ6Ö”"UAÒ¿c¡'JA짘W£"UA­•E) JAbç[Gµ"UAÖ—,ÿJA Á"UA®°syìJA²%sÊ"UA÷$#ÑJA°p&Ñ"UAwDÏ®JAjcûÚ"UAI®â œJAá×õÞ"UA$‰5³cJAtÏ5iÝ"UA£ó6ÑMJAŽ^åÛ"UA×}ENJAåCºŽá"UA–ݦVäJA‰5µfé"UAÐÌJAáa—î"UA£Cž–¸JA’Ð*¦õ"UA‰‹È¢JA3R##UA¼Y‰JAb>a™ #UAžº¢qJAX¹•#UAU³(ZJAÌ•#UAeëzòJA8Ë #UACJA"¼Þ#UA×ë³úJAhö”ð #UAMA“-äJA<âB%#UA¡÷ÈÙJA Qe+#UAFõ¹ZÃJA "ï/#UAè#Q¼­JAùQ13#UA­/Ä/ˆJA87õ¥>#UAm#‘~JA\R@#UA8ø€ÙlJAÓ9 Ÿ?#UA%Cµ{<JA!}¡w;#UA‚ã4JA” m˜7#UAÐWß JA;µ Þ4#UA}#/JA™‘T‚2#UAsa­÷öJAM¡(.#UAlÕÔºæJA±·Ÿ"#UAhä×ÛJA G'#UAD­ÂAJAHðY•ÅJAÂ"Gë|#UAùÉ }¶JAp4‡#UA¢Dúó­JAß Z”#UAn —›‡JA)»òÑŸ#UA*Qø>JAÍjRE²#UA:͈JAü·Yl¼#UA‚@ýÕ´JA¢îÂâ#UA£cÃ7€JAÄW‡”÷#UAV؉xJAƒ7*Ñ$UAÖ¿ã~hJA‘¿$UAf¹Ñ7JA%lî]^$UAùŽv"JAÇÉél$UA£IËÀÿIAÉ{]$UAzÔþVÿIA]-0K$UAŸ[vIÿIAb?Q$UAàeÊCÿIAÄBñOS$UA|ÁÆ,ÿIA1MÃw[$UAôƒèôþIA„h¥tm$UAý`¯>¸þIAºˆ´$UAfå—ƒþIAUÇ “$UA¼>´rþIA+_輜$UAÑÍÆMþIA_ ¸¹$UAúÉ4² þIAÓÚ±Pµ$UA‡µeÞþIA(Ùµ$UA]©\þIA$Ê™´$UAxEfÚþIAónÁ$UA/ÝöIþIA’Á*Á$UADø”"þIA½i†IÁ$UA&|ä3%þIA+ÕÑSÉ$UAX4¸Ø þIA³~`‘Ü$UA8 ^”"þIAE ú,â$UAT=Y-þIA ð}ï$UA~µ€GþIAºMa%UAäÄKþIADZäÿû$UAŠœpþIAcèOÿþ$UAl#É‚õýIAåà~#%UAë5ôÌßýIA¡«œF%%UAC9ÏÏýIA­¿"W)%UA·%L¾ýIA¤>»Û/%UA¦»IÆ´ýIA5°Æ#5%UAÓ\«¬ýIA(£ýIA,Ò³ôZ%UA„ŽG@ŸýIA#êÖ˜^%UA¢–¬U“ýIA5èàRd%UA4ÊSû‘ýIA±Fsp%UA^²ÚÃ~ýIA9—µü”%UAäF‚vsýIABOГ%UAQ1XúnýIA”U¾G¢%UA¿Î4~nýIA,ƒ¥{§%UAµWYCoýIA7M_®%UAð‰*uýIA›äìÒ¸%UA\êÏÃwýIAEÆÂÀ%UAàJµ€uýIAÄ/MÛÊ%UA~Ðç§rýIA÷âTK×%UA]welýIA´ÌüÞ%UA¼êI‰FýIAZñÃï%UA´Ž(ýIAÊ¿Â&UAñ*tíüIA¬£·v&UAŠ}©ºâüIAiɼ&UA/ÈJùÕüIAÃ}má&UAÛ@Ä–wüIAÐÄtÝ1&UAÀTŠüIA¯åü¤L&UA¡LäDaüIAD¡Ò\&UAG÷o#RüIA$?†©`&UAê>ùJüIAUF¾wa&UAÂÌÝBüIA;몋a&UA†ºˆ/üIAóü×þ]&UAó2&¤üIAæ×ë³e&UAÔ<¦ üIAh» k&UA†hÕEõûIAQA¦–o&UA¦"°KñûIA—¾££q&UAûáwåûIAõ«J·{&UABÔÒûIA&•½i&UAie™ûIAtsøŒ&UAüT4IdûIAW x[‡&UA!hY]6ûIA¨çÝ¢&UAEâå~ûIA ×íLˆ&UAî)`#ÑúIAyÁ̃¥&UAƒíFyÊúIA 8Mƒ¤&UA¯”A/¼úIA¾Ti¢&UAZ›RašúIA¿YÑš¢&UAƒ'ÁäsúIAz›8¤&UAÎÅ%.úIAï%8­&UAŽe×½ùIAÈñØ·&UAo`“×ùIAû©[½&UA¸D¿J€ùIA«V;ºÄ&UA¨¨!€bùIAÈG:AÒ&UAäkôMùIAÅbOÎß&UA’zþp?ùIAƒ/dä&UAià1 BùIAR°›î&UAßËAùIA ¬hö&UA¡¶9EùIAMø“›ÿ&UA¦÷ NùIA%m&'UA›=•\YùIAï âé'UA3ÈàViùIA…„ƒ'UA%ÑêùIA¨Vê'UA‘z0 —ùIA:”œ@'UA•-L¡ùIAÞáóÁ'UA;)þØ«ùIAȬ~` 'UAœ(}aÈùIA;È!Ó'UA*çÅžÌùIA—Ec%'UA6õ®^ØùIA/9'UAèD§äùIAðò0B'UAÆ$ËÕèùIAe¶ðÊI'UAÀÉÿ1öùIAZ‘ýŽ\'UA¦)ôLúùIAù¸`'UA<>¼øÿùIAm~ñb'UAÕ]·úIAb³~ìf'UAögØv úIAݡël'UA]”»úIAIc{'UAÛÄÊQúIAèH‹„'UAr)¶\2úIAöª™'UA_Îr€qúIArÈXÌ'UA•e(‚‡úIAÉ]÷„Ù'UA x”úIA‚‹µÞ'UAºí›C¦úIA‡†nã'UA†¡ÂƹúIAŠ9Ýøæ'UA'ì’*ÈúIAfešé'UA…Ù¡âúIAÆË¶±ð'UAðkâ ûIA–2wú'UA>rrz ûIA¶û9A(UAÈ5ù3ûIAžùE% (UA”N*5DûIAem¤(UA ŠoPûIAr÷sÚ(UA̲]^ûIA¦t'Ï%(UAÆiâqûIAA£N1(UAnÕç˜ûIAv‡C(UAFÄDÒûIA¢l0‘f(UA:¡ÃßûIA«bl(UAyI‡ìûIAi1Hs(UAÓ,ñãûûIAa¦¨x(UAå¥EÿIAÆàV=*UA'ó¼ŽOÿIAÅ)¼@*UA$öYfmÿIAûÝ÷æE*UA4×–ä©ÿIAV“ÛiP*UAªh2m¨ÿIA»ÉÕåV*UA DsjÁÿIAV¨¶¶Z*UA›'$ùÿIAWÔ¡f*UA¿.i@"JAºm*UAKX§eJA0Þk*UAê‹ÀJAɶ­*UA£¬£ÿÓJAíãù»*UA]G†èôJA}Yj_»*UAÖB*JAéCnyÆ*UAoØÄALJASOt1Ô*UAeÃcJA]YÆß*UA:!1ÌÄJAÈÈ†Óø*UA¢í‰¦ÛJAY•†5ÿ*UAf¦ƒJAR"h¼+UA¸>oiJAóÁ˜L+UAâêÛ“}JAˆOTÓ+UAf]ØJA³žo©+UA<åÙJA²Aë+UAœæ÷±¸JAÜéJ–2+UAòJt)JAö޶¢?+UAæô7JA›`B+UAsÐ@JAH±óõD+UAïªâkSJA£B„K+UAÛ¨‘‡’JAÍ\^+UAbÅc¬JA¨Xéve+UAS²j ·JA¶vŒ¤f+UAÛþ¾JAÑ»-i+UAm9§ ÃJA‰Àú—l+UAlü0°àJA´q+UAÁ®ÊýïJAŹQ½+UAúÒü®îJAÂ÷l–š+UAšJH$JA¸òZÉœ+UA&&CVJA6üåœ+UAauãŠ]JA\­–¯+UA-J xJAí5æÎ­+UA9²Õ¨©JAõOÎò¸+UAµ¹—FØJA 5yÏ+UA‰§(2èJAÎà4‚×+UAÁÑVpçJAý!aÚ+UAí/^þÚJA/'Jì+UAÕÆDÿJAt‹Öñ+UAUÂËo^JAÍé9i,UAX[Å“rJAÖ`ˆ,UAK"™‡JA»X‚,UAvµ^·JA;Ñj,UAfËwÏJA×Ìe©û+UA —ôÝJAÝ!ý+UAýÏÄ JA5xKý+UAiHJAÀ@û+UA {”&JAš0fÑø+UAïè§3JAC…¬ô+UAœxÙƒEJAˆ•––ü+UAáH, TJAÞ¸âš,UA'DÊeJAþfR,UAÅZþP†JA£Jò+UA¼u³}°JAHçV,UA?…4ÒÔJA==Êò ,UAXÉéJAÍ,ZÎ,UAÖGO†JAÅ,UAi4JA³ÌÆn,UAhÁõY!JA#mrð,UAK}10JA\0,UAæÀçe6JAï$È_",UA7]ÌØ>JA8v&,UAÙ[{êBJAðaÉ',UA~‰ÚxJAt¨Û?,UAAG‡$‡JA¶ž5,UAj*bǺJAg–,UA©ŸKfJAcoïæ+UAÌ[¬EpJA\›Ø­+UA;·ŒÄyJAZ<¦+UAqZT‡JA{Y˜+UAJI|ðŒJAh1ÇŠ+UAÙ“,•JAN“Ý…+UA–6Ù¥¡JA+v+UA,Ú§JAS0{rj+UAîaTU¬JAŸK,"[+UAJž¯JAë±¢F+UA=Õ°JAi-UÉ++UAþÞî8­JAë™l|+UAOš¹u¡JAõÒ€þ*UAYâÀÇ¡JA¤è*UAîÅJA΂5@á*UA!‹V“JA+ßo­×*UAûD´)‘JAé~ˆÉÎ*UAµšÄ”JA¢Jõ%‡*UA€?ã”JAsx*UAJþ~‘•JA.ÀÖ`v*UAî_¾“JA²+¯ch*UAmýx©yJA´œû3*UA?¼z uJAì*è*UA–nGpJA(Xµë)UA;^QÛfJAF½k¶)UAž×UËdJAh|° )UAèP"heJA‚¤M˜)UA/´iÈjJAÄ©aEŒ)UAl{u‰„JA3 ”i)UAæ°›/¶JAE>y%=)UAT±»PùJA²ûìœ)UA¹4õh JAÏ!®Å(UA|Áäb JArѨ{(UA%!úÊ JA5Xzv(UAîôn¬" JA–ÖEJ(UAw•ä„ JA1Òõç'UAð´|ìÕ JAs—H*Î'UA_²Q1 JAý‹ÿl±'UA?ç‡m JA×Ñ.`ž'UA>ö|"× JA\W`ȇ'UAe³}I JA¹Ú}pw'UA¶“i{5 JA¶/p'UAâ0…Ì; JAfÆjj'UAéV1›C JAÛ=mà_'UAI1RzO JAkñ;V'UAô·` JAÜ"{°I'UA}&Òt JAÍX! <'UA=š%¿ƒ JA° KG2'UA1ŽSZJA\N…»&UAU XvJA Ý_­&UA¸›¿´ßJAW¾BÙe&UA>—ºiJA1CŽ%UA(û…¥JAµ“Ÿ¦m%UAƒµ§ÓÇJA;Ó·²_%UAœØ1ÚJA³ jY%UAi:JA+h“‘G%UAH+…¯JAQà¶%UA/O_Ÿ.JA€­¥ý$UA}=•®JAç›å¦Ù$UA^ØÂJAm¤ó¿$UA4 E#JAc^ж$UA ä`=JAÔj®Lª$UAü ˜SJA9Žoùœ$UAÉÕæGŠJAº£FÂy$UA„¶“ºÁJA1ýà;Q$UAî¡—¾ JA‡Öe$UA0/vÌ#JA T$UA¬]Ú“/JAæRàúø#UAõˆè£=JAóÅ3?å#UAp¿¶¤@JA•jIÌÝ#UAen4BJA„e¶Ú#UA1ûv@HJAA}GvÇ#UA`–ÍKJAՌԵ#UA­‡vKJAm ùÆ¡#UAvˆŸ#IJAVFiÍ€#UA†€ŒLJAÒùÑëc#UAN[·WJA^Ö :#UAq¼§_JA fºm)#UA,;N=cJAè¯ù!#UA,Ò :qJA‰_M#UAݼ¦Ú…JA’ÎÉà"UA® –ó›JA 7œ>°"UAª·ôÀJAßþZ¶"UA86ˆ ìJAÂD‹!UA,šÙüJAwšB,R!UAgÉ"ÐJAÑÝG‚E!UAzõ> JAiÎñI1!UAê{\JAï¨ÄV(!UA;øJA^¤rß!UA¶?ÀJAZEà!UAeÙ‡‘lJAz5¹CÏ UApž£vJAýœ³Æ UA#ã¡¶JAZh»ÿ” UAšŒ!¡ÌJAÌC}… UAyhWXæJA%³Á‰z UAÓjý8JAòœA:^ UA5ެÙJA_hgç+ UAΟ™'JAëuÀ# UA+â!b8JAÕ2d UAã¶ÿXJAïfר UA:ŸôµnJAèä~– UA|3)E·JAMO Ñ UA˜Š;ÃJA  UAÍ™bJA=ȼ UA®1’­=JAðvñ UA“|„iJA´\Pz UA*H ðJAƶ¯Ã UAìÃîröJAZñ  UAŒ±¨S.JAŒŒA¿ UA·›e,€JAAN4ä& UA3™:J¿JAáH¬C, UA9lúJA‡I0 UAOåŽYŸJAøAT3 UAZ´ÄáJA²W_3; UA¤ UAG LþJAAž¹š< UA”U÷ýGJA]°Þa? UApX?œJAgê©lF UAZapPÎJA-y¡J UAÎd*ì JA`q’Q UASªUd JA8¬fQX UAÕãµ(z JA¥c.Z UAŠëÉ}‹ JAHK5¦[ UAØ¡àÈ JAÑó$f UAàN˜A!JAWÿ¶x UAËÖô1³!JAb±k-… UAsZL4="JAÊ 2W” UAt[f®"JA›Ú\‡ UAsþIí"JA²Å£ UAîmй„#JAÍ:¡>¨ UAÞr¤þÏ#JAz˜ø² UAÉÅ[é $JA3Vså½ UAMïjWo$JAòs’^Ö UA™¥µ$JA°± íç UA;?œÅ$JAdlì UA÷/™ãï%JA6d\>!UA_½öÐò&JAѦç'ƒ!UAo"SQS'JAàî‹P™!UA2OEá'JAÎN.‰µ!UA4~r÷(JA1š|­½!UAX¢³L(JAÙÎ!UAÆrÁ®É(JAéR˜Øì!UA@+)JAh)_"UAGìóÊ/)JA*íer "UAErd@G)JAÑÙ}ù"UAx4š)JAL+‘("UAÓÆÙÈ*JAnM"UAbÌ{ƒ:*JAsø'Y"UAþc+¢*JA°Ù{"UAÕ!V¯*JAžR"UA&’æJâ*JAÀµÕ"UAcÊ5 +JAÇÚ~"UA¥ØüÈ+JA'/Kß"UAÕ@AEÿ+JA·êûò"UA1ûp°!,JAãÓ‰þ"UAªúg56,JAõ<]g#UA¾ê•k,JAç™#á#UA”scŒ,JA(¹úô #UA¤Û-g«,JA% „*#UA~‚;²ä,JAÕ8-¦;#UA­ÉÁv -JA^hHL#UAbÒí E-JA¹q‹U#UA“בo-JA`yW·^#UAÛ,Ú|®-JAŠiog#UAoåÍŒ.JApÈBo#UA»Koÿ/JA£¼în~#UA½‡Ü‚/JAéúƒ#UA”s3ƒ´/JA‚M!…#UAœýZ)å/JAìðK»†#UA"|øMz0JAŠâŠ#UAí}?&¿0JA¥b¦AŒ#UA>jêç0JA Ü#UA¾è˜€1JAµªï’#UAgqµÒ1JA‘Í’•#UAÍuɶ2JAÑÕIú¥#UA˜RµÄ2JAȳ³§#UAïÕòöO3JAvGdÓ¹#UA(*‚Æ3JABØÎ#UAÿÂÏ>4JAáá#/á#UAšhŽÁb4JA’GÊð#UAn:ÜA5JAPo($$UA­2À5JArH$UA ëaˆä5JA\àÖU$UAU6úr6JA2mˆ.g$UAižþ“6JA㚟“$UAí( fL7JA“<9³Ù$UA”üÈ`7JA !±má$UA¿êh0®7JA`³nÂõ$UA͆úÖ8JA)j6%UAÖÌG89JA|·vP%UAyœÖP9JA]~õÕU%UA ¥l:JA½Dí}%UA…þh:JA 1ñB’%UA‹ºpq{:JAßêò±”%UA‰XËß#;JAIyb÷¬%UA–Þ$¬r;JAE®;*¶%UA6{'Ñ>JAa“n&UAó°¢N>JA­‹&UAKódR?JAºÝ>gW&UA¾€Ô?JAØ&ï6d&UA]¥Ý×?JANy±ûr&UA#Ôo0H@JAo9ð†&UA)TñŸ@JAÒ¸` –&UAS]óæØ@JAâüêŸ&UAé-8; AJAP&_µ§&UA'ìÇø^AJA†.åx°&UA´’ÛˆAJAÓHݯ²&UAK5b{¸AJAï8z´&UAÀ‘'±íAJAÔZ–¶&UA\N¨Ó;BJAƒ š¸&UA ï-¿BJA„ÞæÛ³&UA¹n3+ªBJAù=žŒ&UAÎùö±¥BJAí®Gb†&UAO7×ù‘BJA·¶:k&UAuWBJAU>Âg&UA ;΋šBJAðêX¶d&UAIÔxK©BJAåÅpŠ_&UA’õ0ÆBJAD£i»U&UAÈ4òîBJAWm±J&UA#GCJA ÍùA&UAŠ*ÒFpCJA¦ë™…5&UA* ÚDJAI ²®&UAÁçDJAÚO¦°&UAšp³»DJA9ɵ&UA:îçÊDJA<è­&UAò=ª¹DJATà°ú%UAeü `RDJA>SÓØð%UAÅUÁÖ~DJAJØjéç%UA¹Ä ¹DJA ̵á%UAoN<·DJA¥c\¯Õ%UAÙ 4é´DJAVzÓ%·%UA/~ÔÀGDJAvå 3Ì%UAÌ©CEDJAÖ®>É%UArp°BDJA#]hqÅ%UA ³»jDJAμ§âš%UA¨þúkDJAìÃ`™%UA¨4røDJAé-‚ño%UA ¼œÎDJA3ëõk%UAJÛDJAõàD9A%UA~ŽØ'CJAIgd1%UAòd)T*CJA+x.,%UAÿÐ&‹1CJAƨLŒ%UAŽM¡¥:CJA}àë%UA£÷SONCJAË–Ænñ$UA¬;’UCJAgÄ|›ê$UA} ¤œ“CJA—ˆ—y«$UA!Èu~CJA:€¢£$UAw ~AWCJA]÷é,˜$UAŸ±fCJAhÐQ p$UA„ˆî CJAŠndk$UAkÏ^æûBJA|¸S$UA- —Ð×BJAÃׇ$$UAø2­™ÂBJAûŽŒ·$UAænó²BJA{÷Å $UAE†t„¥BJAž…µK$UA³1ãŽBJA·ú¡fò#UA¹·²HBJA‚9òåÑ#UAн,CBJA$ÇåaÏ#UAáúXB5BJA=òžáÈ#UAzäÍÒ BJAi~+µ#UA]9ÊAJAü”xe—#UAŸÅAJAÔðÞL•#UA¿ç½¢AJA—+ׄ#UAuCÀÇ`@JA^+K$Q#UAêe'[@JAeˆØ7P#UA1Ïí&P@JA|``æN#UAÉ ¨L@JAño²~N#UA û»÷@JAå¶VÃG#UAó„5þý?JAÍ MÚD#UAŒª2ã?JAòí „C#UAöü‹vÐ?JAÄIhhC#UAÜb]º·?JA%N}E#UA “}u­?JAú`SwF#UAøõ²Ž?JAS~çMK#UAT"…w{?JAœ-8FG#UA®ôòˆS?JAóŒ§gB#UAÜ¥Ù56?JAî™NA#UAD©åï?JAå&5ì@#UA,æœÑ>JA=;ʆ?#UA©‡B¹>JA-ë™ <#UAWfÿõ¡>JA_ÝE£9#UAè¦c˜=>JAÒ“H>$#UA%Ö¥>JAQÔ#UAòâ‡ò=JAÕPr\#UAŠyè)ä=JAØÕ#UARÊ·®æ=JA ¾R#UA9Aé=JAµë#UA[*J´ê=JA2–¤¸ #UA¹˜V¾î=JAr»a#UAÞÁ.Tô=JA.¦šÜú"UAÒ—n¡õ=JA&6êô"UA7ü»åó=JA²IMï"UA@ ï=JA·o é"UA“ß/èæ=JAW3(-ã"UAÌt\_Ù=JAk̬Õ"UAIÛ{Ô=JAo~”Ì"UAr£QÓ=JAÔ,VëÇ"UAPÛ”Ô=JAãq†#Ã"UAgjæ×=JAÄÍ»"UAóì‚Eå=JAŠçrÌ©"UAÅsX>JA7Ò™‚"UAݳ„¡>JAUÁÓ—v"UA‹›>Í=JAʳlg"UA v œ=JAì[¢Ua"UAðÍ’T+=JA¶Š€F"UAÙÁ…½8=JA?ó93"UA3ÔüG=JA¬÷ð&"UAɰ²ÍS=JA›ÒQß"UAÿ€dp=JA±r18í!UA$jÀ#e=JA–øÓê!UAf¨»^h=JAC/aÇä!UA Ð׸y=JAôËcÈÈ!UAt^ ݉=JA¼x<(¬!UAOC5?–=JA¨¸0—!UAGa ÿ=JAIàrn}!UA!Ê‚p=JA]ú(1n!UAd§a†³®P!UA);}¤JA(à UAß„>JAl„˜õUA±0´N¦>JA×"UAò¨ÚÛØ>JAZ C)UAÉ·[»î>JAЕ ^+UAgj¥ìB?JA‡ýË»7UAž•òL?JA$"²)9UAkT´›R?JAè¡ßú9UAåÞa?JARe ;UA1Cûé¿?JA¡¡÷AUA€Ò[Â?JAé±âß7UAa_îð@JAÐP;EAUA= ú³6@JAl™?GUAMRu!H@JAŒŒd|IUA:s.xp@JA‚·½ÞLUA?+º2œ@JARU`ÛNUAÎÖ@JAFÕ©öNUAÖ™Úañ@JA#‡OUA¾~* AJA~·ë­WUA*HxÞ$AJA^‘€XUAkµÕò6AJA ´ÓêOUA\ñ›FAJA¸xBNUA£iP€AJA+C“AJA û%&UA®t’¬AJAeïï™UA+)Ð(ÐAJAZ T’UAêÜAJA!î‹ýUAKËÞ¿AJA4Á2?äUAž µAJAÂépÚUAì—+s·AJAþX‚åÒUAò°Ê¿AJAr…LYÁUAå†ü¸ÊAJAl Ù°UA:(ÌAJAýœ®UAÃLU“ÚAJA?g$B˜UAÜêNïAJAü²®¿xUAšJÂPBJAɺßo;UA¬dƒ¯@BJA—pC§ùUA̯GBJA¶ÁïUAD‘%P_BJAªþ©ÌÈUAþšblrBJA˜píW¨UAS7òÖ}BJA/I,“UAäºÎ7†BJA ñ`ê’UAUÁ9BJAmcŠ&”UA•÷†¤èBJAÍ1¼¤UA²ø(CJAt3@Œ¬UAð€\º\CJA¨W)ÍUAvUÿwCJAªÚ('ØUA©ë€§CJA[çÍ?êUAÎ 1FíCJAýç»UAo©ðDDJAM .UA„·Š¹GDJA-k 0UAôž5ÈLDJAm´ÿ‚,UAÍHpPDJAßAb°*UAíkodDJA)ćß-UA\lãkDJA)’ûÕ-UApcœ›ŠDJAÑñ…žUA3-¢J¨DJA´KUAs,ÆEJACM£,UA†ÓÃEJAc®š:UAËÆ^¸’EJA7Lº7UAóÛO£EJAž?1#UAIÒà‰¬EJAp2žUA ±®#µEJAÀJw5UApÈ÷ÇFJAL;h½!UAd±5mLFJA®*‚+UAäæ^Ý{FJAQ®°p UAqYlèœFJA=h ïUA&}ÀǦFJAÑgó‹ñUA{$Jh³FJA àôUA±]¥Á¼FJA_| ¬îUAh8ØÝFJAÚòf“ÜUAÉ÷îFJA§¦·ÐUA•'GJAwBv´UAž$ßÒGJA9u±UA°¦©GJAˆ¥Ié«UAÕ¸ RGJAÕ^0—¾UA¼¿nGJANzÑ.±UA[ø3GJAz§æ¶‰UA©# "GJAn&€UA÷Yý3(GJAv5à }UA&4ì×-GJAl¾}{UAöñ¿1GJA±ÁK´yUAHôQ19GJAôÀÜ9wUA¡mÿn?GJAST·ŠtUA]öuLGJAFoUA'Ê­]GJAéÈflUAµƒwGJAf’¦æaUA?8¬ŸGJAif[¡KUADñp«GJA}Á¬DUA—™ó)°GJA.Cà?UA)âmÆÀGJAhJ.UA¡4 ¨ùGJAÙvÅ@UAf§:HJAB¬»*CUA{õÝSHJA]„$²$UAІíZHJAŒEUAЧuIJAíz#LUA|Ýl–¯IJAHëpUAÒ0”³IJA÷Óßc UAjñŒ³IJAì{ëUA$à`аIJAd˜¥UA‹Ø¹€IJAyÈ–ÐUAß÷ÌSIJAfDÙ¡UA6JºIJA,M“cMUA@ŠüHJA˜4NÁMUA瑎IôHJAdX|ËMUA®/?åìHJA«=µ/UA×@þHêHJAûÒª$UAõ/ÜéHJA±UAî®ÅÑHJA‡;k©UA—¼pÇHJAôø‡#UAÌåñƒÁHJA±]Œ‡ûUA™éL¼HJA–%oòUA¨J¯BiHJA‡ÙÞø®UAÇrÛ9UHJA%³x`¦UAè &±(HJAs#2à’UAøÙHJAÑ[BˆUAa(·HJA•»ØƒUAcœ2ÿGJA9™ÞötUAž› zÚGJA¦6ßÀ@UA]Åð-eHJAµ&OXEUAZlßÊ—HJAýÙ$”UA“Á1†ûGJAk¡t²üUAyÖÛþGJA †»TøUAw.©rHJA#m­ÅÙUAiËÆPHJAfáp°ÇUAÐ},j%HJA‚…µUA˜ù‘Ö(HJAÓå’ÅšUA •ŠŽ'HJAŒ§UAG¾r~HJAOr÷kUA·FʲHJA—Ì •IUAq±¡HJAÝ5¡«EUA³Ñ‡WHJAoR°è@UA+ É\^GJA¯Æàè9UAD/PGJAbB½æþUA‰bWóGJAÁ¼vºUAJ²éåGJA‹ÀUAúIìÔGJA{Sf”sUA\õÚ»GJA÷@ƒuUAL b»GJA`prUA.n~µGJAD}‡ 5UA°ü=¶GJA>€qŒ1UAï„øGJA ±o%UA(hLØÉGJApB–¾÷UA©ô?/ÖGJAòàóøUA™‘˜ÏåGJAÉ Q úUARÄXÔ[HJAÛ_µUAê¿«ƒdHJA ˜?EUA¹»@ ƒHJAIkÏUA <é„HJA÷ë…ÍUA™$J=³HJAw¹B6ØUAiìØÀHJAø†aâÑUA–)(›IJAÌåÃÌUAoàü IJA©…ÆUAt .IJARÂ%†ÅUAÉOè0rIJA}±’©»UA×êx¡JJAPIi$LJAuÞ·5yUAóþÈ£xLJAÇË—öŽUAmÞâwLJA¤Ñ6“UA½í¾ŽcLJAÚyàÏUAÉÇÈJMJA}*DUAz´[PMJAlc™UAn¢VMJA ÜìÛUAî}â~^MJANž5º UA¿§S$dMJA*wJ UA"Œ‚_MJAƒØaUAh—YL5MJA^ˆ]„UA"…F5MJA?\ùYUAÅþææOJA+KiUUAq@w`#OJA 4÷vUAMBå$OJAÒƒâeyUA9Å=-ùNJA`r¬üzUA䤟7ëNJA 5ð¹°UAî˜2ÚNJAÛœO´ÅUAYßgaÚNJAw®ÀÒUA¥feïNJA®é î UA%ÄO‚üNJA$¥Ø38UA VÇÆOJA¡„I>JUAÀáÍ*OJA6ÇäcUAÅ”úOJA™–)]aUAØòX½ƒOJApÝtoUAÁ2|OJA‹,†ûnUAœ;8õOJA™[ÐkUA®ÐÞPJAò¦SnUA"ÝA= PJA§ˆ$†rUAv9îÀPJA’\ð„‚UAÛ”yB_PJAù1ÖEUAœÂþ_dPJAamUAG» SJAGMü&lUAå…Ó.SJAWÇITgUA3m¦4SJAÑ´àžgUAyÿÂ^MSJA@ß;fUA.}\ËESJA-!)QUAž6?ORSJA#Ó9`RUA¯-sSSJA•j>ÈWUA ¤SJA"‘g£gUA©¯™ÝöSJAßJ.”uUAÈhñÕTJA ŠG UAƒC+G6TJAi³œ#„UAÜF?FTJAR“Æí†UA’UTJAøV\ŠUAzIµTJA·77¢UA}ªÖüTJAë¸@p²UAn¿ö UJA<{ζUAFݼUJA‹ýV«ºUAœ(UJAñhë½UA±TýwUJA™'A°ÏUAÄä;UJA’ÖßÑUA×»lˆœUJAeØ¹ÛØUA›õò¥UJAU´ÎPÕUA­"¶­UJA¹þ<ÏUAÿ®—øUJA\ž”UA¢ìUXVJA·J’/HUA†Ê·yzVJA@šE>,UA5ñ+éVJA“Fi´UA/¬½¼øVJA+¢.(UA¿–-ëWJA>8_>/UAÒÓçIYWJA‘°ž1UA¹OBuWJA¹%©ï3UA3÷ÈÙyWJAûˆñ;4UA¹úÈ£˜WJA0¿¡09UApÒ#§úWJAKôSõKUAVf!kEXJAaè?¦ÃUAb}}[fXJA{.]‡UAÏcí„‘XJA>•Úx8UAÄòè˜XJAyN;t,UA8ÇwžXJAÀàÎN#UA`c”´ÑXJAŒðôŸßUAîò‹c@YJA qäNUAmxŒÍhYJAÙÿ#øUAñ²nE}YJA±U ºóUAÝÌå…YJA&_âUAÃÝ´f†YJAY $ßUA¼c;«ŠYJA7tÐUA-÷a#ŽYJA´¬¶5¹UAnÊÕHŽYJAiÅ/ë™UA­‘ iŽYJAËrwUAŒ/‚}…YJA ÐýUAæ¶‚zYJAhéAâñUAð­XmYJAZm¸{ÑUAï+€‚_YJAæx©·UA #íQYJAÈRCó¤UA"È4@YJA×wêÖ“UAj• -YJAY†¦ƒUA]‘Gø YJA•$þhUAF‹»ÛXJA®BUAª|¹¯¸XJASw|0"UAÌœ¬XJAKKë5UA CÏÆ~XJA¸²Z÷ãUA_Ÿ’ëaXJAõ]Ÿ½ÃUA™-?XJAXÔ÷£UA»ÓI¸"XJAÖ~f÷ŒUA2¦XJAÖ§p}UAÂEÛ;XJAP¿ &iUAŒÑŽÑàWJA)ºu9UA晋yÊWJAÑÖ!ëUA¦}H»WJAH\JÅùUAVi¡t®WJAïl ´ÛUA^×ݸ WJAÚëõ¶UAÿnšWJAC¼>®ŽUASðê'—WJAÑþ[pUAåÄ÷$–WJAšMtHJUA'Þò`›WJAÍdüd2UA—gÄ©WJA(•C)UA”ÙÐWJAúç÷·UAmÊ@+ÕWJA½6ÿO°UA^vÃîWJA¸`´è‚UAZƒI¾õWJAÔƒUAžÍR¡¹YJA£[û1þUAô‘ð¾çYJA~¦é©ôUAÊÏkÈZJA®tš¸ðUAÃ-[P1ZJA“!²êUAçŽ}§ZJA8 ®1ãUAâ|>0ÐZJA2!^‰áUA—Áמ[JA{êkßUAÔf«©[[JA=å@zÚUA¼¾4¨˜[JAW»ÊÏÔUA>?ËÆ[JAÔˆ† ÎUAqø~¥à[JAË}kÈUA̪ku%\JAW¡ÒºUAºUÙñn\JAÌ`Æ+©UAä½ÏÄ‹\JAb=°u UA ôþœ\JA¬ùL›UAT%ɽ\JAÄmÍÏUAKêÕ¼è\JAï$Ü|UAÑjá]JAÎ=„„fUALš\J]JAˆÃìCUA.´OÅj]JAÉ&©*)UA’ö1™]JAÞ­¾îUAv÷C³]JA;ã¹UAùãBd¿]JAÍ— ^ŒUAÄ»¤×½]JA¨:6LfUA«×R½]JAˆˆ4wYUA*º’¯]JA|¶ /UAP% •›]JAµ_’ËUAn¹g=}]JA™FiîÍUA}¸¥Ä3]JAzº½\UA*u&%]JAõæE÷UARMIÙ\JAÂ(vIÍUA<ÿmа\JAj®…UA¤][¦\JAû§ fUAl/xñ¡\JAß~@PUAR0Ô)Ÿ\JAt@Ê&UAoº‘Ÿ\JA%sZAUAXUûˆ \JAÀÛÏnÿUAû–ã§\JABË4­äUAL9¾-·\JA…$F#»UA' Ï\JAOº¦}ŽUA|¾ Ué\JA°‚ ékUAà—d*]JA¡HqPUAããÛ>]JAj~ÚâUA±“Ó­“]JA”«æ§ãUAÄ`§v^JAü[bÓ˜UA]h¹'<^JAÐ 5×wUA ·ºee^JA,$]ý[UAªMï^JAaªù UA‚¡«Àz_JAèÕÌ)• UA'Jøº_JAÃ}[ƒ` UA™o_JA M UAd_ç`_JAJ#lyA UAp•&H>_JA£:Ln7 UA«·ÞQ$_JA™jb. UAÊ~êF_JALˆ+% UAá_ÛØ_JA>Ñ8 UA_ör”ö^JA {Ô UA2>“°ì^JAõõM UAÒ;ò=^JA6}ù UAª3<æÙ]JA»#hL@ UAÞN’<¤]JA"QÝô4 UAÃã´}]JA ñc•- UA.p°=]JAZ¼Å UAàJv]JAí íÒ UA7ù¬Âà\JAĈl UA Ÿˆ\JAL'SÉæ UA‰(9M\JAŠ}&#Ë UA‘=*;\JAﺠUA¬z$®-\JACµç<Ç UAä× \JA©&ùéº UA§šÈD\JA‡kë© UAhpõ²÷[JAUv(êš UAEõRó[JA²ü‘Ó“ UA0%F1ê[JA¬/a—‹ UAᣜøí[JAi°Ú9y UA1 Œüó[JA ¾f+g UA7ù[JA#r&û^ UAæ`÷Ê¡[JAÔÐ`!' UA¯IÈ•[JAo­ŒË UA‰ÖÊZJA”›¾ï² UA™™Ån}ZJA'KÓ UA÷*ä?ZJAÒùÑ»t UAæ²6CüYJAaçFQ UA(!‚œYJA$|ÏÍ UA†\®>‰YJA÷SIÓ UA•*°cYJAžÆ4e UAÚF–Š^YJAo*¡ UAß™’>NYJAÂæ%q UALÑöAYJAÄÏk UAÏrá5YJAüi UA‹Æ›Å(YJAýÿè UA©'‰YJAÔ˜M UAË~mÃXJA?Qh-& UA2˜­Ý•XJA‰ö“k, UA\(ðKlXJAª;š<- UAháÁ•üWJAü’µ¼( UAö>ŒœWJAÛ¡w7# UAÐÝò–WJAÓ»•"# UAŠþ”WJAB3ª # UAµWÀwWJAªÞ" UAXÂ’dWJAz[!Š UAµ!q¼PWJA/å UA'pþNWJAæMb1$ UAFñb$NWJAþO¶‡& UA»¨ WJAº\Ì& UA«ê šúVJA£š¿»O UA&–IWJAÔ³úÄP UA¾}rWJAº w^Y UAvPÔi¹VJA ÍܘV UA•î¤!´VJAÁÝQ UAø/æÃ(VJAÍ\ÌQ UA3…íTJA>àS UA‰Š±  TJA¯Æ7`S UA.|¸‹“TJAÁÂjQ UAEÆQ7ÎSJAGy‚W UA›Ã)‚¦SJAê 2¥X UAUãí%SJAV-r…W UAÍ´!ztSJAcZ7gK UAíÈc_SJAŒQQE UAj—*USJA»vB—< UAŸÖv²ASJAÀwÜ UA;,å3SJAÐK³Q UAY¡öRJArr UA~ÒÛSJA{yZ~ä UAöP·RJAä5œË UAÿ ~íÊRJA õø¥ UA~ĉTÔRJATLR UA¶Ê¸ëRJA[¬b*: UA=pW‚+RJAÙÊ€+/ UAæô â"RJA¥&ßÓü UA\£o-èQJAI…BDþ UAXȦbçQJAåâ­sú UAr˜‚IäQJAœ´Å†ô UAƒ×ÁßÁQJA›R}ö UA°c%5¶QJAÔ¼•ö° UA5óÆ!¨QJA·!ÐX± UA¬Š´€ŸQJA›kÂÒ‚ UA­4"ôPJA£V@¯„ UA¾+)·PJAï±Ô, UAM.#´PJACQ`~! UA¼2²@šPJAhVbüUAö-ï—PJA4 ޶îUA “\´˜PJA›æ†äUAø×%žPJA (ÌèÔUA3Ëý¥PJAº߯UA“Ë«¶ªPJAešàA·UAµ¶CDZPJA>-Dw­UA!_%@QJAj«SM*UA)8?…PJADmî’UAÉ(êOJA¼\òUA¹ï;ó¼OJAs+T‡UAÎ?"2OJAGrsxUAõ}(ÙOJAw]¨|UAÛnýʆNJA.Ñ`ÉUA©}QqNJA]b7pUA®šJëPNJA–«ôUA‡úþi NJAtVäaUAžf2Ô NJAWD™euUAƒ|¨íMJAmp{/„UAÙFÊMJA&mÝj“UAÔ8É«MJAšÁôÒ§UA‡’7ŇMJA¤—ØšUAf3PpMJA=å+”UAY2„ZaMJAêÄF ¿UAr›Ö?LJAKmQîUA‡ïQLJADù“üÒUAè:ËìLJAü™¹ÙUA½WL‚­KJAÉÛ|yáUAQ|²üÏKJA5mÛ> UAÝØ1Â;KJAƒu~ðJ UA õ•´2KJAغK UA†LiIKJA•ÄEI UAÆe¨ÜJJA“ö‚_  UAu2JJA)Ãy„ª UAN”æÜIJAh‘± UACY;àãIJAnRÑÐ UA†h̲ÄHJA’ƒþ4Ñ UAåRxÅHJAÄ Ži® UA†¢O£VHJA;[¯ UAxš=AHJAQ8î0¯ UA#Ë(Ä8HJAë^£ = UA¥eEÆ8HJAØÛŒG UA íªaeHJA- B UAyhËwyHJA^°Ñ1{ UAšã)?HJAî¡wS UAºŠŽí3HJA8‡Ê³ UA€l^Â*HJATÙ…› UAh;*HJA3„ßÔÑ UA2dW-*HJA3)B UAØ×@2HJA å¨z UAbÓŽ7HJA2N~‹ UAz|´ª:HJAŽÈÏ” UAå$\N1HJA1U·ó§ UAæ¼²0HJA~'{CÞ UA­ÙHJA^2_~ UA¯šI¸§GJAOE UA‘‹Ô‹„GJA‡Àô; UAÏY ÞjGJAïZ_ UAî/ˆB{GJAJwa UAâ¡X0GJA*í“¥á UAÓó´mGJA(4Þý UA ŸKqGJAé<£ UA/NÒ£xGJA;AŽ˜ UA…^1–éGJAA˜Àõ3 UAdßø²GJA›zUU UA¬äÜ#ŸGJAúšñka UA$‘Ö¾‘GJAIs. f UAËÙOKäGJAÊ´¤ÀŠ UAChýKýGJAH‡BÚ“ UAö/:HJAvl¦ UA^2÷HJAˆcLÈ UA}×HAHJA“‡¤ UAš3H÷HJA¾^³S6UAKËÅ@DHJA ; CUAØO…>HJAT€HЂUAhæñšHJAþ·Œß‰UAôþ”sHJA%Ãdù³UAF¶«ŽUHJA|R$òÓUA\Ÿ]HJAËHšÏUAÐ@X4úGJAY4ðUA5%ÓÉ÷GJA,ÞòUA냘ôGJA±pèöUA&Öµ¾þGJAB‡ÉúUAd"HJAØRÊÃMUAœ´¢æ"HJA{uuVUA9›ÑÛ%HJAüÔ?‰bUAÒËo2HJAóD| vUAáþð`OHJAþ¹–UAñZ$HJAÑ|Gf¢UAm õ¦HJAZVi—UA¸+6޼GJA€X&§UAv>uZ˜GJAÌjÛ‚­UAÙ_«r“GJAX¼ºæºUAn¨yGJAãyy¶UA´`%FGJA A«ªUA²œ&ä"GJAòÄa¥§UA–@ýFJA—:´…§UA¶ÕAªFJAïPŠó UAÂ2|íEJAéú*!™UAê]ÍÄEJA&•ʬ”UAÁØI:˜EJA'QèUA¼/êREJAmQE€UAm-EJAXÄ•{{UAžÊjEJAÅmr&zUAÀÖ;žíDJA²yUAä4aN”DJA$Ö²&xUAkìù²nDJA~zƒÙtUAݵ#bDJA1.°fvUA‹Uƒc7bBJAQßGóUAÈQ!­BJAÒS0áUAGçH÷¡BJAÝ Q„UA×>jŽBJA ,ÈìUAUaÐ1‹BJAÚˆyíUAw,·ï’BJAÌz"UA·c¡ŠBJAÇîà,UAâdú˜BJA0ê˜ê.UA|¼¹‡–BJAš°$,3UA|j!BJA"¢Aµ4UAFÛk‚BJAV®i)8UA[ÒlBJA‚M.AUA tL‚OBJAâBƒPUAÏþo¬GBJAƒÔò•TUAÙófABJAtØÞšYUA NY$>BJA_|á_UA*A >BJAUÖ‚ hUAåçž:BJAAƒÛ|UA]Ú gBBJAQÚh~UAê7q9BJA,”å•UA®L¡t@BJAZ¥ê_›UAú IC3BJA w‚¸UAŸÎ¸1BJAuºþù¼UA—2lÑBJA’°~WÌUAÛ»Y¢CJA‰´¨ÞÔUAþú­>:CJA Ö¬ÙUAØJÀæ´CJAÕµÇðUA¬^ŒïCJAØ:IpúUAsÈ­/DJA‡ó@zUA–Š[•WDJA[ÌgUA¡aÏÍzDJA9ÿ–Ò UAoñ=-¨DJA%î? UA[*Ë~DJA§-TR9UAv?ó«DJAgÞêEUAà{7Æ EJAo$Lø^UA êF-EJAʕކbUAŒIdÔEJAä}œBeUAXJÕÎSEJAI3•,sUAådó/EJAcc·„œUAÔj{qEJA¨6ÌÓ¬UA¢A!”aEJA‹$f½UA<â>؃EJAÜóyÉUA!áÇÃEJAoÚé ßUA>úдEJA¯mžçUAÝ$³öÁEJA›êCðUA±¥YÇEJAˆ°t$õUA.¨›EJA‘%iªUA‰+Aø‹EJA ©eUA³ RÖ4EJA9òÆ•UAsUýšEJA×úÓA½UAHg<¨ÜDJAí# í³UAÏnmÐlDJAû8Ÿ¦UAb§Æ(DJA{‹€XŸUAÛLÛFDJA›´kÈúUA<‹/<…DJALÔ±UA±¬nqDJAO@ÊÂUA"€BœlDJA˜û…ÉUAk(~lDJA­e e'UAÞð¸¼mDJAñºÉë<UAÕšÙ¶pDJA_-ÁDUAPÝÉ…mDJAí}MpIUAÚ ußkDJA¤§´OUA²›ôŒlDJA”ôR YUA¯…)OpDJAã³0Œ`UA`¸¸^DJAÝ‚m_mUAã3DÀLDJA·m±vUAùÎ5@DJA»)º¾{UA¨|Þƒ3DJAY¯×v~UAÇádªDJA‘½ÄSƒUAÔœßûCJAîç|„UAíX­ŒÊCJA‡ªÔ(ƒUAy\=ôÈCJAýh€…UASqLèÈCJAÜ-¦¾‰UAåGuMÇCJAhßï@UAgh&׎CJAÿJUAÑþÍuaCJAùèµÛŽUAU‰~ÉFCJA°mÝ‘UAŒwùß7CJAr#[•UAÚ¸­…1CJA @L™UAhM„-CJA~zSåŸUAA˜qo-CJAqQﺥUAR¡1CJA%SŠY»UAö﯆.CJA FŸÈUAaÞcÞ#CJA E?çUA8&Þr!CJASÈ!ôêUA%ðY¿CJAƱ¨“ñUA¡¼ CJAýä’fUA/d­ªCJAÐÁ†… UAáw¸GûBJAZ´p’UAÿ‡JNóBJAÉMÄUAgÆÎéBJAó[å#UA2 d§ÖBJA}gŒ<UAE ¾BJAI)ðOUA (’jžBJA‹âO¿eUA˜’6–BJAð‹ õmUAxáä<“BJAy_tfuUAÙ͉‘BJAdR~UA$†y:’BJAÜê–Á‡UA'¨&’BJAZŸ3—UA䬖BJAÕ…•UAÖ ªºBJAIëž&šUAR DߪBJA¬‰°³ŸUAÚ» ¸BJAué¤UA—¿„å¿BJAUJ‹d¨UAòR3…ÄBJA+hK ®UAvÿ¦¶ÊBJAʹkˆ´UAˆwÒBJAu†Q°¹UA²](6ÓBJA¹ƒ¡¾UA!9:ÑÐBJA™T1ÃUAUµ~nÑBJAÊ$ÉàÊUAH!Ð^ÊBJAèZÏÊUAQƒzÄBJAÓþ×ÊUA?(ê•BJAIJrÍUALíÚ¥µBJAÚ± UAÍ‚i°BJAˆ+@>UARA9¿AJAÄ`‚xUAú„i‘~AJAW¡3ÒUA9Ù l}AJA°C[…ÔUAÚÎP|AJA+˜pÖUAî>ÏAJAtj†ÜÚUA·©^_¦AJAk¾‡h÷UAì|üœ¹AJARåáxUAF¹ÇAJAn– 7UAr)²»AJA$ ¨­UA‰ð HžAJAA‘;iUAžñ 8šAJA÷"#©UAƒZ[ÔxAJA¢Âšo4UA"†=uAJAÙÂ3;UA×ÃchAJAXâAAUAeg`uAJA k§GUARÏ{AJAÿÌ÷KUA°­ÚY[AJAÆdlUApÜg PAJAKo ðmUAy—‚kKAJArD€ömUAky·¸AJA<:ûj—UAàÁÑ(Õ@JAAìzdÇUA•˜-ï°@JADÚâUA™aK‘@JA WäúUAÇ5rñƒ@JAÃÂöUAü͉d@JA# ªíUA| Š^D@JAט{_çUAÍx¤2@JAò½‹ãUAÛ³§è@JA°â2LâUA›Ú¹÷?JAMߎGâUAo6ç?JA¸T•(âUA¥Â9ß?JA-Š® èUA‡$ÓÇ?JAÍSèUAØ»çm¡?JAæs×`èUAзÑ?JAbûëNéUA¬ ƒ‰B?JA7‡ íUA¬úé!?JAÿCQ5ïUA† ¶VÓ>JAtô‰ëUA/G@ˆ>JA6'­ÂæUA a‘MS>JAMN¥áUAŸ¦9R>JA…þYÜUAr×#¥N>JAl²¾A²UA£)dI>JAÚˆ© UAÓgœx&>JA·÷6ŽUA?Ⱦ(>JA ¬8vUADmµ.>JAtÈÇ&VUAôôÎ">JAoȰUUAK=¬>JAqUý²TUA•”ww=JAÁTOUANNG0=JA€[qKMUA1óv‰üëÄUAŒQ82JAnÌ„¿UAið é1JAá3O¾UA¬\™l•1JAfwf¡ÀUAhÍúU;1JA¡~æ¶UAXÿý1JA:ÒSõ®UAÎ×E0JAkZ©:UA$ƒy)0JA°¹wB­UA [Òü0JA=ÿø¼UAÁY°²0JA鉬³ÌUAlѱõ/JAàû.ËUAÖtÑG”/JAsÜ=>´UAÔI’A/JA¡P¸Ç¡UAŒ˜I¼.JApÈ€8ƒUA‚v³k.JA:8ÙbUAÿÐDLù.JAèã6UA§Ö}™€/JAËÆíç¾UA"8z/JA<5Ö˜ºUA0kßs/JAàû°I¶UAø|¸–/JA ´i ¥UA©1‰,÷/JAŒÂ|M~UAãß;0JA¡œˆzUAAèêUÏ/JA/ø~NeUAbŽ{0JAw¾ÚUAÔ2ž@Ó0JA’sƹûUAá¼×çŽ0JA˧cÅìUA(†R@0JA²ÿÎÆUA¶H8±h/JAÏyWÿ–UAï…7$x/JAF8ó§‹UAæQ™“/JA8Œì´qUA¦Žj//JAúiFUUApb|ÖÈ.JAÓBýÃ:UAj)±PÞ-JA(^,vUAÁÔÒn-JABô³UA AJ:-JA»ÕñUA èù'-JAòÍsUûUAéiûýø,JAéßÐ%ìUA¾Ïìâ,JAb¸ìåUAF`lÆÐ,JAû&ðrÝUAßýŒÙµ,JAñ¾ÌXÎUAçµ$ãš,JAѵ|¼UAÏEíyUA›’n§+JAÑõžiUAݧù™ž+JAãëðS^UA»ÈXš+JA:×|VNUA¡…ÿš+JA"Aš¦GUA¨ôz:§+JAJª‡¸8UAí{X'é+JAËDwÿUAžõÎñ+JAUˆ÷UABe™ô+JAl%&FóUA]êþwò+JAqÿú_ñUAìÓ¨+JA­÷ÉUAFÖ¨ZŠ+JAD1D¼UAPé×»ƒ+JA&dn¹UAîDáÝ{+JAÌp®±·UAv½f=l+JAäV¸UA~©§½*JA¯YMC´UA2ƒuk*JAÇгUAc+^K*JA~%²UAí3A*JAJàÎÒUA –;¤ò)JA9\ ÈUA.9˜ŠÐ)JA÷ÓûUAšŽY#Ä)JA†µŽLøUAð!”ÔX)JAƒÔ¥ÚUA; W?)JA~U¼Ž¶UA=<€ËM)JAÑíU °UAñF€µ÷(JAÒW. ˆUA’ÅÑ•™(JA–(áûYUARPwH(JAY¥1Ê?UA ñA&>(JAä´cß:UA´ÝØÖ (JA:-4MõUAJôrþ'JA³ö¸âUA«È)šÙ'JAhܘÈßUA±aÄ'JAÖ˜rQÜUA¼áíþ¨'JAÆ ÂÛUAbq¹w'JAŽMdPÞUA uHQ'JA” åUAûQft''JAo‘¥ðUA“¦'JAœ™}UA¯8ùÝ&JAMcþUAmapserver-6.4.1/mapscript/java/data/utf-subset.dbf0000644002461700001440000000054112261257215021726 0ustar tbonfortusers_pIDNKREIS_NAMECdKREISN 7337Südliche Weinstraße 100000 0è 10000mapserver-6.4.1/mapscript/java/data/iso-subset.shx0000644002461700001440000000016412261257215021772 0ustar tbonfortusers' :è’zþp?ùIA•þk©F¶TA'Jøº_JAt¨Û?,UA2ttHAhmapserver-6.4.1/mapscript/java/data/utf-subset.shp0000644002461700001440000026555012261257215022002 0ustar tbonfortusers' µ´è’zþp?ùIA•þk©F¶TA'Jøº_JAt¨Û?,UAté-â JA•þk©F¶TAÄTJA儽ÅÏÛTAm ¸»}CJ/JAïX^/½TA»ÕºN/JA:L¸ ½TA¥TæN/JA¢\¯ù÷¼TA7HSôN/JAÁ ó¼TA˜µ—³X/JA9鸻üTAáZº^/JAóEV ¼TAj\’`/JAÍ…â—¼TAié¯\/JAôÜç¼TA²QYrZ/JA^Ú[Œ¼TA·;ÕX/JA˜²®‰¼TAÞV/JAßèyƒ¼TA!æËV/JAöÏY¼TAÿÀak/JAÒ®Wµ<¼TAÎHcN/JA>tv.¼TA;"0 W/JAæ–˜Q"¼TAóþàÉd/JA«Â…%¼TA<\^Bj/JAۇا¼TA‰ÛÓæw/JA<0jÔ¼TAkÎÜÝ~/JA`ͼTAÆr/JA¦µ¼TAÑ®›{z/JA$Àq-í»TAÚî±™/JA´²™Xæ»TA;¹pcŽ/JA¡§^ëá»TAe.™Ž/JAÔ§ú¬Ý»TAk°‘/JA|Ý’§Æ»TAíÐ /JAãCºpÁ»TAi ,’/JAº s„i»TAÈðÔ¬/JA´»Çæ%»TAÅw‡Ä½/JA|Q_ »TA¼z·è×/JAAÖ2ëºTA u>æ/JAhhIb׺TAÎøEþé/JA +0=κTA„`Sç/JAÒ¸µ½ºTA³E³æ/JA`µ6—ºTA|æ•Éì/JAßÄ[~ºTAâÆ¡Æï/JAÅ8nºTA bœù/JAe{Ñ‚VºTA£#WR0JAM•¹Ì)ºTA\¬Wµ0JAŸÝ’C$ºTAëhPÄ0JAÊÈá" ºTA =ë/0JAò.5ñ¹TAF»ì/JAÄ&»Ù¹TA+uï’Ü/JA†W¢¹TAa ÚkÜ/JAxTw–¹TAc«ø/JA?à‹®[¹TA>ô- ù/JA¯2%`H¹TAÂà±öÓ/JA@ž§%¹TAa§ îÊ/JA2 )ǹTAQݯ•Ç/JA›,.sù¸TA .ñÇ/JAà¬AظTA\BòÁÊ/JAÄ¿Ã^ǸTA!ŒÒ/JATßJµ¸TA=?nÙ/JAÖ8~¸TA|æ(èÙ/JA`¢ ¬„¸TAÜÚ!—Ø/JA²Ä¡d¸TAéú¬Ê/JAónB–-¸TA‘Süî‘/JAlT(ê¸TA@dk‚y/JAA; ˜ô·TAcørnc/JAá•÷ÑÝ·TAu£«r/JA|ë`Ù·TAJ¦F,/JA öu‘¹·TA.çÕ /JAQ!l㤷TA-§v¶.JA—u_#ƒ·TAg$™²¥.JAV›ÁžZ·TAáÑÖ§.JA×-ÕMG·TA”úØ®.JAjmþ/!·TA¢O%ެ.JAÚ³ ·TA}‚¤é©.JAg±Þù¶TAy‚ž¶.JAs>ð¶TAª`y%Ä.JA‘…ž[ç¶TAÀròúß.JAŠB…ͶTA¦I=/JA ì+ ¥¶TAç‰ä¥/JA ÐHŸ¶TAñ¸8ÿ.JA¿ ½Œ¶TA¬ÀöŒÿ.JAqcÂvo¶TA½Ahë /JAë:Ïœh¶TAš#Zö.JAšÐ` Z¶TA ìu2é.JA•þk©F¶TAþ¿µã.JAL¨=P¶TA{É"Þ.JA§ źT¶TA–©¾ Ö.JAq©|bX¶TAwiÎ.JAXµE™Y¶TAŨ².JAqŒ¾)V¶TAp?™N£.JA@—¼&V¶TAkƒt–.JA[Ý*W¶TAÌÅY.JA4•ÿY¶TAA×9‡.JApôñ[¶TAã68ƒ.JAkÌ&_¶TA¤9oùˆ.JAX¼d¶TA/+5‰.JAsÒWh¶TAе.JAuí±m¶TA»ÇÇ?k.JA£SˆLm¶TA\¦É `.JA‡94ýr¶TAaêâV[.JA禣x¶TA';AAl.JA`@ÏÎy¶TAkØ}‘s.JAÚ)ž|¶TA~2çi‚.JA{ݸ’¶TAŠÒÓ®}.JAí»™¶TA)”q.JA72#Ι¶TAÓÑp.JAÊ¡¶TAxas.JARŒ½œ¤¶TASÁäßy.JAcYîD¦¶TA>Œróy.JAw±I5¬¶TAÜl±j.JA­ÜŲ¶TAlõ0e.JA9ŠúUº¶TAÑ“àÐZ.JAug‘ÞÀ¶TA€ ˜™`.JAÝâ9|ʶTAhš]-K.JA˜~=Þ¶TAŽÉH.JAÁ…œ å¶TAlC«îH.JAÙOÿé¶TAÙšØM.JAf`ïï¶TAªêå=.JAmáïÑö¶TA½|±Z/.JA\eø¶TA<;+‰.JAWNW>ú¶TA¸Æëï-JAJgDè·TAhK¶è-JAMA]=·TAqâ©úß-JA½Â‰? ·TA½ä9`Ö-JAñ(·TAf*(Ç-JAùÀ«Ë·TA2g÷»-JA¯×g ·TA^àNé¢-JAçjÓm·TAl œÞ…-JAµÆ«Â·TA.rþz-JA;{y÷·TAždAx-JAî"² ·TA“Fq-JAüÎÕ"·TAFk¦i-JA) ²ƒ#·TAØÏÞs_-JAëÏúT&·TA4‡BP-JA·ˆ.·TA÷I-JAã±iº3·TA¿ªpÁB-JAÏð4Ž:·TArý<ˆ<-JAúŸNqI·TA¿ÔÌ/-JAr–…æQ·TAb²¾,-JA·:P\·TA×Ì–%-JAs\N%c·TAÅu¤Q#-JAjÃà j·TAd¯±-JAw%*p·TAn5Je-JA-&öv·TAâo-JAýù1Â{·TA÷û{¶-JA{T¤„·TAS­FI-JA±Ê¾‡·TAîÓyÚù,JAÄe%…·TA`ÕÔæ,JA/$þƒ·TAxÃ?Û,JA›ãô†·TAæA¸Ì,JA@³ú‚·TA;‹(Ç,JA}Jñõˆ·TA)q]¾,JA‚o» ·TAUvÕ›µ,JAh–’·TA„(2B¯,JA™·TAåíÖ\«,JAZ_`¢·TA:\%‡«,JAPü1­·TAùx˜›,JA”ÍAC··TA¥`‚,JA¤ÃØÅ·TAÊÚ´g,JAuä– Ø·TAœ×¸¢O,JAѺÜ·TAúž,=I,JAPvÃß·TAÖùH,JAÄScå·TAü6ª?,JA©Ç^uç·TA¬- ,JA¬Oõè·TA†ýÿ+JA…-åâ·TA“QÕ©ø+JA¿žúÜ·TAKÔ4ò+JAz¶mÛ·TA’¶%æ+JAaIˆÒÛ·TA© dëÞ+JAÙâ NÞ·TA3T ÉÃ+JAÖÜ‚ð·TA¨ÿJ¼+JA»5Cvò·TA´ÎÜŒ¸+JAh¼¾ñ·TA¶ñÌ¡+JA>Õæ0â·TAÈûΙ+JABq$yë·TA¨Ò‘+JA¥ í·TAŸÿ¦—+JAG¾]ø·TAñÙ'oŒ+JA@_¦(ý·TA`çJjˆ+JAÜÞ›Ÿÿ·TA³—–{+JAÎ.ŒK¸TA‘Þäq+JA ’X¸TA.õþp+JAÆd]äú·TAoCñ`+JAwÜ“Sý·TAöiüÙT+JAl‘®Óý·TA‹yðüK+JA‡´Jü·TAÑâ¾C+JA-c|ù·TAP7Ñ8+JAÂÔfú·TA °H 3+JA, 1ý·TAYÙ¬4+JA"áTðÿ·TA0ð0í?+JAë qõý·TA&“ÄD+JAQƒ^¸TAxÑëæH+JA¬ÅŠ´¸TAl[-+JAO¸TAm…“%+JAäošŒ ¸TAgÇÔ·+JA8GìϸTA+JA]\×=¸TAxÃÖ+JAˆ´ôò¸TAÅÔƒÒ+JA)ã È¸TA  +JAˆ¬¦g¸TAËÁ|Ùþ*JAd¤¸TA·ï¼û*JA;0­! ¸TAœ Œóí*JA0¸™Ã¸TAO"U3á*JA´Ñ¥¸TA«nŽøÕ*JAÆ0ïy¸TAêýó°*JA2ˆós¸TAYüšž*JAFü\_¸TA:Oꦄ*JA•`¸TA’ôÓ8z*JA`>Þg¸TAûçõÕg*JAÌz!¸TAÐë ]Q*JA¦À9%¸TA¥‹§ËG*JA.!g¦+¸TAz%Ùé>*JA8ºr!,¸TAq¥\Ð3*JA‚X±m5¸TA‘¸/*JA ?<¸TAµ=´(*JA!#LA¸TA‰Ns!*JAëmA¸TAE¯P‡*JATÐ6„?¸TA0ùÁZ*JAþs¬G¸TA‘˜*JAÂ÷îI¸TA6ª*JAJ¦¬iP¸TA„÷oH*JAx©ÞP¸TA.ɼ *JAس¥M¸TAæ»Þ{*JA-i_±M¸TAdbh}*JAs»O¸TAUNàþ÷)JA2ó]Ç[¸TAx‡·òë)JAþˆ×Y¸TA}ÎÔÛ)JA —ZX¸TAŠn Î)JA0õ S¸TAè›R(Å)JA[æÄR¸TA§`[¼¾)JA¹ï úS¸TAõFø÷±)JAòüi\¸TAn.®)JA"ÓÃa¸TAL üȯ)JACV÷h¸TAÒÕ{¤)JAmž„rg¸TAQl•¦i)JA-ƒ²qf¸TAÞÝ ¼d)JAL°_¸TAÝåzua)JAE‘o^¸TAõ#:Z)JAï/T_¸TAHcüÐS)JAÃaö`¸TAÁÌäO)JAÖÓtg¸TA®œ@J)JA>K~g¸TAa+Q4)JAù†–µ\¸TA¶öm+)JAöçz™[¸TA7¼êž")JA™¼¥]¸TA|=¡D)JAµ)©@c¸TA ®{-)JAR2íMc¸TAsS )JAi¬`¸TA>ËY<ó(JA¢ü•7b¸TAå;s}å(JAm•ß¶`¸TAåsÊ(JAª-ÕÄ^¸TA›Zû ±(JA0(Z¸TAͤçE’(JA`GW Z¸TAñ¿K‚(JA7VíY¸TAV[ŽLï¹TAÝt”&JAu”¶°Ý%JA/T~œA¹TA?Ó¨ºÙ%JA‹B³ÑD¹TAÅLå%JAô2léE¹TAB3:,í%JA“ˆªßN¹TA©¤7׿%JAýÙR¹TA9¹výÕ%JAd½JÐU¹TAæÕ •Ë%JA•öÒŸV¹TA’iA²Æ%JAÎ…ÀU¹TA¤#^ÛÅ%JAÕÇ5PR¹TAЋõÍ%JAÚŸÉÏM¹TAl.‹dÏ%JA v¹TA}!o=Ú$JAñRíIw¹TAdÈÈÏ$JA‰q!|¹TA`~ü³É$JAPod7‚¹TABBê-Â$JASéˉ¹TA5«X¹$JAùÔÞZ¹TA£ˆX²«$JAq÷q¹TAY³`ÃŽ$JAIÿ]Õ‹¹TA°Ÿšžz$JA @óHŒ¹TAFs€j$JAÍ?ֱйTAúÿ¦a$JA‘I’‡¹TAD~áóC$JAÜ£޹TA$A6$JAÖ)!–¹TAö~:Ã#$JAJ©1¹TA¸‡$JA‰”Lª‡¹TAÿQõ#JA0'÷>‰¹TA$‚©lã#JAZQ¢‹Œ¹TAÆ&Ø#JAsç~船TA©¼D¦Í#JAÐÖ¿,€¹TAKMÄŠÁ#JA¿Þz\y¹TAÉ_5þ¿#JA7³†S¹TAK+Ÿx±#JA¡²Œ"~¹TA%_•’œ#JA…qh¾}¹TAhÎqV™#JAW§“n{¹TA°x­[#JAþŠx¹TAѹr4®#JAÚZa^w¹TA0><²#JA¿Êãr¹TAÂ:þË’#JA¢Ci¹TAÜ­¬õ‰#JAZÚo¹TAuм~#JAæ7 ”p¹TA€Vî¥v#JA%¹6Xm¹TA@,Sg#JAŠ3öd¹TAˆXAê\#JA2¿‰6h¹TA ¼ç-G#JAŒJèÓg¹TAe|«RB#JA˜܆e¹TA¦éè?#JAñ(d_¹TAªÖ`Þ?#JAšÂ5ä[¹TAº¥!JAÞÝó›¹TAl þ¶!JAaaQ¤¹TA…r­·!JA¥6ǃ©¹TAÑH„=²!JA@JÖ“­¹TA]êåY¥!JAUuÿ¯¹TAãäI•!JA,á´¹TAžFЊ!JAõù¦¯¹TA-&™{!JAR1´¹TAàS«Kd!JAE¼Ž`½¹TASwYK\!JArpÏŹTAèš«$z!JA’J"”Ö¹TAgý>Ž!JA“êñ]Ó¹TAËg1Y–!JAÅG¹8ܹTA—(éö—!JAº´ÿÔá¹TA(»5—!JA&n_uç¹TAJs’!JA~u$ñ¹TA+gÃo‚!JAš•ºTA¦Xiño!JA§èò)ÿ¹TAοùîg!JA·bGºTA/t\¿`!JAºý­ ºTA£VWže!JAòéÆâºTA;ç)X!JAšSºTAM@QºL!JAæ›)ºTAs~°Rf%ºTA}›¶I!JA=±„?ºTA^ilK!JACq´+OºTAA»I!JAGüÏWºTA†‹;hC!JA@ǰXXºTA¦åŠ“6!JA¼— kVºTAFXÿ JABKn¨KºTAÇŸ'æ JAñDU!JºTAíFê_Ì JAÕæðJºTA”‹ªÌ¥ JA.מbUºTAñ Žˆ JA‚ÿÊ)cºTA¬·­ù JAŸA³…ºTAmd.ƒ– JA}«ûu—ºTAº›¿— JAýœ@‡šºTAYŸ¡k• JAÉcsÉ¥ºTAÊÕn¤ JA|‡áѳºTApÑï‡ JAáÝE¾ÄºTA{-ºö JAŪ_ÈкTA¨U×/ JA‰v'¾ØºTAú´a € JAu*àºTAW¦„ JA AIíºTAª`cƒ JAõ \íôºTA{­Æ^{ JAŸ…yXûºTA«¤ßè\ JAO7Ó »TA±±6âD JAQP…»TA$z LõJAÛh¿£»TA_ÚjêJA^Ä …»TA$·ÑJAîšC¼»TA8­ãY³JAŽep.»TAÓf‡¢JA¹¬»TA<‰IG,JAQUm »TA*ŸkJAG|à"»TAcj ] JA'Ìu¸5»TAWÅ w$JA§$ô@»TA¼SÁ+JAZ:T I»TAkœ°8JAð(%ÈS»TAí´ JA>v:¼Z»TAb†R JAï#J^»TA ÕrïJAß…2\^»TA}j%êJAü.ëÊh»TA¡|N\ØJALÌ,¨i»TA¬ÀãjÔJAw¶¾q»TA%|²½ÆJA=+¢}t»TAoÖõÕ­JAB;<Ôu»TA˜ -ñkJAîµ-X~»TA7€!aJA²ù3™»TA~KOJAUèØŠ»TAy´›8JA¬xÁ>»TAŸxÈJAm¯ª—»TA‹¿s‘JAvX§»TAå tJA`YQª¶»TA¤Ht$JAÒ#ôÀ¾»TA}qÒJA„¿ßÌ»TAÓ|`ÑJA4£¦îØ»TAyqªŽJAu¯ˆÝ»TAlÔJ–­JA–å¼TAªê̺œJAs»@=¼TAý‚ÿ°¡JAÝ4‚*¼TAKíp© JANn`:.¼TA|X>‰žJAýÅ5¼TANë?¤JAÖˆú@¼TAF=öJAé#à Q¼TA(›•ŸJA[s†[¼TA#[‡IJAùžšŠb¼TAÐòÇÜšJAW“˜ûi¼TA¾ÇˆJAÚTK©{¼TAÅ%4Î0JAªõv™v¼TAÞÐ|ë7JAœÝ(Zc¼TAMK*"JAÉŽb¼TAOqÿæJAL¯Bß]¼TAɉ$ÎJAƒð޲‘¼TAŒyJ#ÊJA-” .–¼TAE§‡z¬JA<`k¡¼TA>ã×qJAgtg¨¼TAô[Ý1dJAœgòÿ«¼TA×õTJAOç|6³¼TAröñ…JJA¨ÉÆw¶¼TAµ×ÕFJA±IÓ»¼TAeîEkùJARf¦CÀ¼TAû:ïJAâ¹íÁ¼TA"å‚–’JA¨ RüTAm¡%ùvJAWYdž¼TAïTë¾wJA{‘,—¼TAt[Jz€JAoí˜^ˆ¼TAêF†JAƒ7=|¼TAëïï[ˆJA_ìŸ@r¼TA®WÚ…JAû‹Ó)d¼TAþí1¿}JA†í$Z¼TAÆÌ­)JAé<5‘¼TA‚'¥JAwæk« ¼TAÊö½dðJA'|„ú»TAþ3—ÅÝJA©ýsHí»TAÉѵÕJAõS¨ æ»TA‹Æ”ÇJApx§Ñ»TA<Ž_ÁJAÅÆ»TA¡Û›³JA‰ ˜·»TA¢5|²ªJA/°»TAP%¡ªJAN½Ä³¨»TAÁhö¬JAj4(Ö™»TAªoC«JA0ú|M»TA÷K—¥JA¤¸r߉»TAD)!ŠJAbÁáw»TA÷Wo€JAƤ6lq»TAõ¶c|JAxqtÔk»TAìüó²zJA[;b»TA ðe0tJA~òfU»TAŒœ3ÆdJA©MOÐE»TA¡›|GZJAëømþ>»TA44þcQJAì\8X;»TAî+=|@JAc “À7»TAü§Ð¼&JAÛ(Ê_3»TA6Š\JA Ð-»TA­Nl üJA:µ|ç'»TAk×tÔJAH›7»TA"÷¥¾JA¡±…?»TA„œk½±JAíh ûºTAG_m¢JA|‰…÷ºTA L>KŽJAEþ¾póºTAN¢_JA¯¾ðdòºTAÀÀ24JA"ÓâîºTAôÝð„&JAOtîºTAå"þ JAÕÙxèºTAsìoèJA8QÇÚºTA _œ€äJA´fÂߺTA]^ÖWåJA„h)ÐçºTA¼‡ïJAi mõºTAÕÅejúJAϸ ±»TAB2ª~þJA¬¢žž»TAñ¶éDïJAð)ß²»TA_ 1ÛàJAqµÃ\»TA\3Ô‹ÑJAoñHÊ»TAò°™ÅJAÈ'¦»TAøÇ‰µJAÀ´[ »TA#•´û«JA–WO6,»TAGî?[žJA‡ÐÈC4»TAÙ²-Œ‰JA¯ZÚ”C»TAÅíýƒJAØ5¾L»TAøú GƒJA±ïÐùU»TAƒ/·r‹JAѸne»TAÍp¦JALÕÐìa»TA*üƒøôJAh¶Z»TA ¿ë&÷JAþöçØ`»TAFJùJAÃ_AYf»TAt;hÍúJADÖp»TA–}Z7JA¡`ä‚»TA³)u5JAm;9ÑŒ»TAW1(JA\DZ»TAs‹ØJAjxج»TAC]¿§àJA¡E²Â ¼TAÖü |ÝJA2#ÈD¼TA#Ä@/ßJAåV¼TAÍ:˜«ÙJAL’ Ž-¼TA'ÕžÂJA"ŠŽëN¼TA…ÈN°JAk#|´f¼TAˆå&¡JA“Û)`r¼TAµÎ6[˜JAíädz¼TA+, t˜JA®͆¼TA?¶ä’JA~Wú8¼TA Ì\*ŽJA>­ïš¼TAàßR~JAú7Ž ¼TAªÙ9]JA’NO¦¼TA§J÷JJAxiJ ¼TA„^ܸ JArœUX–¼TAª’íÈûJAÀì1•¼TA7‡›+îJA=¬, ˜¼TA$cðæJAßIÄÔ–¼TAK )½ÎJA¼ÁŠC¼TA=Í­ö¸JAÔ·xX…¼TAϬ»¦©JA0 J'€¼TA[@qB’JA|‰˜z¼TALÚŽtlJA“^~ u¼TAÜ`ße\JA-3t¼TA¨ëcPJAÁù¦fz¼TA™îÖµJA¬]¸f¼TA<-Ùo JAö¹Ã‹]¼TAàþ±öJAJA·E¼TA† úíJA뺒°<¼TAp$ûîìJA šœO4¼TA¦JÆKïJAwì¬.¼TA³ØžnöJApd%¼TAE#7/JAœÐíÔ¼TAù€ŠJAOŒ£"ÿ»TA–oŒ€!JA±Ü"õ»TAïzBk!JAÇpÿí»TA¹JA&ÝXÞá»TAyH@ÆJA¤°¡Ù»TA6"1üJA ô¹­Ì»TAo0 õôJAÐI Ì»TA 4N ÌJAëÜódÚ»TA¯}jºJAç_/¡á»TAí¾‘Ã°JAŠÂ#ä»TA_XÒ‡JA ÚæAè»TAA­\tuJAâ`F‡ì»TAúÊ»ÚUJAj2¼TA¼É¥6;JAÉŸÿ„0¼TA[&o JAŸWÅJ9¼TAŒ: IÇJA®nu•F¼TA6úc´JA6q,ûS¼TAÆ©€JAG£‚¼TA =rª†JAQÉÙÝŽ¼TAƒ&'±†JA°édùª¼TA™÷m»ˆJAÄ‘þι¼TA^Ž$›JA”yõ¤Ñ¼TAqrl¢JAÿ9aæ¼TA¤—¥JAÃkz•è¼TAqÜ#R«JAÉTï¼TA„³“®JAëòìŸö¼TAEg#‹¯JA‡Mv{½TA¥ŠL-®JA×4'½TA Vë³°JA©dRn2½TAþsû¼JAÝ´vP½TAßW_¨¾JAË*ø©W½TAÑë°Ä¿JA!kj}½TA…ClÃJAqò±‚½TA$?'-ÏJA+S½TAD%¡ñJArű ½TAɹ JAéëz™¬½TAE‰EkJA¬ÓÕ³½TA—Nf $JAbp¦ÙýTA¢ *JAtÖ÷àͽTAt *ž.JAÜ*sxÓ½TAéA§.JAdãF>ؽTA~OUª;JAóÚ”÷é½TA¢Œ¡P|JA ˜O÷¾TAz©Sþ«JAúêd";¾TAÓÙ’°JA<“A¾TAà÷ó»±JAg÷~ÂF¾TAÕW¨²JAáº×DS¾TA†ݵJAµ® ÚV¾TA¬ ¶ò¹JA_ê&Z¾TAk¨XÕJAÄpFBe¾TAøìßJA`üë;k¾TAQÖ 5ïJAר9y¾TA‡ðÝVJAs/lò¢¾TA{fSÓJAèUm…¨¾TAj žÞ JAŒý=«¾TAׂ±$JA êU­¾TA{K¹4JAѾG\±¾TAl¶q6JAn±µ¾TA¤"‹D+JA4å¾¾TA ±â(JAOàŸÂ¾TA嘊*JA`3ÓɾTA/-‡+JA޽Ÿ²Ü¾TAl×.1JA±¸Çuå¾TAúô9Ø2JA2Ìë¾TAGþ–4JA€eÔ-û¾TAÚHç7JA¦<,ý¿TAõðø–1JAi+d} ¿TA À¡}!JAvýˆ¿TA3bJAìºLÀ¿TA…òYâJA˜"èÛ!¿TA¢Q”ÆJAT^.¿TA>–+©§JAÊêH¶7¿TA· jüMJAS¹¶([¿TAîà yJAlŠ—š¿TAje†{JA8è`£¿TAï4UxJAÇ(¦¿TAÞðÈkJA¥i«¿TAsëâJAuQ¬†È¿TA€MûK%JAN’à¿TAÂÑ[m:JAiBÌý¿TA5ò?¼EJAïpyÀTA ¾u@mJAqÇuÀTA¸Ì`ŸJAfBOåAÀTAa ´ ¥JAú0 GÀTAiN΀§JA¹çAVLÀTAû¨¥JA·´PÀTA˜@ŒŸJAMWFÆTÀTA_þfO”JA*y²òYÀTA€äèJAÊ`ÀTAf)xFtJAæ “ºcÀTA{TlJA&3ØàhÀTAè6Ç^JA^Z@xÀTA*0ߎJAaY‡VsÀTAù°,¤¨JAÅÀ–uÀTA+­|.ÃJAÆ¥ÁTA§˜&QãJAJCTr\ÁTAIÑ•âJA&fbÁTA¬DâéJA’è»ëhÁTAÖm2\JAðGAÁTAiîAÒ3JA‹@Zc’ÁTAõMºÐJAv,0(ªÁTA0¿ÙJA~bˆ¹ÁTAee¯JA(½vÐÁTAb¯‰¸îJAÊxxSÍÁTAÏOpó·JAo·ÃÌÁTA4àºb¢JAçL‹ ÖÁTAÊn á˜JA¹"}ÞÁTA¥-xJAÑëŒÂTAÜò¤aJA#8Ü'ÂTArÑq xJA¹Ý+QÂTA·¦}‡JAبþpÂTA8ØìJA!k>ÂTAìE?œJA*ÃTARKRNJAc²!<ÃTA x~+îJAr©–N<ÃTAB]üdÅJA”‰é#&JAnÝ0ÃTA¾@ ¤ÆJAÒJäaVÃTAmÜÖMJA]- %gÃTA4Ä_“JAÐ(;gÃTA¤`@isJA78©VgÃTA‰ŒÅ?PJA©l%Ð`ÃTAOå"p+JAv¢ÚŠWÃTA‹)šhJAʬlFÃTAÄΧRáJAYw35ÃTAøèþé×JAOÑ0ÃTAê÷áÄJAÌ¡n7ÃTA}xaÔ‰JAE¥óVÃTA²mˆ6|JAw~JATò¬&¤ÃTAõJ,~JA¡{»‹§ÃTAè,0}JA4ŽÃÃTA¢6„$yJA‚êx&òÃTA”¥GÏVJAL%]ºÄTAO@ÁJA ÄTA¾~øµóJAßÄ'ÄTAu–ìJAá–M/ÄTAFÓ”\ÁJA1R6›kÄTA1Ÿ7¬JA$Ÿ©ŽÄTAì㌧JAp1é—ÄTAÞÆ:£JA#†-¶ÄTARV;èJAÕ‡iÇÄTAßnl(¢JA³ aÕÄTAº®é¶JA ZrÙÄTA™î×nJA« ÷LÝÄTA°še:@JA‹û7NàÄTAÎ:á¤JAü«KåÄTAÜ™]îJA©ïíÄTAÄfµ¼JAUص£øÄTAvXD¼JAÛ …ÞÅTA›2KŸJA±}4,ÅTAcåü ¦JAÇi»ãAÅTAL.¹·¯JAt¥WÒOÅTA|JZßÀJA¢5TÐ_ÅTA£íWÇJADùâ bÅTAð›ÎJA³ûkcÅTA)ÖW JA£„!eÅTAV`tõJAÑX¦iÅTA?¥opJAtí*‡kÅTAÍÙPæ JAÚ÷£†xÅTAH–ƒÃ²JA¨ÎåPƒÅTAÜ/-oÎJAdz Ò”ÅTAÂ! WØJA£ÀVÚ¢ÅTA4ËwÝJA¯ÑͱµÅTA•lü9âJAzØJ<ÃÅTA‚åJAQõ”aËÅTAAŠXÚJA'G&TêÅTA´âæJAxëvóÅTA."ÁJAðxÆTAvárJABÞËæ!ÆTA7!¸ÞJA­M&ÆTA•¹k¾ïJA¡ø× 8ÆTA­iOêJAѬãÆIÆTAAÅE©éJAn®8çKÆTAð~KJA®ÌÆðkÆTA,áÆwJA¤óÊlÆTA7\ÈJA.žvÆTAË&YwJAêšLO…ÆTA'®uJAѲ›ÆTA<öX‚JAJÅ;„¯ÆTAûN뽂JA‡0ºÆTA%†kœ{JA‰oŸßÂÆTA0TyJA·Þ­ÉÆTA¡ŽgJAWNøÒÆTA OçˆJAù²#ÞÆTA¼½‰‰JAàÌ7/äÆTA8Œ¹‚JAÊbsÞëÆTAH2qJAÄŽ(ˆóÆTA¾7ˆ fJA¢UJŽùÆTA¦X5UJAº ûIýÆTATþDUJA&zxÇTA+i †JA/ÏdÄÇTA ¤Æ’JA8 šþÇTA+@èé–JA ÝR"ÇTAÂ¥™˜JARÃDÎ6ÇTA4´5ޝJA~>ßË>ÇTA´D½ØJA·‡emKÇTAÕlR*ùJAÙpN[ÇTAvÂÂŽJA‚Fî°aÇTAXurYJAÈsYlÇTAÄ;¹’JA@át5xÇTA؇áE JAÕo¸ÇTAŒÂMJA=‰U‰dÇTA¯‹Ú•JAµƒwUÇTA@Yø¹JAºˆwÿOÇTAy êJAíàgJÇTAhòlÑJAoþ.rHÇTA5%@JAgôÄEÇTA ÑD^JAä!>)ÇTAdóDêbJAƒ¿í $ÇTAð_°GVJAÉgÒÐÆTAqMÙŒJAú½4OÉÆTAx(5b£JA»Ú|ÌÆTAÆTAš0AæJAó(†þÅTA¤ÀêôJA†–Š<ûÅTA'ÌoýJAÝßýÅTAo‚ë­7JAŸÝ¦õÆTA¾b± JAlšúÃÆTA¦3ÐÄJAׇø2ÆTAõ˜!{JAiÒÌGÆTAÖI"JAoÝOÆTAT&Æ5JAÎã-Ž\ÆTAsãRLJA¡àÆçhÆTA@YbJAb—Ö§qÆTA¼ì¨îkJA§tutÆTAâ+ÛJA{’Ë—yÆTA¹»ä»JAì× „ÆTA˜†€ö¿JAÎgb^‰ÆTAµEmNJAuͦ’ÆTAqfM˜JA†¨BÁ“ÆTAŒ{ò;2JAÓ}Ë¥ÀÆTA"uOÊöJA‡&ò#ÂÆTAqªº‚ÎJAÑŸ¸¾ÆTAö³8wÂJAÑiþÒÀÆTAÒ÷èO³JA®_'wÈÆTAS5²4°JA)ËÅFÏÆTA¶ø‚î±JAâ‰ÇÔÆTAý¾-n´JAžª±íÜÆTA¬À·l¾JA\è,òÆTA=|@?àJA¬£'æôÆTA" úJAÖ{løÆTAœûdîJA‡ŠûÆTAþ´ÙJAŒ8gÄ ÇTA(Íÿq$JAw ¼ŽÇTA–ݨPJAÍäïOÇTAx+¾ûXJAßÐåÜbÇTAe¾jJAǤ5iÇTAÎñSòJAz³uÇTA~ŽË²JAI™'NƒÇTAÌ~wÍJAzDL’ÇTA”ØÀaìJAþ½­¥ÇTA#H{ýJAŒ`©³ÇTA iÎÛJAÇÂâ¾ÇTA]÷vTJAâé¾ÇTAã5W eJA¯õè|ÎÇTA`8Éa…JAÇ7uèÇTAÀUb…‰JAâ6ÛéðÇTANM§(”JAùÅ/ þÇTAÏõÚ¢JA¸G0Ë ÈTA-sSá¯JA)MuÈTA½êtÏçJA/ I5ÈTA¼ µ¤ñJAK7u@ÈTA—oŠ/¿JA’ôÏ#OÈTA­* ÄJAKMlVÈTA00\ÙÅJAòƒ¢]^ÈTAÃ5zÀJA«U=nÈTAå¯ÃJAÑŠ—¸uÈTA]á{`ÒJA:›¨{ÈTAû«˜ÖJA?pr†ÈTA‡–¶áÕJAÉ ëŒÈTA,|yp˜JA”vô‹¬ÈTA¶E„¾JAÅWIFÈÈTA¢ÄGºÏJAdáÔÈTA‹Ñ JA£§ŠÉTA¢?çw÷JAB” ÉTAœ÷2ýJA´f¸ï"ÉTAß)íÿ JAŒìr˜,ÉTA”DJJA ‘ÝeÉTAÎi­JJA§ü—!ÉTA"$MJAíS?¾8ÉTA¹WRÎ^JA ÛѼ:ÉTAO÷(£JA‹}´;?ÉTAÁ¸å¥JA˾VÉTAŠ'î ¢JA´&úΞÉTAº”‹¡JAí}1§ÉTAû{¦`£JA\åýL·ÉTAuNŒóÏJA*ãFlÎÉTAtôÒ·JAs©lÞÖÉTA?Ë:1§JAö`œÜÉTA'wajJA'x6ìÉTA±*-ô3JA»‚AýÉTAØdfMïJA: çÊTA[ZçJA=±êRÊTA‡2SÁ×JA,]Úû=ÊTA!ÙǃÉJA(•ïLÊTAÔ7lJAÈÉ×KoÊTA:E'W€JATá"|ÊTAuOÊ>cJAuË ‹¤ÊTA$Ƶ¾JJA‡ñ¤ß¿ÊTAH'ÂÅ;JA4z«ÜÒÊTAœšâÀ,JAöõÑáÊTA9i¹9$JA€€?ïÊTA¾ œ‡"JA¤þéñÊTAmD<JA¤ú:HËTAC2 "JAÉfQËTAõêFJAÐ(ËTA¼”ïQýJAFødËTAÔ—y6ÝJA´Û^ËTAØàÁ™JA‹ÖÔËTAœÍ‹{:JAü§Ûœ-ËTA‰JAæu¡]/ËTAˆË„ýJA{ƒP4ËTAÓ¸‘‹ÄJA Ø÷ø8ËTA›kP¿§JAôs¬¶@ËTAgzx?JA·Nv1ËTAf6:ùJA®Æl76ËTA2!ˆçJAúY¸T4ËTA}Ý"ÔÑJA*†+¨5ËTA¾R¸äJAJõ\¿LËTAˆ…LÅñJAgC²UZËTAv­  JATÝ…WbËTAö¶T*JAo4FmËTAŽK¹W?JAI2XuËTAG5UJA/º€ËTAÔ_úNnJAžœNmŠËTAaáp~JAÕ$”ÃŽËTAa¯å8œJA¤ñj•ËTAP`|CµJAP4ëlËTAåöìJAÈþí¬ËTA¢3JAM!{»ËTAÎàï„VJAìd `ÁËTAÞó÷ýŸJAqÙµØËTAâ™.Ô½JA–êáËTA’Ý/#âJA6¨ ºéËTA">ÿJAùµO;íËTAÈváVJAf;WúËTAœ¶:‡JAæt¾æÌTA×ĵI°JA©Fµ ÌTA 3P ÊJA4ÆisÌTA°'°ÊäJAþ|{ŸÌTAŽ~&0JA<ŸçÇ?ÌTAu=L FJA?=ÚHÌTA­–:wJA?öBÑOÌTA$¦~†JAHÊó¼SÌTAïðfºJAÁ~F kÌTA|_ûwÏJA^ç’âsÌTAþ2ͦßJAÕ­u÷xÌTAòlxùJAýVg~ÌTAih'JA˜4,Á‚ÌTAá¼YÖJAìθŒÌTA8ÙúJA©¥ŽÌTAÕ”QâJAg­ì “ÌTA á_·JA6ÏþÁŸÌTAœˆJA™xõR¢ÌTAMŒµ•mJA¡ËÕ¢ÌTA9,óyjJAÓþ×»§ÌTAjÈKñ^JAxÃÌTAttãEXJAŠÆŽ?ÍTA¤O* JAFômE<ÍTAGQøªàJAPÓX™7ÍTAúT.©JA{<7®0ÍTA)‹;²yJAjmO-ÍTAG NRJA¢ Îå+ÍTAèÒWJA°=Óõ+ÍTAwïÌ"äJAMVúL)ÍTAÿ'(¬ÏJAéh;X>ÍTA6¶©_ÂJAé4!7QÍTAI×5/´JA†>)#\ÍTA"%•JA£—®jÍTA™âp šJAð ÔmÍTA™´ñLÔJAg—|E…ÍTAc¶Ú€ÝJA/sw~–ÍTA`)_…ëJAŽ˜l¨ÍTA¼²f JAeüÔ¹ÄÍTA ÐÖˆJA¥†µÒÍTA'v8(#JA^RÝÍTAv\Ô/JAнïûÍTAdé87JAw`ϯÎTAÇS«FJAù¸¼è ÎTAý¯ýêJAsÞUaNÎTAnÊoq¾JAO¶;dÎTA´`‚ZJAu9†¨‰ÎTAsg(ÿJAÄe…Þ³ÎTAyON"JA $žÖ¿ÎTAŸ­FÏ/JAn¿½ÆÎTA‡‘z8JA¿þËÎTAò×60JAºúÖÎTAÎ5í8-JA:6_õÙÎTA2Zõ©*JAm_ÝÎTATxq@AJAؼá‚âÎTAÜ|k JA@ÞãûÎTA®ÄMD JAB¶ä¯ÏTA/HJAî€õÌ+ÏTAþpŽJAÜ÷3UÏTA£”_JAmF,…nÏTA”Ý´wìJA^,rñ“ÏTAj3ÞçJA9’¬ËžÏTA„¶] ÙJAKÜ\±³ÏTAîx_–ÓJA/p{b½ÏTAÑ6ø²ËJAˆ™]ÎÃÏTA’fÀJA}B7‚ÉÏTAws…z¥JA×l@†ÔÏTAcbõ.‡JAž uJÞÏTAAð©UJA‘d…ôêÏTA<¬¥1JAN ƒòÏTAç9_ÌJA"Z^ ùÏTAkR_¤üJAzÔGIòÏTAâLíöJA°àríÏTAëª(ŒçJAJÇ7çÏTA}S•ÌJAÀqÒàÏTAgî*¿JA#Çc$ÜÏTA±ä“9‹JAú+¼J¾ÏTAêŽ`‡uJAËܼÏTADÇÞïNJAZòq»ÏTAÅùyÜ6JAôÚ0]¼ÏTA¸Ôw8JAôZ ÂÏTAÀ)h<ùJA$ú)ðÅÏTA9à•ëJA¢ÒJ[ÆÏTA!ÀªÒJA ÄMDÅÏTATPÕÁJA||5=ÆÏTA“«Èa¯JAvhsÉÏTA¶woí‰JAHý ÔÏTA<Í`]JAMý|=ÛÏTAÅø‚?JAIèéeáÏTAó,Y&JA;úqPîÏTA ` zJAq‚ÓØúÏTAi¯^ JAƒ©{ÒîÏTAkñIR JA‚ØâÏTA=ŠÆoJAÉ+3ÝÏTA¥m\JACk:ëÏÏTAÑèUk JA¨F4ò¿ÏTA+±-?JA²¥¹ÏTA¢~#õæJA³ƒ#«¯ÏTAXÈ@ÆÊJAÊ"fÿªÏTA\+Ü©JA†T ¨©ÏTAÔ·tZ“JAc4"ªÏTAµÔ¾mzJA]6À2¨ÏTAa¬±é_JAa†þ¦§ÏTAqå e=JAƒ¢ø¨ÏTA+!þ*JA²³L¶¬ÏTAÝaQ_JA‡Ç®ÏTAÖm$pJAµì¬ÏTAÚT}»JA[Ɇ²ÏTA׋n,|JA-]§¶ÏTAüc \JA2Ç@5¶ÏTA%½íƒAJA黡дÏTA>$gñJA?ÕÃÈÞÏTAŠê ¦ØJA­{ëÏTAHÿçìÀJA3 ÂDýÏTA[:)V¼JA—IÐTAŽ‚º¿JAU§ý¥ÐTAÑö¿JAØEÔ ?ÐTAFÄ'³ºJA‚ѳRÐTA¦i¹JAÑTAKÙfÙ(JAÞÕ2RÑTAB«ÖM/JAÃwøÑTA`Ï“.JA¤¡•ÑTA¤ë%J JA.?S ÑTAºz6JA-f.Q'ÑTA¥áÃ,JANè4FÑTAíê¶JAp3QNÑTAU¨oôJA«Ï< VÑTA’ª*æJAŠZŒ`ÑTAäe ÌJAñ|ÏìqÑTA"¸žo¿JANË‹{ÑTAØè@h°JAÖ§‡È‰ÑTA&N£JA€ïËm“ÑTA< å2“JAðeæðÑTAð2j@‡JA( |¢ÑTAkŸ÷zJAF¦¡«§ÑTA8 ƈjJAöxo>¬ÑTAôŽVSJAjEÒðÑTA/5‡:JA… ›!´ÑTAóTt§JA¯0MA¶ÑTA¨*áJA²Þ(ø¹ÑTA 5øÛJAÏ0·Ù½ÑTA“9JÇJA¬g'…ÃÑTAñtX»JA¸Ã;ÉÑTA1¿Oi³JAñªË|ÎÑTA3ŒqJA?¥ÞtåÑTAšÓN$“JA(‹S”ëÑTAt(À„JAÁ|ÑqîÑTA/vyaJAw‘²ÈñÑTA/[¡âGJANçA(õÑTA@´K"JAl%øüÑTAˆ®JAuÜd@ÒTA;^á>æJA$5ÒTA ^®`ÅJAãýƒÉÒTAüák¡JA*/U¹ ÒTABõ‹ƒlJAÚ?õäÒTAÞKàÇ7JAÆ£mÒTAS0šJA„­‚ó"ÒTAujœˆØJArž°À'ÒTAs!‚³ÃJA7Á‰+ÒTAQª¼üªJAW?¯^0ÒTAcE¾JAÎ Ùä5ÒTA-LûEAJAê;ÒTAꃾ¢#JAÎ÷Â>ÒTA®í9«ÿJA¨P¨ÕGÒTA€Îo»JAL<ß[ÒTAwÁ.YªJAÓÜ ]bÒTA¯¢:­ŽJAíÝCUsÒTAd„ûÜ~JA‘`h²~ÒTAr,rJA;N†ÒTAiö?,jJA¹Í0†ÒTA#6ž[JAè— ¹ÒTAiòx+8JAà -×{ÒTA™ìóÇêJA/¸- lÒTAþŠ@%ÔJA³¢G)eÒTAEèC®JA,ûö\ÒTAÒŸvPˆJA®ý¶çQÒTA©{ÔpJAJM LÒTA)‡ ZbJA•ıGÒTAìþß[JAU 6#DÒTA{ÊfyTJA¼x—Ž<ÒTAƒ‘qEJAŠÏ3ÒTAK)qÔ4JA—zt‚+ÒTA˜‡OËJAqð®Æ$ÒTAHN7JAaµÀ ÒTA“o gÎJAvïÕmÒTAÜ/7¾JAÂ.ÒTA ‚½JA.UðÑTA6¾TIlJAR“KèÑTAáÊL33JAwѤ¾ÑTAØÄ[i$JA¿{¯ÑTAÆ\<±"JAå‘?µ¨ÑTA²K¿MJAÄ%äÖ¡ÑTA˜¯“MJA™²Ú}”ÑTArŒ|&„ JAФI…ÑTAÒÿQ-R JAeF‚ÄoÑTA¾à`6 JA…]oÍzÑTA2ýcÚ JAçà fÑTAé-â JA˜Öw¢—ÑTA:™{­ JA¥z¼b¤ÑTAÂä¡ JA´B¾.©ÑTA½UÖ$ JA ݆¿´ÑTA5€HpE JA;¼ áßÑTA_tºR JAÉŠ íÑTAm«Øh JAëî¨ÒTAå8ö´m JA6D"ÉÒTA2áæîv JAëë+ù$ÒTA—T1w JA«gßY-ÒTA3¾Ûls JA¡kTJ6ÒTA1ô9În JAÅgM_<ÒTAU1}h JAª[ŒX@ÒTASUsg JAv¸WcDÒTAaº·h JA¶Ïï2OÒTA¯šo JAŒ®ŸœUÒTAÇ}-²s JA Û¿íYÒTAÿÊY±v JA¸tUÉlÒTA£'A2| JAê®í„ÒTAînig† JA»p ˜ÒTA9MN`‡ JA;©µ©ÒTAž‹>… JA\N*¦ÒTAGrèï~ JA/#ÄüªÒTAÏq¿\~ JAòk4²ÒTAràå€ JAõ¢å£¶ÒTA÷$äLˆ JA'Ò¡¼ÒTA€#Ç’ JAu‹Í,ÂÒTAfåâ JAJþi«ÕÒTAp»ÊÁ­ JA¹§*wèÒTAÔV‚® JAŒ†vDñÒTA»>ò¦ JAy N^÷ÒTAk󮦠 JASt¦rûÒTA¬¥'3– JAžÚÓTA»‹€ JA+0ƒLÓTA€»} JA„ €ZÓTA›PI0‚ JAøCþtƒÓTA•Ûãê JAœÃ:sÏÓTAwÔ##JAZóóùÓTAY³,ÀJA7¹~ &ÔTAàï^ÔTA¸+ˆvúJAÄ)ÛÏHÔTA-—Ú +JA]ÔTAB¡#vJA¾žÿysÔTA¯K=úJARÁé«ÔTA篾ÔTA¢ºðLBJAl¹—äÔTA)§à&¢JA0¼VõÔTA-Ó_9JA9SúÇ ÕTAÉmKJAš3> ÕTA @FZ«JAĺŸ- ÕTA°tËJAT}ÏÕTA'ïDøJARpÁÕTA+§¶ú@JAdoÊ"ÕTA¾#YlJA£U  'ÕTAö%ÍJAa+˸ÜÔTA‘ß±éJA(©@ùàÔTAò4“2 JANÙO?ëÔTAéNØ›$JAЙmóÔTAÀB 5DJA’ OÕTA7µ­rJAøïAk ÕTA¢ÛYEJAi°+¾1ÕTA §o7JA•аKÕTAúXD9+JAíHx¤QÕTA0½™‚JA“Æš¿yÕTAëªSs˜JAŸ]©>ƒÕTA‡©ÿøJAufHòzÕTA ieJA$E–ŽÕTA~ée$JAv9Ø­ÕTAÓ[(JA¼–Ô½ÕTA”à@Ý/JAÔÇÄ7ÎÕTAßn‡b@JA‚sÇHæÕTAô¼´ ©JAÌP™vÔÕTA³#Å?ÀJAj\ÎÕTAcX¶JA㛜v³ÕTAb©:JAf_ÒËÕTA.C™=&JAõIÎÕÕTAìnŘ1JA +JÅÛÕTA—ŠÓ!DJAÃúˆ¯áÕTAûˆå=TJAp1óäÕTA ©¥GlJAày«òãÕTA4 ‡ƒJAšUÃÄáÕTAíÕfô•JAY RáÕTAÐzN²JA±?:#ãÕTAœD»®™JA£·GÑÕTAWôIY–JAæØÌÕTAÀÚ¢“–JA«ñÝ­ÕTAÂe¨#½JAœxz%°ÕTAâ! ŽËJAþêk²ÕTAU¹]f JA«ÝqµÕTAáçØ¥AJA«¶â„»ÕTA*ã'JA˜ìÒ9ÁÕTA¼”Í’JA«ÛˆÁÕTA?Ì™›JAÍ×·ß¿ÕTAwôG ©JApÌU(ºÕTAÑ[MäJA†ÎS€§ÕTA VNÕüJA:uVH¡ÕTA‘&¼,#JAã/ì{™ÕTAá„Ê1SJAÔ¢(ä’ÕTAFTãibJA¿ÕTA¸—¾|JAœW̉ÕTAœ¹b•tJA³#n¤‚ÕTAú¹–spJAzkº{ÕTAú÷v¶nJA‚ÃhsÕTAŸ1[oJA—‹ÇlÕTATömÖtJAyU„dÕTA·2›vJAÙüduZÕTAöBï†JA(35SÕTA¡³”ÉŠJAçJøóIÕTAbÉ¢ ‰JA¦î•AÕTA[m Ç€JA×òÀù5ÕTAÖèî³eJA¹äWÕTAq4þ0ZJA’´5hÕTA(úÏVJAyÝ3ýÔTATæ¾lWJA^жÍòÔTAG$¾OSJAü˜`îÔTAáIpFJA(¢sìÔTAvV"JA—FÓÚëÔTAÌÆ@ÍëJABÌKíÔTA! eµJA%Ø 5õÔTA7Yg*†JA6 øÔTA¾fmJAÄj×"ýÔTA^Ù¯â;JA {Ç¢ ÕTA!/BÐJA—墪ÕTAˆ¯ð$øJA5–~!ÕTAþ¢^hêJAážWàÕTA:tÇJABŸ;ÕTAñïÄiJA‰w¥ªÕTAÌU )ˆJA ‰ÕTAgPX•}JAjqÿÔTA8[ÊyyJAù˜ŒùÔTA™N{xJA˜{ÀðÔTAã>MµyJA—ß:EÜÔTA“åósJAåÏÚCÖÔTA?4IØkJAslõÑÔTA^A^JAJgÀÊÔTAΣSL?JAÔ9‡ºÔTAÛ8 µ(JAKæ ³ÔTA5úùéÛJAÈËæéÔTAHï€JA^ KÖÔTA£öÚïxJAòCÓÔTA3ÞwJAÛ¿åôËÔTAY.ÅèrJA´û™ÃÔTA,s+‰gJAt»5»ÔTA÷ÐíXJA2Òü?³ÔTA§GJJA˼G©ÔTAºÈäJAJAþû ÔTAÚ$¿5JAª×‡TÔTAZÂzq(JAyUIªwÔTA:ºŒ*JA3oÖhÔTA°> ÷2JAöróSÔTA´"’A=JAsêKÔTA¡ÏmêUJA Th@ÔTAy¨v:lJA ÷;û9ÔTA•5[JA®ãP2ÔTA¹Îú­‰JA„ 2,ÔTAákåΖJAÞ€ê°ÔTA[ëJAb¬­Û ÔTA¿4Ÿ¢JAQ[g6ÔTAÇºæ ­JAK$“ÔTAéP&ˆßJA‹7”rÔTAÚŠêRìJAc“ÄÔTAê&d°öJAkÔTïÿÓTA!^+JAŒÍ¯ûÓTAÝ0b»JA\£VDôÓTAêÌ’JA„ð4ìÓTAÚhynJAûåÓTA3K’®ÿJAÝ/býÞÓTA¨4JAkÞy[ÙÓTA ‚ JAûèQƒÒÓTAS8ñ9;JAÞw@Ç»ÓTAFu+uYJAy’i®ÓTA3ÄcJAý†-­ÓTA*=Ä~mJAÇOeE®ÓTA¶ükg‡JA–>p¹ÓTA䆲¦JA#LŠÂÓTAÈm'q½JA$õ!*ÇÓTAGg‰YÚJAÁ\Ø?ÊÓTAáðfJA=¸¶ÐÓTAxEJAä‰åÑÓTAA"õ-JAaÂheÏÓTAÚ÷§ÛAJA|*zÊÓTAÌûƒ‹VJAHæóÁÓTAÐU&¹aJA’Æ_¾ÓTA{,²SwJAÑTs¹ÓTA¶‹ …†JAK+ùS·ÓTA;}ÊU„JA,;ݤ™ÓTAãd‡–{JAñëíqÓTA¶°z}JA¦I ¨VÓTAð˜n+}JAá f¤FÓTAîÜЯÔJAÓÜÐ-"ÓTAÁšŸoéJA4¾#ÓTAW©ÀJA¤NÚÓTAÐßH(JA³´KˆýÒTA»‹_/JA´Q–ØõÒTAºW¥þ6JA`ª'àÒTA$/Þá“JAèݨ×ÒTAÞåWÚ”JAú)ð³ÒTAÚŒÒõøJAªQ@b©ÒTAæ!&g JAa·Ò<§ÒTA'€’ JA”ñÍœÒTA‰‘±ˆ JAœn¯­‘ÒTA‚JK JAΚr•‘ÒTADûµß' JAA‘ƒ‘ÒTAM8\N JAVYWÒTA| I/Ö JA)ßrºœÒTA&äÕ½ö JAaË¥(´ÒTA-ŠØ!JA&Ü-ÂÒTAPÒ0É!JA¿¤ÎÔÒTAGÔY!JAƒ°‰ÚÒTAõyñj1!JAgE·åÒTA¼Á:ýC!JAL.i‡ëÒTAáiÏ]!JAúS„óÒTAŒÒ®÷y!JAè„‚†øÒTA´Çæâ£!JAA‹&lÓTA÷ÑyÏ!JA&¹¤;ÓTA‰×÷!JA_û[¿ÓTAJ‹kÒ!JAÔ[¯Â.ÓTA¯)˜T!JAØnd2IÓTA! _Ì6!JAïcÂ7]ÓTAªÛѺ&!JAX>ïO[ÓTAVýª@!JA$ @p[ÓTAîQZá½ JA÷Æu –ÓTAÃpm² JApv¢ÓTA <Lª JA^¸¯ÓTAu»‘Ù¨ JA¾Ä÷¶ÓTAº&†Hš JAÙ­½úÛÓTAg0×” JAðC«åÓTAû“’ JA8ܾ£íÓTA!Ð"“ JA–æè†ÔTA-Äœ JA|K ÔTA6îæ¨ JA¦¢]ùÔTAN+Tëµ JAŒÃލÔTAëÁqäÀ JAjo:ÔTAÇ1˜ª JA§í¯ŠBÔTA‡žù« JAy¾ŒÒaÔTAú/óØ© JAuœõqÔTAÉt0­ JAåÔûwÔTA„Ì· JA7[OáÔTA²Mh» JA+ì‰ÔTAJEq JAž q}ÔTA"½ŸÈ JAÞ{ŸP’ÔTAw9sÏ JAÞÓ6z™ÔTAmA¨ÊÓ JAŸ¼ªÔTAÇ:OÔ JA§¯éµÔTA¤”%ŒÎ JAœcÔѾÔTAà°#Å JA@rÊÔTAÚÖѯ JAN.UÆÛÔTA'¬§0­ JA³r‹»áÔTAú g¨ JAF‘|ŠíÔTAG£ü¡ JArC3‚ÿÔTAÊIÄ¢ JA¬*øfÕTAƒQéL¦ JA„¢X-ÕTAÚ7=± JA¼kÁ\ÕTALkè® JAß³œd,ÕTAjYÖ¯ JAϘV5ÕTAu1.³ JAÌÛ#§=ÕTA6›§¾ JAxøûIÕTA žËÊ JAÙ§ËPÕTA¹ÛT…Ø JAåÛ}yUÕTA-†C8ê JACåœ7XÕTAn˜Ìºð JA” 4\ÕTAcZô JANæoÍaÕTA{É=iõ JA™¬¸Ç‚ÕTA—ÆBô JA¹BKÊÕTA¶o‘¶ë JA¬X6B«ÕTAˆn©æ JAÖ·û?ÈÕTAn¥5üæ JA63˜ÛÕTA ñ2ð JA{¥nïÕTA“ÿv‡ù JAöi æ ÖTAl±¦$!JAfW…ÖTAÇ¡Rÿ JA†0Rï#ÖTAùFƒü JAºø¸—+ÖTA‘Ö³cõ JAs—ºÖ0ÖTAÃX4Aê JA3nŠC5ÖTAmg•Ó JAÃcæX9ÖTAM>aË JAºþC<ÖTA¡ç“öÇ JA}Õºä?ÖTAÚáöÆ JA¾ŒDFÖTA}— ÔÊ JAÊ£±XÖTAýV‰õÎ JAÒÂ"_ÖTAYÚÌDÖ JA+Z±!eÖTA!{»¡ï JAÒâM¤€ÖTAÍëßqÐ JAãmÔâ„ÖTA[ZÛ7z JANÕÄv˜ÖTArI]S6 JA;®œ¬§ÖTAu ® JAò'¤n­ÖTAÖn1÷JAmc ý³ÖTAã#ïÐJABƒkпÖTAÇì1ºÅJA¶úÔPÀÖTAç—äE~JA·zç»ÖTAY¾ ZJAPùp´ÖTA㞬BJAåÐ!®ÖTAmÏÄ2JA`oôħÖTA&ÎÆ$JA_¢¡>¢ÖTAr²]¯JA²P²F–ÖTAñ#áàJA“@¤æ‚ÖTAMõHóµJA©m‹¡pÖTAë¨õrJA0”PÖTAO  eJAM}¥KÖTA…çbÕQJA™O20JÖTAòó –:JA:úíIÖTA6(˜‘JAðJêKOÖTA°6ºãJA) 5ÔMÖTA ÷nîJAÁúMÖTADÄ?ÎJACE›GÖTAXH3h°JA‚Ê%<ÖTA›÷uy§JA ›.9ÖTAX¾ŒB JA›êCÎ7ÖTA”r—JANέJ8ÖTAj²ô@ŒJAz ö9ÖTAÊÝiJA’Ìã@ÖTA*ª&YJAPš•ŸFÖTAdš²CJAÚq/+QÖTACÇ3JAžÍÎØ\ÖTAçˆI1+JAI:­ödÖTA¯óÿÁ%JA+™amÖTAIÚ[#%JAp\z0vÖTAyS|(JA‰&:~ÖTA(¸Ý1<JA§;@—–ÖTA2FJAòZ¼$ªÖTA§2öLJAp´’f½ÖTAfþQJA¢>çjÃÖTA•aMJA¸ÆY$ÓÖTAX*|ïOJAï‰^ ïÖTA³¼ÂOJAw|_@ ×TArQ”ãPJAeôÕ×TA½a—NJAÀÒvR#×TAÔ¦ÇGHJA~Ó¥'*×TA=N7ùJAìøDS×TA©€}fJA ö+kd×TAç¶e{êJAÜ¢R×TAi åJA] M×TA.µŽêâJAyý»"¨×TA—@äJA¾v@¸×TA@o•¹æJAàü~}Å×TA›Û€3ïJAÒ;ã××TA#šæúJAÆA>³ì×TA3ƒÂ…JA¢ÛB—ÿ×TA‘…'¹JAü:÷ ØTA-µøÅ JA ,(ÒØTAHÀ*xJAÑ‹ë,ØTA÷ï¥ðJAK`5öCØTA¿.aËìJAÄ(¤MØTAâ_Ý’êJAÎ= XØTAäØŠëJAeQ]_ØTA!PöîJA º$hØTA¦ZuöJAÅ…uYuØTAÄmîùJA/¡]רTA«ÞÕÿJATGäØTAÍ»£JA…«K•ØTAz¨\JAܰ¿pØTA±¯m¤,JAEªhí¦ØTAˆ±»=JAô¬]Þ®ØTA$ùüIJAq[ضØTAuÚjQJA/û­qÀØTAaåÅ‹QJA*Qý£ÅØTA-{ú5KJAüÅÃ'ÌØTAÿ–!§AJA Ì@ÐØTAD@Ö 1JAƒ(ÕØTA4†àä,JA1lè3ÙØTAC.Ì)JA²Ý¶–ߨTAÝÀ)JA訽£åØTA¶Ä+¯+JAõ-Ê®íØTA'®§0JAJÆž±óØTA7tgIJA¹u…4ÙTAtÜØ¹LJArq:ÙTAè†LJAG¶qÙTA çDJA¸#²_!ÙTA±ÍR„;JA Í÷l-ÙTAÓP~I9JAöô™„7ÙTAL+;JA-–¸»@ÙTA¢¾¶8DJAA=œMÙTAµ¨£¡PJA_%áKYÙTA>€ÂSJAµ·—YÙTA„eQ>^JAÀ0?XÙTANJÔðkJA€¦ÿXÙTAj¢ß¥ŠJAØ\–©]ÙTA8Á,JAÔ±/Î^ÙTAãx²JAG;_ÙTA.ƒV=¾JAO¨maÙTA¼ÉÈJAX¶­ÍcÙTAd[£.ÔJA!klÙTA8ÜðÜJAMàÀ‹vÙTARCÙìJA ¶°ƒÙTAÞ_†4ôJAׂc«‡ÙTAMâ@üJAñ7vˆÙTA¢”# JA`›°À†ÙTADù6JA¼t1K…ÙTAÎùvéGJA¦)†ÙTAï?SJAº:Öõ‡ÙTAIz`[JA‹õµ‹ÙTAl•QÝyJA0zh®ÙTAœMX‚JAñMs³ÙTAÈ_ˆŒJAF’ÛéµÙTAZVöÑ—JAÕÃö®¶ÙTAe#G® JA* Ž2¶ÙTA]¤ýà«JArg^ƒ²ÙTA?,ÎJA:#> ÙTA ·ŸPÙJAŒ±ûœÙTA°ë†-êJAžI'mšÙTA©Lâ°øJA«ášÙTA>ûì5JA¡é›ÙTA"5§ŽJAv¡¤ÔÙTAà=_}JA­Û\l·ÙTAõõçóµJAz¢aÂÙTAЮÓÏJA×~T¨ÆÙTAá–íSâJA0b=ôÆÙTA¡(¿ÉðJAæèaCÅÙTAÂ3'kþJAoœv#ÁÙTAifØ‘ JA{Ô,¸ÙTA[1Ì$ JA âD%´ÙTA¥…x;+ JAŸ M­³ÙTA{eKP3 JAAÖGx´ÙTAj¾ó@@ JA.g±ü·ÙTA­…‹fY JA=åJ¹ÀÙTA  JAÖ8áŠÌÙTATǘ׵ JA Ú¾ÞÙTAZ¶Pû JAÊ2ÃßÙTAèU Á JA4€(®àÙTA‰éB2Ò JAn>3èÙTA´c!ä JAD4móÙTAÊáQ!JA…ÚTAyèœA!JAQ×ÔõÚTAŒ|¯È!JAÕè`q ÚTA.È,¹%!JAàÊ.ÚTA™:lÓ&!JAp„ˆ=ÚTAâMó*!JA%1ÃnAÚTAÊJÀ<.!JA|ê:EÚTAãÚ'7!JAós‡ºIÚTA{P@!JA±Ð®KÚTAÂçïL!JA̰M˜KÚTAöˆv a!JA9ß»IÚTAiàƒ}!JA!J„OCÚTALC¨³–!JAÙ‰žÁ:ÚTA]°ž!JAɺ …7ÚTAo`S¥!JAÿr3ÚTA )q›ª!JAŠˆ@É-ÚTA™7§îê!JA~è£+ÚTA,ÄÔûò!JA׉8b+ÚTA äÚ÷!JAŒwg4,ÚTA‡‰”³ü!JABª/ÚTAgwØ"JA¡›ù24ÚTAuâf "JAA›LÚTAÞF>€"JA2I©8XÚTA¸ÒáT"JAÎ<,wjÚTA|8öPh"JA‡-;qÚTA|Y\"JA܉ä{ÚTAY_!“"JAtñ%|ˆÚTA× m2™"JA8$N^ŒÚTA¢uúÅ"JApM5°¦ÚTA¾Fþ¾Ó"JAá¿’3ªÚTA Ö?på"JA*HÓªÚTA-@&#JA>“:¤ªÚTA…óŸC#JAZ{b¨ÚTAÅþQŸ`#JAý¨ÚTA0ŽÁEj#JAƒC6Ò©ÚTA[(ŸÕt#JA6[­ÚTARý…1|#JAŠœ¨í²ÚTAÎCå$#JA±üB„¸ÚTAˆ9rЇ#JAEß”eÃÚTAË8Bsm#JAH üÏÚTAþV.f#JAýF}ÎÔÚTAÜblî_#JAŒTáØÚTA~±Ö\#JAÉ»ïÜÚTAÁ!\#JA}iëHáÚTA¼ÌÌ•^#JA ¬A’æÚTAÍ6 $e#JAÎZ²’ìÚTAUoLv‚#JA*#ØüÚTA!tM{#JAõU¾ÛTA,¾ª‚#JA5 &ÛTAê`›™‡#JAÛ§Ëz ÛTAQ6uõŠ#JA,’ÛTAz—¸Œ#JA< úÛTA~%²‰#JA'»š,ÛTAÍž‰#JA˜fû60ÛTA‚­;“ƒ#JA?á s5ÛTAf>[ím#JAÊ %¤;ÛTA÷LpO#JA0ÞO AÛTAÿ¤HD#JA¼`QFÛTAÑ5ŒÆB#JAŽ+ÈJÛTAª*‡°C#JAj¼ePÛTA’ ËK#JA6Õ±TÛTAq±V'W#JA‹lÊSXÛTA >c#JAê­›iYÛTAïÿKo#JA¤Â¹–XÛTAŽ9ŠX{#JAÅ^¡êVÛTA«+_-«#JA¤"„·fÛTAí—×£©#JAàÆÂjÛTAÐIb£Ø#JAG-DÖ{ÛTA~Ý ªé#JAÍz\ƒÛTAþ½™Tó#JAÈ[hKƒÛTA«;[†û#JA(°µ‰ÛTA>$+£$JA±I¦ÛTA¢¾]¥$JAn}šð±ÛTAœ*úT)$JAôn±¯ÛTA…^…c2$JAÎzº†¯ÛTAe†›{A$JAìlH]®ÛTAk„Q$JAc4 d«ÛTA¿Z4ák$JAªE]Ò ÛTAáb¬ms$JAFoõ5£ÛTAÈO¢ªy$JAzÞ//¥ÛTAÉk#‡$JA ôÓÙ™ÛTAŽç¦Ï“$JA×…ŽÛTAÛþÐç–$JAóô¡º‰ÛTA“•l˜$JAÛTAïÐ&§$JA4g<ÛTAèH:T²$JAPV§þ@ÛTAõ‹1¿µ$JAgõtBÛTAuhWÔ$JAÃÍú@ÛTAÓ½ê$JAì ˆBÛTAaÉXÿ$JAD’§FÛTA]0H %JA”×]JÛTAŒ±ÿ%JAÐÅ“,QÛTAÇM%ò&%JA¤ƒæ[ÛTA¥ˆiü/%JA”{~eÛTA›KT3%JAZyÇðkÛTAÔgO^<%JAÇWˆuÛTA‹ÕÙPA%JAJäd|ÛTAsIC%JA*‚ÛTAòd„E%JAþz+…ÛTA ¤[ÝL%JA뮢lŠÛTA©a¡LP%JAcj¥•ÛTAߘeT%JAM9™ÛTAæ,¥ßZ%JAÍfà\œÛTA›Ywi%JAP -!ŸÛTAï™Wv%JA?+}äŸÛTA»Âé¤%JA¾Þh¡ÛTA¥ò‡“%JA¡ ÐY©ÛTAÖùÛH¡%JA;ÐBJ­ÛTAw§aKÏ%JA'¶M|·ÛTAÇêP &JAÑvá%ÀÛTA[Ã)1&JA4¥ô ÅÛTAmV׿O&JA儽ÅÏÛTA]xñ|U&JA*c!ÌÛTA‚Íüw]&JA'àªMÇÛTA…î¼£V&JA@“Õ–¯ÛTAZ7T&JAœ’‡¥ÛTAÄjבP&JAz××ÛTA» ì#L&JAF—+ÛTAð‰Ì J&JA¾å—‚ÛTA NƒëK&JAðÝqÛTAÛŽ$“S&JAÙ—â’eÛTA9„‚d&JAHErUÛTA*n&JA‘ä‹éNÛTA &1`w&JA*Ó/JÛTAÇGƉ&JASìüFÛTA¡c6Ö¥&JA&àô’DÛTA_îmuï&JA1<ÛTA.oQ­þ&JA{2˜9ÛTA ÛÃÝ 'JA÷2‰}5ÛTAÃÅYR'JA}œ+Â-ÛTAÜ·Î=,'JA”¤V¤!ÛTAuô-Ô5'JAï:ÛTAZý›ªB'JA[x›ÛÛTA]XT'JAYóa®ÛTA¬i­Ó—'JA­ùå!ÛTAš^ÆE¦'JAnV´GÛTAÊü†ç»'JA5Þ•›ÛTA A(JAǽš6ðÚTA±q1G(JA®êÚTA¥´¢9(JAt‚,{ÝÚTAHº´M(JA"/SÛÚTAÞ¹N¥b(JA °NÛÚTAkGÎÏr(JAëï˜ÞÚTAIùz(JA’AsÝÞÚTA«¬:±‡(JAYT£FÛÚTAÃC\s (JAƒ%ÑÚTA_˜é"¾(JA,L’ÈÚTAœpC†)JAª9Y³ÚTAêq,é)JAò!l³¯ÚTAŸ@ *)JAh¦}•ÚTAtÕØ4)JAœâZs‹ÚTA̪7)JAˆË<„ÚTAbFSs/)JA\%Dx‚ÚTADà )JAþþ…|ÚTAu¸³ü )JAÖw4·qÚTAïýN¢Ø(JAøÃâ{VÚTA,µq(JAÍf¸Ÿ,ÚTA¸Qa>N(JAÇÉÚTA6 ö@)(JAºß·LõÙTAœ&Y(JAµA¾ñÙTA·à?šØ'JAc?%SäÙTA I¼Ò'JAIc¬FßÙTA‰¬kÒÒ'JAd•ò±ØÙTAwÙ YÕ'JAÎ=ÏÙTA¥-ºãÜ'JAOZÞ¼ÙTAKƒ*ØØ'JA,JA3æWË~ÙTA),Of,JA™°owÙTAöû”Æ|,JA£ >rÙTA³‘”,JAª-ƒ•kÙTA¥:¼,JAwxš^ÙTAӂ΋æ,JAªÉNPÙTA;ˆ„0ð,JAª ?„MÙTA´j:÷,JAÖÑ”MÙTAC»Y-JAùÑ­¡QÙTA*¶o -JAxˆYQÙTA»u0-JAö>ÏNÙTA“еö?-JA§ÝMÙTA‘t­ÉM-JAÉÐ’/LÙTA!¥>Ãa-JAP |LÙTAÍyÖól-JAÕ@ДMÙTAÿ—´·-JA [Æ%XÙTAC&aÓ-JA§åùªYÙTA¼ŠæIð-JA5ÊåÕVÙTAÎúÔ¨<.JA?u½Àš.JAÂiÐ’ÙTAOª)«.JA(êœ|!ÙTAÆ‹šC».JA{­:<"ÙTA!„hË.JAˆŠÑ!ÙTA°…AØ.JA Ií•"ÙTANªSÏê.JA¿[3Â%ÙTA¨‹ÕÝò.JAU Q¹'ÙTA]¥Xú.JA_"à#ÙTA>/…ÿ.JA7ª•ÙTAÆ\x#/JAVÀ¶û$ÙTAN~&B+/JAՠ‚$ÙTAY´i4/JAÑQLQ ÙTA«01|;/JA0CEŸÙTAt1„(Q/JAÎ5 ÿØTA®¬T/JAà‹èØTAÂL±Z/JA${ÏæØTA'¯-q/JA —IåØTA_(!)|/JAíèbæØTA? —½/JA ƒþ²ïØTA͵a)˜/JAŠôØTAçQ·<¸/JAuÜÞ“ÿØTAĶºâè/JA­LoC ÙTAÉ<‚xù/JAœHZ©ÙTAmï'0JA¸ñHîÙTAg«æ10JA²ËkÙTA£;ÊÏE0JAÛL„ŽÙTA÷ox8u0JA„Œ-)0ÙTAV­íü0JA¥“@ÒFÙTAªìź0JAÔ«fcUÙTAÇO.Î0JAÏ…CÿZÙTA3´ ã0JAkù O]ÙTA)S™ø0JA†Cp\ÙTA¸1JAÛÂÿVÙTAËxò§41JAú5<úVÙTA›jh1JA2fÐ\ÙTA;9§œ1JA—•ÅëcÙTA„ë0¯1JAŽkåùdÙTAÖýl¶1JA•ëœdÙTA2@:Ã1JA –ŠV_ÙTA,ªl™Í1JA£A§|XÙTA»Õ1JA2BKÍPÙTASþzYæ1JA¥ÅžHÙTAÄ•ÇZö1JAŽ‚;šBÙTALÁJ 2JAÿç“q?ÙTAÞ3ÏF2JAç>V=ÙTA +•þ$2JAÒì<ÙTA›”U]@2JAs†êÙ<ÙTAÎhÉåV2JA¤WN>ÙTA/îÖ¡l2JA×gãG>ÙTA£)Fˆy2JA´E =ÙTAls–3‡2JAèËž:ÙTA«è…n’2JAƒãT°7ÙTAŽˆ±F£2JAò_0ÙTAtzdóÝ2JA_ø,ÙTA:8 â3JAae ÙTA­ªØTN3JAðpƒgñØTAÉCiHv3JA•7ŒâØTAˆÔæ{3JA±s YãØTA/›ºÐ’3JA$‘b~æØTAÚ(Ú¬¾3JAG¥  éØTA}ÙÉÓû3JAX,”éØTA“KcD4JA(«wîØTAˆ|gT4JA“¹Ô3èØTA¡üBx4JAfÙרTAçx …4JAùGÆáÎØTAvâ™4JA›?‘ðÃØTA~åJ¤4JA”¹øw¾ØTAé´…†¯4JA—í½ØTA‘¶Pâ½4JA8.2l·ØTAÎ~\45JA2$£J“ØTA¢ ÿ:5JABù=ŽØTA¦ÈóM5JA`ÓÝ¨ŠØTA3½ïg5JA%^\ØTA>´¯A“5JAôó…}ØTAöˆi´5JAW‘.çgØTAJ.þ¼5JAÓwfÒ\ØTAÊÈ(tÆ5JAÿ}ÎêMØTA¢+!5×5JA184>NØTA¬»\ú5JAõ@æ˜RØTA±fœ6JA3 j³_ØTAÿ=üü6JAÞwÉ:gØTA«ßÂÃ&6JAÙö CkØTA¿†>26JAé\Ø9oØTA‚Ë):6JA@®jXpØTAy$þB6JAÚ“¶ùoØTA‹g L6JA…ªi=iØTA¯“¹u7JA%‘PÞ`ØTA„|þ7JA%#`ØTA Ãÿ7JAâÏ vdØTAgS­A7JAø¾‡JsØTA4L;>%7JA¯ïzØTAN©=7JAqº„{ØTA&£I07JAËÂ%ž}ØTA]˜7JAœMÂ'}ØTAU€Ùi¢7JAm $|ØTAD,h¸7JA ó1xØTA1Û$L8JAvù/nØTAií Ù"8JA.0æágØTALsõÀ>8JA™¾´^ØTA­?_C8JAÀ¬@ƒ]ØTAøEH8JAP:úƒZØTA +K'T8JAbnSØTA‰ãM^8JAšk߬OØTAÈZ^Êg8JAµ7OGØTAò3šY€8JAàåô=ØTA„æÑœ8JAdl53ØTA œ)Ä8JA¦ù!I1ØTAˆ:‘6Ì8JA½¸ 0ØTA[Œë8JAS/ê,ØTAÁ¥Þ·'9JA>Ó:!ØTAž‹ñ29JA¬¥AØTAgr¥v79JAÄ!ÎaØTAË\´À‹9JAù¤bØTA0Ê–Ÿ9JA:'FØTAÉóWâÞ9JA1F¤„"ØTA£-¹á9JA‹M±$ØTA¢Ý–Âð9JA„öfr&ØTA‰H:JA¦®½f2ØTAºŽ+„#:JA9yˆ 4ØTAC¨SÔK:JA/¢°6ØTA×Rr€^:JA"a‰7ØTA~$„k:JAJžk8ØTAf"‡€:JA· ý™6ØTAé#p„:JAêÝB6ØTA¥¦MhŽ:JAôXƒ‘5ØTA½Ø ××:JA‹œžü3ØTAßw ç:JA|oAO2ØTAi¦ÑÎê:JApqnŸIØTAÞ±6¡H;JAÖ¶šŒTØTAb6i ;JAÛã¬[ØTAÆê¤.°;JAÎþNªcØTAÆÎ2(è;JA\1ü¾mØTA8F.Ëï;JAƒl‘[ØTAÅ$(…ŽJA¯=Ì^ØTAÇ'ÁE>JAù.9bØTA…vŠJ>JAÖ„úMbØTA•ÇôIT>JAYü(dØTAgŒ—>JA·rjpØTAáà›>JAÐZïkØTAªû!ü¥>JAƒÍÉQØTA Û–­>JAøYº¤CØTA­™0¹µ>JA7…ÂÎ.ØTAMyW¾>JA.x3#ØTA0Å­¼>JAd¸ç%ØTANyü?JA¸P4 ØTA+äï7?JA]˜•!ØTAn '­5?JA#Ù.ØTAŒ³ÎÊ?JAl|ôï4ØTAi.‹â@JA›Y¶9ØTA‹‰)¼N@JA¶kv==ØTAÐõS©P@JA+%–ØTAR}„~~@JA+‚÷ØTA?™'“‡@JA€fèÏØTA›)òûˆ@JA?KŸñ×TA\-‘‰@JA‘X5¦ç×TA ¯§lÇ@JAÒrUé×TAy¬ëjÊ@JA> Éá×TAË0UnAJA#Äê×TA›ûß’åAJAqxì×TA¸Æ¡MbBJAjV²^ð×TAµ<JdBJA./:sà×TAEÚîhBJAo¢bÝÔ×TAE[pBJAc—Q¡È×TAù䤿rBJA§I¡Ã×TA:ª…BJA— ¿§×TAOŽÓ…BJAÓK »¥×TAíÒ¹-‹BJAì–¶’×TAÚ’—BJAl·’)g×TAex2ˤBJAÉÅÝM6×TA°cÕu¤BJAïâÓ—óÖTA"»¬ù¢BJA‹¶ÑvÌÖTAÚÏËx1BJAKû&;ÎÖTAÉ'¿*BJA ž¸ËÖTAîšc(BJA„Ç êÇÖTA¶€¾œ"BJA¹íè«ÖTA¸ %¢BJAA†owŒÖTAAÜBJAÁepˆÖTAÞÝ«BJA6¶(ëˆÖTA|`€JBJAæ*MëŒÖTAò’‡ýAJAð&,ÖTAÛ“ŽóAJAøÈ‰ÖTAv®:ðAJA'F £‚ÖTAúBêðAJAoZ>½{ÖTAÅž0÷AJA%ÍãnÖTAD0‚ñþAJAfq¸woÖTA®kÇ-BJAT ,pÖTAQ®ÈRBJAÑ«ëÇqÖTA ¥£pBJA“¦1iqÖTA¶³Pm´BJA¼—ÛkÖTA3¡4÷¼BJA‡äyÓmÖTA¿º ßBJA/c1omÖTA—$¦CJAÙ(‚oÖTA õ:SCJAäT~³qÖTAçèµ5mCJAŒÒxtÖTAïÍŠ‹ÂCJA¥·ª€ÖTAÌh$‹ÎCJAiÙžo€ÖTA5R$ éCJA—ƒ}ãÖTAðŒÖ DJA©JpV‡ÖTAVw„DJAE)´!ˆÖTA9ôBÄ#DJA!à‡ÖTAœ’û>DJA ®VáƒÖTAú¸<§DJAß"ªÙ}ÖTAß)œ—DJA¹¼QP|ÖTAÇ[ÔEJAò×hÖTAísª-EJAæd¬æeÖTA @+íLEJAëð1ädÖTAÏ%Šd_EJAª ¥eÖTAŠ–»rEJA¶*©hhÖTAŠ·ê;­EJAöQaÖTAkãEJAC9Þ9dÖTA‘ì9BàEJA½ðo~ÖTAœìÍbÏEJA3 'DÖTAþÁtÏEJAõËÂÖTAžÈ‚çEJA³R”‚ÖTAí0DFJAöTlbÖTAïƒ [FJA2·qXÖTAM©p13GJA.Wàs ÖTAsR0˜GJA½Ú¤a©ÖTAð$pÓÑGJAàáû®ÖTAíÍšÿGJA´p*à±ÖTA|™HJA8—×C³ÖTA­æÙ[#HJAÁ ¶³ÖTAo£$±&HJA”;è³ÖTAPìýJŒHJAmi/ÈÖTAÆiÂHJAåibÕÖTAVf+¥ÓHJAÃf>±ØÖTAIFТIJAè ¿ßÖTA4^õ(4IJAØ7ÙæÖTAâ £¡WIJAlpb^èÖTAåŸKeIJA€jMèÖTA:SSmIJA  {íåÖTAgÂþIJADœø»ËÖTA4܇IJAˆòè ÇÖTA sϺ’IJA*ØA6»ÖTA$a›¨–IJAÝ–¹´ÖTA¬Ï7˜IJAÌ¡{é«ÖTAï2v·IJAñ›u›ÖTAãèÕ ÂIJAÏX†S‡ÖTA\­ ŽÕIJAð”Æ|ÖTAêÀltÝIJA1½ÁSvÖTA¸WùŽçIJAÙ=RgÖTAX]ÌtìIJAR¢*5[ÖTAÌ !œïIJAÚ`[ÖTAÚÄžõIJAÍÀ {[ÖTAÒ‰éæ JJA nCiaÖTA@±í%JJAªŒnÖTA'v—5JJA.ùóvÖTAV˜BJJAƒLšÄ{ÖTAm¼deLJJAZR4}ÖTAe¢¦tYJJA‰žc3~ÖTAí–ÆÀzJJA…(€ÖTAøIg‰JJA ã⼂ÖTAÍP5C³JJA·X¾‰ÖTAo¡lãÆJJAðjX‹ÖTANL»ÕJJA þb“‰ÖTA«ŒîJJA­€ÑE†ÖTA¬©c KJAPt…†ÖTA7¨h4KJA6­dn‰ÖTAçYå_KJAQnŸŒÖTAüçéˆKJAÁëo·‘ÖTAR,g”KJA21g’ÖTAbHÔÔKJA˜lõ{•ÖTAÓâ•_çKJA\ÃéÅ–ÖTAn——XLJA»ú,žÖTA ´©ë7LJAQÒ‹”¢ÖTAhqx‡dLJAï‰2„¨ÖTA M;‚LJAÕ?ÅW²ÖTA²N‘z LJA~¾»ÖTAGÖ»LJA£C.cÀÖTAÅ$ú¥íLJAd×ÈÖTA°7þSMJA\¼„žÎÖTA©»“®+MJA;¶\ÓÖTA䉒"EMJAËÓfÁØÖTA^zcMJA¤æ¶íßÖTAPØü?‡MJA¡ >èÖTA˜w…•MJAAQwSçÖTAI¥sŵMJA­lbçÖTA9ùÏMJAd+)mèÖTAð ÝæMJA,Wä=ìÖTA"Û<}NJA’@@…ìÖTAÚ‹%W+NJAˆš†nøÖTAÍ¥zTENJAÌ:ÇþÖTAK TXNJA(10×TAMÁ©ªbNJA·¯±B×TAÊŠ ©‚NJA*«¦å ×TA˜É`¸NJAaZ×TAl€¥ÀNJA(¹v|×TA–•láþNJAω4×TA4÷8i?OJARÅ×ê×TAE‰e²gOJA ^×TAT©sh­OJA Š'×TAi$â×OJAÎ,×TAÈß™íPJAiqi4×TAÞoUPJA¨Èãä<×TAÝ^ËPJAóA×TAjæÍû³PJA¨w¥ªC×TA·$ŒˆÝPJA9ü"F×TAâ»ÄÔQJAO[mçF×TAŸò†pQJAXÓ%¢H×TAýEŒÆhQJAŸ†‡Z×TAâFbQJAþ˜¦lj×TAqÆ[[GQJA,'Ì«×TA‰!xÉGQJA’D6®×TAz)¢ÖTA[èz±RJA¥avq’ÖTA&9ŸSJAL?yÂWÖTAÎÔSJA)ÏLÖTAm޼¡XSJA˜à+úcÖTAóª3ØcSJAòyr§bÖTAnþÓkSJAµ¨Ü cÖTAD›uuSJA±/N`ÖTA€ÑýzSJAƒó$Ã[ÖTAÓïLLrSJALˆdAÖTA›ö@AsSJAðÀÐ:ÖTAæsSJA@œmÌ*ÖTA‡t‡sSJA‡ÅÄ&ÖTA&…)ÅoSJA—”KsÖTA iéroSJA³Ú0 ÖTAgBœ¶mSJA#bQ ÖTAÍ_ö_kSJAÅâBÖTAuoMeSJAÕn.&ÖTA¦“ubSJA{Q¼@ÖTAãLCÉISJAbè öÕTAথüFSJAòä±ôÕTA­®?SJA§Vé‡ïÕTA7_1?9SJA‘æ?²ìÕTAÝ•fÈ2SJA……¥ûëÕTAœŽ#À.SJA‡ÊÒéÕTA åJ,SJA¾ð…÷åÕTAmŽêSJAèp/ÝÕTA’ÑNSJAŽnØMÜÕTArÓoZ SJA1°#“ÕÕTA%¸ýeíRJAºxÒÕTAlúéââRJA =äÎÕTAwWkØRJAbk½’ÌÕTARLIÎRJAÕ™MÌÕTAÌîøœËRJAÔ0ö4ÌÕTA?j%M¼RJAÞŸiÉÕTAyïi ¤RJA&àæÞ¿ÕTA™ ã¶„RJASõкÕTA²xilyRJAó ýµÕTA_GRJAü'<·«ÕTA‰œMa7RJAaXš—¦ÕTAæ $,RJAÀ>z¥ÕTA_´óÿ#RJA€UêwŸÕTAã„_RJAŸËÕTAgW!çRJA…fò‚›ÕTAq_RJAýÐÕ‘ÕTA54wÑöQJAƒ…!ÕTA(D³OßQJAŸAg‚ÕTA Õ‹ÑQJA²µÁ~ÕTAc™Ðè¢QJAÙ ûŽrÕTAGtµÄ†QJA`v¡;nÕTA«U]ýxQJAOÄPë©hPJAå»_kíÔTAÔ”7à>PJAÀåQ^âÔTA1ÿ1è1PJAâ¾íÞÔTAD1¦ó+PJA»#¯ÝÔTA£}޲PJA¯ÙÔTAì°½ïOJAº!FàÑÔTAÂÛ%âOJA¶ÈëçÍÔTAŽžæ:ÑOJA(&‘ÍÊÔTA“ãÅOJA]¿\’ÇÔTAcB¾ß±OJA÷i“¡ÃÔTA†•!”OJAL˸÷ºÔTAóÎoOJAx½í³ÔTAI–a bOJA9²Œ±ÔTA–+rõAOJA|„ÊB¯ÔTAÞmÙÃ6OJAË/i ®ÔTA$˜eþNJAÒº7»§ÔTAòOq2µNJA!ʲŸÔTA¿æxó¥NJAYc{ÔTA½QÒÞŸNJAu‚œÔTAEò×NJA©ø3œÔTAœ¸5î–NJABEžÔTAÈòC”NJA¼pJiÔTA¹‹‹GNJA·kúqŸÔTAx?º‡NJA%Ôè»ÔTAßè)RƒNJAí‘ÊÔTAj´¹m|NJA^_‰SÉÔTAð´ÙnqNJA„C“ÇÔTAÛcNJA\›7òÅÔTAPM_NJAn:MoÅÔTA¤oT]VNJA/„‹CÅÔTAU¦PdENJAå×XÐÄÔTA/3â$NJAùkÃÔTA¾;|ÎMJAükÄ`¾ÔTAW¢Ö¨ÉMJAÍÏV0¾ÔTA¾ˆª¸¸MJA~À5½½ÔTABƒ©™¯MJA>fyã½ÔTAª1-MJA™ZØ/¾ÔTAmÏY—MJA³ãå½ÔTAHtJˇMJA½`¨½ÔTAdPÞ„MJAÈ&Ò¼ÔTA6‰xMJA.e›»ÔTAÞ{ÜnMJAƒlºÔTAzg*ÝTMJAî¢üºµÔTAÎAä°MJA9FµªÔTAèIâQñLJAEEGk¨ÔTA×wýºLJA>(ÉÅŸÔTAôx LJAO>·‰ÔTA Ó€LJA9Û_?žÔTAr£S`zLJAeP }žÔTAˆ™@½lLJA˜¶% ÔTAr¿€&WLJAî»)¥ÔTAŠZúKLJAA¥ÔTAr*Ž8>LJAáŒJú£ÔTAÈR"6LJA¸ji¢ÔTAF~DÌ.LJAJ° •ÔTAi L“LJA>u’ÔTAN„å LJAwäåŽÔTAnîX7ÿKJAyŽZ†ŒÔTAÄŸ«FâKJA¨Žx¢ˆÔTAÅMKJAÉF§ÍƒÔTAOô5šŒKJAeé¦VbÔTA6×ôzKJA(Ë«_ÔTAð2ê]KJAWBÇ[ÔTAγ‹>KJAQÓ™[ÔTAUZ–I+KJAƒ‘•YÔTA êKJAöýÑTÔTAÝÝÅûbJJAc":C@ÔTAÀŸºVJJA8ΗO>ÔTAxçÇ@MJJAìî=ÔTA_ÓÊ*5JJAì*ÍTAä)¼EJAjÏh>ÍTAep0C£EJAÍ%¦¢>ÍTAL¯è‡EJA•V<ÍTANSãYEJA€7I6ÍTALEÅÌIEJA2óL”2ÍTA¹^ºÒDJAWD´àÍTA”ÞôËDJAŠëõEÍTA½óã°DJAyä/œøÌTA˜Ió+ŸDJAôFZ÷ÌTA![Èâ‡DJAù¾×eøÌTAߘõ~DJAcú'õÌTAl`>DJAceWìÌTA x‹…DJA°ô_¯äÌTAtv2ËDJA$Ø?ÚÌTA¦?ý[©DJAt¨B‹ˆÌTA\_µËDJAÁLçáGÌTApòáòÍDJA‘%å CÌTAÃæçeÑDJA/Í•· ÌTA^€ŸDJA¬´ÌTAÆÍãSªDJAk\ÜúðËTA¢¸[¦±DJA¦1*”ÕËTAמB[ÄDJAdi!M…ËTA¹Wϯ²DJAz¿D‹„ËTA\ "\DJA9a“‰€ËTAUÀô2eDJAeVYOñÊTAl2•iDJA*J¹ª¬ÊTA=€XƒDJAG8”ÉTA#ÅD_DJAÜíY’ÉTAHƒg{DJA¯¿vˆŽÉTAmÄÚ}DJA€Ã#ÏRÉTAYL‹DJAÞ_)ÅNÉTA/ÃÆ`„DJA®Ö'MÉTA”Ф“DJA†·v.MÉTAËèöâ–DJA$h>hJÉTA0bZØ“DJA¥_³?ÉTA-ÕDJA óÆ>ÉTAF6VuDJA¤êŒ˜>ÉTA<“ìnDJA©ÕÇ=ÉTAΈ«ÎkDJAÉ¢WÀ7ÉTA`qÂkgDJA|C¡:ÉTAŒ¸ß4iDJAH7ûb ÉTA”êCqDJAãÛ ÉTA #ÖzDJAâoò ÉTA¡Ñ¶DJAj·ÔP ÉTA%Ï4‡DJA¹p,¬ÈÈTAA$ÖiEJAÑ™lÚÈTA t 6EJADIfÚÈTA'¸lEJAkâ! ×ÈTAJ5`EJAQD“ÑÈTA®º1oEJAÄ@ ÌÈTAà'5M!EJA «ÌÈTAj[BqEJA r+&ãÈTASE)’EJAÂÞ[PåÈTAúÀþßEJADãÖÄìÈTA7ü‘¯*FJAQxÚëÈTA%4Ž3FJA’®ÌRêÈTAˆ!‘ÍDFJAx/­ÏÈTAŸ©1¬IFJAœgxÍÈTA ØÈkaFJAZ­ÈTA®p»„¨FJA%×Ë×ÈTAéà/BIJA°iQ/ØÈTAÝQ ±›IJAfÍíÈTAˆ–¬¿IJA>ùZìÈTAJé$JJA™½[öÈTA5r ,JJAT{ÙöÈTA£÷0JJAÙV²¨õÈTAüFJAByÊ êÃTAÊ‘½ß4FJA‘sâðÃTAâLüFJA·TÉ¿øÃTAŠHêôEJAœþ‚é ÄTAU;ìEJA/ªƒ'ÄTAÀfz+çEJAx•¬ÄTAÎI§°ÌEJAššfÐ ÄTABo2á·EJAv¶ ÄTA\pŠÊ£EJAe«ƒ° ÄTA$€…†EJAe)ÝêÄTAò†á~EJAÈZÀƒÄTAt—"~EJAP.BÄTA‚gŸ`šEJA{9ÿÂÃTA¹å‡#¡EJAP‚S­ÃTAZH¡EJAù{©†4ÃTAÙiù…EJA|8!25ÃTA¡ULEJAtæ;ÃTAÚÄÃDEJA¸Œ t9ÃTAûBp8CEJAMìkn5ÃTA†C¾>EJAd<íçÂTAÏkš”;EJAÈlDãÂTA¥ ´2EJAï?ÃãÂTAûÞì…EJAغîñæÂTA…)¦ÇDJA)ЉïÂTAÏo|‚¦DJAgµi-öÂTAˆÒ±\£DJAÁ ‚sõÂTA’N»šžDJALêðÂTA¾hu›DJAä·æìÂTAeT7y—DJA:ÄìÂTA½òòyDJAjÕ!:óÂTA¯‡a]DJAU¹íî÷ÂTAeF™ JDJA"-¬BúÂTA©ç®)DJA“›\ÏûÂTAüÆCJA°|ôåûÂTA¦@y“~CJAöêÌüÂTAB½ijCJAž;ŽÿÂTAħeCJAX€Õ·üÂTAXj¥oCJA4ÙãÂTAU` wCJA0«µ¨ÈÂTAØÆ yCJAî\ÆoÁÂTA¥Y4CJAE½l·ÂTA™•›ƒCJA°FÒµÂTAy‰º †CJAõÄ7´ÂTAÅ£ í†CJAÙ$…Y±ÂTA6?©ÒCJAÖKmtÂTA¹DdôCJA_ÌÚ†_ÂTA·YÈ—ŽCJA×é5ÄZÂTAÑ7 ‡CJArYáÂTACåjsCJA-|ÂTAø{‡eCJAŸÿÁŠ'ÂTAZ|G¿WCJAR~†Ï,ÂTAÀ€ˆ÷ACJAI†¾0ÂTA¶eÔ"1CJA ¥ÞH.ÂTAƒŠ[Ý%CJAxa©.ÂTAh¢PCJA~ƒ'2ÂTA›;cåBJAä7 p8ÂTA˜kÅoÈBJAQuÛµ:ÂTA oƒÛ˜BJAy*ÂqCÂTA€ €£KBJAå‹A„AÂTA¬; š?BJAh°êåAÂTA¤ˆ²BJA$YkKÂTAŸ`ùù¿AJA4ÀÚ•gÂTAV…f–¹AJA¼Û;¦kÂTA&ýÙ·AJAŽQ(oÂTAÈîÅ»AJA¦@ŠxxÂTA×^ìu¸AJA3·Wq€ÂTAù¾š³AJA˜Ñbè‚ÂTAŠ‚c£AJAÒ+c†ÂTAø!~‹’AJA¥CÂTA4µ3{AJAªRÖ¸–ÂTAÓH¡ÖYAJA‘“Ú¥ÂTA';q0CAJAÙø¬ÂTAdŒ=AJA¬jb$¶ÂTA«BtzAJA[m¹ÂTA^‡VfÕ@JAÜâ þËÂTAU­<¤®@JA7g¼JØÂTAß_ß„@JAÖ:[ðæÂTAå#‡›€@JA¥0©féÂTAŸh1òš@JAi[JôÂTA/¬ì&®@JAsarúÂTA£„ÌË@JAePx‹ÃTAËýcÏ@JA:™ˆ‚!ÃTA“’‡xÊ@JANسy'ÃTA2O„Ä@JA“ümD*ÃTAÉ =÷ž@JAÔ¼•Ä/ÃTA)´ œ<@JAêÔO@ÃTAt&è‘é?JAŸ:BwRÃTAžâ\ ?JA;0²¬hÃTAeF9Gn?JAC¦hÃTAEI<ƒþ>JA²ñ[eÃTA…Ëü>JA܉­ÊgÃTAã¼?JA?Û,¡ÃTAçý†`?JA•œÉæ®ÃTA“¡?JAI‡²ÃTAîaHÝû>JA  ³ÃTAh½bí>JAÁÒ혳ÃTAòWÚ)±>JAÐý]2®ÃTA×L)­>JAŽ"2ϯÃTA°¼Â’²>JAк´¤ÀÃTA}‘tLÂ>JA4U=ÕÃTA;9‡GÂ>JAaó)ÙÃTAÖ§j½>JA›É“4ÛÃTA=k„L¨>JAL¬ÇôéÃTAD[h”>JA‡¡N…õÃTA8]_SP>JA>¥_ÄTA7÷( I>JAµÖº+ÄTAˆH­E>JAÕ!^‘ÄTAoeí@>JA6jrÄTATïiÙ4>JA¸Â{´ÄTAñN4(>JAJPé ÄTA;Ö@W>JA\"Hó ÄTA¬o™ü=JA!áNû ÄTAX%jìò=JA2eô„ ÄTAæÆ,í=JAú&ÇÄTA®ó×é=JA‚RÄ ÄTAtŠwöä=JAÓÔÇŒ#ÄTArà‡YÛ=JAÈ÷ -#ÄTAžJI×=JA¡ %ÄTA¾Íß}«=JA‡M³&‚ÄTAJð'±„=JA½s&¶ÌÄTAÌÈ+©ˆ=JAåQDúÏÄTA¡ P—=JA\>ÞÒÄTA5ÐŒ=JAc¤e®ÓÄTA,ŸXiÖ=JASÉV ßÄTA‰ÝÅ=JA71TÃÅTAKgÔÁ=JARˆ@`ÅTAÙ0 º=JAžV2OÅTA!™#ZŸ=JA¡Û bÅTAÊBÏG—=JA¢i×>þÄTAaǹ„=JAŸ¶üÄTA‚Ùv×|=JAÊ’PûÄTA¬À$g=JAFÈøÄTA¢½RZ=JAIQæ3 ÅTAÝAÊÑU=JAŽ–` ÅTA޵8^/=JA¯åPÅTA'cI¹.=JA;f>ÅTA§N‹-,=JAé$›M ÅTA'CýÃ!=JAvâÛ)ÅTAcsô#âà?Dx9JA‰iÔ ÄTAëV^ûp9JAÓB}ÄTAÔ0Ádg9JA8Œø±ÄTAþÀ}Z9JA#1+ÄTAØüÐ1G9JAl(YÄTA¸7&39JAã³[ÄTAñêQ9JAª*ÄTAòŠ;í8JAJ1×@ÄTAójÁöÙ8JA3›«EÄTA`­Â8JA¸·¥ÄTAá[S¶8JAÇaÓJ ÄTA1ˆ·í¨8JA3ÛÉ ÄTAºÙ0˜8JA^°UwÄTAˆÑl†8JA" •ÄTAêZò;ƒ8JA…¶ÄTA¶Š¶Ö|8JAt‘ ÄTAêker8JA6Fˆl ÄTAyŸ]j8JA Xa"ÄTA^§Éd8JAÓ^5(ÄTAbr%Y8JA].K-ÄTA@€ÍõO8JA¥Ÿˆl0ÄTAVHþMF8JA¥÷Ÿ¼/ÄTA—á?C8JA¡úˆ4ÄTA5* ¨88JAñT:ÄTA<¤?9.8JA4Ðã8ÄTAlo¼>&8JA¾5ŒŽ>ÄTA6>Ï8JAØ¡C/@ÄTA´lv8JAÆR´`?ÄTAÏÊ8JAD‹:ÄTAÀyq" 8JAW—ÀùDÄTA:T…8JAÝ&ç¦JÄTAV¹zì7JA:mbãSÄTA†ùºã7JA6¢´AbÄTAÔäˆvØ7JACÍà¾bÄTA˜›'Ü7JAÅ9À~gÄTAÀ¥¾×7JA¢µ×âmÄTAD¥âNÍ7JA·Žx‰oÄTA§NªÇ7JAÿ¶SrÄTA\%ˆ¯7JAŒñžqÄTAŠÄ厯7JA#A=wÄTA°ÿøª7JA@Jä-yÄTAV·_Å¢7JAŒŽí xÄTA4k!™7JAýüxÄTA­]„“7JA!uavÄTA›ýH2€7JAr^DµuÄTA‘?L4|7JAlHâ£wÄTAÃ,4es7JAn[ÒrzÄTAàe¹çd7JAVV‹Ý|ÄTAœìæX7JA€É~ÄTAÀ3T7JAWP¯~ÄTAÓ]ÔL7JA•€`˜~ÄTAøG8G7JA|PUËÄTA®öÒ@7JAÑ{ƒÄTA]ä³Ä07JA·LŽ‹…ÄTAÂç”T"7JAa°N´ˆÄTASž 7JAÍõª-‡ÄTA&"Ò7JAþ¯.bŠÄTAc¾ŠN7JA4-U[ŒÄTAí© M7JA¸HÄTAö%O7JA>䫺˜ÄTAÑ·Qá6JA2L^šÄTAË_õ(â6JArŽ¿¦ÄTAÉ–Ê6JA¼= ÖœÄTA©Sü[´6JA¡'ßžÄTAë!>˜6JA°Åâ˜ÄTA[ÛšŽ6JAìž[ð˜ÄTAb‡£]6JA[OÄTAü+q_6JAî|Ü>sÄTAø¡Õ[Y6JAª qb^ÄTA­é!V6JAá×RÄTA/n÷ U6JA"ñnU*ÄTAÔ ÙÊE6JAf¨7*+ÄTAïJ|86JAåAt/ÃTA´ÌnÃK6JAºb„¸0ÃTAlº±Š_6JA7Ýx®íÂTAçÙ°“`6JA„köËèÂTAÜ®$§q6JAuUº˜ÂTA"£*›6JANiqÇÁTA6€n‡ 6JAÑ m‘ÁTAs‹‹T¥6JAMÔ Ã‰ÁTAO¹'ñ£6JA ÇoyÁTA±ñ¼œ£6JA§{÷¹uÁTA&´´u6JA^«^ÁTAÂXÞW6JA¤\g.NÁTA§¤•P6JA]½ÊgCÁTAðzú-6JAŠ¡#6ÁTARžf¿ 6JAYA”h)ÁTAotJÿ5JAwRKt'ÁTAà“ëã5JA^¨0Û+ÁTAöí¬Zµ5JA®©íZ.ÁTA›7¿z5JAv—5ÁTA¯ ‚Å5JAŒ‚e ÁTA?:Cc5JAK!sõÁTAœ†¥n5JAq£9ÇÁTAÔ·=ŠÈ4JA1ã“ÁTA™q³µ4JA/Ñ yÁTAÓ¨{4JAé2Ê|ÁTAl’{zw4JAð\GÁTAÇÊs4JAµ•^˜ÁTAJ7yóf4JAˆäõÁTAÆY‚ß94JAvÍcÁTA¬âv`ú3JAv4ÃÁTA»Wáä3JA.‹ƒÌ ÁTAŽnö˜ì3JAÎbö[ÁTA¾såW4JA;‘…ÊýÀTAµÝ 4JAV [ZíÀTAÓPë9õ3JAÓÆñÁÀTA>ŸñCê3JA&®¸”ÀTAΛ0hÝ3JAÜW‘_”ÀTAQUFžà3JAó„öñVÀTAFz¡§Ó3JAµ™VÀTA¾ËmeÚ3JAˆ…t91ÀTAx\¢Ü3JA—iº`$ÀTAf½*4JArÁ‘5(ÀTAþƒ!4JA)Vò¿TA”6(‘ù3JA/æ»ì¿TAÛlIâ4JA Ù·¿TAû¾]ó4JAãQ…0¶¿TA{‰# 4JAÔ:8V•¿TA_b¸„3JAº½”˜¿TA:IYTz3JAb‰Þ¿TAg½\ÎF3JA|…|!Û¿TA¯”> -3JA$È>ØØ¿TAóA3JAT‹]Õ¿TA¢¢µï2JAaaE‡Ë¿TAD§=Ð2JAð~ÄiÆ¿TA¤'*ß“2JA¹2À¿TAE¼Z2JAh̾¿TAš;áæ(2JAÜòiâ¿¿TA8An£ž1JAúÆ¿TAÍ5ƒ%1JAô+/nÆ¿TAM#ÊM1JAQwʡƿTA/Oúªi1JA¯mÚ“¿TAa{«âf1JA”ܰ?Ž¿TAOÎñE1JA.#ãJ¿TAÔÃßþ71JAƒÔð8¿TA¹Ñ0*1JAŽñçî,¿TA°6ƒT1JA#rù¿TAáèT¬ø0JA†dK¿TA!rò×Þ0JAxŽ›c ¿TA³=òÍ0JANÑ-¿TAæ,Û À0JA³'ž ü¾TAiů0JA«œ ð¾TAÕ³T¤0JA؉ä¾TA=8à¢0JAø¥·~á¾TAèÝ?ʘ0JAýœ†Ï¾TA 1ö—0JA Òu̾TAFßž“0JA šü¸¾TA¨½D0JAf°–?¯¾TA‹¸ƒ¨…0JAV€œp¾TAÙ›þY0JAñôh+¾TAÂA„yÔ/JAd4£0/¾TAÖÞ9ìB/JA ú1¾TAÄZæ¨/JA†Ù2¾TARn-².JAðHeU7¾TAM©ÆBh.JA*›B#<¾TA‚ÄX˜1.JAt‘&K@¾TAAæ‘'ò-JAÉcOÚH¾TA¤Øˆ°U-JAF™Þ]¾TAÆÅކD-JAÁ9Çè½TAô±RþR-JA.Êé½TA?ä÷zG-JA‚½ÿM¥½TA¯2ˆE-JAý4l½TA§xF-JA,0À<½TAèâHÎL-JAõz_½TAÅ’9ÜO-JA¬__S½TAÜñŸË`-JA]Û²_S½TAÚÐí`-JAa?†Š½TAè¾ xm-JA˜ÛÌÞ½TA+®8n-JAmžÆ½TAg%;Us-JA¬¹êdî¼TA£ 6€-JA÷§)ï¼TA®»‹É-JA Š ø¼TAp@Èþ-JAð–½TA’‡Íç0.JA„m&½TANjÊ´W.JAëô(5½TAÊE6)s.JAg°Ö¨½TA›® I‡.JA hJb½TAò¥,¶.JA³†0V½TA ëVÖ±.JA@U¤p½TA¶ùÉ.JA)E»½TA'³Š â.JA×w£Ã½TA™€Lö.JAÑ¢ºé½TA(Û–³/JAÚþÍY"½TA?ôÌÎ%/JA_U"½TA­ÉC/JAš*S¦,½TA’£šûD/JA¾14,-½TA¸»}CJ/JAïX^/½TA-:‚™>JA“DœšÈTAÊ}Pž>JA=Ÿ&xÈTA ½lù>JAe1bÈTAdµ£ü>JA9³ÈTAì”Pø>JAF)7ÈTA5|°Ÿð>JALÕx(bÈTAóggyè>JAý*æmŽÈTA§rÅ‚è>JAd4Š·‘ÈTA\¨;Iá>JA#’ÈTAuN³>JAÆo»ÈTABÕü¦>JA×ÝgïÈTA¦·‰¿…>JA™”¬DÉTABò¸…>JA"|ÛGÉTA3³|çˆ>JAÐaç JÉTAYyöÇó>JAŸV\m}ÉTA¹–¼ó>JAQ¼[/€ÉTAÿλð>JAW¤‚ÉTAd46mì>JA†Òý)†ÉTA=V£Ìî>JAÇ1’*ˆÉTAÕ 2½?JAÜv;›ÉTA½x9à?JA{W/i ÉTA‚`©ž?JA^Þy¾ÉTAÿÇnDó>JA `R ÊTAôÐA÷>JA­äÝ÷ÊTAùpå?JA·{ {ÊTAÀ+|«?JAîÚ} ÊTA^;k?JAØ=&ÊTAË8?JAOw¿-ÊTA œÙ (?JAm¥R(_ÊTA†Ÿ˜ ?JA~—ÄÊTA-ïVµ?JAz†”ÛÝÊTAÓ;Ëp ?JAü_õ,ËTAÂ0Éà ?JA;Où,ËTA\È M£>JA¼¼m®,ËTAc• >JAÛû5ËTA²¹¸!>JA%,š4ËTAo®]V>JA½ó•`-ËTA(ÿ‰VÓ=JA¿V.-ËTA¸ƒvÒ=JA¸ÂyÒ4ËTA "VÂ=JAJ®;e6ËTAåQ¸>Ã=JA¤v;{lËTAû»=JAØ’_ÇrËTA†ÀßÀ=JAr°ô¡ËTAüŠ´k¬=JAoŸÕÞËTA wäª=JAFPwãËTA3ÕºÙ=JAPb“ßïËTAËbÀ#Ë=JA}õÌTA?ÛÙEÉ=JAy–ÌTAÂi}´¿=JA£«§ ÌTAé†ê=JA™ÌTAYAdäß=JAºF_ ;ÌTAì«;ï=JAqœû>ÌTA)ç´ö=JAZK2/JÌTA­ò¡•ÿ=JAœ=‚*NÌTAší]œ1>JAJÓÇ9WÌTA`BÙV>JAܶ(×aÌTAÉï¾àƒ>JA›±JcÌTA!½¬C—>JA!N1^fÌTA‡Û¢¦>JA;Ø)kÌTAº¬È>JA+…œ°|ÌTAŠÁÜ>JAó†‚ÌTA~P~hã>JAe"@ð†ÌTAG¿é>JA¼´JÉ‹ÌTAA_Óò>JAÖýÌTAÞc ¾ÿ>JA"`à’ÌTAií±?JAo7Êi˜ÌTAG;n85?JA*ŸOç§ÌTAöÄ—T=?JAŠ>ð_­ÌTAY:ðäP?JAùqPºÌTAî‚eæa?JAPeè׿ÌTAXÒOlh?JAÿÏÚÅÌTA™\9Ýx?JAˆ¿¼CÞÌTAGÿùEN?JA®¢xçÜÌTA ,šúM?JAKùÌTA×±Íw™>JAíIþäÌTAk3 g>JAòþòÝÌTA`\œŽ°=JA¦V­SÄÌTAgèâž=JAPVØiÂÌTA$Á(uZ=JAó"ÁÌTAü¬u=JA C¾½ÌTA û*ÖNÏTAÉ “š\3JArHÏTAòI|Ò½0JAþFdóRÏTA²×”ai0JAÄÑÓgRÏTA&9i0JAÍ¢w!'ÏTA}kri0JAèŽ ÏTAA'0JAGô§½ÏTAS ~£{0JA+´¹é ÏTA”Ñ’0JA¡œ¬ ÏTA'ÔyÀ*0JA¥NªîÎTAðTM»ç/JAÈ)tâÎTA’;ìb‰/JA¢Z«ÝÓÎTA­FI/JAÒSê½ÎTAôð{·/JAϤ£ŽœÎTA^¥;jø.JA8'Í›ÎTAÖ^oÁÑ.JA]àv5ÎTAôÉíÄ.JAöI!ŸŸÎTA¼bß½¹.JA$¥¸£ÎTA×Ãi3°.JAþrj•¬ÎTAAäÛ¦.JA_ÿ)ö¬ÎTA§Ý¥/™.JA®¸+èŒÎTA&íH{f.JAHâ¨×‹ÎTAebéìg.JA]6mpÎTA!;‰_.JAÇ Ä4xÎTAÃz«5.JAÃŒnÎTAo Î.JA j¼ÕPÎTAÝÌDÿ-JAm5¾kLÎTA“[› .JAÄñhû+ÎTA¨<±œ.JAy©h'ÎTA4 >$.JAÔT©æÎTAíÁ36û-JAp)V}ÎTA"V<†.JA¾O°ùÍTA` uïõ-JAfÞÌ»÷ÍTAB¡.JA©xúÝÍTA@d<.JAôïÝÍTA‡Oó¢6.JAé$Ô[ ÍTA-Nè¦G.JAp©(HsÍTAD£{lN.JA¯ `TÍTA†äçR.JAÈ? Ü=ÍTAÍ2Ž5Y.JA^ £/6ÍTA í[9a.JAº5ùT ÍTAŒ«–Uc.JA‡qÂþÌTAýù@.JA>3#ÛÿÌTAÂÅP4ƒ.JAwêÌTABev«.JAG<æÚêÌTA‹÷Vµ.JARE:ÀìÌTAFS; µ.JA*††êÌTA7p+µ.JAÏVWçÌTAï=žµ.JAòbCÖÌTAü ».JA×A°.ÐÌTA壗±á.JA½¼mÊÌTAñúmPè.JAq__ÈÌTAŽHÊý.JAY¬sÁÌTA’·ŽI/JA‡èl$¾ÌTAKø¸¬ /JA‚Àæ=¶ÌTAKÿ{} /JArN¦ÌTAÎEýÄ /JAÕ¹4cxÌTAlª/JADKõsÌTAœÖŠ/JAƒù´nÌTAÇž_`ô.JAÝÝUSjÌTAîè<ÌTA_FSŸ4,JAÛy&'9ÌTA5n#¹,JA Xcv4ÌTAJŽ®ù+JA]š¢2ÌTAè'åº+JAù¢/ÌTAÈalÐÅ+JA¦U?¯ÌTA¤SƒîÙ+JA—ß³ŽÌTArá+JAŠ›vúËTAûËKå+JA²Ü<ÑíËTAoX3”ü+JA"HÃÆíËTAø_úÄþ+JA.TÊ'ÎËTAZOã í+JAî*ìOÍËTAñ¤Çê+JAméh_ÓËTAå·… É+JAb†È™ÎËTA¢ ùËÅ+JAø0À&ÈËTAG4 ¬+JA6OÙ¼ÁËTA7Ô¦=“+JAï<ãì¾ËTA[­mõw+JA|øÉCÀËTA3%mïg+JAñÆkJÄËTAšéâW+JAÅ šàÅËTAÐg”(+JAC˰DÄËTA>,tp +JAœ·ÄGÃËTAV rÁ+JAk¯ÿo¾ËTA„jÜãk*JAV"Uì­ËTAtžN9f*JAuF­§ËTA Híåa*JA$ >|ËTA£°˜“*JA¯@kŒyËTAËRÖ*JAoÞ¿Ã’ËTA;• ø)JAVÑÔß’ËTA®€?Ó)JAüþ†V•ËTAøHpš±)JA ¸A_™ËTAg´sö¼)JA+ÇÊk©ËTAØlʱ)JAû9 ‚«ËTA;Iç”)JA²†·ë­ËTAcMÑt)JAQHº˜­ËTAQúá(JA±ËTAѩЮÊ(JAÝ!±ËTAÝUžÅ©(JA¬ï”k¦ËTAqJ­‰–(JAq;V.§ËTA\m³®u(JA™öz¬ËTA,Ú#sf(JAÇÑ&ú¨ËTAž6kb(JAÚÜù¤ËTA k^f(JA,ÖEvœËTAB€ÿ‹(JA|NY5…ËTAŽc潃(JAè2dtËTAvx-Ep(JAä+@áWËTAÊâ}Þ¾(JA(V¢ÏYËTAí ;¸(JAd Ùé>ËTAC9ÙC)JA¡ÛÆ5<ËTA(Ž˜})JAªÄE$:ËTA¬®N©)JAÔü¦9ËTA¯nã)JA)´ð¾8ËTAlÿà{û)JA'¹Üª4ËTAø1¶X*JAçy \EËTAöµDer*JA¢!FHËTAÒ{iã*JATtw…CËTA:¦»+JAh¯)ýBËTA¸·Üã2+JACHV€DËTAÛ§ãF+JAgÏØ<ËTAD.Îs½+JAIŠà#ËTA«é@Û+JA0CžŠ ËTAs ¼Ð],JAÇ?1$ËTA–0®e¼,JA’a€ËTA 5â,JA¶|ç ËTA·PÃê-JA•ÎËTAŽt7|s-JAÆyé¤"ËTA¼Ï©|¨-JA¢ç*ËTAqÆ1ªª-JAõ&rTËTAŠ ×-JAåØ4™ËTA˜T¼Þ-JAÇa‰ËTAô{Î-JA"&ÉæÊTAÀÛ'Ã-JAÄg®•×ÊTAóví?®-JA:ÓäøÏÊTA–ðkФ-JA¸ûŸ]ÄÊTAù †U¥-JAŽ_&½ÊTAõ¨²³-JAˆ=«µÊTA1H£¿-JAç𴢪ÊTA~Æ’ÉÆ-JA¹­¦–ÊTA½c/;á-JADÇDå”ÊTA~'ä!.JA5L‚–ÊTA5Žÿ“I.JAžL‰—ÊTA7|Óµ.JA‡ÍS›ÊTA9ê/JA¢p3›ÊTAm«B3À/JAþrv•ÊTAíºfò¿/JA>ÉhÊTAëÄu/JAÄbðjÊTA] >Òž/JAm"ª UÊTAîÔ¡/JAgòèž%ÊTA2{·ï;/JA*„Rý&ÊTAêÄ´'/JAÔa°ÊTAæ÷/JAÍÚ=|òÉTA™ói /JAŠzWèòÉTA‘}ƺý.JAó äÉTA[|¶Iï.JA5ÒõäÉTAPo¯cì.JA<–Œ4àÉTA‘#ÐÖÛ.JAÙF ^ÅÉTAÜcõˆ´.JA‘ëÅiÇÉTALZÌÒ.JA¾£¢ÉTA¾qf* .JA(ýw‘šÉTA $ɸ.JAg½Ž?oÉTAO ¥Ð.JAÑøéOLÉTA®wߨ.JA8¿%ùAÉTAW„Mì.JA\èÆ)ÉTAtkWsð.JA*žæ$ÉTA(QÓ.JA¿á¯ÉTAõžÛ.JA²dq ÉTA‘q¿ÒÝ.JAÒ46ˆÉTAÏO±ù-JAÏö³åÈTAì§­ù-JA5ºíàÈTAž~Ïd¥-JAxËAhÛÈTAì½>ê™-JAø*&À¹ÈTA!N×=x-JAXØÉ˜ºÈTAb—)Û]-JA߯SÈTAïLÀ§v-JA#úÌHÈTAhM5ôt-JAÿ¼ÐÇ6ÈTAAZ$¤–-JABPÄ[6ÈTAÂà”-JA 5÷ŒÈTA#ÌLŠã-JA|-høÈTA:Á£|ã-JA©Êa:ÈTAʦÁ%ý-JAÐØŒrÈTA þÁ:.JAÉÇ„ÈTAΫgú-JAq¢±òáÇTAy,=a.JAV+\´ëÇTAU/‰ôe.JA¿>ôæØÇTA“ìh.JA0³…Ò´ÇTAJL®×.JALM·ÇTA?dÐ…ß.JAÈfÌ5šÇTAgk»¡÷.JA{áY|šÇTA÷èǨù.JAìa×xbÇTAWeoÿ.JA…úÆ­_ÇTAsÝã­ /JA3Æ×ZÇTAË*z^ö.JA=Õ0ò<ÇTAYRò/JA Mû8ÇTAú ]//JAŒä„2ÇTAúßnM*/JA›§·-ÇTA0MŽËR/JA\Šžû*ÇTAààñ¾U/JẢÖ<3ÇTAxØÐQl/JAŠ-‚Ó1ÇTAý0Æ—n/JAÝ%ÜÓ:ÇTAä§Û­q/JAvxœ@ÇTA7'Î^Ÿ/JAAZ†ž?ÇTALWq›Ÿ/JAD£­9ÇTA~>0£÷/JA”ù89ÇTAm«ßwù/JA±çS¬-ÇTAvÍI¢!0JA’dˆ 3ÇTA¿>üïV0JA‹0ñã:ÇTAúêžx0JAÓé<ÇTAíKλ°0JAãÂF-@ÇTAØM½Ë0JAvYBÇTA=€Zñ0JA“p@¹EÇTASw‚—ñ0JAϸ^È?ÇTAuޱù1JAá –@ÇTAœeÛØP1JAôÍÇ,BÇTAø>n¯­1JAóÌ>ÇTAÇÒsÑ1JA27Ã'=ÇTA>Ç (2JAnç,Å@ÇTA½e_'f2JA<ßÞ]CÇTA¸FTŒ2JAþIùÕ=ÇTA›Ç8¥2JA(¦«éMÇTA® 1”²2JAkÊêXÇTAQ„$g¯2JAküFcÇTA/Djmœ2JAõ{Á“ÇTAãaEâ’2JAªŠ8 ÇTAuSÚHÒ2JAÓåÂ( ÇTA望!Ó2JAðy躭ÇTA46d3JA^‘‚C­ÇTAÀÖ@…3JA·yÉBÁÇTA*Ï]ë2JA<’§¼ÁÇTAµ öoë2JA®‡þÎÇTA­ÉO33JAãxÂÎÇTAšV3JA«äKÈTA÷é‚È3JAö^- ÈTAO+â3JA±ÅîBÈTA­ÊHë3JAy1[ÈTA˜’ßIì3JAGvzÐ]ÈTA>r‹û3JA°Øg]ÈTAúy:GÑ3JAÇn*  ÈTA¼úY'4JAY3CµÈTAòë‡^4JAnYÚà¿ÈTAÜë94JAÛ•²ËÈTAáží‡4JAóz™pÝÈTAQbSon4JAá´ãƒýÈTA^x‰oÜ4JAmÁ«ŸÉTAö óú4JAòLýÉTA›àõ\å4JA»Fò8JAʱûûÙÈTAÛ·µ-g9JA•ìîôÈTAëÚè|9JAºz#øÈTAmK59JAƒÚÇSýÈTAªc¤¦9JAÐVß]ÉTAõ›Ö¥9JAÇT%ÿ ÉTAÀéC>Ã9JAhh­j ÉTATɰ:JAjòuÉTA à‘!:JA…¹€”ÉTAjN”^$:JA;ë5˜ÉTA¬&ý&:JAÜ“/#ÉTAN$>œ):JARÎâ&ÉTA“†ê©:JA:™½:ÉTAƒ‡ãù:JAr“r6>ÉTA¤µ/µ;JA¡“Î?ÉTAf|‡G ;JAŠ*j?ÉTAÓ<ÅQ#;JAD]_AÉTA>Ÿtt+;JA¦ÄøêBÉTAbJ@j0;JAí`óCÉTAÿYž7<;JA>ÓÊ7FÉTAÝñ¥‘=;JA¨9(ìBÉTAaìX?;JAØÂZ>ÉTAçe_B;JAÀóز6ÉTAvM,H;JAˆë`(ÉTAÚ  ¹Q;JA«¶\¬ÉTA“4ºá\;JAƒöÖÉTA|2ãd;JAçѶ7 ÉTAÒéjFk;JAçJAÖ¹ÙlÈTAká“Ô!>JA&|-jÈTAyÊ?ÿ9>JA›˜ÆÉcÈTAæ³G3N>JArd k]ÈTA›qñh>JA°2,+OÈTAmCJ>JASoC<ÈTAê&>JA£2‡Ç/ÈTA"¯ûk’>JA7Œ(ÈTAjO)”>JA¶æ?gÈTA-:‚™>JA“DœšÈTAAh’zþp?ùIAGrsxUA'Jøº_JAt¨Û?,UA*¯8ùÝ&JAMcþUAêž2Ñ&JA%Ót5UAr¡„:Í&JAÍÿÜGUA ÒS/‘&JA.9u UA/vƺ&JAౘ(ßUA)}yëÎ&JA¥ ¶ÄUAàI··&JAbàçI·UAéc}±&JALt²UA½‚Ÿ«&JAÞÐ ®UA E]¥&JA«ovÕ©UAº£Œ¡&JAÄWÎþ¦UA²Êé(œ&JAèã#£UAØ 6š&JAUil¡UA:&€&JAÙJ¹eŽUAhD÷Vs&JApu{‡UA-z!z&JA3ä}o€UAÖçô'b&JA§lÝÂsUAþ ’&JAH^~WKUAHO ט&JA£B!þEUA±™o£&JAW©Š=UA–ÿß»&JAyXÔ,UA⺔Ð&JA’³;"UA(‘/¤È&JAr——UA—À °&JA`jÉæUAA:®«ž&JAL 0UAŠ1yAD&JAÎÈbeóUA€?ÿ›Ë%JA‚7fÈUAoµƒ“j%JAFO£TßUA?o0V%JAÔè;ÍÚUAkÁd%JAE‘ÜUA~Ü$JA»³ÉUA®™Ò–‘$JAg-’²UA' G$JA5+ë™UAì8W?$JAas‡j±UAýŒŒÝ8$JA–‡•‘¿UA±e¨"$JAÅò ÀUA9l¨Í#JAǬÎwÁUA1ô2Ë#JAé“sËâUAõS:hØ#JA½YÔ¸ùUA“mêxã#JA);ÈûUAúÍç#JAS‚FáUAœÆ‘ê#JAnO€É&UA…¥vQæ#JAˆ£*2UAÜIPä#JA˜z Ÿ;UAýÎÃÔ#JA 7\x<UAŽ`ÄÉ#JAu’f=UA€æ…“#JAï$¸7UA¶’ã—#JAx'¬.UAÉŽÏË#JA~›6C*UAJß.š #JAÖ›®6UAFÑd„"JA‡p‡íUA ¿e©n"JAŒ“ÿåUAó"JAOøE“UA>e[ù!JA ú}«£UAœmsù!JAÔM ŽËUAÅPÑèô!JA&ËÊÄÎUA®û4}o!JAg$’ìØUA£¼½wm!JAx û¢áUAñ—ƒûõ JAX™“éUAí“ÞþK!JA±~“>yUAÇ{ÆN!JAׯæØ~UA•ß~—”!JAdÆsnUA¾6½±¥!JA‘Šž’kUA8XM*¯!JAPpöýlUAC"¥ÆÃ!JAÞ¥xˆUAª*8k"JAÀ˧ƒUA2aq$"JA@0A¶UA\×ño"JAíÄ0sUAgî2 Š"JAe3øatUA“`”"JAk-ÙtUAï†3W‹"JA3#€}UAj„î"JAÁ¬‡UAyE([l"JA>,UA\d‚b"JAâ!˜UAëÿ‘Jd"JAí%%´²UAÅ4ý(Z"JA€Z)âÇUAߢɋT"JAFP]ØUAz=ÒŠ"JA†@‰*õUA¢‰.•"JA;t9ùUAi^(¥ª"JAùÌ£íUA[á°ã"JA6-[UAx%?Yn#JA­pÝ?UA3÷##JAï匡UAϵÞ²"JA§ùUA㧯"JAð…>ªûUAîvsߪ"JAðD‡ÿUA…ϧ^"JAßOõù4UAâTŒù4"JAóÊÉoRUA;é="JA­àñÄUUAÿ H"JAMÏßYUA°,Zë"JAºX€UAªv="JAt± ˜UAs.àÈì!JAú)Y±UA“n[yù!JAz£·UA:è^âå!JA]×°ÉUAFcß…â!JAïHÕÑUAí™sòÝ!JAùíÚUA™H²!JAcd¹ÿUA§"O;¢!JA"ÝüUAC_œ8Q!JAÜý¯BUAk*]D!JA䆛MUAã“Ds4!JAà s™YUAã~]Éð JAßoŸUA9ì§õŠ JArqV›ÅUArÖ½J{ JA -˜ ÎUAW<Ëk> JA•û¡lñUAñ“Ì JAIza‹UAÕùêáJARO| $UA6åTÕJAò™¼ UAü•ëÿÅJAüúõUAäø~,gJAWûUA$Žu#JA.R¢«UA\}nûJA9/T=UA¿ *ZJA®+DÃÇUAÑË)UJA÷Ó)=ÊUA%ó^9EJA$uÑUAÒ窆öJA—ÛºUA'ÿùôJAF m«UAпiãJA»Þ‚UA[__qÕJAØÎıUA[øãÝJA‚È_0UAÈ'­³ƒJA€â¶8UAi_¼“uJAu‘ç=UA˜í´ÊhJAÛÔ1CUA(3+|JA#O½PUA¬´è~„JA·Ðs2]UAŠss‡JAŒ§jXlUA7VćJAÛv‡ïtUA°¡(…JA…OuåUA~Awì€JAdË©³UA^I{JA?'˜•UA eÊ;dJAe:º §UA‘È‚l]JAÔsà«UA‚Ëá\JA´w­UA|è¾îSJACI³µUA®pù»&JA(”éüÙUAgü¹–%JA‹ÙÍXåUA/M^,JAh)~z!UAm@ίJA™æät>UA®ú0¹JA ˆÿ°mUAqº JA¡VóBUAl’ÐúJA}ûw®UAúmaÛJA§é¯áÆUAƒ¨†ÈJA¦ÀÇÞUAt•½JA ý²íôUAš5_ ·JA¥ŒqUAÄf”Û²JARGXcUAó`Ø®¯JAÛ46µFUAÝÄ ¬JA.ÿ`UArJ0°JA¼·#tjUAL‘Ó~¯JAÀsI¿mUA~£ŽQ·JAÕ’ùþyUAeû9©·JAÚi“D‚UAÓ±"]±JAØ Ý)ŠUAŸ&™¡JAÐÊÇæ–UAº4£ç‡JADuƒI£UA{È#JAȇ«¥UAOd…“xJAYPœ;©UA‡ÚžmJAvÛÉ8«UA X¹ìKJALÝ0®UAvÉ =JA j2±UA›6B/JA^’±´UAfU™hJAš¹øÊ¹UAkÞ JA=rÂUAz¸öÎýJA{6­ÈUAþT•,òJAö’U…ÒUAk¢_çJAì·HàUAºÊ ÅâJA‘¨5eêUA”šûÞJAÇ1‰öUA¸@ïâßJAEV,UA,ˆö¿äJAJ@UAç÷ާðJA’ßzUA¸6kJAê ˆ1UAsâ³-:JA,MÛUUAÚŸ½kLJA‚vÃcUA<”2QJA°„÷¥kUA ©}PJAIýtUAúµ@)DJA#Û°†UA~Ç~8JA~Ô*+‘UA܃(à,JAƒB¯ï—UAÉJJAy2Õ¸ŸUAfˆ÷JACOʵ§UAº@æJA `‹«UA£2ãùÙJA<”…d®UAœµòÒJAxW±UAÏQV$¹JAxŸï-¸UA‡ ˜u‰JAl€ƒªÃUA˧ÚnJAûV*ÉUA‹ $-;JAóÝvÿÍUAir¡é"JAc>õ‘ÑUA@‡óJA ÿcCÖUA©í™JAÓ}ÕÿÚUA¶¹:ÕÿJA’¶jwàUAZñ3æJAºÝ¨õUA’ERÔJAB¬ñUAMl¢ÖÈJA‡}* UAêÀ¶´JAÚ‰q3UA·9¿­JAñ»:UA¨o×¢JAx*›¾BUA4{’JAx.OñLUAªG¤‚JA·–UAéÅxUJAN†˜UAž†´ÍñJA¥ÑSIœUAÜåŸßJAÐÛÑŸUAxÉJAͺ"ŸUA¦òÒ±¶JA9õ€uÅUAªô JA2]!ÎUAê={c~JAÏ“ÎUA68KÙ[JAš9p±ÊUAؾæ.=JAß8ÚöÂUAƯÛÝ(JA–¶3­ÇUAx\Þæ!JAJåÊUA, È JA»Ã‡œÐUAÅáoíýJAÊÚöŽÓUA4í€íJAHë¦ÖUAff¼µJAFÍUAùç^a–JAu¾Ô°ÌUA®Û‘(~JAÚ›'ÓUAa‘ñôpJAcÀˆßUA믙\JA5&àUA¢Ÿ._JAJœÒ„îUAþy™ôXJAjòýŒóUAô*#î?JAFæìãùUAv'û"JAšQ §üUA„¦CYJA«Ö¾üUAJlšðJA°¨¸§UA·³DÚJAÏh%R UAàIÁ ¿JAMÇ©–UAY?ao½JAUA>Åq·JA(í©_UAüò”JAàgM³#UA4|JAh¡t*UAñ7tnJAvI§ž+UAÁÇ£JAIA&gUAìÝYäJAÈé.2UA+„åÞjJAQtbDUA7 dJA”5-})UAÕ~P4YJA(®7UA<4å»bJAaÓ9u?UA2sÓ+LJAd#€†MUA^d 7JACôUUAVÒ"JA“^UAö- ï8JAe1hUA·ß+*JA¹jcˆqUAª¿×2JA+¸ ÑuUAuÛ3z?JA*ò€k~UAïÍÍo-JAv\‹H}UA­èa¶JA&LîuUA=Ì îJA¡ÇQr„UA=z¡ÙJAsÇ TƒUAÑR7²JAèi,'oUA¢bó0‘JAgÚçgUA' JAÏ ?eUAYØ–Ý JA;7™›nUAÁ®sj JA1UAfªgó JA¹ŠUA²÷Ö JA—˜–UA…—4²² JA‘ôºí£UAlt[ø¤ JA„÷Š©UAVÝæ·… JAÏ•P²UA±}!°A JAóÆ•M¾UAù¼©6 JA¶UA3øA<& JAÈ93¥¹UAŽ÷V÷ JAíÒžÐÀUAÏðÊÑ JAÉe“ÑÉUAäUÍaº JAbþ„çÐUAöFî± JA]0NuÒUA½èÁ£ JA€D¾9ÕUAÛ"e JAò…+zÖUAà€yŠQ JAßfPÝØUAã[@ JA\ô OÞUAôzÚ, JA­‰ åUA{uj JAÚ•¸\ðUAð/îž JA‹þ’úUA1ú» JA¥›ß] UAÔ(x%ÞJA&ì§ UAΫk–ÎJAž¥¼­% UAs†q²JAž)wÝ- UA…ëµñ—JA5ZMg< UA0'Vƒ†JA+ÿ£t> UAvúî+JANÄ"m UA$¡qJAèD© UANІ5ÌJAé“Lï!UAH)âËJAòfLÃ#!UAÑ“˜KÊJAˆÆDE'!UAK§5±ÉJA¡~ÅÆ*!UA|F¹OÉJAÍÎG.!UAÜ\ÉJA?g­1!UA,døÈJA5­5!UA*ªóÿÈJAx=Ù’8!UA¡#ÉJA¡°÷;!UA§ü³BÉJA-Yœw?!UAÍЇÉJA¦¡G÷B!UA5#ÀÉJAwD5’F!UAi¶Y ÊJA[×J!UA‚¡ðVÊJA\>p‘M!UAµ"f—ÊJA¹À$Q!UA¡aáåÊJA/bä«T!UA¾ÏV&ËJA9ç˜+X!UA{5ÌfËJA’mM«[!UAØî ÌJAµ‡ ái!UA˜ûñ²ÉJA£ l!UAOfZHÄJAá4w!UAñÁ9 ÂJA.ûy!UAd|Ì6ºJA£³ƒ!UAÑ\â®JA-Ôw!UAg{¢œJAˆ®Þ[ž!UA{ˆA ‘JA±ÎQâ³!UA’ _‚JA{¾EÏ!UAÝ”a&vJA×ʾ'þ!UAÑh 'JAæù».ò!UA'WÌ7×JA5,m$ê!UAºÛ°JA »ä!UA£+N2¥JAÛ½åPô!UAœ¼{¦œJA?d÷¸ý!UAW(›JA7b@"UAOŠ L¢JAÄ}€"UAÆû] JAúMf"UAS\Íæ‡JAÊJËE5"UAlå…=uJAVÿ«C"UAiËŽú`JA 6±çO"UAþªyXJAI°6©]"UA-s3bKJAã'G}"UAkqÒ'>JARe4¹†"UA²u ò0JAÍÚ6Ö”"UAÒ¿c¡'JA짘W£"UA­•E) JAbç[Gµ"UAÖ—,ÿJA Á"UA®°syìJA²%sÊ"UA÷$#ÑJA°p&Ñ"UAwDÏ®JAjcûÚ"UAI®â œJAá×õÞ"UA$‰5³cJAtÏ5iÝ"UA£ó6ÑMJAŽ^åÛ"UA×}ENJAåCºŽá"UA–ݦVäJA‰5µfé"UAÐÌJAáa—î"UA£Cž–¸JA’Ð*¦õ"UA‰‹È¢JA3R##UA¼Y‰JAb>a™ #UAžº¢qJAX¹•#UAU³(ZJAÌ•#UAeëzòJA8Ë #UACJA"¼Þ#UA×ë³úJAhö”ð #UAMA“-äJA<âB%#UA¡÷ÈÙJA Qe+#UAFõ¹ZÃJA "ï/#UAè#Q¼­JAùQ13#UA­/Ä/ˆJA87õ¥>#UAm#‘~JA\R@#UA8ø€ÙlJAÓ9 Ÿ?#UA%Cµ{<JA!}¡w;#UA‚ã4JA” m˜7#UAÐWß JA;µ Þ4#UA}#/JA™‘T‚2#UAsa­÷öJAM¡(.#UAlÕÔºæJA±·Ÿ"#UAhä×ÛJA G'#UAD­ÂAJAHðY•ÅJAÂ"Gë|#UAùÉ }¶JAp4‡#UA¢Dúó­JAß Z”#UAn —›‡JA)»òÑŸ#UA*Qø>JAÍjRE²#UA:͈JAü·Yl¼#UA‚@ýÕ´JA¢îÂâ#UA£cÃ7€JAÄW‡”÷#UAV؉xJAƒ7*Ñ$UAÖ¿ã~hJA‘¿$UAf¹Ñ7JA%lî]^$UAùŽv"JAÇÉél$UA£IËÀÿIAÉ{]$UAzÔþVÿIA]-0K$UAŸ[vIÿIAb?Q$UAàeÊCÿIAÄBñOS$UA|ÁÆ,ÿIA1MÃw[$UAôƒèôþIA„h¥tm$UAý`¯>¸þIAºˆ´$UAfå—ƒþIAUÇ “$UA¼>´rþIA+_輜$UAÑÍÆMþIA_ ¸¹$UAúÉ4² þIAÓÚ±Pµ$UA‡µeÞþIA(Ùµ$UA]©\þIA$Ê™´$UAxEfÚþIAónÁ$UA/ÝöIþIA’Á*Á$UADø”"þIA½i†IÁ$UA&|ä3%þIA+ÕÑSÉ$UAX4¸Ø þIA³~`‘Ü$UA8 ^”"þIAE ú,â$UAT=Y-þIA ð}ï$UA~µ€GþIAºMa%UAäÄKþIADZäÿû$UAŠœpþIAcèOÿþ$UAl#É‚õýIAåà~#%UAë5ôÌßýIA¡«œF%%UAC9ÏÏýIA­¿"W)%UA·%L¾ýIA¤>»Û/%UA¦»IÆ´ýIA5°Æ#5%UAÓ\«¬ýIA(£ýIA,Ò³ôZ%UA„ŽG@ŸýIA#êÖ˜^%UA¢–¬U“ýIA5èàRd%UA4ÊSû‘ýIA±Fsp%UA^²ÚÃ~ýIA9—µü”%UAäF‚vsýIABOГ%UAQ1XúnýIA”U¾G¢%UA¿Î4~nýIA,ƒ¥{§%UAµWYCoýIA7M_®%UAð‰*uýIA›äìÒ¸%UA\êÏÃwýIAEÆÂÀ%UAàJµ€uýIAÄ/MÛÊ%UA~Ðç§rýIA÷âTK×%UA]welýIA´ÌüÞ%UA¼êI‰FýIAZñÃï%UA´Ž(ýIAÊ¿Â&UAñ*tíüIA¬£·v&UAŠ}©ºâüIAiɼ&UA/ÈJùÕüIAÃ}má&UAÛ@Ä–wüIAÐÄtÝ1&UAÀTŠüIA¯åü¤L&UA¡LäDaüIAD¡Ò\&UAG÷o#RüIA$?†©`&UAê>ùJüIAUF¾wa&UAÂÌÝBüIA;몋a&UA†ºˆ/üIAóü×þ]&UAó2&¤üIAæ×ë³e&UAÔ<¦ üIAh» k&UA†hÕEõûIAQA¦–o&UA¦"°KñûIA—¾££q&UAûáwåûIAõ«J·{&UABÔÒûIA&•½i&UAie™ûIAtsøŒ&UAüT4IdûIAW x[‡&UA!hY]6ûIA¨çÝ¢&UAEâå~ûIA ×íLˆ&UAî)`#ÑúIAyÁ̃¥&UAƒíFyÊúIA 8Mƒ¤&UA¯”A/¼úIA¾Ti¢&UAZ›RašúIA¿YÑš¢&UAƒ'ÁäsúIAz›8¤&UAÎÅ%.úIAï%8­&UAŽe×½ùIAÈñØ·&UAo`“×ùIAû©[½&UA¸D¿J€ùIA«V;ºÄ&UA¨¨!€bùIAÈG:AÒ&UAäkôMùIAÅbOÎß&UA’zþp?ùIAƒ/dä&UAià1 BùIAR°›î&UAßËAùIA ¬hö&UA¡¶9EùIAMø“›ÿ&UA¦÷ NùIA%m&'UA›=•\YùIAï âé'UA3ÈàViùIA…„ƒ'UA%ÑêùIA¨Vê'UA‘z0 —ùIA:”œ@'UA•-L¡ùIAÞáóÁ'UA;)þØ«ùIAȬ~` 'UAœ(}aÈùIA;È!Ó'UA*çÅžÌùIA—Ec%'UA6õ®^ØùIA/9'UAèD§äùIAðò0B'UAÆ$ËÕèùIAe¶ðÊI'UAÀÉÿ1öùIAZ‘ýŽ\'UA¦)ôLúùIAù¸`'UA<>¼øÿùIAm~ñb'UAÕ]·úIAb³~ìf'UAögØv úIAݡël'UA]”»úIAIc{'UAÛÄÊQúIAèH‹„'UAr)¶\2úIAöª™'UA_Îr€qúIArÈXÌ'UA•e(‚‡úIAÉ]÷„Ù'UA x”úIA‚‹µÞ'UAºí›C¦úIA‡†nã'UA†¡ÂƹúIAŠ9Ýøæ'UA'ì’*ÈúIAfešé'UA…Ù¡âúIAÆË¶±ð'UAðkâ ûIA–2wú'UA>rrz ûIA¶û9A(UAÈ5ù3ûIAžùE% (UA”N*5DûIAem¤(UA ŠoPûIAr÷sÚ(UA̲]^ûIA¦t'Ï%(UAÆiâqûIAA£N1(UAnÕç˜ûIAv‡C(UAFÄDÒûIA¢l0‘f(UA:¡ÃßûIA«bl(UAyI‡ìûIAi1Hs(UAÓ,ñãûûIAa¦¨x(UAå¥EÿIAÆàV=*UA'ó¼ŽOÿIAÅ)¼@*UA$öYfmÿIAûÝ÷æE*UA4×–ä©ÿIAV“ÛiP*UAªh2m¨ÿIA»ÉÕåV*UA DsjÁÿIAV¨¶¶Z*UA›'$ùÿIAWÔ¡f*UA¿.i@"JAºm*UAKX§eJA0Þk*UAê‹ÀJAɶ­*UA£¬£ÿÓJAíãù»*UA]G†èôJA}Yj_»*UAÖB*JAéCnyÆ*UAoØÄALJASOt1Ô*UAeÃcJA]YÆß*UA:!1ÌÄJAÈÈ†Óø*UA¢í‰¦ÛJAY•†5ÿ*UAf¦ƒJAR"h¼+UA¸>oiJAóÁ˜L+UAâêÛ“}JAˆOTÓ+UAf]ØJA³žo©+UA<åÙJA²Aë+UAœæ÷±¸JAÜéJ–2+UAòJt)JAö޶¢?+UAæô7JA›`B+UAsÐ@JAH±óõD+UAïªâkSJA£B„K+UAÛ¨‘‡’JAÍ\^+UAbÅc¬JA¨Xéve+UAS²j ·JA¶vŒ¤f+UAÛþ¾JAÑ»-i+UAm9§ ÃJA‰Àú—l+UAlü0°àJA´q+UAÁ®ÊýïJAŹQ½+UAúÒü®îJAÂ÷l–š+UAšJH$JA¸òZÉœ+UA&&CVJA6üåœ+UAauãŠ]JA\­–¯+UA-J xJAí5æÎ­+UA9²Õ¨©JAõOÎò¸+UAµ¹—FØJA 5yÏ+UA‰§(2èJAÎà4‚×+UAÁÑVpçJAý!aÚ+UAí/^þÚJA/'Jì+UAÕÆDÿJAt‹Öñ+UAUÂËo^JAÍé9i,UAX[Å“rJAÖ`ˆ,UAK"™‡JA»X‚,UAvµ^·JA;Ñj,UAfËwÏJA×Ìe©û+UA —ôÝJAÝ!ý+UAýÏÄ JA5xKý+UAiHJAÀ@û+UA {”&JAš0fÑø+UAïè§3JAC…¬ô+UAœxÙƒEJAˆ•––ü+UAáH, TJAÞ¸âš,UA'DÊeJAþfR,UAÅZþP†JA£Jò+UA¼u³}°JAHçV,UA?…4ÒÔJA==Êò ,UAXÉéJAÍ,ZÎ,UAÖGO†JAÅ,UAi4JA³ÌÆn,UAhÁõY!JA#mrð,UAK}10JA\0,UAæÀçe6JAï$È_",UA7]ÌØ>JA8v&,UAÙ[{êBJAðaÉ',UA~‰ÚxJAt¨Û?,UAAG‡$‡JA¶ž5,UAj*bǺJAg–,UA©ŸKfJAcoïæ+UAÌ[¬EpJA\›Ø­+UA;·ŒÄyJAZ<¦+UAqZT‡JA{Y˜+UAJI|ðŒJAh1ÇŠ+UAÙ“,•JAN“Ý…+UA–6Ù¥¡JA+v+UA,Ú§JAS0{rj+UAîaTU¬JAŸK,"[+UAJž¯JAë±¢F+UA=Õ°JAi-UÉ++UAþÞî8­JAë™l|+UAOš¹u¡JAõÒ€þ*UAYâÀÇ¡JA¤è*UAîÅJA΂5@á*UA!‹V“JA+ßo­×*UAûD´)‘JAé~ˆÉÎ*UAµšÄ”JA¢Jõ%‡*UA€?ã”JAsx*UAJþ~‘•JA.ÀÖ`v*UAî_¾“JA²+¯ch*UAmýx©yJA´œû3*UA?¼z uJAì*è*UA–nGpJA(Xµë)UA;^QÛfJAF½k¶)UAž×UËdJAh|° )UAèP"heJA‚¤M˜)UA/´iÈjJAÄ©aEŒ)UAl{u‰„JA3 ”i)UAæ°›/¶JAE>y%=)UAT±»PùJA²ûìœ)UA¹4õh JAÏ!®Å(UA|Áäb JArѨ{(UA%!úÊ JA5Xzv(UAîôn¬" JA–ÖEJ(UAw•ä„ JA1Òõç'UAð´|ìÕ JAs—H*Î'UA_²Q1 JAý‹ÿl±'UA?ç‡m JA×Ñ.`ž'UA>ö|"× JA\W`ȇ'UAe³}I JA¹Ú}pw'UA¶“i{5 JA¶/p'UAâ0…Ì; JAfÆjj'UAéV1›C JAÛ=mà_'UAI1RzO JAkñ;V'UAô·` JAÜ"{°I'UA}&Òt JAÍX! <'UA=š%¿ƒ JA° KG2'UA1ŽSZJA\N…»&UAU XvJA Ý_­&UA¸›¿´ßJAW¾BÙe&UA>—ºiJA1CŽ%UA(û…¥JAµ“Ÿ¦m%UAƒµ§ÓÇJA;Ó·²_%UAœØ1ÚJA³ jY%UAi:JA+h“‘G%UAH+…¯JAQà¶%UA/O_Ÿ.JA€­¥ý$UA}=•®JAç›å¦Ù$UA^ØÂJAm¤ó¿$UA4 E#JAc^ж$UA ä`=JAÔj®Lª$UAü ˜SJA9Žoùœ$UAÉÕæGŠJAº£FÂy$UA„¶“ºÁJA1ýà;Q$UAî¡—¾ JA‡Öe$UA0/vÌ#JA T$UA¬]Ú“/JAæRàúø#UAõˆè£=JAóÅ3?å#UAp¿¶¤@JA•jIÌÝ#UAen4BJA„e¶Ú#UA1ûv@HJAA}GvÇ#UA`–ÍKJAՌԵ#UA­‡vKJAm ùÆ¡#UAvˆŸ#IJAVFiÍ€#UA†€ŒLJAÒùÑëc#UAN[·WJA^Ö :#UAq¼§_JA fºm)#UA,;N=cJAè¯ù!#UA,Ò :qJA‰_M#UAݼ¦Ú…JA’ÎÉà"UA® –ó›JA 7œ>°"UAª·ôÀJAßþZ¶"UA86ˆ ìJAÂD‹!UA,šÙüJAwšB,R!UAgÉ"ÐJAÑÝG‚E!UAzõ> JAiÎñI1!UAê{\JAï¨ÄV(!UA;øJA^¤rß!UA¶?ÀJAZEà!UAeÙ‡‘lJAz5¹CÏ UApž£vJAýœ³Æ UA#ã¡¶JAZh»ÿ” UAšŒ!¡ÌJAÌC}… UAyhWXæJA%³Á‰z UAÓjý8JAòœA:^ UA5ެÙJA_hgç+ UAΟ™'JAëuÀ# UA+â!b8JAÕ2d UAã¶ÿXJAïfר UA:ŸôµnJAèä~– UA|3)E·JAMO Ñ UA˜Š;ÃJA  UAÍ™bJA=ȼ UA®1’­=JAðvñ UA“|„iJA´\Pz UA*H ðJAƶ¯Ã UAìÃîröJAZñ  UAŒ±¨S.JAŒŒA¿ UA·›e,€JAAN4ä& UA3™:J¿JAáH¬C, UA9lúJA‡I0 UAOåŽYŸJAøAT3 UAZ´ÄáJA²W_3; UA¤ UAG LþJAAž¹š< UA”U÷ýGJA]°Þa? UApX?œJAgê©lF UAZapPÎJA-y¡J UAÎd*ì JA`q’Q UASªUd JA8¬fQX UAÕãµ(z JA¥c.Z UAŠëÉ}‹ JAHK5¦[ UAØ¡àÈ JAÑó$f UAàN˜A!JAWÿ¶x UAËÖô1³!JAb±k-… UAsZL4="JAÊ 2W” UAt[f®"JA›Ú\‡ UAsþIí"JA²Å£ UAîmй„#JAÍ:¡>¨ UAÞr¤þÏ#JAz˜ø² UAÉÅ[é $JA3Vså½ UAMïjWo$JAòs’^Ö UA™¥µ$JA°± íç UA;?œÅ$JAdlì UA÷/™ãï%JA6d\>!UA_½öÐò&JAѦç'ƒ!UAo"SQS'JAàî‹P™!UA2OEá'JAÎN.‰µ!UA4~r÷(JA1š|­½!UAX¢³L(JAÙÎ!UAÆrÁ®É(JAéR˜Øì!UA@+)JAh)_"UAGìóÊ/)JA*íer "UAErd@G)JAÑÙ}ù"UAx4š)JAL+‘("UAÓÆÙÈ*JAnM"UAbÌ{ƒ:*JAsø'Y"UAþc+¢*JA°Ù{"UAÕ!V¯*JAžR"UA&’æJâ*JAÀµÕ"UAcÊ5 +JAÇÚ~"UA¥ØüÈ+JA'/Kß"UAÕ@AEÿ+JA·êûò"UA1ûp°!,JAãÓ‰þ"UAªúg56,JAõ<]g#UA¾ê•k,JAç™#á#UA”scŒ,JA(¹úô #UA¤Û-g«,JA% „*#UA~‚;²ä,JAÕ8-¦;#UA­ÉÁv -JA^hHL#UAbÒí E-JA¹q‹U#UA“בo-JA`yW·^#UAÛ,Ú|®-JAŠiog#UAoåÍŒ.JApÈBo#UA»Koÿ/JA£¼în~#UA½‡Ü‚/JAéúƒ#UA”s3ƒ´/JA‚M!…#UAœýZ)å/JAìðK»†#UA"|øMz0JAŠâŠ#UAí}?&¿0JA¥b¦AŒ#UA>jêç0JA Ü#UA¾è˜€1JAµªï’#UAgqµÒ1JA‘Í’•#UAÍuɶ2JAÑÕIú¥#UA˜RµÄ2JAȳ³§#UAïÕòöO3JAvGdÓ¹#UA(*‚Æ3JABØÎ#UAÿÂÏ>4JAáá#/á#UAšhŽÁb4JA’GÊð#UAn:ÜA5JAPo($$UA­2À5JArH$UA ëaˆä5JA\àÖU$UAU6úr6JA2mˆ.g$UAižþ“6JA㚟“$UAí( fL7JA“<9³Ù$UA”üÈ`7JA !±má$UA¿êh0®7JA`³nÂõ$UA͆úÖ8JA)j6%UAÖÌG89JA|·vP%UAyœÖP9JA]~õÕU%UA ¥l:JA½Dí}%UA…þh:JA 1ñB’%UA‹ºpq{:JAßêò±”%UA‰XËß#;JAIyb÷¬%UA–Þ$¬r;JAE®;*¶%UA6{'Ñ>JAa“n&UAó°¢N>JA­‹&UAKódR?JAºÝ>gW&UA¾€Ô?JAØ&ï6d&UA]¥Ý×?JANy±ûr&UA#Ôo0H@JAo9ð†&UA)TñŸ@JAÒ¸` –&UAS]óæØ@JAâüêŸ&UAé-8; AJAP&_µ§&UA'ìÇø^AJA†.åx°&UA´’ÛˆAJAÓHݯ²&UAK5b{¸AJAï8z´&UAÀ‘'±íAJAÔZ–¶&UA\N¨Ó;BJAƒ š¸&UA ï-¿BJA„ÞæÛ³&UA¹n3+ªBJAù=žŒ&UAÎùö±¥BJAí®Gb†&UAO7×ù‘BJA·¶:k&UAuWBJAU>Âg&UA ;΋šBJAðêX¶d&UAIÔxK©BJAåÅpŠ_&UA’õ0ÆBJAD£i»U&UAÈ4òîBJAWm±J&UA#GCJA ÍùA&UAŠ*ÒFpCJA¦ë™…5&UA* ÚDJAI ²®&UAÁçDJAÚO¦°&UAšp³»DJA9ɵ&UA:îçÊDJA<è­&UAò=ª¹DJATà°ú%UAeü `RDJA>SÓØð%UAÅUÁÖ~DJAJØjéç%UA¹Ä ¹DJA ̵á%UAoN<·DJA¥c\¯Õ%UAÙ 4é´DJAVzÓ%·%UA/~ÔÀGDJAvå 3Ì%UAÌ©CEDJAÖ®>É%UArp°BDJA#]hqÅ%UA ³»jDJAμ§âš%UA¨þúkDJAìÃ`™%UA¨4røDJAé-‚ño%UA ¼œÎDJA3ëõk%UAJÛDJAõàD9A%UA~ŽØ'CJAIgd1%UAòd)T*CJA+x.,%UAÿÐ&‹1CJAƨLŒ%UAŽM¡¥:CJA}àë%UA£÷SONCJAË–Ænñ$UA¬;’UCJAgÄ|›ê$UA} ¤œ“CJA—ˆ—y«$UA!Èu~CJA:€¢£$UAw ~AWCJA]÷é,˜$UAŸ±fCJAhÐQ p$UA„ˆî CJAŠndk$UAkÏ^æûBJA|¸S$UA- —Ð×BJAÃׇ$$UAø2­™ÂBJAûŽŒ·$UAænó²BJA{÷Å $UAE†t„¥BJAž…µK$UA³1ãŽBJA·ú¡fò#UA¹·²HBJA‚9òåÑ#UAн,CBJA$ÇåaÏ#UAáúXB5BJA=òžáÈ#UAzäÍÒ BJAi~+µ#UA]9ÊAJAü”xe—#UAŸÅAJAÔðÞL•#UA¿ç½¢AJA—+ׄ#UAuCÀÇ`@JA^+K$Q#UAêe'[@JAeˆØ7P#UA1Ïí&P@JA|``æN#UAÉ ¨L@JAño²~N#UA û»÷@JAå¶VÃG#UAó„5þý?JAÍ MÚD#UAŒª2ã?JAòí „C#UAöü‹vÐ?JAÄIhhC#UAÜb]º·?JA%N}E#UA “}u­?JAú`SwF#UAøõ²Ž?JAS~çMK#UAT"…w{?JAœ-8FG#UA®ôòˆS?JAóŒ§gB#UAÜ¥Ù56?JAî™NA#UAD©åï?JAå&5ì@#UA,æœÑ>JA=;ʆ?#UA©‡B¹>JA-ë™ <#UAWfÿõ¡>JA_ÝE£9#UAè¦c˜=>JAÒ“H>$#UA%Ö¥>JAQÔ#UAòâ‡ò=JAÕPr\#UAŠyè)ä=JAØÕ#UARÊ·®æ=JA ¾R#UA9Aé=JAµë#UA[*J´ê=JA2–¤¸ #UA¹˜V¾î=JAr»a#UAÞÁ.Tô=JA.¦šÜú"UAÒ—n¡õ=JA&6êô"UA7ü»åó=JA²IMï"UA@ ï=JA·o é"UA“ß/èæ=JAW3(-ã"UAÌt\_Ù=JAk̬Õ"UAIÛ{Ô=JAo~”Ì"UAr£QÓ=JAÔ,VëÇ"UAPÛ”Ô=JAãq†#Ã"UAgjæ×=JAÄÍ»"UAóì‚Eå=JAŠçrÌ©"UAÅsX>JA7Ò™‚"UAݳ„¡>JAUÁÓ—v"UA‹›>Í=JAʳlg"UA v œ=JAì[¢Ua"UAðÍ’T+=JA¶Š€F"UAÙÁ…½8=JA?ó93"UA3ÔüG=JA¬÷ð&"UAɰ²ÍS=JA›ÒQß"UAÿ€dp=JA±r18í!UA$jÀ#e=JA–øÓê!UAf¨»^h=JAC/aÇä!UA Ð׸y=JAôËcÈÈ!UAt^ ݉=JA¼x<(¬!UAOC5?–=JA¨¸0—!UAGa ÿ=JAIàrn}!UA!Ê‚p=JA]ú(1n!UAd§a†³®P!UA);}¤JA(à UAß„>JAl„˜õUA±0´N¦>JA×"UAò¨ÚÛØ>JAZ C)UAÉ·[»î>JAЕ ^+UAgj¥ìB?JA‡ýË»7UAž•òL?JA$"²)9UAkT´›R?JAè¡ßú9UAåÞa?JARe ;UA1Cûé¿?JA¡¡÷AUA€Ò[Â?JAé±âß7UAa_îð@JAÐP;EAUA= ú³6@JAl™?GUAMRu!H@JAŒŒd|IUA:s.xp@JA‚·½ÞLUA?+º2œ@JARU`ÛNUAÎÖ@JAFÕ©öNUAÖ™Úañ@JA#‡OUA¾~* AJA~·ë­WUA*HxÞ$AJA^‘€XUAkµÕò6AJA ´ÓêOUA\ñ›FAJA¸xBNUA£iP€AJA+C“AJA û%&UA®t’¬AJAeïï™UA+)Ð(ÐAJAZ T’UAêÜAJA!î‹ýUAKËÞ¿AJA4Á2?äUAž µAJAÂépÚUAì—+s·AJAþX‚åÒUAò°Ê¿AJAr…LYÁUAå†ü¸ÊAJAl Ù°UA:(ÌAJAýœ®UAÃLU“ÚAJA?g$B˜UAÜêNïAJAü²®¿xUAšJÂPBJAɺßo;UA¬dƒ¯@BJA—pC§ùUA̯GBJA¶ÁïUAD‘%P_BJAªþ©ÌÈUAþšblrBJA˜píW¨UAS7òÖ}BJA/I,“UAäºÎ7†BJA ñ`ê’UAUÁ9BJAmcŠ&”UA•÷†¤èBJAÍ1¼¤UA²ø(CJAt3@Œ¬UAð€\º\CJA¨W)ÍUAvUÿwCJAªÚ('ØUA©ë€§CJA[çÍ?êUAÎ 1FíCJAýç»UAo©ðDDJAM .UA„·Š¹GDJA-k 0UAôž5ÈLDJAm´ÿ‚,UAÍHpPDJAßAb°*UAíkodDJA)ćß-UA\lãkDJA)’ûÕ-UApcœ›ŠDJAÑñ…žUA3-¢J¨DJA´KUAs,ÆEJACM£,UA†ÓÃEJAc®š:UAËÆ^¸’EJA7Lº7UAóÛO£EJAž?1#UAIÒà‰¬EJAp2žUA ±®#µEJAÀJw5UApÈ÷ÇFJAL;h½!UAd±5mLFJA®*‚+UAäæ^Ý{FJAQ®°p UAqYlèœFJA=h ïUA&}ÀǦFJAÑgó‹ñUA{$Jh³FJA àôUA±]¥Á¼FJA_| ¬îUAh8ØÝFJAÚòf“ÜUAÉ÷îFJA§¦·ÐUA•'GJAwBv´UAž$ßÒGJA9u±UA°¦©GJAˆ¥Ié«UAÕ¸ RGJAÕ^0—¾UA¼¿nGJANzÑ.±UA[ø3GJAz§æ¶‰UA©# "GJAn&€UA÷Yý3(GJAv5à }UA&4ì×-GJAl¾}{UAöñ¿1GJA±ÁK´yUAHôQ19GJAôÀÜ9wUA¡mÿn?GJAST·ŠtUA]öuLGJAFoUA'Ê­]GJAéÈflUAµƒwGJAf’¦æaUA?8¬ŸGJAif[¡KUADñp«GJA}Á¬DUA—™ó)°GJA.Cà?UA)âmÆÀGJAhJ.UA¡4 ¨ùGJAÙvÅ@UAf§:HJAB¬»*CUA{õÝSHJA]„$²$UAІíZHJAŒEUAЧuIJAíz#LUA|Ýl–¯IJAHëpUAÒ0”³IJA÷Óßc UAjñŒ³IJAì{ëUA$à`аIJAd˜¥UA‹Ø¹€IJAyÈ–ÐUAß÷ÌSIJAfDÙ¡UA6JºIJA,M“cMUA@ŠüHJA˜4NÁMUA瑎IôHJAdX|ËMUA®/?åìHJA«=µ/UA×@þHêHJAûÒª$UAõ/ÜéHJA±UAî®ÅÑHJA‡;k©UA—¼pÇHJAôø‡#UAÌåñƒÁHJA±]Œ‡ûUA™éL¼HJA–%oòUA¨J¯BiHJA‡ÙÞø®UAÇrÛ9UHJA%³x`¦UAè &±(HJAs#2à’UAøÙHJAÑ[BˆUAa(·HJA•»ØƒUAcœ2ÿGJA9™ÞötUAž› zÚGJA¦6ßÀ@UA]Åð-eHJAµ&OXEUAZlßÊ—HJAýÙ$”UA“Á1†ûGJAk¡t²üUAyÖÛþGJA †»TøUAw.©rHJA#m­ÅÙUAiËÆPHJAfáp°ÇUAÐ},j%HJA‚…µUA˜ù‘Ö(HJAÓå’ÅšUA •ŠŽ'HJAŒ§UAG¾r~HJAOr÷kUA·FʲHJA—Ì •IUAq±¡HJAÝ5¡«EUA³Ñ‡WHJAoR°è@UA+ É\^GJA¯Æàè9UAD/PGJAbB½æþUA‰bWóGJAÁ¼vºUAJ²éåGJA‹ÀUAúIìÔGJA{Sf”sUA\õÚ»GJA÷@ƒuUAL b»GJA`prUA.n~µGJAD}‡ 5UA°ü=¶GJA>€qŒ1UAï„øGJA ±o%UA(hLØÉGJApB–¾÷UA©ô?/ÖGJAòàóøUA™‘˜ÏåGJAÉ Q úUARÄXÔ[HJAÛ_µUAê¿«ƒdHJA ˜?EUA¹»@ ƒHJAIkÏUA <é„HJA÷ë…ÍUA™$J=³HJAw¹B6ØUAiìØÀHJAø†aâÑUA–)(›IJAÌåÃÌUAoàü IJA©…ÆUAt .IJARÂ%†ÅUAÉOè0rIJA}±’©»UA×êx¡JJAPIi$LJAuÞ·5yUAóþÈ£xLJAÇË—öŽUAmÞâwLJA¤Ñ6“UA½í¾ŽcLJAÚyàÏUAÉÇÈJMJA}*DUAz´[PMJAlc™UAn¢VMJA ÜìÛUAî}â~^MJANž5º UA¿§S$dMJA*wJ UA"Œ‚_MJAƒØaUAh—YL5MJA^ˆ]„UA"…F5MJA?\ùYUAÅþææOJA+KiUUAq@w`#OJA 4÷vUAMBå$OJAÒƒâeyUA9Å=-ùNJA`r¬üzUA䤟7ëNJA 5ð¹°UAî˜2ÚNJAÛœO´ÅUAYßgaÚNJAw®ÀÒUA¥feïNJA®é î UA%ÄO‚üNJA$¥Ø38UA VÇÆOJA¡„I>JUAÀáÍ*OJA6ÇäcUAÅ”úOJA™–)]aUAØòX½ƒOJApÝtoUAÁ2|OJA‹,†ûnUAœ;8õOJA™[ÐkUA®ÐÞPJAò¦SnUA"ÝA= PJA§ˆ$†rUAv9îÀPJA’\ð„‚UAÛ”yB_PJAù1ÖEUAœÂþ_dPJAamUAG» SJAGMü&lUAå…Ó.SJAWÇITgUA3m¦4SJAÑ´àžgUAyÿÂ^MSJA@ß;fUA.}\ËESJA-!)QUAž6?ORSJA#Ó9`RUA¯-sSSJA•j>ÈWUA ¤SJA"‘g£gUA©¯™ÝöSJAßJ.”uUAÈhñÕTJA ŠG UAƒC+G6TJAi³œ#„UAÜF?FTJAR“Æí†UA’UTJAøV\ŠUAzIµTJA·77¢UA}ªÖüTJAë¸@p²UAn¿ö UJA<{ζUAFݼUJA‹ýV«ºUAœ(UJAñhë½UA±TýwUJA™'A°ÏUAÄä;UJA’ÖßÑUA×»lˆœUJAeØ¹ÛØUA›õò¥UJAU´ÎPÕUA­"¶­UJA¹þ<ÏUAÿ®—øUJA\ž”UA¢ìUXVJA·J’/HUA†Ê·yzVJA@šE>,UA5ñ+éVJA“Fi´UA/¬½¼øVJA+¢.(UA¿–-ëWJA>8_>/UAÒÓçIYWJA‘°ž1UA¹OBuWJA¹%©ï3UA3÷ÈÙyWJAûˆñ;4UA¹úÈ£˜WJA0¿¡09UApÒ#§úWJAKôSõKUAVf!kEXJAaè?¦ÃUAb}}[fXJA{.]‡UAÏcí„‘XJA>•Úx8UAÄòè˜XJAyN;t,UA8ÇwžXJAÀàÎN#UA`c”´ÑXJAŒðôŸßUAîò‹c@YJA qäNUAmxŒÍhYJAÙÿ#øUAñ²nE}YJA±U ºóUAÝÌå…YJA&_âUAÃÝ´f†YJAY $ßUA¼c;«ŠYJA7tÐUA-÷a#ŽYJA´¬¶5¹UAnÊÕHŽYJAiÅ/ë™UA­‘ iŽYJAËrwUAŒ/‚}…YJA ÐýUAæ¶‚zYJAhéAâñUAð­XmYJAZm¸{ÑUAï+€‚_YJAæx©·UA #íQYJAÈRCó¤UA"È4@YJA×wêÖ“UAj• -YJAY†¦ƒUA]‘Gø YJA•$þhUAF‹»ÛXJA®BUAª|¹¯¸XJASw|0"UAÌœ¬XJAKKë5UA CÏÆ~XJA¸²Z÷ãUA_Ÿ’ëaXJAõ]Ÿ½ÃUA™-?XJAXÔ÷£UA»ÓI¸"XJAÖ~f÷ŒUA2¦XJAÖ§p}UAÂEÛ;XJAP¿ &iUAŒÑŽÑàWJA)ºu9UA晋yÊWJAÑÖ!ëUA¦}H»WJAH\JÅùUAVi¡t®WJAïl ´ÛUA^×ݸ WJAÚëõ¶UAÿnšWJAC¼>®ŽUASðê'—WJAÑþ[pUAåÄ÷$–WJAšMtHJUA'Þò`›WJAÍdüd2UA—gÄ©WJA(•C)UA”ÙÐWJAúç÷·UAmÊ@+ÕWJA½6ÿO°UA^vÃîWJA¸`´è‚UAZƒI¾õWJAÔƒUAžÍR¡¹YJA£[û1þUAô‘ð¾çYJA~¦é©ôUAÊÏkÈZJA®tš¸ðUAÃ-[P1ZJA“!²êUAçŽ}§ZJA8 ®1ãUAâ|>0ÐZJA2!^‰áUA—Áמ[JA{êkßUAÔf«©[[JA=å@zÚUA¼¾4¨˜[JAW»ÊÏÔUA>?ËÆ[JAÔˆ† ÎUAqø~¥à[JAË}kÈUA̪ku%\JAW¡ÒºUAºUÙñn\JAÌ`Æ+©UAä½ÏÄ‹\JAb=°u UA ôþœ\JA¬ùL›UAT%ɽ\JAÄmÍÏUAKêÕ¼è\JAï$Ü|UAÑjá]JAÎ=„„fUALš\J]JAˆÃìCUA.´OÅj]JAÉ&©*)UA’ö1™]JAÞ­¾îUAv÷C³]JA;ã¹UAùãBd¿]JAÍ— ^ŒUAÄ»¤×½]JA¨:6LfUA«×R½]JAˆˆ4wYUA*º’¯]JA|¶ /UAP% •›]JAµ_’ËUAn¹g=}]JA™FiîÍUA}¸¥Ä3]JAzº½\UA*u&%]JAõæE÷UARMIÙ\JAÂ(vIÍUA<ÿmа\JAj®…UA¤][¦\JAû§ fUAl/xñ¡\JAß~@PUAR0Ô)Ÿ\JAt@Ê&UAoº‘Ÿ\JA%sZAUAXUûˆ \JAÀÛÏnÿUAû–ã§\JABË4­äUAL9¾-·\JA…$F#»UA' Ï\JAOº¦}ŽUA|¾ Ué\JA°‚ ékUAà—d*]JA¡HqPUAããÛ>]JAj~ÚâUA±“Ó­“]JA”«æ§ãUAÄ`§v^JAü[bÓ˜UA]h¹'<^JAÐ 5×wUA ·ºee^JA,$]ý[UAªMï^JAaªù UA‚¡«Àz_JAèÕÌ)• UA'Jøº_JAÃ}[ƒ` UA™o_JA M UAd_ç`_JAJ#lyA UAp•&H>_JA£:Ln7 UA«·ÞQ$_JA™jb. UAÊ~êF_JALˆ+% UAá_ÛØ_JA>Ñ8 UA_ör”ö^JA {Ô UA2>“°ì^JAõõM UAÒ;ò=^JA6}ù UAª3<æÙ]JA»#hL@ UAÞN’<¤]JA"QÝô4 UAÃã´}]JA ñc•- UA.p°=]JAZ¼Å UAàJv]JAí íÒ UA7ù¬Âà\JAĈl UA Ÿˆ\JAL'SÉæ UA‰(9M\JAŠ}&#Ë UA‘=*;\JAﺠUA¬z$®-\JACµç<Ç UAä× \JA©&ùéº UA§šÈD\JA‡kë© UAhpõ²÷[JAUv(êš UAEõRó[JA²ü‘Ó“ UA0%F1ê[JA¬/a—‹ UAᣜøí[JAi°Ú9y UA1 Œüó[JA ¾f+g UA7ù[JA#r&û^ UAæ`÷Ê¡[JAÔÐ`!' UA¯IÈ•[JAo­ŒË UA‰ÖÊZJA”›¾ï² UA™™Ån}ZJA'KÓ UA÷*ä?ZJAÒùÑ»t UAæ²6CüYJAaçFQ UA(!‚œYJA$|ÏÍ UA†\®>‰YJA÷SIÓ UA•*°cYJAžÆ4e UAÚF–Š^YJAo*¡ UAß™’>NYJAÂæ%q UALÑöAYJAÄÏk UAÏrá5YJAüi UA‹Æ›Å(YJAýÿè UA©'‰YJAÔ˜M UAË~mÃXJA?Qh-& UA2˜­Ý•XJA‰ö“k, UA\(ðKlXJAª;š<- UAháÁ•üWJAü’µ¼( UAö>ŒœWJAÛ¡w7# UAÐÝò–WJAÓ»•"# UAŠþ”WJAB3ª # UAµWÀwWJAªÞ" UAXÂ’dWJAz[!Š UAµ!q¼PWJA/å UA'pþNWJAæMb1$ UAFñb$NWJAþO¶‡& UA»¨ WJAº\Ì& UA«ê šúVJA£š¿»O UA&–IWJAÔ³úÄP UA¾}rWJAº w^Y UAvPÔi¹VJA ÍܘV UA•î¤!´VJAÁÝQ UAø/æÃ(VJAÍ\ÌQ UA3…íTJA>àS UA‰Š±  TJA¯Æ7`S UA.|¸‹“TJAÁÂjQ UAEÆQ7ÎSJAGy‚W UA›Ã)‚¦SJAê 2¥X UAUãí%SJAV-r…W UAÍ´!ztSJAcZ7gK UAíÈc_SJAŒQQE UAj—*USJA»vB—< UAŸÖv²ASJAÀwÜ UA;,å3SJAÐK³Q UAY¡öRJArr UA~ÒÛSJA{yZ~ä UAöP·RJAä5œË UAÿ ~íÊRJA õø¥ UA~ĉTÔRJATLR UA¶Ê¸ëRJA[¬b*: UA=pW‚+RJAÙÊ€+/ UAæô â"RJA¥&ßÓü UA\£o-èQJAI…BDþ UAXȦbçQJAåâ­sú UAr˜‚IäQJAœ´Å†ô UAƒ×ÁßÁQJA›R}ö UA°c%5¶QJAÔ¼•ö° UA5óÆ!¨QJA·!ÐX± UA¬Š´€ŸQJA›kÂÒ‚ UA­4"ôPJA£V@¯„ UA¾+)·PJAï±Ô, UAM.#´PJACQ`~! UA¼2²@šPJAhVbüUAö-ï—PJA4 ޶îUA “\´˜PJA›æ†äUAø×%žPJA (ÌèÔUA3Ëý¥PJAº߯UA“Ë«¶ªPJAešàA·UAµ¶CDZPJA>-Dw­UA!_%@QJAj«SM*UA)8?…PJADmî’UAÉ(êOJA¼\òUA¹ï;ó¼OJAs+T‡UAÎ?"2OJAGrsxUAõ}(ÙOJAw]¨|UAÛnýʆNJA.Ñ`ÉUA©}QqNJA]b7pUA®šJëPNJA–«ôUA‡úþi NJAtVäaUAžf2Ô NJAWD™euUAƒ|¨íMJAmp{/„UAÙFÊMJA&mÝj“UAÔ8É«MJAšÁôÒ§UA‡’7ŇMJA¤—ØšUAf3PpMJA=å+”UAY2„ZaMJAêÄF ¿UAr›Ö?LJAKmQîUA‡ïQLJADù“üÒUAè:ËìLJAü™¹ÙUA½WL‚­KJAÉÛ|yáUAQ|²üÏKJA5mÛ> UAÝØ1Â;KJAƒu~ðJ UA õ•´2KJAغK UA†LiIKJA•ÄEI UAÆe¨ÜJJA“ö‚_  UAu2JJA)Ãy„ª UAN”æÜIJAh‘± UACY;àãIJAnRÑÐ UA†h̲ÄHJA’ƒþ4Ñ UAåRxÅHJAÄ Ži® UA†¢O£VHJA;[¯ UAxš=AHJAQ8î0¯ UA#Ë(Ä8HJAë^£ = UA¥eEÆ8HJAØÛŒG UA íªaeHJA- B UAyhËwyHJA^°Ñ1{ UAšã)?HJAî¡wS UAºŠŽí3HJA8‡Ê³ UA€l^Â*HJATÙ…› UAh;*HJA3„ßÔÑ UA2dW-*HJA3)B UAØ×@2HJA å¨z UAbÓŽ7HJA2N~‹ UAz|´ª:HJAŽÈÏ” UAå$\N1HJA1U·ó§ UAæ¼²0HJA~'{CÞ UA­ÙHJA^2_~ UA¯šI¸§GJAOE UA‘‹Ô‹„GJA‡Àô; UAÏY ÞjGJAïZ_ UAî/ˆB{GJAJwa UAâ¡X0GJA*í“¥á UAÓó´mGJA(4Þý UA ŸKqGJAé<£ UA/NÒ£xGJA;AŽ˜ UA…^1–éGJAA˜Àõ3 UAdßø²GJA›zUU UA¬äÜ#ŸGJAúšñka UA$‘Ö¾‘GJAIs. f UAËÙOKäGJAÊ´¤ÀŠ UAChýKýGJAH‡BÚ“ UAö/:HJAvl¦ UA^2÷HJAˆcLÈ UA}×HAHJA“‡¤ UAš3H÷HJA¾^³S6UAKËÅ@DHJA ; CUAØO…>HJAT€HЂUAhæñšHJAþ·Œß‰UAôþ”sHJA%Ãdù³UAF¶«ŽUHJA|R$òÓUA\Ÿ]HJAËHšÏUAÐ@X4úGJAY4ðUA5%ÓÉ÷GJA,ÞòUA냘ôGJA±pèöUA&Öµ¾þGJAB‡ÉúUAd"HJAØRÊÃMUAœ´¢æ"HJA{uuVUA9›ÑÛ%HJAüÔ?‰bUAÒËo2HJAóD| vUAáþð`OHJAþ¹–UAñZ$HJAÑ|Gf¢UAm õ¦HJAZVi—UA¸+6޼GJA€X&§UAv>uZ˜GJAÌjÛ‚­UAÙ_«r“GJAX¼ºæºUAn¨yGJAãyy¶UA´`%FGJA A«ªUA²œ&ä"GJAòÄa¥§UA–@ýFJA—:´…§UA¶ÕAªFJAïPŠó UAÂ2|íEJAéú*!™UAê]ÍÄEJA&•ʬ”UAÁØI:˜EJA'QèUA¼/êREJAmQE€UAm-EJAXÄ•{{UAžÊjEJAÅmr&zUAÀÖ;žíDJA²yUAä4aN”DJA$Ö²&xUAkìù²nDJA~zƒÙtUAݵ#bDJA1.°fvUA‹Uƒc7bBJAQßGóUAÈQ!­BJAÒS0áUAGçH÷¡BJAÝ Q„UA×>jŽBJA ,ÈìUAUaÐ1‹BJAÚˆyíUAw,·ï’BJAÌz"UA·c¡ŠBJAÇîà,UAâdú˜BJA0ê˜ê.UA|¼¹‡–BJAš°$,3UA|j!BJA"¢Aµ4UAFÛk‚BJAV®i)8UA[ÒlBJA‚M.AUA tL‚OBJAâBƒPUAÏþo¬GBJAƒÔò•TUAÙófABJAtØÞšYUA NY$>BJA_|á_UA*A >BJAUÖ‚ hUAåçž:BJAAƒÛ|UA]Ú gBBJAQÚh~UAê7q9BJA,”å•UA®L¡t@BJAZ¥ê_›UAú IC3BJA w‚¸UAŸÎ¸1BJAuºþù¼UA—2lÑBJA’°~WÌUAÛ»Y¢CJA‰´¨ÞÔUAþú­>:CJA Ö¬ÙUAØJÀæ´CJAÕµÇðUA¬^ŒïCJAØ:IpúUAsÈ­/DJA‡ó@zUA–Š[•WDJA[ÌgUA¡aÏÍzDJA9ÿ–Ò UAoñ=-¨DJA%î? UA[*Ë~DJA§-TR9UAv?ó«DJAgÞêEUAà{7Æ EJAo$Lø^UA êF-EJAʕކbUAŒIdÔEJAä}œBeUAXJÕÎSEJAI3•,sUAådó/EJAcc·„œUAÔj{qEJA¨6ÌÓ¬UA¢A!”aEJA‹$f½UA<â>؃EJAÜóyÉUA!áÇÃEJAoÚé ßUA>úдEJA¯mžçUAÝ$³öÁEJA›êCðUA±¥YÇEJAˆ°t$õUA.¨›EJA‘%iªUA‰+Aø‹EJA ©eUA³ RÖ4EJA9òÆ•UAsUýšEJA×úÓA½UAHg<¨ÜDJAí# í³UAÏnmÐlDJAû8Ÿ¦UAb§Æ(DJA{‹€XŸUAÛLÛFDJA›´kÈúUA<‹/<…DJALÔ±UA±¬nqDJAO@ÊÂUA"€BœlDJA˜û…ÉUAk(~lDJA­e e'UAÞð¸¼mDJAñºÉë<UAÕšÙ¶pDJA_-ÁDUAPÝÉ…mDJAí}MpIUAÚ ußkDJA¤§´OUA²›ôŒlDJA”ôR YUA¯…)OpDJAã³0Œ`UA`¸¸^DJAÝ‚m_mUAã3DÀLDJA·m±vUAùÎ5@DJA»)º¾{UA¨|Þƒ3DJAY¯×v~UAÇádªDJA‘½ÄSƒUAÔœßûCJAîç|„UAíX­ŒÊCJA‡ªÔ(ƒUAy\=ôÈCJAýh€…UASqLèÈCJAÜ-¦¾‰UAåGuMÇCJAhßï@UAgh&׎CJAÿJUAÑþÍuaCJAùèµÛŽUAU‰~ÉFCJA°mÝ‘UAŒwùß7CJAr#[•UAÚ¸­…1CJA @L™UAhM„-CJA~zSåŸUAA˜qo-CJAqQﺥUAR¡1CJA%SŠY»UAö﯆.CJA FŸÈUAaÞcÞ#CJA E?çUA8&Þr!CJASÈ!ôêUA%ðY¿CJAƱ¨“ñUA¡¼ CJAýä’fUA/d­ªCJAÐÁ†… UAáw¸GûBJAZ´p’UAÿ‡JNóBJAÉMÄUAgÆÎéBJAó[å#UA2 d§ÖBJA}gŒ<UAE ¾BJAI)ðOUA (’jžBJA‹âO¿eUA˜’6–BJAð‹ õmUAxáä<“BJAy_tfuUAÙ͉‘BJAdR~UA$†y:’BJAÜê–Á‡UA'¨&’BJAZŸ3—UA䬖BJAÕ…•UAÖ ªºBJAIëž&šUAR DߪBJA¬‰°³ŸUAÚ» ¸BJAué¤UA—¿„å¿BJAUJ‹d¨UAòR3…ÄBJA+hK ®UAvÿ¦¶ÊBJAʹkˆ´UAˆwÒBJAu†Q°¹UA²](6ÓBJA¹ƒ¡¾UA!9:ÑÐBJA™T1ÃUAUµ~nÑBJAÊ$ÉàÊUAH!Ð^ÊBJAèZÏÊUAQƒzÄBJAÓþ×ÊUA?(ê•BJAIJrÍUALíÚ¥µBJAÚ± UAÍ‚i°BJAˆ+@>UARA9¿AJAÄ`‚xUAú„i‘~AJAW¡3ÒUA9Ù l}AJA°C[…ÔUAÚÎP|AJA+˜pÖUAî>ÏAJAtj†ÜÚUA·©^_¦AJAk¾‡h÷UAì|üœ¹AJARåáxUAF¹ÇAJAn– 7UAr)²»AJA$ ¨­UA‰ð HžAJAA‘;iUAžñ 8šAJA÷"#©UAƒZ[ÔxAJA¢Âšo4UA"†=uAJAÙÂ3;UA×ÃchAJAXâAAUAeg`uAJA k§GUARÏ{AJAÿÌ÷KUA°­ÚY[AJAÆdlUApÜg PAJAKo ðmUAy—‚kKAJArD€ömUAky·¸AJA<:ûj—UAàÁÑ(Õ@JAAìzdÇUA•˜-ï°@JADÚâUA™aK‘@JA WäúUAÇ5rñƒ@JAÃÂöUAü͉d@JA# ªíUA| Š^D@JAט{_çUAÍx¤2@JAò½‹ãUAÛ³§è@JA°â2LâUA›Ú¹÷?JAMߎGâUAo6ç?JA¸T•(âUA¥Â9ß?JA-Š® èUA‡$ÓÇ?JAÍSèUAØ»çm¡?JAæs×`èUAзÑ?JAbûëNéUA¬ ƒ‰B?JA7‡ íUA¬úé!?JAÿCQ5ïUA† ¶VÓ>JAtô‰ëUA/G@ˆ>JA6'­ÂæUA a‘MS>JAMN¥áUAŸ¦9R>JA…þYÜUAr×#¥N>JAl²¾A²UA£)dI>JAÚˆ© UAÓgœx&>JA·÷6ŽUA?Ⱦ(>JA ¬8vUADmµ.>JAtÈÇ&VUAôôÎ">JAoȰUUAK=¬>JAqUý²TUA•”ww=JAÁTOUANNG0=JA€[qKMUA1óv‰üëÄUAŒQ82JAnÌ„¿UAið é1JAá3O¾UA¬\™l•1JAfwf¡ÀUAhÍúU;1JA¡~æ¶UAXÿý1JA:ÒSõ®UAÎ×E0JAkZ©:UA$ƒy)0JA°¹wB­UA [Òü0JA=ÿø¼UAÁY°²0JA鉬³ÌUAlѱõ/JAàû.ËUAÖtÑG”/JAsÜ=>´UAÔI’A/JA¡P¸Ç¡UAŒ˜I¼.JApÈ€8ƒUA‚v³k.JA:8ÙbUAÿÐDLù.JAèã6UA§Ö}™€/JAËÆíç¾UA"8z/JA<5Ö˜ºUA0kßs/JAàû°I¶UAø|¸–/JA ´i ¥UA©1‰,÷/JAŒÂ|M~UAãß;0JA¡œˆzUAAèêUÏ/JA/ø~NeUAbŽ{0JAw¾ÚUAÔ2ž@Ó0JA’sƹûUAá¼×çŽ0JA˧cÅìUA(†R@0JA²ÿÎÆUA¶H8±h/JAÏyWÿ–UAï…7$x/JAF8ó§‹UAæQ™“/JA8Œì´qUA¦Žj//JAúiFUUApb|ÖÈ.JAÓBýÃ:UAj)±PÞ-JA(^,vUAÁÔÒn-JABô³UA AJ:-JA»ÕñUA èù'-JAòÍsUûUAéiûýø,JAéßÐ%ìUA¾Ïìâ,JAb¸ìåUAF`lÆÐ,JAû&ðrÝUAßýŒÙµ,JAñ¾ÌXÎUAçµ$ãš,JAѵ|¼UAÏEíyUA›’n§+JAÑõžiUAݧù™ž+JAãëðS^UA»ÈXš+JA:×|VNUA¡…ÿš+JA"Aš¦GUA¨ôz:§+JAJª‡¸8UAí{X'é+JAËDwÿUAžõÎñ+JAUˆ÷UABe™ô+JAl%&FóUA]êþwò+JAqÿú_ñUAìÓ¨+JA­÷ÉUAFÖ¨ZŠ+JAD1D¼UAPé×»ƒ+JA&dn¹UAîDáÝ{+JAÌp®±·UAv½f=l+JAäV¸UA~©§½*JA¯YMC´UA2ƒuk*JAÇгUAc+^K*JA~%²UAí3A*JAJàÎÒUA –;¤ò)JA9\ ÈUA.9˜ŠÐ)JA÷ÓûUAšŽY#Ä)JA†µŽLøUAð!”ÔX)JAƒÔ¥ÚUA; W?)JA~U¼Ž¶UA=<€ËM)JAÑíU °UAñF€µ÷(JAÒW. ˆUA’ÅÑ•™(JA–(áûYUARPwH(JAY¥1Ê?UA ñA&>(JAä´cß:UA´ÝØÖ (JA:-4MõUAJôrþ'JA³ö¸âUA«È)šÙ'JAhܘÈßUA±aÄ'JAÖ˜rQÜUA¼áíþ¨'JAÆ ÂÛUAbq¹w'JAŽMdPÞUA uHQ'JA” åUAûQft''JAo‘¥ðUA“¦'JAœ™}UA¯8ùÝ&JAMcþUAmapserver-6.4.1/mapscript/java/data/subset-umlauts.map0000644002461700001440000000124012261257215022641 0ustar tbonfortusers# # See http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1753 # # Donated by: Nicol Hermann # Modified by Umberto Nicoletti # MAP NAME test EXTENT 3404414.882766 5429530.647216 3456884.187265 5550332.450907 SIZE 600 600 UNITS METERS LAYER NAME test-iso STATUS DEFAULT TYPE polygon DATA "iso-subset" TEMPLATE "dummy.html" CLASS NAME test COLOR 128 128 0 OUTLINECOLOR 0 0 0 END END LAYER NAME test-utf STATUS DEFAULT TYPE polygon DATA "utf-subset" TEMPLATE "dummy.html" CLASS NAME test COLOR 128 128 0 OUTLINECOLOR 0 0 0 END END END mapserver-6.4.1/mapscript/java/javamodule.i0000644002461700001440000001331412261257215020542 0ustar tbonfortusers %include arrays_java.i # Uncomment this if you wish to hace enums wrapped in an interface compatible # with that generated by swig 1.3.21 (tests wont compile, though) #%include enumsimple.swg /* Mapscript library loader */ %pragma(java) jniclasscode=%{ static { String library = System.getProperty("mapserver.library.name", "javamapscript"); System.loadLibrary(library); /* TODO Throw when return value not MS_SUCCESS? */ edu.umn.gis.mapscript.mapscript.msSetup(); } %} %typemap(jni) gdBuffer %{jbyteArray%} %typemap(jtype) gdBuffer %{byte[]%} %typemap(jstype) gdBuffer %{byte[]%} %typemap(out) gdBuffer %{ $result = SWIG_JavaArrayOutSchar(jenv, $1.data, $1.size); if( $1.owns_data ) msFree($1.data); %} %typemap(javain) gdBuffer "$javainput" %typemap(javaout) gdBuffer { return $jnicall; } /* String conversion utility function */ %{ /* These functions taken from: http://java.sun.com/docs/books/jni/html/other.html#26018 Umberto Nicoletti, umberto.nicoletti@gmail.com Fix bug: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1753 */ void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) { jclass cls = (*env)->FindClass(env, name); /* if cls is NULL, an exception has already been thrown */ if (cls != NULL) { (*env)->ThrowNew(env, cls, msg); } /* free the local ref */ (*env)->DeleteLocalRef(env, cls); } char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr) { jbyteArray bytes = 0; jthrowable exc; char *result = 0; jclass jcls_str; jmethodID MID_String_getBytes; if (jstr == NULL) { return NULL; } if ((*env)->EnsureLocalCapacity(env, 2) < 0) { return 0; /* out of memory error */ } jcls_str = (*env)->FindClass(env, "java/lang/String"); MID_String_getBytes = (*env)->GetMethodID(env, jcls_str, "getBytes", "()[B"); bytes = (*env)->CallObjectMethod(env, jstr, MID_String_getBytes); exc = (*env)->ExceptionOccurred(env); if (!exc) { jint len = (*env)->GetArrayLength(env, bytes); result = (char *)malloc(len + 1); if (result == 0) { JNU_ThrowByName(env, "java/lang/OutOfMemoryError",0); (*env)->DeleteLocalRef(env, bytes); return 0; } (*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *)result); result[len] = 0; /* NULL-terminate */ } else { (*env)->DeleteLocalRef(env, exc); } (*env)->DeleteLocalRef(env, bytes); return result; } jstring JNU_NewStringNative(JNIEnv *env, const char *str) { jstring result; jbyteArray bytes = 0; int len; jclass jcls_str; jmethodID MID_String_init; if (str == NULL) { return NULL; } if ((*env)->EnsureLocalCapacity(env, 2) < 0) { return NULL; /* out of memory error */ } jcls_str = (*env)->FindClass(env, "java/lang/String"); MID_String_init = (*env)->GetMethodID(env, jcls_str, "", "([B)V"); len = strlen(str); bytes = (*env)->NewByteArray(env, len); if (bytes != NULL) { (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str); result = (*env)->NewObject(env, jcls_str, MID_String_init, bytes); (*env)->DeleteLocalRef(env, bytes); return result; } /* else fall through */ return NULL; } %} %typemap(in) char * { $1 = JNU_GetStringNativeChars(jenv, $input); } /* The default mapping would use ReleaseStringUTFChars to release the memory allocated with JNU_GetStringNativeChars which causes a memory corruption. (#3491) */ %typemap(freearg, noblock=1) char * { if ($1) free($1); } %typemap(out) char * { $result = JNU_NewStringNative(jenv, $1); } /* =============================================================================== RFC-24 implementation follows =============================================================================== Modified constructor according to: - cache population and sync, item 3.2 */ %typemap(javaconstruct) layerObj(mapObj map) %{ { this($imcall, true); if (map != null) { this.map=map; } } %} %typemap(javaconstruct) classObj(layerObj layer) %{ { this($imcall, true); if (layer != null) { this.layer=layer; } } %} %typemap(javaout) int insertLayer { // call the C API int actualIndex=$jnicall; /* Store parent reference, item 3.2 */ layer.map=this; return actualIndex; } %typemap(javaout) layerObj* getLayer { // call the C API long cPtr=$jnicall; layerObj layer = null; if (cPtr != 0) { layer=new layerObj(cPtr, true); /* Store parent reference, item 3.2 */ layer.map=this; } return layer; } %typemap(javaout) layerObj* getLayerByName { // call the C API long cPtr=$jnicall; layerObj layer = null; if (cPtr != 0) { layer=new layerObj(cPtr, true); /* Store parent reference, item 3.2 */ layer.map=this; } return layer; } %typemap(javaout) int insertClass { // call the C API int actualIndex=$jnicall; /* Store parent reference, item 3.2 */ classobj.layer=this; return actualIndex; } %typemap(javaout) classObj* getClass { // call the C API long cPtr=$jnicall; classObj clazz = null; if (cPtr != 0) { clazz=new classObj(cPtr, true); /* Store parent reference, item 3.2 */ clazz.layer=this; } return clazz; } %typemap(javacode) struct layerObj %{ /* parent reference, RFC-24 item 3.2 */ mapObj map=null; %} %typemap(javacode) struct classObj %{ /* parent reference, RFC-24 item 3.2 */ layerObj layer=null; %} mapserver-6.4.1/mapscript/java/README0000644002461700001440000000475712261257215017134 0ustar tbonfortusersJava mapscript ============== WARNING: Starting with version 6.1 Mapserver (and Mapscript) uses libtool to build the shared libraries. Some files have changed names and the javamapscript.so shared library now depends on libmapserver.so. The easiest way way to handle the dependency is to simply use the 'make install' target. To generate the SWIG wrappers you need swig > 1.3.24. MAPSCRIPT Reference ------------------- The complete reference documentation is available on-line: http://mapserver.gis.umn.edu/docs/reference/mapscript or in the file: ../doc/mapscript.txt SWIG wrappers ------------- MapServer releases, beginning with 4.2.4, contain pre-generated wrapper code (mapscript/java/mapscript_wrap.c) and class files (mapscript/java/edu). Nevertheless it is recommended that you generate your own using the "interface" target in the Java Makefile. Requires swig > 1.3.24. Version above 1.3.28 or 1.3.29 are recommended. Installation ------------ After MapServer is configured and compiled, change directory to the Java mapscript location and execute: $ cd mapscript/java $ make $ make test (recommended) $ make threadtests (optional) $ make install (required as of 6.1) Remember to set the appropriate variable (LD_LIBRARY_PATH, java.library.path or edit /etc/ld.so.conf) to make sure Java can locate and load the libraries. Windows ------- Edit makefile.vc to match your environment. You will need to set JAVA_HOME and SWIG_HOME to the appropriate variables. You will likely need to copy all of the DLLs needed to run MapServer into the mapscript/java directory (including libmap.dll) so the mapscript.dll can see them to run. cd mapscript/java nmake /f makefile.vc nmake /f makefile.vc test International language support ------------------------------ Since May 2006 Java mapscript has complete support for international languages usage in queries and mapscript internals. To document this improvement we have created the examples/QueryByAttributeUnicode.java test program which uses the ISO-8859-15 encoding. http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1753 http://thread.gmane.org/gmane.comp.gis.mapserver.user/19298/focus=19298 http://thread.gmane.org/gmane.comp.gis.mapserver.user/19213/focus=19213 Onlice resources ---------------- Java mapscript related: http://mapserver.gis.umn.edu/docs/howto/javamapscript http://mapserver.gis.umn.edu/docs/howto/java_mapscript_Tomcat_55 http://mapserver.gis.umn.edu/docs/faq/thread_safety General: http://mapserver.gis.umn.edu/docs mapserver-6.4.1/mapscript/java/CMakeLists.txt0000644002461700001440000000262012261257215020777 0ustar tbonfortusersFIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(JNI) FIND_PACKAGE(Java) if(NOT JNI_INCLUDE_DIRS OR NOT Java_JAVAC_EXECUTABLE OR NOT Java_JAR_EXECUTABLE) message(SEND_ERROR "Could not find required Java componenents. Try setting the JAVA_HOME environment variable (required on e.g. Ubuntu)") endif(NOT JNI_INCLUDE_DIRS OR NOT Java_JAVAC_EXECUTABLE OR NOT Java_JAR_EXECUTABLE) INCLUDE_DIRECTORIES(${JNI_INCLUDE_DIRS}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/java) SET (CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/edu/umn/gis/mapscript") SET(CMAKE_SWIG_FLAGS -package edu.umn.gis.mapscript) SWIG_ADD_MODULE(javamapscript java ../mapscript.i) SWIG_LINK_LIBRARIES(javamapscript ${MAPSERVER_LIBMAPSERVER}) ADD_CUSTOM_COMMAND(TARGET javamapscript WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} POST_BUILD COMMAND ${Java_JAVAC_EXECUTABLE} edu/umn/gis/mapscript/*.java COMMAND ${Java_JAR_EXECUTABLE} cf mapscript.jar edu COMMENT "Compiling java source files, creating mapscript.jar" ) get_target_property(LOC_MAPSCRIPT_LIB ${SWIG_MODULE_javamapscript_REAL_NAME} LOCATION) install(FILES ${LOC_MAPSCRIPT_LIB} DESTINATION ${CMAKE_INSTALL_LIBDIR}) mapserver-6.4.1/mapscript/java/javaextend.i0000644002461700001440000000247412261257215020551 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Java-specific extensions to MapScript objects * Author: Sean Gillies, sgillies@frii.com * Jerry Pisk, jerry.pisk@gmail.com * *****************************************************************************/ /* =============================================================================== imageObj =============================================================================== */ /* getBytes moved to mapscript/swiginc/image.i */ /* ============================================================================== pointObj ============================================================================== */ %extend pointObj { pointObj(double x, double y, double z, double m) { pointObj *p; p = (pointObj *)calloc(1,sizeof(pointObj)); if (!p) return NULL; p->x = x; p->y = y; #ifdef USE_POINT_Z_M p->z = z; p->m = m; #endif return p; } pointObj(double x, double y, double z) { pointObj *p; p = (pointObj *)calloc(1,sizeof(pointObj)); if (!p) return NULL; p->x = x; p->y = y; #ifdef USE_POINT_Z_M p->z = z; p->m = -2e38; #endif return p; } } mapserver-6.4.1/mapscript/java/examples/0000755002461700001440000000000012261257215020055 5ustar tbonfortusersmapserver-6.4.1/mapscript/java/examples/ShapeInfo.java0000644002461700001440000000250112261257215022572 0ustar tbonfortusersimport edu.umn.gis.mapscript.*; /** *

Title: Mapscript shapeinfo example.

*

Description: A Java based mapscript example to dump information from a shapefile.

*

Copyright: Copyright (c) 2004

*

Company: GeoZervice

* @author Yew K Choo (ykchoo@geozervice.com) * @version 1.0 */ public class ShapeInfo { public static String getShapeType(int type) { switch (type) { case 1: return "point"; case 3: return "arc"; case 5: return "polygon"; case 8: return "multipoint"; default: return "unknown"; } } public static void usage() { System.err.println("Usage: ShapeInfo {shapefile.shp} {shapefile.dbf}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 2) usage(); shapefileObj shapefile = new shapefileObj (args[0],-1); System.out.println ("Shapefile name = " + args[0]); System.out.println ("Type = " + getShapeType(shapefile.getType())); System.out.println ("Number of features " + shapefile.getNumshapes()); System.out.println("bounds (" + shapefile.getBounds().getMinx() + "," + shapefile.getBounds().getMiny() + ")" + "(" + shapefile.getBounds().getMaxx() + "," + shapefile.getBounds().getMaxy() + ")"); shapefile.delete(); //mapscript.msCleanup(); } } mapserver-6.4.1/mapscript/java/examples/MakePoint.java0000644002461700001440000000046612261257215022615 0ustar tbonfortusers/* Created by unicoletti@prometeo.it to test backwards-compatible pointObj constructor. See bug #1106. 2/1/2005: Created */ import edu.umn.gis.mapscript.*; public class MakePoint { public static void main(String[] args) { pointObj result = new pointObj(0,0,0); System.out.println("Point made!"); } } mapserver-6.4.1/mapscript/java/examples/WxSTestNoThread.java0000644002461700001440000000471112261257215023731 0ustar tbonfortusersimport edu.umn.gis.mapscript.mapObj; import edu.umn.gis.mapscript.OWSRequest; import edu.umn.gis.mapscript.mapscript; import java.io.*; class WxSTest_nothread { public String mapName; public byte[] resultBytes; public void run() { mapObj map = new mapObj(mapName); map.setMetaData( "ows_onlineresource", "http://dummy.org/" ); OWSRequest req = new OWSRequest(); req.setParameter( "SERVICE", "WMS" ); req.setParameter( "VERSION", "1.1.0" ); req.setParameter( "REQUEST", "GetCapabilities" ); mapscript.msIO_installStdoutToBuffer(); int owsResult = map.OWSDispatch( req ); if( owsResult != 0 ) System.out.println( "OWSDispatch Result (expect 0): " + owsResult ); // System.out.println( "Document:" ); // System.out.println( mapscript.msIO_getStdoutBufferString() ); resultBytes = mapscript.msIO_getStdoutBufferBytes(); mapscript.msIO_resetHandlers(); } } public class WxSTestNoThread { public static void main(String[] args) { try { WxSTest_nothread tt[] = new WxSTest_nothread[1]; int i; int expectedLength=0, success = 0, failure=0; for( i = 0; i < tt.length; i++ ) { tt[i] = new WxSTest_nothread(); tt[i].mapName = args[0]; } for( i = 0; i < tt.length; i++ ) tt[i].run(); for( i = 0; i < tt.length; i++ ) { if( i == 0 ) { expectedLength = tt[i].resultBytes.length; System.out.println( "["+i+"] Document Length: " + expectedLength + ", expecting somewhere around 10000 or more." ); } else if( expectedLength != tt[i].resultBytes.length ) { System.out.println( "["+i+"] Document Length:" + tt[i].resultBytes.length + " Expected:" + expectedLength ); failure++; } else success++; // dump test results to fs for post-mortem inspection FileOutputStream fos = new FileOutputStream("/tmp/wxs_test_"+i); fos.write(tt[i].resultBytes); fos.close(); } System.out.println( "Successes: " + success ); System.out.println( "Failures: " + failure ); } catch( Exception e ) { e.printStackTrace(); } } } mapserver-6.4.1/mapscript/java/examples/WxSTest.java0000644002461700001440000000475212261257215022311 0ustar tbonfortusersimport edu.umn.gis.mapscript.mapObj; import edu.umn.gis.mapscript.OWSRequest; import edu.umn.gis.mapscript.mapscript; import java.io.*; class WxSTest_thread extends Thread { public String mapName; public byte[] resultBytes; public void run() { mapObj map = new mapObj(mapName); map.setMetaData( "ows_onlineresource", "http://dummy.org/" ); OWSRequest req = new OWSRequest(); req.setParameter( "SERVICE", "WMS" ); req.setParameter( "VERSION", "1.1.0" ); req.setParameter( "REQUEST", "GetCapabilities" ); mapscript.msIO_installStdoutToBuffer(); int owsResult = map.OWSDispatch( req ); if( owsResult != 0 ) System.out.println( "OWSDispatch Result (expect 0): " + owsResult ); // System.out.println( "Document:" ); // System.out.println( mapscript.msIO_getStdoutBufferString() ); resultBytes = mapscript.msIO_getStdoutBufferBytes(); mapscript.msIO_resetHandlers(); } } public class WxSTest { public static void main(String[] args) { try { WxSTest_thread tt[] = new WxSTest_thread[100]; int i; int expectedLength=0, success = 0, failure=0; for( i = 0; i < tt.length; i++ ) { tt[i] = new WxSTest_thread(); tt[i].mapName = args[0]; } for( i = 0; i < tt.length; i++ ) tt[i].start(); for( i = 0; i < tt.length; i++ ) { tt[i].join(); if( i == 0 ) { expectedLength = tt[i].resultBytes.length; System.out.println( "["+i+"] Document Length: " + expectedLength + ", expecting somewhere around 10000 or more." ); } else if( expectedLength != tt[i].resultBytes.length ) { System.out.println( "["+i+"] Document Length:" + tt[i].resultBytes.length + " Expected:" + expectedLength ); failure++; } else success++; // dump test results to fs for post-mortem inspection FileOutputStream fos = new FileOutputStream("/tmp/wxs_test_"+i); fos.write(tt[i].resultBytes); fos.close(); } System.out.println( "Successes: " + success ); System.out.println( "Failures: " + failure ); } catch( Exception e ) { e.printStackTrace(); } } } mapserver-6.4.1/mapscript/java/examples/QueryByAttribute.java0000644002461700001440000000163612261257215024212 0ustar tbonfortusersimport edu.umn.gis.mapscript.imageObj; import edu.umn.gis.mapscript.mapObj; import edu.umn.gis.mapscript.layerObj; import edu.umn.gis.mapscript.shapeObj; import edu.umn.gis.mapscript.mapscriptConstants; public class QueryByAttribute { public static void main(String[] args) { String filter="A Point"; mapObj map = new mapObj(args[0]); if (args.length == 2) { filter=args[1]; } else { filter="A Point"; } layerObj layer = map.getLayerByName("POINT"); layer.setTemplate("template.html"); layer.queryByAttributes(map,"FNAME", filter, mapscriptConstants.MS_MULTIPLE); layer.open(); System.out.println( "Searched for: " +filter ); int results=layer.getNumResults(); System.out.println( "Results number (should be always 1): " +results ); for(int i=0;iTitle: Mapscript shape dump example.

*

Description: A Java based mapscript example to create an image given a mapfile.

* @author Yew K Choo ykchoo@geozervice.com * @version 1.0 */ public class Metadata { public static void usage() { System.err.println("Usage: Metadata {mapfile}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 1) usage(); mapObj map = new mapObj(args[0]); for (int i=0; i<100; i++) { System.out.println("Web->key1 ? "+map.getWeb().getMetadata().get("key1",null)); System.out.println("Web->key2 ? "+map.getWeb().getMetadata().get("key2",null)); System.out.println("Web->key3 ? "+map.getWeb().getMetadata().get("key3",null)); System.out.println("Web->key4 ? "+map.getWeb().getMetadata().get("key4",null)); System.out.println("Web->key5 ? "+map.getWeb().getMetadata().get("key5",null)); System.gc(); System.gc(); System.gc(); System.out.println("Web->key1 ? "+map.getWeb().getMetadata().get("key1",null)); } map.delete(); } } mapserver-6.4.1/mapscript/java/examples/DrawMap.java0000644002461700001440000000224512261257215022256 0ustar tbonfortusersimport edu.umn.gis.mapscript.*; /** *

Title: Mapscript shape dump example.

*

Description: A Java based mapscript example to create an image given a mapfile.

* @author Yew K Choo ykchoo@geozervice.com * @version 1.0 */ public class DrawMap { public static void usage() { System.err.println("Usage: DrawMap {mapfile} {outfile}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 2) usage(); mapObj map = new mapObj(args[0]); //map.getImagecolor().setRGB(153, 153, 204); //styleObj st = map.getLayer(1).getClass(0).getStyle(0); //st.getColor().setHex("#000000"); if( map.getLayer(1).getMetaData("hidden") != null ) { System.out.println("Layer 1 is hidden? "+map.getLayer(1).getMetaData("hidden")); } int i=0; //for (i=0; i<100; i++) { imageObj img = map.draw(); System.out.println("Image size is: "+img.getSize()); System.out.println("Image size from getBytes is: "+img.getBytes().length); System.out.println(i+") the map will be drawn to:"+args[1]); img.save(args[1], map); //} img.delete(); map.delete(); //mapscript.msCleanup(); } } mapserver-6.4.1/mapscript/java/examples/RunTimeBuiltWMSClient.java0000644002461700001440000000452712261257215025041 0ustar tbonfortusersimport edu.umn.gis.mapscript.*; /** This example demoes a wms client almost entirely configured at run time and without the use of a map file. TODO: remove the need for even a basic map file and do everything at run time @author: Nicole Herman, Umberto Nicoletti */ public class RunTimeBuiltWMSClient { public static void main(String[] args) { System.out.println(mapscript.msGetVersion()); mapObj map; webObj web; imageObj bild; map = new mapObj("data/emptymap.map"); /* map.setWidth(400); map.setHeight(400); map.setDebug(1); // map.setExtent(3280364,5237512,3921499,6103271); map.setExtent(3400000,5700000,3700000,6000000); // map.setExtent(3300000,5600000,3800000,6100000); */ map.setProjection("init=epsg:31467"); map.setImageType("png"); outputFormatObj output = new outputFormatObj("gd/png", ""); output.setName("png"); output.setDriver("gd/png"); output.setMimetype("image/png"); output.setExtension("png"); output.setImagemode(MS_IMAGEMODE.MS_IMAGEMODE_RGB.swigValue()); /* This fixes bug #1870 and #1803 */ // Instanz des WebObjekts // web = new webObj(); web=map.getWeb(); web.setImagepath("/tmp/"); web.setImageurl("http://katrin/~nicol/mapserver/tmp/"); web.setLog("/tmp/wms.log"); web.setHeader("nh_header.html"); web.setTemplate("../html/form.html"); web.setEmpty("../themen/noFeature.html"); // no longer necessary //web.setMap(map); //map.setWeb(web); System.out.println("ImagePath="+web.getImagepath()); // Layer Objekt wird erzeugt layerObj layer; layer = new layerObj(map); layer.setName("DUEKN5000"); layer.setDebug(mapscriptConstants.MS_ON); layer.setType(MS_LAYER_TYPE.MS_LAYER_RASTER); layer.setConnectiontype(MS_CONNECTION_TYPE.MS_WMS); // TODO: replace with a permanent url layer.setConnection("http://www.mapserver.niedersachsen.de/freezoneogc/mapserverogc?"); layer.setMetaData("wms_srs", "EPSG:31467"); layer.setMetaData("wms_name", "DUEKN5000"); layer.setMetaData("wms_server_version", "1.1.1"); layer.setMetaData("wms_format","image/png"); layer.setProjection("init=epsg:31467"); layer.setStatus(mapscriptConstants.MS_ON); bild = map.draw(); bild.save("test.png", map); bild.delete(); } } mapserver-6.4.1/mapscript/java/examples/RFC24.java0000644002461700001440000000773612261257215021515 0ustar tbonfortusersimport edu.umn.gis.mapscript.*; /** *

Title: Mapscript RFC24 tests.

*

Description: Tests for RFC24 implementation. (http://mapserver.gis.umn.edu/development/rfc/ms-rfc-24/)

* @author Umberto Nicoletti (umberto.nicoletti@gmail.com) */ public class RFC24 { String mapfile; public static void main(String[] args) { new RFC24(args[0]).run(); } public RFC24(String mapfile) { this.mapfile=mapfile; } public void run() { System.out.println("Running "+getClass().getName()); testLayerObj(); testClassObj(); testInsertLayerObj(); testInsertClassObj(); testGetLayerObj(); testGetLayerObjByName(); testGetClassObj(); testGetOutputformatObj(); testInsertOutputformatObj(); System.out.println("Finished "+getClass().getName()); } public void testLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(map); map=null; gc(); assertNotNull(newLayer.getMap(), "testLayerObj"); } public void testInsertLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,-1); map=null; gc(); assertNotNull(newLayer.getMap(), "testInsertLayerObj"); } public void testGetLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayer(1); map=null; gc(); assertNotNull(newLayer.getMap(), "testGetLayerObj"); } public void testGetLayerObjByName() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayerByName("POLYGON"); map=null; gc(); assertNotNull(newLayer.getMap(), "testGetLayerObjByName"); } public void testClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(layer); map=null; layer=null; gc(); assertNotNull(newClass.getLayer(), "testClassObj"); } public void testInsertClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,-1); map=null; layer=null; gc(); assertNotNull(newClass.getLayer(), "testInsertClassObj"); } public void testGetClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=layer.getClass(0); map=null; layer=null; gc(); assertNotNull(newClass.getLayer(), "testGetClassObj"); } public void testGetOutputformatObj() { mapObj map=new mapObj(mapfile); outputFormatObj format=null; for (int i=0; iTitle: Mapscript shape dump example.

*

Description: A Java based mapscript to dump information from a shapefile.

* @author Yew K Choo (ykchoo@geozervice.com) * @version 1.0 */ public class DumpShp { public static String getShapeType(int type) { switch (type) { case 1: return "point"; case 3: return "arc"; case 5: return "polygon"; case 8: return "multipoint"; default: return "unknown"; } } public static void usage() { System.err.println("Usage: DumpShp {shapefile.shp}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 1) usage(); shapefileObj shapefile = new shapefileObj (args[0],-1); System.out.println ("Shapefile opened (type = " + getShapeType(shapefile.getType()) + " with " + shapefile.getNumshapes() + " shapes)."); shapeObj shape = new shapeObj(-1); for(int i=0; i Reply-To: Jerry Pisk To: MAPSERVER-DEV@LISTS.UMN.EDU Hi everybody, as I mentioned in my previous e-mail I was able to get mapserver to work in a multithreaded program. But the code I covered was just a fraction of mapserver's code, I only tested mapfile load and map drawing from a PostGIS backend. Since I do not have the resources to do extensive testing I decided to share what I've done with the community. I wrote a simple Java program that creates a number of threads and executes map operations on them. It uses Java mapscript to call mapserver. The following assumes a JDK (I used 1.5 but older versions should work as well) is installed and JAVA_HOME points to it. There are two source files: ================ MapTest.java ================ public class MapTest { public static void main(String args[]) { String mapfile = null; Integer threads = null; Integer iterations = null; for( int i = 0; i < args.length; i++ ) { if( "-t".equals(args[i]) ) { i++; threads = new Integer(args[i]); continue; } if( "-i".equals(args[i]) ) { i++; iterations = new Integer(args[i]); continue; } mapfile = args[i]; } Thread[] tpool = new Thread[threads.intValue()]; for( int i = 0; i < tpool.length; i++ ) { tpool[i] = new MapThread(mapfile, iterations.intValue()); } for( int i = 0; i < tpool.length; i++ ) { tpool[i].start(); } } } ================================================ ================ MapThread.java ================ import edu.umn.gis.mapscript.mapObj; public class MapThread extends Thread { MapThread(String mapfile, int iterations) { this.mapfile = mapfile; this.iterations = iterations; } public void run() { mapObj map = new mapObj(mapfile); for( int i = 0; i < iterations; i++ ) { map.draw(); // Add additional test code here } } String mapfile; int iterations; } ================================================ To use these simply compile mapserver and mapscript (for java you may need to run 'make interface' in mapscript/java). Save the two Java files into a directory of your choice. Compile them (point to your mapscript.jar, in mapscript/java/): $JAVA_HOME/bin/javac -cp ./mapscript.jar *.java and execute: $JAVA_HOME/bin/java -Djava.library.path=./ -cp ./:./mapscript.jar MapTest -t -i where is the number of threads to create, is the number of iterations to execute on each thread and is a full path to your map file. Again, make sure you point to your mapscript.jar and point to where libmapscript.so is in that java.library.path definition (I copied those two files into the same directory as the Java code but your setup may differ). There were occasional libgd related errors (Unable to initialize image) but those simply resulted in an exception being thrown, which is in my humble opinion acceptable, as long as the code does not crash. The code does no error checking, feel free to add it but this is really meant to be a developer's troubleshooting tool, not an end user utility. Also if a map drawing fails that thread will simply exit without finishing its number of iterations. The point of all this is to help make mapserver thread safe. The code above is meant as a simple starting point that should help mapserver developers test the code in a multithreaded application. Any comments and thoughts or even module tests (I do not have the resources to test a lot of mapserver's code, especially all the various data back ends) will be appreciated. Jerry Pisk ---------- $Id$ mapserver-6.4.1/mapscript/java/tests/threadtest/MapTest.java0000644002461700001440000000164112261257215023772 0ustar tbonfortusers// $Id$ // // See README_THREADTEST.TXT for usage details. // public class MapTest { public static void main(String args[]) { String mapfile = null; Integer threads = null; Integer iterations = null; for( int i = 0; i < args.length; i++ ) { if( "-t".equals(args[i]) ) { i++; threads = new Integer(args[i]); continue; } if( "-i".equals(args[i]) ) { i++; iterations = new Integer(args[i]); continue; } mapfile = args[i]; } Thread[] tpool = new Thread[threads.intValue()]; for( int i = 0; i < tpool.length; i++ ) { tpool[i] = new MapThread(mapfile, iterations.intValue(), i); } for( int i = 0; i < tpool.length; i++ ) { tpool[i].start(); } } } mapserver-6.4.1/mapscript/java/tests/threadtest/MapThread.java0000644002461700001440000000537012261257215024265 0ustar tbonfortusers// $Id$ // // See README_THREADTEST.TXT for usage details. // import edu.umn.gis.mapscript.*; public class MapThread extends Thread { MapThread(String mapfile, int iterations, int id) { this.mapfile = mapfile; this.iterations = iterations; this.id=id; } public void run() { System.out.println("Thread "+id+" running..."); /* Uncomment this if you need to reschedule threads if (id>=5) { try { sleep(10000); } catch(InterruptedException ie) { ie.printStackTrace(); } } */ for( int i = 0; i < iterations; i++ ) { mapObj map = new mapObj(mapfile); long path=Math.round(Math.random()*10); if ( path > 5 ) { System.out.println("Thread "+id+"-"+i+" querying..."); query(map); } else { System.out.println("Thread "+id+"-"+i+" using geos to create a buffer..."); try { createBuffer(map); } catch(Exception e) { System.out.println("have you enabled GEOS support? "+e.getMessage()); } } // We use this to test swig's memory management code //System.gc(); //map.draw().save("/tmp/mapthread"+id+"-"+i+".png", map); map.draw(); } mapscript.msConnPoolCloseUnreferenced(); System.out.println("Thread "+id+" done."); } public void createBuffer(mapObj map) { layerObj layer = map.getLayer(3); if (layer!=null) { layer.open(); layer.queryByIndex(map,0,-1,mapscriptConstants.MS_FALSE); shapeObj shape=layer.getShape(layer.getResults().getResult(0)); if (shape!=null) { shapeObj buffer=shape.buffer(0.1); if (buffer != null) { layerObj bufferLayer=new layerObj(map); bufferLayer.setStatus(mapscriptConstants.MS_DEFAULT); bufferLayer.setDebug(mapscriptConstants.MS_ON); bufferLayer.setName("BUFFER"); //bufferLayer.setType(mapscriptConstants.MS_LAYER_POLYGON); bufferLayer.setProjection("init=epsg:4326"); bufferLayer.setType(MS_LAYER_TYPE.MS_LAYER_POINT); bufferLayer.setOpacity(50); classObj clazz=new classObj(bufferLayer); clazz.setName("Buffer class"); styleObj style=new styleObj(clazz); colorObj green=new colorObj(0,254,0,-4); //green.setRGB(0,254,0); style.setColor(green); bufferLayer.addFeature(buffer); } else { System.out.println("Buffer shape is NULL!"); } } } } public void query(mapObj map) { layerObj layer = map.getLayer(3); if (layer!=null) { layer.setTemplate("template.html"); String filter="A Point"; layer.queryByAttributes(map,"FNAME", filter, mapscriptConstants.MS_MULTIPLE); layer.open(); System.out.println( " numresults: " +layer.getNumResults() ); layer.close(); } } String mapfile; int iterations; int id; } mapserver-6.4.1/maphttp.c0000644002461700001440000010064312261257215015141 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Utility functions to access files via HTTP (requires libcurl) * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2001-2003, Daniel Morissette, DM Solutions Group Inc * * 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 ****************************************************************************/ /* For now this code is enabled only when WMS/WFS client is enabled. * This should be changed to a test on the presence of libcurl which * is really what the real dependency is. */ #include "mapserver-config.h" #if defined(USE_CURL) #include "mapserver.h" #include "maphttp.h" #include "maperror.h" #include "mapthread.h" #include "mapows.h" #include #ifndef _WIN32 #include #include #endif /* * Note: This code uses libcurl to access remote files via the HTTP protocol. * Requires libcurl v 7.10 or more recent. * See http://curl.haxx.se/libcurl/c/ for the lib source code and docs. */ #include /********************************************************************** * msHTTPInit() * * This function is called to init libcurl before the first HTTP request * in this process is executed. * On further calls (when gbCurlInitialized = MS_TRUE) it simply doest nothing. * * Returns MS_SUCCESS/MS_FAILURE. * * msHTTPCleanup() will have to be called in msCleanup() when this process * exits. **********************************************************************/ static int gbCurlInitialized = MS_FALSE; int msHTTPInit() { /* curl_global_init() should only be called once (no matter how * many threads or libcurl sessions that'll be used) by every * application that uses libcurl. */ msAcquireLock(TLOCK_OWS); if (!gbCurlInitialized && curl_global_init(CURL_GLOBAL_ALL) != 0) { msReleaseLock(TLOCK_OWS); msSetError(MS_HTTPERR, "Libcurl initialization failed.", "msHTTPInit()"); return MS_FAILURE; } gbCurlInitialized = MS_TRUE; msReleaseLock(TLOCK_OWS); return MS_SUCCESS; } /********************************************************************** * msHTTPCleanup() * **********************************************************************/ void msHTTPCleanup() { msAcquireLock(TLOCK_OWS); if (gbCurlInitialized) curl_global_cleanup(); gbCurlInitialized = MS_FALSE; msReleaseLock(TLOCK_OWS); } /********************************************************************** * msHTTPInitRequestObj() * * Should be called on a new array of httpRequestObj to initialize them * for use with msHTTPExecuteRequest(), etc. * * Note that users of this module should always allocate and init one * more instance of httpRequestObj in their array than what they plan to * use because the terminate_handler() needs the last entry in the array * to have reqObj->request == NULL * **********************************************************************/ void msHTTPInitRequestObj(httpRequestObj *pasReqInfo, int numRequests) { int i; for(i=0; idebug) { msDebug("msHTTPWriteFct(id=%d, %d bytes)\n", psReq->nLayerId, (int)(size*nmemb)); } if(psReq->nMaxBytes > 0 && (psReq->result_size + size*nmemb) > psReq->nMaxBytes) { msSetError(MS_HTTPERR, "Requested transfer larger than configured maximum %d.", "msHTTPWriteFct()", psReq->nMaxBytes ); return -1; } /* Case where we are writing to a disk file. */ if( psReq->fp != NULL ) { psReq->result_size += size*nmemb; return fwrite(buffer, size, nmemb, psReq->fp); } /* Case where we build up the result in memory */ else { if( psReq->result_data == NULL ) { psReq->result_buf_size = size*nmemb + 10000; psReq->result_data = (char *) msSmallMalloc( psReq->result_buf_size ); } else if( psReq->result_size + nmemb * size > psReq->result_buf_size ) { psReq->result_buf_size = psReq->result_size + nmemb*size + 10000; psReq->result_data = (char *) msSmallRealloc( psReq->result_data, psReq->result_buf_size ); } if( psReq->result_data == NULL ) { msSetError(MS_HTTPERR, "Unable to grow HTTP result buffer to size %d.", "msHTTPWriteFct()", psReq->result_buf_size ); psReq->result_buf_size = 0; psReq->result_size = 0; return -1; } memcpy( psReq->result_data + psReq->result_size, buffer, size*nmemb ); psReq->result_size += size*nmemb; return size*nmemb; } } /********************************************************************** * msGetCURLAuthType() * * Returns the equivalent CURL CURLAUTH_ constant given a * MS_HTTP_AUTH_TYPE, or CURLAUTH_BASIC if no match is found. **********************************************************************/ long msGetCURLAuthType(enum MS_HTTP_AUTH_TYPE authType) { switch (authType) { case MS_BASIC: return CURLAUTH_BASIC; case MS_DIGEST: return CURLAUTH_DIGEST; case MS_NTLM: return CURLAUTH_NTLM; case MS_ANY: return CURLAUTH_ANY; case MS_ANYSAFE: return CURLAUTH_ANYSAFE; default: return CURLAUTH_BASIC; } } /********************************************************************** * msHTTPAuthProxySetup() * * Common code used by msPrepareWFSLayerRequest() and * msPrepareWMSLayerRequest() to handle proxy / http auth for requests * * Return value: * MS_SUCCESS if all requests completed succesfully. * MS_FAILURE if a fatal error happened **********************************************************************/ int msHTTPAuthProxySetup(hashTableObj *mapmd, hashTableObj *lyrmd, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, const char* namespaces) { const char *pszTmp; char *pszProxyHost=NULL; long nProxyPort=0; char *pszProxyUsername=NULL, *pszProxyPassword=NULL; char *pszHttpAuthUsername=NULL, *pszHttpAuthPassword=NULL; enum MS_HTTP_AUTH_TYPE eHttpAuthType = MS_BASIC; enum MS_HTTP_AUTH_TYPE eProxyAuthType = MS_BASIC; enum MS_HTTP_PROXY_TYPE eProxyType = MS_HTTP; /* ------------------------------------------------------------------ * Check for authentication and proxying metadata. If the metadata is not found * in the layer metadata, check the map-level metadata. * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_host")) != NULL) { pszProxyHost = msStrdup(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_port")) != NULL) { nProxyPort = atol(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_type")) != NULL) { if (strcasecmp(pszTmp, "HTTP") == 0) eProxyType = MS_HTTP; else if (strcasecmp(pszTmp, "SOCKS5") == 0) eProxyType = MS_SOCKS5; else { msSetError(MS_WMSERR, "Invalid proxy_type metadata '%s' specified", "msHTTPAuthProxySetup()", pszTmp); return MS_FAILURE; } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_auth_type")) != NULL) { if (strcasecmp(pszTmp, "BASIC") == 0) eProxyAuthType = MS_BASIC; else if (strcasecmp(pszTmp, "DIGEST") == 0) eProxyAuthType = MS_DIGEST; else if (strcasecmp(pszTmp, "NTLM") == 0) eProxyAuthType = MS_NTLM; else if (strcasecmp(pszTmp, "ANY") == 0) eProxyAuthType = MS_ANY; else if (strcasecmp(pszTmp, "ANYSAFE") == 0) eProxyAuthType = MS_ANYSAFE; else { msSetError(MS_WMSERR, "Invalid proxy_auth_type metadata '%s' specified", "msHTTPAuthProxySetup()", pszTmp); return MS_FAILURE; } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_username")) != NULL) { pszProxyUsername = msStrdup(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_password")) != NULL) { pszProxyPassword = msDecryptStringTokens(map, pszTmp); if (pszProxyPassword == NULL) { return(MS_FAILURE); /* An error should already have been produced */ } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "auth_type")) != NULL) { if (strcasecmp(pszTmp, "BASIC") == 0) eHttpAuthType = MS_BASIC; else if (strcasecmp(pszTmp, "DIGEST") == 0) eHttpAuthType = MS_DIGEST; else if (strcasecmp(pszTmp, "NTLM") == 0) eHttpAuthType = MS_NTLM; else if (strcasecmp(pszTmp, "ANY") == 0) eHttpAuthType = MS_ANY; else if (strcasecmp(pszTmp, "ANYSAFE") == 0) eHttpAuthType = MS_ANYSAFE; else { msSetError(MS_WMSERR, "Invalid auth_type metadata '%s' specified", "msHTTPAuthProxySetup()", pszTmp); return MS_FAILURE; } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "auth_username")) != NULL) { pszHttpAuthUsername = msStrdup(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "auth_password")) != NULL) { pszHttpAuthPassword = msDecryptStringTokens(map, pszTmp); if (pszHttpAuthPassword == NULL) { return(MS_FAILURE); /* An error should already have been produced */ } } pasReqInfo[numRequests].pszProxyAddress = pszProxyHost; pasReqInfo[numRequests].nProxyPort = nProxyPort; pasReqInfo[numRequests].eProxyType = eProxyType; pasReqInfo[numRequests].eProxyAuthType = eProxyAuthType; pasReqInfo[numRequests].pszProxyUsername = pszProxyUsername; pasReqInfo[numRequests].pszProxyPassword = pszProxyPassword; pasReqInfo[numRequests].eHttpAuthType = eHttpAuthType; pasReqInfo[numRequests].pszHttpUsername = pszHttpAuthUsername; pasReqInfo[numRequests].pszHttpPassword = pszHttpAuthPassword; return MS_SUCCESS; } /********************************************************************** * msHTTPExecuteRequests() * * Fetch a map slide via HTTP request and save to specified temp file. * * If bCheckLocalCache==MS_TRUE then if the pszOutputfile already exists * then is is not downloaded again, and status 242 is returned. * * Return value: * MS_SUCCESS if all requests completed succesfully. * MS_FAILURE if a fatal error happened * MS_DONE if some requests failed with 40x status for instance (not fatal) **********************************************************************/ int msHTTPExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, int bCheckLocalCache) { int i, nStatus = MS_SUCCESS, nTimeout, still_running=0, num_msgs=0; CURLM *multi_handle; CURLMsg *curl_msg; char debug = MS_FALSE; const char *pszCurlCABundle = NULL; if (numRequests == 0) return MS_SUCCESS; /* Nothing to do */ if (!gbCurlInitialized) msHTTPInit(); /* Establish the timeout (seconds) for how long we are going to wait * for a response. * We use the longest timeout value in the array of requests */ nTimeout = pasReqInfo[0].nTimeout; for (i=0; i nTimeout) nTimeout = pasReqInfo[i].nTimeout; if (pasReqInfo[i].debug) debug = MS_TRUE; /* For the download loop */ } if (nTimeout <= 0) nTimeout = 30; /* Check if we've got a CURL_CA_BUNDLE env. var. * If set then the value is the full path to the ca-bundle.crt file * e.g. CURL_CA_BUNDLE=/usr/local/share/curl/curl-ca-bundle.crt */ pszCurlCABundle = getenv("CURL_CA_BUNDLE"); if (debug) { msDebug("HTTP: Starting to prepare HTTP requests.\n"); if (pszCurlCABundle) msDebug("Using CURL_CA_BUNDLE=%s\n", pszCurlCABundle); } /* Alloc a curl-multi handle, and add a curl-easy handle to it for each * file to download. */ multi_handle = curl_multi_init(); if (multi_handle == NULL) { msSetError(MS_HTTPERR, "curl_multi_init() failed.", "msHTTPExecuteRequests()"); return(MS_FAILURE); } for (i=0; iversion_num/0x10000 & 0xff, psCurlVInfo->version_num/0x100 & 0xff, psCurlVInfo->version_num & 0xff ); } } if (pasReqInfo[i].pszUserAgent) { curl_easy_setopt(http_handle, CURLOPT_USERAGENT, pasReqInfo[i].pszUserAgent ); } /* Enable following redirections. Requires libcurl 7.10.1 at least */ curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1 ); curl_easy_setopt(http_handle, CURLOPT_MAXREDIRS, 10 ); /* Set timeout.*/ curl_easy_setopt(http_handle, CURLOPT_TIMEOUT, nTimeout ); /* Pass CURL_CA_BUNDLE if set */ if (pszCurlCABundle) curl_easy_setopt(http_handle, CURLOPT_CAINFO, pszCurlCABundle ); /* Set proxying settings */ if (pasReqInfo[i].pszProxyAddress != NULL && strlen(pasReqInfo[i].pszProxyAddress) > 0) { long nProxyType = CURLPROXY_HTTP; curl_easy_setopt(http_handle, CURLOPT_PROXY, pasReqInfo[i].pszProxyAddress); if (pasReqInfo[i].nProxyPort > 0 && pasReqInfo[i].nProxyPort < 65535) { curl_easy_setopt(http_handle, CURLOPT_PROXYPORT, pasReqInfo[i].nProxyPort); } switch (pasReqInfo[i].eProxyType) { case MS_HTTP: nProxyType = CURLPROXY_HTTP; break; case MS_SOCKS5: nProxyType = CURLPROXY_SOCKS5; break; } curl_easy_setopt(http_handle, CURLOPT_PROXYTYPE, nProxyType); /* If there is proxy authentication information, set it */ if (pasReqInfo[i].pszProxyUsername != NULL && pasReqInfo[i].pszProxyPassword != NULL && strlen(pasReqInfo[i].pszProxyUsername) > 0 && strlen(pasReqInfo[i].pszProxyPassword) > 0) { char szUsernamePasswd[128]; #if LIBCURL_VERSION_NUM >= 0x070a07 long nProxyAuthType = CURLAUTH_BASIC; /* CURLOPT_PROXYAUTH available only in Curl 7.10.7 and up */ nProxyAuthType = msGetCURLAuthType(pasReqInfo[i].eProxyAuthType); curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, nProxyAuthType); #else /* We log an error but don't abort processing */ msSetError(MS_HTTPERR, "CURLOPT_PROXYAUTH not supported. Requires Curl 7.10.7 and up. *_proxy_auth_type setting ignored.", "msHTTPExecuteRequests()"); #endif /* LIBCURL_VERSION_NUM */ snprintf(szUsernamePasswd, 127, "%s:%s", pasReqInfo[i].pszProxyUsername, pasReqInfo[i].pszProxyPassword); curl_easy_setopt(http_handle, CURLOPT_PROXYUSERPWD, szUsernamePasswd); } } /* Set HTTP Authentication settings */ if (pasReqInfo[i].pszHttpUsername != NULL && pasReqInfo[i].pszHttpPassword != NULL && strlen(pasReqInfo[i].pszHttpUsername) > 0 && strlen(pasReqInfo[i].pszHttpPassword) > 0) { char szUsernamePasswd[128]; long nHttpAuthType = CURLAUTH_BASIC; snprintf(szUsernamePasswd, 127, "%s:%s", pasReqInfo[i].pszHttpUsername, pasReqInfo[i].pszHttpPassword); curl_easy_setopt(http_handle, CURLOPT_USERPWD, szUsernamePasswd); nHttpAuthType = msGetCURLAuthType(pasReqInfo[i].eHttpAuthType); curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, nHttpAuthType); } /* NOSIGNAL should be set to true for timeout to work in multithread * environments on Unix, requires libcurl 7.10 or more recent. * (this force avoiding the use of sgnal handlers) */ #ifdef CURLOPT_NOSIGNAL curl_easy_setopt(http_handle, CURLOPT_NOSIGNAL, 1 ); #endif /* If we are writing file to disk, open the file now. */ if( pasReqInfo[i].pszOutputFile != NULL ) { if ( (fp = fopen(pasReqInfo[i].pszOutputFile, "wb")) == NULL) { msSetError(MS_HTTPERR, "Can't open output file %s.", "msHTTPExecuteRequests()", pasReqInfo[i].pszOutputFile); return(MS_FAILURE); } pasReqInfo[i].fp = fp; } curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, &(pasReqInfo[i])); curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, msHTTPWriteFct); /* Provide a buffer where libcurl can write human readable error msgs */ if (pasReqInfo[i].pszErrBuf == NULL) pasReqInfo[i].pszErrBuf = (char *)msSmallMalloc((CURL_ERROR_SIZE+1)* sizeof(char)); pasReqInfo[i].pszErrBuf[0] = '\0'; curl_easy_setopt(http_handle, CURLOPT_ERRORBUFFER, pasReqInfo[i].pszErrBuf); if(pasReqInfo[i].pszPostRequest != NULL ) { char szBuf[100]; struct curl_slist *headers=NULL; snprintf(szBuf, 100, "Content-Type: %s", pasReqInfo[i].pszPostContentType); headers = curl_slist_append(headers, szBuf); curl_easy_setopt(http_handle, CURLOPT_POST, 1 ); curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, pasReqInfo[i].pszPostRequest); curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers); /* curl_slist_free_all(headers); */ /* free the header list */ } /* Added by RFC-42 HTTP Cookie Forwarding */ if(pasReqInfo[i].pszHTTPCookieData != NULL) { /* Check if there's no end of line in the Cookie string */ /* This could break the HTTP Header */ int nPos; for(nPos=0; nPosmsg == CURLMSG_DONE && curl_msg->data.result != CURLE_OK) { /* Something went wrong with this transfer... report error */ for (i=0; ieasy_handle) { psReq = &(pasReqInfo[i]); break; } } if (psReq != NULL) { /* Record error code in nStatus as a negative value */ psReq->nStatus = -curl_msg->data.result; } } } if (debug) { /* Print a msDebug header for timings reported in the loop below */ msDebug("msHTTPExecuteRequests() timing summary per layer (connect_time + time_to_first_packet + download_time = total_time in seconds)\n"); } /* Check status of all requests, close files, report errors and cleanup * handles */ for (i=0; inStatus == 242) continue; /* Nothing to do here, this file was in cache already */ if (psReq->fp) fclose(psReq->fp); psReq->fp = NULL; http_handle = (CURL*)(psReq->curl_handle); if (psReq->nStatus == 0 && curl_easy_getinfo(http_handle, CURLINFO_HTTP_CODE, &lVal) == CURLE_OK) { char *pszContentType = NULL; psReq->nStatus = lVal; /* Fetch content type of response */ if (curl_easy_getinfo(http_handle, CURLINFO_CONTENT_TYPE, &pszContentType) == CURLE_OK && pszContentType != NULL) { psReq->pszContentType = msStrdup(pszContentType); } } if (!MS_HTTP_SUCCESS(psReq->nStatus)) { /* Set status to MS_DONE to indicate that transfers were */ /* completed but may not be succesfull */ nStatus = MS_DONE; if (psReq->nStatus == -(CURLE_OPERATION_TIMEOUTED)) { /* Timeout isn't a fatal error */ if (psReq->debug) msDebug("HTTP: TIMEOUT of %d seconds exceeded for %s\n", nTimeout, psReq->pszGetUrl ); msSetError(MS_HTTPERR, "HTTP: TIMEOUT of %d seconds exceeded for %s\n", "msHTTPExecuteRequests()", nTimeout, psReq->pszGetUrl); /* Rewrite error message, the curl timeout message isn't * of much use to our users. */ sprintf(psReq->pszErrBuf, "TIMEOUT of %d seconds exceeded.", nTimeout); } else if (psReq->nStatus > 0) { /* Got an HTTP Error, e.g. 404, etc. */ if (psReq->debug) msDebug("HTTP: HTTP GET request failed with status %d (%s)" " for %s\n", psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); msSetError(MS_HTTPERR, "HTTP GET request failed with status %d (%s) " "for %s", "msHTTPExecuteRequests()", psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); } else { /* Got a curl error */ errorObj *error = msGetErrorObj(); if (psReq->debug) msDebug("HTTP: request failed with curl error " "code %d (%s) for %s", -psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); if(!error || error->code == MS_NOERR) /* only set error if one hasn't already been set */ msSetError(MS_HTTPERR, "HTTP: request failed with curl error " "code %d (%s) for %s", "msHTTPExecuteRequests()", -psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); } } /* Report download times foreach handle, in debug mode */ if (psReq->debug) { double dConnectTime=0.0, dTotalTime=0.0, dStartTfrTime=0.0; curl_easy_getinfo(http_handle, CURLINFO_CONNECT_TIME, &dConnectTime); curl_easy_getinfo(http_handle, CURLINFO_STARTTRANSFER_TIME, &dStartTfrTime); curl_easy_getinfo(http_handle, CURLINFO_TOTAL_TIME, &dTotalTime); /* STARTTRANSFER_TIME includes CONNECT_TIME, but TOTAL_TIME * doesn't, so we need to add it. */ dTotalTime += dConnectTime; msDebug("Layer %d: %.3f + %.3f + %.3f = %.3fs\n", psReq->nLayerId, dConnectTime, dStartTfrTime-dConnectTime, dTotalTime-dStartTfrTime, dTotalTime); } /* Cleanup this handle */ curl_easy_setopt(http_handle, CURLOPT_URL, "" ); curl_multi_remove_handle(multi_handle, http_handle); curl_easy_cleanup(http_handle); psReq->curl_handle = NULL; } /* Cleanup multi handle, each handle had to be cleaned up individually */ curl_multi_cleanup(multi_handle); return nStatus; } /********************************************************************** * msHTTPGetFile() * * Wrapper to call msHTTPExecuteRequests() for a single file. **********************************************************************/ int msHTTPGetFile(const char *pszGetUrl, const char *pszOutputFile, int *pnHTTPStatus, int nTimeout, int bCheckLocalCache, int bDebug, int nMaxBytes) { httpRequestObj *pasReqInfo; /* Alloc httpRequestInfo structs through which status of each request * will be returned. * We need to alloc 2 instance of requestobj so that the last * object in the array can be set to NULL. */ pasReqInfo = (httpRequestObj*)calloc(2, sizeof(httpRequestObj)); MS_CHECK_ALLOC(pasReqInfo, 2*sizeof(httpRequestObj), MS_FAILURE); msHTTPInitRequestObj(pasReqInfo, 2); pasReqInfo[0].pszGetUrl = msStrdup(pszGetUrl); pasReqInfo[0].pszOutputFile = msStrdup(pszOutputFile); pasReqInfo[0].debug = (char)bDebug; pasReqInfo[0].nTimeout = nTimeout; pasReqInfo[0].nMaxBytes = nMaxBytes; if (msHTTPExecuteRequests(pasReqInfo, 1, bCheckLocalCache) != MS_SUCCESS) { *pnHTTPStatus = pasReqInfo[0].nStatus; if (pasReqInfo[0].debug) msDebug("HTTP request failed for %s.\n", pszGetUrl); msHTTPFreeRequestObj(pasReqInfo, 2); free(pasReqInfo); return MS_FAILURE; } *pnHTTPStatus = pasReqInfo[0].nStatus; msHTTPFreeRequestObj(pasReqInfo, 2); free(pasReqInfo); return MS_SUCCESS; } #endif /* defined(USE_WMS_LYR) || defined(USE_WMS_SVR) */ mapserver-6.4.1/mapoglrenderer.h0000644002461700001440000001226412261257215016500 0ustar tbonfortusers/****************************************************************************** * $id: mapoglrenderer.h 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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 OGL_H #define OGL_H #ifdef USE_OGL #include "mapoglcontext.h" #include "mapserver.h" #include #include #include #include #include class OglCache { public: ~OglCache() { glDeleteTextures(1, &texture); } GLuint texture; ms_uint32 width; ms_uint32 height; ms_uint32 patternDistance; }; typedef OglCache* OglCachePtr; class OglRenderer { public: OglRenderer(ms_uint32 width, ms_uint32 height, colorObj* color = NULL); virtual ~OglRenderer(); void renderPolyline(shapeObj *p, colorObj *c, double width, int patternlength, double* pattern, int lineCap = MS_CJC_ROUND, int joinStyle = MS_CJC_ROUND, colorObj *outlinecolor = NULL, double outlinewidth = 0); void renderPolygon(shapeObj*, colorObj *color, colorObj *outlinecolor, double outlinewidth, const OglCachePtr& tile = OglCachePtr(), int lineCap=MS_CJC_ROUND, int joinStyle=MS_CJC_ROUND); void renderGlyphs(double x, double y, colorObj *color, colorObj *outlinecolor, double size, const char* font, char *thechars, double angle, colorObj *shadowcolor, double shdx, double shdy); void renderPixmap(symbolObj *symbol, double x, double y, double angle, double scale); void renderEllipse(double x, double y, double angle, double w, double h, colorObj *color, colorObj *outlinecolor, double outlinewidth); void renderVectorSymbol(double x, double y, symbolObj *symbol, double scale, double angle, colorObj *c, colorObj *oc, double ow); void renderTile(const OglCachePtr& tile, double x, double y, double angle); void renderPolylineTile(shapeObj *p, const OglCachePtr& tile); static bool getStringBBox(char *font, double size, char *string, rectObj *rect, double** advances); void setTransparency(double transparency); void readRasterBuffer(rasterBufferObj * rb); void drawRasterBuffer(rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height); static void initializeRasterBuffer(rasterBufferObj * rb, int width, int height, bool useAlpha); OglCachePtr getTexture(); int getWidth() const { return width; } int getHeight() const { return height; } bool isValid() const { return valid && context->isValid(); } protected: OglCachePtr texture; ms_uint32 width; ms_uint32 height; double transparency; bool valid; GLint viewportX; GLint viewportY; GLsizei viewportWidth; GLsizei viewportHeight; typedef std::map > fontCache_t; typedef std::map > dashCache_t; static FTFont* getFTFont(const char* font, double size); bool loadLine(shapeObj* shape, double width, int patternlength, double *pattern); double drawQuad(pointObj *p1, pointObj *p2, double width, double tilelength = 0.0, double textureStart = 0.0); double drawTriangles(pointObj *p1, pointObj *p2, double width, double tilelength = 0.0, double textureStart = 0.0); void drawVectorLineStrip(symbolObj *symbol, double width); void drawFan(pointObj* center, pointObj* from, pointObj* to, int resolution); void createShapes(); GLuint createTexture(ms_uint32 x, ms_uint32 y); void makeCurrent(); void setColor(colorObj *color); GLUtesselator *tess; enum shapes_t { circle = 0}; OglContext* context; static dashCache_t dashCache; static fontCache_t fontCache; static std::vector shapes; static std::vector testSymbols; static ms_uint32 OUTLINE_WIDTH; static ms_uint32 FONT_SIZE; static ms_uint32 FONT_RES; static double OGL_PI; static ms_uint32 SHAPE_CIRCLE_RES; static double SHAPE_CIRCLE_RADIUS; static double SIZE_RES; }; #endif /* USE_OGL */ #endif mapserver-6.4.1/mappostgis.c0000644002461700001440000027677112261257215015672 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: PostGIS CONNECTIONTYPE support. * Author: Paul Ramsey * Dave Blasby * ****************************************************************************** * Copyright (c) 2010 Paul Ramsey * Copyright (c) 2002 Refractions Research * * 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. ****************************************************************************/ /* ** Some theory of operation: ** ** Build SQL from DATA statement and LAYER state. SQL is always of the form: ** ** SELECT [this, that, other], geometry, uid ** FROM [table|(subquery) as sub] ** WHERE [box] AND [filter] ** ** So the geometry always resides at layer->numitems and the uid always ** resides at layer->numitems + 1 ** ** Geometry is requested as Hex encoded WKB. The endian is always requested ** as the client endianness. ** ** msPostGISLayerWhichShapes creates SQL based on DATA and LAYER state, ** executes it, and places the un-read PGresult handle in the layerinfo->pgresult, ** setting the layerinfo->rownum to 0. ** ** msPostGISNextShape reads a row, increments layerinfo->rownum, and returns ** MS_SUCCESS, until rownum reaches ntuples, and it returns MS_DONE instead. ** */ /* GNU needs this for strcasestr */ #define _GNU_SOURCE /* required for MSVC */ #define _USE_MATH_DEFINES #include #include #include #include "mapserver.h" #include "maptime.h" #include "mappostgis.h" #define FP_EPSILON 1e-12 #define FP_EQ(a, b) (fabs((a)-(b)) < FP_EPSILON) #define FP_LEFT -1 #define FP_RIGHT 1 #define FP_COLINEAR 0 #define SEGMENT_ANGLE 10.0 #define SEGMENT_MINPOINTS 10 #ifdef USE_POSTGIS /* ** msPostGISCloseConnection() ** ** Handler registered witih msConnPoolRegister so that Mapserver ** can clean up open connections during a shutdown. */ void msPostGISCloseConnection(void *pgconn) { PQfinish((PGconn*)pgconn); } /* ** msPostGISCreateLayerInfo() */ msPostGISLayerInfo *msPostGISCreateLayerInfo(void) { msPostGISLayerInfo *layerinfo = msSmallMalloc(sizeof(msPostGISLayerInfo)); layerinfo->sql = NULL; layerinfo->srid = NULL; layerinfo->uid = NULL; layerinfo->pgconn = NULL; layerinfo->pgresult = NULL; layerinfo->geomcolumn = NULL; layerinfo->fromsource = NULL; layerinfo->endian = 0; layerinfo->rownum = 0; layerinfo->version = 0; layerinfo->paging = MS_TRUE; layerinfo->force2d = MS_TRUE; return layerinfo; } /* ** msPostGISFreeLayerInfo() */ void msPostGISFreeLayerInfo(layerObj *layer) { msPostGISLayerInfo *layerinfo = NULL; layerinfo = (msPostGISLayerInfo*)layer->layerinfo; if ( layerinfo->sql ) free(layerinfo->sql); if ( layerinfo->uid ) free(layerinfo->uid); if ( layerinfo->srid ) free(layerinfo->srid); if ( layerinfo->geomcolumn ) free(layerinfo->geomcolumn); if ( layerinfo->fromsource ) free(layerinfo->fromsource); if ( layerinfo->pgresult ) PQclear(layerinfo->pgresult); if ( layerinfo->pgconn ) msConnPoolRelease(layer, layerinfo->pgconn); free(layerinfo); layer->layerinfo = NULL; } /* ** postgresqlNoticeHandler() ** ** Propagate messages from the database to the Mapserver log, ** set in PQsetNoticeProcessor during layer open. */ void postresqlNoticeHandler(void *arg, const char *message) { layerObj *lp; lp = (layerObj*)arg; if (lp->debug) { msDebug("%s\n", message); } } /* ** Expandable pointObj array. The lineObj unfortunately ** is not useful for this purpose, so we have this one. */ pointArrayObj* pointArrayNew(int maxpoints) { pointArrayObj *d = msSmallMalloc(sizeof(pointArrayObj)); if ( maxpoints < 1 ) maxpoints = 1; /* Avoid a degenerate case */ d->maxpoints = maxpoints; d->data = msSmallMalloc(maxpoints * sizeof(pointObj)); d->npoints = 0; return d; } /* ** Utility function to creal up the pointArrayObj */ void pointArrayFree(pointArrayObj *d) { if ( ! d ) return; if ( d->data ) free(d->data); free(d); } /* ** Add a pointObj to the pointObjArray, allocating ** extra storage space if we've used up our existing ** buffer. */ static int pointArrayAddPoint(pointArrayObj *d, const pointObj *p) { if ( !p || !d ) return MS_FAILURE; /* Avoid overwriting memory buffer */ if ( d->maxpoints - d->npoints == 0 ) { d->maxpoints *= 2; d->data = realloc(d->data, d->maxpoints * sizeof(pointObj)); } d->data[d->npoints] = *p; d->npoints++; return MS_SUCCESS; } /* ** Pass an input type number through the PostGIS version ** type map array to handle the pre-2.0 incorrect WKB types */ static int wkbTypeMap(wkbObj *w, int type) { if ( type < WKB_TYPE_COUNT ) return w->typemap[type]; else return 0; } /* ** Read the WKB type number from a wkbObj without ** advancing the read pointer. */ static int wkbType(wkbObj *w) { int t; memcpy(&t, (w->ptr + 1), sizeof(int)); return wkbTypeMap(w,t); } /* ** Read the type number of the first element of a ** collection without advancing the read pointer. */ static int wkbCollectionSubType(wkbObj *w) { int t; memcpy(&t, (w->ptr + 1 + 4 + 4 + 1), sizeof(int)); return wkbTypeMap(w,t); } /* ** Read one byte from the WKB and advance the read pointer */ static char wkbReadChar(wkbObj *w) { char c; memcpy(&c, w->ptr, sizeof(char)); w->ptr += sizeof(char); return c; } /* ** Read one integer from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline int wkbReadInt(wkbObj *w) { int i; memcpy(&i, w->ptr, sizeof(int)); w->ptr += sizeof(int); return i; } /* ** Read one double from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline double wkbReadDouble(wkbObj *w) { double d; memcpy(&d, w->ptr, sizeof(double)); w->ptr += sizeof(double); return d; } /* ** Read one pointObj (two doubles) from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline void wkbReadPointP(wkbObj *w, pointObj *p) { memcpy(&(p->x), w->ptr, sizeof(double)); w->ptr += sizeof(double); memcpy(&(p->y), w->ptr, sizeof(double)); w->ptr += sizeof(double); } /* ** Read one pointObj (two doubles) from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline pointObj wkbReadPoint(wkbObj *w) { pointObj p; wkbReadPointP(w, &p); return p; } /* ** Read a "point array" and return an allocated lineObj. ** A point array is a WKB fragment that starts with a ** point count, which is followed by that number of doubles * 2. ** Linestrings, circular strings, polygon rings, all show this ** form. */ static void wkbReadLine(wkbObj *w, lineObj *line) { int i; pointObj p; int npoints = wkbReadInt(w); line->numpoints = npoints; line->point = msSmallMalloc(npoints * sizeof(pointObj)); for ( i = 0; i < npoints; i++ ) { wkbReadPointP(w, &p); line->point[i] = p; } } /* ** Advance the read pointer past a geometry without returning any ** values. Used for skipping un-drawable elements in a collection. */ static void wkbSkipGeometry(wkbObj *w) { int type, npoints, nrings, ngeoms, i; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); switch(type) { case WKB_POINT: w->ptr += 2 * sizeof(double); break; case WKB_CIRCULARSTRING: case WKB_LINESTRING: npoints = wkbReadInt(w); w->ptr += npoints * 2 * sizeof(double); break; case WKB_POLYGON: nrings = wkbReadInt(w); for ( i = 0; i < nrings; i++ ) { npoints = wkbReadInt(w); w->ptr += npoints * 2 * sizeof(double); } break; case WKB_MULTIPOINT: case WKB_MULTILINESTRING: case WKB_MULTIPOLYGON: case WKB_GEOMETRYCOLLECTION: case WKB_COMPOUNDCURVE: case WKB_CURVEPOLYGON: case WKB_MULTICURVE: case WKB_MULTISURFACE: ngeoms = wkbReadInt(w); for ( i = 0; i < ngeoms; i++ ) { wkbSkipGeometry(w); } } } /* ** Convert a WKB point to a shapeObj, advancing the read pointer as we go. */ static int wkbConvPointToShape(wkbObj *w, shapeObj *shape) { int type; lineObj line; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); if( type != WKB_POINT ) return MS_FAILURE; if( ! (shape->type == MS_SHAPE_POINT) ) return MS_FAILURE; line.numpoints = 1; line.point = msSmallMalloc(sizeof(pointObj)); line.point[0] = wkbReadPoint(w); msAddLineDirectly(shape, &line); return MS_SUCCESS; } /* ** Convert a WKB line string to a shapeObj, advancing the read pointer as we go. */ static int wkbConvLineStringToShape(wkbObj *w, shapeObj *shape) { int type; lineObj line; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); if( type != WKB_LINESTRING ) return MS_FAILURE; wkbReadLine(w,&line); msAddLineDirectly(shape, &line); return MS_SUCCESS; } /* ** Convert a WKB polygon to a shapeObj, advancing the read pointer as we go. */ static int wkbConvPolygonToShape(wkbObj *w, shapeObj *shape) { int type; int i, nrings; lineObj line; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); if( type != WKB_POLYGON ) return MS_FAILURE; /* How many rings? */ nrings = wkbReadInt(w); /* Add each ring to the shape */ for( i = 0; i < nrings; i++ ) { wkbReadLine(w,&line); msAddLineDirectly(shape, &line); } return MS_SUCCESS; } /* ** Convert a WKB curve polygon to a shapeObj, advancing the read pointer as we go. ** The arc portions of the rings will be stroked to linestrings as they ** are read by the underlying circular string handling. */ static int wkbConvCurvePolygonToShape(wkbObj *w, shapeObj *shape) { int type, i, ncomponents; int failures = 0; int was_poly = ( shape->type == MS_SHAPE_POLYGON ); /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); ncomponents = wkbReadInt(w); if( type != WKB_CURVEPOLYGON ) return MS_FAILURE; /* Lower the allowed dimensionality so we can * catch the linear ring components */ shape->type = MS_SHAPE_LINE; for ( i = 0; i < ncomponents; i++ ) { if ( wkbConvGeometryToShape(w, shape) == MS_FAILURE ) { wkbSkipGeometry(w); failures++; } } /* Go back to expected dimensionality */ if ( was_poly) shape->type = MS_SHAPE_POLYGON; if ( failures == ncomponents ) return MS_FAILURE; else return MS_SUCCESS; } /* ** Convert a WKB circular string to a shapeObj, advancing the read pointer as we go. ** Arcs will be stroked to linestrings. */ static int wkbConvCircularStringToShape(wkbObj *w, shapeObj *shape) { int type; lineObj line = {0, NULL}; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); if( type != WKB_CIRCULARSTRING ) return MS_FAILURE; /* Stroke the string into a point array */ if ( arcStrokeCircularString(w, SEGMENT_ANGLE, &line) == MS_FAILURE ) { if(line.point) free(line.point); return MS_FAILURE; } /* Fill in the lineObj */ if ( line.numpoints > 0 ) { msAddLine(shape, &line); if(line.point) free(line.point); } return MS_SUCCESS; } /* ** Compound curves need special handling. First we load ** each component of the curve on the a lineObj in a shape. ** Then we merge those lineObjs into a single lineObj. This ** allows compound curves to serve as closed rings in ** curve polygons. */ static int wkbConvCompoundCurveToShape(wkbObj *w, shapeObj *shape) { int npoints = 0; int type, ncomponents, i, j; lineObj *line; shapeObj shapebuf; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w)); /* Init our shape buffer */ msInitShape(&shapebuf); if( type != WKB_COMPOUNDCURVE ) return MS_FAILURE; /* How many components in the compound curve? */ ncomponents = wkbReadInt(w); /* We'll load each component onto a line in a shape */ for( i = 0; i < ncomponents; i++ ) wkbConvGeometryToShape(w, &shapebuf); /* Do nothing on empty */ if ( shapebuf.numlines == 0 ) return MS_FAILURE; /* Count the total number of points */ for( i = 0; i < shapebuf.numlines; i++ ) npoints += shapebuf.line[i].numpoints; /* Do nothing on empty */ if ( npoints == 0 ) return MS_FAILURE; /* Allocate space for the new line */ line = msSmallMalloc(sizeof(lineObj)); line->numpoints = npoints; line->point = msSmallMalloc(sizeof(pointObj) * npoints); /* Copy in the points */ npoints = 0; for ( i = 0; i < shapebuf.numlines; i++ ) { for ( j = 0; j < shapebuf.line[i].numpoints; j++ ) { /* Don't add a start point that duplicates an endpoint */ if( j == 0 && i > 0 && memcmp(&(line->point[npoints - 1]),&(shapebuf.line[i].point[j]),sizeof(pointObj)) == 0 ) { continue; } line->point[npoints++] = shapebuf.line[i].point[j]; } } line->numpoints = npoints; /* Clean up */ msFreeShape(&shapebuf); /* Fill in the lineObj */ msAddLineDirectly(shape, line); return MS_SUCCESS; } /* ** Convert a WKB collection string to a shapeObj, advancing the read pointer as we go. ** Many WKB types (MultiPoint, MultiLineString, MultiPolygon, MultiSurface, ** MultiCurve, GeometryCollection) can be treated identically as collections ** (they start with endian, type number and count of sub-elements, then provide the ** subelements as WKB) so are handled with this one function. */ static int wkbConvCollectionToShape(wkbObj *w, shapeObj *shape) { int i, ncomponents; int failures = 0; /*endian = */wkbReadChar(w); /*type = */wkbTypeMap(w,wkbReadInt(w)); ncomponents = wkbReadInt(w); /* * If we can draw any portion of the collection, we will, * but if all the components fail, we will draw nothing. */ for ( i = 0; i < ncomponents; i++ ) { if ( wkbConvGeometryToShape(w, shape) == MS_FAILURE ) { wkbSkipGeometry(w); failures++; } } if ( failures == ncomponents ) return MS_FAILURE; else return MS_SUCCESS; } /* ** Generic handler to switch to the appropriate function for the WKB type. ** Note that we also handle switching here to avoid processing shapes ** we will be unable to draw. Example: we can't draw point features as ** a MS_SHAPE_LINE layer, so if the type is WKB_POINT and the layer is ** MS_SHAPE_LINE, we exit before converting. */ int wkbConvGeometryToShape(wkbObj *w, shapeObj *shape) { int wkbtype = wkbType(w); /* Peak at the type number */ switch(wkbtype) { /* Recurse into anonymous collections */ case WKB_GEOMETRYCOLLECTION: return wkbConvCollectionToShape(w, shape); /* Handle area types */ case WKB_POLYGON: return wkbConvPolygonToShape(w, shape); case WKB_MULTIPOLYGON: return wkbConvCollectionToShape(w, shape); case WKB_CURVEPOLYGON: return wkbConvCurvePolygonToShape(w, shape); case WKB_MULTISURFACE: return wkbConvCollectionToShape(w, shape); } /* We can't convert any of the following types into polygons */ if ( shape->type == MS_SHAPE_POLYGON ) return MS_FAILURE; /* Handle linear types */ switch(wkbtype) { case WKB_LINESTRING: return wkbConvLineStringToShape(w, shape); case WKB_CIRCULARSTRING: return wkbConvCircularStringToShape(w, shape); case WKB_COMPOUNDCURVE: return wkbConvCompoundCurveToShape(w, shape); case WKB_MULTILINESTRING: return wkbConvCollectionToShape(w, shape); case WKB_MULTICURVE: return wkbConvCollectionToShape(w, shape); } /* We can't convert any of the following types into lines */ if ( shape->type == MS_SHAPE_LINE ) return MS_FAILURE; /* Handle point types */ switch(wkbtype) { case WKB_POINT: return wkbConvPointToShape(w, shape); case WKB_MULTIPOINT: return wkbConvCollectionToShape(w, shape); } /* This is a WKB type we don't know about! */ return MS_FAILURE; } /* ** Calculate determinant of a 3x3 matrix. Handy for ** the circle center calculation. */ static inline double arcDeterminant3x3(double *m) { /* This had better be a 3x3 matrix or we'll fall to bits */ return m[0] * ( m[4] * m[8] - m[7] * m[5] ) - m[3] * ( m[1] * m[8] - m[7] * m[2] ) + m[6] * ( m[1] * m[5] - m[4] * m[2] ); } /* ** What side of p1->p2 is q on? */ static inline int arcSegmentSide(const pointObj *p1, const pointObj *p2, const pointObj *q) { double side = ( (q->x - p1->x) * (p2->y - p1->y) - (p2->x - p1->x) * (q->y - p1->y) ); if ( FP_EQ(side,0.0) ) { return FP_COLINEAR; } else { if ( side < 0.0 ) return FP_LEFT; else return FP_RIGHT; } } /* ** Calculate the center of the circle defined by three points. ** Using matrix approach from http://mathforum.org/library/drmath/view/55239.html */ int arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, pointObj *center, double *radius) { pointObj c; double r; /* Components of the matrices. */ double x1sq = p1->x * p1->x; double x2sq = p2->x * p2->x; double x3sq = p3->x * p3->x; double y1sq = p1->y * p1->y; double y2sq = p2->y * p2->y; double y3sq = p3->y * p3->y; double matrix_num_x[9]; double matrix_num_y[9]; double matrix_denom[9]; /* Intialize matrix_num_x */ matrix_num_x[0] = x1sq+y1sq; matrix_num_x[1] = p1->y; matrix_num_x[2] = 1.0; matrix_num_x[3] = x2sq+y2sq; matrix_num_x[4] = p2->y; matrix_num_x[5] = 1.0; matrix_num_x[6] = x3sq+y3sq; matrix_num_x[7] = p3->y; matrix_num_x[8] = 1.0; /* Intialize matrix_num_y */ matrix_num_y[0] = p1->x; matrix_num_y[1] = x1sq+y1sq; matrix_num_y[2] = 1.0; matrix_num_y[3] = p2->x; matrix_num_y[4] = x2sq+y2sq; matrix_num_y[5] = 1.0; matrix_num_y[6] = p3->x; matrix_num_y[7] = x3sq+y3sq; matrix_num_y[8] = 1.0; /* Intialize matrix_denom */ matrix_denom[0] = p1->x; matrix_denom[1] = p1->y; matrix_denom[2] = 1.0; matrix_denom[3] = p2->x; matrix_denom[4] = p2->y; matrix_denom[5] = 1.0; matrix_denom[6] = p3->x; matrix_denom[7] = p3->y; matrix_denom[8] = 1.0; /* Circle is closed, so p2 must be opposite p1 & p3. */ if ( FP_EQ(p1->x,p3->x) && FP_EQ(p1->y,p3->y) ) { c.x = (p1->x + p2->x) / 2.0; c.y = (p1->y + p2->y) / 2.0; r = sqrt( (p1->x - p2->x) * (p1->x - p2->x) + (p1->y - p2->y) * (p1->y - p2->y) ) / 2.0; } /* There is no circle here, the points are actually co-linear */ else if ( arcSegmentSide(p1, p3, p2) == FP_COLINEAR ) { return MS_FAILURE; } /* Calculate the center and radius. */ else { double denom = 2.0 * arcDeterminant3x3(matrix_denom); /* Center components */ c.x = arcDeterminant3x3(matrix_num_x) / denom; c.y = arcDeterminant3x3(matrix_num_y) / denom; /* Radius */ r = sqrt((p1->x-c.x) * (p1->x-c.x) + (p1->y-c.y) * (p1->y-c.y)); } if ( radius ) *radius = r; if ( center ) *center = c; return MS_SUCCESS; } /* ** Write a stroked version of the circle defined by three points into a ** point buffer. The segment_angle (degrees) is the coverage of each stroke segment, ** and depending on whether this is the first arc in a circularstring, ** you might want to include_first */ int arcStrokeCircle(const pointObj *p1, const pointObj *p2, const pointObj *p3, double segment_angle, int include_first, pointArrayObj *pa) { pointObj center; /* Center of our circular arc */ double radius; /* Radius of our circular arc */ double sweep_angle_r; /* Total angular size of our circular arc in radians */ double segment_angle_r; /* Segment angle in radians */ double a1, /*a2,*/ a3; /* Angles represented by p1, p2, p3 relative to center */ int side = arcSegmentSide(p1, p3, p2); /* What side of p1,p3 is the middle point? */ int num_edges; /* How many edges we will be generating */ double current_angle_r; /* What angle are we generating now (radians)? */ int i; /* Counter */ pointObj p; /* Temporary point */ int is_closed = MS_FALSE; /* We need to know if we're dealing with a circle early */ if ( FP_EQ(p1->x, p3->x) && FP_EQ(p1->y, p3->y) ) is_closed = MS_TRUE; /* Check if the "arc" is actually straight */ if ( ! is_closed && side == FP_COLINEAR ) { /* We just need to write in the end points */ if ( include_first ) pointArrayAddPoint(pa, p1); pointArrayAddPoint(pa, p3); return MS_SUCCESS; } /* We should always be able to find the center of a non-linear arc */ if ( arcCircleCenter(p1, p2, p3, ¢er, &radius) == MS_FAILURE ) return MS_FAILURE; /* Calculate the angles that our three points represent */ a1 = atan2(p1->y - center.y, p1->x - center.x); /* UNUSED a2 = atan2(p2->y - center.y, p2->x - center.x); */ a3 = atan2(p3->y - center.y, p3->x - center.x); segment_angle_r = M_PI * segment_angle / 180.0; /* Closed-circle case, we sweep the whole circle! */ if ( is_closed ) { sweep_angle_r = 2.0 * M_PI; } /* Clockwise sweep direction */ else if ( side == FP_LEFT ) { if ( a3 > a1 ) /* Wrapping past 180? */ sweep_angle_r = a1 + (2.0 * M_PI - a3); else sweep_angle_r = a1 - a3; } /* Counter-clockwise sweep direction */ else if ( side == FP_RIGHT ) { if ( a3 > a1 ) /* Wrapping past 180? */ sweep_angle_r = a3 - a1; else sweep_angle_r = a3 + (2.0 * M_PI - a1); } else sweep_angle_r = 0.0; /* We don't have enough resolution, let's invert our strategy. */ if ( (sweep_angle_r / segment_angle_r) < SEGMENT_MINPOINTS ) { segment_angle_r = sweep_angle_r / (SEGMENT_MINPOINTS + 1); } /* We don't have enough resolution to stroke this arc, * so just join the start to the end. */ if ( sweep_angle_r < segment_angle_r ) { if ( include_first ) pointArrayAddPoint(pa, p1); pointArrayAddPoint(pa, p3); return MS_SUCCESS; } /* How many edges to generate (we add the final edge * by sticking on the last point */ num_edges = floor(sweep_angle_r / fabs(segment_angle_r)); /* Go backwards (negative angular steps) if we are stroking clockwise */ if ( side == FP_LEFT ) segment_angle_r *= -1; /* What point should we start with? */ if( include_first ) { current_angle_r = a1; } else { current_angle_r = a1 + segment_angle_r; num_edges--; } /* For each edge, increment or decrement by our segment angle */ for( i = 0; i < num_edges; i++ ) { if (segment_angle_r > 0.0 && current_angle_r > M_PI) current_angle_r -= 2*M_PI; if (segment_angle_r < 0.0 && current_angle_r < -1*M_PI) current_angle_r -= 2*M_PI; p.x = center.x + radius*cos(current_angle_r); p.y = center.y + radius*sin(current_angle_r); pointArrayAddPoint(pa, &p); current_angle_r += segment_angle_r; } /* Add the last point */ pointArrayAddPoint(pa, p3); return MS_SUCCESS; } /* ** This function does not actually take WKB as input, it takes the ** WKB starting from the numpoints integer. Each three-point edge ** is stroked into a linestring and appended into the lineObj ** argument. */ int arcStrokeCircularString(wkbObj *w, double segment_angle, lineObj *line) { pointObj p1, p2, p3; int npoints, nedges; int edge = 0; pointArrayObj *pa; if ( ! w || ! line ) return MS_FAILURE; npoints = wkbReadInt(w); nedges = npoints / 2; /* All CircularStrings have an odd number of points */ if ( npoints < 3 || npoints % 2 != 1 ) return MS_FAILURE; /* Make a large guess at how much space we'll need */ pa = pointArrayNew(nedges * 180 / segment_angle); wkbReadPointP(w,&p3); /* Fill out the point array with stroked arcs */ while( edge < nedges ) { p1 = p3; wkbReadPointP(w,&p2); wkbReadPointP(w,&p3); if ( arcStrokeCircle(&p1, &p2, &p3, segment_angle, edge ? 0 : 1, pa) == MS_FAILURE ) { pointArrayFree(pa); return MS_FAILURE; } edge++; } /* Copy the point array into the line */ line->numpoints = pa->npoints; line->point = msSmallMalloc(line->numpoints * sizeof(pointObj)); memcpy(line->point, pa->data, line->numpoints * sizeof(pointObj)); /* Clean up */ pointArrayFree(pa); return MS_SUCCESS; } /* ** For LAYER types that are not the usual ones (charts, ** annotations, etc) we will convert to a shape type ** that "makes sense" given the WKB input. We do this ** by peaking at the type number of the first collection ** sub-element. */ static int msPostGISFindBestType(wkbObj *w, shapeObj *shape) { int wkbtype; /* What kind of geometry is this? */ wkbtype = wkbType(w); /* Generic collection, we need to look a little deeper. */ if ( wkbtype == WKB_GEOMETRYCOLLECTION ) wkbtype = wkbCollectionSubType(w); switch ( wkbtype ) { case WKB_POLYGON: case WKB_CURVEPOLYGON: case WKB_MULTIPOLYGON: shape->type = MS_SHAPE_POLYGON; break; case WKB_LINESTRING: case WKB_CIRCULARSTRING: case WKB_COMPOUNDCURVE: case WKB_MULTICURVE: case WKB_MULTILINESTRING: shape->type = MS_SHAPE_LINE; break; case WKB_POINT: case WKB_MULTIPOINT: shape->type = MS_SHAPE_POINT; break; default: return MS_FAILURE; } return wkbConvGeometryToShape(w, shape); } /* ** Recent versions of PgSQL provide the version as an int in a ** simple call to the connection handle. For earlier ones we have ** to parse the version string into a usable number. */ static int msPostGISRetrievePgVersion(PGconn *pgconn) { #ifndef POSTGIS_HAS_SERVER_VERSION int pgVersion = 0; char *strVersion = NULL; char *strParts[3] = { NULL, NULL, NULL }; int i = 0, j = 0, len = 0; int factor = 10000; if (pgconn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a postgis connection.", "msPostGISRetrievePgVersion()"); return MS_FAILURE; } if (! PQparameterStatus(pgconn, "server_version") ) return MS_FAILURE; strVersion = msStrdup(PQparameterStatus(pgconn, "server_version")); if( ! strVersion ) return MS_FAILURE; strParts[j] = strVersion; j++; len = strlen(strVersion); for( i = 0; i < len; i++ ) { if( strVersion[i] == '.' ) { strVersion[i] = '\0'; if( j < 3 ) { strParts[j] = strVersion + i + 1; j++; } else { free(strVersion); msSetError(MS_QUERYERR, "Too many parts in version string.", "msPostGISRetrievePgVersion()"); return MS_FAILURE; } } } for( j = 0; j < 3 && strParts[j]; j++ ) { pgVersion += factor * atoi(strParts[j]); factor = factor / 100; } free(strVersion); return pgVersion; #else return PQserverVersion(pgconn); #endif } /* ** Get the PostGIS version number from the database as integer. ** Versions are multiplied out as with PgSQL: 1.5.2 -> 10502, 2.0.0 -> 20000. */ static int msPostGISRetrieveVersion(PGconn *pgconn) { static char* sql = "SELECT postgis_version()"; int version = 0; size_t strSize; char *strVersion = NULL; char *ptr; char *strParts[3] = { NULL, NULL, NULL }; int i = 0, j = 0; int factor = 10000; PGresult *pgresult = NULL; if ( ! pgconn ) { msSetError(MS_QUERYERR, "No open connection.", "msPostGISRetrieveVersion()"); return MS_FAILURE; } pgresult = PQexecParams(pgconn, sql,0, NULL, NULL, NULL, NULL, 0); if ( !pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { msSetError(MS_QUERYERR, "Error executing SQL: %s", "msPostGISRetrieveVersion()", sql); return MS_FAILURE; } if (PQgetisnull(pgresult, 0, 0)) { PQclear(pgresult); msSetError(MS_QUERYERR,"Null result returned.","msPostGISRetrieveVersion()"); return MS_FAILURE; } strSize = PQgetlength(pgresult, 0, 0) + 1; strVersion = (char*)msSmallMalloc(strSize); strlcpy(strVersion, PQgetvalue(pgresult, 0, 0), strSize); PQclear(pgresult); ptr = strVersion; strParts[j++] = strVersion; while( ptr != '\0' && j < 3 ) { if ( *ptr == '.' ) { *ptr = '\0'; strParts[j++] = ptr + 1; } if ( *ptr == ' ' ) { *ptr = '\0'; break; } ptr++; } for( i = 0; i < j; i++ ) { version += factor * atoi(strParts[i]); factor = factor / 100; } free(strVersion); return version; } /* ** msPostGISRetrievePK() ** ** Find out that the primary key is for this layer. ** The layerinfo->fromsource must already be populated and ** must not be a subquery. */ static int msPostGISRetrievePK(layerObj *layer) { PGresult *pgresult = NULL; char *sql = 0; size_t size; msPostGISLayerInfo *layerinfo = 0; int length; int pgVersion; char *pos_sep; char *schema = NULL; char *table = NULL; if (layer->debug) { msDebug("msPostGISRetrievePK called.\n"); } layerinfo = (msPostGISLayerInfo *) layer->layerinfo; /* Attempt to separate fromsource into schema.table */ pos_sep = strstr(layerinfo->fromsource, "."); if (pos_sep) { length = strlen(layerinfo->fromsource) - strlen(pos_sep) + 1; schema = (char*)msSmallMalloc(length); strlcpy(schema, layerinfo->fromsource, length); length = strlen(pos_sep); table = (char*)msSmallMalloc(length); strlcpy(table, pos_sep + 1, length); if (layer->debug) { msDebug("msPostGISRetrievePK(): Found schema %s, table %s.\n", schema, table); } } if (layerinfo->pgconn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a postgis connection.", "msPostGISRetrievePK()"); return MS_FAILURE; } pgVersion = msPostGISRetrievePgVersion(layerinfo->pgconn); if (pgVersion < 70000) { if (layer->debug) { msDebug("msPostGISRetrievePK(): Major version below 7.\n"); } return MS_FAILURE; } if (pgVersion < 70200) { if (layer->debug) { msDebug("msPostGISRetrievePK(): Version below 7.2.\n"); } return MS_FAILURE; } if (pgVersion < 70300) { /* ** PostgreSQL v7.2 has a different representation of primary keys that ** later versions. This currently does not explicitly exclude ** multicolumn primary keys. */ static char *v72sql = "select b.attname from pg_class as a, pg_attribute as b, (select oid from pg_class where relname = '%s') as c, pg_index as d where d.indexrelid = a.oid and d.indrelid = c.oid and d.indisprimary and b.attrelid = a.oid and a.relnatts = 1"; sql = msSmallMalloc(strlen(layerinfo->fromsource) + strlen(v72sql)); sprintf(sql, v72sql, layerinfo->fromsource); } else { /* ** PostgreSQL v7.3 and later treat primary keys as constraints. ** We only support single column primary keys, so multicolumn ** pks are explicitly excluded from the query. */ if (schema && table) { static char *v73sql = "select attname from pg_attribute, pg_constraint, pg_class, pg_namespace where pg_constraint.conrelid = pg_class.oid and pg_class.oid = pg_attribute.attrelid and pg_constraint.contype = 'p' and pg_constraint.conkey[1] = pg_attribute.attnum and pg_class.relname = '%s' and pg_class.relnamespace = pg_namespace.oid and pg_namespace.nspname = '%s' and pg_constraint.conkey[2] is null"; sql = msSmallMalloc(strlen(schema) + strlen(table) + strlen(v73sql)); sprintf(sql, v73sql, table, schema); free(table); free(schema); } else { static char *v73sql = "select attname from pg_attribute, pg_constraint, pg_class where pg_constraint.conrelid = pg_class.oid and pg_class.oid = pg_attribute.attrelid and pg_constraint.contype = 'p' and pg_constraint.conkey[1] = pg_attribute.attnum and pg_class.relname = '%s' and pg_table_is_visible(pg_class.oid) and pg_constraint.conkey[2] is null"; sql = msSmallMalloc(strlen(layerinfo->fromsource) + strlen(v73sql)); sprintf(sql, v73sql, layerinfo->fromsource); } } if (layer->debug > 1) { msDebug("msPostGISRetrievePK: %s\n", sql); } layerinfo = (msPostGISLayerInfo *) layer->layerinfo; if (layerinfo->pgconn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a postgis connection.", "msPostGISRetrievePK()"); free(sql); return MS_FAILURE; } pgresult = PQexecParams(layerinfo->pgconn, sql, 0, NULL, NULL, NULL, NULL, 0); if ( !pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { static char *tmp1 = "Error executing SQL: "; char *tmp2 = NULL; size_t size2; size2 = sizeof(char)*(strlen(tmp1) + strlen(sql) + 1); tmp2 = (char*)msSmallMalloc(size2); strlcpy(tmp2, tmp1, size2); strlcat(tmp2, sql, size2); msSetError(MS_QUERYERR, "%s", "msPostGISRetrievePK()", tmp2); free(tmp2); free(sql); return MS_FAILURE; } if (PQntuples(pgresult) < 1) { if (layer->debug) { msDebug("msPostGISRetrievePK: No results found.\n"); } PQclear(pgresult); free(sql); return MS_FAILURE; } if (PQntuples(pgresult) > 1) { if (layer->debug) { msDebug("msPostGISRetrievePK: Multiple results found.\n"); } PQclear(pgresult); free(sql); return MS_FAILURE; } if (PQgetisnull(pgresult, 0, 0)) { if (layer->debug) { msDebug("msPostGISRetrievePK: Null result returned.\n"); } PQclear(pgresult); free(sql); return MS_FAILURE; } size = PQgetlength(pgresult, 0, 0) + 1; layerinfo->uid = (char*)msSmallMalloc(size); strlcpy(layerinfo->uid, PQgetvalue(pgresult, 0, 0), size); PQclear(pgresult); free(sql); return MS_SUCCESS; } /* ** msPostGISParseData() ** ** Parse the DATA string for geometry column name, table name, ** unique id column, srid, and SQL string. */ int msPostGISParseData(layerObj *layer) { char *pos_opt, *pos_scn, *tmp, *pos_srid, *pos_uid, *pos_geom, *data; int slength; msPostGISLayerInfo *layerinfo; assert(layer != NULL); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*)(layer->layerinfo); if (layer->debug) { msDebug("msPostGISParseData called.\n"); } if (!layer->data) { msSetError(MS_QUERYERR, "Missing DATA clause. DATA statement must contain 'geometry_column from table_name' or 'geometry_column from (sub-query) as sub'.", "msPostGISParseData()"); return MS_FAILURE; } data = layer->data; /* ** Clean up any existing strings first, as we will be populating these fields. */ if( layerinfo->srid ) { free(layerinfo->srid); layerinfo->srid = NULL; } if( layerinfo->uid ) { free(layerinfo->uid); layerinfo->uid = NULL; } if( layerinfo->geomcolumn ) { free(layerinfo->geomcolumn); layerinfo->geomcolumn = NULL; } if( layerinfo->fromsource ) { free(layerinfo->fromsource); layerinfo->fromsource = NULL; } /* ** Look for the optional ' using unique ID' string first. */ pos_uid = strcasestr(data, " using unique "); if (pos_uid) { /* Find the end of this case 'using unique ftab_id using srid=33' */ tmp = strstr(pos_uid + 14, " "); /* Find the end of this case 'using srid=33 using unique ftab_id' */ if (!tmp) { tmp = pos_uid + strlen(pos_uid); } layerinfo->uid = (char*) msSmallMalloc((tmp - (pos_uid + 14)) + 1); strlcpy(layerinfo->uid, pos_uid + 14, tmp - (pos_uid + 14)+1); msStringTrim(layerinfo->uid); } /* ** Look for the optional ' using srid=333 ' string next. */ pos_srid = strcasestr(data, " using srid="); if (!pos_srid) { layerinfo->srid = (char*) msSmallMalloc(1); (layerinfo->srid)[0] = '\0'; /* no SRID, so return just null terminator*/ } else { slength = strspn(pos_srid + 12, "-0123456789"); if (!slength) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You specified 'USING SRID' but didnt have any numbers! %s", "msPostGISParseData()", data); return MS_FAILURE; } else { layerinfo->srid = (char*) msSmallMalloc(slength + 1); strlcpy(layerinfo->srid, pos_srid + 12, slength+1); msStringTrim(layerinfo->srid); } } /* ** This is a little hack so the rest of the code works. ** pos_opt should point to the start of the optional blocks. ** ** If they are both set, return the smaller one. */ if (pos_srid && pos_uid) { pos_opt = (pos_srid > pos_uid) ? pos_uid : pos_srid; } /* If one or none is set, return the larger one. */ else { pos_opt = (pos_srid > pos_uid) ? pos_srid : pos_uid; } /* No pos_opt? Move it to the end of the string. */ if (!pos_opt) { pos_opt = data + strlen(data); } /* ** Scan for the 'geometry from table' or 'geometry from () as foo' clause. */ /* Find the first non-white character to start from */ pos_geom = data; while( *pos_geom == ' ' || *pos_geom == '\t' || *pos_geom == '\n' || *pos_geom == '\r' ) pos_geom++; /* Find the end of the geom column name */ pos_scn = strcasestr(data, " from "); if (!pos_scn) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. Must contain 'geometry from table' or 'geometry from (subselect) as foo'. %s", "msPostGISParseData()", data); return MS_FAILURE; } /* Copy the geometry column name */ layerinfo->geomcolumn = (char*) msSmallMalloc((pos_scn - pos_geom) + 1); strlcpy(layerinfo->geomcolumn, pos_geom, pos_scn - pos_geom+1); msStringTrim(layerinfo->geomcolumn); /* Copy the table name or sub-select clause */ layerinfo->fromsource = (char*) msSmallMalloc((pos_opt - (pos_scn + 6)) + 1); strlcpy(layerinfo->fromsource, pos_scn + 6, pos_opt - (pos_scn + 6)+1); msStringTrim(layerinfo->fromsource); /* Something is wrong, our goemetry column and table references are not there. */ if (strlen(layerinfo->fromsource) < 1 || strlen(layerinfo->geomcolumn) < 1) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. Must contain 'geometry from table' or 'geometry from (subselect) as foo'. %s", "msPostGISParseData()", data); return MS_FAILURE; } /* ** We didn't find a ' using unique ' in the DATA string so try and find a ** primary key on the table. */ if ( ! (layerinfo->uid) ) { if ( strstr(layerinfo->fromsource, " ") ) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You must specify 'using unique' when supplying a subselect in the data definition.", "msPostGISParseData()"); return MS_FAILURE; } if ( msPostGISRetrievePK(layer) != MS_SUCCESS ) { /* No user specified unique id so we will use the PostgreSQL oid */ /* TODO: Deprecate this, oids are deprecated in PostgreSQL */ layerinfo->uid = msStrdup("oid"); } } if (layer->debug) { msDebug("msPostGISParseData: unique_column=%s, srid=%s, geom_column_name=%s, table_name=%s\n", layerinfo->uid, layerinfo->srid, layerinfo->geomcolumn, layerinfo->fromsource); } return MS_SUCCESS; } /* ** Decode a hex character. */ static unsigned char msPostGISHexDecodeChar[256] = { /* not Hex characters */ 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, /* 0-9 */ 0,1,2,3,4,5,6,7,8,9, /* not Hex characters */ 64,64,64,64,64,64,64, /* A-F */ 10,11,12,13,14,15, /* not Hex characters */ 64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64, /* a-f */ 10,11,12,13,14,15, 64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, /* not Hex characters (upper 128 characters) */ 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64 }; /* ** Decode hex string "src" (null terminated) ** into "dest" (not null terminated). ** Returns length of decoded array or 0 on failure. */ int msPostGISHexDecode(unsigned char *dest, const char *src, int srclen) { if (src && *src && (srclen % 2 == 0) ) { unsigned char *p = dest; int i; for ( i=0; i>4) ); if (c3 != '=') { *p++=(((b2&0xf)<<4)|(b3>>2) ); } if (c4 != '=') { *p++=(((b3&0x3)<<6)|b4 ); } } free(buf); return(p-dest); } return 0; } /* ** msPostGISBuildSQLBox() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLBox(layerObj *layer, rectObj *rect, char *strSRID) { char *strBox = NULL; size_t sz; if (layer->debug) { msDebug("msPostGISBuildSQLBox called.\n"); } if ( strSRID ) { static char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%s)"; /* 10 doubles + 1 integer + template characters */ sz = 10 * 22 + strlen(strSRID) + strlen(strBoxTemplate); strBox = (char*)msSmallMalloc(sz+1); /* add space for terminating NULL */ if ( sz <= snprintf(strBox, sz, strBoxTemplate, rect->minx, rect->miny, rect->minx, rect->maxy, rect->maxx, rect->maxy, rect->maxx, rect->miny, rect->minx, rect->miny, strSRID)) { msSetError(MS_MISCERR,"Bounding box digits truncated.","msPostGISBuildSQLBox"); return NULL; } } else { static char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))')"; /* 10 doubles + template characters */ sz = 10 * 22 + strlen(strBoxTemplate); strBox = (char*)msSmallMalloc(sz+1); /* add space for terminating NULL */ if ( sz <= snprintf(strBox, sz, strBoxTemplate, rect->minx, rect->miny, rect->minx, rect->maxy, rect->maxx, rect->maxy, rect->maxx, rect->miny, rect->minx, rect->miny) ) { msSetError(MS_MISCERR,"Bounding box digits truncated.","msPostGISBuildSQLBox"); return NULL; } } return strBox; } /* ** msPostGISBuildSQLItems() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLItems(layerObj *layer) { char *strEndian = NULL; char *strGeom = NULL; char *strItems = NULL; msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISBuildSQLItems called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( ! layerinfo->geomcolumn ) { msSetError(MS_MISCERR, "layerinfo->geomcolumn is not initialized.", "msPostGISBuildSQLItems()"); return NULL; } /* ** Get the server to transform the geometry into our ** native endian before transmitting it to us.. */ if (layerinfo->endian == LITTLE_ENDIAN) { strEndian = "NDR"; } else { strEndian = "XDR"; } { /* ** We transfer the geometry from server to client as a ** hex or base64 encoded WKB byte-array. We will have to decode this ** data once we get it. Forcing to 2D (via the AsBinary function ** which includes a 2D force in it) removes ordinates we don't ** need, saving transfer and encode/decode time. */ char *force2d = ""; #if TRANSFER_ENCODING == 64 static char *strGeomTemplate = "encode(ST_AsBinary(%s(\"%s\"),'%s'),'base64') as geom,\"%s\""; #else static char *strGeomTemplate = "encode(ST_AsBinary(%s(\"%s\"),'%s'),'hex') as geom,\"%s\""; #endif if( layerinfo->force2d ) { if( layerinfo->version >= 20100 ) force2d = "ST_Force2D"; else force2d = "ST_Force_2D"; } strGeom = (char*)msSmallMalloc(strlen(strGeomTemplate) + strlen(force2d) + strlen(strEndian) + strlen(layerinfo->geomcolumn) + strlen(layerinfo->uid)); sprintf(strGeom, strGeomTemplate, force2d, layerinfo->geomcolumn, strEndian, layerinfo->uid); } if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLItems: %d items requested.\n",layer->numitems); } /* ** Not requesting items? We just need geometry and unique id. */ if (layer->numitems == 0) { strItems = msStrdup(strGeom); } /* ** Build SQL to pull all the items. */ else { int length = strlen(strGeom) + 2; int t; for ( t = 0; t < layer->numitems; t++ ) { length += strlen(layer->items[t]) + 3; /* itemname + "", */ } strItems = (char*)msSmallMalloc(length); strItems[0] = '\0'; for ( t = 0; t < layer->numitems; t++ ) { strlcat(strItems, "\"", length); strlcat(strItems, layer->items[t], length); strlcat(strItems, "\",", length); } strlcat(strItems, strGeom, length); } free(strGeom); return strItems; } /* ** msPostGISBuildSQLSRID() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLSRID(layerObj *layer) { char *strSRID = NULL; msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISBuildSQLSRID called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; /* An SRID was already provided in the DATA line. */ if ( layerinfo->srid && (strlen(layerinfo->srid) > 0) ) { strSRID = msStrdup(layerinfo->srid); if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLSRID: SRID provided (%s)\n", strSRID); } } /* ** No SRID in data line, so extract target table from the 'fromsource'. ** Either of form "thetable" (one word) or "(select ... from thetable)" ** or "(select ... from thetable where ...)". */ else { char *f_table_name; char *strSRIDTemplate = "find_srid('','%s','%s')"; char *pos = strstr(layerinfo->fromsource, " "); if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLSRID: Building find_srid line.\n"); } if ( ! pos ) { /* target table is one word */ f_table_name = msStrdup(layerinfo->fromsource); if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLSRID: Found table (%s)\n", f_table_name); } } else { /* target table is hiding in sub-select clause */ pos = strcasestr(layerinfo->fromsource, " from "); if ( pos ) { char *pos_paren; char *pos_space; pos += 6; /* should be start of table name */ pos_paren = strstr(pos, ")"); /* first ) after table name */ pos_space = strstr(pos, " "); /* first space after table name */ if ( pos_space < pos_paren ) { /* found space first */ f_table_name = (char*)msSmallMalloc(pos_space - pos + 1); strlcpy(f_table_name, pos, pos_space - pos+1); } else { /* found ) first */ f_table_name = (char*)msSmallMalloc(pos_paren - pos + 1); strlcpy(f_table_name, pos, pos_paren - pos+1); } } else { /* should not happen */ return NULL; } } strSRID = msSmallMalloc(strlen(strSRIDTemplate) + strlen(f_table_name) + strlen(layerinfo->geomcolumn)); sprintf(strSRID, strSRIDTemplate, f_table_name, layerinfo->geomcolumn); if ( f_table_name ) free(f_table_name); } return strSRID; } /* ** msPostGISReplaceBoxToken() ** ** Convert a fromsource data statement into something usable by replacing the !BOX! token. ** ** Returns malloc'ed char* that must be freed by caller. */ static char *msPostGISReplaceBoxToken(layerObj *layer, rectObj *rect, const char *fromsource) { char *result = NULL; if ( strstr(fromsource, BOXTOKEN) && rect ) { char *strBox = NULL; char *strSRID = NULL; /* We see to set the SRID on the box, but to what SRID? */ strSRID = msPostGISBuildSQLSRID(layer); if ( ! strSRID ) { return NULL; } /* Create a suitable SQL string from the rectangle and SRID. */ strBox = msPostGISBuildSQLBox(layer, rect, strSRID); if ( ! strBox ) { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISReplaceBoxToken()"); if (strSRID) free(strSRID); return NULL; } /* Do the substitution. */ while ( strstr(fromsource, BOXTOKEN) ) { char *start, *end; char *oldresult = result; size_t buffer_size = 0; start = strstr(fromsource, BOXTOKEN); end = start + BOXTOKENLENGTH; buffer_size = (start - fromsource) + strlen(strBox) + strlen(end) +1; result = (char*)msSmallMalloc(buffer_size); strlcpy(result, fromsource, start - fromsource +1); strlcpy(result + (start - fromsource), strBox, buffer_size-(start - fromsource)); strlcat(result, end, buffer_size); fromsource = result; if (oldresult != NULL) free(oldresult); } if (strSRID) free(strSRID); if (strBox) free(strBox); } else { result = msStrdup(fromsource); } return result; } /* ** msPostGISBuildSQLFrom() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLFrom(layerObj *layer, rectObj *rect) { char *strFrom = 0; msPostGISLayerInfo *layerinfo; if (layer->debug) { msDebug("msPostGISBuildSQLFrom called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( ! layerinfo->fromsource ) { msSetError(MS_MISCERR, "Layerinfo->fromsource is not initialized.", "msPostGISBuildSQLFrom()"); return NULL; } /* ** If there's a '!BOX!' in our source we need to substitute the ** current rectangle for it... */ strFrom = msPostGISReplaceBoxToken(layer, rect, layerinfo->fromsource); return strFrom; } /* ** msPostGISBuildSQLWhere() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid) { char *strRect = 0; char *strFilter = 0; char *strUid = 0; char *strWhere = 0; char *strLimit = 0; char *strOffset = 0; size_t strRectLength = 0; size_t strFilterLength = 0; size_t strUidLength = 0; size_t strLimitLength = 0; size_t strOffsetLength = 0; size_t bufferSize = 0; int insert_and = 0; msPostGISLayerInfo *layerinfo; if (layer->debug) { msDebug("msPostGISBuildSQLWhere called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( ! layerinfo->fromsource ) { msSetError(MS_MISCERR, "Layerinfo->fromsource is not initialized.", "msPostGISBuildSQLWhere()"); return NULL; } /* Populate strLimit, if necessary. */ if ( layerinfo->paging && layer->maxfeatures >= 0 ) { static char *strLimitTemplate = " limit %d"; strLimit = msSmallMalloc(strlen(strLimitTemplate) + 12); sprintf(strLimit, strLimitTemplate, layer->maxfeatures); strLimitLength = strlen(strLimit); } /* Populate strOffset, if necessary. */ if ( layerinfo->paging && layer->startindex > 0 ) { static char *strOffsetTemplate = " offset %d"; strOffset = msSmallMalloc(strlen(strOffsetTemplate) + 12); sprintf(strOffset, strOffsetTemplate, layer->startindex-1); strOffsetLength = strlen(strOffset); } /* Populate strRect, if necessary. */ if ( rect && layerinfo->geomcolumn ) { char *strBox = 0; char *strSRID = 0; size_t strBoxLength = 0; static char *strRectTemplate = "%s && %s"; /* We see to set the SRID on the box, but to what SRID? */ strSRID = msPostGISBuildSQLSRID(layer); if ( ! strSRID ) { return NULL; } strBox = msPostGISBuildSQLBox(layer, rect, strSRID); if ( strBox ) { strBoxLength = strlen(strBox); } else { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISBuildSQLWhere()"); return NULL; } strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn)); sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox); strRectLength = strlen(strRect); if (strBox) free(strBox); if (strSRID) free(strSRID); } /* Populate strFilter, if necessary. */ if ( layer->filter.string ) { static char *strFilterTemplate = "(%s)"; strFilter = (char*)msSmallMalloc(strlen(strFilterTemplate) + strlen(layer->filter.string)); sprintf(strFilter, strFilterTemplate, layer->filter.string); strFilterLength = strlen(strFilter); } /* Populate strUid, if necessary. */ if ( uid ) { static char *strUidTemplate = "\"%s\" = %ld"; strUid = (char*)msSmallMalloc(strlen(strUidTemplate) + strlen(layerinfo->uid) + 64); sprintf(strUid, strUidTemplate, layerinfo->uid, *uid); strUidLength = strlen(strUid); } bufferSize = strRectLength + 5 + strFilterLength + 5 + strUidLength + strLimitLength + strOffsetLength; strWhere = (char*)msSmallMalloc(bufferSize); *strWhere = '\0'; if ( strRect ) { strlcat(strWhere, strRect, bufferSize); insert_and++; free(strRect); } if ( strFilter ) { if ( insert_and ) { strlcat(strWhere, " and ", bufferSize); } strlcat(strWhere, strFilter, bufferSize); free(strFilter); insert_and++; } if ( strUid ) { if ( insert_and ) { strlcat(strWhere, " and ", bufferSize); } strlcat(strWhere, strUid, bufferSize); free(strUid); insert_and++; } if ( strLimit ) { strlcat(strWhere, strLimit, bufferSize); free(strLimit); } if ( strOffset ) { strlcat(strWhere, strOffset, bufferSize); free(strOffset); } return strWhere; } /* ** msPostGISBuildSQL() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQL(layerObj *layer, rectObj *rect, long *uid) { msPostGISLayerInfo *layerinfo = 0; char *strFrom = 0; char *strItems = 0; char *strWhere = 0; char *strSQL = 0; static char *strSQLTemplate0 = "select %s from %s where %s"; static char *strSQLTemplate1 = "select %s from %s%s"; char *strSQLTemplate = 0; if (layer->debug) { msDebug("msPostGISBuildSQL called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; strItems = msPostGISBuildSQLItems(layer); if ( ! strItems ) { msSetError(MS_MISCERR, "Failed to build SQL items.", "msPostGISBuildSQL()"); return NULL; } strFrom = msPostGISBuildSQLFrom(layer, rect); if ( ! strFrom ) { msSetError(MS_MISCERR, "Failed to build SQL 'from'.", "msPostGISBuildSQL()"); return NULL; } /* If there's BOX hackery going on, we don't want to append a box index test at the end of the query, the user is going to be responsible for making things work with their hackery. */ if ( strstr(layerinfo->fromsource, BOXTOKEN) ) strWhere = msPostGISBuildSQLWhere(layer, NULL, uid); else strWhere = msPostGISBuildSQLWhere(layer, rect, uid); if ( ! strWhere ) { msSetError(MS_MISCERR, "Failed to build SQL 'where'.", "msPostGISBuildSQL()"); return NULL; } strSQLTemplate = strlen(strWhere) ? strSQLTemplate0 : strSQLTemplate1; strSQL = msSmallMalloc(strlen(strSQLTemplate) + strlen(strFrom) + strlen(strItems) + strlen(strWhere)); sprintf(strSQL, strSQLTemplate, strItems, strFrom, strWhere); if (strItems) free(strItems); if (strFrom) free(strFrom); if (strWhere) free(strWhere); return strSQL; } #define wkbstaticsize 4096 int msPostGISReadShape(layerObj *layer, shapeObj *shape) { char *wkbstr = NULL; unsigned char wkbstatic[wkbstaticsize]; unsigned char *wkb = NULL; wkbObj w; msPostGISLayerInfo *layerinfo = NULL; int result = 0; int wkbstrlen = 0; if (layer->debug) { msDebug("msPostGISReadShape called.\n"); } assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Retrieve the geometry. */ wkbstr = (char*)PQgetvalue(layerinfo->pgresult, layerinfo->rownum, layer->numitems ); wkbstrlen = PQgetlength(layerinfo->pgresult, layerinfo->rownum, layer->numitems); if ( ! wkbstr ) { msSetError(MS_QUERYERR, "Base64 WKB returned is null!", "msPostGISReadShape()"); return MS_FAILURE; } if(wkbstrlen > wkbstaticsize) { wkb = calloc(wkbstrlen, sizeof(char)); } else { wkb = wkbstatic; } #if TRANSFER_ENCODING == 64 result = msPostGISBase64Decode(wkb, wkbstr, wkbstrlen - 1); #else result = msPostGISHexDecode(wkb, wkbstr, wkbstrlen); #endif if( ! result ) { if(wkb!=wkbstatic) free(wkb); return MS_FAILURE; } /* Initialize our wkbObj */ w.wkb = (char*)wkb; w.ptr = w.wkb; w.size = (wkbstrlen - 1)/2; /* Set the type map according to what version of PostGIS we are dealing with */ if( layerinfo->version >= 20000 ) /* PostGIS 2.0+ */ w.typemap = wkb_postgis20; else w.typemap = wkb_postgis15; switch (layer->type) { case MS_LAYER_POINT: shape->type = MS_SHAPE_POINT; result = wkbConvGeometryToShape(&w, shape); break; case MS_LAYER_LINE: shape->type = MS_SHAPE_LINE; result = wkbConvGeometryToShape(&w, shape); break; case MS_LAYER_POLYGON: shape->type = MS_SHAPE_POLYGON; result = wkbConvGeometryToShape(&w, shape); break; case MS_LAYER_ANNOTATION: case MS_LAYER_QUERY: case MS_LAYER_CHART: result = msPostGISFindBestType(&w, shape); break; case MS_LAYER_RASTER: msDebug("Ignoring MS_LAYER_RASTER in msPostGISReadShape.\n"); break; case MS_LAYER_CIRCLE: msDebug("Ignoring MS_LAYER_RASTER in msPostGISReadShape.\n"); break; default: msDebug("Unsupported layer type in msPostGISReadShape()!\n"); break; } /* All done with WKB geometry, free it! */ if(wkb!=wkbstatic) free(wkb); if (result != MS_FAILURE) { int t; long uid; char *tmp; /* Found a drawable shape, so now retreive the attributes. */ shape->values = (char**) msSmallMalloc(sizeof(char*) * layer->numitems); for ( t = 0; t < layer->numitems; t++) { int size = PQgetlength(layerinfo->pgresult, layerinfo->rownum, t); char *val = (char*)PQgetvalue(layerinfo->pgresult, layerinfo->rownum, t); int isnull = PQgetisnull(layerinfo->pgresult, layerinfo->rownum, t); if ( isnull ) { shape->values[t] = msStrdup(""); } else { shape->values[t] = (char*) msSmallMalloc(size + 1); memcpy(shape->values[t], val, size); shape->values[t][size] = '\0'; /* null terminate it */ msStringTrimBlanks(shape->values[t]); } if( layer->debug > 4 ) { msDebug("msPostGISReadShape: PQgetlength = %d\n", size); } if( layer->debug > 1 ) { msDebug("msPostGISReadShape: [%s] \"%s\"\n", layer->items[t], shape->values[t]); } } /* t is the geometry, t+1 is the uid */ tmp = PQgetvalue(layerinfo->pgresult, layerinfo->rownum, t + 1); if( tmp ) { uid = strtol( tmp, NULL, 10 ); } else { uid = 0; } if( layer->debug > 4 ) { msDebug("msPostGISReadShape: Setting shape->index = %ld\n", uid); msDebug("msPostGISReadShape: Setting shape->resultindex = %ld\n", layerinfo->rownum); } shape->index = uid; shape->resultindex = layerinfo->rownum; if( layer->debug > 2 ) { msDebug("msPostGISReadShape: [index] %ld\n", shape->index); } shape->numvalues = layer->numitems; msComputeBounds(shape); } if( layer->debug > 2 ) { char *tmp = msShapeToWKT(shape); msDebug("msPostGISReadShape: [shape] %s\n", tmp); free(tmp); } return MS_SUCCESS; } #endif /* USE_POSTGIS */ /* ** msPostGISLayerOpen() ** ** Registered vtable->LayerOpen function. */ int msPostGISLayerOpen(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo; int order_test = 1; const char* force2d_processing; assert(layer != NULL); if (layer->debug) { msDebug("msPostGISLayerOpen called: %s\n", layer->data); } if (layer->layerinfo) { if (layer->debug) { msDebug("msPostGISLayerOpen: Layer is already open!\n"); } return MS_SUCCESS; /* already open */ } if (!layer->data) { msSetError(MS_QUERYERR, "Nothing specified in DATA statement.", "msPostGISLayerOpen()"); return MS_FAILURE; } /* ** Initialize the layerinfo **/ layerinfo = msPostGISCreateLayerInfo(); if (((char*) &order_test)[0] == 1) { layerinfo->endian = LITTLE_ENDIAN; } else { layerinfo->endian = BIG_ENDIAN; } /* ** Get a database connection from the pool. */ layerinfo->pgconn = (PGconn *) msConnPoolRequest(layer); /* No connection in the pool, so set one up. */ if (!layerinfo->pgconn) { char *conn_decrypted; if (layer->debug) { msDebug("msPostGISLayerOpen: No connection in pool, creating a fresh one.\n"); } if (!layer->connection) { msSetError(MS_MISCERR, "Missing CONNECTION keyword.", "msPostGISLayerOpen()"); return MS_FAILURE; } /* ** Decrypt any encrypted token in connection string and attempt to connect. */ conn_decrypted = msDecryptStringTokens(layer->map, layer->connection); if (conn_decrypted == NULL) { return MS_FAILURE; /* An error should already have been produced */ } layerinfo->pgconn = PQconnectdb(conn_decrypted); msFree(conn_decrypted); conn_decrypted = NULL; /* ** Connection failed, return error message with passwords ***ed out. */ if (!layerinfo->pgconn || PQstatus(layerinfo->pgconn) == CONNECTION_BAD) { char *index, *maskeddata; if (layer->debug) msDebug("msPostGISLayerOpen: Connection failure.\n"); maskeddata = msStrdup(layer->connection); index = strstr(maskeddata, "password="); if (index != NULL) { index = (char*)(index + 9); while (*index != '\0' && *index != ' ') { *index = '*'; index++; } } msSetError(MS_QUERYERR, "Database connection failed (%s) with connect string '%s'\nIs the database running? Is it allowing connections? Does the specified user exist? Is the password valid? Is the database on the standard port?", "msPostGISLayerOpen()", PQerrorMessage(layerinfo->pgconn), maskeddata); free(maskeddata); free(layerinfo); return MS_FAILURE; } /* Register to receive notifications from the database. */ PQsetNoticeProcessor(layerinfo->pgconn, postresqlNoticeHandler, (void *) layer); /* Save this connection in the pool for later. */ msConnPoolRegister(layer, layerinfo->pgconn, msPostGISCloseConnection); } else { /* Connection in the pool should be tested to see if backend is alive. */ if( PQstatus(layerinfo->pgconn) != CONNECTION_OK ) { /* Uh oh, bad connection. Can we reset it? */ PQreset(layerinfo->pgconn); if( PQstatus(layerinfo->pgconn) != CONNECTION_OK ) { /* Nope, time to bail out. */ msSetError(MS_QUERYERR, "PostgreSQL database connection gone bad (%s)", "msPostGISLayerOpen()", PQerrorMessage(layerinfo->pgconn)); return MS_FAILURE; } } } /* Get the PostGIS version number from the database */ layerinfo->version = msPostGISRetrieveVersion(layerinfo->pgconn); if( layerinfo->version == MS_FAILURE ) return MS_FAILURE; if (layer->debug) msDebug("msPostGISLayerOpen: Got PostGIS version %d.\n", layerinfo->version); force2d_processing = msLayerGetProcessingKey( layer, "FORCE2D" ); if(force2d_processing && !strcasecmp(force2d_processing,"no")) { layerinfo->force2d = MS_FALSE; } if (layer->debug) msDebug("msPostGISLayerOpen: Forcing 2D geometries: %s.\n", (layerinfo->force2d)?"yes":"no"); /* Save the layerinfo in the layerObj. */ layer->layerinfo = (void*)layerinfo; return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerOpen()"); return MS_FAILURE; #endif } /* ** msPostGISLayerClose() ** ** Registered vtable->LayerClose function. */ int msPostGISLayerClose(layerObj *layer) { #ifdef USE_POSTGIS if (layer->debug) { msDebug("msPostGISLayerClose called: %s\n", layer->data); } if( layer->layerinfo ) { msPostGISFreeLayerInfo(layer); } return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerClose()"); return MS_FAILURE; #endif } /* ** msPostGISLayerIsOpen() ** ** Registered vtable->LayerIsOpen function. */ int msPostGISLayerIsOpen(layerObj *layer) { #ifdef USE_POSTGIS if (layer->debug) { msDebug("msPostGISLayerIsOpen called.\n"); } if (layer->layerinfo) return MS_TRUE; else return MS_FALSE; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerIsOpen()"); return MS_FAILURE; #endif } /* ** msPostGISLayerFreeItemInfo() ** ** Registered vtable->LayerFreeItemInfo function. */ void msPostGISLayerFreeItemInfo(layerObj *layer) { #ifdef USE_POSTGIS if (layer->debug) { msDebug("msPostGISLayerFreeItemInfo called.\n"); } if (layer->iteminfo) { free(layer->iteminfo); } layer->iteminfo = NULL; #endif } /* ** msPostGISLayerInitItemInfo() ** ** Registered vtable->LayerInitItemInfo function. ** Our iteminfo is list of indexes from 1..numitems. */ int msPostGISLayerInitItemInfo(layerObj *layer) { #ifdef USE_POSTGIS int i; int *itemindexes ; if (layer->debug) { msDebug("msPostGISLayerInitItemInfo called.\n"); } if (layer->numitems == 0) { return MS_SUCCESS; } if (layer->iteminfo) { free(layer->iteminfo); } layer->iteminfo = msSmallMalloc(sizeof(int) * layer->numitems); if (!layer->iteminfo) { msSetError(MS_MEMERR, "Out of memory.", "msPostGISLayerInitItemInfo()"); return MS_FAILURE; } itemindexes = (int*)layer->iteminfo; for (i = 0; i < layer->numitems; i++) { itemindexes[i] = i; /* Last item is always the geometry. The rest are non-geometry. */ } return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerInitItemInfo()"); return MS_FAILURE; #endif } /* ** msPostGISLayerWhichShapes() ** ** Registered vtable->LayerWhichShapes function. */ int msPostGISLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; char *strSQL = NULL; PGresult *pgresult = NULL; char** layer_bind_values = (char**)msSmallMalloc(sizeof(char*) * 1000); char* bind_value; char* bind_key = (char*)msSmallMalloc(3); int num_bind_values = 0; /* try to get the first bind value */ bind_value = msLookupHashTable(&layer->bindvals, "1"); while(bind_value != NULL) { /* put the bind value on the stack */ layer_bind_values[num_bind_values] = bind_value; /* increment the counter */ num_bind_values++; /* create a new lookup key */ sprintf(bind_key, "%d", num_bind_values+1); /* get the bind_value */ bind_value = msLookupHashTable(&layer->bindvals, bind_key); } assert(layer != NULL); assert(layer->layerinfo != NULL); if (layer->debug) { msDebug("msPostGISLayerWhichShapes called.\n"); } /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } /* ** This comes *after* parsedata, because parsedata fills in ** layer->layerinfo. */ layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Build a SQL query based on our current state. */ strSQL = msPostGISBuildSQL(layer, &rect, NULL); if ( ! strSQL ) { msSetError(MS_QUERYERR, "Failed to build query SQL.", "msPostGISLayerWhichShapes()"); return MS_FAILURE; } if (layer->debug) { msDebug("msPostGISLayerWhichShapes query: %s\n", strSQL); } if(num_bind_values > 0) { pgresult = PQexecParams(layerinfo->pgconn, strSQL, num_bind_values, NULL, (const char**)layer_bind_values, NULL, NULL, 1); } else { pgresult = PQexecParams(layerinfo->pgconn, strSQL,0, NULL, NULL, NULL, NULL, 0); } /* free bind values */ free(bind_key); free(layer_bind_values); if ( layer->debug > 1 ) { msDebug("msPostGISLayerWhichShapes query status: %s (%d)\n", PQresStatus(PQresultStatus(pgresult)), PQresultStatus(pgresult)); } /* Something went wrong. */ if (!pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { if ( layer->debug ) { msDebug("msPostGISLayerWhichShapes(): Error (%s) executing query: %s\n", PQerrorMessage(layerinfo->pgconn), strSQL); } msSetError(MS_QUERYERR, "Error executing query: %s ", "msPostGISLayerWhichShapes()", PQerrorMessage(layerinfo->pgconn)); free(strSQL); if (pgresult) { PQclear(pgresult); } return MS_FAILURE; } if ( layer->debug ) { msDebug("msPostGISLayerWhichShapes got %d records in result.\n", PQntuples(pgresult)); } /* Clean any existing pgresult before storing current one. */ if(layerinfo->pgresult) PQclear(layerinfo->pgresult); layerinfo->pgresult = pgresult; /* Clean any existing SQL before storing current. */ if(layerinfo->sql) free(layerinfo->sql); layerinfo->sql = strSQL; layerinfo->rownum = 0; return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerWhichShapes()"); return MS_FAILURE; #endif } /* ** msPostGISLayerNextShape() ** ** Registered vtable->LayerNextShape function. */ int msPostGISLayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo; if (layer->debug) { msDebug("msPostGISLayerNextShape called.\n"); } assert(layer != NULL); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*) layer->layerinfo; shape->type = MS_SHAPE_NULL; /* ** Roll through pgresult until we hit non-null shape (usually right away). */ while (shape->type == MS_SHAPE_NULL) { if (layerinfo->rownum < PQntuples(layerinfo->pgresult)) { /* Retrieve this shape, cursor access mode. */ msPostGISReadShape(layer, shape); if( shape->type != MS_SHAPE_NULL ) { (layerinfo->rownum)++; /* move to next shape */ return MS_SUCCESS; } else { (layerinfo->rownum)++; /* move to next shape */ } } else { return MS_DONE; } } /* Found nothing, clean up and exit. */ msFreeShape(shape); return MS_FAILURE; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerNextShape()"); return MS_FAILURE; #endif } /* ** msPostGISLayerGetShape() ** ** Registered vtable->LayerGetShape function. For pulling from a prepared and ** undisposed result set. */ int msPostGISLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifdef USE_POSTGIS PGresult *pgresult = NULL; msPostGISLayerInfo *layerinfo = NULL; long shapeindex = record->shapeindex; int resultindex = record->resultindex; assert(layer != NULL); assert(layer->layerinfo != NULL); if (layer->debug) { msDebug("msPostGISLayerGetShape called for record = %i\n", resultindex); } /* If resultindex is set, fetch the shape from the resultcache, otherwise fetch it from the DB */ if (resultindex >= 0) { int status; layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Check the validity of the open result. */ pgresult = layerinfo->pgresult; if ( ! pgresult ) { msSetError( MS_MISCERR, "PostgreSQL result set is null.", "msPostGISLayerGetShape()"); return MS_FAILURE; } status = PQresultStatus(pgresult); if ( layer->debug > 1 ) { msDebug("msPostGISLayerGetShape query status: %s (%d)\n", PQresStatus(status), status); } if( ! ( status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) ) { msSetError( MS_MISCERR, "PostgreSQL result set is not ready.", "msPostGISLayerGetShape()"); return MS_FAILURE; } /* Check the validity of the requested record number. */ if( resultindex >= PQntuples(pgresult) ) { msDebug("msPostGISLayerGetShape got request for (%d) but only has %d tuples.\n", resultindex, PQntuples(pgresult)); msSetError( MS_MISCERR, "Got request larger than result set.", "msPostGISLayerGetShape()"); return MS_FAILURE; } layerinfo->rownum = resultindex; /* Only return one result. */ /* We don't know the shape type until we read the geometry. */ shape->type = MS_SHAPE_NULL; /* Return the shape, cursor access mode. */ msPostGISReadShape(layer, shape); return (shape->type == MS_SHAPE_NULL) ? MS_FAILURE : MS_SUCCESS; } else { /* no resultindex, fetch the shape from the DB */ int num_tuples; char *strSQL = 0; /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } /* ** This comes *after* parsedata, because parsedata fills in ** layer->layerinfo. */ layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Build a SQL query based on our current state. */ strSQL = msPostGISBuildSQL(layer, 0, &shapeindex); if ( ! strSQL ) { msSetError(MS_QUERYERR, "Failed to build query SQL.", "msPostGISLayerGetShape()"); return MS_FAILURE; } if (layer->debug) { msDebug("msPostGISLayerGetShape query: %s\n", strSQL); } pgresult = PQexecParams(layerinfo->pgconn, strSQL,0, NULL, NULL, NULL, NULL, 0); /* Something went wrong. */ if ( (!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK) ) { if ( layer->debug ) { msDebug("msPostGISLayerGetShape(): Error (%s) executing SQL: %s\n", PQerrorMessage(layerinfo->pgconn), strSQL ); } msSetError(MS_QUERYERR, "Error executing SQL: %s", "msPostGISLayerGetShape()", PQerrorMessage(layerinfo->pgconn)); if (pgresult) { PQclear(pgresult); } free(strSQL); return MS_FAILURE; } /* Clean any existing pgresult before storing current one. */ if(layerinfo->pgresult) PQclear(layerinfo->pgresult); layerinfo->pgresult = pgresult; /* Clean any existing SQL before storing current. */ if(layerinfo->sql) free(layerinfo->sql); layerinfo->sql = strSQL; layerinfo->rownum = 0; /* Only return one result. */ /* We don't know the shape type until we read the geometry. */ shape->type = MS_SHAPE_NULL; num_tuples = PQntuples(pgresult); if (layer->debug) { msDebug("msPostGISLayerGetShape number of records: %d\n", num_tuples); } if (num_tuples > 0) { /* Get shape in random access mode. */ msPostGISReadShape(layer, shape); } return (shape->type == MS_SHAPE_NULL) ? MS_FAILURE : ( (num_tuples > 0) ? MS_SUCCESS : MS_DONE ); } #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetShape()"); return MS_FAILURE; #endif } /********************************************************************** * msPostGISPassThroughFieldDefinitions() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ /* These are the OIDs for some builtin types, as returned by PQftype(). */ /* They were copied from pg_type.h in src/include/catalog/pg_type.h */ #ifndef BOOLOID #define BOOLOID 16 #define BYTEAOID 17 #define CHAROID 18 #define NAMEOID 19 #define INT8OID 20 #define INT2OID 21 #define INT2VECTOROID 22 #define INT4OID 23 #define REGPROCOID 24 #define TEXTOID 25 #define OIDOID 26 #define TIDOID 27 #define XIDOID 28 #define CIDOID 29 #define OIDVECTOROID 30 #define FLOAT4OID 700 #define FLOAT8OID 701 #define INT4ARRAYOID 1007 #define TEXTARRAYOID 1009 #define BPCHARARRAYOID 1014 #define VARCHARARRAYOID 1015 #define FLOAT4ARRAYOID 1021 #define FLOAT8ARRAYOID 1022 #define BPCHAROID 1042 #define VARCHAROID 1043 #define DATEOID 1082 #define TIMEOID 1083 #define TIMESTAMPOID 1114 #define TIMESTAMPTZOID 1184 #define NUMERICOID 1700 #endif #ifdef USE_POSTGIS static void msPostGISPassThroughFieldDefinitions( layerObj *layer, PGresult *pgresult ) { int i, numitems = PQnfields(pgresult); msPostGISLayerInfo *layerinfo = layer->layerinfo; for(i=0; igeomcolumn) == 0 ) continue; oid = PQftype(pgresult,i); fmod = PQfmod(pgresult,i); if( (oid == BPCHAROID || oid == VARCHAROID) && fmod >= 4 ) { sprintf( gml_width, "%d", fmod-4 ); } else if( oid == BOOLOID ) { gml_type = "Integer"; sprintf( gml_width, "%d", 1 ); } else if( oid == INT2OID ) { gml_type = "Integer"; sprintf( gml_width, "%d", 5 ); } else if( oid == INT4OID || oid == INT8OID ) { gml_type = "Integer"; } else if( oid == FLOAT4OID || oid == FLOAT8OID ) { gml_type = "Real"; } else if( oid == NUMERICOID ) { gml_type = "Real"; if( fmod >= 4 && ((fmod - 4) & 0xFFFF) == 0 ) { gml_type = "Integer"; sprintf( gml_width, "%d", (fmod - 4) >> 16 ); } else if( fmod >= 4 ) { sprintf( gml_width, "%d", (fmod - 4) >> 16 ); sprintf( gml_precision, "%d", ((fmod-4) & 0xFFFF) ); } } else if( oid == DATEOID || oid == TIMESTAMPOID || oid == TIMESTAMPTZOID ) { gml_type = "Date"; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } } #endif /* defined(USE_POSTGIS) */ /* ** msPostGISLayerGetItems() ** ** Registered vtable->LayerGetItems function. Query the database for ** column information about the requested layer. Rather than look in ** system tables, we just run a zero-cost query and read out of the ** result header. */ int msPostGISLayerGetItems(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; static char *strSQLTemplate = "select * from %s where false limit 0"; PGresult *pgresult = NULL; char *col = NULL; char *sql = NULL; char *strFrom = NULL; char found_geom = 0; const char *value; int t, item_num; rectObj rect; /* A useless rectangle for our useless query */ rect.minx = rect.miny = rect.maxx = rect.maxy = 0.0; assert(layer != NULL); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*) layer->layerinfo; assert(layerinfo->pgconn); if (layer->debug) { msDebug("msPostGISLayerGetItems called.\n"); } /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* This allocates a fresh string, so remember to free it... */ strFrom = msPostGISReplaceBoxToken(layer, &rect, layerinfo->fromsource); /* ** Both the "table" and "(select ...) as sub" cases can be handled with the ** same SQL. */ sql = (char*) msSmallMalloc(strlen(strSQLTemplate) + strlen(strFrom)); sprintf(sql, strSQLTemplate, strFrom); free(strFrom); if (layer->debug) { msDebug("msPostGISLayerGetItems executing SQL: %s\n", sql); } pgresult = PQexecParams(layerinfo->pgconn, sql,0, NULL, NULL, NULL, NULL, 0); if ( (!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK) ) { if ( layer->debug ) { msDebug("msPostGISLayerGetItems(): Error (%s) executing SQL: %s\n", PQerrorMessage(layerinfo->pgconn), sql); } msSetError(MS_QUERYERR, "Error executing SQL: %s", "msPostGISLayerGetItems()", PQerrorMessage(layerinfo->pgconn)); if (pgresult) { PQclear(pgresult); } free(sql); return MS_FAILURE; } free(sql); layer->numitems = PQnfields(pgresult) - 1; /* dont include the geometry column (last entry)*/ layer->items = msSmallMalloc(sizeof(char*) * (layer->numitems + 1)); /* +1 in case there is a problem finding geometry column */ found_geom = 0; /* havent found the geom field */ item_num = 0; for (t = 0; t < PQnfields(pgresult); t++) { col = PQfname(pgresult, t); if ( strcmp(col, layerinfo->geomcolumn) != 0 ) { /* this isnt the geometry column */ layer->items[item_num] = msStrdup(col); item_num++; } else { found_geom = 1; } } /* ** consider populating the field definitions in metadata. */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msPostGISPassThroughFieldDefinitions( layer, pgresult ); /* ** Cleanup */ PQclear(pgresult); if (!found_geom) { msSetError(MS_QUERYERR, "Tried to find the geometry column in the database, but couldn't find it. Is it mis-capitalized? '%s'", "msPostGISLayerGetItems()", layerinfo->geomcolumn); return MS_FAILURE; } return msPostGISLayerInitItemInfo(layer); #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetItems()"); return MS_FAILURE; #endif } /* * make sure that the timestring is complete and acceptable * to the date_trunc function : * - if the resolution is year (2004) or month (2004-01), * a complete string for time would be 2004-01-01 * - if the resolluion is hour or minute (2004-01-01 15), a * complete time is 2004-01-01 15:00:00 */ int postgresTimeStampForTimeString(const char *timestring, char *dest, size_t destsize) { int nlength = strlen(timestring); int timeresolution = msTimeGetResolution(timestring); int bNoDate = (*timestring == 'T'); if (timeresolution < 0) return MS_FALSE; switch(timeresolution) { case TIME_RESOLUTION_YEAR: if (timestring[nlength-1] != '-') { snprintf(dest, destsize,"date '%s-01-01'",timestring); } else { snprintf(dest, destsize,"date '%s01-01'",timestring); } break; case TIME_RESOLUTION_MONTH: if (timestring[nlength-1] != '-') { snprintf(dest, destsize,"date '%s-01'",timestring); } else { snprintf(dest, destsize,"date '%s01'",timestring); } break; case TIME_RESOLUTION_DAY: snprintf(dest, destsize,"date '%s'",timestring); break; case TIME_RESOLUTION_HOUR: if (timestring[nlength-1] != ':') { if(bNoDate) snprintf(dest, destsize,"time '%s:00:00'", timestring); else snprintf(dest, destsize,"timestamp '%s:00:00'", timestring); } else { if(bNoDate) snprintf(dest, destsize,"time '%s00:00'", timestring); else snprintf(dest, destsize,"timestamp '%s00:00'", timestring); } break; case TIME_RESOLUTION_MINUTE: if (timestring[nlength-1] != ':') { if(bNoDate) snprintf(dest, destsize,"time '%s:00'", timestring); else snprintf(dest, destsize,"timestamp '%s:00'", timestring); } else { if(bNoDate) snprintf(dest, destsize,"time '%s00'", timestring); else snprintf(dest, destsize,"timestamp '%s00'", timestring); } break; case TIME_RESOLUTION_SECOND: if(bNoDate) snprintf(dest, destsize,"time '%s'", timestring); else snprintf(dest, destsize,"timestamp '%s'", timestring); break; default: return MS_FAILURE; } return MS_SUCCESS; } /* * create a postgresql where clause for the given timestring, taking into account * the resolution (e.g. second, day, month...) of the given timestring * we apply the date_trunc function on the given timestring and not on the time * column in order for postgres to take advantage of an eventual index on the * time column * * the generated sql is * * ( * timecol >= date_trunc(timestring,resolution) * and * timecol < date_trunc(timestring,resolution) + interval '1 resolution' * ) */ int createPostgresTimeCompareSimple(const char *timecol, const char *timestring, char *dest, size_t destsize) { int timeresolution = msTimeGetResolution(timestring); char timeStamp[100]; char *interval; if (timeresolution < 0) return MS_FALSE; postgresTimeStampForTimeString(timestring,timeStamp,100); switch(timeresolution) { case TIME_RESOLUTION_YEAR: interval = "year"; break; case TIME_RESOLUTION_MONTH: interval = "month"; break; case TIME_RESOLUTION_DAY: interval = "day"; break; case TIME_RESOLUTION_HOUR: interval = "hour"; break; case TIME_RESOLUTION_MINUTE: interval = "minute"; break; case TIME_RESOLUTION_SECOND: interval = "second"; break; default: return MS_FAILURE; } snprintf(dest, destsize,"(%s >= date_trunc('%s',%s) and %s < date_trunc('%s',%s) + interval '1 %s')", timecol, interval, timeStamp, timecol, interval, timeStamp, interval); return MS_SUCCESS; } /* * create a postgresql where clause for the range given by the two input timestring, * taking into account the resolution (e.g. second, day, month...) of each of the * given timestrings (both timestrings can have different resolutions, although I don't * know if that's a valid TIME range * we apply the date_trunc function on the given timestrings and not on the time * column in order for postgres to take advantage of an eventual index on the * time column * * the generated sql is * * ( * timecol >= date_trunc(mintimestring,minresolution) * and * timecol < date_trunc(maxtimestring,maxresolution) + interval '1 maxresolution' * ) */ int createPostgresTimeCompareRange(const char *timecol, const char *mintime, const char *maxtime, char *dest, size_t destsize) { int mintimeresolution = msTimeGetResolution(mintime); int maxtimeresolution = msTimeGetResolution(maxtime); char minTimeStamp[100]; char maxTimeStamp[100]; char *minTimeInterval,*maxTimeInterval; if (mintimeresolution < 0 || maxtimeresolution < 0) return MS_FALSE; postgresTimeStampForTimeString(mintime,minTimeStamp,100); postgresTimeStampForTimeString(maxtime,maxTimeStamp,100); switch(maxtimeresolution) { case TIME_RESOLUTION_YEAR: maxTimeInterval = "year"; break; case TIME_RESOLUTION_MONTH: maxTimeInterval = "month"; break; case TIME_RESOLUTION_DAY: maxTimeInterval = "day"; break; case TIME_RESOLUTION_HOUR: maxTimeInterval = "hour"; break; case TIME_RESOLUTION_MINUTE: maxTimeInterval = "minute"; break; case TIME_RESOLUTION_SECOND: maxTimeInterval = "second"; break; default: return MS_FAILURE; } switch(mintimeresolution) { case TIME_RESOLUTION_YEAR: minTimeInterval = "year"; break; case TIME_RESOLUTION_MONTH: minTimeInterval = "month"; break; case TIME_RESOLUTION_DAY: minTimeInterval = "day"; break; case TIME_RESOLUTION_HOUR: minTimeInterval = "hour"; break; case TIME_RESOLUTION_MINUTE: minTimeInterval = "minute"; break; case TIME_RESOLUTION_SECOND: minTimeInterval = "second"; break; default: return MS_FAILURE; } snprintf(dest, destsize,"(%s >= date_trunc('%s',%s) and %s < date_trunc('%s',%s) + interval '1 %s')", timecol, minTimeInterval, minTimeStamp, timecol, maxTimeInterval, maxTimeStamp, maxTimeInterval); return MS_SUCCESS; } int msPostGISLayerSetTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { char **atimes, **aranges = NULL; int numtimes=0,i=0,numranges=0; size_t buffer_size = 512; char buffer[512], bufferTmp[512]; buffer[0] = '\0'; bufferTmp[0] = '\0'; if (!lp || !timestring || !timefield) return MS_FALSE; if( strchr(timestring,'\'') || strchr(timestring, '\\') ) { msSetError(MS_MISCERR, "Invalid time filter.", "msPostGISLayerSetTimeFilter()"); return MS_FALSE; } /* discrete time */ if (strstr(timestring, ",") == NULL && strstr(timestring, "/") == NULL) { /* discrete time */ createPostgresTimeCompareSimple(timefield, timestring, buffer, buffer_size); } else { /* multiple times, or ranges */ atimes = msStringSplit (timestring, ',', &numtimes); if (atimes == NULL || numtimes < 1) return MS_FALSE; strlcat(buffer, "(", buffer_size); for(i=0; ifilteritem) free(lp->filteritem); lp->filteritem = msStrdup(timefield); if (&lp->filter) { /* if the filter is set and it's a string type, concatenate it with the time. If not just free it */ if (lp->filter.type == MS_EXPRESSION) { snprintf(bufferTmp, buffer_size, "(%s) and %s", lp->filter.string, buffer); loadExpressionString(&lp->filter, bufferTmp); } else { freeExpression(&lp->filter); loadExpressionString(&lp->filter, buffer); } } return MS_TRUE; } char *msPostGISEscapeSQLParam(layerObj *layer, const char *pszString) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; int nError; size_t nSrcLen; char* pszEscapedStr =NULL; if (layer && pszString && strlen(pszString) > 0) { if(!msPostGISLayerIsOpen(layer)) msPostGISLayerOpen(layer); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *) layer->layerinfo; nSrcLen = strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 2 * nSrcLen + 1); PQescapeStringConn (layerinfo->pgconn, pszEscapedStr, pszString, nSrcLen, &nError); if (nError != 0) { free(pszEscapedStr); pszEscapedStr = NULL; } } return pszEscapedStr; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISEscapeSQLParam()"); return NULL; #endif } void msPostGISEnablePaging(layerObj *layer, int value) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISEnablePaging called.\n"); } if(!msPostGISLayerIsOpen(layer)) msPostGISLayerOpen(layer); assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; layerinfo->paging = value; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISEnablePaging()"); #endif return; } int msPostGISGetPaging(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISGetPaging called.\n"); } if(!msPostGISLayerIsOpen(layer)) return MS_TRUE; assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; return layerinfo->paging; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISEnablePaging()"); return MS_FAILURE; #endif } int msPostGISLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msPostGISLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msPostGISLayerFreeItemInfo; layer->vtable->LayerOpen = msPostGISLayerOpen; layer->vtable->LayerIsOpen = msPostGISLayerIsOpen; layer->vtable->LayerWhichShapes = msPostGISLayerWhichShapes; layer->vtable->LayerNextShape = msPostGISLayerNextShape; layer->vtable->LayerGetShape = msPostGISLayerGetShape; layer->vtable->LayerClose = msPostGISLayerClose; layer->vtable->LayerGetItems = msPostGISLayerGetItems; /* layer->vtable->LayerGetExtent = msPostGISLayerGetExtent; */ layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; /* layer->vtable->LayerGetAutoStyle, not supported for this layer */ /* layer->vtable->LayerCloseConnection = msPostGISLayerClose; */ layer->vtable->LayerSetTimeFilter = msPostGISLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection, use defaut*/ layer->vtable->LayerEscapeSQLParam = msPostGISEscapeSQLParam; layer->vtable->LayerEnablePaging = msPostGISEnablePaging; layer->vtable->LayerGetPaging = msPostGISGetPaging; return MS_SUCCESS; } mapserver-6.4.1/maphash.h0000644002461700001440000001165212261257215015113 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations for the hashTableObj and related stuff. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 1996-2005 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 MAPHASH__H #define MAPHASH__H #ifdef __cplusplus extern "C" { #endif #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #else #define MS_DLL_EXPORT #endif #define MS_HASHSIZE 41 /* ========================================================================= * Structs * ========================================================================= */ #ifndef SWIG struct hashObj { struct hashObj *next; /* pointer to next item */ char *key; /* string key that is hashed */ char *data; /* string stored in this item */ }; #endif /*SWIG*/ typedef struct { #ifndef SWIG struct hashObj **items; /* the hash table */ #endif #ifdef SWIG %immutable; #endif /*SWIG*/ int numitems; /* number of items */ #ifdef SWIG %mutable; #endif /*SWIG*/ } hashTableObj; /* ========================================================================= * Functions * ========================================================================= */ #ifndef SWIG /* msCreateHashTable - create a hash table * ARGS: * None * RETURNS: * New hash table */ MS_DLL_EXPORT hashTableObj *msCreateHashTable( void ); /* For use in mapfile.c with hashTableObj structure members */ MS_DLL_EXPORT int initHashTable( hashTableObj *table ); /* msFreeHashTable - free allocated memory * ARGS: * table - target hash table * RETURNS: * None */ MS_DLL_EXPORT void msFreeHashTable( hashTableObj *table ); /* Free only the items for hashTableObj structure members (metadata, &c) */ MS_DLL_EXPORT void msFreeHashItems( hashTableObj *table ); /* msInsertHashTable - insert new item * ARGS: * table - the target hash table * key - key string for new item * value - data string for new item * RETURNS: * pointer to the new item or NULL * EXCEPTIONS: * raise MS_HASHERR on failure */ MS_DLL_EXPORT struct hashObj *msInsertHashTable( hashTableObj *table, const char *key, const char *value ); /* msLookupHashTable - get the value of an item by its key * ARGS: * table - the target hash table * key - key string of item * RETURNS: * string value of item */ MS_DLL_EXPORT char *msLookupHashTable( hashTableObj *table, const char *key); /* msRemoveHashTable - remove item from table at key * ARGS: * table - target hash table * key - key string * RETURNS: * MS_SUCCESS or MS_FAILURE */ MS_DLL_EXPORT int msRemoveHashTable( hashTableObj *table, const char *key); /* msFirstKeyFromHashTable - get key of first item * ARGS: * table - target hash table * RETURNS: * first key as a string */ MS_DLL_EXPORT const char *msFirstKeyFromHashTable( hashTableObj *table ); /* msNextKeyFromHashTable - get next key * ARGS: * table - target hash table * prevkey - the previous key * RETURNS: * the key of the item of following prevkey as a string */ MS_DLL_EXPORT const char *msNextKeyFromHashTable( hashTableObj *table, const char *prevkey ); /* msHashIsEmpty - get next key * ARGS: * table - target hash table * RETURNS: * MS_TRUE if the table is empty and MS_FALSE if the table has items */ MS_DLL_EXPORT int msHashIsEmpty( hashTableObj* table ); #endif /*SWIG*/ #ifdef __cplusplus } #endif #endif /* MAPHASH__H */ mapserver-6.4.1/mapkmlrenderer.h0000644002461700001440000001413512261257215016501 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Headers for mapkmlrenderer.cpp Google Earth KML output * Author: David Kana and the MapServer team * ****************************************************************************** * Copyright (c) 1996-2009 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 MAPKMLRENDERER_H #define MAPKMLRENDERER_H #include "mapserver-config.h" #if defined(USE_KML) #include "mapserver.h" #include "maplibxml2.h" class KmlRenderer { private: const char *pszLayerDescMetadata; /*if the kml_description is set*/ char **papszLayerIncludeItems; int nIncludeItems; char **papszLayerExcludeItems; int nExcludeItems; char *pszLayerNameAttributeMetadata; protected: // map properties int Width, Height; rectObj MapExtent; double MapCellsize; colorObj BgColor; char MapPath[MS_MAXPATHLEN]; // xml nodes pointers xmlDocPtr XmlDoc; xmlNodePtr DocNode; xmlNodePtr LayerNode; xmlNodePtr GroundOverlayNode; xmlNodePtr PlacemarkNode; xmlNodePtr GeomNode; xmlNodePtr DescriptionNode; int CurrentShapeIndex; int CurrentDrawnShapeIndex; char *CurrentShapeName; char **Items; int NumItems; int DumpAttributes; // placemark symbology hashTableObj *StyleHashTable; labelStyleObj LabelStyle; strokeStyleObj *LineStyle; int numLineStyle; colorObj PolygonColor; char SymbolName[128]; char SymbolUrl[128]; enum { NumSymbologyFlag = 4}; char SymbologyFlag[NumSymbologyFlag]; enum symbFlagsEnum { Label, Line, Polygon, Symbol }; int FirstLayer; mapObj *map; layerObj *currentLayer; int AltitudeMode; int Tessellate; int Extrude; enum altitudeModeEnum { undefined, clampToGround, relativeToGround, absolute }; /**True if elevation is taken from a feature attribute*/ bool mElevationFromAttribute; /**Attribute index of elevation (or -1 if elevation is not attribute driven*/ int mElevationAttributeIndex; double mCurrentElevationValue; outputFormatObj *aggFormat; protected: imageObj* createInternalImage(); xmlNodePtr createPlacemarkNode(xmlNodePtr parentNode, char *styleUrl); xmlNodePtr createGroundOverlayNode(xmlNodePtr parentNode, char *imageHref, layerObj *layer); xmlNodePtr createDescriptionNode(shapeObj *shape); char* lookupSymbolUrl(imageObj *img, symbolObj *symbol, symbolStyleObj *style); void addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts); void setupRenderingParams(hashTableObj *layerMetadata); void addAddRenderingSpecifications(xmlNodePtr node); int checkProjection(mapObj *map); int createIconImage(char *fileName, symbolObj *symbol, symbolStyleObj *style); void renderSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); ////////////////////////////////////////////////////////////////////////////// void renderLineVector(imageObj *img, shapeObj *p, strokeStyleObj *style); void renderPolygonVector(imageObj *img, shapeObj *p, colorObj *color); void renderGlyphsVector(imageObj *img, double x, double y, labelStyleObj *style, char *text); char* lookupPlacemarkStyle(); void flushPlacemark(); xmlNodePtr getGeomParentNode(const char *geomName); char* getLayerName(layerObj *layer); void processLayer(layerObj *layer, outputFormatObj *format); void addLineStyleToList(strokeStyleObj *style); const char *getAliasName(layerObj *lp, char *pszItemName, const char *namespaces); public: KmlRenderer(int width, int height, outputFormatObj *format, colorObj* color = NULL); virtual ~KmlRenderer(); imageObj* createImage(int width, int height, outputFormatObj *format, colorObj* bg); int saveImage(imageObj *img, FILE *fp, outputFormatObj *format); int startNewLayer(imageObj *img, layerObj *layer); int closeNewLayer(imageObj *img, layerObj *layer); void startShape(imageObj *img, shapeObj *shape); void endShape(imageObj *img, shapeObj *shape); void renderLine(imageObj *img, shapeObj *p, strokeStyleObj *style); void renderPolygon(imageObj *img, shapeObj *p, colorObj *color); void renderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text); // Symbols void renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void renderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); int getTruetypeTextBBox(imageObj *img,char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances); int mergeRasterBuffer(imageObj *image, rasterBufferObj *rb); }; #endif /* USE_KML */ #endif mapserver-6.4.1/maplegend.c0000644002461700001440000010402412261257215015415 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Legend generation. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include "mapserver.h" #define PSF .8 #define VMARGIN 5 /* margin at top and bottom of legend graphic */ #define HMARGIN 5 /* margin at left and right of legend graphic */ /* * generic function for drawing a legend icon. (added for bug #2348) * renderer specific drawing functions shouldn't be called directly, but through * this function */ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, int width, int height, imageObj *image, int dstX, int dstY, int scale_independant, class_hittest *hittest) { int i, type, hasmarkersymbol; double offset; double polygon_contraction = 0.5; /* used to account for the width of a polygon's outline */ shapeObj box, zigzag; pointObj marker; char szPath[MS_MAXPATHLEN]; styleObj outline_style; imageObj *image_draw = image; int originalopacity = lp->opacity; rendererVTableObj *renderer; outputFormatObj *transFormat = NULL, *altFormat=NULL; const char *alternativeFormatString = NULL; if(!MS_RENDERER_PLUGIN(image->format)) { msSetError(MS_MISCERR,"unsupported image format","msDrawLegendIcon()"); return MS_FAILURE; } alternativeFormatString = msLayerGetProcessingKey(lp, "RENDERER"); if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFormatString!=NULL && (altFormat= msSelectOutputFormat(map, alternativeFormatString))) { msInitializeRendererVTable(altFormat); image_draw = msImageCreate(image->width, image->height, altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor); renderer = MS_IMAGE_RENDERER(image_draw); } else { renderer = MS_IMAGE_RENDERER(image_draw); if (lp->opacity > 0 && lp->opacity < 100) { if (!renderer->supports_transparent_layers) { image_draw = msImageCreate(image->width, image->height, image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!image_draw) { msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.", "msDrawLegendIcon()"); return (MS_FAILURE); } /* set opacity to full, as the renderer should be rendering a fully opaque image */ lp->opacity=100; } } } if(renderer->supports_clipping && MS_VALID_COLOR(map->legend.outlinecolor)) { /* keep GD specific code here for now as it supports clipping */ rectObj clip; clip.maxx = dstX + width - 1; clip.maxy = dstY + height -1; clip.minx = dstX; clip.miny = dstY; renderer->setClip(image_draw,clip); } /* if the class has a keyimage, treat it as a point layer * (the keyimage will be treated there) */ if(theclass->keyimage != NULL) { type = MS_LAYER_POINT; } else { /* some polygon layers may be better drawn using zigzag if there is no fill */ type = lp->type; if(type == MS_LAYER_POLYGON) { type = MS_LAYER_LINE; for(i=0; inumstyles; i++) { if(MS_VALID_COLOR(theclass->styles[i]->color)) { /* there is a fill */ type = MS_LAYER_POLYGON; } if(MS_VALID_COLOR(theclass->styles[i]->outlinecolor)) { /* there is an outline */ polygon_contraction = MS_MAX(polygon_contraction, theclass->styles[i]->width / 2.0); } } } } /* initialize the box used for polygons and for outlines */ msInitShape(&box); box.line = (lineObj *)msSmallMalloc(sizeof(lineObj)); box.numlines = 1; box.line[0].point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5); box.line[0].numpoints = 5; box.line[0].point[0].x = dstX + polygon_contraction; box.line[0].point[0].y = dstY + polygon_contraction; box.line[0].point[1].x = dstX + width - polygon_contraction; box.line[0].point[1].y = dstY + polygon_contraction; box.line[0].point[2].x = dstX + width - polygon_contraction; box.line[0].point[2].y = dstY + height - polygon_contraction; box.line[0].point[3].x = dstX + polygon_contraction; box.line[0].point[3].y = dstY + height - polygon_contraction; box.line[0].point[4].x = box.line[0].point[0].x; box.line[0].point[4].y = box.line[0].point[0].y; box.line[0].numpoints = 5; /* ** now draw the appropriate color/symbol/size combination */ switch(type) { case MS_LAYER_ANNOTATION: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); hasmarkersymbol = 0; for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; if (theclass->styles[i]->symbol < map->symbolset.numsymbols && theclass->styles[i]->symbol > 0) { hasmarkersymbol = 1; break; } } if (hasmarkersymbol) { for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); } } else if (theclass->labels && theclass->numlabels > 0) { labelObj *label = theclass->labels[0]; /* use the first label definition */ double lsize = label->size; double langle = label->angle; int lpos = label->position; int loffsetx = label->offsetx; int loffsety = label->offsety; int lstatus = label->status; if(!hittest || hittest->labelhits[0].status == 1) { label->offsetx = 0; label->offsety = 0; label->angle = 0; label->position = MS_CC; if (label->type == MS_TRUETYPE) label->size = height; label->status = MS_ON; msDrawLabel(map, image_draw, marker, (char*)"Az", label,1.0); label->size = lsize; label->position = lpos; label->angle = langle; label->offsetx = loffsetx; label->offsety = loffsety; label->status = lstatus; } } break; case MS_LAYER_POINT: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); if(theclass->keyimage != NULL) { int symbolNum; styleObj imgStyle; symbolObj *symbol=NULL; symbolNum = msAddImageSymbol(&(map->symbolset), msBuildPath(szPath, map->mappath, theclass->keyimage)); if(symbolNum == -1) { msSetError(MS_GDERR, "Failed to open legend key image", "msCreateLegendIcon()"); return(MS_FAILURE); } symbol = map->symbolset.symbol[symbolNum]; initStyle(&imgStyle); /*set size so that symbol will be scaled properly #3296*/ if (width/symbol->sizex < height/symbol->sizey) imgStyle.size = symbol->sizey*(width/symbol->sizex); else imgStyle.size = symbol->sizey*(height/symbol->sizey); if (imgStyle.size > imgStyle.maxsize) imgStyle.maxsize = imgStyle.size; imgStyle.symbol = symbolNum; msDrawMarkerSymbol(&map->symbolset,image_draw,&marker,&imgStyle,lp->scalefactor * image_draw->resolutionfactor); /* TO DO: we may want to handle this differently depending on the relative size of the keyimage */ } else { for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); } } break; case MS_LAYER_LINE: offset = 1; /* To set the offset, we only check the size/width parameter of the first style */ if (theclass->numstyles > 0) { if (theclass->styles[0]->symbol > 0 && theclass->styles[0]->symbol < map->symbolset.numsymbols && map->symbolset.symbol[theclass->styles[0]->symbol]->type != MS_SYMBOL_SIMPLE) offset = theclass->styles[0]->size/2; else offset = theclass->styles[0]->width/2; } msInitShape(&zigzag); zigzag.line = (lineObj *)msSmallMalloc(sizeof(lineObj)); zigzag.numlines = 1; zigzag.line[0].point = (pointObj *)msSmallMalloc(sizeof(pointObj)*4); zigzag.line[0].numpoints = 4; zigzag.line[0].point[0].x = dstX + offset; zigzag.line[0].point[0].y = dstY + height - offset; zigzag.line[0].point[1].x = dstX + MS_NINT(width / 3.0) - 1; zigzag.line[0].point[1].y = dstY + offset; zigzag.line[0].point[2].x = dstX + MS_NINT(2.0 * width / 3.0) - 1; zigzag.line[0].point[2].y = dstY + height - offset; zigzag.line[0].point[3].x = dstX + width - offset; zigzag.line[0].point[3].y = dstY + offset; for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) msDrawLineSymbol(&map->symbolset, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); else msDrawTransformedShape(map, &map->symbolset, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); } free(zigzag.line[0].point); free(zigzag.line); break; case MS_LAYER_CIRCLE: case MS_LAYER_RASTER: case MS_LAYER_CHART: case MS_LAYER_POLYGON: for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) msDrawShadeSymbol(&map->symbolset, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); else msDrawTransformedShape(map, &map->symbolset, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); } break; default: return MS_FAILURE; break; } /* end symbol drawing */ /* handle an outline if necessary */ if(MS_VALID_COLOR(map->legend.outlinecolor)) { initStyle(&outline_style); outline_style.color = map->legend.outlinecolor; msDrawLineSymbol(&map->symbolset, image_draw, &box, &outline_style, 1.0 * image_draw->resolutionfactor); /* reset clipping rectangle */ if(renderer->supports_clipping) renderer->resetClip(image_draw); } if (altFormat) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rendererVTableObj *altrenderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); altrenderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height); /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == altrenderer) { altrenderer->freeSymbol(s); s->renderer = NULL; } } } msFreeImage(image_draw); } else if(image != image_draw) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); lp->opacity = originalopacity; renderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height); msFreeImage(image_draw); /* deref and possibly free temporary transparent output format. */ msApplyOutputFormat( &transFormat, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } free(box.line[0].point); free(box.line); return MS_SUCCESS; } imageObj *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* class, int width, int height, int scale_independant) { imageObj *image; outputFormatObj *format = NULL; int i = 0; rendererVTableObj *renderer = MS_MAP_RENDERER(map); if( !renderer ) { msSetError(MS_MISCERR, "invalid map outputformat", "msCreateLegendIcon()"); return(NULL); } /* ensure we have an image format representing the options for the legend */ msApplyOutputFormat(&format, map->outputformat, map->legend.transparent, map->legend.interlace, MS_NOOVERRIDE); image = msImageCreate(width,height,format,map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &(map->legend.imagecolor)); /* drop this reference to output format */ msApplyOutputFormat( &format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); if(image == NULL) { msSetError(MS_GDERR, "Unable to initialize image.","msCreateLegendIcon()"); return(NULL); } /* Call drawLegendIcon with destination (0, 0) */ /* Return an empty image if lp==NULL || class=NULL */ /* (If class is NULL draw the legend for all classes. Modifications done */ /* Fev 2004 by AY) */ if (lp) { #ifdef USE_GD msClearLayerPenValues(lp); /* just in case the mapfile has already been processed */ #endif if (class) { msDrawLegendIcon(map, lp, class, width, height, image, 0, 0, scale_independant, NULL); } else { for (i=0; inumclasses; i++) { msDrawLegendIcon(map, lp, lp->class[i], width, height, image, 0, 0, scale_independant, NULL); } } } return image; } /* * Calculates the optimal size for the legend. If the optional layerObj * argument is given, the legend size will be calculated for only that * layer. Otherwise, the legend size is calculated for all layers that * are not MS_OFF or of MS_LAYER_QUERY type. * * Returns one of: * MS_SUCCESS * MS_FAILURE */ int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_y, int *layer_index, int num_layers, map_hittest *hittest, int resolutionfactor) { int i, j; int status, maxwidth=0, nLegendItems=0; char *text, *transformedText; /* legend text before/after applying wrapping, encoding if necessary */ layerObj *lp; rectObj rect; int current_layers=0; /* reset sizes */ *size_x = 0; *size_y = 0; /* enable scale-dependent calculations */ if(!scale_independent) { map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) return MS_FAILURE; } /* * step through all map classes, and for each one that will be displayed * calculate the label size */ if (layer_index != NULL && num_layers >0) current_layers = num_layers; else current_layers = map->numlayers; for(i=0; i< current_layers; i++) { int layerindex; double lsize; if (layer_index != NULL && num_layers > 0) layerindex = layer_index[i]; else layerindex = map->layerorder[i]; lp = (GET_LAYER(map, layerindex)); if((lp->status == MS_OFF && (layer_index == NULL || num_layers <= 0)) || (lp->type == MS_LAYER_QUERY)) /* skip it */ continue; if(hittest && hittest->layerhits[layerindex].status == 0) continue; if(!scale_independent && map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } for(j=lp->numclasses-1; j>=0; j--) { text = lp->class[j]->title?lp->class[j]->title:lp->class[j]->name; /* point to the right legend text, title takes precedence */ if(!text) continue; /* skip it */ /* skip the class if the classgroup is defined */ if(lp->classgroup && (lp->class[j]->group == NULL || strcasecmp(lp->class[j]->group, lp->classgroup) != 0)) continue; /* verify class scale */ if(!scale_independent && map->scaledenom > 0) { if((lp->class[j]->maxscaledenom > 0) && (map->scaledenom > lp->class[j]->maxscaledenom)) continue; if((lp->class[j]->minscaledenom > 0) && (map->scaledenom <= lp->class[j]->minscaledenom)) continue; } if(hittest && hittest->layerhits[layerindex].classhits[j].status == 0) continue; /* * apply encoding and line wrapping to the legend label if requested * this is done conditionally as the text transformation function * does some memory allocations that can be avoided in most cases. * the transformed text must be freed once finished, this must be done * conditionnally by testing if the transformed text pointer is the * same as the class name pointer */ if(map->legend.label.encoding || map->legend.label.wrap) transformedText = msTransformLabelText(map,&map->legend.label, text); else transformedText = msStrdup(text); lsize = map->legend.label.size; if(map->legend.label.type == MS_TRUETYPE) { lsize *= resolutionfactor; lsize = MS_MAX(lsize, map->legend.label.minsize*resolutionfactor); lsize = MS_MIN(lsize, map->legend.label.maxsize*resolutionfactor); } if(transformedText == NULL || msGetLabelSize(map, &map->legend.label, transformedText, lsize, &rect, NULL) != MS_SUCCESS) { /* something bad happened */ if(transformedText) msFree(transformedText); return MS_FAILURE; } msFree(transformedText); maxwidth = MS_MAX(maxwidth, MS_NINT(rect.maxx - rect.minx)); *size_y += MS_MAX(MS_NINT(rect.maxy - rect.miny), map->legend.keysizey); nLegendItems++; } } /* Calculate the size of the legend: */ /* - account for the Y keyspacing */ *size_y += (2*VMARGIN) + ((nLegendItems-1) * map->legend.keyspacingy); /* - determine the legend width */ *size_x = (2*HMARGIN) + maxwidth + map->legend.keyspacingx + map->legend.keysizex; if(*size_y <=0 || *size_x <=0) return MS_FAILURE; return MS_SUCCESS; } /* ** Creates a GD image of a legend for a specific map. msDrawLegend() ** respects the current scale, and classes without a name are not ** added to the legend. ** ** scale_independent is used for WMS GetLegendGraphic. It should be set to ** MS_FALSE in most cases. If it is set to MS_TRUE then the layers' minscale ** and maxscale are ignored and layers that are currently out of scale still ** show up in the legend. */ imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest) { int i,j; /* loop counters */ pointObj pnt; int size_x, size_y=0; layerObj *lp; rectObj rect; imageObj *image = NULL; outputFormatObj *format = NULL; char *text; struct legend_struct { int height; char *transformedText; int layerindex,classindex; struct legend_struct* pred; }; typedef struct legend_struct legendlabel; legendlabel *head=NULL,*cur=NULL; if(!MS_RENDERER_PLUGIN(map->outputformat)) { msSetError(MS_MISCERR,"unsupported output format","msDrawLegend()"); return NULL; } if(msValidateContexts(map) != MS_SUCCESS) return NULL; /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */ if(msLegendCalcSize(map, scale_independent, &size_x, &size_y, NULL, 0, hittest, map->resolution/map->defresolution) != MS_SUCCESS) return NULL; /* * step through all map classes, and for each one that will be displayed * keep a reference to its label size and text */ for(i=0; inumlayers; i++) { double lsize; lp = (GET_LAYER(map, map->layerorder[i])); if((lp->status == MS_OFF) || (lp->type == MS_LAYER_QUERY)) /* skip it */ continue; if(hittest && hittest->layerhits[map->layerorder[i]].status == 0) continue; if(!scale_independent && map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(!scale_independent && lp->maxscaledenom <=0 && lp->minscaledenom <=0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } for(j=lp->numclasses-1; j>=0; j--) { text = lp->class[j]->title?lp->class[j]->title:lp->class[j]->name; /* point to the right legend text, title takes precedence */ if(!text) continue; /* skip it */ /* skip the class if the classgroup is defined */ if(lp->classgroup && (lp->class[j]->group == NULL || strcasecmp(lp->class[j]->group, lp->classgroup) != 0)) continue; if(!scale_independent && map->scaledenom > 0) { /* verify class scale here */ if((lp->class[j]->maxscaledenom > 0) && (map->scaledenom > lp->class[j]->maxscaledenom)) continue; if((lp->class[j]->minscaledenom > 0) && (map->scaledenom <= lp->class[j]->minscaledenom)) continue; } if(hittest && hittest->layerhits[map->layerorder[i]].classhits[j].status == 0) { continue; } cur = (legendlabel*) msSmallMalloc(sizeof(legendlabel)); /* * apply encoding and line wrapping to the legend label if requested * this is done conditionnally as the text transformation function * does some memory allocations that can be avoided in most cases. * the transformed text must be freed once finished, this must be done * conditionally by testing if the transformed text pointer is the * same as the class name pointer */ if(map->legend.label.encoding || map->legend.label.wrap) cur->transformedText = msTransformLabelText(map,&map->legend.label,text); else cur->transformedText = msStrdup(text); /* so we can always do msFree() when cleaning up */ cur->classindex = j; cur->layerindex = map->layerorder[i]; cur->pred = head; head = cur; lsize = map->legend.label.size; if(map->legend.label.type == MS_TRUETYPE) { lsize *= lp->scalefactor * map->resolution/map->defresolution; lsize = MS_MAX(lsize, map->legend.label.minsize*map->resolution/map->defresolution); lsize = MS_MIN(lsize, map->legend.label.maxsize*map->resolution/map->defresolution); } if(cur->transformedText==NULL || msGetLabelSize(map, &map->legend.label, cur->transformedText, lsize, &rect, NULL) != MS_SUCCESS) { /* something bad happened, free allocated mem */ while(cur) { free(cur->transformedText); head = cur; cur = cur->pred; free(head); } return(NULL); } cur->height = MS_MAX(MS_NINT(rect.maxy - rect.miny), map->legend.keysizey); } } /* ensure we have an image format representing the options for the legend. */ msApplyOutputFormat(&format, map->outputformat, map->legend.transparent, map->legend.interlace, MS_NOOVERRIDE); /* initialize the legend image */ image = msImageCreate(size_x, size_y, format, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->legend.imagecolor); if(!image) { msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawLegend()"); return NULL; } /* image = renderer->createImage(size_x,size_y,format,&(map->legend.imagecolor)); */ /* drop this reference to output format */ msApplyOutputFormat(&format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); #ifdef USE_GD msClearPenValues(map); /* just in case the mapfile has already been processed */ #endif pnt.y = VMARGIN; pnt.x = HMARGIN + map->legend.keysizex + map->legend.keyspacingx; while(cur) { /* cur initially points on the last legend item, i.e. the one that should be at the top */ int number_of_newlines=0, offset=0; class_hittest *ch = NULL; /* set the scale factor so that scale dependant symbols are drawn in the legend with their default size */ if(map->layers[cur->layerindex]->sizeunits != MS_PIXELS) { map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); map->layers[cur->layerindex]->scalefactor = (msInchesPerUnit(map->layers[cur->layerindex]->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize; } if(hittest) { ch = &hittest->layerhits[cur->layerindex].classhits[cur->classindex]; } if(msDrawLegendIcon(map, map->layers[cur->layerindex], map->layers[cur->layerindex]->class[cur->classindex], map->legend.keysizex, map->legend.keysizey, image, HMARGIN, (int) pnt.y, scale_independent, ch) != MS_SUCCESS) return NULL; /* * adjust the baseline for multiline truetype labels. the label point is the bottom left * corner of the *first* line, which we do not know exactly as we only have the * bounding box of the whole label. current approach is to suppose that all lines * mostly have the same height, and offset the starting point by the mean hight of * one line. This isn't perfect but still much better than the previous approach */ if(map->legend.label.type==MS_TRUETYPE && (number_of_newlines=msCountChars(cur->transformedText,'\n')) > 0) { offset=cur->height/(number_of_newlines+1); pnt.y += offset; } else pnt.y += cur->height; /* TODO: note tbonfort: if this todo concerned treating the individual heights of the legend labels, then this is now done */ msDrawLabel(map, image, pnt, cur->transformedText, &(map->legend.label), 1.0 * image->resolutionfactor); if(offset) { /* if we had multiple lines, adjust the current position so it points to the bottom of the current label */ pnt.y += cur->height-offset; } pnt.y += map->legend.keyspacingy; /* bump y for next label */ /* clean up */ free(cur->transformedText); head = cur; cur = cur->pred; free(head); } /* next legend */ return(image); } /* TODO */ int msEmbedLegend(mapObj *map, imageObj *img) { int s,l; pointObj point; imageObj *image = NULL; symbolObj *legendSymbol; char* imageType = NULL; rendererVTableObj *renderer; s = msGetSymbolIndex(&(map->symbolset), "legend", MS_FALSE); if(s != -1) msRemoveSymbol(&(map->symbolset), s); /* solves some caching issues in AGG with long-running processes */ if(msGrowSymbolSet(&map->symbolset) == NULL) return -1; s = map->symbolset.numsymbols; legendSymbol = map->symbolset.symbol[s]; map->symbolset.numsymbols++; initSymbol(legendSymbol); if(!MS_RENDERER_PLUGIN(map->outputformat) || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { imageType = msStrdup(map->imagetype); /* save format */ if MS_DRIVER_CAIRO(map->outputformat) map->outputformat = msSelectOutputFormat( map, "cairopng" ); else map->outputformat = msSelectOutputFormat( map, "png" ); msInitializeRendererVTable(map->outputformat); } renderer = MS_MAP_RENDERER(map); /* render the legend. */ image = msDrawLegend(map, MS_FALSE, NULL); if( image == NULL ) return -1; if (imageType) { map->outputformat = msSelectOutputFormat( map, imageType ); /* restore format */ msFree(imageType); } /* copy renderered legend image into symbol */ legendSymbol->pixmap_buffer = calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(legendSymbol->pixmap_buffer, sizeof(rasterBufferObj), MS_FAILURE); if(MS_SUCCESS != renderer->getRasterBufferCopy(image,legendSymbol->pixmap_buffer)) return MS_FAILURE; legendSymbol->renderer = renderer; msFreeImage( image ); if(!legendSymbol->pixmap_buffer) return(-1); /* something went wrong creating scalebar */ legendSymbol->type = MS_SYMBOL_PIXMAP; /* intialize a few things */ legendSymbol->name = msStrdup("legend"); legendSymbol->sizex = legendSymbol->pixmap_buffer->width; legendSymbol->sizey = legendSymbol->pixmap_buffer->height; /* I'm not too sure this test is sufficient ... NFW. */ /* if(map->legend.transparent == MS_ON) */ /* gdImageColorTransparent(legendSymbol->img_deprecated, 0); */ switch(map->legend.position) { case(MS_LL): point.x = MS_NINT(legendSymbol->sizex/2.0); point.y = map->height - MS_NINT(legendSymbol->sizey/2.0); break; case(MS_LR): point.x = map->width - MS_NINT(legendSymbol->sizex/2.0); point.y = map->height - MS_NINT(legendSymbol->sizey/2.0); break; case(MS_LC): point.x = MS_NINT(map->width/2.0); point.y = map->height - MS_NINT(legendSymbol->sizey/2.0); break; case(MS_UR): point.x = map->width - MS_NINT(legendSymbol->sizex/2.0); point.y = MS_NINT(legendSymbol->sizey/2.0); break; case(MS_UL): point.x = MS_NINT(legendSymbol->sizex/2.0); point.y = MS_NINT(legendSymbol->sizey/2.0); break; case(MS_UC): point.x = MS_NINT(map->width/2.0); point.y = MS_NINT(legendSymbol->sizey/2.0); break; } l = msGetLayerIndex(map, "__embed__legend"); if(l == -1) { if(msGrowMapLayers(map) == NULL) return(-1); l = map->numlayers; map->numlayers++; if(initLayer((GET_LAYER(map, l)), map) == -1) return(-1); GET_LAYER(map, l)->name = msStrdup("__embed__legend"); GET_LAYER(map, l)->type = MS_LAYER_POINT; if(msGrowLayerClasses( GET_LAYER(map, l) ) == NULL) return(-1); if(initClass(GET_LAYER(map, l)->class[0]) == -1) return(-1); GET_LAYER(map, l)->numclasses = 1; /* so we make sure to free it */ /* update the layer order list with the layer's index. */ map->layerorder[l] = l; } GET_LAYER(map, l)->status = MS_ON; if(map->legend.postlabelcache) { /* add it directly to the image */ if(msMaybeAllocateClassStyle(GET_LAYER(map, l)->class[0], 0)==MS_FAILURE) return MS_FAILURE; GET_LAYER(map, l)->class[0]->styles[0]->symbol = s; msDrawMarkerSymbol(&map->symbolset, img, &point, GET_LAYER(map, l)->class[0]->styles[0], 1.0); } else { if(!GET_LAYER(map, l)->class[0]->labels) { if(msGrowClassLabels(GET_LAYER(map, l)->class[0]) == NULL) return MS_FAILURE; initLabel(GET_LAYER(map, l)->class[0]->labels[0]); GET_LAYER(map, l)->class[0]->numlabels = 1; GET_LAYER(map, l)->class[0]->labels[0]->force = MS_TRUE; GET_LAYER(map, l)->class[0]->labels[0]->size = MS_MEDIUM; /* must set a size to have a valid label definition */ GET_LAYER(map, l)->class[0]->labels[0]->priority = MS_MAX_LABEL_PRIORITY; GET_LAYER(map, l)->class[0]->labels[0]->annotext = NULL; } if(GET_LAYER(map, l)->class[0]->labels[0]->numstyles == 0) { if(msGrowLabelStyles(GET_LAYER(map,l)->class[0]->labels[0]) == NULL) return(MS_FAILURE); GET_LAYER(map,l)->class[0]->labels[0]->numstyles = 1; initStyle(GET_LAYER(map,l)->class[0]->labels[0]->styles[0]); GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; } GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->symbol = s; msAddLabel(map, GET_LAYER(map, l)->class[0]->labels[0], l, 0, NULL, &point, NULL, -1); } /* Mark layer as deleted so that it doesn't interfere with html legends or with saving maps */ GET_LAYER(map, l)->status = MS_DELETE; return(0); } mapserver-6.4.1/.travis.yml0000644002461700001440000001710212261257215015426 0ustar tbonfortuserslanguage: php php: - 5.5 env: global: # Encrypted private key of the deploy key of the github.com/mapserver/coverage.git repository - secure: "B1Tt18Q4F82+cXlj4fBoZDiyWbXLuzpJD6jt828qiS/i9ws8IEqYF7x3V4fo\nAnO1pZ84hdIOEfcSj2tFnysCPZ+zpOPzN2ma7iVEgmFTPNXf8pSx8CTXtiI/\nohUEcnARRCyuCK7cjEP5m4iWGazI+Pc563X4g67ToRPkLhIdrEg=" - secure: "OvxCriM3Dwa0wkZ+nQL8e6nuMrG2hrfET+QEPRps/fPSGSR+yRWo04hBqRn2\niBTJGpi0JvaTN0pxjCx2I/+4jbzkNt+J6IqSz2KTUzseiWA3tyAN8uel6fIo\nkS90UJ7OeKUuYkvzfVwYn6pxM6b+CN6+DTs0dlWgxyMg/AtVdz8=" - secure: "Vcf+jOzNtXapBf8qfM8N0ZTarQ9B7qqvG8X8fLJP5M2uDO2BrruMIZPpxwcL\nGMBkkZZGuofeqOs+BNxwnO1l4YOC+JUzQGQnExbEi02QDVzdR4+3sUvruXtL\nU/ppXvjghchgqvVp8QMjiVkUG1Ja1qwwCDM0GSN/PTfBy+Pjav0=" - secure: "FcCFPhMjgeAcSMFiTaZC6cp3IrAP9PvpAiuiKchG2smlQe85nvwdUbap7aFu\nJ8ujnuqzQJ1pc2+GAtCn0OZZ1Bh9mW31FEESiU74TphaKOFY8qAKrR7TamWx\n5XLqHvNu16LlOy/Cy8G82dMCGzPJCadM/ZwdI/RsWwRqjHgIHv0=" - secure: "Zs2+0yF2P6WWVT4o1kmgkSRmHUL1dkAYk+tHU0Piie+czblouMmqdJwsBNP6\nQF454VinL3Pu2tgbDAF10V+HknW/0ZevvmcrNa9k+Hjry8VtMNdM7jMqv4it\nYU5IGR55wfRg5q6c1jRxIPwc3Ssh2VOlz7HByppPG6i37prYO8I=" - secure: "rnFScHTmX9VDMUquOlP1FPGCr/GpCu64xw4m5AC5nIP/BCSdFSak02cc/JgC\nJPvuoud5xftyBspPRDB2eBP4YXOcPuSEdysibpGGBagKj7faCNQmCZSDd3zR\nWvLJwlfuQ39PoTIHU6O/TCX4U+v/gm4WJMwm1Tip1ID+wqqyoNU=" - secure: "h57JVvts9A0XF9ckGGokZwuD1hTBDOS0o1Yq3lD0Xd2BeJrgAXwgnKsBnBNP\nEMTBfRLGVyTgR8hiamySlWUUyVVQXMuLvKu1JnlrnZltMC8YGH4QEQwc7Twj\ni2GmsouUUHGOHU10U1F+YllSWZJjfLa6kgjkMNHg617c+PZfPLg=" - secure: "gB/9lGc5o6xeJSLler3s5ZmP0Kn+x1knSw5BIUQkke7rzWlMIaeZHqEf1iQm\n49Q2Aepo0I+RdAaGNlPHR3KrUc3P3/ZokWZ1zv449Mh0OKLNrLSE+CruuVYj\n2XcOrLC2vjSsMfaM9520spdjbvVpcTUKJho9kGRTPKLs8YbGLv8=" - secure: "px+guXOAtfmiBRub6sgvzlidKEmCNVthyAcaRHRzdtl6j7XoXHPGL2QHb8YH\nxV/wtDnLFIZi1eoShpLwABGvqQ1KQ20X+nz8FWZDnmDK3PXVBTqaUMyarmEB\nT7UohY94d8S2NqWJqeiOqVfMBOsIve9N1g3mcSUAlYMngEYoVt0=" - secure: "jPxrLpA61LxMH2a8k9P22l3/7Yx+Lhzmrne61xkFGo1F9oqwHap88AKm0gP3\nEApgDmCVRvHgetfEFIxapF+6yPZinE0EsqJonKS1NCeKjs91LMsM7Dr3UiU3\nNaco2w3B0v6dDOdG1JhAV6N/CqdWXz85hooSWsLrWpYMtPbOfJQ=" - secure: "dFvmnenj189QmbFdTW2ckHPbYojouowtz8cURDrR/2BiU0a3GUUDHP0h9O+c\nLDfJ1g03hsMr8m/45QdpL/x2lROimczFNu/U+uS8Vtja1z4SYaOMDjW4p3pq\nqPzQc/WmlpBY8wmfCH1WqmRRPvrfKceEDtVhWXruxpSZUx/OvoY=" - secure: "TmOZmx8kyEOCUOMmWKuPpKzqBpbCKMOJpankHhhEAwJ00iJ3bMzdZk7dFsMV\nq9sk2nAgkARsVakfhiUvM516CKgf3J5rskUq+AQs6JdFP8w9A3LKowLHxlqg\nCvhQtOm3ff1EVQKeDOfgUxaI20Ulq6sl+b1/uq2W1v25IqwR1ps=" - secure: "rYU47VfOGgheYhF/Xy6DM9iRi+NPSoyfMQ9B0Hoznm7k/TI1ojEky/wnIp3A\n+UdkoNo0xYzLZdjY4b1UBukMTKZJXVpYHs+KwKMhJQU3UaXpWEWo0Hqr8fU1\nOf7nspF27o79xcc3R+Okuz7L2J8+jD6Ggi2NW5vvp2S+jQW4Py4=" - secure: "PXqhXu3cK9nf80Pv4AgqS2R8HVLAHVGozqfAeAgPDOZQYUCbAyEm/QZ5WbPb\nzNQAYuEFVjt59H0b3fOM5rUSX8Igx0NeG9rxG6WYyitXZWinXyeKeZ5yKn1f\nI/gIZPVH1r1H30+TCOH9sD9rH/2eRzb5ycDGKccZfv5/MocwKwg=" - secure: "KK6YzOtwmbd3UbfiavTowvUkTGXN23ZMONwP7OpTTDZ+1/XVBeiuGLJAdHsn\nLPOImlytI9SavQekA6w4EaPb9VLRoC+O1CXOlllEjxfo0LojXDBKCaoyXOx3\nu1K8aXjyeZ2dPagjz06NV6r+y9tGypHrR7qXArVANRkzsajpABM=" - secure: "XH1YshS/QJTOWxlccDjHVCSnN3IDYqug8hw+xOpNXeKR/VbZ82lv6s1gURHh\nKI6jDPGUFiD/OA37SDmArT/CbZ2zDJtSB8YNDr8w/wInlp7vnWBoRWlFQ3eP\nsJDexlZTCvo3TUogHFpLrbq9WuEXLCJ/yfYq1zJfFvipDWR6MhQ=" - secure: "QoM0cJU0QioMMcD8Vs4xD04+jMGrTmbxxESpR4fwllAhP0ZpZt8E1qPQV9Hq\nVNzRVF/FLMlmDL8LzAYOFzVZASpb0X0l5KmxqRN3rRkSDc/LLSQf+701W00T\nJLAUXB05JPvJE5QBM5VgqNivO1JAC/Y0D83Pio8fHxYFUG6M9DM=" - secure: "LufnBePmcGefhwb3ofhBiPWdiGjGMa8G83HNdYv4BGMNyJqGa4rVaFg5yPa2\nLZx0JPwEoWK+i3QuI2ug37bSSBMf0130sUOn+E+Vy4fHeGrCdt3WrwSjACq5\nGgaBQ1JN6zLI8Gt4ekcOBOZNme6a+eMoW6asAhroIPoU1Jo/5o0=" - secure: "LZorvKqv/ncsk6sZS5NaZch/msx3HCHcy3e6BEJwudQHnF5iLz8TGbJFL9UL\nXjVX6H+CmnOQW9qbMEWTfMVXuLEXCVpX0YoQuhYwYEbhdSmz8PFJlv8BxxJg\n3OOZo0QgD2ZZ/KBenj3XIVVKeS2jHBUhXKP8G6D88xmdt3GtzRY=" - secure: "JmHFSkvxfoY6vfSM35K2eC4X0GN9n1SWapBzIFT70rz3PNKAY2QAGlvcMI2W\nZZ5JouXHHESXR+mujllzZRcx9ZJQ67k65OxG+a1ID+rivTO1A0kU36chBy8Q\nNgskyAD68gixuYts+4MXb1biXKdEO9AmUTu3zDvgqo5vcTIjvPU=" - secure: "QMjLOqEDegfPTTlm1f4SX2/77XLqAjpPrQ483EGRY59/xrS1aI0l9jTgpgTv\nZ/JyuYOX+JkbQBeW1ZuAhaXH1Q2AZ7Sun+adJ0B4yLZTHFiiy2mIFe7CcUCi\np+WgxwSPvi+uZUvEEAczKFWDKvM8qyUwZoHqaYj7VU4mComfsyE=" - secure: "RynRoItVw0gkM5OznZYhoDuukwOXVVXS5sF75G53FpoobXQYaUR20BoPFqtT\nHptuGei3f23Afiq3j807GWNoOxqVIaIoijMVxEBk6/xu43DYqUO3Nx4fB6Bk\nHdp4qNTfTVtsqy7IuXzbB3koS5xc1DUPHFDYh10pH5xWItUxlEc=" - secure: "UVtqSIfAKYSW0J06QEo+HveY+krqc7rEvnO5SNVzcQCFahnfWOIec6WQPd6O\nF/wPRjcC/zxg8PK/u5RHOKDNY6/nFNnRE7b8+MkxKcWZiFy0TipGjr57n6GW\nzgBGFi4Kw8XqFkC4hKC2eqiA8iYC+xCVzLNtnT3zp0fBG/nSrR8=" - secure: "jGoUxEIa0Mi1RZU+nZpgO9c5vw82Yl4s1h+0bimQ17OA44mmOD4UQ4ygkH+1\nKsDwJ1JxP85K2EVZdwI4EswHCH1gYRzHyO0Mo6r9LOB8aGb60mq4BCQj80oI\nlw/i4K037sb0zqys7uu0J0UD9Xep0F49uYBdrnXl5l/fLzHTm1w=" - secure: "CzFKm/g+wLUdsu4ecEx6v93ZS/CM0/3hcBxPtt/nRbmF95KW+QZMIpwUbmsH\nIZhljPkWjKOceB1sotdJjXWzEuPMj64rh9cJyWw2WO7eGG0NtbovZPUEZF4P\nz6sa3KcjNnLYAMq3Op29p23DLaZWzJqy6yzFvYQF8lxUYIyhLDU=" - secure: "fwO9vY9pIHgsCoETgQCkTVzKguuItFwLnkWOzZtzvt8fiJw2/ZafycnsTJMc\nh3/jZpn1+K+dQr7jMks9vKTXLq5101Z4SBbxaa0bt9NjyGlL72gf8sB331Oh\nLZ/E/415jeRT8sFoYNvKOfL+rtqqHaimJkaS/XvRUfru/zrb5Rw=" - secure: "TN6ig2qgH6EFGEttDtD9rxj2bH3BUJA4rJafjOXiAdQUVcH9E6lWeIaorzy9\n5Empsi/iC2rXF9i+JwE+OreUh47NL3P9jQN8dNkRmyLiuGpVVmreXynLydsS\nmaxPVwRKKSkL1PR54ICQ/Blw0vR27AqlvxO/gLcESG9Xu3Isa4o=" - secure: "BacSp+HDt0fEiSElLIzfTxi72sjO1VZkQc2/+AEJqYnGmBse1eofV9XRSlfd\nfm2qDXER34y2PerxBL5EmF3D0kG8vhBANOtHTHw5LlTR8xa/MJIMZag6zw7q\nBacSmiRNbw9XpTN+lcYvzrKFaf29exBvdKCGBv7qdMzLcEMxBVw=" - secure: "Bj/9iVBA6DGVcGRdbt3bQms8VglgSjdhI7IwvRkO3Gfvq0FTg1Hu8nodAiwM\nrfMfHzvTGNZudAkBRmPE6xZtIbID6v89S8CqEx3iGU+qbvni2nVt1SzEppb4\n8oZLKlZf3dCthrR2rpIdVMcccWhW3AjDfHKO9OlV2VR90NkWKz4=" - secure: "OJqQvNnWc0MWNOxsyhtfnn6XLj3Ssmcl+nRAp2KBwI691HvXMDsqmIXBEjq1\nql+iuNn7sxn9v+ooGXmrFS9CHndncmtKEvNzdi1HKlJhEAG0+MCYnwYwaQHr\n+6HhCnLoZ2wiE+OANFjodkQRNQ4VyATOEn5WFnp56CEtiFQiNzM=" compiler: - gcc before_install: - git submodule update --init --recursive - sudo mv /etc/apt/sources.list.d/pgdg-source.list* /tmp - sudo apt-get -qq remove postgis - sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable - sudo apt-get update -qq - sudo apt-get install -qq bison flex swig cmake librsvg2-dev colordiff postgis postgresql-9.1-postgis-2.0-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev libgeos-dev libgd2-xpm-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal1-dev libproj-dev libxml2-dev python-dev php5-dev libexempi-dev lcov lftp - sudo pip install git+git://github.com/tbonfort/cpp-coveralls.git@extensions - cd msautotest - ./create_postgis_test_data.sh - python -m SimpleHTTPServer &> /dev/null & - cd .. - touch maplexer.l - touch mapparser.y script: - ./run-test-suite.sh after_success: # Only run coverage when it is safe to do so (not on pull requests), and only on master branch - echo "$TRAVIS_SECURE_ENV_VARS" - echo "$TRAVIS_BRANCH" - sh -c 'if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "master"; then echo "run coverage"; ./run_code_coverage_upload.sh; fi' - coveralls --exclude renderers --exclude mapscript --exclude apache --exclude build/mapscript/mapscriptJAVA_wrap.c --exclude build/mapscript/mapscriptPYTHON_wrap.c --exclude shp2img.c --exclude legend.c --exclude scalebar.c --exclude msencrypt.c --exclude sortshp.c --exclude shptreevis.c --exclude shptree.c --exclude testexpr.c --exclude sym2img.c --exclude testcopy.c --exclude shptreetst.c --exclude tile4ms.c --extension .c --extension .cpp notifications: email: recipients: - thomas.bonfort@gmail.com irc: channels: - "irc.freenode.org#mapserver" use_notice: true mapserver-6.4.1/INSTALL.CMAKE0000644002461700001440000002205012261257215015163 0ustar tbonfortusersCMake Build Instructions ======================== Since version 6.4, MapServer is built with the CMake build tool instead of the previous autotools chain. CMake is opensource and free of charge and is usually included in distribution packages, or can be downloaded and compiled with no third party dependencies. CMake itself does not do the actual compiling of the MapServer source code, it mainly creates platform specific build files that can then be used by standard build utilities (make on unixes, visual studio on windows, xcode on osx, etc...) Install CMake ------------- MapServer requires at least CMake version 2.6.0, although the build process with such an old version has not been thouroughly tested. 2.8.0 and above are recommended. Distro Packaged Version ....................... Linux distributions usually include the cmake package, that can be installed with your usual package manager: apt-get, yum, yast, etc... Installing Your Own ................... Head over to http://www.cmake.org/cmake/resources/software.html to download a source tarball (for unixes) or a binary installer (for windows). If you are building from source, the build process is detailed in the tarball readme files, and consists only in $ tar xzf cmake-x.y.z.tar.gz $ cd cmake-x.y.z $ ./bootstrap $ make # make install Creating the MapServer platform specific project with CMake ----------------------------------------------------------- Although you can run and build from MapServer's source directory as created by downloading a tarball or using a git clone, it is **highly** recommended to run "out-of-source" builds, i.e. having all build files be compiled and created in a different directory than the actual MapServer sources. This allows to have different configurations running alongside each other (e.g. release and debug builds, cross-compiling, enabled features, etc...). Running CMake From the Command Line ................................... mkdir build cd build cmake .. ## fix dependency issues make Running the GUI version of cmake ................................ CMake can be run in graphical mode, in which case the list of available options are presented in a more user-friendly manner mkdir build cd build ccmake .. ## follow instructions, fix dependency issues make Options and Dependencies ........................ Depending on what packages are available in the default locations of your system, the previous "cmake .." step will most probably have failed with messages indicating missing dependencies (by default, MapServer has *many* of those). The error message that CMake prints out should give you a rather good idea of what steps you should take next, depending on wether the failed dependency is a feature you require in your build or not. - Either disable the dependency by rerunning cmake with -DWITH_DEPENDENCY=0, e.g. $ cmake .. -DWITH_CAIRO=0 - Or, if the failed dependency relates to a feature you want built in, and that cmake has not been able to find it's installation location, there are 3 possible reasons: 1 You have not installed the third party package, and/or the third party development headers. Use your standard package manager to install the failing package, along with it's development headers. The development packages on linux usually end with "-dev" or "-devel", e.g. libcairo2-devel , libpng-dev, etc... $ (sudo) apt-get install libcairo-dev $ cmake .. 2 You have installed the third party package in a non standard location, which you must give to cmake so it can find the required headers and libraries $ cmake .. -DCMAKE_PREFIX_PATH=/opt/cairo-1.18.2 Cmake expects these nonstandard prefixes to contain standard subdirectories, i.e. /opt/cairo-1.18.2/include/cairo.h and /opt/cairo-1.18.2/lib/libcairo.so. You can specify multiple prefixes on the cmake command line by separating them with the platform specific separator (e.g. ":" on unixes), e.g. $ cmake .. -DCMAKE_PREFIX_PATH=/opt/cairo-1.18.2:/opt/freeware 3 If you're certain that the packages development headers are installed, and/or that you pointed to a valid installation prefix, but cmake is still failing, then there's an issue with MapServer's cmake setup, and you can bring this up on the mailing list or issue tracker. Available Options ----------------- Following is a list of option, taken from MapServer's CMakeLists.txt configuration file. After the description of the option, the ON/OFF flag states if the option is enabled by default (in which case the cmake step will fail if the dependency cannot be found). All of these can be enabled or disabled by passing "-DWITH_XXX=0" or "-DWITH_XXX=1" to the "cmake .." invocation in order to override a default selection. - option(WITH_PROJ "Choose if reprojection support should be built in" ON) - option(WITH_KML "Enable native KML output support (requires libxml2 support)" OFF) - option(WITH_SOS "Enable SOS Server support (requires PROJ and libxml2 support)" OFF) - option(WITH_WMS "Enable WMS Server support (requires proj support)" ON) - option(WITH_GD "Choose if (old) GD support should be built in" OFF) - option(WITH_FRIBIDI "Choose if FriBidi glyph shaping support should be built in (usefull for left-to-right languages)" ON) - option(WITH_ICONV "Choose if Iconv Internationalization support should be built in" ON) - option(WITH_CAIRO "Choose if CAIRO rendering support should be built in (required for SVG and PDF output)" ON) - option(WITH_SVGCAIRO "Choose if SVG symbology support (via libsvgcairo) should be built in (requires cairo, libsvg, libsvg-cairo. Incompatible with librsvg)" OFF) - option(WITH_RSVG "Choose if SVG symbology support (via librsvg) should be built in (requires cairo, librsvg. Incompatible with libsvg-cairo)" OFF) - option(WITH_MYSQL "Choose if MYSQL joining support should be built in" OFF) - option(WITH_FCGI "Choose if FastCGI support should be built in" ON) - option(WITH_GEOS "Choose if GEOS geometry operations support should be built in" ON) - option(WITH_POSTGIS "Choose if Postgis input support should be built in" ON) - option(WITH_GDAL "Choose if GDAL input raster support should be built in" ON) - option(WITH_OGR "Choose if OGR/GDAL input vector support should be built in" ON) - option(WITH_CURL "Enable Curl HTTP support (required for wms/wfs client, remote SLDs and pixmap symbols)" OFF) - option(WITH_CLIENT_WMS "Enable Client WMS Layer support (requires CURL and GDAL support)" OFF) - option(WITH_CLIENT_WFS "Enable Client WMS Layer support (requires CURL and OGR support)" OFF) - option(WITH_WFS "Enable WFS Server support (requires PROJ and OGR support)" ON) - option(WITH_WCS "Enable WCS Server support (requires PROJ and GDAL support)" ON) - option(WITH_LIBXML2 "Choose if libxml2 support should be built in (used for sos, wcs 1.1,2.0 and wfs 1.1)" ON) - option(WITH_THREAD_SAFETY "Choose if a thread-safe version of libmapserver should be built (only recommended for some mapscripts)" OFF) - option(WITH_GIF "Enable GIF support (for PIXMAP loading)" ON) - option(WITH_PYTHON "Enable Python mapscript support" OFF) - option(WITH_PHP "Enable Python mapscript support" OFF) - option(WITH_PERL "Enable Perl mapscript support" OFF) - option(WITH_RUBY "Enable Ruby mapscript support" OFF) - option(WITH_JAVA "Enable Java mapscript support" OFF) - option(WITH_CSHARP "Enable C# mapscript support" OFF) - option(WITH_ORACLESPATIAL "include oracle spatial database input support" OFF) - option(WITH_ORACLE_PLUGIN "include oracle spatial database input support as plugin" OFF) - option(WITH_MSSQL2008 "include mssql 2008 database input support as plugin" OFF) - option(WITH_SDE_PLUGIN "include ArcSDE support as a plugin (must specify SDE_INCLUDE_DIR and SDE_LIBRARY_DIR)." OFF) - option(WITH_SDE "include ArcSDE support. Add -DSDE_VERSION=91 to use 9.1 arcSDE version" OFF) - option(WITH_EXEMPI "include xmp output metadata support" OFF) - option(WITH_XMLMAPFILE "include native xml mapfile support (requires libxslt/libexslt)" OFF) The following options are for advanced users, i.e. you should not enable them unless you know what you are doing: - option(BUILD_STATIC "Also build a static version of mapserver" OFF) - option(LINK_STATIC_LIBMAPSERVER "Link to static version of libmapserver (also for mapscripts)" OFF) - option(WITH_APACHE_MODULE "include (experimental) support for apache module" OFF) - option(WITH_GENERIC_NINT "generic rounding" OFF) - option(WITH_POINT_Z_M "include Z and M coordinates in point structure (advanced, not recommended)" OFF) The following are some common CMake options not specific to MapServer itself: - CMAKE_INSTALL_PREFIX : path where mapserver binaries and libraries should be installed. Defaults to /usr/local on unix. - CMAKE_PREFIX_PATH : platform-specific separator separated list of prefixes where dependencies will be looked for, e.g. "-DCMAKE_PREFIX_PATH=/opt/freeware:/opt/jdk-1.5.6" - CMAKE_BUILD_TYPE : Specify the build type. Usually one of 'Debug' or 'Release', e.g. "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_BUILD_TYPE=Debug" You can find a more extensive list of cmake variables here: http://www.cmake.org/Wiki/CMake_Useful_Variables mapserver-6.4.1/maplexer.l0000644002461700001440000013244012261257215015312 0ustar tbonfortusers%{ /* ** READ ME FIRST! ** ** When this file is altered, it is necessary to do "make lexer". Due to ** problems detailed in #2310 the lexer is no longer automatically rebuilt ** when maplexer.l is altered. */ /* C declarations */ #include #include #include #include #include #include "mapserver.h" #include "maperror.h" #include "mapfile.h" #include "maptime.h" #include "mapsymbol.h" #include "mapparser.h" #include "mapprimitive.h" /* msyylineno is required for flex 2.5.4 and older, but is already defined by * flex 2.5.31 (bug 975). * Unfortunately there is no clean way to differenciate the two versions, * so we use the symbol YY_CURRENT_BUFFER_LVALUE to base our test since it * was not present in 2.5.4 and is present in 2.5.31. Hopefully that won't * put us in trouble with other versions. If that happens then we can * switch to using autoconf to detect the version. */ #ifndef YY_CURRENT_BUFFER_LVALUE int msyylineno = 1; #endif int msyysource=MS_STRING_TOKENS; double msyynumber; int msyystate=MS_TOKENIZE_DEFAULT; char *msyystring=NULL; char *msyybasepath=NULL; char *msyystring_buffer_ptr; int msyystring_buffer_size = 256; int msyystring_size; char msyystring_begin; char *msyystring_buffer = NULL; int msyystring_icase = MS_FALSE; int msyystring_return_state; int msyystring_begin_state; int msyystring_size_tmp; int msyyreturncomments = 0; #define MS_LEXER_STRING_REALLOC(string, string_size, max_size, string_ptr) \ if (string_size >= max_size) { \ msyystring_size_tmp = max_size; \ max_size = ((max_size*2) > string_size) ? max_size*2 : string_size+1; \ string = (char *) msSmallRealloc(string, sizeof(char *) * max_size); \ string_ptr = string; \ string_ptr += msyystring_size_tmp; \ } #define MS_LEXER_RETURN_TOKEN(token) \ MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), \ msyystring_buffer_size, msyystring_buffer_ptr); \ strcpy(msyystring_buffer, msyytext); \ return(token); #define MAX_INCLUDE_DEPTH 5 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_lineno[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; char path[MS_MAXPATHLEN]; %} %s URL_VARIABLE %s URL_STRING %s EXPRESSION_STRING %s INCLUDE %s MSSTRING %% if (msyystring_buffer == NULL) msyystring_buffer = (char*) msSmallMalloc(sizeof(char) * msyystring_buffer_size); msyystring_buffer[0] = '\0'; msyystring_buffer_size = 0; switch(msyystate) { case(MS_TOKENIZE_DEFAULT): break; case(MS_TOKENIZE_FILE): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyysource=MS_FILE_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_STRING): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_STRING_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_URL_VARIABLE): BEGIN(URL_VARIABLE); msyystring_begin_state = URL_VARIABLE; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; (void) yyunput; /* just to avoid warning about it being unrefed */ break; case(MS_TOKENIZE_URL_STRING): BEGIN(URL_STRING); msyystring_begin_state = URL_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; return(0); break; case(MS_TOKENIZE_EXPRESSION): BEGIN(EXPRESSION_STRING); msyystring_begin_state = EXPRESSION_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; break; case(99): BEGIN(INITIAL); /* may not need this one */ msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; return(0); break; default: break; } [ \t\r]+ ; #.* { if (msyyreturncomments) return(MS_COMMENT); } _|\. ; or|\|\| { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_OR); } and|&& { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_AND); } not|! { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_NOT); } eq|=|== { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_EQ); } ne|!= { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_NE); } gt|> { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GT); } lt|< { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LT); } ge|>= { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GE); } le|<= { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LE); } ~ { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_RE); } =\* { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IEQ); } ~\* { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IRE); } in { MS_LEXER_RETURN_TOKEN(IN); } area { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_AREA); } length { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_LENGTH); } tostring { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_TOSTRING); } commify { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_COMMIFY); } round { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_ROUND); } buffer { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_BUFFER); } difference { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_DIFFERENCE); } simplify { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFY); } simplifypt { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFYPT); } generalize { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_GENERALIZE); } smoothsia { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SMOOTHSIA); } intersects { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_INTERSECTS); } disjoint { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DISJOINT); } touches { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_TOUCHES); } overlaps { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_OVERLAPS); } crosses { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CROSSES); } within { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_WITHIN); } contains { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CONTAINS); } beyond { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_BEYOND); } dwithin { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DWITHIN); } fromtext { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_FROMTEXT); } colorrange { MS_LEXER_RETURN_TOKEN(COLORRANGE); } datarange { MS_LEXER_RETURN_TOKEN(DATARANGE); } rangeitem { MS_LEXER_RETURN_TOKEN(RANGEITEM); } align { MS_LEXER_RETURN_TOKEN(ALIGN); } anchorpoint { MS_LEXER_RETURN_TOKEN(ANCHORPOINT); } angle { MS_LEXER_RETURN_TOKEN(ANGLE); } antialias { MS_LEXER_RETURN_TOKEN(ANTIALIAS); } backgroundcolor { MS_LEXER_RETURN_TOKEN(BACKGROUNDCOLOR); } bandsitem { MS_LEXER_RETURN_TOKEN(BANDSITEM); } bindvals { MS_LEXER_RETURN_TOKEN(BINDVALS); } browseformat { MS_LEXER_RETURN_TOKEN(BROWSEFORMAT); } buffer { MS_LEXER_RETURN_TOKEN(BUFFER); } character { MS_LEXER_RETURN_TOKEN(CHARACTER); } class { MS_LEXER_RETURN_TOKEN(CLASS); } classitem { MS_LEXER_RETURN_TOKEN(CLASSITEM); } classgroup { MS_LEXER_RETURN_TOKEN(CLASSGROUP); } cluster { MS_LEXER_RETURN_TOKEN(CLUSTER); } color { MS_LEXER_RETURN_TOKEN(COLOR); } config { MS_LEXER_RETURN_TOKEN(CONFIG); } connection { MS_LEXER_RETURN_TOKEN(CONNECTION); } connectiontype { MS_LEXER_RETURN_TOKEN(CONNECTIONTYPE); } data { MS_LEXER_RETURN_TOKEN(DATA); } datapattern { MS_LEXER_RETURN_TOKEN(DATAPATTERN); } debug { MS_LEXER_RETURN_TOKEN(DEBUG); } driver { MS_LEXER_RETURN_TOKEN(DRIVER); } dump { MS_LEXER_RETURN_TOKEN(DUMP); } empty { MS_LEXER_RETURN_TOKEN(EMPTY); } encoding { MS_LEXER_RETURN_TOKEN(ENCODING); } end { MS_LEXER_RETURN_TOKEN(END); } error { MS_LEXER_RETURN_TOKEN(ERROR); } expression { MS_LEXER_RETURN_TOKEN(EXPRESSION); } extent { MS_LEXER_RETURN_TOKEN(EXTENT); } extension { MS_LEXER_RETURN_TOKEN(EXTENSION); } feature { MS_LEXER_RETURN_TOKEN(FEATURE); } filled { MS_LEXER_RETURN_TOKEN(FILLED); } filter { MS_LEXER_RETURN_TOKEN(FILTER); } filteritem { MS_LEXER_RETURN_TOKEN(FILTERITEM); } footer { MS_LEXER_RETURN_TOKEN(FOOTER); } font { MS_LEXER_RETURN_TOKEN(FONT); } fontset { MS_LEXER_RETURN_TOKEN(FONTSET); } force { MS_LEXER_RETURN_TOKEN(FORCE); } formatoption { MS_LEXER_RETURN_TOKEN(FORMATOPTION); } from { MS_LEXER_RETURN_TOKEN(FROM); } gap { MS_LEXER_RETURN_TOKEN(GAP); } geomtransform { MS_LEXER_RETURN_TOKEN(GEOMTRANSFORM); } grid { MS_LEXER_RETURN_TOKEN(GRID); } gridstep { MS_LEXER_RETURN_TOKEN(GRIDSTEP); } graticule { MS_LEXER_RETURN_TOKEN(GRATICULE); } group { MS_LEXER_RETURN_TOKEN(GROUP); } header { MS_LEXER_RETURN_TOKEN(HEADER); } image { MS_LEXER_RETURN_TOKEN(IMAGE); } imagecolor { MS_LEXER_RETURN_TOKEN(IMAGECOLOR); } imagetype { MS_LEXER_RETURN_TOKEN(IMAGETYPE); } imagequality { MS_LEXER_RETURN_TOKEN(IMAGEQUALITY); } imagemode { MS_LEXER_RETURN_TOKEN(IMAGEMODE); } imagepath { MS_LEXER_RETURN_TOKEN(IMAGEPATH); } temppath { MS_LEXER_RETURN_TOKEN(TEMPPATH); } imageurl { MS_LEXER_RETURN_TOKEN(IMAGEURL); } include { BEGIN(INCLUDE); } index { MS_LEXER_RETURN_TOKEN(INDEX); } initialgap { MS_LEXER_RETURN_TOKEN(INITIALGAP); } interlace { MS_LEXER_RETURN_TOKEN(INTERLACE); } intervals { MS_LEXER_RETURN_TOKEN(INTERVALS); } join { MS_LEXER_RETURN_TOKEN(JOIN); } keyimage { MS_LEXER_RETURN_TOKEN(KEYIMAGE); } keysize { MS_LEXER_RETURN_TOKEN(KEYSIZE); } keyspacing { MS_LEXER_RETURN_TOKEN(KEYSPACING); } label { MS_LEXER_RETURN_TOKEN(LABEL); } labelcache { MS_LEXER_RETURN_TOKEN(LABELCACHE); } labelformat { MS_LEXER_RETURN_TOKEN(LABELFORMAT); } labelitem { MS_LEXER_RETURN_TOKEN(LABELITEM); } labelmaxscale { MS_LEXER_RETURN_TOKEN(LABELMAXSCALE); } labelmaxscaledenom { MS_LEXER_RETURN_TOKEN(LABELMAXSCALEDENOM); } labelminscale { MS_LEXER_RETURN_TOKEN(LABELMINSCALE); } labelminscaledenom { MS_LEXER_RETURN_TOKEN(LABELMINSCALEDENOM); } labelrequires { MS_LEXER_RETURN_TOKEN(LABELREQUIRES); } latlon { MS_LEXER_RETURN_TOKEN(LATLON); } layer { MS_LEXER_RETURN_TOKEN(LAYER); } leader { MS_LEXER_RETURN_TOKEN(LEADER); } legend { MS_LEXER_RETURN_TOKEN(LEGEND); } legendformat { MS_LEXER_RETURN_TOKEN(LEGENDFORMAT); } linecap { MS_LEXER_RETURN_TOKEN(LINECAP); } linejoin { MS_LEXER_RETURN_TOKEN(LINEJOIN); } linejoinmaxsize { MS_LEXER_RETURN_TOKEN(LINEJOINMAXSIZE); } log { MS_LEXER_RETURN_TOKEN(LOG); } map { MS_LEXER_RETURN_TOKEN(MAP); } marker { MS_LEXER_RETURN_TOKEN(MARKER); } markersize { MS_LEXER_RETURN_TOKEN(MARKERSIZE); } mask { MS_LEXER_RETURN_TOKEN(MASK); } maxarcs { MS_LEXER_RETURN_TOKEN(MAXARCS); } maxboxsize { MS_LEXER_RETURN_TOKEN(MAXBOXSIZE); } maxdistance { MS_LEXER_RETURN_TOKEN(MAXDISTANCE); } maxfeatures { MS_LEXER_RETURN_TOKEN(MAXFEATURES); } maxinterval { MS_LEXER_RETURN_TOKEN(MAXINTERVAL); } maxscale { MS_LEXER_RETURN_TOKEN(MAXSCALE); } maxscaledenom { MS_LEXER_RETURN_TOKEN(MAXSCALEDENOM); } maxgeowidth { MS_LEXER_RETURN_TOKEN(MAXGEOWIDTH); } maxlength { MS_LEXER_RETURN_TOKEN(MAXLENGTH); } maxsize { MS_LEXER_RETURN_TOKEN(MAXSIZE); } maxsubdivide { MS_LEXER_RETURN_TOKEN(MAXSUBDIVIDE); } maxtemplate { MS_LEXER_RETURN_TOKEN(MAXTEMPLATE); } maxwidth { MS_LEXER_RETURN_TOKEN(MAXWIDTH); } metadata { MS_LEXER_RETURN_TOKEN(METADATA); } mimetype { MS_LEXER_RETURN_TOKEN(MIMETYPE); } minarcs { MS_LEXER_RETURN_TOKEN(MINARCS); } minboxsize { MS_LEXER_RETURN_TOKEN(MINBOXSIZE); } mindistance { MS_LEXER_RETURN_TOKEN(MINDISTANCE); } repeatdistance { MS_LEXER_RETURN_TOKEN(REPEATDISTANCE); } maxoverlapangle { MS_LEXER_RETURN_TOKEN(MAXOVERLAPANGLE); } minfeaturesize { MS_LEXER_RETURN_TOKEN(MINFEATURESIZE); } mininterval { MS_LEXER_RETURN_TOKEN(MININTERVAL); } minscale { MS_LEXER_RETURN_TOKEN(MINSCALE); } minscaledenom { MS_LEXER_RETURN_TOKEN(MINSCALEDENOM); } mingeowidth { MS_LEXER_RETURN_TOKEN(MINGEOWIDTH); } minlength { MS_LEXER_RETURN_TOKEN(MINLENGTH); } minsize { MS_LEXER_RETURN_TOKEN(MINSIZE); } minsubdivide { MS_LEXER_RETURN_TOKEN(MINSUBDIVIDE); } mintemplate { MS_LEXER_RETURN_TOKEN(MINTEMPLATE); } minwidth { MS_LEXER_RETURN_TOKEN(MINWIDTH); } name { MS_LEXER_RETURN_TOKEN(NAME); } offset { MS_LEXER_RETURN_TOKEN(OFFSET); } offsite { MS_LEXER_RETURN_TOKEN(OFFSITE); } opacity { MS_LEXER_RETURN_TOKEN(OPACITY); } outlinecolor { MS_LEXER_RETURN_TOKEN(OUTLINECOLOR); } outlinewidth { MS_LEXER_RETURN_TOKEN(OUTLINEWIDTH); } outputformat { MS_LEXER_RETURN_TOKEN(OUTPUTFORMAT); } overlaybackgroundcolor { MS_LEXER_RETURN_TOKEN(OVERLAYBACKGROUNDCOLOR); } overlaycolor { MS_LEXER_RETURN_TOKEN(OVERLAYCOLOR); } overlaymaxsize { MS_LEXER_RETURN_TOKEN(OVERLAYMAXSIZE); } overlayminsize { MS_LEXER_RETURN_TOKEN(OVERLAYMINSIZE); } overlayoutlinecolor { MS_LEXER_RETURN_TOKEN(OVERLAYOUTLINECOLOR); } overlaysize { MS_LEXER_RETURN_TOKEN(OVERLAYSIZE); } overlaysymbol { MS_LEXER_RETURN_TOKEN(OVERLAYSYMBOL); } partials { MS_LEXER_RETURN_TOKEN(PARTIALS); } pattern { MS_LEXER_RETURN_TOKEN(PATTERN); } points { MS_LEXER_RETURN_TOKEN(POINTS); } items { MS_LEXER_RETURN_TOKEN(ITEMS); } position { MS_LEXER_RETURN_TOKEN(POSITION); } postlabelcache { MS_LEXER_RETURN_TOKEN(POSTLABELCACHE); } priority { MS_LEXER_RETURN_TOKEN(PRIORITY); } processing { MS_LEXER_RETURN_TOKEN(PROCESSING); } projection { MS_LEXER_RETURN_TOKEN(PROJECTION); } queryformat { MS_LEXER_RETURN_TOKEN(QUERYFORMAT); } querymap { MS_LEXER_RETURN_TOKEN(QUERYMAP); } reference { MS_LEXER_RETURN_TOKEN(REFERENCE); } region { MS_LEXER_RETURN_TOKEN(REGION); } relativeto { MS_LEXER_RETURN_TOKEN(RELATIVETO); } requires { MS_LEXER_RETURN_TOKEN(REQUIRES); } resolution { MS_LEXER_RETURN_TOKEN(RESOLUTION); } defresolution { MS_LEXER_RETURN_TOKEN(DEFRESOLUTION); } scale { MS_LEXER_RETURN_TOKEN(SCALE); } scaledenom { MS_LEXER_RETURN_TOKEN(SCALEDENOM); } scalebar { MS_LEXER_RETURN_TOKEN(SCALEBAR); } scaletoken { MS_LEXER_RETURN_TOKEN(SCALETOKEN); } shadowcolor { MS_LEXER_RETURN_TOKEN(SHADOWCOLOR); } shadowsize { MS_LEXER_RETURN_TOKEN(SHADOWSIZE); } shapepath { MS_LEXER_RETURN_TOKEN(SHAPEPATH); } size { MS_LEXER_RETURN_TOKEN(SIZE); } sizeunits { MS_LEXER_RETURN_TOKEN(SIZEUNITS); } status { MS_LEXER_RETURN_TOKEN(STATUS); } style { MS_LEXER_RETURN_TOKEN(STYLE); } styleitem { MS_LEXER_RETURN_TOKEN(STYLEITEM); } symbol { MS_LEXER_RETURN_TOKEN(SYMBOL); } symbolscale { MS_LEXER_RETURN_TOKEN(SYMBOLSCALE); } symbolscaledenom { MS_LEXER_RETURN_TOKEN(SYMBOLSCALEDENOM); } symbolset { MS_LEXER_RETURN_TOKEN(SYMBOLSET); } table { MS_LEXER_RETURN_TOKEN(TABLE); } template { MS_LEXER_RETURN_TOKEN(TEMPLATE); } templatepattern { MS_LEXER_RETURN_TOKEN(TEMPLATEPATTERN); } text { MS_LEXER_RETURN_TOKEN(TEXT); } tileindex { MS_LEXER_RETURN_TOKEN(TILEINDEX); } tileitem { MS_LEXER_RETURN_TOKEN(TILEITEM); } tilesrs { MS_LEXER_RETURN_TOKEN(TILESRS); } title { MS_LEXER_RETURN_TOKEN(TITLE); } to { MS_LEXER_RETURN_TOKEN(TO); } tolerance { MS_LEXER_RETURN_TOKEN(TOLERANCE); } toleranceunits { MS_LEXER_RETURN_TOKEN(TOLERANCEUNITS); } transparency { MS_LEXER_RETURN_TOKEN(TRANSPARENCY); } transparent { MS_LEXER_RETURN_TOKEN(TRANSPARENT); } transform { MS_LEXER_RETURN_TOKEN(TRANSFORM); } type { MS_LEXER_RETURN_TOKEN(TYPE); } units { MS_LEXER_RETURN_TOKEN(UNITS); } validation { MS_LEXER_RETURN_TOKEN(VALIDATION); } values { MS_LEXER_RETURN_TOKEN(VALUES); } web { MS_LEXER_RETURN_TOKEN(WEB); } width { MS_LEXER_RETURN_TOKEN(WIDTH); } wkt { MS_LEXER_RETURN_TOKEN(WKT); } wrap { MS_LEXER_RETURN_TOKEN(WRAP); } annotation { MS_LEXER_RETURN_TOKEN(MS_LAYER_ANNOTATION); } auto { MS_LEXER_RETURN_TOKEN(MS_AUTO); } auto2 { MS_LEXER_RETURN_TOKEN(MS_AUTO2); } bevel { MS_LEXER_RETURN_TOKEN(MS_CJC_BEVEL); } bitmap { MS_LEXER_RETURN_TOKEN(MS_BITMAP); } butt { MS_LEXER_RETURN_TOKEN(MS_CJC_BUTT); } cc { MS_LEXER_RETURN_TOKEN(MS_CC); } center { MS_LEXER_RETURN_TOKEN(MS_ALIGN_CENTER); } chart { MS_LEXER_RETURN_TOKEN(MS_LAYER_CHART); } circle { MS_LEXER_RETURN_TOKEN(MS_LAYER_CIRCLE); } cl { MS_LEXER_RETURN_TOKEN(MS_CL); } cr { MS_LEXER_RETURN_TOKEN(MS_CR); } csv { MS_LEXER_RETURN_TOKEN(MS_DB_CSV); } postgresql { MS_LEXER_RETURN_TOKEN(MS_DB_POSTGRES); } mysql { MS_LEXER_RETURN_TOKEN(MS_DB_MYSQL); } default { MS_LEXER_RETURN_TOKEN(MS_DEFAULT); } dd { MS_LEXER_RETURN_TOKEN(MS_DD); } ellipse { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_ELLIPSE); } embed { MS_LEXER_RETURN_TOKEN(MS_EMBED); } false { MS_LEXER_RETURN_TOKEN(MS_FALSE); } feet { MS_LEXER_RETURN_TOKEN(MS_FEET); } follow { MS_LEXER_RETURN_TOKEN(MS_FOLLOW); } giant { MS_LEXER_RETURN_TOKEN(MS_GIANT); } hatch { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_HATCH); } hilite { MS_LEXER_RETURN_TOKEN(MS_HILITE); } inches { MS_LEXER_RETURN_TOKEN(MS_INCHES); } kilometers { MS_LEXER_RETURN_TOKEN(MS_KILOMETERS); } large { MS_LEXER_RETURN_TOKEN(MS_LARGE); } lc { MS_LEXER_RETURN_TOKEN(MS_LC); } left { MS_LEXER_RETURN_TOKEN(MS_ALIGN_LEFT); } line { MS_LEXER_RETURN_TOKEN(MS_LAYER_LINE); } ll { MS_LEXER_RETURN_TOKEN(MS_LL); } lr { MS_LEXER_RETURN_TOKEN(MS_LR); } medium { MS_LEXER_RETURN_TOKEN(MS_MEDIUM); } meters { MS_LEXER_RETURN_TOKEN(MS_METERS); } nauticalmiles { MS_LEXER_RETURN_TOKEN(MS_NAUTICALMILES); } miles { MS_LEXER_RETURN_TOKEN(MS_MILES); } miter { MS_LEXER_RETURN_TOKEN(MS_CJC_MITER); } multiple { MS_LEXER_RETURN_TOKEN(MS_MULTIPLE); } none { MS_LEXER_RETURN_TOKEN(MS_CJC_NONE); } normal { MS_LEXER_RETURN_TOKEN(MS_NORMAL); } off { MS_LEXER_RETURN_TOKEN(MS_OFF); } ogr { MS_LEXER_RETURN_TOKEN(MS_OGR); } on { MS_LEXER_RETURN_TOKEN(MS_ON); } one-to-one { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_ONE); } one-to-many { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_MANY); } oraclespatial { MS_LEXER_RETURN_TOKEN(MS_ORACLESPATIAL); } percentages { MS_LEXER_RETURN_TOKEN(MS_PERCENTAGES); } pixmap { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_PIXMAP); } pixels { MS_LEXER_RETURN_TOKEN(MS_PIXELS); } point { MS_LEXER_RETURN_TOKEN(MS_LAYER_POINT); } polygon { MS_LEXER_RETURN_TOKEN(MS_LAYER_POLYGON); } postgis { MS_LEXER_RETURN_TOKEN(MS_POSTGIS); } plugin { MS_LEXER_RETURN_TOKEN(MS_PLUGIN); } query { MS_LEXER_RETURN_TOKEN(MS_LAYER_QUERY); } raster { MS_LEXER_RETURN_TOKEN(MS_LAYER_RASTER); } right { MS_LEXER_RETURN_TOKEN(MS_ALIGN_RIGHT); } round { MS_LEXER_RETURN_TOKEN(MS_CJC_ROUND); } sde { MS_LEXER_RETURN_TOKEN(MS_SDE); } selected { MS_LEXER_RETURN_TOKEN(MS_SELECTED); } simple { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SIMPLE); } single { MS_LEXER_RETURN_TOKEN(MS_SINGLE); } small { MS_LEXER_RETURN_TOKEN(MS_SMALL); } square { MS_LEXER_RETURN_TOKEN(MS_CJC_SQUARE); } svg { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SVG); } polaroffset { MS_LEXER_RETURN_TOKEN(POLAROFFSET); } tiny { MS_LEXER_RETURN_TOKEN(MS_TINY); } triangle { MS_LEXER_RETURN_TOKEN(MS_CJC_TRIANGLE); } true { MS_LEXER_RETURN_TOKEN(MS_TRUE); } truetype { MS_LEXER_RETURN_TOKEN(MS_TRUETYPE); } uc { MS_LEXER_RETURN_TOKEN(MS_UC); } ul { MS_LEXER_RETURN_TOKEN(MS_UL); } ur { MS_LEXER_RETURN_TOKEN(MS_UR); } union { MS_LEXER_RETURN_TOKEN(MS_UNION); } uvraster { MS_LEXER_RETURN_TOKEN(MS_UVRASTER); } contour { MS_LEXER_RETURN_TOKEN(MS_CONTOUR); } vector { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_VECTOR); } wfs { MS_LEXER_RETURN_TOKEN(MS_WFS); } wms { MS_LEXER_RETURN_TOKEN(MS_WMS); } alpha { MS_LEXER_RETURN_TOKEN(MS_GD_ALPHA); } \[[a-z/\.][a-z0-9/\.\-\=_ ]*\] { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_STRING); } \[[0-9]*\] { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } \[[^\]]*\] { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_BINDING); } \[shape\] { /* attribute binding - shape (fixed value) */ return(MS_TOKEN_BINDING_SHAPE); } \[map_cellsize\] { /* attribute binding - map cellsize */ return(MS_TOKEN_BINDING_MAP_CELLSIZE); } \[data_cellsize\] { /* attribute binding - data cellsize */ return(MS_TOKEN_BINDING_DATA_CELLSIZE); } \[[^\]]*\] { /* attribute binding - numeric (no quotes) */ msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_DOUBLE); } \"\[[^\"]*\]\"|\'\[[^\']*\]\' { /* attribute binding - string (single or double quotes) */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_STRING); } \`\[[^\`]*\]\` { /* attribute binding - time */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_TIME); } -?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } -?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_TOKEN_LITERAL_NUMBER); } \`[^\`]*\` { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_LITERAL_TIME); } \/[^\/]*\/i { msyytext++; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_IREGEX); } \/[^\/]*\/ { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_REGEX); } \(.*\) { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_EXPRESSION); } \{.*\} { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_LIST); } \'|\" { msyystring_return_state = MS_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } \'|\"|\"i|\'i { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); if (msyystring_begin == msyytext[0]) { BEGIN(msyystring_begin_state); *msyystring_buffer_ptr = '\0'; if (msyystring_return_state == MS_STRING) { if (msyystring_icase && strlen(msyytext)==2) { msyystring_icase = MS_FALSE; // reset return MS_ISTRING; } else return MS_STRING; } return msyystring_return_state; } else { ++msyystring_size; *msyystring_buffer_ptr++ = *msyytext; if (strlen(msyytext)==2) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = msyytext[1]; } } } \\\'|\\\"|\\\\|\\ { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; if (strlen(msyytext) == 2) *msyystring_buffer_ptr++ = msyytext[1]; else *msyystring_buffer_ptr++ = msyytext[0]; } [^\\\'\\\"]+ { char *yptr = msyytext; while ( *yptr ) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = *yptr++; } } \"[^\"]*\"|\'[^\']*\' { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; if(include_stack_ptr >= MAX_INCLUDE_DEPTH) { msSetError(MS_IOERR, "Includes nested to deeply.", "msyylex()"); return(-1); } include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; /* save state */ include_lineno[include_stack_ptr] = msyylineno; include_stack_ptr++; msyyin = fopen(msBuildPath(path, msyybasepath, msyytext), "r"); if(!msyyin) { msSetError(MS_IOERR, "Error opening included file \"%s\".", "msyylex()", msyytext); return(-1); } msyy_switch_to_buffer( msyy_create_buffer(msyyin, YY_BUF_SIZE) ); msyylineno = 1; BEGIN(INITIAL); } \'|\" { msyystring_return_state = MS_TOKEN_LITERAL_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } [a-z/\.][a-z0-9/\._\-\=]* { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_STRING); } \n { msyylineno++; } <> { if( --include_stack_ptr < 0 ) return(EOF); /* end of main file */ else { fclose(YY_CURRENT_BUFFER->yy_input_file); msyy_delete_buffer( YY_CURRENT_BUFFER ); msyy_switch_to_buffer(include_stack[include_stack_ptr]); msyylineno = include_lineno[include_stack_ptr]; } } [\r|\n|\0] { return(0); } . { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(0); } . { return(msyytext[0]); } %% /* ** Any extra C functions */ int msyywrap() /* override */ { return(1); } int msyyerror(char *s) { msSetError(MS_PARSEERR, "%s", "msyyparse()", s); return(0); } mapserver-6.4.1/cgiutil.c0000644002461700001440000003331512261257215015125 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: cgiRequestObj and CGI parameter parsing. * Author: Steve Lime and the MapServer team. * * Notes: Portions derived from NCSA HTTPd Server's example CGI programs (util.c). * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include #include #include #include "mapserver.h" #include "cgiutil.h" #define LF 10 #define CR 13 int readPostBody( cgiRequestObj *request, char **data ) { size_t data_max, data_len; int chunk_size; msIO_needBinaryStdin(); /* -------------------------------------------------------------------- */ /* If the length is provided, read in one gulp. */ /* -------------------------------------------------------------------- */ if( getenv("CONTENT_LENGTH") != NULL ) { data_max = (size_t) atoi(getenv("CONTENT_LENGTH")); /* Test for suspicious CONTENT_LENGTH (negative value or SIZE_MAX) */ if( data_max >= SIZE_MAX ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("Suspicious Content-Length.\n"); return MS_FAILURE; } *data = (char *) malloc(data_max+1); if( *data == NULL ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("malloc() failed, Content-Length: %u unreasonably large?\n", (unsigned int)data_max ); return MS_FAILURE; } if( (int) msIO_fread(*data, 1, data_max, stdin) < data_max ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("POST body is short\n"); return MS_FAILURE; } (*data)[data_max] = '\0'; return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Otherwise read in chunks to the end. */ /* -------------------------------------------------------------------- */ #define DATA_ALLOC_SIZE 10000 data_max = DATA_ALLOC_SIZE; data_len = 0; *data = (char *) msSmallMalloc(data_max+1); while( (chunk_size = msIO_fread( *data + data_len, 1, data_max-data_len, stdin )) > 0 ) { data_len += chunk_size; if( data_len == data_max ) { /* Realloc buffer, making sure we check for possible size_t overflow */ if ( data_max > SIZE_MAX - (DATA_ALLOC_SIZE+1) ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("Possible size_t overflow, cannot reallocate input buffer, POST body too large?\n" ); return MS_FAILURE; } data_max = data_max + DATA_ALLOC_SIZE; *data = (char *) msSmallRealloc(*data, data_max+1); } } (*data)[data_len] = '\0'; return MS_SUCCESS; } static char* msGetEnv(const char *name, void* thread_context) { return getenv(name); } int loadParams(cgiRequestObj *request, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context) { register int x,m=0; char *s, *queryString = NULL, *httpCookie = NULL; int debuglevel; int maxParams = MS_DEFAULT_CGI_PARAMS; if (getenv2==NULL) getenv2 = &msGetEnv; if(getenv2("REQUEST_METHOD", thread_context)==NULL) { msIO_printf("This script can only be used to decode form results and \n"); msIO_printf("should be initiated as a CGI process via a httpd server.\n"); return -1; } debuglevel = (int)msGetGlobalDebugLevel(); if(strcmp(getenv2("REQUEST_METHOD", thread_context),"POST") == 0) { /* we've got a post from a form */ char *post_data; int data_len; request->type = MS_POST_REQUEST; s = getenv2("CONTENT_TYPE", thread_context); if (s != NULL) request->contenttype = msStrdup(s); /* we've to set default Content-Type which is * application/octet-stream according to * W3 RFC 2626 section 7.2.1 */ else request->contenttype = msStrdup("application/octet-stream"); if (raw_post_data) { post_data = msStrdup(raw_post_data); data_len = raw_post_data_length; } else { if(MS_SUCCESS != readPostBody( request, &post_data )) return -1; data_len = strlen(post_data); } /* if the content_type is application/x-www-form-urlencoded, we have to parse it like the QUERY_STRING variable */ if(strncmp(request->contenttype, "application/x-www-form-urlencoded", strlen("application/x-www-form-urlencoded")) == 0) { while( data_len > 0 && isspace(post_data[data_len-1]) ) post_data[--data_len] = '\0'; while( post_data[0] ) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(post_data,'&'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword(request->ParamValues[m],'='); m++; } free( post_data ); } else request->postrequest = post_data; /* check the QUERY_STRING even in the post request since it can contain information. Eg a wfs request with */ s = getenv2("QUERY_STRING", thread_context); if(s) { if (debuglevel >= MS_DEBUGLEVEL_DEBUG) msDebug("loadParams() QUERY_STRING: %s\n", s); queryString = msStrdup(s); for(x=0; queryString[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(queryString,'&'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword(request->ParamValues[m],'='); m++; } } } else { if(strcmp(getenv2("REQUEST_METHOD", thread_context),"GET") == 0) { /* we've got a get request */ request->type = MS_GET_REQUEST; s = getenv2("QUERY_STRING", thread_context); if(s == NULL) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("No query information to decode. QUERY_STRING not set.\n"); return -1; } if (debuglevel >= MS_DEBUGLEVEL_DEBUG) msDebug("loadParams() QUERY_STRING: %s\n", s); if(strlen(s)==0) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("No query information to decode. QUERY_STRING is set, but empty.\n"); return -1; } /* don't modify the string returned by getenv2 */ queryString = msStrdup(s); for(x=0; queryString[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(queryString,'&'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword(request->ParamValues[m],'='); m++; } } else { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("This script should be referenced with a METHOD of GET or METHOD of POST.\n"); return -1; } } /* check for any available cookies */ s = getenv2("HTTP_COOKIE", thread_context); if(s != NULL) { httpCookie = msStrdup(s); request->httpcookiedata = msStrdup(s); for(x=0; httpCookie[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(httpCookie,';'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword_skip(request->ParamValues[m],'=',' '); m++; } } if (queryString) free(queryString); if (httpCookie) free(httpCookie); return(m); } void getword(char *word, char *line, char stop) { int x = 0,y; for(x=0; ((line[x]) && (line[x] != stop)); x++) word[x] = line[x]; word[x] = '\0'; if(line[x]) ++x; y=0; while((line[y++] = line[x++])); } char *makeword_skip(char *line, char stop, char skip) { int x = 0,y,offset=0; char *word = (char *) msSmallMalloc(sizeof(char) * (strlen(line) + 1)); for(x=0; ((line[x]) && (line[x] == skip)); x++); offset = x; for(x=offset; ((line[x]) && (line[x] != stop)); x++) word[x-offset] = line[x]; word[x-offset] = '\0'; if(line[x]) ++x; y=0; while((line[y++] = line[x++])); return word; } char *makeword(char *line, char stop) { int x = 0,y; char *word = (char *) msSmallMalloc(sizeof(char) * (strlen(line) + 1)); for(x=0; ((line[x]) && (line[x] != stop)); x++) word[x] = line[x]; word[x] = '\0'; if(line[x]) ++x; y=0; while((line[y++] = line[x++])); return word; } char *fmakeword(FILE *f, char stop, int *cl) { int wsize; char *word; int ll; wsize = 102400; ll=0; word = (char *) msSmallMalloc(sizeof(char) * (wsize + 1)); while(1) { word[ll] = (char)fgetc(f); if(ll==wsize) { word[ll+1] = '\0'; wsize+=102400; word = (char *)msSmallRealloc(word,sizeof(char)*(wsize+1)); } --(*cl); if((word[ll] == stop) || (feof(f)) || (!(*cl))) { if(word[ll] != stop) ll++; word[ll] = '\0'; word = (char *) msSmallRealloc(word, ll+1); return word; } ++ll; } } char x2c(char *what) { register char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return(digit); } void unescape_url(char *url) { register int x,y; for(x=0,y=0; url[y]; ++x,++y) { if((url[x] = url[y]) == '%') { url[x] = x2c(&url[y+1]); y+=2; } } url[x] = '\0'; } void plustospace(char *str) { register int x; for(x=0; str[x]; x++) if(str[x] == '+') str[x] = ' '; } int rind(char *s, char c) { register int x; for(x=strlen(s) - 1; x != -1; x--) if(s[x] == c) return x; return -1; } int _getline(char *s, int n, FILE *f) { register int i=0; while(1) { s[i] = (char)fgetc(f); if(s[i] == CR) s[i] = fgetc(f); if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) { s[i] = '\0'; return (feof(f) ? 1 : 0); } ++i; } } void send_fd(FILE *f, FILE *fd) { char c; while (1) { c = fgetc(f); if(feof(f)) return; fputc(c,fd); } } int ind(char *s, char c) { register int x; for(x=0; s[x]; x++) if(s[x] == c) return x; return -1; } /* ** patched version according to CERT advisory... */ void escape_shell_cmd(char *cmd) { register int x,y,l; l=strlen(cmd); for(x=0; cmd[x]; x++) { if(ind("&;`'\"|*?~<>^()[]{}$\\\n",cmd[x]) != -1) { for(y=l+1; y>x; y--) cmd[y] = cmd[y-1]; l++; /* length has been increased */ cmd[x] = '\\'; x++; /* skip the character */ } } } /* ** Allocate a new request holder structure */ cgiRequestObj *msAllocCgiObj() { cgiRequestObj *request = (cgiRequestObj *)malloc(sizeof(cgiRequestObj)); if(!request) return NULL; request->ParamNames = (char **) msSmallMalloc(MS_DEFAULT_CGI_PARAMS*sizeof(char*)); request->ParamValues = (char **) msSmallMalloc(MS_DEFAULT_CGI_PARAMS*sizeof(char*)); request->NumParams = 0; request->type = MS_GET_REQUEST; request->contenttype = NULL; request->postrequest = NULL; request->httpcookiedata = NULL; return request; } void msFreeCgiObj(cgiRequestObj *request) { msFreeCharArray(request->ParamNames, request->NumParams); msFreeCharArray(request->ParamValues, request->NumParams); request->ParamNames = NULL; request->ParamValues = NULL; request->NumParams = 0; request->type = -1; msFree(request->contenttype); msFree(request->postrequest); msFree(request->httpcookiedata); request->contenttype = NULL; request->postrequest = NULL; request->httpcookiedata = NULL; msFree(request); } mapserver-6.4.1/mapthread.c0000644002461700001440000002643212261257215015434 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: UMN MapServer * Purpose: Support code for abstracting thread issues. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /****************************************************************************** THREAD-SAFE SUPPORT IN MAPSERVER ================================ If thread safety is enabled the USE_THREAD macro will be defined. Thread API (mapthread.h/c) -------------------------- This API is made available to avoid having dependencies on different thread libraries in lots of places in MapServer. It is intended to provide minimal services required by mapserver and isn't intended to be broadly useful. It should be available for Win32 and pthreads environments. It should be possible to implement for other thread libraries if needed. int msGetThreadId(): Returns the current threads integer id. This can be used for making some information thread specific, as has been done for the global error context in maperror.c. void msAcquireLock(int): Acquires the indicated Mutex. If it is already held by another thread then this thread will block till the other thread releases it. If this thread already holds the mutex then behaviour is undefined. If the mutex id is not valid (not in the range 0 to TLOCK_STATIC_MAX) then results are undefined. void msReleaseLock(int): Releases the indicated mutex. If the lock id is invalid, or if the mutex is not currently held by this thread then results are undefined. It is incredibly important to ensure that any mutex that is acquired is released as soon as possible. Any flow of control that could result in a mutex not being release is going to be a disaster. The mutex numbers are defined in mapthread.h with the TLOCK_* codes. If you need a new mutex, add a #define in mapthread.h for it. Currently there is no "dynamic" mutex allocation, but this could be added. Making Things Thread-safe ------------------------- Generally, to make MapServer thread-safe it is necessary to ensure that different threads aren't read and updating common datastructures at the same time and that all appropriate state be kept thread specific. Generally this will mean: o The previously global error status (errorObj ms_error) is now thread specific. Use msGetErrorObj() to get the current threads error state. o Use of subcomponents that are not thread safe need to be protected by a Mutex (lock). Currently a mutex is used for the entire map file parsing operation (msLoadMap() in mapfile.c) since the yacc parser uses a number of global variables. It is also done with pj_init() from PROJ.4 since this does not appear to be thread safe. It isn't yet clear if pj_transform() is thread safe. It is expected that mutexes will need to be employed in a variety of other places to ensure serialized access to risky functionality. This may apply to sublibraries like GDAL for instance. If a new section that is not thread-safe is identified (and assuming it can't be internally modified to make it thread-safe easily), it is necessary to define a new mutex (#define a TLOCK code in mapthread.h), and then surround the resource with acquire and release lock calls. eg. msAcquireLock( TLOCK_PROJ ); if( !(p->proj = pj_init(p->numargs, p->args)) ) { msReleaseLock( TLOCK_PROJ ); msSetError(MS_PROJERR, pj_strerrno(pj_errno), "msProcessProjection()"); return(-1); } msReleaseLock( TLOCK_PROJ ); It is imperative that any acquired locks be released on all possible control paths or else the MapServer will lock up as other thread try to acquire the lock and block forever. Other Thread-safe Issues ------------------------ Some issues are not easily corrected with Mutexes or other similar mechanisms. The following restrictions currently apply to MapServer when trying to use it in thread-safe mode. Note that failure to adhere to these constraints will not usually generate nice error messages, instead operation will just fail sometimes. 1) It is currently assumed that a mapObj belongs only to one thread at a time. That is, there is no effort to syncronize access to a mapObj itself. 2) Stuff that results in a chdir() call are problematic. In particular, the .map file SHAPEPATH directive should not be used. Use full paths to data files instead. ******************************************************************************/ #include #include "mapserver.h" #include "mapthread.h" #if defined(USE_THREAD) static int thread_debug = 0; static char *lock_names[] = { NULL, "PARSER", "GDAL", "ERROROBJ", "PROJ", "TTF", "POOL", "SDE", "ORACLE", "OWS", "LAYER_VTABLE", "IOCONTEXT", "TMPFILE", "DEBUGOBJ", "OGR", "TIME", "FRIBIDI", "WXS", "GEOS", NULL }; #endif /************************************************************************/ /* ==================================================================== */ /* PTHREADS */ /* ==================================================================== */ /************************************************************************/ #if defined(USE_THREAD) && !defined(_WIN32) #include "pthread.h" static int mutexes_initialized = 0; static pthread_mutex_t mutex_locks[TLOCK_MAX]; /************************************************************************/ /* msThreadInit() */ /************************************************************************/ void msThreadInit() { static pthread_mutex_t core_lock = PTHREAD_MUTEX_INITIALIZER; if( thread_debug ) fprintf( stderr, "msThreadInit() (posix)\n" ); pthread_mutex_lock( &core_lock ); for( ; mutexes_initialized < TLOCK_STATIC_MAX; mutexes_initialized++ ) pthread_mutex_init( mutex_locks + mutexes_initialized, NULL ); pthread_mutex_unlock( &core_lock ); } /************************************************************************/ /* msGetThreadId() */ /************************************************************************/ int msGetThreadId() { return (int) pthread_self(); } /************************************************************************/ /* msAcquireLock() */ /************************************************************************/ void msAcquireLock( int nLockId ) { if( mutexes_initialized == 0 ) msThreadInit(); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msAcquireLock(%d/%s) (posix)\n", nLockId, lock_names[nLockId] ); pthread_mutex_lock( mutex_locks + nLockId ); } /************************************************************************/ /* msReleaseLock() */ /************************************************************************/ void msReleaseLock( int nLockId ) { assert( mutexes_initialized > 0 ); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msReleaseLock(%d/%s) (posix)\n", nLockId, lock_names[nLockId] ); pthread_mutex_unlock( mutex_locks + nLockId ); } #endif /* defined(USE_THREAD) && !defined(_WIN32) */ /************************************************************************/ /* ==================================================================== */ /* WIN32 THREADS */ /* ==================================================================== */ /************************************************************************/ #if defined(USE_THREAD) && defined(_WIN32) #include static int mutexes_initialized = 0; static HANDLE mutex_locks[TLOCK_MAX]; /************************************************************************/ /* msThreadInit() */ /************************************************************************/ void msThreadInit() { /* static pthread_mutex_t core_lock = PTHREAD_MUTEX_INITIALIZER; */ static HANDLE core_lock = NULL; if( mutexes_initialized >= TLOCK_STATIC_MAX ) return; if( thread_debug ) fprintf( stderr, "msThreadInit() (win32)\n" ); if( core_lock == NULL ) core_lock = CreateMutex( NULL, TRUE, NULL ); else WaitForSingleObject( core_lock, INFINITE ); for( ; mutexes_initialized < TLOCK_STATIC_MAX; mutexes_initialized++ ) mutex_locks[mutexes_initialized] = CreateMutex( NULL, FALSE, NULL ); ReleaseMutex( core_lock ); } /************************************************************************/ /* msGetThreadId() */ /************************************************************************/ int msGetThreadId() { return (int) GetCurrentThreadId(); } /************************************************************************/ /* msAcquireLock() */ /************************************************************************/ void msAcquireLock( int nLockId ) { if( mutexes_initialized == 0 ) msThreadInit(); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msAcquireLock(%d/%s) (win32)\n", nLockId, lock_names[nLockId] ); WaitForSingleObject( mutex_locks[nLockId], INFINITE ); } /************************************************************************/ /* msReleaseLock() */ /************************************************************************/ void msReleaseLock( int nLockId ) { assert( mutexes_initialized > 0 ); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msReleaseLock(%d/%s) (win32)\n", nLockId, lock_names[nLockId] ); ReleaseMutex( mutex_locks[nLockId] ); } #endif /* defined(USE_THREAD) && defined(_WIN32) */ mapserver-6.4.1/mapserver-config.h.in0000644002461700001440000000305512261257215017344 0ustar tbonfortusers#ifndef _MAPSERVER_CONFIG_H #define _MAPSERVER_CONFIG_H #cmakedefine USE_PROJ 1 #cmakedefine USE_GD 1 #cmakedefine USE_GD_GIF 1 #cmakedefine USE_GD_PNG 1 #cmakedefine USE_GD_JPEG 1 #cmakedefine USE_GD_FREETYPE 1 #cmakedefine USE_POSTGIS 1 #cmakedefine USE_GDAL 1 #cmakedefine USE_OGR 1 #cmakedefine USE_WMS_SVR 1 #cmakedefine USE_WCS_SVR 1 #cmakedefine USE_WFS_SVR 1 #cmakedefine USE_SOS_SVR 1 #cmakedefine USE_WFS_LYR 1 #cmakedefine USE_WMS_LYR 1 #cmakedefine USE_CURL 1 #cmakedefine USE_CAIRO 1 #cmakedefine USE_GEOS 1 #cmakedefine USE_GIF 1 #cmakedefine USE_JPEG 1 #cmakedefine USE_PNG 1 #cmakedefine USE_ICONV 1 #cmakedefine USE_FRIBIDI 1 #cmakedefine USE_LIBXML2 1 #cmakedefine USE_FASTCGI 1 #cmakedefine USE_MYSQL 1 #cmakedefine USE_THREAD 1 #cmakedefine USE_KML 1 #cmakedefine USE_POINT_Z_M 1 #cmakedefine USE_ORACLESPATIAL 1 #cmakedefine USE_EXEMPI 1 #cmakedefine USE_XMLMAPFILE 1 #cmakedefine USE_GENERIC_MS_NINT 1 #cmakedefine POSTGIS_HAS_SERVER_VERSION 1 #cmakedefine USE_SVG_CAIRO 1 #cmakedefine USE_RSVG 1 #cmakedefine USE_SDE 1 #cmakedefine SDE64 1 /*windows specific hacks*/ #if defined(_WIN32) #cmakedefine REGEX_MALLOC 1 #cmakedefine USE_GENERIC_MS_NINT 1 #endif #cmakedefine HAVE_STRRSTR 1 #cmakedefine HAVE_STRCASECMP 1 #cmakedefine HAVE_STRCASESTR 1 #cmakedefine HAVE_STRDUP 1 #cmakedefine HAVE_STRLCAT 1 #cmakedefine HAVE_STRLCPY 1 #cmakedefine HAVE_STRLEN 1 #cmakedefine HAVE_STRNCASECMP 1 #cmakedefine HAVE_VSNPRINTF 1 #cmakedefine HAVE_DLFCN_H 1 #cmakedefine HAVE_LRINTF 1 #cmakedefine HAVE_LRINT 1 #cmakedefine HAVE_SYNC_FETCH_AND_ADD 1 #endif mapserver-6.4.1/mapproject.c0000644002461700001440000012045412261257215015632 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: projectionObj / PROJ.4 interface. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "mapproject.h" #include "mapthread.h" #include #include #include #include "mapaxisorder.h" #ifdef USE_PROJ static int msTestNeedWrap( pointObj pt1, pointObj pt2, pointObj pt2_geo, projectionObj *src_proj, projectionObj *dst_proj ); #endif /************************************************************************/ /* int msIsAxisInverted */ /* Check to see if we shoud invert the axis. */ /* */ /************************************************************************/ int msIsAxisInverted(int epsg_code) { const unsigned int row = epsg_code / 8; const unsigned char index = epsg_code % 8; /*check the static table*/ if ((row < sizeof(axisOrientationEpsgCodes)) && (axisOrientationEpsgCodes[row] & (1 << index))) return MS_TRUE; else return MS_FALSE; } /************************************************************************/ /* msProjectPoint() */ /************************************************************************/ int msProjectPoint(projectionObj *in, projectionObj *out, pointObj *point) { #ifdef USE_PROJ projUV p; int error; if( in && in->gt.need_geotransform ) { double x_out, y_out; x_out = in->gt.geotransform[0] + in->gt.geotransform[1] * point->x + in->gt.geotransform[2] * point->y; y_out = in->gt.geotransform[3] + in->gt.geotransform[4] * point->x + in->gt.geotransform[5] * point->y; point->x = x_out; point->y = y_out; } /* -------------------------------------------------------------------- */ /* If the source and destination are simple and equal, then do */ /* nothing. */ /* -------------------------------------------------------------------- */ if( in && in->numargs == 1 && out && out->numargs == 1 && strcmp(in->args[0],out->args[0]) == 0 ) { /* do nothing, no transformation required */ } /* -------------------------------------------------------------------- */ /* If we have a fully defined input coordinate system and */ /* output coordinate system, then we will use pj_transform. */ /* -------------------------------------------------------------------- */ else if( in && in->proj && out && out->proj ) { double z = 0.0; if( pj_is_latlong(in->proj) ) { point->x *= DEG_TO_RAD; point->y *= DEG_TO_RAD; } #if PJ_VERSION < 480 msAcquireLock( TLOCK_PROJ ); #endif error = pj_transform( in->proj, out->proj, 1, 0, &(point->x), &(point->y), &z ); #if PJ_VERSION < 480 msReleaseLock( TLOCK_PROJ ); #endif if( error || point->x == HUGE_VAL || point->y == HUGE_VAL ) { msSetError(MS_PROJERR,"proj says: %s","msProjectPoint()",pj_strerrno(error)); return MS_FAILURE; } if( pj_is_latlong(out->proj) ) { point->x *= RAD_TO_DEG; point->y *= RAD_TO_DEG; } } /* -------------------------------------------------------------------- */ /* Otherwise we fallback to using pj_fwd() or pj_inv() and */ /* assuming that the NULL projectionObj is supposed to be */ /* lat/long in the same datum as the other projectionObj. This */ /* is essentially a backwards compatibility mode. */ /* -------------------------------------------------------------------- */ else { /* nothing to do if the other coordinate system is also lat/long */ if( in == NULL && out != NULL && pj_is_latlong(out->proj) ) return MS_SUCCESS; if( out == NULL && in != NULL && pj_is_latlong(in->proj) ) return MS_SUCCESS; p.u = point->x; p.v = point->y; if(in==NULL || in->proj==NULL) { /* input coordinates are lat/lon */ p.u *= DEG_TO_RAD; /* convert to radians */ p.v *= DEG_TO_RAD; p = pj_fwd(p, out->proj); } else { if(out==NULL || out->proj==NULL) { /* output coordinates are lat/lon */ p = pj_inv(p, in->proj); p.u *= RAD_TO_DEG; /* convert to decimal degrees */ p.v *= RAD_TO_DEG; } else { /* need to go from one projection to another */ p = pj_inv(p, in->proj); p = pj_fwd(p, out->proj); } } if( p.u == HUGE_VAL || p.v == HUGE_VAL ) return MS_FAILURE; point->x = p.u; point->y = p.v; } if( out && out->gt.need_geotransform ) { double x_out, y_out; x_out = out->gt.invgeotransform[0] + out->gt.invgeotransform[1] * point->x + out->gt.invgeotransform[2] * point->y; y_out = out->gt.invgeotransform[3] + out->gt.invgeotransform[4] * point->x + out->gt.invgeotransform[5] * point->y; point->x = x_out; point->y = y_out; } return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectPoint()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectGrowRect() */ /************************************************************************/ #ifdef USE_PROJ static void msProjectGrowRect(projectionObj *in, projectionObj *out, rectObj *prj_rect, int *rect_initialized, pointObj *prj_point, int *failure ) { if( msProjectPoint(in, out, prj_point) == MS_SUCCESS ) { if( *rect_initialized ) { prj_rect->miny = MS_MIN(prj_rect->miny, prj_point->y); prj_rect->maxy = MS_MAX(prj_rect->maxy, prj_point->y); prj_rect->minx = MS_MIN(prj_rect->minx, prj_point->x); prj_rect->maxx = MS_MAX(prj_rect->maxx, prj_point->x); } else { prj_rect->minx = prj_rect->maxx = prj_point->x; prj_rect->miny = prj_rect->maxy = prj_point->y; *rect_initialized = MS_TRUE; } } else (*failure)++; } #endif /* def USE_PROJ */ /************************************************************************/ /* msProjectSegment() */ /* */ /* Interpolate along a line segment for which one end */ /* reprojects and the other end does not. Finds the horizon. */ /************************************************************************/ #ifdef USE_PROJ static int msProjectSegment( projectionObj *in, projectionObj *out, pointObj *start, pointObj *end ) { pointObj testPoint, subStart, subEnd; /* -------------------------------------------------------------------- */ /* Without loss of generality we assume the first point */ /* reprojects, and the second doesn't. If that is not the case */ /* then re-call with the points reversed. */ /* -------------------------------------------------------------------- */ testPoint = *start; if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) { testPoint = *end; if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) return MS_FAILURE; else return msProjectSegment( in, out, end, start ); } /* -------------------------------------------------------------------- */ /* We will apply a binary search till we are within out */ /* tolerance. */ /* -------------------------------------------------------------------- */ subStart = *start; subEnd = *end; #define TOLERANCE 0.01 while( fabs(subStart.x - subEnd.x) + fabs(subStart.y - subEnd.y) > TOLERANCE ) { pointObj midPoint; midPoint.x = (subStart.x + subEnd.x) * 0.5; midPoint.y = (subStart.y + subEnd.y) * 0.5; testPoint = midPoint; if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) subEnd = midPoint; else subStart = midPoint; } /* -------------------------------------------------------------------- */ /* Now reproject the end points and return. */ /* -------------------------------------------------------------------- */ *end = subStart; if( msProjectPoint( in, out, end ) == MS_FAILURE || msProjectPoint( in, out, start ) == MS_FAILURE ) return MS_FAILURE; else return MS_SUCCESS; } #endif /************************************************************************/ /* msProjectShapeLine() */ /* */ /* Reproject a single linestring, potentially splitting into */ /* more than one line string if there are over the horizon */ /* portions. */ /* */ /* For polygons, no splitting takes place, but over the horizon */ /* points are clipped, and one segment is run from the fall */ /* over the horizon point to the come back over the horizon point. */ /************************************************************************/ #ifdef USE_PROJ static int msProjectShapeLine(projectionObj *in, projectionObj *out, shapeObj *shape, int line_index) { int i; pointObj lastPoint, thisPoint, wrkPoint, firstPoint; lineObj *line = shape->line + line_index; lineObj *line_out = line; int valid_flag = 0; /* 1=true, -1=false, 0=unknown */ int numpoints_in = line->numpoints; int line_alloc = numpoints_in; int wrap_test; #ifdef USE_PROJ_FASTPATHS #define MAXEXTENT 20037508.34 #define M_PIby360 .0087266462599716479 #define MAXEXTENTby180 111319.4907777777777777777 if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) { for( i = line->numpoints-1; i >= 0; i-- ) { #define p_x line->point[i].x #define p_y line->point[i].y p_x *= MAXEXTENTby180; p_y = log(tan((90 + p_y) * M_PIby360)) * MS_RAD_TO_DEG; p_y *= MAXEXTENTby180; if (p_x > MAXEXTENT) p_x = MAXEXTENT; if (p_x < -MAXEXTENT) p_x = -MAXEXTENT; if (p_y > MAXEXTENT) p_y = MAXEXTENT; if (p_y < -MAXEXTENT) p_y = -MAXEXTENT; #undef p_x #undef p_y } return MS_SUCCESS; } #endif wrap_test = out != NULL && out->proj != NULL && pj_is_latlong(out->proj) && !pj_is_latlong(in->proj); line->numpoints = 0; if( numpoints_in > 0 ) firstPoint = line->point[0]; memset( &lastPoint, 0, sizeof(lastPoint) ); /* -------------------------------------------------------------------- */ /* Loop over all input points in linestring. */ /* -------------------------------------------------------------------- */ for( i=0; i < numpoints_in; i++ ) { int ms_err; wrkPoint = thisPoint = line->point[i]; ms_err = msProjectPoint(in, out, &wrkPoint ); /* -------------------------------------------------------------------- */ /* Apply wrap logic. */ /* -------------------------------------------------------------------- */ if( wrap_test && i > 0 && ms_err != MS_FAILURE ) { double dist; pointObj pt1Geo; if( line_out->numpoints > 0 ) pt1Geo = line_out->point[0]; else pt1Geo = wrkPoint; /* this is a cop out */ dist = wrkPoint.x - pt1Geo.x; if( fabs(dist) > 180.0 && msTestNeedWrap( thisPoint, firstPoint, pt1Geo, in, out ) ) { if( dist > 0.0 ) wrkPoint.x -= 360.0; else if( dist < 0.0 ) wrkPoint.x += 360.0; } } /* -------------------------------------------------------------------- */ /* Put result into output line with appropriate logic for */ /* failure breaking lines, etc. */ /* -------------------------------------------------------------------- */ if( ms_err == MS_FAILURE ) { /* We have started out invalid */ if( i == 0 ) { valid_flag = -1; } /* valid data has ended, we need to work out the horizon */ else if( valid_flag == 1 ) { pointObj startPoint, endPoint; startPoint = lastPoint; endPoint = thisPoint; if( msProjectSegment( in, out, &startPoint, &endPoint ) == MS_SUCCESS ) { line_out->point[line_out->numpoints++] = endPoint; } valid_flag = -1; } /* Still invalid ... */ else if( valid_flag == -1 ) { /* do nothing */ } } else { /* starting out valid. */ if( i == 0 ) { line_out->point[line_out->numpoints++] = wrkPoint; valid_flag = 1; } /* Still valid, nothing special */ else if( valid_flag == 1 ) { line_out->point[line_out->numpoints++] = wrkPoint; } /* we have come over the horizon, figure out where, start newline*/ else { pointObj startPoint, endPoint; startPoint = lastPoint; endPoint = thisPoint; if( msProjectSegment( in, out, &endPoint, &startPoint ) == MS_SUCCESS ) { lineObj newLine; /* force pre-allocation of lots of points room */ if( line_out->numpoints > 0 && shape->type == MS_SHAPE_LINE ) { newLine.numpoints = numpoints_in - i + 1; newLine.point = line->point; msAddLine( shape, &newLine ); /* new line is now lineout, but start without any points */ line_out = shape->line + shape->numlines-1; line_out->numpoints = 0; /* the shape->line array is realloc, refetch "line" */ line = shape->line + line_index; } else if( line_out == line && line->numpoints >= i-2 ) { newLine.numpoints = numpoints_in; newLine.point = line->point; msAddLine( shape, &newLine ); line = shape->line + line_index; line_out = shape->line + shape->numlines-1; line_out->numpoints = line->numpoints; line->numpoints = 0; /* * Now realloc this array large enough to hold all * the points we could possibly need to add. */ line_alloc = line_alloc * 2; line_out->point = (pointObj *) realloc(line_out->point, sizeof(pointObj) * line_alloc); } line_out->point[line_out->numpoints++] = startPoint; } line_out->point[line_out->numpoints++] = wrkPoint; valid_flag = 1; } } lastPoint = thisPoint; } /* -------------------------------------------------------------------- */ /* Make sure that polygons are closed, even if the trip over */ /* the horizon left them unclosed. */ /* -------------------------------------------------------------------- */ if( shape->type == MS_SHAPE_POLYGON && line_out->numpoints > 2 && (line_out->point[0].x != line_out->point[line_out->numpoints-1].x || line_out->point[0].y != line_out->point[line_out->numpoints-1].y) ) { /* make a copy because msAddPointToLine can realloc the array */ pointObj sFirstPoint = line_out->point[0]; msAddPointToLine( line_out, &sFirstPoint ); } return(MS_SUCCESS); } #endif /************************************************************************/ /* msProjectShape() */ /************************************************************************/ int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape) { #ifdef USE_PROJ int i; #ifdef USE_PROJ_FASTPATHS int j; if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) { for( i = shape->numlines-1; i >= 0; i-- ) { for( j = shape->line[i].numpoints-1; j >= 0; j-- ) { #define p_x shape->line[i].point[j].x #define p_y shape->line[i].point[j].y p_x *= MAXEXTENTby180; p_y = log(tan((90 + p_y) * M_PIby360)) * MS_RAD_TO_DEG; p_y *= MAXEXTENTby180; if (p_x > MAXEXTENT) p_x = MAXEXTENT; if (p_x < -MAXEXTENT) p_x = -MAXEXTENT; if (p_y > MAXEXTENT) p_y = MAXEXTENT; if (p_y < -MAXEXTENT) p_y = -MAXEXTENT; #undef p_x #undef p_y } } msComputeBounds( shape ); /* fixes bug 1586 */ return MS_SUCCESS; } #endif for( i = shape->numlines-1; i >= 0; i-- ) { if( shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON ) { if( msProjectShapeLine( in, out, shape, i ) == MS_FAILURE ) msShapeDeleteLine( shape, i ); } else if( msProjectLine(in, out, shape->line+i ) == MS_FAILURE ) { msShapeDeleteLine( shape, i ); } } if( shape->numlines == 0 ) { msFreeShape( shape ); return MS_FAILURE; } else { msComputeBounds( shape ); /* fixes bug 1586 */ return(MS_SUCCESS); } #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectShape()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectLine() */ /* */ /* This function is now normally only used for point data. */ /* msProjectShapeLine() is used for lines and polygons and has */ /* lots of logic to handle horizon crossing. */ /************************************************************************/ int msProjectLine(projectionObj *in, projectionObj *out, lineObj *line) { #ifdef USE_PROJ int i, be_careful = 1; if( be_careful ) be_careful = out->proj != NULL && pj_is_latlong(out->proj) && !pj_is_latlong(in->proj); if( be_careful ) { pointObj startPoint, thisPoint; /* locations in projected space */ startPoint = line->point[0]; for(i=0; inumpoints; i++) { double dist; thisPoint = line->point[i]; /* ** Read comments before msTestNeedWrap() to better understand ** this dateline wrapping logic. */ msProjectPoint(in, out, &(line->point[i])); if( i > 0 ) { dist = line->point[i].x - line->point[0].x; if( fabs(dist) > 180.0 ) { if( msTestNeedWrap( thisPoint, startPoint, line->point[0], in, out ) ) { if( dist > 0.0 ) { line->point[i].x -= 360.0; } else if( dist < 0.0 ) { line->point[i].x += 360.0; } } } } } } else { for(i=0; inumpoints; i++) { if( msProjectPoint(in, out, &(line->point[i])) == MS_FAILURE ) return MS_FAILURE; } } return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectLine()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectRectGrid() */ /************************************************************************/ #define NUMBER_OF_SAMPLE_POINTS 100 int msProjectRectGrid(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef USE_PROJ pointObj prj_point; rectObj prj_rect; int rect_initialized = MS_FALSE, failure=0; int ix, iy; double dx, dy; double x, y; dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS; dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS; /* first ensure the top left corner is processed, even if the rect turns out to be degenerate. */ prj_point.x = rect->minx; prj_point.y = rect->miny; #ifdef USE_POINT_Z_M prj_point.z = 0.0; prj_point.m = 0.0; #endif /* USE_POINT_Z_M */ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); failure = 0; for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) { x = rect->minx + ix * dx; for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) { y = rect->miny + iy * dy; prj_point.x = x; prj_point.y = y; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); } } if( !rect_initialized ) { prj_rect.minx = 0; prj_rect.maxx = 0; prj_rect.miny = 0; prj_rect.maxy = 0; msSetError(MS_PROJERR, "All points failed to reproject.", "msProjectRect()"); } else { msDebug( "msProjectRect(): some points failed to reproject, doing internal sampling.\n" ); } rect->minx = prj_rect.minx; rect->miny = prj_rect.miny; rect->maxx = prj_rect.maxx; rect->maxy = prj_rect.maxy; if( !rect_initialized ) return MS_FAILURE; else return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectRectTraditionalEdge() */ /************************************************************************/ #ifdef notdef static int msProjectRectTraditionalEdge(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef USE_PROJ pointObj prj_point; rectObj prj_rect; int rect_initialized = MS_FALSE, failure=0; int ix, iy; double dx, dy; double x, y; dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS; dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS; /* first ensure the top left corner is processed, even if the rect turns out to be degenerate. */ prj_point.x = rect->minx; prj_point.y = rect->miny; #ifdef USE_POINT_Z_M prj_point.z = 0.0; prj_point.m = 0.0; #endif /* USE_POINT_Z_M */ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); /* sample along top and bottom */ if(dx > 0) { for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) { x = rect->minx + ix * dx; prj_point.x = x; prj_point.y = rect->miny; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); prj_point.x = x; prj_point.y = rect->maxy; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); } } /* sample along left and right */ if(dy > 0) { for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) { y = rect->miny + iy * dy; prj_point.y = y; prj_point.x = rect->minx; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); prj_point.x = rect->maxx; prj_point.y = y; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); } } /* ** If there have been any failures around the edges, then we had better ** try and fill in the interior to get a close bounds. */ if( failure > 0 ) return msProjectRectGrid( in, out, rect ); rect->minx = prj_rect.minx; rect->miny = prj_rect.miny; rect->maxx = prj_rect.maxx; rect->maxy = prj_rect.maxy; if( !rect_initialized ) return MS_FAILURE; else return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()"); return(MS_FAILURE); #endif } #endif /* def notdef */ /************************************************************************/ /* msProjectRectAsPolygon() */ /************************************************************************/ static int msProjectRectAsPolygon(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef USE_PROJ shapeObj polygonObj; lineObj ring; /* pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4]; */ pointObj *ringPoints; int ix, iy; double dx, dy; /* -------------------------------------------------------------------- */ /* Build polygon as steps around the source rectangle. */ /* -------------------------------------------------------------------- */ dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS; dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS; if(dx==0 && dy==0) { pointObj foo; msDebug( "msProjectRect(): Warning: degenerate rect {%f,%f,%f,%f}\n",rect->minx,rect->miny,rect->minx,rect->miny ); foo.x = rect->minx; foo.y = rect->miny; msProjectPoint(in,out,&foo); rect->minx=rect->maxx=foo.x; rect->miny=rect->maxy=foo.y; return MS_SUCCESS; } ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*4+4); ring.point = ringPoints; ring.numpoints = 0; msInitShape( &polygonObj ); polygonObj.type = MS_SHAPE_POLYGON; /* sample along top */ if(dx != 0) { for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) { ringPoints[ring.numpoints].x = rect->minx + ix * dx; ringPoints[ring.numpoints++].y = rect->miny; } } /* sample on along right side */ if(dy != 0) { for(iy = 1; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) { ringPoints[ring.numpoints].x = rect->maxx; ringPoints[ring.numpoints++].y = rect->miny + iy * dy; } } /* sample along bottom */ if(dx != 0) { for(ix = NUMBER_OF_SAMPLE_POINTS-1; ix >= 0; ix-- ) { ringPoints[ring.numpoints].x = rect->minx + ix * dx; ringPoints[ring.numpoints++].y = rect->maxy; } } /* sample on along left side */ if(dy != 0) { for(iy = NUMBER_OF_SAMPLE_POINTS-1; iy >= 0; iy-- ) { ringPoints[ring.numpoints].x = rect->minx; ringPoints[ring.numpoints++].y = rect->miny + iy * dy; } } msAddLineDirectly( &polygonObj, &ring ); /* -------------------------------------------------------------------- */ /* Attempt to reproject. */ /* -------------------------------------------------------------------- */ msProjectShapeLine( in, out, &polygonObj, 0 ); /* If no points reprojected, try a grid sampling */ if( polygonObj.numlines == 0 || polygonObj.line[0].numpoints == 0 ) { msFreeShape( &polygonObj ); return msProjectRectGrid( in, out, rect ); } /* -------------------------------------------------------------------- */ /* Collect bounds. */ /* -------------------------------------------------------------------- */ rect->minx = rect->maxx = polygonObj.line[0].point[0].x; rect->miny = rect->maxy = polygonObj.line[0].point[0].y; for( ix = 1; ix < polygonObj.line[0].numpoints; ix++ ) { pointObj *pnt = polygonObj.line[0].point + ix; rect->minx = MS_MIN(rect->minx,pnt->x); rect->maxx = MS_MAX(rect->maxx,pnt->x); rect->miny = MS_MIN(rect->miny,pnt->y); rect->maxy = MS_MAX(rect->maxy,pnt->y); } msFreeShape( &polygonObj ); /* -------------------------------------------------------------------- */ /* Special case to handle reprojection from "more than the */ /* whole world" projected coordinates that sometimes produce a */ /* region greater than 360 degrees wide due to various wrapping */ /* logic. */ /* -------------------------------------------------------------------- */ if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj) && rect->maxx - rect->minx > 360.0 ) { rect->maxx = 180; rect->minx = -180; } return MS_SUCCESS; #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectRect() */ /************************************************************************/ int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef notdef return msProjectRectTraditionalEdge( in, out, rect ); #else return msProjectRectAsPolygon( in, out, rect ); #endif } /************************************************************************/ /* msProjectionsDiffer() */ /************************************************************************/ /* ** Compare two projections, and return MS_TRUE if they differ. ** ** For now this is implemented by exact comparison of the projection ** arguments, but eventually this should call a PROJ.4 function with ** more awareness of the issues. ** ** NOTE: MS_FALSE is returned if either of the projection objects ** has no arguments, since reprojection won't work anyways. */ int msProjectionsDiffer( projectionObj *proj1, projectionObj *proj2 ) { int i; if( proj1->numargs == 0 || proj2->numargs == 0 ) return MS_FALSE; if( proj1->numargs != proj2->numargs ) return MS_TRUE; /* This test should be more rigerous. */ if( proj1->gt.need_geotransform || proj2->gt.need_geotransform ) return MS_TRUE; for( i = 0; i < proj1->numargs; i++ ) { if( strcmp(proj1->args[i],proj2->args[i]) != 0 ) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* msTestNeedWrap() */ /************************************************************************/ /* Frank Warmerdam, Nov, 2001. See Also: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=15 Proposal: Modify msProjectLine() so that it "dateline wraps" objects when necessary in order to preserve their shape when reprojecting to lat/long. This will be accomplished by: 1) As each vertex is reprojected, compare the X distance between that vertex and the previous vertex. If it is less than 180 then proceed to the next vertex without any special logic, otherwise: 2) Reproject the center point of the line segment from the last vertex to the current vertex into lat/long. Does it's longitude lie between the longitudes of the start and end point. If yes, return to step 1) for the next vertex ... everything is fine. 3) We have determined that this line segment is suffering from 360 degree wrap to keep in the -180 to +180 range. Now add or subtract 360 degrees as determined from the original sign of the distances. This is similar to the code there now (though disabled in CVS); however, it will ensure that big boxes will remain big, and not get dateline wrapped because of the extra test in step 2). However step 2 is invoked only very rarely so this process takes little more than the normal process. In fact, if we were sufficiently concerned about performance we could do a test on the shape MBR in lat/long space, and if the width is less than 180 we know we never need to even do test 1). What doesn't this resolve: This ensures that individual lines are kept in the proper shape when reprojected to geographic space. However, it does not: o Ensure that all rings of a polygon will get transformed to the same "side" of the world. Depending on starting points of the different rings it is entirely possible for one ring to end up in the -180 area and another ring from the same polygon to end up in the +180 area. We might possibly be able to achieve this though, by treating the multi-ring polygon as a whole and testing the first point of each additional ring against the last vertex of the previous ring (or any previous vertex for that matter). o It does not address the need to cut up lines and polygons into distinct chunks to preserve the correct semantics. Really a polygon that spaces the dateline in a -180 to 180 view should get split into two polygons. We haven't addressed that, though if it were to be addressed, it could be done as a followon and distinct step from what we are doing above. In fact this sort of improvement (split polygons based on dateline or view window) should be done for all lat/long shapes regardless of whether they are being reprojected from another projection. o It does not address issues related to viewing rectangles that go outside the -180 to 180 longitude range. For instance, it is entirely reasonable to want a 160 to 200 longitude view to see an area on the dateline clearly. Currently shapes in the -180 to -160 range which should be displayed in the 180 to 200 portion of that view will not be because there is no recogition that they belong there. */ #ifdef USE_PROJ static int msTestNeedWrap( pointObj pt1, pointObj pt2, pointObj pt2_geo, projectionObj *in, projectionObj *out ) { pointObj middle; middle.x = (pt1.x + pt2.x) * 0.5; middle.y = (pt1.y + pt2.y) * 0.5; if( msProjectPoint( in, out, &pt1 ) == MS_FAILURE || msProjectPoint( in, out, &pt2 ) == MS_FAILURE || msProjectPoint( in, out, &middle ) == MS_FAILURE ) return 0; /* * If the last point was moved, then we are considered due for a * move to. */ if( fabs(pt2_geo.x-pt2.x) > 180.0 ) return 1; /* * Otherwise, test to see if the middle point transforms * to be between the end points. If yes, no wrapping is needed. * Otherwise wrapping is needed. */ if( (middle.x < pt1.x && middle.x < pt2_geo.x) || (middle.x > pt1.x && middle.x > pt2_geo.x) ) return 1; else return 0; } #endif /* def USE_PROJ */ /************************************************************************/ /* msProjFinder() */ /************************************************************************/ #ifdef USE_PROJ static char *ms_proj_lib = NULL; static char *last_filename = NULL; static const char *msProjFinder( const char *filename) { if( last_filename != NULL ) free( last_filename ); if( filename == NULL ) return NULL; if( ms_proj_lib == NULL ) return filename; last_filename = (char *) malloc(strlen(filename)+strlen(ms_proj_lib)+2); sprintf( last_filename, "%s/%s", ms_proj_lib, filename ); return last_filename; } #endif /* def USE_PROJ */ /************************************************************************/ /* msSetPROJ_LIB() */ /************************************************************************/ void msSetPROJ_LIB( const char *proj_lib, const char *pszRelToPath ) { #ifdef USE_PROJ static int finder_installed = 0; char *extended_path = NULL; /* Handle relative path if applicable */ if( proj_lib && pszRelToPath && proj_lib[0] != '/' && proj_lib[0] != '\\' && !(proj_lib[0] != '\0' && proj_lib[1] == ':') ) { struct stat stat_buf; extended_path = (char*) msSmallMalloc(strlen(pszRelToPath) + strlen(proj_lib) + 10); sprintf( extended_path, "%s/%s", pszRelToPath, proj_lib ); #ifndef S_ISDIR # define S_ISDIR(x) ((x) & S_IFDIR) #endif if( stat( extended_path, &stat_buf ) == 0 && S_ISDIR(stat_buf.st_mode) ) proj_lib = extended_path; } msAcquireLock( TLOCK_PROJ ); if( finder_installed == 0 && proj_lib != NULL) { finder_installed = 1; pj_set_finder( msProjFinder ); } if (proj_lib == NULL) pj_set_finder(NULL); if( ms_proj_lib != NULL ) { free( ms_proj_lib ); ms_proj_lib = NULL; } if( last_filename != NULL ) { free( last_filename ); last_filename = NULL; } if( proj_lib != NULL ) ms_proj_lib = msStrdup( proj_lib ); msReleaseLock( TLOCK_PROJ ); if ( extended_path ) msFree( extended_path ); #endif } /************************************************************************/ /* msGetProjectionString() */ /* */ /* Return the projection string. */ /************************************************************************/ char *msGetProjectionString(projectionObj *proj) { char *pszProjString = NULL; int i = 0, nLen = 0; if (proj) { /* -------------------------------------------------------------------- */ /* Alloc buffer large enough to hold the whole projection defn */ /* -------------------------------------------------------------------- */ for (i=0; inumargs; i++) { if (proj->args[i]) nLen += (strlen(proj->args[i]) + 2); } pszProjString = (char*)malloc(sizeof(char) * nLen+1); pszProjString[0] = '\0'; /* -------------------------------------------------------------------- */ /* Plug each arg into the string with a '+' prefix */ /* -------------------------------------------------------------------- */ for (i=0; inumargs; i++) { if (!proj->args[i] || strlen(proj->args[i]) == 0) continue; if (pszProjString[0] == '\0') { /* no space at beginning of line */ if (proj->args[i][0] != '+') strcat(pszProjString, "+"); } else { if (proj->args[i][0] != '+') strcat(pszProjString, " +"); else strcat(pszProjString, " "); } strcat(pszProjString, proj->args[i]); } } return pszProjString; } /************************************************************************/ /* msAxisNormalizePoints() */ /* */ /* Convert the passed points to "easting, northing" axis */ /* orientation if they are not already. */ /************************************************************************/ void msAxisNormalizePoints( projectionObj *proj, int count, double *x, double *y ) { int i; const char *axis = NULL; for( i = 0; i < proj->numargs; i++ ) { if( strstr(proj->args[i],"epsgaxis=") != NULL ) { axis = strstr(proj->args[i],"=") + 1; break; } } if( axis == NULL ) return; if( strcasecmp(axis,"en") == 0 ) return; if( strcasecmp(axis,"ne") != 0 ) { msDebug( "msAxisNormalizePoints(): odd +epsgaxis= value: '%s'.", axis ); return; } /* Switch axes */ for( i = 0; i < count; i++ ) { double tmp; tmp = x[i]; x[i] = y[i]; y[i] = tmp; } } /************************************************************************/ /* msAxisDenormalizePoints() */ /* */ /* Convert points from easting,northing orientation to the */ /* preferred epsg orientation of this projectionObj. */ /************************************************************************/ void msAxisDenormalizePoints( projectionObj *proj, int count, double *x, double *y ) { /* For how this is essentially identical to normalizing */ msAxisNormalizePoints( proj, count, x, y ); } mapserver-6.4.1/tests/0000755002461700001440000000000012261257216014457 5ustar tbonfortusersmapserver-6.4.1/tests/line.shx0000644002461700001440000000015412261257215016131 0ustar tbonfortusers' 6èÀ¿BwIœ­I@À?BwIœ­I@2(mapserver-6.4.1/tests/vera/0000755002461700001440000000000012261257215015413 5ustar tbonfortusersmapserver-6.4.1/tests/vera/RELEASENOTES.TXT0000644002461700001440000001766012261257215017717 0ustar tbonfortusersBitstream Vera Fonts - April 16, 2003 ===================================== The version number of these fonts is 1.10 to distinguish them from the beta test fonts. Note that the Vera copyright is incorporated in the fonts themselves. The License field in the fonts contains the copyright license as it appears below. The TrueType copyright field is not large enough to contain the full license, so the license is incorporated (as you might think if you thought about it) into the license field, which unfortunately can be obscure to find. (In pfaedit, see: Element->Font Info->TTFNames->License). Our apologies for it taking longer to complete the fonts than planned. Beta testers requested a tighter line spacing (less leading) and Jim Lyles redesigned Vera's accents to bring its line spacing to more typical of other fonts. This took additional time and effort. Our thanks to Jim for this effort above and beyond the call of duty. There are four monospace and sans faces (normal, oblique, bold, bold oblique) and two serif faces (normal and bold). Fontconfig/Xft2 (see www.fontconfig.org) can artificially oblique the serif faces for you: this loses hinting and distorts the faces slightly, but is visibly different than normal and bold, and reasonably pleasing. On systems with fontconfig 2.0 or 2.1 installed, making your sans, serif and monospace fonts default to these fonts is very easy. Just drop the file local.conf into your /etc/fonts directory. This will make the Bitstream fonts your default fonts for all applications using fontconfig (if sans, serif, or monospace names are used, as they often are as default values in many desktops). The XML in local.conf may need modification to enable subpixel decimation, if appropriate, however, the commented out phrase does so for XFree86 4.3, in the case that the server does not have sufficient information to identify the use of a flat panel. Fontconfig 2.2 adds Vera to the list of font families and will, by default use it as the default sans, serif and monospace fonts. During the testing of the final Vera fonts, we learned that screen fonts in general are only typically hinted to work correctly at integer pixel sizes. Vera is coded internally for integer sizes only. We need to investigate further to see if there are commonly used fonts that are hinted to be rounded but are not rounded to integer sizes due to oversights in their coding. Most fonts work best at 8 pixels and below if anti-aliased only, as the amount of work required to hint well at smaller and smaller sizes becomes astronomical. GASP tables are typically used to control whether hinting is used or not, but Freetype/Xft does not currently support GASP tables (which are present in Vera). To mitigate this problem, both for Vera and other fonts, there will be (very shortly) a new fontconfig 2.2 release that will, by default not apply hints if the size is below 8 pixels. if you should have a font that in fact has been hinted more agressively, you can use fontconfig to note this exception. We believe this should improve many hinted fonts in addition to Vera, though implemeting GASP support is likely the right long term solution. Font rendering in Gnome or KDE is the combination of algorithms in Xft2 and Freetype, along with hinting in the fonts themselves. It is vital to have sufficient information to disentangle problems that you may observe. Note that having your font rendering system set up correctly is vital to proper judgement of problems of the fonts: * Freetype may or may not be configured to in ways that may implement execution of possibly patented (in some parts of the world) TrueType hinting algorithms, particularly at small sizes. Best results are obtained while using these algorithms. * The freetype autohinter (used when the possibly patented algorithms are not used) continues to improve with each release. If you are using the autohinter, please ensure you are using an up to date version of freetype before reporting problems. * Please identify what version of freetype you are using in any bug reports, and how your freetype is configured. * Make sure you are not using the freetype version included in XFree86 4.3, as it has bugs that significantly degrade most fonts, including Vera. if you build XFree86 4.3 from source yourself, you may have installed this broken version without intending it (as I did). Vera was verified with the recently released Freetype 2.1.4. On many systems, 'ldd" can be used to see which freetype shared library is actually being used. * Xft/X Render does not (yet) implement gamma correction. This causes significant problems rendering white text on a black background (causing partial pixels to be insufficiently shaded) if the gamma of your monitor has not been compensated for, and minor problems with black text on a while background. The program "xgamma" can be used to set a gamma correction value in the X server's color pallette. Most monitors have a gamma near 2. * Note that the Vera family uses minimal delta hinting. Your results on other systems when not used anti-aliased may not be entirely satisfying. We are primarily interested in reports of problems on open source systems implementing Xft2/fontconfig/freetype (which implements antialiasing and hinting adjustements, and sophisticated subpixel decimation on flatpanels). Also, the algorithms used by Xft2 adjust the hints to integer widths and the results are crisper on open source systems than on Windows or MacIntosh. * Your fontconfig may (probably does) predate the release of fontconfig 2.2, and you may see artifacts not present when the font is used at very small sizes with hinting enabled. "vc-list -V" can be used to see what version you have installed. We believe and hope that these fonts will resolve the problems reported during beta test. The largest change is the reduction of leading (interline spacing), which had annoyed a number of people, and reduced Vera's utility for some applcations. The Vera monospace font should also now make '0' and 'O' and '1' and 'l' more clearly distinguishable. The version of these fonts is version 1.10. Fontconfig should be choosing the new version of the fonts if both the released fonts and beta test fonts are installed (though please discard them: they have names of form tt20[1-12]gn.ttf). Note that older versions of fontconfig sometimes did not rebuild their cache correctly when new fonts are installed: please upgrade to fontconfig 2.2. "fc-cache -f" can be used to force rebuilding fontconfig's cache files. If you note problems, please send them to fonts at gnome dot org, with exactly which face and size and unicode point you observe the problem at. The xfd utility from XFree86 CVS may be useful for this (e.g. "xfd -fa sans"). A possibly more useful program to examine fonts at a variety of sizes is the "waterfall" program found in Keith Packard's CVS. $ cvs -d :pserver:anoncvs@keithp.com:/local/src/CVS login Logging in to :pserver:anoncvs@keithp.com:2401/local/src/CVS CVS password: $ cvs -d :pserver:anoncvs@keithp.com:/local/src/CVS co waterfall $ cd waterfall $ xmkmf -a $ make # make install # make install.man Again, please make sure you are running an up-to-date freetype, and that you are only examining integer sizes. Reporting Problems ================== Please send problem reports to fonts at gnome org, with the following information: 1. Version of Freetype, Xft2 and fontconfig 2. Whether TT hinting is being used, or the autohinter 3. Application being used 4. Character/Unicode code point that has problems (if applicable) 5. Version of which operating system 6. Please include a screenshot, when possible. Please check the fonts list archives before reporting problems to cut down on duplication. mapserver-6.4.1/tests/vera/README.TXT0000644002461700001440000000050012261257215016744 0ustar tbonfortusersContained herin is the Bitstream Vera font family. The Copyright information is found in the COPYRIGHT.TXT file (along with being incoporated into the fonts themselves). The releases notes are found in the file "RELEASENOTES.TXT". We hope you enjoy Vera! Bitstream, Inc. The Gnome Project mapserver-6.4.1/tests/vera/Vera.ttf0000644002461700001440000020061412261257215017032 0ustar tbonfortusersOS/2´_ôcëpVPCLTÑŠ^—ëÈ6cmap¤Ãè ±lXcvt ÿÓ9üüfpgmç´ñÄ&`‹gaspH glyf tAÏ&ìŠ~hdmx4ð!ìHheadÝ„¢ÐT6hheaEoëL$hmtx ÆŽ²´Ä0kernÜRÕ™½ -ŠlocaóËÒ=»„maxpG:ë, nameټȵßpost´Z/»¸ôŽprep;ñ øh::_:: dM0­l  ƒ p t › &   Y &  &   c . 5 ` õ s 0¡ & {Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera SansBitstreamVeraSans-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera SansBitstreamVeraSans-RomanRelease 1.10Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.com5¸ËËÁªœ¦¸fqË ²…u¸Ãˉ-˦ðÓª‡ËªJ3ËÙôT´œ99N´R¸çÍ7sÍ`s3¢V¦V9Åɸßsºé3¼Dßͪåªˤ{¸o{RÇÍššoËÍžÓðºƒÕ˜HžÕÁËöƒT3fÓǤ͚sÕ þ+¤´œbœ-ÕÕÕð{T¤¸#Ӹ˦Ãì“ Ó\qÛ…#¨H99`Õš#fy```{œw`ªé`b{Å{´RÍf¼fwÍ;…‰{ÍJ/œœ}oo5jo{®²-–{öƒT7öœáföÍD)fîs¸€@ÿûþúù%ø2÷–öõþôþó%òñ–ð%ïŠAïþî–í–ìúëúêþé:èBçþæ2åäSå–äŠAäSãâ/ãúâ/áþàþß2ÞÝ–ÜþÛÚ}Ù»ØþÖŠAÖ}ÕÔGÕ}ÔGÓÒÓþÒÑþÐþÏþÎþÍ–ÌËÌþËÊ2ÉþÆ…ÆÅÄþÃþÂþÁþÀþ¿þ¾þ½þ¼þ»þº¹†%¹þ¸·»¸þ·¶]·»·€¶µ%¶]@ÿ¶@µ%´þ³–²þ±þ°þ¯þ®d­¬«%¬d«ª«%ª©ŠA©ú¨þ§þ¦þ¥¤þ£¢£2¢¡d ŠA –Ÿþž žþ œ›œd›š›š™ ˜þ—– —þ– •ŠA•–”“”(“’ú‘»‘þ]»€Ž%]@Ž%þŒ‹.Œþ‹.І%ŠA‰ˆ ‰ˆ ‡†%‡d†…†%…„þƒ‚ƒþ‚þ€þþ@ÿ~}}~þ}}|d{T{%zþyþxw v uþtúsúrúqúpþoþnþl!kþjBjSiþh}gBfþeþdþcþbþa:`ú^ ]þ[þZþYX YúX WW2VþUTUBTSSRQJQþP OþNMNþMLþKJKþJIJI IH GþF–E–DþC-CúB»AK@þ?þ>=>=<=<; <@ÿ; :þ9þ878ú76765 65 43 21 2þ1 0/ 0 / .- .- ,2+*%+d*)*%)('%(A'%&% &% $þ#þ"!! dú d BþúBBþdþþþþBþ-B}dþ  þ   þ  þ-þdþ@-þ-þ¸d…++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++¶, °%Id°@QX ÈY!-,°%Id°@QX ÈY!-,  °P° y ¸ÿÿPXY°°%°%#á °P° y ¸ÿÿPXY°°%á-,KPX °ýEDY!-,°%E`D-,KSX°%°%EDY!!-,ED-fþ–f¤@ ûû/ÄÔì1ÔìÔì0!%!!füsüåþ–øòr)5Õ @@ƒ ü<ì2991/äüÌ0K° TX½ @ ÿÀ878Y¶ P ]%3#3#5ËËË¢þþÕýqþ›eŪéÕM@„üüÜì1ô<ì20K°TK°T[X½@ÿÀ878Y@0 @ P ` p   ¿ ]#!#oª$ªÕýÕ+ýÕ+ž¾`@1 ‡  ‡   üÌ91/<Ô<<ü<<Ô<<Ä2ì220@   ]!! !3!!!!#!#!5!!5!þÝT%Dh$i g8þ¡R>þ›h gþÛg¡hþÅ`Tþ¾if…þ²‡þaŸþašþ²™þbžþbž™NšŸªþÓm!(/Õ@U" '&( /)/))/B" ) *!††#Љ*Љ- ) " & 0ü<ìô<ü<ôäì1/äìÄÔäì2Äîî99990KSXíí9í9íY"K° TX½0@00ÿÀ878YK° TK°T[K°T[X½0ÿÀ00@878Y#.'5.546753.'>54&´diÒjfÑoÝÉÚÌd]®SS¯\ãÖãÖdtzqá{þÓ---´@AÈ$¬–£¼ëè¯*.þU#´œ©Ãš jXV`ÕþOnZXhqÿã)ð #'3•@6$%&%&'$'B’ ’.’$’ &Œ($‘4'!%   ! + 1 4üÄìôìîöî991ä2ô<äìîöîî0KSXííY"K° TK° T[K° T[K°T[K°T[K° T[X½4@44ÿÀ878Y"32654&'2#"&546"32654&%3#2#"&546ÑWccWUccUžº» º»ü—VcbWWcd1 üZ ž¼»ŸŸ¹º‘”„‚••‚ƒ•Ü»»ÛÛ»¼Ûa•‚„””„–ùó Û»½ÚÛ¼ºÜÿãþð 0Í@–  † †  † †††  !         B  (('•+•'”$‘Œ .  .'.'!!1üìÄÔÔìÆî99999991/ÆäöæîîÆ9990KSXíí9í9í9í9í9íí9í9ííí9Y"²2]@² " ) **&:4D ^YZ UZZY0g{›š™—• “••"™-  ' (   2'') #**(/2; 49?2J LKFO2VZ Y UY\_2j i`2uy z““—•œœŸš › š 2 2°29]]3267 >73#'#"5467.54632.#"ò[UÔ _¦Iþ{ü;Bº h]ühäƒñþΆ†02Þ¸S¥UWžDiƒ;#Q¡X’Â?@ýøYËr„þþ~þã“YW×€ác?}<¢Å$$¶/1oX3gŪoÕB@ „üì1ôì0K°TK°T[X½@ÿÀ878Y@ @P`p ]#oªÕýÕ+°þò{ O@˜—  Üä2ì991üì0K°TX½@ÿÀ878YK°TX½ÿÀ@878Y#&547{†‚ƒ… –•”—æþ>ççþ;åëÆàßÄì¤þòo @˜— Ü<ôì991üì03#654¤ –••– …ƒƒìþ<ßàþ:ëåÅççÂ=JÃðN@,  ™ ™ ‘    Ô<ä2Ü<ä2991ôÔ<ì2Äì2990%#'%%73%Ãþ™g:þ°rþ°:gþ™:PrPßÂÃbËþ‡yËbÃÂcËyþ‡ËÙÛ #@ œ  Üü<ü<ì1/Ô<ü<Ä0!!#!5!®-ýÓ¨ýÓ-ýÓªýÓ-ª-žÿÃþ@ žƒüìÔÌ1üì073#ðÓ¤Rþ¬þÀ@d߃¶œÜÌ1Ôì0!!dý僤ۮþ·ƒüì1/ì073#ÛÓÓþþÿB²Õ-@BŸ/Ä991ôì0KSXííY"3#ªýøªÕùm‡ÿãð #@   ‘Œ üìôì1äôìî0"32'2#"‹œœû þ÷ûûþ÷ PþÍþÌþÍþÍ3343 þsþ†þ‡þsyzáZÕ K@B     ÔìÄüì1/ì2ôìÔì0KSXY"K°TX½ ÿÀ @878Y´]7!5%3!!þJþ™eÊJü¤ªsH¸HúÕª–Jð¥@'B¡”  ‘   üÄÔìÀÀ91/ì2ôìôì0KSXíí9Y"K°TK°T[K°T[X½@ÿÀ878Y@2UVVzzv‡tvust‚†‚‚‚¨¨]]%!!567>54&#"5>32‰ÁüLs3aM§†_ÓxzÔXèE[þôªªªw‘:m—Iw–BCÌ12èÂ\¥pþëœÿãsð({@. † †     “  “#‘Œ£)&  )üÄÄÔìôì991ìäôäìæîîîî90K°TK°T[X½)@))ÿÀ878Y@ daa d!]!"&'532654&+532654&#"5>32?‘£þÐþè^ÇjTÈm¾Ç¹¥®¶•ž£˜S¾rsÉYæ Ž%ÄÝò%%Ã12–„•¦wps{$&´ Ѳ|«d¤Õ Œ@   B     ÜÔ<Äì291/äÔ<ì290KSXÉÉY"K° TK° T[X½@ÿÀ878Y@* *HYiwŠ+&+6NO O Vfuz… ]] !33##!5þþ5þÕÕÉý^%üãÍü3¨þ `ÞÿãdÕu@#†  ‰   Œ¤  üÄÔìÄî1ääôìæîþÄî90K°TK°T[X½@ÿÀ878YK°TX½ÿÀ@878Y!!>32!"&'532654&#"Ýý ,X,ú$þÔþï^ÃhZÀk­ÊÊ­Q¡TÕªþ’þîêñþõ Ë10¶œœ¶$&ÿã–ð $X@$ †   ¥  ‰"‘Œ% " !%üììôìä1äôäüäîîî90@ËËÍÍÍËˤ²]]"32654&.#">32# !2¤ˆŸŸˆˆŸŸ L›LÈÓ;²káþðâþýþîPL›;º¢¡»»¡¢ºy¸$&þòþïW]þïëæþêyb¥¨hÕc@B üÌÄ991/ôì0KSXííY"K°TX½@ÿÀ878Y@X9Hg°°]]!#!¨ÀýâÓþý3ÕVú+‹ÿã‹ð #/C@%  ' - ‘Œ'£0 $*$ !0üÄìôÄìîî991ìäôìîî990"32654&%&&54632#"$54632654&#"‹¥¥¦¥þ¥‚‘ÿÞßþ‘’£þ÷÷÷þ÷¤H‘ƒ‚““‚ƒ‘Åš‡‡š›†‡šV ²€³Ðг€² "ÆÙèèÙÆat‚‚tt‚‚ÿã‡ð$X@#†  ¥ ‰ ‘Œ%!"" %üìäôìì1äôìæþõîî90@ÄÂÀÀÀÂμé]]7532#"543 !"&2654&#"áLœKÈÓ:²làþûâþ±þåLœ>ˆŸŸˆˆŸŸ¸$& V\ëæþsþ†þŸþ[—º¢¡»»¡¢ºðÃ#@ƒ¦ƒü<ì21/ìôì073#3#ðÓÓÓÓþþ#þžÿÃ# %@ƒžƒ¦  ü<ì2ÔÌ1äüìî03#3#ðÓÓÓ¤R#þýÙ¬þÀ@Ù^Û¦M@*œœœœB¨§$#üì291ôì90KSXííííY" 5Ûûøúþðþ‘þ“¶ѦÑÙ`Û¢@ œœ#ü<Ä21ÔìÔì0!!!!Ùúþúþ¢¨ðªÙ^Û¦O@+œœœœB¨§$#ü<ì91ôì90KSXííííY"55Ùúþð¶þ/¦þ/¶m“°ð$p@+$  †ˆ•‘ƒ   &%ÜÄüìÔìî99991/îöþôîÍ9990K° TX½%@%%ÿÀ878Y¶y z z ]%3##546?>54&#"5>32‡ËËÅ¿8ZZ93ƒlO³a^Ág¸ßHZX/'þþ‘še‚VY5^1YnFC¼98ŸL‰VV/5<4‡þœq¢ L•@2  ©©L43¬0©7¬$©7CM34( (+(I+*(I,=MÜìüìþýþ<Æî991ÔÄüìþíÔÆÅî2Äî990K° TK° T[K°T[K°T[K°T[X½MÿÀMM@878Y@ NN/N?N]32654&#"#"&5463253>54&'&$#"3267#"$'&5476$32úŽ|{zy!<›g¬×Ø«gœ;’¥?@hþÕ°{â`±smiùhZ}þÙ˜¹þ¸€€†ˆ~R½Ôk{KOþÂþè£¤ŽŒ¥¤þHMIùÈÈúKLƒý ß±k¼Pƒ‹A@fþµÁŸþêjhmWQoagƒ}}I½¶J}‡® bæ{þùþÐhÕ º@A       B•    ÔÄ91/<äÔì90KSXííííííííY"² ]@:XvpŒ VXP ghxv|rwx‡ˆ€ ˜™–]] !3#!#¼þî%þ{å9Òˆý_ˆÕý®ú+þÉìÕ C@#• •• ­ . !üì2üìÔì9991/ììôìî90²"]!2654&#!2654&#%!2#!“D££þ¼+”‘‘”þ çú€|•¥þðûýèÉý݇‹Œ…fþ>orqp¦À±‰¢ ˘ÈÚsÿã'ð6@ ¡® •¡®•‘Œ 0üì2ì1äôìôìîöî0´].# !267# !2'fç‚ÿþð‚çfjí„þ­þz†S†íbÕ_^þÇþØþÙþÇ^_ÓHHŸghŸGɰÕ.@• •  2 üìôì99991/ìôì0²`]3 !%! )“ô5þáþËþBŸ²–þhþPþa/ûw.,¦þ—þ€þ~þ–É‹Õ .@•••­   üì2ÔÄÄ1/ììôìî0² ]!!!!!!ɰýÇý9øü>ÕªþFªýãªÉ#Õ )@••­ üì2ÔÄ1/ìôìî0² ]!!!!#ÉZýpPý°ÊÕªþHªý7sÿã‹ð9@ ••¡®•‘Œ43 üìüäüÄ1äôìôìþÔî990%!5!# !2&&# !26Ãþ¶uþæ þ¢þu‹^’opü‹þîþík¨Õ‘¦ýSU™mn™HF×_`þÎþÑþÒþÎ%É;Õ ,@•­ 8  üì2üì21/<ä2üì0²P ]3!3#!#ÉÊÞÊÊý"ÊÕýœdú+Çý9É“Õ9·¯üì1/ì0K°TX½ÿÀ@878Y@ 0@P`Ÿ]3#ÉÊÊÕú+ÿ–þf“Õ M@ •° 9 üìä991äüì990K°TX½ ÿÀ @878Y@ 0 @ P ` Ÿ ]3+53265ÉÊÍãM?†nÕú“þòôª–ÂÉjÕ ï@(B¯  üì2ÔÄ91/<ì290KSXííííY"²]@’ ((764GFCUgvwƒˆ”›ç    (+*66650 A@E@@@ b`hgwp ‹‹Ž š¶µÅÅ×Öèéèê÷øù,]q]q3! !#ÉÊžýþöý3ÊÕý‰wýHüãÏý1ÉjÕ%@ •:üìì1/äì0@ 0P€€]3!!ÉÊ×ü_ÕúÕªÉÕ ¿@4  B ¯   >  üìüì91/<Äì290KSXííííY"²p]@V   && & 45 i|{y €‚‚  #,'( 4<VY ej vy •›]]! !###É-}-ÅþËþÄÕüøú+üúáÉ3Õ y@B¯6 üìüì991/<ì2990KSXííY"² ]@068HGif€ FIWXeiy…Š•šŸ ]]!3!#É–ÄþðýjÄÕûáú+áûsÿãÙð #@•• ‘Œ 3üìüì1äôìî0"32' ! 'ÜþýÜÜþÿÜ:xþˆþÆþÅþ‡yLþ¸þåþæþ¸HH¤þ[þžþŸþ[¤bb¥ÉÕ:@••   ? üì2üì91/ôìÔì0@ ?_¯]32654&#%!2+#“þššþ8ÈûþÿûþÊ/ýÏ’‡†’¦ãÛÝâý¨sþøÙð R@*  B ••‘Œ    3üìüì9991Ääôìî990KSXíí9Y""32#'# ! 'ÜþýÜÜþÿ? ôÝ!#þÅþ‡y;:xÑLþ¸þåþæþ¸HHúÏþÝï¥ab¥þ[þžþüþŽÉTÕ±@5  B• •   ?  üì2üÄì99991/<ôìÔì9990KSXíí9Y"²@]@Bz%%%&'&&& 66FFhuuwˆˆ˜˜]]#.+#! 32654&#A{>ÍÙ¿J‹xÜÊÈüƒý‰þ’••’¼~þh–bý‰ÕÖØºOýƒ…‡ÿã¢ð'~@<    B ¡”••”%‘Œ( "-"(ÜÄìüìä99991äôäìîöîÆ90KSXí9í9Y"²)]¶)/)O)].#"!"&'532654&/.54$32HsÌ_¥³w¦zâ×þÝþçjï€{ìr­¼‡š{âÊõiÚ¤Å76€vce+Ù¶Ùà0/ÐEFˆ~n|-À«Æä&ÿúéÕJ@•@@Ôäüä1/ôì20K° TX½@ÿÀ878Y@  @ p Ÿ ]!!#!ïýîËýîÕªúÕ+²ÿã)ÕK@ •Œ  8Aüìüì1ä2ôì99990K°TX½@ÿÀ878Y¶Ÿ]332653! ²Ë®Ã®ËþßþæþåþßÕüuðÓÓð‹ü\þÜþÖ*$hÕ·@'B¯ÔÄ91/ì290KSXííííY"²P]@b*GGZ}ƒ *&&))% 833<<7HEEIIGYVfiizvvyyu€˜—)]]!3 3JýÆÓÙÚÒýÇÕûéú+D¦Õ {@I      B ¯    ÔÌ91/<ì2290KSXííííííííY"²]@ò  ($ >>4 0 LMB @ Yjkg ` {|€ –•     !   # $ %  <:5306 9 ? 0FFJ@E@BBB@@ D M @@XVY Pfgab```d d d wv{xwtyywpx  †‡ˆ‰… Š —Ÿ¯[]]3 3 3# #DÌ:9ã:9Íþ‰þþÅþÂþÕûîûîú+úð=;Õ ]@F      B ¯   ÔÄÜÄ91/<ì290KSXííííííííY"K° TK° T[K°T[X½ ÿÀ @878Y@¸ '' 486 KX[fkww †€‡‹… ”—–     &()&(' ) 54<;:;4 4 8 ? H O X _ eejjhiil l xyyx}  x €€ƒˆ…„ƒ ”——•“ Ÿ ¯ @]]3 3 # #ÙsuÙþ Ùþ\þYÚÕýÕ+ý3üø{ý…ÿüçÕ”@(B¯@@ Ôäüä91/ì290KSXííííY"² ]@<5000F@@@QQQe„“ &)78@ ghxp Ÿ ]]3 3#Ùž›ÙýðËÕýšfüòý9Ç\Õ ›@B••B ÜÄÔä991/ìôì0KSXííY"K° TK° T[X½ @ ÿÀ878Y@@ )&8HGH    / 59? GJO UYfio wx Ÿ ]]!!!5!s•üPÇû=°ügÕšûoªš‘°þòXS@©²©±CÜüÌ21üìôì0K° TX½ÿÀ@878YK°TK°T[X½@ÿÀ878Y!#3!°¨ððþXùüÿB²Õ-@BŸ/Ä991ôì0KSXííY"#ªªýøÕùm“Çþòo<@©²©±Cü<Üì1üìôì0K°TK°T[X½ÿÀ@878Y!53#5oþXïïøÞÙ¨ÛÕ@ ÜÌ91ôÌ290##¼ÉþHþHÉÕýÓ‹þu-ÿìþþ¬µ©ÄÄ1Ôì0!5ûØþ¬ªð‰f1@ ´³DÜì1ôì0K° TK°T[X½ÿÀ@878Y #o™þºfþŠv{ÿã-{ %¼@'  ©¹ †º¹#¸Œ   E&üìÌÔì22991/ÄäôüôìÆîî9990@n0000 0!0"?'@@@@ @!@"PPPP P!P"P'p'…‡‡‡ ‡!…"' 'ð'000 0!@@@ @!PPP P!``` `!ppp p!€€€ €!]]"326=7#5#"&5463!54&#"5>32¾ß¬o™¹¸¸?¼ˆ¬Ëýû§—`¶Te¾Zóð3f{bsÙ´)LýªfaÁ¢½À‹..ª''üºÿ㤠8@¹  ¹Œ¸—G Füì22ôì1/ìäôÄìÆî0¶`€ ]4&#"326>32#"&'#3å§’’§§’’§ýŽ:±{ÌÿÿÌ{±:¹¹/ËççËËççRdaþ¼þøþøþ¼ad¨qÿãç{?@†ˆ† ˆ ¹¹¸Œ HEüä2ì1äôìþôîõî0@ € ].#"3267#"!2çNP³ÆÆ³PNM¥]ýþÖ-U¢5¬++ãÍÍã++ª$$>:#qÿãZ8@¹¹Œ¸—G Eüìôì221/ìäôÄìÄî0¶`€ ]3#5#"3232654&#"¢¸¸:±|ËÿÿË|±ýǧ’’¨¨’’§¶^ùì¨daDDaþËççËËççqÿã{p@$ †ˆ©¹ »¹¸ ŒKEüìôìÄ91äôìäîîôî90@)?p Ðð?????,// , ooooo ]q]!3267# 32.#"ü² Í·jÇbcÐkþôþÇ)ü⸥ˆš¹^Z¾Ç44®*,8 CþÝÄ—´®ž/øp@ ©‡—¼    Lü<Äü<ÄÄ991/ä2üìî2990K° TX½ÿÀ@878YK°TX½@ÿÀ878Y¶@P ]#"!!##535463ø°cM/þѹ°°®½™Phcü/ÑN»«qþVZ{ (J@#  †¹¹&#¸'¼ ¹½& G E)üÄìôì221/ÄäìäôÄìþÕî990¶`*€* *]4&#"326!"&'5326=#"3253¢¥•”¥¥”•¥¸þþúa¬QQžRµ´9²|ÎüüÎ|²9¸=ÈÜÜÈÇÜÜëþâþé³,*½¿[cb::bcªºd4@ ‡¸ — N  Füì2ôì1/<ìôÄì90²`]#4&#"#3>32d¸||•¬¹¹B³uÁƤý\žŸž¾¤ý‡ýžedïÁy+@¾±¼Fü<ì21/äüì0@  @ P ` p ]3#3#Á¸¸¸¸`û éÿÛþVy D@ ¾ ‡½¼ ±O  Fü<ì2ä991ìäôìî990@ @P`p]3+532653#Á¸£µF1iL¸¸`ûŒÖÀœa™(麜 ¼@)B¼— F üì2ÔÄ91/<ìä90KSXííííY"² ]@_ ')+Vfgsw‚‰Ž“–—£    ('(++@ h` ‰…‰š—ª§¶ÅÖ÷ð÷ð]q]33 ##º¹%ëý®kðýǹüiãýôý¬#ýÝÁy"·—Füì1/ì0@ @P`pð]3#Á¸¸ùìº{"Z@&  ‡ ¸¼PPF#üì2üüüì91/<<äô<Äì290@0$P$p$$ $ $¿$ß$ÿ$ ]>32#4&#"#4&#"#3>32)EÀ‚¯¾¹ru¦¹rw¦¹¹?°yz«‰|võâý\ž¡œ¾¤ý‡ž¢›¿£ý‡`®gb|ºd{6@ ‡¸ ¼ N  Füì2ôì1/<äôÄì90´`Ï]#4&#"#3>32d¸||•¬¹¹B³uÁƤý\žŸž¾¤ý‡`®edïqÿãu{ J@¹¹ ¸Œ QEüìôì1äôìî0@#?{{   {  { ð]"32654&'2#"s”¬«•“¬¬“ðþîðñþïßçÉÉçèÈÇéœþÈþìþíþÇ98ºþV¤{>@¹¹¸Œ½¼ GFüì22ôì1äääôÄìÄî0@ `€ à]%#3>32#"&4&#"326s¹¹:±{ÌÿÿÌ{±8§’’§§’’§¨ý® ªdaþ¼þøþøþ¼aëËççËËççqþVZ{ >@¹  ¹¸Œ½¼ GEüìôì221äääôÄìÆî0@ `€ à]32654&#"#"3253#/§’’¨¨’’§s:±|ËÿÿË|±:¸¸/ËççËËççý®daDDadªùöºJ{0@  ‡¸ ¼ FüÄì21/äôìÄÔÌ90´PŸ].#"#3>32JI,œ§¹¹:º….´˾ý²`®fcoÿãÇ{'ç@<  S  SB †‰†‰¹¹%¸Œ( R"E(üÄìÔìä99991äôìþõîõî90KSXí9í9Y"²']@m   . , , , ; ; ; ; $( ( *//*(() )!$'† † † †      '/)?)_))€)) )ð)]]q.#"#"&'532654&/.54632‹N¨Z‰‰b”?Ä¥÷ØZÃlfÆa‚Œe«@«˜àÎf´?®((TT@I!*™‰œ¶##¾55YQKP%$•‚ž¬7òž8@©¼‡  Fü<Äü<Ä2991/ìô<Äì2990²¯]!!;#"&5#53w{þ…Ks½½Õ¢‡‡žþÂý ‰NšŸÒ`>®ÿãX`6@ ‡Œ ¼  NFüìôì21/ä2ôÄì90´`Ï]332653#5#"&®¸||•­¸¸C±uÁȺ¦ýaŸŸ¾¤{û ¬fcð=`@'B¿ÔÄ91/ì290KSXííííY"K° TX½ÿÀ@878YK°TK°T[X½@ÿÀ878Y@ŽHj{†€‘¤  &&)) 55::0FFIIFH@VVYYPffiigh`ut{{uz……‰‰‰†––—š˜˜—¨§°Àßÿ>]]3 3#=Ã^^Ãþ\ú`üT¬û V5` @IU U U U   B ¿    ÔÌ91/<ì2290KSXííííííííY"K° TK°T[K°T[K°T[K° T[X½ ÿÀ @878YK° TK° T[K°T[X½ @ ÿÀ878Y@ÿ" 5 IIF @ [[U P nnf yy‡™˜” ¼¼ÎÇÏ         %%#'!%""%' $ ! # 9669 0FHF@B@@@D D D @@VVVPQRRPS T U cdejejjjn a g ouuy}x}zzxy  { v } ‡ˆ——”“œ›˜˜™@/– Ÿ¦¦¤¤««©©«¤ ¯µ±½»¸ ¿ÄÃÌÊy]]333# #V¸æåÙæå¸þÛÙñòÙ`ü–jü–jû –üj;y` Z@F      B ¿  ÔÄÔÄ91/<ì290KSXííííííííY"K° TK°T[K°T[K°T[X½ ÿÀ @878YK°TX½ @ ÿÀ878Y@˜   & =1 UWX f vzvt ‚ ™Ÿ—’ ¦©¯¥£       )&% * :9746 9 0 IFE J @ YVYYWVYVV Y P o x ›”«¤° Ï ß ÿ /]] # # 3 dþkªÙþºþºÙ³þrÙ))`ýßýÁ¸þHJþq=þV`¢@C        B  ‡½ ¼  ÔÄÄ91ä2ôì9990KSXíííííí2Y"K° TK°T[X½ÿÀ@878YK°TX½@ÿÀ878Y@ð     # 5 I O N Z Z j ‡ € “        '$$  )( % $ $ ' ** 755008 6 6 8 990A@@@@@@@@B E G II@TQQUPPVUVW W U U YYPffh ii`{xx‰Š … … ‰ ‰‰™ • • šš¤ ¤ ««°Ïßÿe]]+5326?3 3“N”|“lLT3!þ;Ã^^ÃhÈzšH†TNü”lXÛ` ´@B©¼© ÜÄ2Ä991/ìôì0KSXííY"K° TK° T[X½ @ ÿÀ878YK°TX½ ÿÀ @878Y@B&GI  + 690 @@E@@CWY_ ``f``b € ¯ ]]!!!5!qjýL´ü}´ýe`¨üÛ“¨%þ²$‚@4 %   ! © ©À ©±% $  C %Ô<Äü<Ä299999991üìÄôìî99999990K° TX½%ÿÀ%%@878Y²&]#"&=4&+5326=46;#"3>ù©lŽ==k©ù>DV[noZV¾”Ýï—ts•ðÝ“XøŽŽœøXþ®·±Ôì1üÌ0#®ªøþ²$ž@6%   ©©#À©±%#C %Ô<Ä2ü<Ä99999991üìÄôìî99999990K° TX½%@%%ÿÀ878YK°TX½%ÿÀ%%@878Y²&]326=467.=4&+532;#"+FŒUZooZUŒF?ù§lŽ>>Žl§ù?¾VøœŽŽøŽW“Ýð•st—ïÝ”ÙÓÛ1#@ œœ ÔÄ1ÔüÔìÀ990#"'&'&'&#"56632326Ûi³an’ ›^X¬bi³an“ ›^V©1²OD;>MS²OE<>LÿÿhN'$¼uhm !Ë@T   !!  ! !!!B  Á • Ž  !  VV!"ÔÄÔì2Ôî299999991/<æÖîÔî9990KSXííííííííY"² #]@  s › P#f iu {yyv v!€# ]]4&#"326!.54632#!#TY?@WX??Y˜þð!þX=>Ÿsr¡?<Òˆý_ˆÕZ?YWA?XXþóýN)sIs ¡rFv)ú‹þÿÿsþu'ð'&Ý-ÿÿÉ‹k'(žuÿÿÉ3^'1þuÿÿsÿãÙN'2'uÿÿ²ÿã)N'8îuÿÿ{ÿã-f'DRÿÿ{ÿã-f'DCRÿÿ{ÿã-f'D×Rÿÿ{ÿã-'DŽRÿÿ{ÿã-7'DØRÿÿ{ÿã-'DÜRÿÿqþuç{'FÝÿÿqÿãf'H‹ÿÿqÿãf'HC‹ÿÿqÿãf'H׋ÿÿqÿã'HŽ‹ÿÿof'ÖÿÿÿÿǦf'ÖCÿÿÿÿÞ\f'Ö×ÿÿÿÿôF'ÖŽÿÿÿºd7'Qؘÿÿqÿãuf'Rsÿÿqÿãuf'RCsÿÿqÿãuf'R×sÿÿqÿãu'RŽsÿÿqÿãu7'RØsÿÿ®ÿãXf'X{ÿÿ®ÿãXf'XC{ÿÿ®ÿãXf'X×{ÿÿ®ÿãX'XŽ{9ÿ;ÇÕ '@¹  YW Y Ô<ìü<ì1äôÔ<ì203!!#!5!¨°oþ‘°þ‘oÕþ\™û£]™Ãu=ð  @ÃÄà ‘ Z[ZÜìüì1ôìüì0"32654&'2#"&546PnnPPnoO@v+..¹†‡´¸ooPOmmOOp1.-rB„·´‡†º¬þÇ#˜!Q@+  †ˆ †ˆ ¹ ¹¸Œ"  "ÜìÔ<Ô<<ì221äô<ÄìÄþôîõî9990%&&'667#&73¦“¤¤JˆDF‰HA‰Mfñþ÷ ñfI‰ƒX⸹⡬)*ü *'ª#þä 32þá!bð`@!† ©  ”‘   Ü<ÌÌü<ÄÔÄ1/ì2ôäìÔ<î2î990K° TX½ÿÀ@878Y´66].#"!!!!53#535632NLˆ=”t‡þy-üìÇÇÖè=—´¶))›Ô×þ/ªªÑîó\ÿ=¢ð >‘@54&.#"#"&'532654/.5467.54632{?>‹ú?>ÌS8alÎÓƒ\]>9Ì­IšXW”:fqÝÖ€][;;ȦI™¨.Z.L…‡-[.Kˆ“¤''PGZswšeZŒ54m@ލ¤''TLf{x™f[1,pE‚Ÿ3Ñ…! · Ç \ Ôì1Ôì04632#"&3­~|«¬}}¬ú|««|}¬¬žÿ;9Õ %@Á]] ÔÔüÜì91Ä2ôì90!###&&54$yÀ¾Ž×ëÕùfùáNݸ¾èºÿã¬/š@0-'!  *†¹*¹—Œ.  !' $'$-F0üÄüÌÆîÔîî99991/äþîþÕî990@@'(Š Š     ! "&  : :!MM I!I"jj ¥¥¦ ]]4632#"&'532654&/.5467.#"#ºïÚÐÛ—¨:A9¦`áÓ@ˆIPŒAtx;e\`W§—ƒq‚ˆ»qÈÛèàs`/Q*%jŽd¬·¤_[?T>7;‡[¬gp‹ƒû“åÍ/8L`@6EBC?2ÉH0É9JCÊ 9ÊÉÈ É$HE301BKL?gwyVpMIßÑ`3þœDåÍ/IC@&=Ë>:ÌAÊ$1Ë04ÌGÊÉÈ$É 7aD=0^* D^ JÜÌüìþí2î1/îöþýîÖîýîÖî02#"$'&5476$"32676654&'&&&&#"3267#"&54632˜mmllmmþù˜˜þùmmllmm˜ƒâ^^``^^⃄ã^]]^\^ã§B‚B•§«›@zBC‰FØûûØIˆÍnmmþúš˜þûmmnnmm˜šmmng^^^å‚ã^^__^]⃅ã]^^õ! ¯Ÿ®"ôÐÑò'“FÕ >@!  É  b b cbcÔäüäÔìÔì91ô<<ì2Ô<<Ä903#######5J®¤ªqÃ7ËrqËrÉÕÿý¾äþÑ/þB^þä^sîRf1@ ´³DÔì1ôì0K° TK°T[X½ÿÀ@878Y3#‹Çþº™fþˆ×F)’@ÎÍddÜüÔì1ü<ì20K° TK° T[X½@ÿÀ878YK° TK° T[K°T[K°T[X½ÿÀ@878YK°TK°T[X½@ÿÀ878Y@````pppp]3#%3#^ËËþyËËÊÊÊÙ'ÛÝ>@" Ïœ Ï œ  Ü<Ä291Ô<Ì2ü<ìþ<ì990!!!!!'7!5!7!Ù}®/þHÃ{üúþþ}®þÕ¶Ãý‡¢;fÕ¨ðªþÇfÓªðHÕ‡@9  B• ••••­    ÔÔ<ì2ÔÄÄ91/<ììÄôììîî0KSXííííY"²€]@gww† …– ¿ ]!!!!!!#!5ýÇý9øü=ýð Íq‹þ¶ËÕªþFªýãªþÕžüðfÿºå +ž@< +,  )&  *&•& •‘&Œ,+,* # )#3,üìüìÀ999999991äôìîÀÀ99999990@*WZWU!je!{vu! FYVjddj(|svz( ]] 324&'.#"&5!27!"&''¶ý3>¡_Ü'y=¡_Üþý''†NOy;‚ÝW¢fªNPþˆþÆ€Ý[¢gXü²@CHp¸¸@Cþ¸þåp¼Džf b¥MK¿YÆgþöžþŸþ[KK¿XÝÝÏî /ÿ@- !$'!!0 $*0ÔÄÔÄ99991ÔÄÔÄÀ9990@¾     $$$   $$ $ ***///***55500055 5 :::???:::EEE@@@EE E JJJOOOJJJV´° °!°"°&°'°(´)]]32654&#".#"326#"&54632>32#"&“1†Te€vYR…Ä1…UfvYR†F^ˆº§†_™HDža†¼§†^•/XZ‡ie†‡7XX„je†ˆ‡ߦ¯Ø~ŠŠƒá§¯ÖwÙÛ .@МР œ   Ô<ì2ü<ì21/ìÔ<ìü<ì0!!#!5!!!®-ýÓ¨ýÓ-ýÓúþþ}ªþ}ƒªƒû¦ªÙÛ¨ T@.œœœœBѧœ $# ü<ì2291/ìôì90KSXííííY" 5!!Ûü@Àúþúþúþøþëþî²pªoüªÙÛ¨ V@/œœœœBѧœ$ # ü<<ì291/ìôì90KSXííííY"55!5ÙúþÁAúþø°þ‘ªþ²ýǪªRÃÕÆ@F  B Ó Ó   fe f eÔ<ì2ìüì2ì99991/ä2Ô<ì2Ô<ì290KSXííííY"K° TX½ÿÀ@878Y@(†¦ µ' ' ')((79‡ ˆ¦ ¥ª©]]!#!5!5'!5!3 3!!!þcÉþ` Tþ´þþ{y¿þÂþµTŸÇþ9Ç{3›{JýD¼ý¶{›3®þVå` M@% ‡Œ ¼½!   NF!üì2ôìÄ91ää2ô<ìÜÄ990¶"`"Ï"]3326533267#"&'#"&'®¸Š‡”•¸#% )I#ER2‘bf*þV ýH‘”¨¨ü¢<9 ”NPOONNý×hÿçÁ-)b@'! '!Õ* $$*ÔÌÜÌ9991äÌÜÌÎÎ990K° TK° T[K°T[K°T[K°T[X½*@**ÿÀ878Y>54&#"#"&54632#"&54324&#"32ôIH7$$0e´ÖþßÕ˜ËÝ¢e‚ WOmVPmmW£Kƒt,>bþÊþùþ±þFØ£Æ[àt}þþÏt{þw;Á ]@    ÔÄ91ÄÔÌÎ990@0QVPZ spvupz €€ Z pp{ t €€ ]]!! !!5 7êüA ýJïúÞÕýIÁÁý3ýÀ•!ãœþwqÁ@×Ö¯ggÔìÔì1üìì20!#!#œÕðý ïÁø¶}ùƒÿáÿðª/#Ë@1 ÚÙ"ØÕ $ #" #h#$ÔÔÔì9999991/<äôì22î9990K° TX½$ÿÀ$$@878Y@V             ##(]]#3267#"&5467!##"#>3!‡¶i/7.%7vy"PþºÂµÃ)6<  ¥y‘þJ\:1fd.¡xüo‘@E¦}/þú%&@ Û Ûܱ& iji&Üìüì1üìÜäÞä026732#"&'&&#"#"&546327j ¾ÊPd@7*8  k½ÄOeD=!0 þú°l9¼TA6?&#Hý•Ánþ!þbSA8?SsÕ;ð)_@3(%ãÝá%Ý ßÞÝ à‘* "(kl"k *ÜìÌüì22ÀÀ9991ôäüôìÄîíÖîî99990!!#5#"&5463354&#"56632"32655‹°ýP®•,]€˜¿¼¶uu>ˆDI‘E·³þì¡~bRh‚P{¸þ@p?D‡q‡Š[[""°ðCO@Mr`Õdð.@ãáÝ àÝ‘ klk Üìüì991ôìôìüì0!!2#"&546"32654&‹°ýPX³Îγ³Ðгi~hi}|P{Ý¿¿Ûܾ¿Ýs¡ˆ…  …‰ NÏç@@" å‘å  mm  ÔììÔììÀÀ9991/<ì2ôì0%!5654#"!5!&5! Ïý¨±ÆþøØØþ÷Dzý¨?ž‘1/Ž¡²²²aLÊð"þÝïÊþ´a²²‹*¸>ŠþwþËÂþØ{ÿão{3>@C'-%= 4©%†ˆ©:¹.†-º*¹»1 ¸Œ%?47&%7& =&-7"E?üìÌÔü<ÔìÄ999991Ää2ô<Ääü<ôìÄî2îôîî9990@0+0,0-0.0/00@+@,@-@.@/@0P+P,P-P.P/P0…+…0€@@ @°@À@Ð@à@à@ð@??? ??0,0-0.0/@,@-@.@/P,P-P.P/ooo oo`,`-`.`/p,p-p.p/€,€-€.€/]q].#">32!3267#"&'#"&5463!54&#"5>32"326=¶¥‰™¹DJÔ„âü² Ì·hÈddÐj§øMIؽÒýû§—`¶Te¾ZŽÕï߬o™¹”—´®ž0Z^þÝúZ¿È55®*,ywxx»¨½À‹..ª''`þf{bsÙ´)Hÿ¢œ¼ +ä@<+,&  )&  *&¹& ¹¸&Œ,+,* # #Q)E,üì2ôì2À9999991äôìîÀÀ99999990@p(?-YVUV jf!{    { z{ {!"#$%{&›•%¨ -ð-&YVUZ(ifej(ztvz(‰•š$¢­$]] 32654&'.#".5327#"&''‰þ)gA“¬\*g>—©}66ñ]ŸC‹_’56þîð`¡?‹`!ý°*(èÈOuš))ëÓHn.—MÅw834¨O³MÆxþíþÇ43¨Nÿã¬Õ $†@/ †ˆ !ƒ# •Œ#%" " "!& %ÜìÔüìÔì99991äôìþÍôî9990K°TK°T[K°T[X½%ÿÀ%%@878Y@ ttttv]33267#"&546?>7>5#53ô¾7ZZ:3ƒmN´`^Àg¸àIYX0&ÄÊÊDœe‚WX5^1YnFC¼98ŸL‰VV/5<6þ5Õ b@ƒ ü<ì2991/ôüÌ0K° TX½ @ ÿÀ878YK°TK°T[K°T[X½ ÿÀ @878Y¶ P ]#53#3ËËË¢×þú+eþ›ÙÛ^@ œÜÔì1ÔÄì0!#!Ù¨û¦^ýÁ•=ÿ×} *@    ÔÌ91ÔÌÄ903##'%\½sý®BþÁ}}`ùºs-Pbý;þV#Š@@   B   ©Šæ©Šæ©!—$  $ÔÌ91Ä2Äüìôìîöîî299990KSXí2í9Y"K° TX½$ÿÀ$$@878Y.#"!!#"&'53267#5!>32&P,`r<þÃ:¼º:d/4a/am"‰ø?$Æ—5dð¤z„þÉý…þãÓ¦!!‰¦­J·ÃÙÛô;?@.9*-" *œ19œ"œ œ<-<Ô<Ä21ÔìÔìÜüÔìÀ9999990#"'&'&'&#"56632326#"'&'&'&#"56632326Ûi³an’ ›^X¬bi³an“ ›^V©gi³an’ ›^X¬bi³an“ ›^V©o³NE;=LT³NE;=KÚ²OE;=LS²NE;=Kÿú`Á8@ÔÌ91/ÄÌ90@cmpxyvn]] !3!¬þ^DýïàCúšîûÄú?ž%# †@Ièèèè è è è  è B  ç¦ o o nüü<Ôì2991ô<ì2990KSXííííííííY"55%þÓ-þ+#þÓ-þ+#¿þôþô¿¢R¢¿þôþô¿¢RÁH# †@I è è è è èèèèB  ç¦ o opü<üÔ<ì991ô<ì2990KSXííííííííY"5%5ÁÕþ+-þÓ²Õþ+-þÓ#þ^Rþ^¿  ¿þ^Rþ^¿  ìþ #@ƒ   ÔüÔìÔì1/<<ì220%3#%3#%3#–ÔÔ©ÕÕú­ÕÕþþþþþþÿÿhk'$¼uÿÿh^'$¼uÿÿsÿãÙ^'2'us Õ;@•••­   üìÔÄÄÔì299991/ìì2ôì2î0!!!!! !# !3úýÇý9øû×þOþA¿±gþ¿þÀ@AÕªþFªýãª|pm|ªþáþàþßþßqÿãÃ{'3„@1†ˆ ©. ¹(¹»"%¸Œ4"1 K1 Q+E4üìôüôìÄ9991ä2ô<Ääì2Äî2îôî90@%?5_5p5Ÿ5Ï5Ð5ð5????? ooooo ]q].#"!3267#"&'#"32>32%"32654& ¤‰™¹Hü² Ì·jÈbdÐj òQGÑŒñþïñŒÓBNèâú°”¬«•“¬¬”˜³®ž5Z¾Ç44®*,nmnm98olkpþ݇çÉÉçèÈÇééy¶©é/Æ1üì0!!üyéyµ©/Ì1Ôì0!!øy®émÕ '@ž   ÜüÌÔÌþÔÎ1ô<ì20#53#53Ó¤RšÓ¤Ré­?þÁ­­?þÁ®émÕ '@ ž  ÜìÔÌÜîÔÎ1ô<ì203#%3#Ó¤RšÓ¤RÕ¬þÀ@¬¬þÀ@®éÓÕ@ žÜüÔÌ1ôì0#53Ó¤Ré­?þÁ²þ×Õ@ žqÜìÔÌ1ôì03#Ó¤RÕ˜þÁ?Ù–Ûo )@êêœ r ÜÔ<ü<Ä1ÔÄüÄîî03#3#!!ßööööýúúþoöþõAªþ#îu"@ÔÌ91ÔÌ990 úþþôþ þ üÏüÇ9%ûÛûÓ-ÿÿ=þV'\Ž^ÿÿÿüçN'<suþ‰ÿãÍð+@BŒ‘ÔÌ1ää0KSXííY"3#- ü\ ðùó^R¼²#/ƒ@I -'! - -¹ëì'¹ë!0 *$0* $ $(st*(s0Üäìôäì9999999991ÔäìôäìÀ9999999907'#"&''7&&5467'766324&#"326{ÏrÎ%$&(ÑrÏ;t=:x=ÏqÏ%%&&ÏsÏ7t@?s9ÏqÏ(&%%ÏsÎ>v:@t8ÎsÏ'%$þ|pššprœžs#G@%èèèèBç¦onüì291ôì90KSXííííY"5sþÓ-þ+#¿þôþô¿¢RÁ–#I@&èèèèBç¦opü<ì91ôì90KSXííííY"5ÁÕþ+-þÓ#þ^Rþ^¿  /J›@( ©‡¾±— ¼ Lü<Ä2Äü<Äî2991/<æ2îþîîî2990K° TX½ÿÀ@878YK°TX½@ÿÀ878Y@0P€€€ Ðï]]#!##53546;#"3#J¹þ¹°°­³¹°cMù¹¹`û Ñü/ÑN·¯™Phc²é/J„@! © ‡— ¼   Lü<ÄÄü<Äî991/<æ2þîî2990K° TX½ÿÀ@878YK°TX½@ÿÀ878Y@0P€ € € Ðï]!#!"!!##53546J¹þ·cM/þѹ°°®ùì{Phcü/ÑN»«9ÿ;ÇÕ>@ ¹¹  ÂY W Y Ô<<ì2ü<<ì21äôÄ2Ä2î2î20%!#!5!!5!3!!!Çþ‘°þ‘oþ‘o°oþ‘oßþ\¤š™¤þ\™ýáÛH®F·ƒÔì1Ôì03#ÛÓÓFþ®ÿÓþ@ žƒÔìÔÌ1üì0%3#Ó¤Rþ¬þÀ@®ÿmþ '@ žƒ   ÜìÔÌÜîÔÎ1ü<ì20%3#%3#šÓ¤RþfÓ¤Rþ¬þÀ@¬¬þÀ@qÿã Lð #'3?K®@D$%&%&'$'B@’ .’(’F’4 :&Œ$‘L%IC'1+C =  1 =I 7+ ! LüäìÔÄìäîîöîî991ä2ô<<ä2ì2îöîî20KSXííY"K°TK° T[K° T[K° T[K° T[K°T[X½L@LLÿÀ878Y"32654&'2#"&5462#"&546!3#"32654&2#"&546"32654&ôWddWUccUžº» º»ùtž¼»ŸŸ¹º% üZ VcbWWcd²žº» º»ŸWccWUcc‘”„‚••‚ƒ•Ü»»ÛÛ»¼ÛàÛ»½ÚÛ¼ºÜùóŽ•‚„””„–ýŸÜ»»ÛÛ»¼Û”„‚••‚ƒ•ÿÿhm'$¼uÿÿÉ‹m'(žuÿÿhk'$¼uÿÿÉ‹N'(žuÿÿÉ‹k'(žuÿÿ¢k',ÿ/uÿÿÿþ`m',ÿ/uÿÿXN',ÿ/uÿÿ;ºk',ÿ/uÿÿsÿãÙk'2'uÿÿsÿãÙm'2'uÿÿsÿãÙk'2'uÿÿ²ÿã)k'8îuÿÿ²ÿã)m'8îuÿÿ²ÿã)k'8îuÁy` ·¿Füì1/ì0@ @P`p]3#Á¸¸`û Áî?f7@ ´³uÜì91ôì290K° TK°T[X½ÿÀ@878Y3#'#¶”õ‹´´‹fþˆõõ¶J7c@$  Ãà íVwVvôìüì99991ü<üÔ<ì99990K° TK° T[X½ÿÀ@878Y'.#"#>3232673#"&ü9! &$}f[&@%9! &$}f[&@Z7IR‡“!7IR‡“Õb+ö/·ïîÔÌ1üì0K° TK°T[X½ÿÀ@878Y!!ÕVýªö”Ç)9H W@ ð³VVÜìÔì1ô<Ôì0K° TX½ÿÀ@878YK°TK°T[K°T[X½@ÿÀ878Y332673#"&Çv aWV` v ž‘‘žHKKJLšDf,@ ÎÍdÔì1üì0K° TX½ÿÀ@878Y3#šÌÌÌîá _@Áò ÁñV xVÔìôì1ôìôì0K° TK° T[X½ÿÀ@878YK° TK° T[K° T[X½ÿÀ@878Y4&#"3267#"&54632˜X@AWWA@XzŸssŸŸssŸô?XW@AWX@s  ssŸŸ#þuÁ@  ó' ÜÔìÔÌ1/ÔüÄ90!#"&'532654&'T76xv.W+"J/;<+->i0Y[ ƒ0.W=ðî®fB@´³ÔÜÔÌ991ô<ì20K° TK°T[X½ÿÀ@878Y3#3#ü²ø‡ªß‰fþˆxþˆLþuÁ @  óô 'ÔìÄÔÌ1/üüÄ90!33267#"&546¸w-+76 >&Dzs5=X..… W]0iÁî?f7@ ´³uÜì91ô<ì90K° TK°T[X½ÿÀ@878Y373¶õ‹´´‹õîxõõþˆÿòuÕ ?@ •  : yô<ìÄü<Ä991/äì90´0P]3%!!'7ÓË9Pþw×ü^”MáÕý˜Ûoþîýãª;jnžH ^@ — z z Ô<äü<ä991/ì90K°TX½ @ ÿÀ878Y@ @ P ` sz p à ð ]37#'7Ǹ}Lɸ{JÅý¦ZjüãšXjÿÿ‡ÿã¢m'6‹uÿÿoÿãÇf'Vàÿÿ\m'=¾uÿÿXÛf']àþ¢®˜@ õõÜ<ì21ÔìÔì0##®ªªª˜ý öý ö ºÕ g@  © ••  2  yô<ì2ÄôìÄ91/Æ2îöîî20@( °Ÿ Ÿ Ÿ Ÿ ŸŸŸŸ¿ ¿ ¿ ¿ ¿¿¿¿]]! )#53!!3 !Ó ±–þiþPþ`ÉÉËPþ°ó5þáþËÕþ—þ€þ~þ–¼ãþýê.,qÿãu('@^%{&%#${##{#({'(#&'('%$%(('"#" ! B('&%"! ##¹ ¹Œ#±)&' ! (%#" QE)üìôì99999991ìÄôìî9990KSXÉÉÉÉííííY"²?*]@v%+("/#/$)%-&-'*(6%F%X X!` `!f"u u!u"%#%$&&&''(6$6%F$E%Z Z!b b!z{     {zzv v!x" *ð*']].#"32654&#"5432''%'3%F2X)§¹®’‘®6 ~rþäæçþåÝ4*ŸþÁ!µäM!þÙ“ØÃ¼ÞÞ¼z¼&þà­ÿþÉ7ÿú7´kc\Ì‘oabÿÿÿüçk'<suÿÿ=þVf'\^ÉÕ =@• •ö  ? üì22üì91/ôüìÔì0@ ?_]332+#32654&#ÉÊþûþÿûþÊÊþš™ŽÕþøáÜÜâþ®'ýÑ’††‘ºþV¤>@¹¹Œ¸½— GFüì22ôì1ìääôÄìÆî0@ `€ à]%#3>32#"&4&#"326s¹¹:±{ÌÿÿÌ{±8§’’§§’’§¨ý®¾ý¢daþ¼þøþøþ¼aëËççËËççÙ-Û×¶œÔÄ1Ôì0!!Ùúþת?œÅ …@M œ  œœœœœ œ œ B   Ô<Ì291Ô<Ì290KSXííííííííY" '7œþ7Éwþ5þ5vÈþ8vËËLþ5þ7yËþ5yÉËyþ5ˉœÅß ,@Ý ÝÝ ÷‘ |]|| Üôäüä1ôììÔìî2035733!œÌßæ‰Íý× c)t'ý+n^œ´ðJ@$}}BÝÝ÷ Ý‘~ÜÄÔÄì91ôÄìüìî90KSXí2íY"!!56754&#"56632 ¨ýª"?XhU4zHM…9‘®þµ8rn81^BQ##{„l‹þä0bÍð(H@' Ý Ý Ý Ý ø÷Ý ø#‘)~&~ )ÜÄÄÔìÔì9991ôäìüäìÔìîî90#"&'532654&##532654&#"56632 \e¾±9}F4wCmxolV^^ad_(fQI€7©Z`mR|†yOFJLl?<:=svcE`ÿÿ‰ÿãð'ð'¼5 ‹ýdÿÿ‰ÿã?ð'ð'¼5ñ‹ýdÿÿbÿãð'ò'¼5 ‹ýdÿÿsÿã‹m'* uÿÿqþVZH'JÚ‹ÿÿÉ•P', ÿ/uÿÿ‡þu¢ð'6Ý‹ÿÿoþuÇ{'VÝÿÿsÿã'k'&-uÿÿqÿãçf'F‰ÿÿsÿã'm'&-uÿÿqÿãçf'Fà‰qÿãô$J@$Ó ù"¹¹ Œ¸—   GE%üìô<Äü<Ä1/ìäôÄìÄîý<î20¶`&€& &]!5!533##5#"3232654&#"¢þºF¸šš¸:±|ËÿÿË|±ýǧ’’¨¨’’§¶N}““}úü¨daDDaþËççËËççd߃¶œÜÌ1Ôì0!!dý僤ÛH®F·ƒÔì1Ôì03#ÛÓÓFþÿãð1@: Ó"+Ó ¡®•¡®•/‘Œ) 2+"!)#&  , & &*!/<ÔÄ2üÄÄ99999999991Ä2äôìôìîöîî2Ý<î20K° TK° T[K° T[K°T[K°T[K°T[X½2ÿÀ22@878Y@z  1Ti lnooooiko o!o"o#n$l%i'i-ŸŸŸ Ÿ Ÿ Ÿ Ÿ ŸŸŸŸŸŸ–Ÿ Ÿ!Ÿ"Ÿ#Ÿ$Ÿ%Ÿ&Ÿ'Ÿ(Ÿ)Ÿ*Ÿ+Ÿ,-2   USjg ]].#"!!!!3267#"#734&5465#7332[©fÊ A7ýæ¾8þŠ Êf©[Y¹`íþË(Ó7‹Â7œ(6ìb¹bÕiZÈ»{.# .{»ÊZiÓHH"{/ #/{"G×)Ù¥@ ÎddÔüÜì1Ô<ì20K°TK°T[X½@ÿÀ878YK°TK° T[K°T[X½ÿÀ@878YK°TK°T[X½@ÿÀ878YK°TX½ÿÀ@878Y@````pppp]3#%3#^ËËþyËËÙËËËsîðö@BúÄÀ1ôÌ0KSXÉÉY"K° TX½ÿÀ@878YK°TX½@ÿÀ878Y@ %%6FVjg //]]3#7¹ä™öþø¶Jéu@!  ÃÃúVV ÔìÔì99991ô<ìÔì2990K° TX½ÿÀ@878YK°TX½@ÿÀ878Y´ ]'.#"#4632326=3#"&ü9 $(}gV$=09" (}gT";9! 2-ev 3)dw î‹ö‰@BúÄÀ1ôÌ0KSXÉÉY"K° TX½ÿÀ@878YK°TX½@ÿÀ878Y@*$$5CUUŸŸ¯¯//]]#ÇÄ™æöþøÏî1øw@ úÔÄ91ô<Ä90K° TX½ÿÀ@878YK°TX½@ÿÀ878YK°TX½ÿÀ@878Y@ //- ]3#'#¢¼Ó‹¦¦‹øþö²²Ïî1ø†@ úÔÄ91ôÄ290K° TK° T[K° T[K° T[X½ÿÀ@878YK°TX½@ÿÀ878YK°TX½ÿÀ@878Y@ "  ]373¢Ó‹¦¦‹Óî ²²þö?œôß Ô@ Ý ÷‘ ] ÜÔ<Äì291ôüÔ<ì290K°TK°T[K°T[K°T[K° T[K° T[X½@ÿÀ878YK°TK°T[X½ÿÀ@878Y@T /9IFYi‹«»       "5GK S[ e„¥µ]] !33##5!5ÝþË5¦‡‡þbfþ]ýämººyÇ9ø j@à úVVÔìÔì1ôüÄ20K° TX½ÿÀ@878YK°TX½@ÿÀ878YK°TK°T[X½ÿÀ@878Y332673#"&Çv cSRav  Ÿø6978w{zšfÛ¶úÔÌ1ôÌ03#šÌÌÛÍ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßà>: ~ÿ1BSax~’ÇÝ©À & 0 : ¬!""""+"H"e%Êûÿÿ   0AR^x}’ÆØ©À  0 9 ¬!""""+"H"`%ÊûÿÿÿãÿõÿØÿ ÿ^ÿCÿhÿüöüÛà–à…àVßjÞqÞ_Úï¿8ôüúúü (B¬£„…½–熎‹©¤ŠÙƒ“ñò—ˆÃÝðžªóôõ¢­ÉÇ®bcdËeÈÊÏÌÍÎèfÒÐѯgï‘ÕÓÔhêì‰jikmln oqprsutvwéxzy{}|¸¡~€ëíºýþÿøÖùúãä×àÚÛÜßØÞ²³¶·Ä´µÅ‚‡«˜¨š™î¼¥’”•Íf‹‹55®Å´žªšq=3ۤ=´Ù‹žãd‹Û²‡á–œdž¨‹²ð²ž´Ù´Ù´Ù?“‡y}É–s)ÉÉšÉ3sÉ\É\ÿ–?ÉuÉçÉüÉLsÓÉLsɇãÿúÛ²yéD{=ãÿü{\°²Ç´Ùÿìªç{ºfqqìqÑ/qº9Á9ÿÛ¢º9Á˺ºåqºqJº+o#7®¼=‹V¼;¼=3X²´Ùyy–sÉüÉLsÛ²ç{ç{ç{ç{ç{ç{fqìqìqìqìq99ÿÇ9ÿÞ9ÿôºåqåqåqåqåq®®®®9ì\¸3ž º's×´ÙËLfªÝ´Ù´Ù´ÙR®#hdœ¶ÿá+/ÅsÅ`NÛ{åH?55´Ù=´ÙZÿúåžåÁìyyLss/q%®%®‹®‹²´Ùô¼=ãÿüVþ‰^3ž3Á / /9‹Û‹®%® ¼qyÉyÉÉ\¢\ÿþ\\;LsLsLsÛ²Û²Û²9ÁÁ¶ÕÇšî#ðLÁÿòF‡+o{\3X²3 åqãÿü¼=×ɺ´Ù´5‰5^5bÁ‰Á‰Áb3sq\ɇ+o–sfq–sfqqãd‹Û×s¶ ÏÏ5?Çšÿ+   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóõôöøùúûüýþÿ     sfthyphenperiodcenteredEuroc6459c6460c6461c6462c6463c6466c6467c6468c6469""""X“ÿ¶Oƒ²ö!n˜´ÊÞE‚~áL·üeÏî  R s ®  ß X ° û : i “ æ  = z /¬E…ëuñ)pཊëP‹±á@Ö"m¹#{ßC€øw³R¡Ø‡Äº‡wè [ r ó!5!B!â!ï!ü" ""#"0"="J"W"d"q"~"‹"˜"¥"²"¿"Ì"Ù"æ"ó## ##'#4#A#N#[#h#”#Ï$4$%3%S%&&º'K''·((X(Ã)_*%*\*£*é+z+Ó,D,,±-P- ..R.ª/‡0A0½11!1P1Ï2H2z2ß3F3p3p3}3Š3—3æ4z44£4Ñ4ÿ5595g5‘5ž5«5Ï6[6“6Í7C7©7ë888J999)969C9P9]9j9w9„9‘9ž9«9¸9Å9Ò9ï::{: :å;;^;Ž;Ä;ô<"<_<§<´<Á<Î<Û<þ=c>;>H>U>˜>ç>ý?a??Ü@:@K@\@m@z@‡@”@¡@®@»@È@Õ@âA@AVAkBEBªB÷C_C²CÿDUDÛE*E?-†” x$ÿÓ%ÿ·&')*K+-r./2934K57ÿD9ÿˆ:ÿ­;ÿš<ÿ =IQR&UYÿÉZ\ÿÜbÿÓdg9xy&z&{&|&}&‰­ÿÓ®ÿÓ¯9ºÿÜ»ÿ ÇÿÓÉÿÓÐ9Ñ9Ò9åéêÿ ëÿÜìöKûý$ÿÓ$ÿÜ$ÿÜ$$9$&ÿÜ$*ÿÜ$2ÿÜ$4ÿÜ$6$7ÿa$8$9ÿ}$:ÿ$;$<ÿa$FÿÜ$GÿÜ$HÿÜ$Iÿ·$RÿÜ$TÿÜ$WÿÜ$X$Yÿˆ$Zÿ­$\ÿu$b9$dÿÜ$gÿÜ$h$oÿÜ$pÿÜ$qÿÜ$rÿÜ$sÿÜ$yÿÜ$zÿÜ${ÿÜ$|ÿÜ$}ÿÜ$~$$€$$©ÿ·$ª$­9$®9$¯ÿÜ$´þø$µÿ$ºÿu$»ÿa$Å/$Ç9$É9$ÐÿÜ$ÑÿÜ$ÒÿÜ$Ó$Ô$Õ$ã$êÿa$ëÿu$öÿÜ$ù$ûÿÜ$üÿÜ$ýÿÜ$þÿÜ%%&ÿÜ%*ÿÜ%2ÿÜ%6ÿÜ%9ÿÁ%:ÿ·%<ÿ%dÿÜ%gÿÜ%©ÿÁ%ªÿÜ%¯ÿÜ%´ÿ%µÿ%»ÿ%Åÿ­%ÐÿÜ%ÑÿÜ%ÒÿÜ%ãÿÜ%êÿ%öÿÜ%ùÿÜ%ûÿÜ%ýÿÜ&&$&6&<ÿÜ&b&©ÿÜ&ªÿÜ&­&®&´&µ&&»ÿÜ&Å&Ç&É&ã&êÿÜ&ù''$ÿÜ'9ÿÜ':'<ÿ'bÿÜ'©ÿÜ'ªÿÜ'­ÿÜ'®ÿÜ'´ÿÓ'µÿÉ'»ÿ'ÅÿD'ÇÿÜ'ÉÿÜ'êÿ))þ·)ÿa)$ÿD)6ÿÜ)7ÿÜ)DÿD)Hÿ)Lÿk)Rÿ·)Uÿk)Xÿ)\ÿD)bÿD)iÿD)jÿD)kÿD)lÿD)mÿD)nÿD)pÿ)qÿ)rÿ)sÿ)yÿ·)zÿ·){ÿ·)|ÿ·)}ÿ·)~ÿ)ÿ)€ÿ)ÿ)©)ª)­ÿD)®ÿD)´ÿÓ)µ)ºÿD)Åþˆ)ÇÿD)ÉÿD)ãÿÜ)ëÿD)ùÿÜ**$*7ÿ·*:*<ÿš*b*©ÿÜ*ªÿÜ*­*®*´ÿÓ*µÿÓ*»ÿš*ÅÿÉ*Ç*É*êÿš++ÿÜ++©+ª+´ÿ·+µÿÁ+Åÿ·-ÿ·-$ÿÜ-bÿÜ-©ÿÜ-ªÿÜ-­ÿÜ-®ÿÜ-´ÿ·-µÿÁ-Åÿ-ÇÿÜ-ÉÿÜ.ÿ).$ÿÜ.&ÿ.2ÿ.7ÿa.8ÿÉ.:ÿ·.<ÿ·.DÿÜ.Hÿš.Rÿš.Xÿš.\ÿk.bÿÜ.dÿ.gÿ.hÿÉ.iÿÜ.jÿÜ.kÿÜ.lÿÜ.mÿÜ.nÿÜ.pÿš.qÿš.rÿš.sÿš.yÿš.zÿš.{ÿš.|ÿš.}ÿš.~ÿš.ÿš.€ÿš.ÿš.©ÿ}.ª.­ÿÜ.®ÿÜ.¯ÿ.´ÿÁ.µÿÁ.ºÿk.»ÿ·.Å.ÇÿÜ.ÉÿÜ.Ðÿ.Ñÿ.Òÿ.ÓÿÉ.ÔÿÉ.ÕÿÉ.êÿ·.ëÿk.ûÿ.ýÿ/ÿÜ/$//2ÿ·/7þæ/8ÿš/9ÿ/:ÿD/<þð/D/HÿÜ/RÿÜ/XÿÜ/\ÿD/b//gÿ·/hÿš/i/j/k/l/m/n/pÿÜ/qÿÜ/rÿÜ/sÿÜ/yÿÜ/zÿÜ/{ÿÜ/|ÿÜ/}ÿÜ/~ÿÜ/ÿÜ/€ÿÜ/ÿÜ/©/ª/­//®//¯ÿ·/´þa/µýæ/ºÿD/»þð/Å/Ç//É//Ðÿ·/Ñÿ·/Òÿ·/Óÿš/Ôÿš/Õÿš/êþð/ëÿD292ÿ­2ÿÜ2$ÿÜ29ÿÜ2;ÿ}2<ÿ2bÿÜ2©ÿÜ2ª2­ÿÜ2®ÿÜ2´ÿÓ2µÿÜ2»ÿ2ÅÿD2ÇÿÜ2ÉÿÜ2êÿ3ÿÓ3þÁ33$ÿ}383:3<ÿÓ3Dÿ¤3Hÿ·3LÿÓ3QÿÜ3Rÿ·3UÿÜ3VÿÜ3XÿÜ3\3bÿ}3h3iÿ¤3jÿ¤3kÿ¤3lÿ¤3mÿ¤3nÿ¤3pÿ·3qÿ·3rÿ·3sÿ·3xÿÜ3yÿ·3zÿ·3{ÿ·3|ÿ·3}ÿ·3~ÿÜ3ÿÜ3€ÿÜ3ÿÜ3©ÿÜ3ª3­ÿ}3®ÿ}3´&3µ&3º3»ÿÓ3Åþ·3Çÿ}3Éÿ}3Ó3Ô3Õ3äÿÜ3êÿÓ3ë3úÿÜ494©4ª4´ÿÓ4µÿÜ4Åÿ}5ÿ­5ÿ·5ÿÁ5$ÿ­5&ÿš57ÿk59ÿ5:ÿ­5<ÿ}5DÿÓ5Hÿ¤5Rÿ¤5Xÿ¤5\ÿ5bÿ­5dÿš5iÿÓ5jÿÓ5kÿÓ5lÿÓ5mÿÓ5nÿÓ5pÿ¤5qÿ¤5rÿ¤5sÿ¤5yÿ¤5zÿ¤5{ÿ¤5|ÿ¤5}ÿ¤5~ÿ¤5ÿ¤5€ÿ¤5ÿ¤5©ÿ5ªÿÜ5­ÿ­5®ÿ­5´ÿk5µÿ}5ºÿ5»ÿ}5ÅÿÜ5Çÿ­5Éÿ­5êÿ}5ëÿ5ûÿš5ýÿš6$&6&6*6264666b&6d6g6­&6®&6¯6Ç&6É&6Ð6Ñ6Ò6ã6ö6ù6û6ý7ÿD7ÿ 7ÿ7$ÿa7&ÿˆ77ÿÜ7Dþ­7Fþ¤7Hþ¤7LÿÁ7Rþ¤7UþÓ7Vþ­7XþÉ7Zþ­7\þÁ7bÿa7dÿˆ7iþ­7jþ­7kþ­7lþ­7mþ­7nþ­7oþ¤7pþ¤7qþ¤7rþ¤7sþ¤7yþ¤7zþ¤7{þ¤7|þ¤7}þ¤7~þÉ7þÉ7€þÉ7þÉ7©ÿD7ªÿ7­ÿa7®ÿa7´7µÿÓ7ºþÁ7Åþø7Çÿa7Éÿa7äþ­7ëþÁ7úþ­7ûÿˆ7üþ¤7ýÿˆ7þþ¤8$8-8=ÿÜ8b8­8®8Ç8É8åÿÜ9ÿˆ9þø9ÿY9$ÿ}92ÿÜ9Dÿa9Hÿa9LÿÓ9Rÿa9Xÿu9\ÿÉ9bÿ}9gÿÜ9iÿa9jÿa9kÿa9lÿa9mÿa9nÿa9pÿa9qÿa9rÿa9sÿa9yÿa9zÿa9{ÿa9|ÿa9}ÿa9~ÿu9ÿu9€ÿu9ÿu9©ÿN9ªÿ9­ÿ}9®ÿ}9¯ÿÜ9´9µ9ºÿÉ9Åþæ9Çÿ}9Éÿ}9ÐÿÜ9ÑÿÜ9ÒÿÜ9ëÿÉ:ÿ­:ÿ:ÿˆ:$ÿ:Dÿ}:Hÿˆ:LÿÓ:Rÿˆ:Uÿ¤:Xÿ·:\ÿÜ:bÿ:iÿ}:jÿ}:kÿ}:lÿ}:mÿ}:nÿ}:pÿˆ:qÿˆ:rÿˆ:sÿˆ:yÿˆ:zÿˆ:{ÿˆ:|ÿˆ:}ÿˆ:~ÿ·:ÿ·:€ÿ·:ÿ·:©ÿ:ªÿÜ:­ÿ:®ÿ:´ÿÜ:µ:ºÿÜ:Åþø:Çÿ:Éÿ:ëÿÜ;ÿš;$;&ÿk;2ÿ};7ÿÜ;Hÿ¤;b;dÿk;gÿ};pÿ¤;qÿ¤;rÿ¤;sÿ¤;©ÿ;ª;­;®;¯ÿ};´ÿa;µÿ­;ÅÿÓ;Ç;É;Ðÿ};Ñÿ};Òÿ};ûÿk;ýÿk<ÿ <þa<þð<$ÿa<&ÿ<2ÿ<Dþæ<Hþð<Lÿ·<Rþð<Xÿ<bÿa<dÿ<gÿ<iþæ<jþæ<kþæ<lþæ<mþæ<nþæ<pþð<qþð<rþð<sþð<yþð<zþð<{þð<|þð<}þð<~ÿ<ÿ<€ÿ<ÿ<©ÿ<ªÿk<­ÿa<®ÿa<¯ÿ<´ÿ<µÿÜ<Åþø<Çÿa<Éÿa<Ðÿ<Ñÿ<Òÿ<ûÿ<ýÿ=ÿÜ=©=ª=´ÿÜ=µÿÜ=ÅÿÜH[ÿÜIÿIÿkIÿ·IWÿÜIZÿÜI\ÿÜI©ÿ·IªÿÜI´AIµIºÿÜIÅÿIëÿÜNDÿÜNHÿ·NRÿ·NXÿÁN\ÿ·NiÿÜNjÿÜNkÿÜNlÿÜNmÿÜNnÿÜNpÿ·Nqÿ·Nrÿ·Nsÿ·Nyÿ·Nzÿ·N{ÿ·N|ÿ·N}ÿ·N~ÿÁNÿÁN€ÿÁNÿÁNºÿ·Nëÿ·QQQQ©QªQ´ÿkQµÿQÅÿ¤R&RÿÜRR[ÿÁR©RªR´ÿkRµÿ·RÅÿ}Uÿ}UÿDUÿÜUFÿÓUGÿÜUHÿÓUIUJÿÜUKÿÜUPÿÜUQÿÜURÿÓUTÿÜUUÿÜUXUYUZU[ÿÉU\U]UoÿÓUpÿÓUqÿÓUrÿÓUsÿÓUxÿÜUyÿÓUzÿÓU{ÿÓU|ÿÓU}ÿÓU~UU€UU©ÿ·UªU´UµVUºUÅþÉUæUëU÷ÿÜUüÿÓUþÿÓYÿÉYÿaYÿY©ÿÜYªÿÜY´YµÿÜYÅþðZZÿDZÿZ©ÿÜZªÿÜZ´ZµZÅÿ)[FÿÜ[HÿÁ[RÿÁ[oÿÜ[pÿÁ[qÿÁ[rÿÁ[sÿÁ[yÿÁ[zÿÁ[{ÿÁ[|ÿÁ[}ÿÁ[üÿÜ[þÿÜ\ÿÜ\þÜ\ÿk\©ÿÜ\ªÿÜ\´\µ\ÅþÓbÿÓbÿÜbÿÜb$9b&ÿÜb*ÿÜb2ÿÜb4ÿÜb6b7ÿab8b9ÿ}b:ÿb;b<ÿabFÿÜbGÿÜbHÿÜbIÿ·bRÿÜbTÿÜbWÿÜbXbYÿˆbZÿ­b\ÿubb9bdÿÜbgÿÜbhboÿÜbpÿÜbqÿÜbrÿÜbsÿÜbyÿÜbzÿÜb{ÿÜb|ÿÜb}ÿÜb~bb€bb©ÿ·bªb­9b®9b¯ÿÜb´þøbµÿbºÿub»ÿabÅ/bÇ9bÉ9bÐÿÜbÑÿÜbÒÿÜbÓbÔbÕbãbêÿabëÿuböÿÜbùbûÿÜbüÿÜbýÿÜbþÿÜdd$d6d<ÿÜdbd©ÿÜdªÿÜd­d®d´dµ&d»ÿÜdÅdÇdÉdãdêÿÜdùg9gÿ­gÿÜg$ÿÜg9ÿÜg;ÿ}g<ÿgbÿÜg©ÿÜgªg­ÿÜg®ÿÜg´ÿÓgµÿÜg»ÿgÅÿDgÇÿÜgÉÿÜgêÿh$h-h=ÿÜhbh­h®hÇhÉhåÿÜp[ÿÜq[ÿÜr[ÿÜs[ÿÜxxxx©xªx´ÿkxµÿxÅÿ¤y&yÿÜyy[ÿÁy©yªy´ÿkyµÿ·yÅÿ}z&zÿÜzz[ÿÁz©zªz´ÿkzµÿ·zÅÿ}{&{ÿÜ{{[ÿÁ{©{ª{´ÿk{µÿ·{Åÿ}|&|ÿÜ||[ÿÁ|©|ª|´ÿk|µÿ·|Åÿ}}&}ÿÜ}}[ÿÁ}©}ª}´ÿk}µÿ·}Åÿ}‰&‰©‰ª‰´ÿ‰µÿ‰Åÿ­©ª´ÿ­µÿ¤Åÿ©$©%ÿÜ©&ÿÜ©'ÿÜ©)©*ÿÜ©+©-ÿÜ©.©/©2©3©4©5©7ÿ©9ÿ©:ÿÜ©;©<ÿk©=©I©Q©R©U©YÿÜ©ZÿÜ©\ÿÜ©b©dÿÜ©g©x©y©z©{©|©}©‰©—©­©®©¯©ºÿÜ©»ÿk©Ç©É©Ð©Ñ©Ò©å©é©êÿk©ëÿÜ©ì©öÿÜ©ûÿÜ©ýÿܪ$ÿ·ª%ÿ·ª&ÿܪ'ÿܪ)ª*ª+ª-ÿܪ.ª/ª2ÿܪ3ª4ª5ª7ÿDª9ÿNª:ÿª;ÿª<ÿª=ªIªQªRªUªYÿܪZÿܪ\ÿܪbÿ·ªdÿܪgÿܪxªyªzª{ª|ª}ª‰ªª­ÿ·ª®ÿ·ª¯ÿܪºÿܪ»ÿªÇÿ·ªÉÿ·ªÐÿܪÑÿܪÒÿܪåªéªêÿªëÿܪìªöªûÿܪýÿÜ­ÿÓ­ÿÜ­ÿÜ­$9­&ÿÜ­*ÿÜ­2ÿÜ­4ÿÜ­6­7ÿa­8­9ÿ}­:ÿ­;­<ÿa­FÿÜ­GÿÜ­HÿÜ­Iÿ·­RÿÜ­TÿÜ­WÿÜ­X­Yÿˆ­Zÿ­­\ÿu­b9­dÿÜ­gÿÜ­h­oÿÜ­pÿÜ­qÿÜ­rÿÜ­sÿÜ­yÿÜ­zÿÜ­{ÿÜ­|ÿÜ­}ÿÜ­~­­€­­©ÿ·­ª­­9­®9­¯ÿÜ­´þø­µÿ­ºÿu­»ÿa­Å/­Ç9­É9­ÐÿÜ­ÑÿÜ­ÒÿÜ­Ó­Ô­Õ­ã­êÿa­ëÿu­öÿÜ­ù­ûÿÜ­üÿÜ­ýÿÜ­þÿÜ®ÿÓ®ÿÜ®ÿÜ®$9®&ÿÜ®*ÿÜ®2ÿÜ®4ÿÜ®6®7ÿa®8®9ÿ}®:ÿ®;®<ÿa®FÿÜ®GÿÜ®HÿÜ®Iÿ·®RÿÜ®TÿÜ®WÿÜ®X®Yÿˆ®Zÿ­®\ÿu®b9®dÿÜ®gÿÜ®h®oÿÜ®pÿÜ®qÿÜ®rÿÜ®sÿÜ®yÿÜ®zÿÜ®{ÿÜ®|ÿÜ®}ÿÜ®~®®€®®©ÿ·®ª®­9®®9®¯ÿÜ®´þø®µÿ®ºÿu®»ÿa®Å/®Ç9®É9®ÐÿÜ®ÑÿÜ®ÒÿܮӮԮծã®êÿa®ëÿu®öÿÜ®ù®ûÿÜ®üÿÜ®ýÿÜ®þÿܯ9¯ÿ­¯ÿܯ$ÿܯ9ÿܯ;ÿ}¯<ÿ¯bÿܯ©ÿܯª¯­ÿܯ®ÿܯ´ÿÓ¯µÿܯ»ÿ¯ÅÿD¯ÇÿܯÉÿܯêÿ´$þø´%ÿÁ´&ÿ·´'ÿÁ´)ÿÁ´*ÿ·´+ÿÁ´-ÿÁ´.ÿÁ´/ÿÁ´2ÿ·´3ÿÁ´4ÿ·´5ÿÁ´7´9´:´;ÿˆ´<´=ÿÜ´Iÿ·´Qÿ´Rÿk´Uÿ´Yÿ·´Zÿ·´\ÿ·´bþø´dÿ·´gÿ·´xÿ´yÿk´zÿk´{ÿk´|ÿk´}ÿk´‰ÿÁ´þ}´­þø´®þø´¯ÿ·´ºÿ·´»´Çþø´Éþø´Ðÿ·´Ñÿ·´Òÿ·´åÿÜ´éÿ·´ê´ëÿ·´ìÿÁ´öÿ·´ûÿ·´ýÿ·ºÿܺþܺÿkº©ÿܺªÿܺ´ºµºÅþÓ»ÿ »þa»þð»$ÿa»&ÿ»2ÿ»Dþæ»Hþð»Lÿ·»Rþð»Xÿ»bÿa»dÿ»gÿ»iþæ»jþæ»kþæ»lþæ»mþæ»nþæ»pþð»qþð»rþð»sþð»yþð»zþð»{þð»|þð»}þð»~ÿ»ÿ»€ÿ»ÿ»©ÿ»ªÿk»­ÿa»®ÿa»¯ÿ»´ÿ»µÿÜ»Åþø»Çÿa»Éÿa»Ðÿ»Ñÿ»Òÿ»ûÿ»ýÿÅ$&Å%ÿ·Å&ÿÅ'ÿ·Å)ÿ·Å*ÿ·Å+ÿ·Å-/Å.ÿ·Å/ÿ·Å2ÿÅ3ÿ·Å4ÿÅ5ÿ·Å7þæÅ9þˆÅ:ÿÅ;ÿ·Å<þˆÅ=ÅIÿÜÅQÿ·ÅRÿ·ÅUÿ·ÅYÿÅZÿ<Å\ÿÅb&ÅdÿÅgÿÅxÿ·Åyÿ·Åzÿ·Å{ÿ·Å|ÿ·Å}ÿ·Å‰ÿ·Å&Å­&Å®&ůÿźÿÅ»þˆÅÇ&ÅÉ&ÅÐÿÅÑÿÅÒÿÅåÅéÿ·ÅêþˆÅëÿÅìÿ·Åöÿ·ÅûÿÅýÿÇÿÓÇÿÜÇÿÜÇ$9Ç&ÿÜÇ*ÿÜÇ2ÿÜÇ4ÿÜÇ6Ç7ÿaÇ8Ç9ÿ}Ç:ÿÇ;Ç<ÿaÇFÿÜÇGÿÜÇHÿÜÇIÿ·ÇRÿÜÇTÿÜÇWÿÜÇXÇYÿˆÇZÿ­Ç\ÿuÇb9ÇdÿÜÇgÿÜÇhÇoÿÜÇpÿÜÇqÿÜÇrÿÜÇsÿÜÇyÿÜÇzÿÜÇ{ÿÜÇ|ÿÜÇ}ÿÜÇ~ÇÇ€ÇÇ©ÿ·ÇªÇ­9Ç®9ǯÿÜÇ´þøÇµÿǺÿuÇ»ÿaÇÅ/ÇÇ9ÇÉ9ÇÐÿÜÇÑÿÜÇÒÿÜÇÓÇÔÇÕÇãÇêÿaÇëÿuÇöÿÜÇùÇûÿÜÇüÿÜÇýÿÜÇþÿÜÉÿÓÉÿÜÉÿÜÉ$9É&ÿÜÉ*ÿÜÉ2ÿÜÉ4ÿÜÉ6É7ÿaÉ8É9ÿ}É:ÿÉ;É<ÿaÉFÿÜÉGÿÜÉHÿÜÉIÿ·ÉRÿÜÉTÿÜÉWÿÜÉXÉYÿˆÉZÿ­É\ÿuÉb9ÉdÿÜÉgÿÜÉhÉoÿÜÉpÿÜÉqÿÜÉrÿÜÉsÿÜÉyÿÜÉzÿÜÉ{ÿÜÉ|ÿÜÉ}ÿÜÉ~ÉÉ€ÉÉ©ÿ·ÉªÉ­9É®9ɯÿÜÉ´þøÉµÿɺÿuÉ»ÿaÉÅ/ÉÇ9ÉÉ9ÉÐÿÜÉÑÿÜÉÒÿÜÉÓÉÔÉÕÉãÉêÿaÉëÿuÉöÿÜÉùÉûÿÜÉüÿÜÉýÿÜÉþÿÜÐ9Ðÿ­ÐÿÜÐ$ÿÜÐ9ÿÜÐ;ÿ}Ð<ÿÐbÿÜЩÿÜЪЭÿÜЮÿÜдÿÓеÿÜлÿÐÅÿDÐÇÿÜÐÉÿÜÐêÿÑ9Ñÿ­ÑÿÜÑ$ÿÜÑ9ÿÜÑ;ÿ}Ñ<ÿÑbÿÜÑ©ÿÜѪѭÿÜÑ®ÿÜÑ´ÿÓѵÿÜÑ»ÿÑÅÿDÑÇÿÜÑÉÿÜÑêÿÒ9Òÿ­ÒÿÜÒ$ÿÜÒ9ÿÜÒ;ÿ}Ò<ÿÒbÿÜÒ©ÿÜÒªÒ­ÿÜÒ®ÿÜÒ´ÿÓÒµÿÜÒ»ÿÒÅÿDÒÇÿÜÒÉÿÜÒêÿÓ$Ó-Ó=ÿÜÓbÓ­Ó®ÓÇÓÉÓåÿÜÔ$Ô-Ô=ÿÜÔbÔ­Ô®ÔÇÔÉÔåÿÜÕ$Õ-Õ=ÿÜÕbÕ­Õ®ÕÇÕÉÕåÿÜã$&ã&ã*ã2ã4ã6ãb&ãdãgã­&ã®&ã¯ãÇ&ãÉ&ãÐãÑãÒãããöãùãûãýåÿÜå©åªå´ÿÜåµÿÜåÅÿÜéé©éªé´ÿ¤éµÿéÅÿ·êÿ êþaêþðê$ÿaê&ÿê2ÿêDþæêHþðêLÿ·êRþðêXÿêbÿaêdÿêgÿêiþæêjþæêkþæêlþæêmþæênþæêpþðêqþðêrþðêsþðêyþðêzþðê{þðê|þðê}þðê~ÿêÿê€ÿêÿê©ÿêªÿkê­ÿaê®ÿaê¯ÿê´ÿêµÿÜêÅþøêÇÿaêÉÿaêÐÿêÑÿêÒÿêûÿêýÿëÿÜëþÜëÿkë©ÿÜëªÿÜë´ëµëÅþÓììÿkìÿ·ì©ìªì´ÿÜìµìÅÿDöö$ö7ÿ·ö:ö<ÿšöbö©ÿÜöªÿÜö­ö®ö´ÿÓöµÿÓö»ÿšöÅÿÉöÇöÉöêÿšù$&ù&ù*ù2ù4ù6ùb&ùdùgù­&ù®&ù¯ùÇ&ùÉ&ùÐùÑùÒùãùöùùùûùýûû$û6û<ÿÜûbû©ÿÜûªÿÜû­û®û´ûµ&û»ÿÜûÅûÇûÉûãûêÿÜûùýý$ý6ý<ÿÜýbý©ÿÜýªÿÜý­ý®ý´ýµ&ý»ÿÜýÅýÇýÉýãýêÿÜýù MB@hmþ ¼þ‰þ‰ L GÌþBGÌSf €¯ JBits@ ûþšmãB±‹`#cÕVeraSansÿÿÿÿ6ÿÿþ628R00@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "                      "       #                       #     $               $    &              &    ÿÿ P ì_<õº¹ð¸ºÂg‘þ‰þ Lmmapserver-6.4.1/tests/vera/COPYRIGHT.TXT0000644002461700001440000001350212261257215017365 0ustar tbonfortusersBitstream Vera Fonts Copyright The fonts have a generous copyright, allowing derivative works (as long as "Bitstream" or "Vera" are not in the names), and full redistribution (so long as they are not *sold* by themselves). They can be be bundled, redistributed and sold with any software. The fonts are distributed under the following copyright: Copyright ========= Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. Copyright FAQ ============= 1. I don't understand the resale restriction... What gives? Bitstream is giving away these fonts, but wishes to ensure its competitors can't just drop the fonts as is into a font sale system and sell them as is. It seems fair that if Bitstream can't make money from the Bitstream Vera fonts, their competitors should not be able to do so either. You can sell the fonts as part of any software package, however. 2. I want to package these fonts separately for distribution and sale as part of a larger software package or system. Can I do so? Yes. A RPM or Debian package is a "larger software package" to begin with, and you aren't selling them independently by themselves. See 1. above. 3. Are derivative works allowed? Yes! 4. Can I change or add to the font(s)? Yes, but you must change the name(s) of the font(s). 5. Under what terms are derivative works allowed? You must change the name(s) of the fonts. This is to ensure the quality of the fonts, both to protect Bitstream and Gnome. We want to ensure that if an application has opened a font specifically of these names, it gets what it expects (though of course, using fontconfig, substitutions could still could have occurred during font opening). You must include the Bitstream copyright. Additional copyrights can be added, as per copyright law. Happy Font Hacking! 6. If I have improvements for Bitstream Vera, is it possible they might get adopted in future versions? Yes. The contract between the Gnome Foundation and Bitstream has provisions for working with Bitstream to ensure quality additions to the Bitstream Vera font family. Please contact us if you have such additions. Note, that in general, we will want such additions for the entire family, not just a single font, and that you'll have to keep both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add glyphs to the font, they must be stylistically in keeping with Vera's design. Vera cannot become a "ransom note" font. Jim Lyles will be providing a document describing the design elements used in Vera, as a guide and aid for people interested in contributing to Vera. 7. I want to sell a software package that uses these fonts: Can I do so? Sure. Bundle the fonts with your software and sell your software with the fonts. That is the intent of the copyright. 8. If applications have built the names "Bitstream Vera" into them, can I override this somehow to use fonts of my choosing? This depends on exact details of the software. Most open source systems and software (e.g., Gnome, KDE, etc.) are now converting to use fontconfig (see www.fontconfig.org) to handle font configuration, selection and substitution; it has provisions for overriding font names and subsituting alternatives. An example is provided by the supplied local.conf file, which chooses the family Bitstream Vera for "sans", "serif" and "monospace". Other software (e.g., the XFree86 core server) has other mechanisms for font substitution. mapserver-6.4.1/tests/vera/VeraBd.ttf0000644002461700001440000016253412261257215017310 0ustar tbonfortusersOS/2µ‰÷=Ï@VPCLT,e‰Ï˜6cmap¤Ãè ­¸Xcvt >¹-âRfpgmÆp9)Œgaspå glyf4Þh¥)„&hdmxE¼úÏÐHheadóO«“å$6hhea. Ï$hmtxyò€®±,kernÔê¹ÜlocaXùz[·Ämaxp}Îü name·YÍ¿ëpostø¡xúµ<†prep|a¢ç!\§::N:: R^0±p  ‡ t t Ÿ &   ; 0  0   C , [ `   0­ & ‡Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera Sans BoldRelease 1.10BitstreamVeraSans-BoldCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera Sans BoldRelease 1.10BitstreamVeraSans-BoldCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comf3f¼é=¢úff¬Tì¼bf…Tfm¤fÍ3bq%¤¼ºåfHZfmöÃð99Xm=²²fuf°f9Ñœ{Ï{X3fLfL¬šJ#ššDDÍÁf?š;ËËÕÕP¬¬w Çò/X²#öö/55îç3˜ÑX š˜¼ÍååòsfÕ+ÕÃá×åj-ÕÕð¨jìáÕ!føìƒ¦ø#^Í`lj켺3B3\Õššáfy```{ìø;ÝÕj\{šÝ®º…®`bššXîššÑÍšPËË‹‹1öðL`¨Á%Á!J–Jƒ¨7{ÉÁÁÁÁ–'žì}3˜ÑXyÍ9bœœœ“¸“¸sA„€&þ%$!:$ú#"!:"þ!: ú»dþþþþþþþþþ}þ}  Œ þ À  Y Œ €  & Y @ & þþ €²—.Aúúþúú@ÿ}ÿ>þþüû,üþû,úþùøGù}øG÷úöþõþôþó»òþñþðþïîþíì íþì ì@ëê ë2ê éúè‘èþçúæúå‘åþäþãþâþáþàþßþÞúÝÜÝdÜÛ ÛdÚÙ%ÚúÙ%ØÑ%Øú×Ö×ÖÕÖÕÔÓ Ô Ó ÒÑ%ÒúÑ‘Ñ%Д Ð#ÏÎÏ&ÎÍÎÍÌ‘ÌËÊÉ»ÊþÉÈ]ɻɀÈ@ÿÇ%È]È@Ç%ÆþÅdÄÄþÃÂþÁþÀ¿:Àú¿­¿:¾½¾2½¼½¼»¼»º »º ¹‘¹þ¸þ·¶µþ´þ³þ²±°¯­¯ú®­®ú­‘­¬‘¬}«þª&©þ¨þ§þ¦þ¥ ¤þ£¢£þ¢¢@¡ ¡ú ‘ Ÿ‘Ÿúž” žþœ›»œþ›š]›»›€š%š]š@™þ˜—.˜þ—.–‘–@ÿ•” • ” “‘“K’‘’þ‘‘%ŽþþŒþ‹þŠþ‰þˆ‡%ˆþ‡%†þ…þ„2ƒ–‚þþ€ ~þ}þ|þ{úzúyþwv¦wþv¦utuútsúr}qþpo,o,númúlúkþjþiþhc h2gþf2ed eþd d@cb c b a`a–``_ ^þ]þ\\þ[Z[þZZYþXúWþV@ÿVþUþTSRQRúQQPOPúONONMLKLKJKJIJIHúGFGFEúDCDCBA%BúAA%@?@þ?>?>=< =< ;d:þ98þ7656%5455À4 44€32 33@2 10¦1þ00¦/ .-,:-ú,%,:+d*d)þ(''& %$#@+$#" "ú!!@  %¸@‘ K}Kþ%ú%dþþdÀ€  ú 2   €  @ þþþ þ @údþ  ¸d…++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++¶, °%Id°@QX ÈY!-,°%Id°@QX ÈY!-,  °P° y ¸ÿÿPXY°°%°%#á °P° y ¸ÿÿPXY°°%á-,KPX ¸(EDY!-,°%E`D-,KSX°%°%EDY!!-,ED-fþ–f¤¼&&¶‰/ÄÔì1ÔìÔì0!%!!füsüåþ–øòr)‡Õ @Œ‹ Ô<ì2991/äüì0!!!!h3þþ3hþ˜ÕýÃþ^¢ýÌþœÃªhÕ@ŽüüÜì1ô<ì20###híËíÕýÕ+ýÕ+‹)¾K@1’ ’    ÔÌ91/<ä2Ô<<ì22Ô<<ì220!3!!!!#!#!5!!5!!!`aÝaþ¶Eþ°`Ý`þø`ß`þéHFþåR`PþøF¾þþÕþî×þþ×Õýªþî þÓ#*1s@? %$ + ,#–•,–•“,“ (/($ +/ 2ÔÄüÔ<ü<ÔüÄ991/ÄìÔÄüôìõî99999990#&&''&&546773&&'6654&¢}êosëy!ïÉõã¢dÈedÈe þÍô÷¢GUNðWWPþÓ-.);?7*´©³É çã"þ*/þá(»·¸ÅBE5;Cþ±þêBBDCBÿãÃð '3c@5  % ."™( ™˜œ41+  1 +%4ÜÄìôìîöî991ä2ô<äìîöîî0KSXííY""32654&'2#"&546#3!2#"&546"32654&3GNMHHLMGºÖÖºº××ý%Ý¥ÞûºÕÕººÕÕºHNNHHMNh{rs{{sr{¨Ø½½ÛÛ½¼ÙüÓ Ù½½ÚÚ½½Ù¨|rs}}sr|{ÿã¤ð&06@Y     ,-./+0()'%0' - ‘-¡!Ÿžœ˜ '*$ 0$*$  *  1üìÄÔÔìÆî99999991/Æäöæîîî99990KSXí9í9íí9Y"²']@„   ' 0   0%/ / %&? ? @K K K/K0ZZUZ Z U(\.\0X2_2dig`i i d&€2, ' '* 9 5005@J I'I(WW\ ['ggl ]] >7!!'# 5467.54632.#"3267™577oc%þXbiè‚þùþ»¢*(þÓ[Åk^¨PMU1—ABªwCt2ßþ>F®n¶þäkþ¾mFDÛ’áj5j:£Äþê0.;6"WþÓ/wGs¢))ê°Õ@ Žüì1ôì0#°íÕýÕ+°þò @¤£ üüÄ2991üì0!&547!þ×™’“˜)€€þò÷½ÛÛÁõíþ;ÝÝþ:¤þòø @ ¤£  ÔÄ2ì991üì0654'!¤€€€€)˜“’™þòîÆÝÝÅíõþ?ÛÛþC÷)9ðF@(  ¥ œ   Ô<Ä2Ü<Ä2991ôÄ2ôÄ290%#'%%73%þ¶JLþ³ªþ²LNþ²LNªMÁ­®¸þ¨X¸®­¶Xþ¨¶ÙÛ "@§ ¦  Ô<Äü<Ä1/ô<ü<Ä0!!#!5!Ñ ýöîýö ýôìýô ì mþÝ9ƒ@ ©¨üìÔÌ1üì0!#Ñh÷ÕdƒþÏþ‹uo¼ãß·«ªÔÄ1ôì0!!otýŒßþÝÑ9ƒ·¨üì1/ì0!!Ñhþ˜ƒþ}ÿBìÕ·/Ä991ôÌ03#ÞýñÝÕùmbÿã/ð #@ ¬¬œ˜ üìüì1äôìî0&#"326! ! ®i||jj|{jþÀþÚþÙþÀ@'&@ìååþèþåèèþþm“st“þmçÕ (@®®®  ÔÄìÄüì1/ì2ôìÔì0!%!!!ðTþ£[nTûì ÅHHû5þö¢ßð–@)% ¬œ¯ÜÄüÔì9991/ì2ôìÔì990KSXí9íY"K° TX½@ÿÀ878Y@&**"""555BJFF]]!!>54&#">3 N‘ûÃ!IFuZÖz‚þz )~ÊþåáB~Di€MLH+-ìÓzÓ±‰ÿãîð(L@+¬ – ± ¬ –±¬°#œ˜)& )üäÄüìÔì9991äôäüôìþõîî90!"&'32654&##532654&#"663 º—þ¬þºsçqlÕg™£§£š¢‘ŽŠ~]¾^ràl#!Š%'Á•Þç%%)67jcfiø[]V^*) ¿Àƒ§\3Õ C@ !  ! % ®   üÔ<Äì291/äÔ<ì290KSXííY"!!3#!!òþZ¦@¬ÕÕþ”ýj˜ý®üRþéþðJžÿãÕ=@"•¬–•¬² ¯ ˜" ÜÄüìÄî1äôìæþõîþä90!!663 !"&'32654&#"Ù½ýv,Y00þµþÚù{zÛaŒ¡¡ŒS¼lÕþåç þïôòþî12/FF‰uvˆ+-ÿã#î $7@¬¬ – •¬"œ˜% %$%üìüäîÄ1äôüôìîÖî90"32654&&&#"6632! !2åeeeefeev_¨P¬ÀBš[åþÆþøþÝþÁuEgÂჃƒƒƒƒƒƒÍþì-+¿¼11þôÙðþ߉ir§ ‰îÕE@%¯ÜÌ91/ôì0KSXííY"²]@ &5F]!!!‰eýºþ‰'ý1ÕÙûº}ÿãð #/G@( '¬¬°-¬œ˜0 $*& '&!$0üäìüìôìî991äôìäîî990"32654&%&&54$! ! $54632654&#"Élttlkrrþ|ˆŠ‹ˆ˜›þÙþÞþÝþ×›òc\ZbbZ\cœvnnuunou)ª½ÆÅ¾ª)*½ÞããÞ½UY``YY_`jÿãî$7@¬ –•¬ ¬œ˜%%" $%üìÄüüä1äôìÄþõîî9073267#"54! !"&2654&#"Í\¨R¬ÀDšZåþç9$@þŠþºiÀeffeeff!++¿¼22 Úñ"þvþ˜þŽþY‚„„‚ƒƒåN`@¨³¨ü<ì21/ìôì0!!!!åiþ—iþ—`þ}þ¦þ}þÝN` %@¨©¨³  ü<ì2ÔÄ1äüìî0!#!!åiøÕdiþ—ƒþÏþ‹uþ}Ù=ÛÇ@µ´ÔÄ291ôì90 5Ûü<ÄúþÍþ´þ¶úÏìÏÙ'ÛÛ@ §¶§Ô<Ä21Ôìüì0!!!!ÙúþúþÛëÜíÙ=ÛÇ@µ´Ô<Ä91ôì9055ÙúþÅÍúþ1ìþ1úJð!H@'Œ‘• ¡‹   "Ô<ì2ÔÔì99991/ìôüôìí9990!546776654&#"6632!!Åþ—Bj@95`VQ¼fyÈ]ôN^@D*þ—iþ—ø1Rb:4\.FOCB:*(Ç¿b›Y9>K-Áþœ‡þœo  Ml@: 40LM3 ¸30 ¸0¸·7$¸·CN34L **)(I(*)4=NÔÄììÔììîþ<Æ991ôììÔììÄîÄî299999032654&#"#"&54632536654&'&$#"3267#"$'&5476$32!#?iZYjkZXiš…Y¬×Ø«Y…Ñ|Ž:;_þã¦tÔZ”¥ked“~üYk}þÙ˜¹þ¸€€†ˆ~~O´àn{KMþºþ×'{ŽzyþZGOùÈÈúPGƒýKÉd¯Iz„=;bþɵ•þûdbg^P¢agƒ}}I½¶J}|ˆ«¡bå~þñþÔ 'Õ @@     % ®   ÔÄ91/<äÔì90KSXííííííííY"K° TX½ ÿÀ @878Y@€ / V f  t Š Ÿ ¿ ¿ Ï Ï ß   %* IFGH XYVWhifg` t{zu{t ‰††‰ ™–•š ¶¹ ËÅÅËÂÍ ÙÖÖÙÕÚ /]]!!!!!Fý¦_þ})Ë)þ}ý¨™ÌþðÕú+%R¼‰Õ P@%¹¾¹ ¹   !üì2ÔìÔì99991/ìôìôì90@ ""/"P"]2654&+2654&+)! [^^[ÕâtutuâH|ˆþÜþÖýB7f“PNMQþÄýsbcaaþy$ÂØÔÕ¼Ïm™fÿã\ð;@   ®® œ˜- +üÄ2ì1äôìþÄÅ990´/_]%# !2.#"3267\jæ}þ‹þL´u}æjkÐsÎììÎsÐkR78¡ef¡87þËIDþøèçþøDI¼9Õ.@À À -. üìüì99991/ìôì0²P]32654&#! )=Šìùøíýõ–TMwiffixþ°þ°þj²üqêßÞè#ateþø§©þ÷eta¼áÕ 0@À¾ÀÀ   üì2ÔÄÄ1/ìôìôì0¶ P p ]!!!!!!¼ýrgý™¤ûÛÕþÝþêþÝþªþݼËÕ +@À¾À üì2ÔÄ1/ôìôì0¶ P p ]!!!!!¼ýrgý™þÕþÝþêþÝý‡fÿãúðK@%   ¹®® œ˜1 3/-+üìôäüÄ1ÄäôìîîÅ9990²_]%# !2.#"3267#!úþÊ¥þ‹þL¼‚•y}÷|æùðÝ@À¾   üì2Ôì21/<ô<ôì0@P ` p Ÿ ]!!!!!!¼8þýÈþÕýÇ9ú+yý‡¼=Õ7·Áüì1/ì0K°TK°T[X½ÿÀ@878Y¶@P]!!¼þÕú+ÿþf=Õ L@ À  üÄì991äüì990K°TK°T[X½ ÿÀ @878Y¶ @ P ]!!#3265¼þÑþÍN3IO@UZfi ]]!!!!¼®mþRýáþ“Õüú+üfÿãfð 2@®® œ˜ -7-+üìüì1äôìî0@ /?]"3254 ! f°Â°±Â±h˜þhþ˜þ™þg™Ùþüìëþüëìþdþ•þ–þdœjkœ¼‰Õ 1@ ® ®  - üì2Ôì99991/ôìÔì0²]! !#!32654&#¼1þÏþãþþÕpzzpÕýêëýýú¾þ_mddlfþÕfðb@ ®®œ˜  - 7-+üìüì9991Ääôìî90@,  '/V S f ` w w p  Y Y YXj i x ]]# ! !"3254þþf™gk•×Ê-þ‘þã°Â¾´±Â˜lkœþhþ‘üþ”\þ°þüìðÿëì¼Õ‡@2% ® ®     üì2ÔÄì9991/<ôìÔì9990KSXíí9Y"²]@66EEVVPee`]2654&+!! !.#ßyiiy¢þL'O}@Ñþf¶7q^?ZgfXþþöýËÕÆÖ”¾-þXspR“ÿã-ð'§@*% Ãî®%œ˜( "(ÜìÄÔìÄ99991äôìþåå9990@Tp)9999 JJJ X ]\^^ Z!joooh o n!t t t || |!– — ›šœ š!¦ ¦ ¦ ªªªª ª!(]].#"!"$'32654&/.54$!2Ë{êhŠ„Yu¤ùÒþÛþÓŽþâ |~†[ˆ•àÏ {¦þÄ78LP@À88Ôìüì1/ôì20K° TK°T[X½ÿÀ@878Y²@ ]!!!! `þþþÕþÝûN²¼ÿãÃÕ3@ À˜  9üìüì1ä2ôì90¶@pŸ]!3265!! ¼y‰ŠyþÂþºþ»þÂÕü¹ŸŸ¹üþÃþÊ6= 'Õ˜@'%ÁÔÄ91/ì290KSXííííY"K° TK°T[X½ÿÀ@878Y@, ° GGHHEJWX]]! !! ƒŒ‹ƒý×þ5Õû²Nú+=“Õ x@J 6  6 6 6   % Á    ÔÌ91/<ì2290KSXííííííííY"K° TK° T[K° T[K° T[X½ ÿÀ @878Y@Ì  % :?:?3 0 0 @ @ @ ^^a ¸± ° °         '('(%* /66220002 4 6 ?IFHE J ]]ZZUURRRZ U ] ooonhheh k n i o wwx v x ˆ…‰ ·º¶¸±¾ K]]! ! !! !=qsnþ þDþñþôþDÕûÃ=ûÃ=ú+oû‘'Õ û@E    %  Á   ÔÄÜÄ91/<ì290KSXííííííííY"K° TK°T[K°T[X½ ÿÀ @878Y@X  /& <3 _P € ¿°    ++%$%+ :55: P ejo ¹µµº ]] ! ! ! !üþoþ£þ¦þmþ’GF”úýþþúÛþáÿìßÕ @(%Á:: Ôìüì91/ì290KSXííííY"K° TK° T[K°T[X½ ÿÀ @878Y@, %%0@P`° %*5:0 O o ]]! !!¥TT¦ýÇþÕýìü ý‹u\qÕ w@%ÀÀ ÔÄÜÄ991/ìôì0KSXííY"K° TK° T[X½ ÿÀ @878Y@ %)69? FHO V_ o ]!!!5!sçüß8úë!üöÕéü7þÝéɰþò@ĤģüüÌ21üìüì0!!!!°mþçý“áú áÿBìÕ·/Ä991ôÌ03ýòݾ“ùm‹þòø@ĤÄ£ÔÌ2ì1üìüì0!5!!5!øý“þçmþòá`áϨåÕ@ ÔÌ91ôÌ290##ÕñþfþgòÕýÓ-þÓ-þþÛ´/Ä1ÔÌ0!5üþÛ¾¾^î“fN·ÆÅÔÌ1ôì0K° TK°T[X½ÿÀ@878YK° TX½ÿÀ@878Y´] #yÄþfþˆxXÿãÅ{ %@*  ÒÏŸÐ ÌËŸ#ʘ # = ;&üìÄôì229991/äôüôìæîöî9990@L/'= =!?'M M!] ]!n n!~ ~!p'Œ Œ! !­ ­!½ ½!20C@SPc`…€“¢ ²°]]"326=%!5#"&54$!354&#">3 ¢pq[QeŠiþ—H´®Ù"Ó†ŽsÆUsèt/ øLJDM‘m)‡ý¦f]ˢŸUO..ï¬ÿã^ 8@¡ С˜Ê£ÐB@ üì22ôì1/äìäôìæî0´O`]%2654&#">32#"&'!!syyss{{{J´uÏ þöÏu´Jþšf稠 ¨©ŸŸ©Õb]þ·þýþýþ·]b¢Xÿã5{7@ÌÔÌ Ô ¡¡Ê˜B ;üÄ2ì1äôìþôîõî0´_].#"3267# !25I“O–§§–T—@T­WþÑþªV/X«=þÜ20¯¯21þÛ77\ÿã8@¡Ð¡Ð˜Ê£ @B ;üìôì221/ìäôäìäî0´O`]!!5#"322654&#"¦hþ˜J²uÏþö Ït³¢syysryy¼Xùì¢c\II]üɨ  ¨¨  ¨Xÿã {C@!Ø ÌÔŸ ×ŸÊ ˜ D ;üìôìÄ91äôìäþôîî90´/?]!3267# ! 4&#" ü» œŒqí}þþÐþ¯K"=þw`h‚3f~~CDþì015:þ“f}un'`@ ¡Ÿ£³   E Ü<ìü<ÄÄ991/ä2üìî2990K° TK°T[X½ÿÀ@878Y@ €€]#"!!!#35463ÆL<2þÎþš²²ÌÖë7DNÿü `N·¯\þFy(K@&ÌÔŸ¡ Ð Ê ³#¡ÚÐ& @ B;)üìÄôì221/ääìäôäìþõî990´O*`*]%#"54325!!"&'3265"32654&¦J²uÍþô Íu²Jhþ«þ¼iÄc^´[°¤ìo|xsp||¾b\CúûA\c¦üþòþã !65š¤¤–šŸ¤•–¤¬5@  ÛÐÊ£ G üì2ôì1/<ìôäì9990´`€]!54&'.#"!!>32þ˜ H.p€þšfQ¶nÂɪýVo™“n#'­™ýÙý¨b]î¬)@ݳ£ ü<ì21/ìôì0@ P ` p € ]!!!!¬fþšfþš`û þÜÿ¼þF =@ ŸݳÚ £  ü<ì2Ä991ìäôìî990@ P`p€]!+53265!!¬fØÍ±>fLfþš`û´áíë\‡þܬy Œ@³£   üì2ÔÄ91/<ìä90@`;IIZ]X_ogvv{ˆ…‡‹Ÿ•–›¹:DGJV]g`ewpv|‡ˆ‹’—›]]!! !!¬fœ ýÝNþNþKþšü±›ýþý¢Óþ-¬·£ üì1/ì0@ P`p€]!!¬fþšù쪴{%t@)  Û Ð#ʳ  H H &üü<üìüì991/<<äô<äì29990K°TX½&ÿÀ&&@878Y@'0'P'p'€''¯']>32!>54&#"!4&#"!!>32ºD»pÁÊþ˜FNfoþ˜@Rgpþ˜hB«gt²¦hmîãýVH wk¨ŸýÚHºk©ýÙ`¤_`p¬{5@  ÛÐʳ G üì2ôì1/<äôäì9990´`€]!54&'.#"!!>32þ˜ H.p€þšfQ¶nÂɪýVo›‘n#'­™ýÙ`¤b]îXÿã'{ -@¡¡ ʘ BLB;üìüì1äôìî0¶7?G]"32654& ! Áw}}wu||u!Eþ»þßþÞþ¹G{«¡¡««¡¡«þÈþìþìþÈ88¬þV^{;@¡Ð¡Ðʘ޳B @ üì22ôì1äääôäìäî0´O`]%!!>32#"&"32654&þšfJ´uÏ þöÏu´¤s{{ssyy¢ý´ ¤b]þ·þýþýþ·]7©ŸŸ©¨  ¨\þVy ;@¡ СÐʳޘ @B;üìôì221äääôäìæî0´O`]"32654&#"325!!ºryyrsyyyJ²uÏþö Ïu²Jhþ˜w¨  ¨¨  ¨ý+c\IG\c¦ùö¬ì{C@ À ”Ê ³  üÄì21/äôäüÄ990K°TX½@ÿÀ878Y.#"!!>32ì/]/Š•þšfE³}*(/±¥ýü`¸nejÿãb{'Ü@@  6  6% ÌÔÌÔŸŸ%ʘ( SRP"M(üìÄÔìä99991äôìþõîõî90KSXí9í9Y"² ]@^ #  ,. . . . . ) 9; ; ; : : K J J J H w w ºº º º º º %  7 ?)_) ]].#"!"&'32654&/.54632sÖ_fcKa?¾þøþúoí}kátijIm?ïÀôücÚ=þð0035+. # «³´##44:90/ ¢¥²¬¤žx@¡³¡    Tü<Äü<ÄÄ991/Äìô<ì2990K°TK°T[K°T[K°T[X½ÿÀ@878Y@??PPP`` ]]!!;!"&5#33qþ>\¸þÍÔ±²²žþÂÿþ%N7ÿ±ÔÛ> ÿã`;@ ÛИ³ G üìôì291/ä2ôäì9990´`€]!3265!!5#"& hG.p€fþšQµmÂË´¬p[þí.‡w#&¬™)û ¢b]î`è@'%ßÔÄ91/ì290KSXííííY"K° TK°T[X½ÿÀ@878Y@| 0@Vf€ °°°°ÀÀÐÐàààðð  &$+)64990FFII`x‡ˆ‡ˆ––™™•š¨¶¹$]]! !!fgþGþw`üúû H` @J 4  4 4 4   % ß    ÔÌ91/<ì2290KSXííííííííY"K° TK° T[K° T[X½ ÿÀ @878Y@æ 550 G @ @ _ l  °°°°° ÀÀÑ Ð ààï    &$+)*+ $ % /554;::78 ?GIFHGH YVV[ T Y _f`b```d ` upspppt p ‡ˆ„‰ † ‹ ”› ¦©¦©¥© ¦ ª ¶¹¶¹ ÆÄÊÉÕÙ×Úåé æ ê []]!!!! !H\¼½+¼½\þÙþy½¼þy`üüýüû üþ ` „@F    % ß   ÔÄÔÄ91/<ì290KSXííííííííY"K° TK°T[K°T[K°T[X½ ÿÀ @878Y@Ú  / 3< CL R\ bl sz € ——œ Ÿ  ¯ °°°¿ ¿ ¿ ÀÀÏ Ï ÐÐß ß ààï ï ÷ð÷ÿ 2     $++$ 4;;4 0 DKKD o †€‰€ —•š™š– §°¿¿° ÀÏÏÀ ×ÐߨßÐ çàïèïà ùö:]] !! ! !Çþl{åè{þl¨þ…üùþ…=#þ´LýßýÁbþžþF`A@C %  ŸÚ³  ÔÄ91ä2ôì9990KSXííííí9íY"K° TK°T[K°T[X½ÿÀ@878Y@¤ @Pet†€” ´°°°ÀÀÔÐàà $$$5586699EEJJEEge†††ˆ ˆ—––™ ™¨ªª©©µ¼¸° ° ¿ ¹ ¹ÈË ËÉÖå9]]! !+5326?f-fþ)G½›Ïp[S `ýøû6»•ë:K\F` ž@%¡³¡ ÔÄÌ2991/ìôì0KSXííY"K° TK° T[X½ ÿÀ @878Y@DYVifyv„“ &)/ 9? J_ Žž±½ÀÏÐßãì]]!!!5!uÑý²NüNýË`úýšÿúfþ²²$^@1 %   ! Ä áÄàÄ£% $  %Ô<Ìü<Ä299999991üìôìôì99999990#"&554&##5326554633#"3²ÙÚÈlŽ==ŽlÈÚÙEUZnoYUmá°ÁÀ–ußt–ÍÁ¯áWަŽŽœ¦Wþç¶Ôì1ÔÌ0#çãøþ²²$`@2%   ÄáÄ#àÄ£%# %Ô<Ì2ü<Ì99999991üìôìôì9999999032655467&&554&##53233#"##FŒUZooZUŒFÙÚÈlŽ==ŽlÈÚÙmW¦œŽަŽWá¯ÁÍ–tßu–ÀÁ°Ù²ÛR#@ § §ÔÄ1ÔìÜìÀ990#"'&'&'&#"56632326Ûj³`k›^X¬bk²`k›^V©RôPE:=MSôPE:=Kÿÿ 'k'$u 'm!{@S!! ! !%!®â !  UU "ÔÄÔìÔî9999999991/<ÆæÖîî9990KSXííííííííY"K° TX½"ÿÀ""@878Y@À/!/!:!o! ¶ ¶º·°°°·ºº¿¿¿º¿!¿! # ///  /// "+ #EKUZ` ` ` ooo``ooo`fi `#tuyz{t …Š…Š •š° ° ° ° ¿¿¿¿°°¿¿¿·°³¼ D]] !!!.54632%32654&#"!þ}^ý¦_þ}§vt¨þwM66MN56MJ™Ì¸úHþð¸"K+u¨¨u/L{6MM66MMûŸRÿÿfþo\ð'&Ýsÿÿ¼ák'(´uÿÿ¼öm'15uÿÿfÿãfk'2Nuÿÿ¼ÿãÃk'8'uÿÿXÿãÅf'DºÿÿXÿãÅf'DCºÿÿXÿãÅf'D׺ÿÿXÿãÅ1'DŽºÿÿXÿãÅ9'DغÿÿXÿãÅ'DܺÿÿXþo5{'FݸÿÿXÿã f'HÙÿÿXÿã f'HCÙÿÿXÿã f'H×ÙÿÿXÿã 1'HŽÙÿÿ¬f'ÖÿwÿÿÿÕf'ÖCÿwÿÿÿþðf'Ö×ÿwÿÿ<²1'ÖŽÿwÿÿ¬9'QØòÿÿXÿã'f'R×ÿÿXÿã'f'RC×ÿÿXÿã'f'R××ÿÿXÿã'1'RŽ×ÿÿXÿã'9'RØ×ÿÿ ÿãf'Xòÿÿ ÿãf'XCòÿÿ ÿãf'X×òÿÿ ÿã1'XŽò5ÿ;ÃÕ *@åã ä WV W Ô<äü<ä1ä2ôìî20!!!!!5!VJ#þÝþ¶þß!ÕþƒîûÑ/î²dLþ @æçæ  XYXÔìüì1Ôìüì0"32654&'2#"&546HdcIHdeGBz0/11-0|D¿Á\dHHbcGHd¢3/0xDCy-03¿Á®þlj˜#W@. ÌÔ ÌÔ ¡ ¡!ʘ$   B$ÔüÔ<<Ä2ì22991Ääô<ìÄþôîõî9990&&##667###$4%3¾NMMNËJAY—9S’: ¢þúþö¢G“Z,“lm”*9þÜ02ýi2/þÛ þä (.ô##þá}çð@@!–• Ÿ¬œ ¬ Ô<ÄÄü<ÄÔÄ1/Ä2ì2ôìî2õî990&&#"!!!!3#5356!2ÛF”Mvquþ‹û–ãÂÂþ\µºþâ'&}ƒªïþºþö Fïªøÿ=øð3?k@8@1:4 %+èè1œ@ =!+%74:!=\.!\=[.7[(@ÜÄìÄÔÄìÔìî9999991ÄôìþÅÅ999990&&#"#"&'532654'&'&&5467&&546326654&ucž9KL¼ ÒŸquMKòÕUµfs¶9AN´$Ë oqKAåÉT´þšDC{¶AFжã''1/CO Y­}uŸ0)qI‘§í)+2(FJW³‚hš33oK¢ý…L2CbBO4Cj'‘ö`·é ]Ôì1Ôì04676632#"&'&&'535‚IIƒ245633ƒJI‚326úJ‚235624IJƒ336633ƒÿ;dÕ &@ ^^ÔìÔìÄ91Ä2ôÄÌ0!###&&54$\¾½¾ÌÞÕùfùùNÛ²¾è¬ÿãh0j@4.(" !+ŸŸ+Ÿ£˜/"!(%  a%.(a_ . 1üìÔìôìÝî99991/äþîþÕî990@ /2O2p2Ÿ2]4$! #"&'532654&/.5467.#"!¬ —1]EtkåçAŠJ8s6HX7bFXT‹‘`[efþšZÞÜàÚG NJ%94%@©u½¼ôH9/D7'1‡Ztž2UYnmû´åÍ 4Lb@8-*+'î0î!ëæ5í æ2+ëA'*,$0-+$!1g3f$cX;eX3cGMÔììüìüìî299991/ì2îþîüîÖî9990"32676654&'&&#32654&'2#'&&###2#"$'&5476$yÐWWWWWVÑy{ÎWWWWWXϲ##NOM+°®i`)Goåk&: Õ1˜mmllmmþù˜˜þùmmllmm3WWWÏzyÏWVVUWWÏyzÏWXVþÙÏ5442ŠwyVpP:ÝÕNAþœD7nmmþúš˜þûmmnnmm˜šmmnåÍ1IH@(  ïïëæ2í&æë>f,X c8e XhDJÔììüì2ìî1/ìîþîüþÅþÄ990&&#"3267#"&54632'"32676654&'&&'2#"$'&5476$+9o9q~r@s.Aƒ>ÓþþÓE€îyÐWWWWWVÑy{ÎWWWWWXÏy˜mmllmmþù˜˜þùmmllmmf×%#€rs~$#ÕêÂÃé·WWWÏzyÏWVVUWWÏyzÏWXVšnmmþúš˜þûmmnnmm˜šmmn'“RÕ v@>  %  î  ji i jiÔìäÔìÔìä91ô<<ì2Ô<<Ä9990KSXÉÉÉÉY"73#######5ww㪉L‰¬q®¬¬Õããý¾µÿþKBþM³mî¢f7·ÆÅÔÌ1ôì0K° TK°T[X½ÿÀ@878Y´]!#‡þÄfþˆÅ;;1\@ñðÔüÔì1ô<ì20K° TK° T[K°T[K°T[X½@ÿÀ878YK° TX½ÿÀ@878Y3#%3#Åëë‹ëë1öööÙÿöÛ =@!   §¶ §  Ô<Ä291Ô<ì2ü<ì2.À990!3!!!'7#5!7!Ùü•‘ëþ^®Püêü–’쨰ý¨Û1}´ëÜíþϲíÜÕ¡@7%À ®À ¾ À  /ÔÄÄÔ<ì291/<Äìôäìîî90KSXííííY"K° TK° T[X½ÿÀ@878Y@&W††³³µµ ] !!!!!!!!!{ÿyþ}‘ýsfýš¤ûÛþ“þÕýžbþÝþêþÝþªþÝ^þ¢-ÿ¶– +è@> +,   )*&®& ®œ&˜,+,* # )-#7-+,üìüìÀ999999991äôìîÀÀ99999990@p- -*'&!/-976!9)?-GYVT!Y(Y)jege!j%j($'))68)KFE I)Z^SVV T!V"[(j ejlaf c!k(x ™ ˜ ª ]]3254&/.#".5!27!"&''\4ƒS±ÂM3‚R°ÂþêJJ™gšøfÇqÉMLþhþ˜™ÿfÊqs>;ëDu1“:9þüì@q.þêdú—kœKMÇsÇcÿšþ–þdOOËqúé /B@#  $'!ó-ôó!ò0 $k*k0ÔìÔì99991üìü<ìÀ999032654&#"&&#"326#"&546326632#"&¼+vIZqgLHwþñ+tKZqfMGz©DŸa‹Æ¯ŒZ™cGž_ŒÅ¯Œ[–1CDeOMeeCCdOMeia‚~ó³¼êq„~ò´½ënÙÛ .@õ§õ  § l l Ô<ì2ü<ì21/ìÔ<ìü<ì0!!#!5!!!Ñ ýöîýö ýöúþþžìþžbìbûêîÙÛ¨ '@  § ö Ô<Ä2291/äüÌ90%!55ÛúþüúþîîîÆÑÑóPëNÙÛ¨ '@ §ö  Ô<<Ä291/äüÄ907!!55%Ùúþúþîî´ôþ²ëþ°óÑyÕ´@B  % ÷ ÷   nm n mÔ<ì2ìü<ì2ì999991/ä2Ô<ü<Ô<ì290KSXííííY"²]@, $+6:FI   0@€€°° ]]!!!5!5'!5!! !!!!Nþ9þƒþ:Æ1þk$þ±! þ°%þj1Ç þ` ÂBVÀþ3ÍýåÀVB®þT¢` :@! Û˜ ³Þ!   !üì2ÜÄì91ää2ô<ì990!3265!3267#"&'#"&'®idfgdh!'!5]-Yq#/‡YJhþT ýutqqt‹ýG8 úKSOO/0þ;ÿçR)8@'! '!ù* $$*ÔÌÜÌ9991äÌÜÌÎÎ9906654&#"#"&54632#"&54324&#"32þ;'#ÂS0@ºÒõþ»ÿ¶êï³e‹ID`IFa~¬qº9WzºC2Eqþ¾þèþ¨þGé·Ë Uór|þïÒtx)þw“Á O@  ûûú  ÔÄÜÄÄ91Äüìî990@ &#)  ) ( ) 8 ]]!! !!5 Bü’lý’¥ú–ºý_Áþ÷ý{ýNþö¬²–þw²Á@ýüúppÔìÔì1üìì20!!!!–þ¨ý”þ¨Áø¶)ù×ÿÝJD/@    ÔÌ991/<ÔÌ22990#!#!#"663J'°šþá˜î—þá˜7: Õ¼ÙDàüœdüœd>DÇœ3þ‹°,B²*#¸²ÿº @ÿþ- *(&  qr q-Üìüì991üììüìì9026732#"&54&#"#"&54632jcãìi‚RA@Ae '&>ÄkTF32°-üÓÓ…hB:Yr õ7Œ^‘¤Òâ‰YUW¦O\©KàØ=ÈÄ4>3:rWTþ@LH†t„8;##´¯uuð 9A  @œ  uu ÔìÔì991ôìôìüì02#"&546!!"32654&BÕ÷öÖÖ÷÷Æ7üÉœT[[TS[[ðÞ¾¾Üܾ¾ÞüMÈÑ~tt||tt~7îåF³ ½  @  xwx w ÔììÔììÀÀ9991/<ì2üì990!!654&#"!!&5! Ë#ýŸ~„˲±Ë„~ýŸ#~zx89xzÿ#V¥Ëééˤþ÷UþÝy¤9yþ‡þǤþêXÿã{>Ì@B8>6Ò6Ø'Ì&Ô# Ÿ6Ï-*Ì>Ë;Ÿ×Ê0*˜? - 6 & 7 3;?üÄìÔü<ÔìÄ999991ä2ô<Ääü<ôìÄæþ<ôîîî9990@N>>?@MMO@^^_@nno@@@­­½½2=0>B=@>R=P>b=`>ƒ=€>’=>¤= >²=°>]]4&#""326=>32>3 !3267#"$'#"&54$!354&#"w`g€ýápq[QeŠý^wßa–ÙGMÌz =üº›qí}ÿ~³þ÷Heß‹Ââ"Ó†ŽsÆUªf}un²LJDM‘m)JMOMOþÂþöf~~CDþì01kdkdŨŸUO..Nÿ¢)Á +¸@> )+ *& ¡&¡Ê&˜++, #* #)B#LB;,üìüìÀ999999991/äôìîÀÀ9999990@@:5 ;75!8)?-IF KGD!H)[VT!U(ikfe!e(5:)EJ)U^(i em( ]].#"32654&'.5!27!"&''XK/w}HO0u|ý;CDG"j³K“mFEþ»þßl¶M”pD«¡)A‹«¡+CýäNÈ{8,,že•PÊ~þìþÈ--›^ÿãÕ!M@*‘• Œ‹ ¡˜ "  "ÜìÔÔ<ì299991äôìþíôî9990!3267#"$54677665%!!çiAm@84`VQ½ewË\ôÿN^@D*iþ—iÛ1Q~d:3\/FPDBþÆ*(Ǿc›X:=L-Ãd‡Õ @Œ‹ Ü<ì2991/ôüì0!!!33þ˜h=¢þ^ýÃqdþœÙÛ@ §ÔÔì1ÔÄì0!#!Ùëûéý’Lÿ×Z² n@*      %  º@  ÔÄ91Äüì90KSXÉÉÉÉÉÉY"3##'%ƒ×`ý²wþÍ‘%hß²•ùºN7ý…þV7#w@I #"!   %  ¬”¬” ŸŸŸ!£Þ$Ä2äüìîî2õîõî99990KSXí9í2Y"&&#"!!#"&'53267#5!766327.T*Zd!þ´…)å¿A…D.U)Ycuò!3*ã¾B„ìþs¨îý_ÎÌþsMîüÎËÙáÛ#;C@!.9* 1§ §"§9*§1<-<Ô<Ä21ÄÔìÜìîÜîÀ9999990#"'&'&'&#"56632326#"'&'&'&#"56632326Ûj³`k›^X¬bi³an“ ›^V©gj³`k ›^X¬bk²`k›^V©#ôPE:=MSôNE;=Kþ³ôPE:=LTôPE:>K“Á ²¸ @ ú/Î91/îî90!!!Éþºþ#-3úmVüªÁú?ž‰j' 5³  »@  y yÔü<Ôì2991ô<ì299055‹þÛ%þÌþÜ$þ'òÝÝòqºsòÝÝòqºÁ‰' 5³  »@ yy Ô<üÔ<ì991ô<ì29905-5%% íþ%þÛþ!ëþ$þÜ'þºþòÝÝòþºþòÝÝ¢^ƒ #@¨   ÜüÔüÔì1/<<ì220!!!!!!öhþ˜ú¬hþ˜ªhþ˜ƒþ}ƒþ}ƒþ}ÿÿ 'k'$uÿÿ 'm'$uÿÿfÿãfm'2NufÿþÁ×P@" À¾ À À   -+ üìÔÄÄÔì299991/ì2ôì2ôìÀÀ0@ !!?!O!_!]# !3!!!!!!"# !2œiþßþâ iZhýsfýš¤û / þFþ&Úº 0²âäåä²þÝþêþÝþªþÝ…ihƒXÿã^{'3t@2" ØÌÔ Ÿ.¡(¡×Ÿ%ʘ4"1 1 +B;4üìÔüÔÄì9991ä2ô<ìäìîþôîî9990@/5?5O5O5_5o5o55F"]]4&#"!3267#"&'# !2>3 %"32654&îw`h‚Aü» œŒqí}~ÿ~¥ÖHRÕ‚þÞþ¹G"†ÎQRLJBúcw}}wu||ªf}unwf~~CDþì01QWTT88RVWQþÆ:«¡¡««¡¡«°²¹´ª/Æ1ôì0!!ü²þþ°²¹´ª/Ì1ôì0!!ø²þþÓX…Õ +º@    ÜüÌÔÌþÔÎ1ô<ì20!3!3!þ¬ãÕdþþ¬ãÕdXbþžþå`þ ¼XoÕ +º @  ÜìÔÌÜîÔÎ1ô<ì20!#!#!TäÕeúTäÕeÕþãþ `þáþ¢^ÓX‹Õ¹@ ÜüÔÌ1ôì0!3'þ¬ãÕdX`þ X9Õ¹@ ÜìÔÌ1ôì0!#åTãÕdÕþãþ `ÙVÛ® 0¼@ §¦ z{z Ô<ìü<ì1ôÄüÔìî0!!!!!!Á3þÍ3þÍþúþ‹þËXþËìþ#îuv@A%ÔÄ91ÜÌ990KSXÉÉÉÉÉÉÉÉY" úþþôþ þ üÏüÇ9%ûÛûÓ-ÿÿþF1'\Žœÿÿÿìßk'<Íuþhÿãîð+@55%˜œÔÌ1ää0KSXííY"#3¸à¦à J=ÏÅ#/@ ! ! $A !* @&00   '}|~-} |0Üìì2üìì29999991Ôìì2üìì2À999990'7&&5467'766327'#"&72654&#"²Ï™ÏÑ™Ï0l=6l9ϘÏÏšÏ.j?:l¦[€\[€~ ÏšÏ1k??l.ÍšÏÏšÏ7n6?i/ϙζ\\\]~ž‰‹'¼¶yÔì291ôì905‹þÛ%þ'òÝÝòqºÁ‰®'¼¶yÔ<ì91ôì905%%Áíþ$þÜ'þºþòÝÝ+Bu@& ¡Ý Ÿ£ ³    ETü<ìì2ô<ü<Ì991/<ä2ü<ìíî2990K°TK°T[K°T[K°T[X½ÿÀ@878Y´@€]!!#"!!!!#35463Ùiþ—JÆK:þþ—þkþ—°°ÌÖþÜ$ë7DNû `ü `N·¯'Bl@! ¡ Ÿ£ ³     ETü<ìì2ôüÌ991/<ä2üìî2990K°TK°T[K°T[K°T[X½ÿÀ@878Y´@€]!!!"!!!#3546{Çþ—þîL<þçþš²²Ìùì)7DNÿü `N·¯3ÿ;ÃÕ?@!å å ãä W VW Ô<<äü<<ä291ä2ôüÔ<ì2î20!!!!!!!5!!5!VJ#þÝ#þÝþ¶þÝ#þß!Õþƒîþ<îþƒ}îÄîÑ9‰·üì1ÔÌ0!!Ñhþ˜‰þ}“ÿLƒ¹@ ¨ÜìÔÌ1üì0!#øTæÓeƒþãþ `“ÿFƒ +º @¨  ÜìÔÌÜîÔÎ1ü<ì20!#!#øTæÓeúTäÕeƒþãþ `þáþ¢^Bÿã Vð #/3?K|@C3 2211 003%@ *™$F4 ™:0˜2$œL3IC1!  C=!'= I7' -LÜäìÔÌìäîîîöî991ä2ô<<ä2ì2îöîî20KSXííY""32654&'2#"&546"32654&'2#"&546#32#"&546"32654& ÇHNNHGLLGºÕÖ¹ºØ×øÅHNNHHMNGºÕÕººÕՇݥ޺ÖÖºº×׺GNMHHLMh{rs{{sr{¨Ø½½ÛÛ½¼Ù8|rs}}sr|¨Ù½½ÚÚ½½Ùùó ý ؽ½ÛÛ½¼Ù¨{rs{{sr{ÿÿ 'k'$uÿÿ¼ák'(´uÿÿ 'k'$uÿÿ¼ák'(´uÿÿ¼ák'(´uÿÿ¼²k',ÿduÿÿÿëÝk',ÿduÿÿ)Ÿk',ÿduÿÿ=k',ÿduÿÿfÿãfk'2Nuÿÿfÿãfk'2Nuÿÿfÿãfk'2Nuÿÿ¼ÿãÃk'8'uÿÿ¼ÿãÃk'8'uÿÿ¼ÿãÃk'8'u¬`·ß üì1/ì0@ P`p€]!!¬fþš`û ‡îyf6@ ÆÅÔÌ91ôì290K° TK°T[X½ÿÀ@878Y3#'#‡ò²ÇDzfþˆáá¤\9É@  ¼@ Å€€ ÔìÔì99991ôìüì9999990K° TK°T[X½ÿÀ@878Y@T              ( ]]'&'&#"#4632326=3#"&7/$&‹g]$I)=%$(‹g]$CT%>;ˆ”+@9ˆ”ÅX;EµÔÄ1ÔÌ0K° TK°T[X½@ÿÀ878YK°TX½ÿÀ@878Y!!Åvýм°PF i@  ÔìÔì1Ô<ÔÌ0K° TK°T[K°T[X½@ÿÀ878YK° TX½ÿÀ@878Y@]332673#"&° cSSc ®œœ®FFJJF™™w;‰1*·ñ‚Ôì1Ôì0K° TX½@ÿÀ878Y!!wþî1öãá C½ @ ƒ:ƒ Ôìüì1Ôìüì0K° TK°T[X½ÿÀ@878Y32654&#"4632#"&}M67LM67Lš§vv§§vv§þ7LM66MM6v§§vv§§þoË5@   ÔÔÌ991/ÔÌÔÌ0K° TX½ÿÀ@878Y!#"&/32654&'Z:7{0f42S!:A+->j/_[ ˜.(R<ÁîÕfE@ÅÔÌÜÜÌÌ991ô<Ì20K° TK°T[X½ÿÀ@878Y3#3#ƒÙø£-çþð®fþˆxþˆVþo@   ÔÄÌ991/ÔÌÔÌ0!33267#"&546Å2&;1'M(7^)s{6CI'1œ \V5m‡îyf6@ ÆÅÔÌ91ô<ì90K° TK°T[X½ÿÀ@878Y 373‡ÿ²ÇDzÿîxããþˆÿ¤ìÕ `@2 % À   „ü<ü<Ä.9991/äì90KSXÉÉÉÉY"!7!!'%Çþþs¤ûÛ”#Õþ`¹ÁþðþþÝ j¾ÅÿÛ ~@-   % £   T ü<ì2.À991/ì90KSXÉÉÉÉY"² ]@utƒ@ P ` ` tp p €€ ]]!7!'7Çhoðþ˜}oìþ Xš¤üÇVš£ÿÿ“ÿã-k'6Éuÿÿjÿãbf'Vàbÿÿ\qk'=Ïuÿÿ\Ff']àTþ¢ç˜@ Ô<ì21ÄÔÄÆ0##çããã˜ý öüý ö!LÕ •@¹À À  -. „ ü<ì2ÄüìÄ91/îöîÖ<î20@X!P!`!////////OOOOOOOO________ŸŸŸŸŸŸŸŸ¿¿¿¿¿¿¿¿(]]3#32654&#! )#3Pëë‰ìùøíýö•ULxhgghyþ°þ°þk®®²þ¿þüþ¶êßÞè#ateþø§©þ÷etamXÿã'(õ@Y&'('%$%(('"#" ! "! 5((5(%('&%"! ##¡ ¡˜#£)'& !#(%" BB;)üìÔì99991ìÄôìî9990KSXí9í2ÉÉÉÉY"K°TK°T[X½)@))ÿÀ878Y@6f!/*76"?*O*oooooooooo]].#"32654&! 4!2''%'!%˜7l4u‚ru| £ujþ»þßþÞþ¹-.N$¾þ‹%3¼`ox#þÅç…y”¨«¡-\”ˆþÿ”þìþÈ8ç ÛwaÊtr`ÿÿÿìßk'<ÍuÿÿþFf'\œ¼‰Õ Œ@® ® - üì22Ôì99991/äÔìÔì0K° TK° T[K°T[K°T[K°T[X½ÿÀ@878Y@,0000PPPP    °°°°]]!!3 !32654&#=þþ1þÏþãþÕpzzpþþÕþüýëêýºþ]mcen¬þV^;@¡Ð¡Ð˜ÊÞ£B @ üì22ôì1ìääôäìæî0´O`]%!!>32#"&"32654&þšfJ´uÏ þöÏu´¤s{{ssyy¢ý´¾ý¨b]þ·þýþýþ·]7©ŸŸ©¨  ¨Ù Ûø·§¦ÔÄ1ôì0!!Ùúþøì)´Û /@   Ô<Ì291Ô<Ì290 '7´þN²¨þNþN¨²þN¨²²3þNþP¨°þP¨°²¨þN²{œß 7´¾  @ š …†… ÔäÄüä1ôìÔìî29035733!ÏáåâÌý9 4 1ýZmœð]@% ¸ ² º"@œˆÜÄÔÔì9991ôìüÄî9990KSXÉ9ÉY"!!56654&#"56632œrý_9=4I;>ŽTW£Kž´GeD¨™ 5P(2>-/ºoHyVZð(W@ #  ¸"²¼"#@#œ)ˆ&ˆ )ÜÄÄÔìÔì9991ôììüÄþÅÎ9990#"&'532654&##532654&#"56632P\fÆÉQ”DB€<_hkrJTbZNP4{FA—W§±Z`nQ®$%@;@=‰/3--¦piE`dÿã¨ð ›@     %¸²¾´œ ¸@˜œ    †…†…Ä2ÔÄäüäì2ÄÆ9991/æäîÄ2öîÖîî2î2990KSXÉÉííY"333##5!5#335733!9ïïø‰‰æþyþ+ߦßùôÍàæßÍýþ¼ýù›¢¢¨þ™ ýI 4 1ýZdÿãåð'¬@   %!   ¸$²$¾& !&²"œº@ ˜œ#ˆ%…#†… (ÄÔÄÔÄÄäþäî9991/æäîîöîÖîî2þÄ99990KSXÉ9ÉííY"%!!56654&#"56632#335733!qtý];>3J<>‹UX¡JŸ³Icûªß¦ßùôÍàæßÍý¨¨š 5N'2?-0»oH|Tþ• ýI 4 1ýZhÿã¨ð 6:Á@ : 9988 77: %.1* #! ¸´#!¸$²-*¼$!#µ91œ7˜¸@$$8'" :!'"4  †'ˆ4ˆ-";Ä2ÔÄÄÔìÔìî2ÄÆ9999991/Ä2îäö<îîþÄþÅÎî299990KSXÉÉííY"33##5!53#"&'532654&##532654&#"56632#3'ø‰‰æþy‡ïïü%]fÇÉQ”DB€<_hjsJTb[OO5zGA˜V§±Z-ߦßDýù›¢¢¨7þ¼#nQ®$%@;@=‰/3--¦piE`ûq ÿÿfÿãúk'* 1uÿÿ\þFF'JÚÝÿÿ¼=k', ÿduÿÿ“þo-ð'6ÝÝÿÿjþob{'VÝbÿÿfÿã\k'&fuÿÿXÿãuf'FÓÿÿfÿã\k'&fuÿÿXÿãLf'FàÓ\ÿã¨$Kº%@" ¡Ð¡ Иʣ    @"B;%üìô<Äü<Ä1/ìäôäìäîÝ<î20²O&]!5!5!3#!5#"322654&#"¦þºFhššþ˜J²uÏþö Ït³¢syysryy¼ÍrrÍû+¢c\II]üɨ  ¨¨  ¨o¼ãß·«ªÔÄ1ôì0!!otýŒßþÝÑ9‰·üì1ÔÌ0!!Ñhþ˜‰þ}ÿÙÿãð1r@;.*÷(÷1.®®œ˜!2*("%!) 2 +) )% 2ÔÄ2Ä2üÄÄ99999999991Ä2äôüÄþÄî2Ý<î2990%# '#73&&5467#736!2&&#"!!!!3267_Ïpþúþ™KÙXbºXMepÏ_Q¸c³-Vþ­YþÕ2¯~cµTR78õà Ãö87þËNO{vÃ$$ ÃzzOOÅ;ö@ ñÔüÔì1Ô<ì203#%3#Åëë‹ëëöööömîNö8µÔÄ1ÔÄ0K° TX½ÿÀ@878Y@ //]!#3þãÄöþø¤î\ø#Ã@  »@! $ €€ $ÔìÔìÀ999991Ô<ìÔì29990K° TX½$ÿÀ$$@878Y@\             ##+]]'&'&#"#465463232653#"&8- (‹kW%J';'%'‹kW&F#<2j‚'<9j²î“ö8µÔÄ1ÔÄ0K° TX½ÿÀ@878Y@ //]#ÍÆÄþãöþø‡îyöE@ ÔÄ91Ô<Ä90K° TX½ÿÀ@878Y@/// ]!#'#f4ß²ÇDzöþø¡¡‡îyöK@ ÔÄ91ÔÄ290K° TX½ÿÀ@878Y@//// ]373fß²ÇDzßþø°îPö S@  ÔìÔì1ÔÄ2Ì0K° TX½ÿÀ@878Y@///// / ]332673#"&°`LL`¬””¬ö=<<=‡‡w‰ö*·ñ‚Ôì1Ôì0K° TX½ÿÀ@878Y!!wþîöö  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßà>: ~ÿ1BSax~’ÇÝ©À & 0 : ¬!""""+"H"e%Êûÿÿ   0AR^x}’ÆØ©À  0 9 ¬!""""+"H"`%ÊûÿÿÿãÿõÿØÿ ÿ^ÿCÿhÿüöüÛà–à…àVßjÞqÞ_Úï¿8ôüúúü (B¬£„…½–熎‹©¤ŠÙƒ“ñò—ˆÃÝðžªóôõ¢­ÉÇ®bcdËeÈÊÏÌÍÎèfÒÐѯgï‘ÕÓÔhêì‰jikmln oqprsutvwéxzy{}|¸¡~€ëíºýþÿøÖùúãä×àÚÛÜßØÞ²³¶·Ä´µÅ‚‡«˜¨š™î¼¥’”•ÍfÉɦ+ô‹‘ Bú{sè°¨¤/)´Ù mRo Ñì‘b‘ç‘¢‘‰‘\‘ž‘‘‰‘}‘j3å3´Ù´Ù´Ù¤‡1 ¼ßf¤¼w¼w¼‘f²¼ú¼úÿ3¼¼ö¼²¼ÍfݼÍf)¼Óu ¼1 Ó=+'ËÿìÍ\¨°ì¨‹´Ï^fXº¬¾Xº\mX{'º\²¬¾¬¾ÿ¼R¬¾¬Vª²¬Xº¬º\ò¬ÃjÓ² 7dH)7¨\²ì²´Ù1 1 ßfw¼²¼Íf¼fXfXfXfXfXfX¾XmXmXmXmX¾¬¾ÿÕ¾ÿþ¾<²¬XXXXX² ² ² ² 5²‘®‘}'Á¬'mÅ´Ù®Í-ªÃ´Ù´Ù´Ù‘ã®Z;¾)L–'ÿÝá3ƒžƒu'7bXN¤¦´ÙVL‘´Ù“+ž+Á¢‘1 1 Íf VfÁXBÓB¼ Ó ´Ùô7ËÿìVþhJLžLÁî+î'3 Ñ “B“ …B1 w¼1 w¼w¼ú¼úÿëú)úÍfÍfÍf¼¼¼¾¬‡¤Å°wãÁV‡#ÿ¤øÿÛÓÃjÍ\¨\ì´!XËÿì7缺¬´Ù´{mZHdHdHh‘fº\ú¼ÓÃjßf¾Xßf¾Xº\Ro Ñ‘ÿÙÅm¤²‡‡°wÿ   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóõôöøùúûüýþÿ    sfthyphenperiodcenteredEuroc6459c6460c6461c6462c6463c6466c6467c6468%%%%NqÓ]ÜÆÞ 6©ÇÞô N{òU•å?uã<_НÐóOû ¡ K Á í G € © è E a ç > ‡ Ä*Ÿ2e¡àç:\u—¹ÍÚ#pÅ|¿è$†£ZŸí<~*‰ÑZ@!âIªÀ"dqjw„‘ž«¸ÅÒßìù   - : G T a n { ˆ • ¢ ¯ ¼ É Ö ã ð!!]!È""¨"Ú##†$.$Á%!%K%‹%Î&H''n'¥'Ô((Š(Ú)6){)ž)Ø*<*Ê++p,5,Ú-8-a-}-Î.B.½.ä//\/Œ/Œ/™/¦/³00¢0¹0Ð1161U1t1¨1ü2 2292É2ì33v3Ò44-4L4~5*575D5Q5^5k5x5…5’5Ÿ5¬5¹5Æ5Ó5à5í6 676Ê6ú7H7k7³7ï8'8W8†8Ô9-9:9G9T9a9„::Ç:Ô:á;O;ž;´;í<ª>·>Ä>Ñ>Þ>ë>ø?????–?­@4@T@AA@AuA­AðB‚ 7þÓ9ÿk:ÿ¤;ÿY<þÓ»þÓêþÓ$&$&$&$&$7ÿa$8ÿÁ$9ÿu$:ÿ¤$<ÿ<$Yÿ·$\ÿ·$hÿÁ$µÿD$·ÿD$ºÿ·$»ÿ<$Är$År$ÓÿÁ$ÔÿÁ$ÕÿÁ$êÿ<$ëÿ·%9ÿ­%:ÿ%<ÿ%»ÿ%êÿ&/&6&&µK&·K&ã&&ù&'&'<ÿk'»ÿk'ÄÿÜ'ÅÿÜ'êÿk)þ·)ÿÁ)þÓ)ÿ)ÿ)$ÿ)Dÿˆ)Hÿ­)Rÿ­)Uÿ})Xÿš)\ÿ)bÿ)iÿˆ)jÿˆ)kÿˆ)lÿˆ)mÿˆ)nÿˆ)pÿ­)qÿ­)rÿ­)sÿ­)yÿ­)zÿ­){ÿ­)|ÿ­)}ÿ­)~ÿš)ÿš)€ÿš)ÿš) ÿˆ)¡ÿ­)­ÿ)®ÿ)±ÿ­)·&)ºÿ)Äþ­)Åþ­)Çÿ)Éÿ)ëÿ*7ÿÜ*<ÿÓ*»ÿÓ*êÿÓ.ÿN.&ÿ¤.2ÿ¤.8ÿÜ.HÿÜ.RÿÜ.XÿÜ.\ÿ}.dÿ¤.gÿ¤.hÿÜ.pÿÜ.qÿÜ.rÿÜ.sÿÜ.yÿÜ.zÿÜ.{ÿÜ.|ÿÜ.}ÿÜ.~ÿÜ.ÿÜ.€ÿÜ.ÿÜ.‘ÿÉ.¡ÿÜ.¯ÿ¤.°ÿš.±ÿÜ.ºÿ}.Ä&.Å&.Ðÿ¤.Ñÿ¤.Òÿ¤.ÓÿÜ.ÔÿÜ.ÕÿÜ.ëÿ}.ûÿ¤.ýÿ¤/2ÿ·/7þ­/8ÿ·/9þæ/:ÿa/<þÁ/\ÿu/gÿ·/hÿ·/‘ÿ·/¯ÿ·/°ÿ·/µþ/·þ)/ºÿu/»þÁ/Ðÿ·/Ñÿ·/Òÿ·/Óÿ·/Ôÿ·/Õÿ·/êþÁ/ëÿu2ÿÓ2&2ÿÓ2$ÿÉ29ÿÉ2;ÿ·2<ÿ·2bÿÉ2­ÿÉ2®ÿÉ2»ÿ·2ÇÿÉ2ÉÿÉ2êÿ·3þˆ3ÿÜ3þˆ3$ÿD3DÿÉ3VÿÜ3\&3bÿD3iÿÉ3jÿÉ3kÿÉ3lÿÉ3mÿÉ3nÿÉ3 ÿÉ3­ÿD3®ÿD3µ&3·93º&3Äþa3Åþa3ÇÿD3ÉÿD3äÿÜ3ë&3úÿÜ4&5&5&57ÿ¤5<ÿ5\ÿ¤5ºÿ¤5»ÿ5êÿ5ëÿ¤66ÿ¤6ãÿ¤6ùÿ¤7þÜ7þÓ7þÉ7ÿ7ÿ7$ÿa77/7Dþø7Fþð7Hþð7Rþð7Uÿ7Vþð7Xÿ7Zÿ7\ÿ 7bÿa7iþø7jþø7kþø7lþø7mþø7nþø7oþð7pþð7qþð7rþð7sþð7yþð7zþð7{þð7|þð7}þð7~ÿ7ÿ7€ÿ7ÿ7 ÿ<7¡ÿa7­ÿa7®ÿa7±ÿa7ºÿ 7Äþø7Åþø7Çÿa7Éÿa7äþð7ëÿ 7úþð7üþð7þþð8$ÿÁ8bÿÁ8­ÿÁ8®ÿÁ8ÇÿÁ8ÉÿÁ9þø9ÿk9þø9ÿ¤9ÿ¤9$ÿu92ÿÜ9Dÿ9Hÿ9LÿÜ9Rÿ9Xÿ·9bÿu9gÿÜ9iÿ9jÿ9kÿ9lÿ9mÿ9nÿ9pÿ9qÿ9rÿ9sÿ9yÿ9zÿ9{ÿ9|ÿ9}ÿ9~ÿ·9ÿ·9€ÿ·9ÿ·9‘ÿÜ9 ÿ9¡ÿ9­ÿu9®ÿu9¯ÿÜ9°ÿÜ9±ÿ9Äÿ9ÅÿD9Çÿu9Éÿu9ÐÿÜ9ÑÿÜ9ÒÿÜ:ÿY:ÿ¤:ÿY:ÿÁ:ÿÁ:$ÿ¤:Dÿ·:Hÿ·:Rÿ·:UÿÜ:bÿ¤:iÿ·:jÿ·:kÿ·:lÿ·:mÿ·:nÿ·:pÿ·:qÿ·:rÿ·:sÿ·:yÿ·:zÿ·:{ÿ·:|ÿ·:}ÿ·: ÿ·:¡ÿ·:­ÿ¤:®ÿ¤:±ÿ·:Çÿ¤:Éÿ¤;ÿY;&ÿ·;2ÿ·;HÿÉ;dÿ·;gÿ·;pÿÉ;qÿÉ;rÿÉ;sÿÉ;‘ÿ·;¯ÿ·;°ÿ·;Ä&;Å&;Ðÿ·;Ñÿ·;Òÿ·;ûÿ·;ýÿ·<þ­<þÓ<þ­<ÿN<ÿN<$ÿ<<&ÿ·<2ÿ·<DÿD<HÿD<RÿD<Xÿk<bÿ<<dÿ·<gÿ·<iÿD<jÿD<kÿD<lÿD<mÿD<nÿD<pÿD<qÿD<rÿD<sÿD<yÿD<zÿD<{ÿD<|ÿD<}ÿD<~ÿk<ÿk<€ÿk<ÿk<‘ÿÜ< ÿD<¡ÿD<­ÿ<<®ÿ<<¯ÿ·<°ÿ¤<±ÿD<Äþˆ<ÅþÓ<Çÿ<<Éÿ<<Ðÿ·<Ñÿ·<Òÿ·<ûÿ·<ýÿ·=ÿÜD\ÿÁDºÿÁDëÿÁIÿIÿÜIÿIµVI·NHÿÉNRÿÉNpÿÉNqÿÉNrÿÉNsÿÉNyÿÉNzÿÉN{ÿÉN|ÿÉN}ÿÉN¡ÿÓN±ÿÉUþÓUþÜUµ&U·VYÿYYÿYZÿ}Zÿ}\ÿa\ÿDb&b&b&b&b7ÿab8ÿÁb9ÿub:ÿ¤b<ÿ<bYÿ·b\ÿ·bhÿÁbµÿDb·ÿDbºÿ·b»ÿ<bÄrbÅrbÓÿÁbÔÿÁbÕÿÁbêÿ<bëÿ·d/d6&dµKd·Kdã&dù&gÿÓg&gÿÓg$ÿÉg9ÿÉg;ÿ·g<ÿ·gbÿÉg­ÿÉg®ÿÉg»ÿ·gÇÿÉgÉÿÉgêÿ·h$ÿÁhbÿÁh­ÿÁh®ÿÁhÇÿÁhÉÿÁi\ÿÁiºÿÁiëÿÁj\ÿÁjºÿÁjëÿÁk\ÿÁkºÿÁkëÿÁl\ÿÁlºÿÁlëÿÁm\ÿÁmºÿÁmëÿÁn\ÿÁnºÿÁnëÿÁÿÜ‘ÿÓ‘&‘ÿÓ‘$ÿÜ‘9ÿÜ‘;ÿ·‘<ÿÜ‘bÿÜ‘­ÿÜ‘®ÿÜ‘»ÿÜ‘ÇÿÜ‘ÉÿÜ‘êÿÜ­&­&­&­&­7ÿa­8ÿÁ­9ÿu­:ÿ¤­<ÿ<­Yÿ·­\ÿ·­hÿÁ­µÿD­·ÿD­ºÿ·­»ÿ<­Är­År­ÓÿÁ­ÔÿÁ­ÕÿÁ­êÿ<­ëÿ·®&®&®&®&®7ÿa®8ÿÁ®9ÿu®:ÿ¤®<ÿ<®Yÿ·®\ÿ·®hÿÁ®µÿD®·ÿD®ºÿ·®»ÿ<®Är®År®ÓÿÁ®ÔÿÁ®ÕÿÁ®êÿ<®ëÿ·¯ÿÓ¯&¯ÿÓ¯$ÿɯ9ÿɯ;ÿ·¯<ÿ·¯bÿɯ­ÿɯ®ÿɯ»ÿ·¯ÇÿɯÉÿɯêÿ·´$þø´-ÿ¤´<&´bþø´þÓ´­þø´®þø´»&´Çþø´Éþø´ê&¶$ÿ¶-ÿ¤¶9&¶<K¶bÿ¶þø¶­ÿ¶®ÿ¶»K¶Çÿ¶Éÿ¶êKºÿaºÿD»þ­»þÓ»þ­»ÿN»ÿN»$ÿ<»&ÿ·»2ÿ·»DÿD»HÿD»RÿD»Xÿk»bÿ<»dÿ·»gÿ·»iÿD»jÿD»kÿD»lÿD»mÿD»nÿD»pÿD»qÿD»rÿD»sÿD»yÿD»zÿD»{ÿD»|ÿD»}ÿD»~ÿk»ÿk»€ÿk»ÿk»‘ÿÜ» ÿD»¡ÿD»­ÿ<»®ÿ<»¯ÿ·»°ÿ¤»±ÿD»Äþˆ»ÅþÓ»Çÿ<»Éÿ<»Ðÿ·»Ñÿ·»Òÿ·»ûÿ·»ýÿ·Ä7þaÄ9þæÄ:ÿ)Ä<þšÄ»þšÄêþšÅ7þaÅ9þæÅ:ÿ)Å<þšÅ»þšÅêþšÇ&Ç&Ç&Ç&Ç7ÿaÇ8ÿÁÇ9ÿuÇ:ÿ¤Ç<ÿ<ÇYÿ·Ç\ÿ·ÇhÿÁǵÿDÇ·ÿDǺÿ·Ç»ÿ<ÇÄrÇÅrÇÓÿÁÇÔÿÁÇÕÿÁÇêÿ<Çëÿ·É&É&É&É&É7ÿaÉ8ÿÁÉ9ÿuÉ:ÿ¤É<ÿ<ÉYÿ·É\ÿ·ÉhÿÁɵÿDÉ·ÿDɺÿ·É»ÿ<ÉÄrÉÅrÉÓÿÁÉÔÿÁÉÕÿÁÉêÿ<Éëÿ·ÐÿÓÐ&ÐÿÓÐ$ÿÉÐ9ÿÉÐ;ÿ·Ð<ÿ·ÐbÿÉЭÿÉЮÿÉлÿ·ÐÇÿÉÐÉÿÉÐêÿ·ÑÿÓÑ&ÑÿÓÑ$ÿÉÑ9ÿÉÑ;ÿ·Ñ<ÿ·ÑbÿÉÑ­ÿÉÑ®ÿÉÑ»ÿ·ÑÇÿÉÑÉÿÉÑêÿ·ÒÿÓÒ&ÒÿÓÒ$ÿÉÒ9ÿÉÒ;ÿ·Ò<ÿ·ÒbÿÉÒ­ÿÉÒ®ÿÉÒ»ÿ·ÒÇÿÉÒÉÿÉÒêÿ·Ó$ÿÁÓbÿÁÓ­ÿÁÓ®ÿÁÓÇÿÁÓÉÿÁÔ$ÿÁÔbÿÁÔ­ÿÁÔ®ÿÁÔÇÿÁÔÉÿÁÕ$ÿÁÕbÿÁÕ­ÿÁÕ®ÿÁÕÇÿÁÕÉÿÁá2ÿ·á7þ­á8ÿ·á9þæá:ÿaá<þÁá\ÿuágÿ·áhÿ·á‘ÿ·á¯ÿ·á°ÿ·áµþˆá·þ­áºÿuá»þÁáÐÿ·áÑÿ·áÒÿ·áÓÿ·áÔÿ·áÕÿ·áêþÁáëÿuã6ÿ¤ããÿ¤ãùÿ¤åÿÜè&è<ÿkè»ÿkèÄÿÜèÅÿÜèêÿkêþ­êþÓêþ­êÿNêÿNê$ÿ<ê&ÿ·ê2ÿ·êDÿDêHÿDêRÿDêXÿkêbÿ<êdÿ·êgÿ·êiÿDêjÿDêkÿDêlÿDêmÿDênÿDêpÿDêqÿDêrÿDêsÿDêyÿDêzÿDê{ÿDê|ÿDê}ÿDê~ÿkêÿkê€ÿkêÿkê‘ÿÜê ÿDê¡ÿDê­ÿ<ê®ÿ<ê¯ÿ·ê°ÿ¤ê±ÿDêÄþˆêÅþÓêÇÿ<êÉÿ<êÐÿ·êÑÿ·êÒÿ·êûÿ·êýÿ·ëÿaëÿDö7ÿÜö<ÿÓö»ÿÓöêÿÓù6ÿ¤ùãÿ¤ùùÿ¤û/û6&ûµKû·Kûã&ûù&ý/ý6&ýµKý·Kýã&ýù& NE@í§mþ …þhþh V •¼GÌþBGÌSf €¯ JBits ûþšmãB³É`#cÕVeraSansBdÿÿÿÿ6ÿÿþ628B00@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               !                        !        #                     #        $                       $        %                       %        '                   '       (             !   (       ÿÿÿð_<õº¹Ìº¼–²þhþ Vmmapserver-6.4.1/tests/polygon.shp0000644002461700001440000000035412261257215016663 0ustar tbonfortusers' vèпBwIœI@Ð?BwIœÝI@@пBwIœI@Ð?BwIœÝI@пBwIœI@пBwIœÝI@Ð?BwIœÝI@Ð?BwIœI@пBwIœI@mapserver-6.4.1/tests/home.png0000644002461700001440000000236412261257215016121 0ustar tbonfortusers‰PNG  IHDR!"æ®@óPLTEÿÿÿ‚Zzzz¶–Rüä´ž>ήnf* ¶Zæ†F222ÚÒ¾Úz:&&&¾¾½jZ:.¢~BÖÆª"ÚÚÚîîâ^^]žz;`>bbbâÆœÒÒÒBBB šz:»šZšvBʾ¦üöç²ZzjJâÊœþÞž†>r: ºj:ŠjN¼¦‚«RÒ²~êâÒnnn†f&zb>òÒ–V2–zNžžžZJ6ò֪¦b‚rRîʒξš¨†EÖ²{ ‹‹Š~b>FFF>>>Þ¾ƒŠfN:"ÖºŽjFñÞ¾«f⊦Z2îÎ’òÞ†n>F:(žv6¾žrÜδîîîLLLž…^úêÌvvvþúò¶šV’Jv. ³’OjZBʦo–r2Òr6öÖšxdF¢†^ŽzZ.*ÆÆÆšzN¶~f¾ž[úÚšÞÒ¾:rrrNB.>6%žBJ=)'rLöÞ´úîÒ–^6´ ‚âââjjj…9 ºªŽòÎ–æÆŽòêÞ÷ò鯢j:."ZN7Ò²‚Z6Ö¶zþþþ‰vW*"¶^RF2ªN~~~ª–jÖËºêÆŽâ¾ŠæææîÔªòâÆ š‚^µ–iŽj*°ŽL®b.öҖʪj...ySƪzaR;Ò®wªŠZVVVâÖ²šþÚžöڨ¢^êÊ’þþòúòÞÑËɉb'Ú¶~úâºîÚ¾Ú¾ŠÞº‚Ú~>:⾆Ϊs***¢F†F¬Ž^ ÞÞÞþþö úÖš²V÷îÛæÂŽÂžff2 êêêʺšæÊžB"®–vŠ7 îΞ޺†úÞª.& ®Všr/¦nþúꮊF²’f•m*úÚžöÖ¢ž~>š†`dV<ûæÂ"""žv2Ú¶‚¢‚JæÂŠr^B¦–2 òòòšb6»¢sVJ6Ò®~þþúf. fffn^BöæÆ¶šnƦvöÒšþòÚ€^"¦‚>ÖÖÖ¾ª†òÚ¬¾/ñ‚tRNS@æØfbKGDˆH pHYs..BÖtIMEÔ,Q‚m˜mIDATxœ½Ï¿KaÇñçŽôð‡S$ªÉáì Áÿ@Q —F!÷hðqˆlhî°åÀ!'WGáð:—þˆ²ZºUèyžÓûñ\]CÐg¹áûº7wüûî~£&T#Á0†bµlD‡„b»Ã3 R“à Њ$A% ŒfùÉ,Tð€C Ž(°0ˆÛ-Oj¼@ÛsBÊž¸©–‚ 3k ¤$Sn‰‹¶ ,ã‡%!¯õ;ÔÌ]r”ˆ¸¤·w¥‘Óê¾nÈ$AHÏv–jD±ë56¤dg?5wEW!„ØÊ;õ1¦Ï”¿Áˆ­BŸ¿Œƒ‚5(y£…ÎxµZÉ8CØGbY–M3ØêI™0wLó2(pH’ý®ªº®ó” ®è ‘¥_S‘ó VY7,Ëj¤±vºÿ4Y‹tãý¬’š €_½àˆEåD _ÙžïsùÇå7ïz„¨ëöæØá¸§£½IEND®B`‚mapserver-6.4.1/tests/polygon.shx0000644002461700001440000000015412261257215016671 0ustar tbonfortusers' 6èпBwIœI@Ð?BwIœÝI@2@mapserver-6.4.1/tests/point.shp0000644002461700001440000000020012261257215016313 0ustar tbonfortusers' @èBwIœ½I@BwIœ½I@ BwIœ½I@mapserver-6.4.1/tests/test.map0000644002461700001440000000716012261257216016141 0ustar tbonfortusersMAP NAME "Testing" EXTENT -0.5 50.977222 0.5 51.977222 #IMAGETYPE JPEG #IMAGETYPE PNG24 IMAGETYPE PNG IMAGECOLOR 255 255 255 STATUS ON SIZE 200 200 FONTSET "fonts.txt" SYMBOLSET "symbols.txt" SCALEBAR STATUS EMBED POSTLABELCACHE TRUE STYLE 0 UNITS METERS SIZE 150 3 POSITION LR TRANSPARENT TRUE COLOR 0 0 0 IMAGECOLOR 242 255 195 BACKGROUNDCOLOR 255 255 255 LABEL TYPE BITMAP SIZE TINY COLOR 0 0 0 POSITION UR BUFFER 10 END END LEGEND IMAGECOLOR 255 255 255 END WEB METADATA "key1" "value1" "key2" "value2" "key3" "value3" "key4" "value4" "ows_enable_request" "*" END END PROJECTION "init=epsg:4326" END LAYER NAME "RASTER" TYPE RASTER PROJECTION "init=epsg:4326" END DATA "raster.tif" PROCESSING "BANDS=1" STATUS ON # DEFAULT END LAYER NAME "POLYGON" TYPE POLYGON PROJECTION "init=epsg:4326" END STATUS ON # DEFAULT DATA "polygon" METADATA "key1" "value1" "key2" "value2" "key3" "value3" "key4" "value4" END CLASSITEM "FNAME" CLASS NAME "0" METADATA "key1" "value1" "key2" "value2" "key3" "value3" "key4" "value4" END STYLE COLOR 255 153 102 OUTLINECOLOR 0 0 204 #SYMBOL 1 #SIZE 2 END END CLASS NAME "1" EXPRESSION "foo" STYLE COLOR 255 153 102 OUTLINECOLOR 0 0 204 SYMBOL 1 SIZE 2 END END END LAYER NAME "LINE" TYPE LINE PROJECTION "init=epsg:4326" END #TRANSPARENCY 1 STATUS ON # DEFAULT DATA "line" CLASSITEM "FNAME" CLASS NAME "0" STYLE COLOR 0 153 0 #SYMBOL 1 #SIZE 3 WIDTH 3 END END CLASS NAME "1" EXPRESSION "foo" STYLE COLOR 0 153 0 SYMBOL 1 SIZE 3 END END END LAYER NAME "POINT" EXTENT -0.5 51.0 0.5 52.0 TYPE POINT PROJECTION "init=epsg:4326" END STATUS OFF # DEFAULT DATA "point" CLASSITEM "FNAME" LABELITEM "FNAME" CLASS NAME "0" STYLE COLOR 0 0 0 SYMBOL 1 SIZE 13 END STYLE COLOR 204 204 204 SYMBOL 1 SIZE 7 END LABEL TYPE TRUETYPE FONT "Vera" SIZE 10 COLOR 0 0 0 END TEMPLATE "point.html" END CLASS NAME "1" EXPRESSION "foo" STYLE COLOR 0 0 0 SYMBOL 1 SIZE 13 END END END LAYER NAME "INLINE" TYPE POINT PROJECTION "init=epsg:4326" END STATUS OFF # DEFAULT FEATURE POINTS -0.2 51.5 END END CLASS NAME "0" STYLE COLOR 0 0 0 SYMBOL 1 SIZE 3 END END END LAYER NAME "INLINE-PIXMAP-RGBA" TYPE POINT TRANSPARENCY ALPHA DEBUG ON PROJECTION "init=epsg:4326" END STATUS OFF FEATURE POINTS 0.2 51.7 END END CLASS NAME "0" STYLE SYMBOL 'xmarks-png' END LABEL COLOR 0 0 0 END END END LAYER NAME "INLINE-PIXMAP-PCT" TYPE ANNOTATION DEBUG ON TRANSPARENCY ALPHA PROJECTION "init=epsg:4326" END STATUS OFF # DEFAULT FEATURE POINTS 0.2 51.2 END END CLASS NAME "0" STYLE SYMBOL 'home-png' END TEXT "." LABEL COLOR 0 0 0 END END END END mapserver-6.4.1/tests/point.dbf0000644002461700001440000000016612261257215016267 0ustar tbonfortusers_aFIDN FNAMEC 1A Point mapserver-6.4.1/tests/fonts.txt0000644002461700001440000000006212261257215016346 0ustar tbonfortusersVera ./vera/Vera.ttf VeraBd ./vera/VeraBd.ttf mapserver-6.4.1/tests/README0000644002461700001440000000100312261257215015330 0ustar tbonfortusersMapServer Test Data =================== This is a self-contained lightweight dataset that is used as a test fixture for MapServer unit tests. It might also be used for regression testing or by users that want to verify their build by executing:: $ ./shp2img -m tests/test.map -o test.png Currently (Oct/2004) only the Python mapscript unit tests and the Java mapscript "make test" target use these data. For information on the Python MapScript unit tests see ../mapscript/python/tests/TESTING.TXT mapserver-6.4.1/tests/raster.tif0000644002461700001440000006616612261257215016501 0ustar tbonfortusersII*Fe############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################6#########################################################################################################################################################qq6@##############################################################################################################################################################6r6##############################################################################################################################################################866###6############################################################################################################################################################=##################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################c=##################s6vv;66:?#####################################################################################################################################-k1q0:ccE100+,ss8sa1s8;v6;8666##################################################################################################################s?#################1-Zq@=as1sv6a+:l,6;6sss1:?#################################################################################################################qq6#################,\Z^k=@8E@6@@6kk;?ac:?;vvv66###############################################################################################################l+l6AA#################Zaa(*:?E+cqqql5C?*,:=:8#################################################################################################################qr66@EE#################Zg\X8Iacqs@E;66o6? ###############################################################################################################:sss6:AFC################uqZZ,V(ONCF G >E6l+q?################################################################################################################q?8s8v666################aaZ(69GW88;? GG6q15##################################################################################################################16+0=s1=s#################V+q166FICC? 65CuI####################################################################################################################o1k6G65 ##################^6C-kv:8,8;6 @5A??######################################################################################################################569I####################:ZZcs444s@1vE######################################################################################################################q6####################+X__X@cV(q0=q@s@=#########################################################################################################################################56saV(c1@sZ> 6:K EE6########################################################################################################################################k((&\^6A>6lqFmmL?Cb%%E##################################################################################################################66#############0#######(Z(qlF 9IIEEAf7m@6;#########00001+cc+11:1:s,al:8s8;#################################################################################:?6#############*=######c(l<6:E6Z,8vl::==6:??6####0c(&sqqq=0(0lv66686qr66;;6################################################################################666#########6###lA######(q6<######lEW9 -Zass1v;WE:c10(__&(sq+ar@G6+qq010=:118;;666??:?@#################################################################################qls###########krq;6####A[ougV(rac= 80@86s(__(lqv6:1q:1\Xq@0=E818??666;;?C##################################################################################(+#############s(0@:####*6v(,(VZag5NG8116N())s00+N?q\c:+\X8K6N6@E@@:6###################################################################################*1##############lr6?\X8,\c\VZqFC66 q_(=0=Ns(__q=c\, NE6;v;666E####################################################################################5###################5*o6X+g((o>W>IF\)))c? Eqdiidx qsEGCAE6666 ########################################################################################################q5oZZ6q(u>I66+&luggCFu6@lsI[%C1q_RAm[[%8=,c444=s1=18#############################################################################################################(6o-oAC6?6 -l<9K,sq_s0XX58+&4D&qEG?=@1s@E##############################################################################################################Zc(\1CF Irc&(a*6100ccqFlC(sG((CWANI%CE#############################################################################################################ol-:5qFI()4q0+aV666F%ffI %GL[%IIW%FA###############################################################################################################lo< oGN6l\6FFA>I[GF ILLIffm@@:###########################################################################################################grrqs0cc+,oW5,cZ->?FIIIA66a0q@IGF%E@6############################################################################################################,65or66ur@I%CV\+agal1lcc11(&Ebs8::  ;8vv66@###########################################################################################################ggv;1o6C6F%mIo!*FG9oW6V(086:6mcq0=:EGF:6qq66CE##############################################################################################################16;vo6?IEg*n66(kG@((oCCA?acsGNE6ql6AIII#################################################################################################################k6:6gr###laag566F>g\l>9AEA>6qI[f7m[@u1AC?66@?#################################################################################################################1CFo#####a\\sv15((kC-5 uk?%A681sq66sv6s1###########################################################################################################################((5Ag1?1-o5WI<GG80qsqq0:+0:666ss8#########################################################################################################################oo16,(-*o5bC9F[[[[[Ira0:66r6 ###########################################################################################################################:8g1511FElVqFG>FIF6sv@>>9F gs;r1@>GI6s111111ssl######++c&s#####################################################################################################################oEK85 I ###s6FA>>Aur66vll10s44q=0c(((__sq==########################################################################################################k16g###### F@###>###!6Gvsssslsv61u6q+++((q==0&&qcc\+; EEC@##################################################################################################65*a?#######u6:#######neCrss0c(0:8qurrrqqg6Es(&s=66E@6####################################################################################################*o########1###########>555q,l8:00sqruu1u@6r15ECIIFE@6666############################################################################################################Z?###(;########555661rv10@=+a+lals+qcsF?CC6vs11svv8:#########################################################################################################(###?#########rru1o1ugl::1ls+\1lXq0?;6@6qlc&4D=vv::########################################################################################################9##### ########qq,gu11*g??llsgg;a\E6;6vl+csD6??#######################################################################################################5###############a\((c+\,5C(+:s:A-66 ?s110(((\1Fb66;######################################################################################################G?#############6s\\\cc((1? ?9<68 L?F@6;10000((cqAII;6 #############################################################################s8####################################g,c(aqu1r6GEA?FW ? F:6ql?66qg6 CC@886 ###########################################################################l10:ss############l#####################a\c\c1sA 9LL%W?GF::A6*6AIIACA56 ###################################################################?;,sss65oq; ###5#####66ur+(c###################lg*>916?K 9C ;6GA6>5CGo(6ECAC>AE @@#################################################################qE1+;6E5o###gZsE?66qqgV\=K#################+86?<NK?9FC @C>:65 I F9? @;8;@:6666;;#################################################################;Gv6E@?665FA6###l(rK?qgsrl-E################g6@6@C9?G:II68>AAFFF>5>6@ 6::AC666################################################################C6?;8ss;6,++as8:ZaEE6*669< C#############q6 IFA@E>GI<?:A16K####:66u5rZ\:+l880=s6;6666;;################################################################666;;6@q\+s++0q(lN 615@5665s:############6?AF>@@6?IAC66#######666sssqq(ss(ssssss@1ss8?;vs###############################################################:?@66((6qa+c1?EN6r5?6k*u>CK#############@#####6;6####A5:#########l+c00++lgnns1+(qq=@@@=:6;,s###############################################################E6?vs8sg15k5 IEG6666616FICE##################6###############,+c&44q0869An+(c1:::GG @vg6##############################################################G6 6sv?sr:1u?>FFC666666u5qs##################################,,a\Vc@=:?;6< A*s @EN @666?E #############################################################(uC?6sv?v65C:66?666666qg(N?6;;66##############################,a\X+1-K?==:s< GN @66?CC?6############################################################q?A>1610:;656q66 6666666u1 s6@@66##############################aX&=sVlEqs@01kAI  @????@66s+c##########################################################A@E?>96*sK;666::E 666666v66u66v666##############################o--o80r u6811l((,:@@@=?6666sa\Xc=1:######################################################:q:656u6sss? 666sv6666qqgq?G 666#################################loGe>G 96k*5 666gZa65ACE6q6##################################################6g1E?6>:15A>FF 6qslc0:6666u15NE66#################&q################AG?A>55-(*1>E;??G6661lFIIIFFE#################################################ElX0 s66u5AAA:6vsll,,??8?6,+c(@####################kA#################F5CA>??115l^k5uv8v0@== E?6659 FFA>>?6################################################o\qe?66u6@66rqsss6u>?;?s((,6###################:I###################5>####6ku5-?GG<5 A56GGGE6655>A@6666qsvv6;###############################################-9%>A@6666666u6666AAFF:s6 [###############################################ug\&&\6A<<I ;6665:::66qllv6@?@?##############################################6GIC6666666vvsssq66?CCCAF####################################################rZV\+8 I II ?;;6666:566rg6ECC??##############################################6666666666qsvsvsqv E??@@?#####################################################r(l6IIC66665A:@6;6666666656AEE@??6##############################################66666q6666u::666u@ 66666####################################################6uol FAuqvac:66C??@;6;66666655>666#############################################6666ru@6665::566AFE6sl1:8##################################################66659 6*qqZl?8866666666666:5u6666#############################################66666:?66@6qsq66@??6666@@#################################################6666rkg+c\++g?@@E ?@@?66@6666666::5:E66666###########################################6666666666rr666@6666:A?;#################################################66qqq(\+lqr5A>6 @66666666666666556;666666##########################################66666666svsq666@66666666sv8#################################################6qqqq1-IIog=@00:?666v6;66666666rq66v666###########################################6666666qsv6666666666666666@###############################################66qq665 III 6--g=s@E6;666666666666u6vs866###########################################v66666q6666666666666666666@??##############################################66uu6A:569llq::= ?666;;666666ss66qs668###########################################;666666::6666666666666666@@@6##############################################665::666666r*-n-EEKKG666;;66v6666666u6666866########################################??5666666uu6??66666666666;;;6########################6ss##################666666666666qq,\\ZoAEKG;;66666qv;66666655666;6;;#######################################?6656666665?666s666s+(s44:########################5::6#############a###6666svs666rqq((+5EECA G6s6666666666665566666;#######################################6666666sss666666qsv6s,\X&_4D#########################:::6,dd @\0qq0vk,==:?66qqs;66rrk(^*6 @ :6G?vs;;666666666666:56666######################################6666qa(q08666666uu66sa(ZXcETT###########################q\1.K(+qs@s*l@@E;6qq66qqqg*9<?6v6 66;;;66666666666655:???@6#####################################666qaXc:?;vv6;65u66,a\VWN##########################XX(</((,v =(\= ?6qq66qg,qr599?AAECC:66@@66666666666::??#######################################s6qq*oFC666;?66ur6qZVV6WWN##########################((II ?q(l68\g@vqr66s,,q66656FFIFC:AC?@6666666666666666#########################################q6sq1C?u666??6uk65-l6>A??6?66666666vsls666666666666#######qs;66qvvq66#######################,6@@6666v66u6qqGGq6:5ku>FCE###############################!^E?>8+a%E66666665::?56666666qvvvv66666q666666666666666#####6q66vv6666?66#####################8E56666;6:51 qv661:56E################################-s*6F>FEC?66666666ss6666qs6;6666qqvs186666q66666@6666666666666qr66v66666666666###################GN@6666666@5:kaq::>:F#################################-k6AGG9A E?8+1:ss66sqsv666sqq6?;66655u666q,lv?666666666666666666u6666;66666666666#################W6qsqq6@?E@:>6k^sO5:?EE#################################-9I>g*6??66g+0q@=sls6@66qqq66;;66665>C?6qqq6?@66666666666666666666666666666666666#################?qq66:?C?@666ql8glWE6:6 #################################6o,(_(l@C@681,qqv?s+s?66uu66666qv66666sqqCA?666666666666666666666666666666666666#################@6k6?rv?vssslq6@16@66@##################################1(V( E6l1cc016FIEr,:G6661r6666r66666qqv66666666666666666666666666666666666666#################=6u:@6*6E:6vs6@C5>C@6@?###################################g^nl>G\c1+v;?A?11 6661u666;;65?@666qq66;;66666666666666666666666666666666666666#################N 6:6ac?>>>AE6u6;6###################################+((l*8Eq:C56 G6@> E666u5:@666666rqq66@?66666666666666666666666666666666666666#################;qs0+X&D:s6AAC::C:56###################################slVV(6GG@Aur EE??6u6666665>AA@66666qqq66??6666666666666666666vvvvv6666666666666##################,l86-lb@666666####A?6#################################(u6gV*5A5kr NE@6qqv;6666666666666sqq66666666666666v66666s666vvv6666666666666##################GF L[%###############################################sv6ug(k I6uo>W?66655A?6;;6666666666q,s66666666666666666666666666666666666666666###################66?:66A#############################################qq6:66l+q1I v88;>IC:=?6@@6:A:u66666qls6s,q66666@@66666666666666vvv6666666666666@?666####################65u6###########################################1ssq66rgq6CIFokrCCE?g4P ;6666665?@6666sa+86sq66@::??666666s666666qssvv6666666666??666######################F###########################################6qg,s6;6666u5FI>6,(svs1;V^@b6666666666q,l,6;666?:?6666666vvs866q666666666666666666666####################################################################656IIFAAAAFA6g\XXl:+cq@\9%eN@:6vs6666q,,66@666?@@6666666666qsvv;66:666666??666666666####################################################################>>>:?AAA:6q6q(k6GGI9 :18NC:6qs6EE:rq,,666?6??C?@6666666qssq66?@@66666666666?@66666666######################################################################?:::######rr656 G95uAGIFGb6qq6?@g,,q66???C66666666q,ss66???6666666666666666666##########################################################################6:>#######:A5F>o((sGEIIG%erq6AC6q(,66????6666666666qll66?C??6666666666666666666#####################################################################################666:###-9GGAFFIC5>F6s,gq6?66vvvssvvv66q,6AAACC?66666@:::66666?@666##############################################################################################GIFFFF####?6qq6qg6@@?66qsvvlssss88vr5CAAAA?::?@66::::??66##################################################################################################>FFAAC######ssq66rr@@@66gqs6666666?6:C?6666666666666666666?@666#####################################################################################################:?#######gsv66r5?@66qgq6666666???666666666666666svslsssss6vvv6#############################################################################################################,as8sv66?@66rk6666666;66v666666666666s,lll11ssls86ss11sv##########################################################################################################6k16vv86;6sllqr666666?66v68vvs6666vlsl,q6q66666?@6r6vs11ss66vv6##################################################################################################6556>6666sllv66?::?CAAA:u66s666666s,l66:>AA?66:>>:666vssss8#################################################################################6qgZass:=@#####:6666u55>>66vs666??::?@66555666v6665>?@6666666666666:>>A:u66;#################################################################################5>>6:666;665?@6666uuu6r66>:666666vv66666666:::>##########################6##########################################################qq6559 ACF??666666q66>>5u6666??:5uuu6u:E@666556:AA>:666666666:########################6666#####################################################a###8sqsv6u51:EAFC6s+1::svs6666666u5?CCC?666@:>>5>C6666;6vv6666;655:666666666#################66666666666#####################################################1666;5u66u55AE??:rqq6?6ssslsvvvlv6:AAACu6@@@66::5>FF>::@66666r6;;6q66?A6#################88vv666666666666#####################################################5::66;sq6666AC??5156CC6666qsvv666@???:u6@@666665:>>AF##########:u6####################666s1s1s6666666svv#####################################################s6556sc&s=86;@A:511?E###A656??ACC@@6666###66vv666#########################################66rrvss88666666666####################################################=:6655g4D@:?;?66###########FA6666v########ss8v##########################################66qqqs;;?666666##################################################Za=:?6u*!^KE@############################################################################66qqq6;6686666666##################################################-6?G?6uonnAN?#############################################################################5:55:666v::86v666##############################################,lvr6 II@@A6>?666888ssvv##############################################gq6;FFAC?59?LW ;;#############################################################################666u5:::566;6ss88############################################squ5?EC>######## IF6##############################################################################6u666666666666666;############################################6:>A##############::###############################################################################6uu666666666666666##########################################l? ?###################################################################################################66r666666666666666######################################6q1: ####################################################################################################vvs666q6666665666;6####################################A#####>E####################################################################################################sssv6u5::66666:?66##############################################################################################################################################sssvv86666:>>:?::6############################################################################################################################################vllvv66666v666:>A:::##########################################################################################################################################r66qsvsvvv88svv;666666666####################################################################################################################################lssssvsq66rqs8vsv886;;vv6s66666#################################################################################################################################vvssssvsvsqvvuuq66s6;;6;vs66666666##############################################################################################################################ss66v666vvvv6qs66u16666666;v666666666#############################################################################################6;####6;#######################666666666:66666666;65>??66666;666;6666#############################################################################################:6666?E######################>:>>?A>>>::666::@66>:??66666666666##############################################################################################u6?CA?#######################:>AC>>??:A>>>556?::66;656??AA666666##############################################################################################:@@6666######################vs6;6qvss665556@:55@6666666:@66?################################################################################################6666666#####################sls1lsqss8s66u5>6666A:566888666??666#################################################################################################6666666666q6666vv########v6u66vsv666v888s>55666@65:>:66;;666666vs##################################################################################################666666slllsvvvv666666u1qs6qqqqv6666666s88s6556666q666:A?@@666666þ£Ÿ 5fNf@Zfffnf(@vf/home/sean/projects/ms_43/mapserver/tests/raster.tifÈ(ˆQÀ(À(½HH¯¯§§¥¥££¡¡——••‘‘……{{yywwuussqqkkcc[[UUQQOOKKúúGGøøööôôððììêêèè5533ää11ââààÚÚÖÖÔÔÌÌÆÆÄÄ ¼¼¶¶´´²²°°®®¬¬ªª¨¨¦¦¢¢  ˜˜””ŽŽŒŒŠŠˆˆ„„€€vvrrppffbb``\\ZZRRýýHHFFDDõõBBóó@@íí::ëëééççãã00áá..ÝÝÛÛ(($$ÕÕ""ÓÓÏÏÍÍËËÉÉÇÇÅÅÃÃÁÁ½½»»¹¹µµÖ”¼`¼`ˆB˜Øîþ_ªˆB˜PˆB˜¾©,`ˆ–—´÷D´÷DˆB˜îþÙ²,ˆB˜ˆ–—pö_Î^: `xœ—´÷D´÷DˆB˜8îþ5—:ˆB˜xœ—¸îþ@H_à¸îþ³ãˆB˜0œ—ÀãUçJç€Aç²€;çAç;çPz˜¯¯§§¥¥££¡¡——••‘‘……{{yywwuussqqkkcc[[UUQQOOKKúúGGøøööôôððììêêèè5533ää11ââààÚÚÖÖÔÔÌÌÆÆÄÄ ¼¼¶¶´´²²°°®®¬¬ªª¨¨¦¦¢¢  ˜˜””ŽŽŒŒŠŠˆˆ„„€€vvrrppffbb``\\ZZRRýýHHFFDDõõBBóó@@íí::ëëééççãã00áá..ÝÝÛÛ(($$ÕÕ""ÓÓÏÏÍÍËËÉÉÇÇÅÅÃÃÁÁ½½»»¹¹µµ€w°X£¨XÀ¯—ØîþÈâ¢Ð £¨X±¥À¯—(îþ¼`»_2¶P@¡T´±¥ÈâPü¢PÌgPð ÷&±¥àï_( ÷ü_°€w°¢hîþ;¥€w°¢¨X¢´”xîþÄöR¢¨X¸îþÝ„Rü_°€w°h ¢¨îþ;¥€w°h ¢¨X¯¯§§¥¥££¡¡——••‘‘……{{yywwuussqqkkcc[[UUQQOOKKúúGGøøööôôððììêêèè––5533ää11ââààÚÚÖÖÔÔÌÌÆÆÄÄ ¼¼¶¶´´²²°°®®¬¬ªª¨¨¦¦¢¢  ˜˜””ŽŽŒŒŠŠˆˆ„„€€vvrrppffbb``\\ZZRRýýHHFFDDõõBBóó@@íí::ëëééççãã00áá..ÝÝÛÛ(($$ÕÕ""ÓÓÏÏÍÍËËÉÉÇÇÅÅÃÃÁÁ½½»»¹¹µµ îþ˜ îþ`”;Ø îþ¼`¼`x…—ø îþx…— îþ˜ îþL îþÁX¼`L „¼`È îþ¶½x…— îþ˜ îþˆB˜H îþÁXˆB˜p îþ¼`¤Ö”0œ—¼`àÖ”¼`ˆB˜ˆ îþJ܈B˜P¼` ¼`¼` îþ˜ îþ]äˆB˜¼`È îþVƒmapserver-6.4.1/tests/line.shp0000644002461700001440000000027412261257215016124 0ustar tbonfortusers' ^èÀ¿BwIœ­I@À?BwIœ­I@(À¿BwIœ­I@À?BwIœ­I@À¿BwIœ­I@À?BwIœ­I@mapserver-6.4.1/tests/point.shx0000644002461700001440000000015412261257215016333 0ustar tbonfortusers' 6èBwIœ½I@BwIœ½I@2 mapserver-6.4.1/tests/xmarks.png0000644002461700001440000000443112261257215016473 0ustar tbonfortusers‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ84³95¦IDATxÚí™ÛoÛØÆ?I”¨›mù'v’Ý\Ým·—ûRèßÝ×¢@[-Ò´ÝMëd['Žcù.Û²$S¢¤¾üƘ%$[v·%@És¾¹}3gNFqÄQ•´ iMÒ†¤û’*’2’II-IÜ‹ëkgg’Ny·Ö“Ñ´2wž‘T–ôXÒsIO%Í>+)\€1€G’rN€×SIÇ’>H:”Ô ëÉà“GA?ã\—T“H*® ðן›vøÝå›=IÛ’Ž*¾É™[/â"Ÿq®Iš“4#)¸¾¤KI'¸E `}Ìp°`îûI;’rq5‚)€ýZÒÏÐx‘‰sLÜAËgL¼-éaÜ*@Ь³V³ÄïÂU¹Ï‚a¢Á5À øô¢¤/$}%iaòh«ècIoq·h½çÀç™+Çï@ç%-IZÁ¢æbKÀº oM%ÌReUXæ ÷e Ñî.€_Kz/©5ASñ"h {½ŠÒªÌ{‰"FqtÃz’\€Ÿ¼ç,:·9—ô?Iÿø¤ä6ô7ÆÚ`³Ì›Á5÷$½“ô_I§é9‚”FJ˜u ˜yC˜"&°Þ0`CR7¬'ÃÉ'a=éÅQ°åÜî…ÀÒ’Ô„Ñú“\(‡éf½‚4q€¯oã:}|;ç"w"‰£`ÇCKÁÒ’ÔŒ£ é­àÈc?ƒ¿“\Ø]h³’.ã(x'©9mòq/¸y:XùEVÀ“çÎs”6V€>¸ˆžaº}9FóK°Æ<“W$}ÿO{T$=Ô±÷xaÔàçXáĬà(~™Á-)rq-:–šA‹%I8 :ÓdO‚ö©¤/:@YI¯PD,U”9ƒ&dÿJG\f5ªüªì‡õdGÁŸ/83Ïðß)Yôò·™øo(mG)ò;I¿'«?Àæ]ð–˜Ëˆ£ Ø J^g.yÊhÓ2f€VN¬ôÑ”´‰†:Œ3ƒ[<“4UGA6Ž‚9I¿ôÎ_¦¬ÝcÌ6Š„pˆ²º¸YœkÔfW1Ptš8w¸°'PÞ,Ú ]-è»8 úhì)„ۘ߷þß>Á¿}~xOÙ^rÞa‰õCà,PD qI[󼫑V$}ƒvM€GT°ËÌ#ž`ÉWŒµÖ“^jž32ñŠ PÜF{c 2üj ‘ޤóIŒB@Ÿ’‘\ý2Çùœ`.ò¿%¥«ýÿ-é\Æå‘°ž â(Ø¥ œu.¾ ©â]¨Š»ôŒÝ”=w)-jL`Bd]­•wlsJ2Ü”ôw ÁÓÊ èEç)¡¤ÙÀQhÎ-.z¸Ð4%B›ÂnCÒϤâƳ1-A½æ|)i+¬'ÓÌ‘uuPÉ‘OÉÌQp“Ù‚ürŠ„”áû²KûVÿ‡n•eKÆþþBÒ{(yšÃ˜*Ûˆ38þ͸«Õ)7¯Àí_C“U1‘ïbŽ[Á nQv˜bmq“øD6Lu †hµb\>üôø¤ßr_ã{cŽM·RÛ#¨—%ý ÉßB€ %ÄPÒÈh³‰Væx)5ù?}Ìø×”öc8}"(b©Ï«Pj_R6Ž‚ë\ eeÝ’Ô„He]€5™|Ȥó’)Ò«¶ ²é—pü¬c‹]hñ¥¤o%ýQÒß … U–©ŸIZ™diÀ¦Ô¼ ྤA–@m[ ÃÍ#øN1w# mÞ=øà¿•ô&¬'—“²6VþoÚ®”\&/¤JðB–yÏhº+i¤Òuƒ]t5úÚi;z\vÜc9¹=¡ôöG!r€¹õð { X“¡‚«æx·Å\Ià44Œ£à+,»{‰`m`_Ò_ðyñ{š’WŠã(Ø#.\i}*ÕҜŬ«}:’úé é±€Xr‹ [­=c¢*ÇÆG´Púq4ˆ£Šk \¸ŽCÉ-ì«`kañ#+ƒ1%ò1BÔ\MSƵ²ÜÄQpBÿ®M-ëŸæmec¡ýšk²¬ ø+ÊG[]ÒˆÉîzÁ\‘`;ð+¨[ZÁJ˜xB{ó>ìdÞ 'Àñº*ol‘ÿ…Qæ¾$)¤%ؽk_tB×â¹fÁ š?¢‰ $(POLYGON) clean: dropdb -U $(USER) $(DBNAME) testdb: sql createdb -U $(USER) $(DBNAME) createlang -U $(USER) plpgsql $(DBNAME) psql -U $(USER) -d $(DBNAME) -c "CREATE SCHEMA postgis" psql -U $(USER) -d $(DBNAME) -f $(POSTGIS)/lwpostgis.sql psql -U $(USER) -d $(DBNAME) -f $(POSTGIS)/spatial_ref_sys.sql psql -U $(USER) -d $(DBNAME) -f $(POLYGON) psql -U $(USER) -d $(DBNAME) -c "CREATE VIEW polygon_v AS SELECT * FROM postgis.polygon" mapserver-6.4.1/tests/test.png0000644002461700001440000002551012261257215016146 0ustar tbonfortusers‰PNG  IHDRÈÈU= _ IDATxœí{|ÕùðŸ33»;{Í&Ù\ È%È- ´XÛz)Ú(©Õh­‚¥¾­$á×Vß×^l«mµöõmm‹¿öU Ѫ¥­µAi°¾/XªˆR  „„Üv7{™ÝÝ™óþ1aØìN6³ÙÝdVæûG>'³gΜ9ó<ç9ç97ôÚk¯ÁYôz½×ë‚ Ä+ùùù022 ”DR¥×ë ‰ˆÅ@8€¼¼<1G±%¬Vk6óå÷û¥Ün· ‰‘ļ‹`Á+ÍLQEÿÒ˃qLZR*£ù$(((}²¥ÿ8ÂøÈµ @»ûÙ±i¥öŽ3ýË?sî¼>³ü™{Ù‚ûþ>&_G‡Ã!þ/æhÍš5ÐÜ [ 6À-»hnm-ÿÜ÷Ñšõ€ŠM mÚ´I&­¾²ù¢Q<â!‹‹`gÙuö“‡<³—È¿ã¹b3Ò°%.@|ë)ô£¿r{÷qúÙöŽwbJÌ‘N§€H$'D‰$I\² nÿáÐöí‰H×Ãá0Úºu«”–Á`ÓºÅ÷fò`{Qmì¿áp˜((((((°Z­V«U¯×‹¸WCͨ±9î­õc±Z­Èû¥&ˆÜÖÖ–xu¼ïËÛÕëâ®ÄçKöå‹Åb±ˆ7z½ÞLê6ëBQ²†Ÿsñþ-Þ¹³ì:1 ê² ãä+é;~÷ˆeô߸|íÞ½  ÷÷÷K¿I¢‹1ŸÏ­­­‹/v:‡¯¹æZ1Z4ßl´þ àñx8Ž3 ‡Cª³Àf³ÓùÖÜRÏ?|¦û—«…››có•rÙÿøñÖRŠ=qâD\B Õ…¢ù±ìc³“ˆõÖߊ8åÍh}?ú¨³FE²Œ ‚h†††Ä+MMM---4Mƒ\Þ‘dkÅßÔgk%s áp8//OÊQb™hh3/ÉÖJj•I¬íÄpÑÇûhÏ G›û/ZŸVlB0‘­óƳ'>3P:¨ØûòéK¾,“–BN\¹®àØ´ßM†ƒ=ŸþR\+ck×ôí€5ñVV ›ø>ù­‡`ûƒ= O’±µI*hîÀêâ‹@ˆD?ô;–^&ÿŽcÊ(Áú‹ª¹‘s,¿ö¿Ðsͽq‚ÎÖÊ6Ø¡êÂÇá¬0Jw³µƒA¼ªÄÐÂX[+¦EÅ}~½^>@ÍcéÕD+{šcu[ ËË„X)Cú¶V‰¡9[Ÿ¯Q¥ç;Ž œ­„†­©”¿Â„œ³µ ÈRbha¬­k„ñmíøævÙcûäó%ÙZQF$[+ºcÑЀ¨¿mmm<ð€x%Š‚uÎÖz<l­¨’‰†®s·¶wvÔT1èÃXzç}»<w¶È¼£(_~¿_”ÏñìU,¢¶AVmíhZV«Õf³Ùl6š¦išk꺺:Ñ>õžÅçóù|¾«®º*‡ÃẺºØ´Pl¿VBzG©cMºˆh‰EÚc…d²¸2ûñ¥711ß_lÀØŠ«­ÇC¶é “­ØÎ¶„dÃeÛ²H¯—\È’šýO£ëLå;­Q³ýôÊk"&ZOÙμð3lÁŒ$7Ž‘-÷YÎýƒã, ó4çgÆk6ò:}ÔhJ‡I]á‰N¯¼Ö~ºÓÞÝ‘ä^¥¥õµÐèS@àyÁlaØ  Téç?}D£ÄÒ%äÂÙ]ãÀ²+*öýÝSµx¼Û‰£1$þ\p€‰ú¤qn‡O¢5ù“ÝüÊÛ¯^·æÝ+ýèî§¹ƒ‡P4¢÷¹t!&É[É—ÖxíÔ” ¿ü áøëÂþ7Ñ¢•пˆâ2¨®.ÞÿÿàÄ·&¹w´i)ç̉Ea;E b{-¹ÂR±",ú_`¼JHI“GY³ÆÖˆÒãTZËËûp‘ýˆ_ØÔvݲʻ¾°Dô<]qÅo¾ù&÷‡ L8šg÷Iµ$¤R&|Ž×;ûÄÀhS»¹Þxò’~D%ö'7?¢ôfŸï|6î'°’ßU{’× Ä6;Ä´£&ÿÉô419”Ôn…˜êJÊ~ì;e ±Í7L ¤Ëh/CDôëALý!u:Ò©N¿{dôÝÞzë­Wtçí«k:íŸeæz¶ ºãÆ1ý>™lÅŠ¼ÔZûTp¶[%"•°ò¶ˆþ•‡ªìÐÕÛý ûÙ:Ï«vM¬}*ù-S‘­I0Fcû9"±"ŸNk8V±D’7ùÇdK¦›Ð ƒ˜b‹ëÜIâ%ç\‰ûuçÎJ³•*­­­b ¾¾¶l䦦&1ÐÒÒk×®€íÛ·ÃØ"¯««kkkß-®VWÚ}•-6©ûšÙ¾+¨Ö&jÙJ…sýØVlbg?VŸ;û²>YvöUZZ*ÍVf\#‰~ìt³•~ÉAö‚·ÿ A{Bã(óV.šÖlqÑÊ};Œî~×Ü‹óV\„ K¿kqöõ-¿:ù­çZ±ŽšDRîþó|ÙAVš3çÅþ2óÀkLQ…¯¢:ÉÝÙyÚ;dð»û–_]tôýÒƒ£-Ͳ÷v–½·s`Ñgí§;“ßž­lYN2%UÐÑjÛ™®Â£ûµ>R|t¿sþJÁ`äh³-iÎÉÖúõâ-ñcÞÉáz:ˆÙUDŸ xÚ[ùêãÈb&W¡ì¶¥mm¾™s#ƒIn'’8·à¬ `‚) ‰d±àå_…†-|ç!H‘?ûQ9K(Y)&K†ƒQÚœ,[©A  ²2Üù¡Àóxd„üÞ“Ÿ©%«ÀjÛ>°éâõt²Û%ÿ–l ],ªººÒT?"ðGáp˜X°€Ðú§S7üóÙÃŇß9½òZq˜YùÒã›Iñ#ù›7Ð5…ŽCBí÷F=—MÍO8>zóÌœ‹’ä ²]Ë“×Þ&Þ)¼¸Y(šÂã?¹ÜÊž®YÍÑæäJþ#ÆUž“ûˆòÏklhmíåNJÉC 2ͬRhØ’÷dÃhü ÞI)ðÃØÒŠ~¼õÖyÿˆ²¤^Z©kâx3Ý”?…!åm:±}ð§7-™(f’4¥Ÿyš'ÔDÔØ¼ÿ~·Û}õÕWÀmŸž»íß]xKƒ\̆¶¶ Ÿ¨¸ÞJÐD„ÐÀ¯¿Vúý?cŒ1Z±Úrc̓Ûöï®Ñ[`\MÌP¶§¥HÉ~Î>Júd™ùˆÊA »w&Œ¦VMLþ³ÂNð$z’WbDІ .»Ì÷Ž@Âpô“gk’‘lh&šI@bïRþÕj%o`lu7б|9Π&ÆU§±ýSÉ·›š˜î½÷^øß•)ÜrnpEY„Á•tªÓ{ŽÛÅ1š¦_zé¥Ã‡·>÷ܱØÒÈ Ä’¢ÒjkØ çFr]„±>÷¸1Ží²,kwvÍŸ¿à Ÿ˜uMüžctÒJáÞ'î«uü¢Ú©ä®sn7q½Hâ˜O¬ÿMjþ˶œ¤É£¸á{ŽŽ™?þçSWÚª~¸«û—«5ŒUXz'¼²~&Øív…wMEuz`éíÝÌo1H\V Ë9›;|¢ð#fsš˜8j15³£v0‘û^¥6Q¥Ù:÷å—GŒ?Ì™Î'L4Ì9A30y¶¤aNqKSSÓæÍ›¥hR&N#Q(£“ÿˆöMÄAW q„êêêâJ:ùÑWY_TVye 8‘؉ÇÅÍ,*UDu¢V P²µˆ¬W3ñbrçg,ÒØ¶„¬Æ)OP!™u h’•Za¥€VX) ?/C–Ä1å Z"[fd¢GF˜ OMö@шýt§ýôÇ´ÏÏëéP~iÄ’€Š Pá &ȰµÀ[6/d/AÊڀ㑓…E†ëÀI³»ßË&9Y‚“’ ü®ÁïÛþ’JÖæ°õŸÐ…ü® .âLc D8d85Û3òúŽÚÎt :ÃPõª¸hÊÉ=ɲõµœ [ìýK.’Ö^líïªx¯ÍS±Ð={)XO–vì1¹ú’rÎ_1Z|Õ‚Îò`ÉÇ{Ï,½ë&Sf²°Ö¯¿0ƒ©Ç†¢@±®ô5ïª÷~UvöZ©™Xx›cçç¬ÿ²“¯ D€³¿é»ìE÷ê>Oôþ3¥³©cë?îè:0¼pÕ$MÉN?RèKKÔ8¼¥9c˸äB$,|ï.XrõϯXN¼ñ¨ø“ðoÇók…×ÑðàÓ¨ ºöBmýW/½¦ùï¡ÆsÃѼžæ)ŸtêLƬ±“˜\aepX6 ‚{Dè9IÌ™MX,üаpè0ATì@sf“%% °,>ÙÃad2–ýþ‡ÜÎð|éö¼CÞò긙’…FiúãSIDA>jÜËj…£G…+¿~ð±d ùä»ÔÓ‘%%£qhš|d7ñƒ?m¬Ðž·öwÑžA^odó&éƒÎ½ Èe— •Õøðë›Û(»ÌûU `VÅþÀb’;áè: ÷»B3Ý•F­“´×)¨á„m‚©QÃX„p;‡±{Âa0X-Dq Iâ`æ®?/ßðõ¡(mqV-å—¦ÓÈ‚de³‚ ßyZ ·ÿ·¿Ïÿ_|D#ðÖÓpå7qÀ‡¼Üæùü.9·’+rR !ôøÔ•Ðþøâ-gÞkoùèTd&À¸“éRâÜ<ÀXbçJL¸-ƒÓ3Hò™‡IHt:æž5L994V (Ý3@ qÖ56ËNæœ8O£‰Lîö„ÔÍUB­á¹ræ !TS^øáigì1ýû÷‹qÎj\:¡ä)Ç2Çtªá‡?¹QvG¶'NÄN’B‰ÑRÚ¾-dQ 'Íù¨†“à† -î€Q5ÌÔè¡f S@j˜YNÂWBZj(/ÞSØ7œ„5”ÝM&vú»Dâ¡©VCÔŒxÀ¨e*0¥™OG ã$+q탈SÃt$‹’ó)ëºJL1áÁ@j;êž|g„XÇÛ5k˜òÓ$''Y\½29î9nß¼ùÞ_ß{QI£T¡d©±Q:‰À½§,ËpwܱáÞSô«¯¾Ê0Ì‘#G2Û7³™D캉DgXÜ6euu¥Ì™Bî¾[fße°X,mmm,Ë&®ÎI$¶+*‘¨^™,¬$$Δü˜83–ÅÑüó»o©[=`™{Ñé®î~y®b<Ü“l/]ò«_=œ$……•ó>xšân«b:^êôt9>»iÓ¦† M·¬°C•…ñ° ÷Õ:x™9è©#?™-vå“„´zF"vÿ; Ùn‰ckʇ¤â—Oe_/×ÑË,.·\_mg˜}«×ÏçSó›=‹eOS-#}霗¬;vDœÝ Q¢¼¼¼³³ó7íl‡“Ù±#3ûûÊ·àeWIdV²ryÉ’]g’ˆl×aº¦€ÊvEIgV½Ö‚O­°R`z*øä‹Õd[[ɇ-’ß -)LNZ.…«å@®Ö—]¦#ЕÙÆDì²F‰ÌV Ó †J–ABÌN¶²Ä­±L'ug™ðFM²R@éJVÙ§Êx©_âJV•/cͦ„VX) V h…•Za¥€VX) ³ú^áÒ{Ù‹ —Þƒ\CAåKïA“¬”Ð +´ÂJ­°R@+¬Ð +”n‚¡pêD:¨| Ð$+%r~ÌC=…ÇöÓ>&HŽ6GŒL5Zý%•éï"’Û…E»û O29{u!“kµ„­QÚLÁEtòÓÞaߌ9LÉlž6¥ù¸\-,2ÄØOwtw肾¨ÑÂÏò”ÏWñ:ÁEžC|Ôðš‡OÓÞa{Ïa‚ç½eóƒ1‡æ^aaA0 X†z,C§.1ç UÚ7sž¸{¤Q´;Qkã(/8yÐ2tÊä<ÍŒþ²yéAÀpéWЪ/¡YÄ/_%¾õ”ÝórÁ§n€¥_6ø]€Á82HEÂHày¢©º‰ä^ßÍ[Š&øñþ7Çk¾†{ÑÛ[ó¹~ ¡7%%°pDXuísêØ°öÒOnlŽ©¡ˆàr §{A=9Àl!™×x0þGe=ð¼í̱¼¾cQ£ÅSQÍ̘ÜssL ÅQè@ÿõ{¸ä+Øå j᪻d#Ÿ$þë`<™×wL ˆ`ÁŒ½dÒï§T §Àhá `Cøý—pÏ1<2„ûúP(@Çœ),D£àsçÞgvöòLQ…ÓQ©OÃeªT •Ö”©¡ˆ `ðzð°3 p<Íœ‰Œ4` €ó˜ `?sÈ8˜âJWÅB¬Ó§3’“j(ˆ¦f"?ýl;jü-†y—bÇáT0c¥P¾J8ÙƒËVÂÅuœÉêž½d¸jÉä¶Ž%÷¬a„5.úœP½W/’‚Sû °Àl‚•0ga¯¹(]FöÈa5TÈö¢ÚØU³õ¦J6rˆ lßž©÷£åHv+ÉŒÏ4›.d_$ÙW“ÙzSá¾›‰)Þâ{SI>¦˜85Tˆlaij˜9梙^45”GSÃtÑÔ02¹ç_l£TÜ>3p3²ï&ì,»nâHÊÈha­Y0f;ÛÔ¶ªÙ7¼¥!5LgQtÙRCŒqrÑöµù¨×»]°´cpò#h§˜l©á„Üõ—w_9Ôsì·ˆÿ~ÔëZ<³€ÚøDuuu~~þÃ?¼aÆÎÎNhÿÉ¿ùçGO®¿lõ#;½õÒeåòÇ\GÕpz¬á®¹èw¯ú=B{O ^òË—~zµñ  Èh4Š‘mÿîúó¾c{¾…jüÆ85}T¿&gÓkE…Zýˆü›¬X±b¼{§Q§M “ Zk¨ÆFiª64yÀúöÛ™z?­QšjTÃÌòvõºL%¥F5Ìp@SÃiASÃÈè~ðjPº‰Ô0që=…[vƒ¦†)‘Éýà?ßùì„·ð0ÁÎi)AÂÄ­ù85LG²¦ÚRðp°!# ¼7¹k qÆ ˜”‘Àg~ªÕpêÉa5œvk˜2gX(°lÙ²Õ«W———á/íû÷¿ïõú²¡†9?§Ζ”®©©€åË—www»2,é2§£(<NG™ͲÇöÕÖÖÆyÐÞÞîñxº»:]¿¾íyÛÉSPx4 dV²PcfÆc”3þÚºººÄÓ!jjjÚÛÛ«æV~Ûc[&(,åd²°Æ;eJá|ÔIºóû‡Žã(Jæ-Ú÷ïc9¨®®^·nݳÏf¦–ÛM‡;ðÓZçó‰’õÌ“›·]otu‹®Ób1¯[—ginÔ,®©u>ϲ¬tåÙmÞv½JË-‹Øÿ»ÍËМ9_XP³¸¦Îó¢X^›6mzºV†u0PZe12SÛÈì̦ð8';wGù¡; W:$?Î À P³¸:^¼ã­ÑB)ûÎvÙJQT×ýŸŠ‚ mðšó’U}ÿ.1P³¸æw«ØWÖÏkaMÓ4Mƒ\Ý?ir¾°ZZw,þſİÙ2z2ã>j±Xì´ÌSéó…[_ø«$_"÷Ý÷?išÞò§oz~@¸¹ù¡§Z3ò ·²ÂƒÂ ½:+㬽¹~Ûõö¶Nf[ûBkVúŸœÂš> j8eÈ …GМ^åGÐv Ý”¡V h…•Za¥€VX)p~¹k×®$¿NˆLa)ï +Ú?]ØUŽVcid…O®Ÿ ° èB~3B{´ßMDÀL˜ y=Íë˜ #„‰IŠ×ÓœÁ¥ÍœÁ$žf¯4ÁšnxÞàw™Ü&WíséØxÄE¢<ñ:=ÇEÈpPŒŽÎÎU'xN<©XЖ|6Ï1Ù8Ú’þ±A¬é€ç©pÐ2Ømî1úÜ,‚€$¯3D­ùaK>›WÄŒ˜Òc‚, A@/Æ$¸¨Ž ,CFú€Çàw›‡{xÚ´³öâˆÙÎéi”é9’)¡ Öаº WðêBŒÉÝO{‡Éhñ:C0¿$d/ÎdmÎ`šX,xžb3b4¼D$¤gF¨ßÀŒ„ìÅa›ƒµ9ÄSë§M°¦aifDÏŒ.è3¼Ť.¢7FLÖ`aY(¿„µ”^”'E‡½$gÎãÌyG…Áï2¹Î˜]ˆÑ}d„%£À›W<]²¥T°:”£p2»ÚNAŸ(1¼&÷íÔ±‚‹pS4¿4lÎã F6¯ˆŠe¬'0¥åEVEVŒ‹Rá ˜×X›#j´šFhÏÁç$¸ˆqd <Â8d/™ÙÒj¬¬C…ƒæáÓ–¡ST8$dÄlgóŠÂ¶ÂˆÉ1ÙH.jî1 ‘ÁsÖ“þ’*¦¸2Yœ‹Z†{,ýd4,g0 g2E³G9§§ïÁELî~2FóK§^¶4ÁÊ2\Ô82`vöê^„1&La›c¤r‘`0Š¿ó”.X0C𚘊 "(6  úEa{qlJX ̈e°Û2tÊèuRl°5Ù‚3"æ<}еØCöÒÛ >' |N‚ç0B¡Â™SüÞš`e]ȯ 1d$I…-v6ÏÁë ±­(Μ皳,l-°ö70#Æc`<–¡S¾²ùLq¥@R´Ïir˜‡{Œ^§Á;DFãG³=P83XX¶9¢´ADl…Joï9lð»Éh˜dëÀI^gˆØR;2M4ÁÊ.ú£ ù@ ôb‹*lÎKlBa=í/ÃL¶3]æáÓºßÄ2&× HÒ\„ ùul€à¢€§§Ã–ü £Ü_:‡)ž1ÙâäLVoù‚‚î‚‹Ñ0ù­'=z#O›¦ìÅU*Xë×_ˆñrhn„5*Øe²á›ãö=øÃgaÉÕ€øÏkÄ?"fÍKr—ð»õ¸î+ø½×ñ¿ÛÀ1¢œ:Ž +IAh–^†fÍCÇÞF7AÙâ™;á«?BèƒÄ-†JÌ/¡ÂA2$xŽà9}ÀšJÁ:zô¨’xßpîÐÝ›˜h¸(` àŒßÝ~>ƒû0ñ>ö¹A€ç€ç€$Q~hˆ¸Qù\tÁb8³æIÛãÁÁë ˆ‹`‚H %Ý^&ã M›6)‰7Å‚UWWŠ·4gö‰SÀ àõà¡a èõ¨ 9ݘq=!Á^/¸\ØãÁ ‘úe IDAT(‚£ ÙmÈ@cž. €F¯S:”—‡¬V0› ’@ ‰5–Þ碽Ãf×"”žµ9Bù%SÙ„WñìÑF4lÉݱñ hÚ 6¬þ|êzˆFay=þÜ!•â7?„«.Ã]]²cƒ"Xx úÌõ¨¼œ¸çIâç/¡ùóˆGv¿|•£/6ÂÊ Æs>‡ç­ÆƒƒÂW~ aÏ#§Â!"+*¤xÒ}"3‚JÛXŸÌ6”gƒÒY˜ ð`/D#02"°!‚6 Æ€OÃâ2=l6ôù/¡ ÁëAbÙ¥$ $ ¶|¡¸.½N…C¯bûÜàrÁ;ÿXnÆdˆŽB|ÔàsÒžA}ÐXˆB¼Þ8•ﭙ¬#BA<4Œ½^ˆD˜M¨°ÙóA§‡`;1ÃÑ„ ì`Ë‹³•cRãy…°Ë Á @:ÝÕ[nüÑãtÄdÃzH6hð»,C=Æ‘2Âò:}ÄZè›1'PX6•Sk4S˜õA âmCw=‰òípù:X^Á®ú^tx<°áqôó6jÉbêѽä¯_' Ä·žJ’ ±ñIÂbA?~ý`+QR‚w$T1ÙJD8dð»h¯“ ù1Bs^¨`&ã( [ §x–f §¢´B(-…¥—@ïqÜ¡6ˆ½½èÝ@q™àõ‚ßKX-æÂl³ òá‚E}Që@¨ ßè>cvÑ}ÀÓÖZÀæ9X›ƒ7Nõ±œ™7…ñ#|’La,‚€!Æî`ü˜ ƒØ´"I  ÈhBy60›A§'EóDPcÃË-f÷óÈ€!àAÀÉÓ¦ Õ,( ¦a 4S8Å¢©™¸óO¨¤}o+jø-r8àšFøÔõÀ²xÎ¥BñE‘£xö•üÊÛ„`Pøæã²é¾¶I¸þ§ÂÈ_óÕ[ ^-?ø¦£û ÑçAtú½Ø=s¾»¢šÍ+Rû´ B”V@i…ðNúÌ5Ø5Ç߯v¸!Àíï>öhy[ìpô¼üÀÑ£ðÊ6à9|ø0¼ø³pò$ì)Ó»Às“@ê‚yÅ¡ü’%Ú§Àk¦P-<>vâ`¢IEŒõ˜ó¨+Ÿ Hd2Ö=yÃÝk¶Gisâ(ät­NSqÕ°eÚû¦2@l|„Í èößA4ü|õA³ð—ŸÀM?xñ¸ùˆFð  ï^ú?ÐðØk¿=ÚPtÎ;*T,Xç%€6m“fTäçËF³ÁÂå6+ØòyU~DÍæ<¨±¡µµg¼_§Í*”Ýø¾à82´U_éùf 'hü I9*ßšP! w0T±»A#—A[·nUOy¥ð´Åä‚ë­ó4S¨ä¦0ãä~¥fnT‰ŠK#—ÑLaΣNSHM×Üó‰»ÁZ¯Pq¯p*} Ÿ¥FßZr¤iñ”4/F×x¶úŒ $?ýö<'­Ã³GV¤ßýëÞM»½qwÝ d|ÔëªyðoL˜“®ïß¿_ ¬X±Bºˆ·4$Ö±!ïú§ÞÜûÃë3ïq]L1í¨¸ÆÊŽ)DÍðî=_þ̯^Q2ââüô&+REíÛ·odd䡇zï½÷ìvûÕW_ý /:[µÿäÆšÿs‹l]Ã>8|ÿWþì…ùIÑdž•}étq~õ ûÄÀ%sJ”ßõÜsÏy½Þ«®ºêÎ;ïܽ{÷®]»b+­8ŽýâÑD^ü‹Vé"Æø|³›ç‘)ä\~Ï6O0b76?‡ü¡õ«æ?}ûå±ÑDSÈýaI ©BÙ¾}{EEE¬T‰÷‡ gÜÒ]R"xKƒÈì»Ä¢NS¨â+ÓŽDjã«–…¢\¿7Øÿë¯õ{ƒ†îEÍñ‘¨O@\5sà 7Œi`ýUŒ|.аE4‹Ð°eÙÏ_\¿jjl•ÑóÆAªâ6V¦ÁCs£Ì•±ßfYyá¨Ä47ÆÇIÄF–¹ þô?®øÓÞ£ÒOÙ@…GÌG¦ð“ jlؽ;0ݹˆç<2…ŸØ€*Q±`iä2š)Ìy4S˜"*14ê¨ –F.3m¦0yù²ËÌš)THrSh±(Úµa…óz½J¢©¸ÆR‰¡Q@•|¤¨(U0dq¨gzÑLaΣ™ÂQ‰¡Q@•¨X°4rôÚk¯)‰§|j¼ÂJ5y½|9ÖL¡B22mFùén O‰Wq¥C£þ€*Q±`iä2š)ÌyÔi UìÇj8¯×V–9Nõ9EVåb  ÖùʲeËêêênºåë÷Þ{ïž={Žt~lxào£B–;h¦PE,{l_]]˲±išÞ³gÃ0 Ãôöö¹-î.ušB´{÷n%ñ •žÏ©pm’_ëêJGÏ+TUš‚À¢E‹êêê€ãέgŒ…¦é}ûöy<`Æ9ÐëòÄÛúà¹çŽMXàɉF£ c*¬b4S8Í,Z´¨¶¶¶¶¶v<‘aY¶¦¦F/°Ì­^´hÑ@o·K­î•ÖX“ C[TŽ¢|}©ÏçS3‘–––$k_ÇÃãñìÚõšÃQ,ËtŸ|ìOM:"¯±4?Öt²víÚ]Û-e»’WWNçð3›ÿàØÿüýUÞ[ttoGoïiGyŃ>¸nݺlç6%4S8ÍX,–ÛÊÙöŽç{éªË*Š’ÿ",ËnþÏß^·Ü”/^)¨*a†n ÓÃñVøú׿ÎqܳÏ>;…ÙM°TAÍ⚀òŽç{éªvzMÓâuŽãX–}ù¥í_. ü±Îw—ÅN[ì¥+ç²÷½î¹³*¤ 4ÁRgÅëÅnªªÃ²âñÇ—~º¾vf€aC G9æÚç®°T×äÍ[þѽW9JG½6f m0¨èkR~¿_I¼@@é#±Kconn = (PGconn *) msConnPoolRequest( layer ); 2) In msPOSTGISLayerOpen(): if msConnPoolRequest() returned NULL then manually open a connection to the database (ie. PQconnectcb()) and then register this handle with the pool API by calling msmsConnPoolRegister(). layerinfo->conn = PQconnectdb( layer->connection ); if (PQstatus(layerinfo->conn) == CONNECTION_BAD) else msConnPoolRegister( layer, layerinfo->conn, msPOSTGISCloseConnection ); 3) Implement a callback function (msPOSTGISCloseConnection) that the connection pooling API can call when it wants to close the connection. static void msPOSTGISCloseConnection( void *conn_handle ) { PQfinish( (PGconn*) conn_handle ); } 4) In msPOSTGISLayerClose() release the connection handle instead of directly closing it. msConnPoolRelease( layer, layerinfo->conn ); layerinfo->conn = NULL; 5) If there was any use of msCheckConnection() or the "sameconnection" member of the layerObj, then old style connection pooling is already present. Remove it. Thats it! Other Notes ----------- o The connection pooling API will report details about connection registrations, requests, releases and closes if the layer debug flag is on for the layers in question. o The connection pooling API will let a connection be used/referenced multiple times from a single thread, but will not allow a connection to be shared between different threads concurrently. But if a connection is released by one thread, it is available for use by another thread. ****************************************************************************/ #include "mapserver.h" #include "mapthread.h" /* defines for lifetime. A positive number is a time-from-last use in seconds */ #define MS_LIFE_FOREVER -1 #define MS_LIFE_ZEROREF -2 #define MS_LIFE_SINGLE -3 typedef struct { enum MS_CONNECTION_TYPE connectiontype; char *connection; int lifespan; int ref_count; int thread_id; int debug; time_t last_used; void *conn_handle; void (*close)( void * ); } connectionObj; /* ** These static structures are protected by the TLOCK_POOL mutex. */ static int connectionCount = 0; static int connectionMax = 0; static connectionObj *connections = NULL; /************************************************************************/ /* msConnPoolRegister() */ /* */ /* Register a new connection with the connection pool tracker. */ /************************************************************************/ void msConnPoolRegister( layerObj *layer, void *conn_handle, void (*close_func)( void * ) ) { const char *close_connection = NULL; connectionObj *conn = NULL; if( layer->debug ) msDebug( "msConnPoolRegister(%s,%s,%p)\n", layer->name, layer->connection, conn_handle ); /* -------------------------------------------------------------------- */ /* We can't meaningful keep a connection with no connection or */ /* connection type string on the layer. */ /* -------------------------------------------------------------------- */ if( layer->connection == NULL ) { if( layer->tileindex != NULL && layer->connectiontype == MS_OGR ) { /* this is ok, no need to make a fuss */ } else { msDebug( "%s: Missing CONNECTION on layer %s.\n", "msConnPoolRegister()", layer->name ); msSetError( MS_MISCERR, "Missing CONNECTION on layer %s.", "msConnPoolRegister()", layer->name ); } return; } /* -------------------------------------------------------------------- */ /* Grow the array of connection information objects if needed. */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_POOL ); if( connectionCount == connectionMax ) { connectionMax += 10; connections = (connectionObj *) realloc(connections, sizeof(connectionObj) * connectionMax ); if( connections == NULL ) { msSetError(MS_MEMERR, NULL, "msConnPoolRegister()"); msReleaseLock( TLOCK_POOL ); return; } } /* -------------------------------------------------------------------- */ /* Set the new connection information. */ /* -------------------------------------------------------------------- */ conn = connections + connectionCount; connectionCount++; conn->connectiontype = layer->connectiontype; conn->connection = msStrdup( layer->connection ); conn->close = close_func; conn->ref_count = 1; conn->thread_id = msGetThreadId(); conn->last_used = time(NULL); conn->conn_handle = conn_handle; conn->debug = layer->debug; /* -------------------------------------------------------------------- */ /* Categorize the connection handling information. */ /* -------------------------------------------------------------------- */ close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); if( close_connection == NULL ) close_connection = "NORMAL"; if( strcasecmp(close_connection,"NORMAL") == 0 ) conn->lifespan = MS_LIFE_ZEROREF; else if( strcasecmp(close_connection,"DEFER") == 0 ) conn->lifespan = MS_LIFE_FOREVER; else if( strcasecmp(close_connection,"ALWAYS") == 0 ) conn->lifespan = MS_LIFE_SINGLE; else { msDebug("msConnPoolRegister(): " "Unrecognised CLOSE_CONNECTION value '%s'\n", close_connection ); msSetError( MS_MISCERR, "Unrecognised CLOSE_CONNECTION value '%s'", "msConnPoolRegister()", close_connection ); conn->lifespan = MS_LIFE_ZEROREF; } msReleaseLock( TLOCK_POOL ); } /************************************************************************/ /* msConnPoolClose() */ /* */ /* Close the indicated connection. The index in the connection */ /* table is passed. Remove the connection from the table as */ /* well. */ /************************************************************************/ static void msConnPoolClose( int conn_index ) { connectionObj *conn = connections + conn_index; if( conn->ref_count > 0 ) { if( conn->debug ) msDebug( "msConnPoolClose(): " "Closing connection %s even though ref_count=%d.\n", conn->connection, conn->ref_count ); msSetError( MS_MISCERR, "Closing connection %s even though ref_count=%d.", "msConnPoolClose()", conn->connection, conn->ref_count ); } if( conn->debug ) msDebug( "msConnPoolClose(%s,%p)\n", conn->connection, conn->conn_handle ); if( conn->close != NULL ) conn->close( conn->conn_handle ); /* free malloced() stuff in this connection */ free( conn->connection ); connectionCount--; if( connectionCount == 0 ) { /* if there are no connections left we will "cleanup". */ connectionMax = 0; free( connections ); connections = NULL; } else { /* move the last connection in place of our now closed one */ memcpy( connections + conn_index, connections + connectionCount, sizeof(connectionObj) ); } } /************************************************************************/ /* msConnPoolRequest() */ /* */ /* Ask for a connection from the connection pool for use with */ /* the current layer. If found (CONNECTION and CONNECTIONTYPE */ /* match) then return it and up the ref count. Otherwise */ /* return NULL. */ /************************************************************************/ void *msConnPoolRequest( layerObj *layer ) { int i; const char* close_connection; if( layer->connection == NULL ) return NULL; /* check if we must always create a new connection */ close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); if( close_connection && strcasecmp(close_connection,"ALWAYS") == 0 ) return NULL; msAcquireLock( TLOCK_POOL ); for( i = 0; i < connectionCount; i++ ) { connectionObj *conn = connections + i; if( layer->connectiontype == conn->connectiontype && strcasecmp( layer->connection, conn->connection ) == 0 && (conn->ref_count == 0 || conn->thread_id == msGetThreadId()) && conn->lifespan != MS_LIFE_SINGLE) { void *conn_handle = NULL; conn->ref_count++; conn->thread_id = msGetThreadId(); conn->last_used = time(NULL); if( layer->debug ) { msDebug( "msConnPoolRequest(%s,%s) -> got %p\n", layer->name, layer->connection, conn->conn_handle ); conn->debug = layer->debug; } conn_handle = conn->conn_handle; msReleaseLock( TLOCK_POOL ); return conn_handle; } } msReleaseLock( TLOCK_POOL ); return NULL; } /************************************************************************/ /* msConnPoolRelease() */ /* */ /* Release the passed connection for the given layer. */ /* Internally the reference count is dropped, and the */ /* connection may be closed. We assume the caller has already */ /* acquired the pool lock. */ /************************************************************************/ void msConnPoolRelease( layerObj *layer, void *conn_handle ) { int i; if( layer->debug ) msDebug( "msConnPoolRelease(%s,%s,%p)\n", layer->name, layer->connection, conn_handle ); if( layer->connection == NULL ) return; msAcquireLock( TLOCK_POOL ); for( i = 0; i < connectionCount; i++ ) { connectionObj *conn = connections + i; if( layer->connectiontype == conn->connectiontype && strcasecmp( layer->connection, conn->connection ) == 0 && conn->conn_handle == conn_handle ) { conn->ref_count--; conn->last_used = time(NULL); if( conn->ref_count == 0 ) conn->thread_id = 0; if( conn->ref_count == 0 && (conn->lifespan == MS_LIFE_ZEROREF || conn->lifespan == MS_LIFE_SINGLE) ) msConnPoolClose( i ); msReleaseLock( TLOCK_POOL ); return; } } msReleaseLock( TLOCK_POOL ); msDebug( "%s: Unable to find handle for layer '%s'.\n", "msConnPoolRelease()", layer->name ); msSetError( MS_MISCERR, "Unable to find handle for layer '%s'.", "msConnPoolRelease()", layer->name ); } /************************************************************************/ /* msConnPoolMapCloseUnreferenced() */ /* */ /* Close any unreferenced connections. */ /************************************************************************/ void msConnPoolCloseUnreferenced() { int i; /* this really needs to be commented out before commiting. */ /* msDebug( "msConnPoolCloseUnreferenced()\n" ); */ msAcquireLock( TLOCK_POOL ); for( i = connectionCount - 1; i >= 0; i-- ) { connectionObj *conn = connections + i; if( conn->ref_count == 0 ) { /* for now we don't assume the locks are re-entrant, so release */ /* it so msConnPoolClose() can get it. */ msConnPoolClose( i ); } } msReleaseLock( TLOCK_POOL ); } /************************************************************************/ /* msConnPoolFinalCleanup() */ /* */ /* Close any remaining open connections. This is normally */ /* called just before (voluntary) application termination. */ /************************************************************************/ void msConnPoolFinalCleanup() { /* this really needs to be commented out before commiting. */ /* msDebug( "msConnPoolFinalCleanup()\n" ); */ msAcquireLock( TLOCK_POOL ); while( connectionCount > 0 ) msConnPoolClose( 0 ); msReleaseLock( TLOCK_POOL ); } mapserver-6.4.1/maplibxml2.c0000644002461700001440000000705712261257215015540 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: libxml2 convenience wrapper functions * Author: Tom Kralidis (tomkralidis@hotmail.com) * ****************************************************************************** * Copyright (c) 2007, Tom Kralidis * * 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. ****************************************************************************/ #include "mapserver.h" #ifdef USE_LIBXML2 #include #include #include #include /** * msLibXml2GenerateList() * * Convenience function to produce a series of XML elements from a delimited list * * @param xmlNodePtr psParent the encompassing node * @param xmlNsPtr psNs the namespace object * @param const char *elname the list member element name * @param const char *values the list member element values * @param char delim the delimiter * */ void msLibXml2GenerateList(xmlNodePtr psParent, xmlNsPtr psNs, const char *elname, const char *values, char delim) { char **tokens = NULL; int n = 0; int i = 0; tokens = msStringSplit(values, delim, &n); if (tokens && n > 0) { for (i=0; inodesetval)) { xmlXPathFreeObject(result); return NULL; } return result; } /** * msLibXml2GetXPathTree * * Convenience function to fetch an XPath and children * * @param xmlDocPtr doc the XML doc pointer * @param xmlXPathObjectPtr the xpath object * * @return result string * */ const char *msLibXml2GetXPathTree(xmlDocPtr doc, xmlXPathObjectPtr xpath) { xmlBufferPtr xbuf; const char *result = NULL; xbuf = xmlBufferCreate(); if (xpath) { if (xmlNodeDump(xbuf, doc, xpath->nodesetval->nodeTab[0], 0, 0) == -1) { return NULL; } result = msStrdup((char *)xbuf->content); } xmlBufferFree(xbuf); return result; } #endif /* defined(USE_LIBXML2) */ mapserver-6.4.1/mapcontext.c0000644002461700001440000021040712261257215015646 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Web Map Context implementation * Author: Julien-Samuel Lacroix, DM Solutions Group (lacroix@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2002-2003, Julien-Samuel Lacroix, DM Solutions Group Inc * * 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 ****************************************************************************/ #include "mapserver.h" #if defined(USE_WMS_LYR) && defined(USE_OGR) /* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */ #include "cpl_minixml.h" #endif /* msGetMapContextFileText() ** ** Read a file and return is content ** ** Take the filename in argument ** Return value must be freed by caller */ char * msGetMapContextFileText(char *filename) { char *pszBuffer; FILE *stream; int nLength; /* open file */ if(filename != NULL && strlen(filename) > 0) { stream = fopen(filename, "rb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } } else { msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } fseek( stream, 0, SEEK_END ); nLength = ftell( stream ); fseek( stream, 0, SEEK_SET ); pszBuffer = (char *) malloc(nLength+1); if( pszBuffer == NULL ) { msSetError(MS_MEMERR, "(%s)", "msGetMapContextFileText()", filename); fclose( stream ); return NULL; } if(fread( pszBuffer, nLength, 1, stream ) == 0 && !feof(stream)) { free( pszBuffer ); fclose( stream ); msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } pszBuffer[nLength] = '\0'; fclose( stream ); return pszBuffer; } #if defined(USE_WMS_LYR) && defined(USE_OGR) /* **msGetMapContextXMLHashValue() ** **Get the xml value and put it in the hash table ** */ int msGetMapContextXMLHashValue( CPLXMLNode *psRoot, const char *pszXMLPath, hashTableObj *metadata, char *pszMetadata ) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( metadata != NULL ) { msInsertHashTable(metadata, pszMetadata, pszValue ); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLHashValue() ** **Get the xml value and put it in the hash table ** */ int msGetMapContextXMLHashValueDecode( CPLXMLNode *psRoot, const char *pszXMLPath, hashTableObj *metadata, char *pszMetadata ) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( metadata != NULL ) { msDecodeHTMLEntities(pszValue); msInsertHashTable(metadata, pszMetadata, pszValue ); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLStringValue() ** **Get the xml value and put it in the string field ** */ int msGetMapContextXMLStringValue( CPLXMLNode *psRoot, char *pszXMLPath, char **pszField) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( pszField != NULL ) { *pszField = msStrdup(pszValue); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLStringValue() ** **Get the xml value and put it in the string field ** */ int msGetMapContextXMLStringValueDecode( CPLXMLNode *psRoot, char *pszXMLPath, char **pszField) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( pszField != NULL ) { msDecodeHTMLEntities(pszValue); *pszField = msStrdup(pszValue); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLFloatValue() ** **Get the xml value and put it in the string field ** */ int msGetMapContextXMLFloatValue( CPLXMLNode *psRoot, char *pszXMLPath, double *pszField) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( pszField != NULL ) { *pszField = atof(pszValue); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* ** msLoadMapContextURLELements ** ** Take a Node and get the width, height, format and href from it. ** Then put this info in metadatas. */ int msLoadMapContextURLELements( CPLXMLNode *psRoot, hashTableObj *metadata, const char *pszMetadataRoot) { char *pszMetadataName; if( psRoot == NULL || metadata == NULL || pszMetadataRoot == NULL ) return MS_FAILURE; pszMetadataName = (char*) malloc( strlen(pszMetadataRoot) + 10 ); sprintf( pszMetadataName, "%s_width", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "width", metadata, pszMetadataName ); sprintf( pszMetadataName, "%s_height", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "height", metadata, pszMetadataName ); sprintf( pszMetadataName, "%s_format", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "format", metadata, pszMetadataName ); sprintf( pszMetadataName, "%s_href", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "OnlineResource.xlink:href", metadata, pszMetadataName ); free(pszMetadataName); return MS_SUCCESS; } /* msLoadMapContextKeyword ** ** Put the keywords from a XML node and put them in a metadata. ** psRoot should be set to keywordlist */ int msLoadMapContextListInMetadata( CPLXMLNode *psRoot, hashTableObj *metadata, char *pszXMLName, char *pszMetadataName, char *pszHashDelimiter) { char *pszHash, *pszXMLValue, *pszMetadata; if(psRoot == NULL || psRoot->psChild == NULL || metadata == NULL || pszMetadataName == NULL || pszXMLName == NULL) return MS_FAILURE; /* Pass from KeywordList to Keyword level */ psRoot = psRoot->psChild; /* Loop on all elements and append keywords to the hash table */ while (psRoot) { if (psRoot->psChild && strcasecmp(psRoot->pszValue, pszXMLName) == 0) { pszXMLValue = psRoot->psChild->pszValue; pszHash = msLookupHashTable(metadata, pszMetadataName); if (pszHash != NULL) { pszMetadata = (char*)malloc(strlen(pszHash)+ strlen(pszXMLValue)+2); if(pszHashDelimiter == NULL) sprintf( pszMetadata, "%s%s", pszHash, pszXMLValue ); else sprintf( pszMetadata, "%s%s%s", pszHash, pszHashDelimiter, pszXMLValue ); msInsertHashTable(metadata, pszMetadataName, pszMetadata); free(pszMetadata); } else msInsertHashTable(metadata, pszMetadataName, pszXMLValue); } psRoot = psRoot->psNext; } return MS_SUCCESS; } /* msLoadMapContextContactInfo ** ** Put the Contact informations from a XML node and put them in a metadata. ** */ int msLoadMapContextContactInfo( CPLXMLNode *psRoot, hashTableObj *metadata ) { if(psRoot == NULL || metadata == NULL) return MS_FAILURE; /* Contact Person primary */ msGetMapContextXMLHashValue(psRoot, "ContactPersonPrimary.ContactPerson", metadata, "wms_contactperson"); msGetMapContextXMLHashValue(psRoot, "ContactPersonPrimary.ContactOrganization", metadata, "wms_contactorganization"); /* Contact Position */ msGetMapContextXMLHashValue(psRoot, "ContactPosition", metadata, "wms_contactposition"); /* Contact Address */ msGetMapContextXMLHashValue(psRoot, "ContactAddress.AddressType", metadata, "wms_addresstype"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.Address", metadata, "wms_address"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.City", metadata, "wms_city"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.StateOrProvince", metadata, "wms_stateorprovince"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.PostCode", metadata, "wms_postcode"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.Country", metadata, "wms_country"); /* Others */ msGetMapContextXMLHashValue(psRoot, "ContactVoiceTelephone", metadata, "wms_contactvoicetelephone"); msGetMapContextXMLHashValue(psRoot, "ContactFacsimileTelephone", metadata, "wms_contactfacsimiletelephone"); msGetMapContextXMLHashValue(psRoot, "ContactElectronicMailAddress", metadata, "wms_contactelectronicmailaddress"); return MS_SUCCESS; } /* ** msLoadMapContextLayerFormat ** ** */ int msLoadMapContextLayerFormat(CPLXMLNode *psFormat, layerObj *layer) { char *pszValue, *pszValue1, *pszHash; if(psFormat->psChild != NULL && strcasecmp(psFormat->pszValue, "Format") == 0 ) { if(psFormat->psChild->psNext == NULL) pszValue = psFormat->psChild->pszValue; else pszValue = psFormat->psChild->psNext->pszValue; } else pszValue = NULL; if(pszValue != NULL && strcasecmp(pszValue, "") != 0) { /* wms_format */ pszValue1 = (char*)CPLGetXMLValue(psFormat, "current", NULL); if(pszValue1 != NULL && (strcasecmp(pszValue1, "1") == 0 || strcasecmp(pszValue1, "true")==0)) msInsertHashTable(&(layer->metadata), "wms_format", pszValue); /* wms_formatlist */ pszHash = msLookupHashTable(&(layer->metadata), "wms_formatlist"); if(pszHash != NULL) { pszValue1 = (char*)malloc(strlen(pszHash)+ strlen(pszValue)+2); sprintf(pszValue1, "%s,%s", pszHash, pszValue); msInsertHashTable(&(layer->metadata), "wms_formatlist", pszValue1); free(pszValue1); } else msInsertHashTable(&(layer->metadata), "wms_formatlist", pszValue); } /* Make sure selected format is supported or select another * supported format. Note that we can efficiently do this * only for GIF/PNG/JPEG, can't try to handle all GDAL * formats. */ pszValue = msLookupHashTable(&(layer->metadata), "wms_format"); if ( #if !(defined USE_GD_PNG || defined USE_PNG) strcasecmp(pszValue, "image/png") == 0 || strcasecmp(pszValue, "PNG") == 0 || #endif #if !(defined USE_GD_JPEG || defined USE_JPEG) strcasecmp(pszValue, "image/jpeg") == 0 || strcasecmp(pszValue, "JPEG") == 0 || #endif #ifndef USE_GD_GIF strcasecmp(pszValue, "image/gif") == 0 || strcasecmp(pszValue, "GIF") == 0 || #endif 0 ) { char **papszList=NULL; int i, numformats=0; pszValue = msLookupHashTable(&(layer->metadata), "wms_formatlist"); papszList = msStringSplit(pszValue, ',', &numformats); for(i=0; i < numformats; i++) { if ( #if (defined USE_GD_PNG || defined USE_PNG) strcasecmp(papszList[i], "image/png") == 0 || strcasecmp(papszList[i], "PNG") == 0 || #endif #if (defined USE_GD_JPEG || defined USE_JPEG) strcasecmp(papszList[i], "image/jpeg") == 0 || strcasecmp(papszList[i], "JPEG") == 0 || #endif #ifdef USE_GD_GIF strcasecmp(papszList[i], "image/gif") == 0 || strcasecmp(papszList[i], "GIF") == 0 || #endif 0 ) { /* Found a match */ msInsertHashTable(&(layer->metadata), "wms_format", papszList[i]); break; } } if(papszList) msFreeCharArray(papszList, numformats); } /* end if unsupported format */ return MS_SUCCESS; } int msLoadMapContextLayerStyle(CPLXMLNode *psStyle, layerObj *layer, int nStyle) { char *pszValue, *pszValue1, *pszValue2; char *pszHash, *pszStyle=NULL, *pszStyleName; CPLXMLNode *psStyleSLDBody; pszStyleName =(char*)CPLGetXMLValue(psStyle,"Name",NULL); if(pszStyleName == NULL) { pszStyleName = (char*)malloc(20); sprintf(pszStyleName, "Style{%d}", nStyle); } else pszStyleName = msStrdup(pszStyleName); /* wms_style */ pszValue = (char*)CPLGetXMLValue(psStyle,"current",NULL); if(pszValue != NULL && (strcasecmp(pszValue, "1") == 0 || strcasecmp(pszValue, "true") == 0)) msInsertHashTable(&(layer->metadata), "wms_style", pszStyleName); /* wms_stylelist */ pszHash = msLookupHashTable(&(layer->metadata), "wms_stylelist"); if(pszHash != NULL) { pszValue1 = (char*)malloc(strlen(pszHash)+ strlen(pszStyleName)+2); sprintf(pszValue1, "%s,%s", pszHash, pszStyleName); msInsertHashTable(&(layer->metadata), "wms_stylelist", pszValue1); free(pszValue1); } else msInsertHashTable(&(layer->metadata), "wms_stylelist", pszStyleName); /* Title */ pszStyle = (char*)malloc(strlen(pszStyleName)+20); sprintf(pszStyle,"wms_style_%s_title",pszStyleName); if( msGetMapContextXMLHashValue(psStyle, "Title", &(layer->metadata), pszStyle) == MS_FAILURE ) msInsertHashTable(&(layer->metadata), pszStyle, layer->name); free(pszStyle); /* SLD */ pszStyle = (char*)malloc(strlen(pszStyleName)+15); sprintf(pszStyle, "wms_style_%s_sld", pszStyleName); msGetMapContextXMLHashValueDecode( psStyle, "SLD.OnlineResource.xlink:href", &(layer->metadata), pszStyle ); free(pszStyle); /* SLDBODY */ pszStyle = (char*)malloc(strlen(pszStyleName)+20); sprintf(pszStyle, "wms_style_%s_sld_body", pszStyleName); psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.StyledLayerDescriptor"); /*some clients such as OpenLayers add a name space, which I believe is wrong but added this additional test for compatibility #3115*/ if (psStyleSLDBody == NULL) psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.sld:StyledLayerDescriptor"); if(psStyleSLDBody != NULL && &(layer->metadata) != NULL) { pszValue = CPLSerializeXMLTree(psStyleSLDBody); if(pszValue != NULL) { /* Before including SLDBody in the mapfile, we must replace the */ /* double quote for single quote. This is to prevent having this: */ /* "metadata" "" */ char *c; for(c=pszValue; *c != '\0'; c++) if(*c == '"') *c = '\''; msInsertHashTable(&(layer->metadata), pszStyle, pszValue ); msFree(pszValue); } } free(pszStyle); /* LegendURL */ pszStyle = (char*) malloc(strlen(pszStyleName) + 25); sprintf( pszStyle, "wms_style_%s_legendurl", pszStyleName); msLoadMapContextURLELements( CPLGetXMLNode(psStyle, "LegendURL"), &(layer->metadata), pszStyle ); free(pszStyle); free(pszStyleName); /* */ /* Add the stylelist to the layer connection */ /* */ if(msLookupHashTable(&(layer->metadata), "wms_stylelist") == NULL) { if(layer->connection) pszValue = msStrdup(layer->connection); else pszValue = msStrdup( "" ); pszValue1 = strstr(pszValue, "STYLELIST="); if(pszValue1 != NULL) { pszValue1 += 10; pszValue2 = strchr(pszValue, '&'); if(pszValue2 != NULL) pszValue1[pszValue2-pszValue1] = '\0'; msInsertHashTable(&(layer->metadata), "wms_stylelist", pszValue1); } free(pszValue); } /* */ /* Add the style to the layer connection */ /* */ if(msLookupHashTable(&(layer->metadata), "wms_style") == NULL) { if(layer->connection) pszValue = msStrdup(layer->connection); else pszValue = msStrdup( "" ); pszValue1 = strstr(pszValue, "STYLE="); if(pszValue1 != NULL) { pszValue1 += 6; pszValue2 = strchr(pszValue, '&'); if(pszValue2 != NULL) pszValue1[pszValue2-pszValue1] = '\0'; msInsertHashTable(&(layer->metadata), "wms_style", pszValue1); } free(pszValue); } return MS_SUCCESS; } int msLoadMapContextLayerDimension(CPLXMLNode *psDimension, layerObj *layer) { char *pszValue, *pszHash; char *pszDimension=NULL, *pszDimensionName=NULL; pszDimensionName =(char*)CPLGetXMLValue(psDimension,"name",NULL); if(pszDimensionName == NULL) { return MS_FALSE; } else pszDimensionName = msStrdup(pszDimensionName); pszDimension = (char*)malloc(strlen(pszDimensionName)+50); /* wms_dimension: This is the current dimension */ pszValue = (char*)CPLGetXMLValue(psDimension, "current", NULL); if(pszValue != NULL && (strcasecmp(pszValue, "1") == 0 || strcasecmp(pszValue, "true") == 0)) msInsertHashTable(&(layer->metadata), "wms_dimension", pszDimensionName); /* wms_dimensionlist */ pszHash = msLookupHashTable(&(layer->metadata), "wms_dimensionlist"); if(pszHash != NULL) { pszValue = (char*)malloc(strlen(pszHash)+ strlen(pszDimensionName)+2); sprintf(pszValue, "%s,%s", pszHash, pszDimensionName); msInsertHashTable(&(layer->metadata), "wms_dimensionlist", pszValue); free(pszValue); } else msInsertHashTable(&(layer->metadata), "wms_dimensionlist", pszDimensionName); /* Units */ sprintf(pszDimension, "wms_dimension_%s_units", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "units", &(layer->metadata), pszDimension); /* UnitSymbol */ sprintf(pszDimension, "wms_dimension_%s_unitsymbol", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "unitSymbol", &(layer->metadata), pszDimension); /* userValue */ sprintf(pszDimension, "wms_dimension_%s_uservalue", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata), pszDimension); if(strcasecmp(pszDimensionName, "time") == 0) msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata), "wms_time"); /* default */ sprintf(pszDimension, "wms_dimension_%s_default", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "default", &(layer->metadata), pszDimension); /* multipleValues */ sprintf(pszDimension, "wms_dimension_%s_multiplevalues", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "multipleValues",&(layer->metadata), pszDimension); /* nearestValue */ sprintf(pszDimension, "wms_dimension_%s_nearestvalue", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "nearestValue", &(layer->metadata), pszDimension); free(pszDimension); free(pszDimensionName); return MS_SUCCESS; } /* ** msLoadMapContextGeneral ** ** Load the General block of the mapcontext document */ int msLoadMapContextGeneral(mapObj *map, CPLXMLNode *psGeneral, CPLXMLNode *psMapContext, int nVersion, char *filename) { char *pszProj=NULL; char *pszValue, *pszValue1, *pszValue2; /* Projection */ pszValue = (char*)CPLGetXMLValue(psGeneral, "BoundingBox.SRS", NULL); if(pszValue != NULL) { if(strncasecmp(pszValue, "AUTO:", 5) == 0) { pszProj = msStrdup(pszValue); } else { pszProj = (char*) malloc(sizeof(char)*(strlen(pszValue)+10)); sprintf(pszProj, "init=epsg:%s", pszValue+5); } msInitProjection(&map->projection); map->projection.args[map->projection.numargs] = msStrdup(pszProj); map->projection.numargs++; msProcessProjection(&map->projection); if( (map->units = GetMapserverUnitUsingProj(&(map->projection))) == -1) { free(pszProj); msSetError( MS_MAPCONTEXTERR, "Unable to set units for projection '%s'", "msLoadMapContext()", pszProj ); return MS_FAILURE; } free(pszProj); } else { msDebug("Mandatory data General.BoundingBox.SRS missing in %s.", filename); } /* Extent */ if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.minx", &(map->extent.minx)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.minx missing in %s.", filename); } if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.miny", &(map->extent.miny)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.miny missing in %s.", filename); } if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxx", &(map->extent.maxx)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.maxx missing in %s.", filename); } if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxy", &(map->extent.maxy)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.maxy missing in %s.", filename); } /* Title */ if( msGetMapContextXMLHashValue(psGeneral, "Title", &(map->web.metadata), "wms_title") == MS_FAILURE) { if ( nVersion >= OWS_1_0_0 ) msDebug("Mandatory data General.Title missing in %s.", filename); else { if( msGetMapContextXMLHashValue(psGeneral, "gml:name", &(map->web.metadata), "wms_title") == MS_FAILURE ) { if( nVersion < OWS_0_1_7 ) msDebug("Mandatory data General.Title missing in %s.", filename); else msDebug("Mandatory data General.gml:name missing in %s.", filename); } } } /* Name */ if( nVersion >= OWS_1_0_0 ) { pszValue = (char*)CPLGetXMLValue(psMapContext, "id", NULL); if (pszValue) map->name = msStrdup(pszValue); } else { if(msGetMapContextXMLStringValue(psGeneral, "Name", &(map->name)) == MS_FAILURE) { msGetMapContextXMLStringValue(psGeneral, "gml:name", &(map->name)); } } /* Keyword */ if( nVersion >= OWS_1_0_0 ) { msLoadMapContextListInMetadata( CPLGetXMLNode(psGeneral, "KeywordList"), &(map->web.metadata), "KEYWORD", "wms_keywordlist", "," ); } else msGetMapContextXMLHashValue(psGeneral, "Keywords", &(map->web.metadata), "wms_keywordlist"); /* Window */ pszValue1 = (char*)CPLGetXMLValue(psGeneral,"Window.width",NULL); pszValue2 = (char*)CPLGetXMLValue(psGeneral,"Window.height",NULL); if(pszValue1 != NULL && pszValue2 != NULL) { map->width = atoi(pszValue1); map->height = atoi(pszValue2); } /* Abstract */ if( msGetMapContextXMLHashValue( psGeneral, "Abstract", &(map->web.metadata), "wms_abstract") == MS_FAILURE ) { msGetMapContextXMLHashValue( psGeneral, "gml:description", &(map->web.metadata), "wms_abstract"); } /* DataURL */ msGetMapContextXMLHashValueDecode(psGeneral, "DataURL.OnlineResource.xlink:href", &(map->web.metadata), "wms_dataurl"); /* LogoURL */ /* The logourl have a width, height, format and an URL */ msLoadMapContextURLELements( CPLGetXMLNode(psGeneral, "LogoURL"), &(map->web.metadata), "wms_logourl" ); /* DescriptionURL */ /* The descriptionurl have a width, height, format and an URL */ msLoadMapContextURLELements( CPLGetXMLNode(psGeneral, "DescriptionURL"), &(map->web.metadata), "wms_descriptionurl" ); /* Contact Info */ msLoadMapContextContactInfo( CPLGetXMLNode(psGeneral, "ContactInformation"), &(map->web.metadata) ); return MS_SUCCESS; } /* ** msLoadMapContextLayer ** ** Load a Layer block from a MapContext document */ int msLoadMapContextLayer(mapObj *map, CPLXMLNode *psLayer, int nVersion, char *filename, int unique_layer_names) { char *pszProj=NULL; char *pszValue; char *pszHash, *pszName=NULL; CPLXMLNode *psFormatList, *psFormat, *psStyleList, *psStyle, *psExtension; CPLXMLNode *psDimensionList, *psDimension; int nStyle; layerObj *layer; /* Init new layer */ if(msGrowMapLayers(map) == NULL) return MS_FAILURE; layer = (GET_LAYER(map, map->numlayers)); initLayer(layer, map); layer->map = (mapObj *)map; layer->type = MS_LAYER_RASTER; /* save the index */ GET_LAYER(map, map->numlayers)->index = map->numlayers; map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; /* Status */ pszValue = (char*)CPLGetXMLValue(psLayer, "hidden", "1"); if((pszValue != NULL) && (atoi(pszValue) == 0 && !strcasecmp(pszValue, "true") == 0)) layer->status = MS_ON; else layer->status = MS_OFF; /* Queryable */ pszValue = (char*)CPLGetXMLValue(psLayer, "queryable", "0"); if(pszValue !=NULL && (atoi(pszValue) == 1 || strcasecmp(pszValue, "true") == 0)) layer->template = msStrdup("ttt"); /* Name and Title */ pszValue = (char*)CPLGetXMLValue(psLayer, "Name", NULL); if(pszValue != NULL) { msInsertHashTable( &(layer->metadata), "wms_name", pszValue ); if (unique_layer_names) { pszName = (char*)malloc(sizeof(char)*(strlen(pszValue)+15)); sprintf(pszName, "l%d:%s", layer->index, pszValue); layer->name = msStrdup(pszName); free(pszName); } else layer->name = msStrdup(pszValue); } else { pszName = (char*)malloc(sizeof(char)*15); sprintf(pszName, "l%d:", layer->index); layer->name = msStrdup(pszName); free(pszName); } if(msGetMapContextXMLHashValue(psLayer, "Title", &(layer->metadata), "wms_title") == MS_FAILURE) { if(msGetMapContextXMLHashValue(psLayer, "Server.title", &(layer->metadata), "wms_title") == MS_FAILURE) { msDebug("Mandatory data Layer.Title missing in %s.", filename); } } /* Server Title */ msGetMapContextXMLHashValue(psLayer, "Server.title", &(layer->metadata), "wms_server_title"); /* Abstract */ msGetMapContextXMLHashValue(psLayer, "Abstract", &(layer->metadata), "wms_abstract"); /* DataURL */ if(nVersion <= OWS_0_1_4) { msGetMapContextXMLHashValueDecode(psLayer, "DataURL.OnlineResource.xlink:href", &(layer->metadata), "wms_dataurl"); } else { /* The DataURL have a width, height, format and an URL */ /* Width and height are not used, but they are included to */ /* be consistent with the spec. */ msLoadMapContextURLELements( CPLGetXMLNode(psLayer, "DataURL"), &(layer->metadata), "wms_dataurl" ); } /* The MetadataURL have a width, height, format and an URL */ /* Width and height are not used, but they are included to */ /* be consistent with the spec. */ msLoadMapContextURLELements( CPLGetXMLNode(psLayer, "MetadataURL"), &(layer->metadata), "wms_metadataurl" ); /* MinScale && MaxScale */ pszValue = (char*)CPLGetXMLValue(psLayer, "sld:MinScaleDenominator", NULL); if(pszValue != NULL) { layer->minscaledenom = atof(pszValue); } pszValue = (char*)CPLGetXMLValue(psLayer, "sld:MaxScaleDenominator", NULL); if(pszValue != NULL) { layer->maxscaledenom = atof(pszValue); } /* */ /* Server */ /* */ if(nVersion >= OWS_0_1_4) { if(msGetMapContextXMLStringValueDecode(psLayer, "Server.OnlineResource.xlink:href", &(layer->connection)) == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.OnlineResource.xlink:href missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } else { msGetMapContextXMLHashValueDecode(psLayer, "Server.OnlineResource.xlink:href", &(layer->metadata), "wms_onlineresource"); layer->connectiontype = MS_WMS; } } else { if(msGetMapContextXMLStringValueDecode(psLayer, "Server.onlineResource", &(layer->connection)) == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.onlineResource missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } else { msGetMapContextXMLHashValueDecode(psLayer, "Server.onlineResource", &(layer->metadata), "wms_onlineresource"); layer->connectiontype = MS_WMS; } } if(nVersion >= OWS_0_1_4) { if(msGetMapContextXMLHashValue(psLayer, "Server.version", &(layer->metadata), "wms_server_version") == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.version missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } } else { if(msGetMapContextXMLHashValue(psLayer, "Server.wmtver", &(layer->metadata), "wms_server_version") == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.wmtver missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } } /* Projection */ msLoadMapContextListInMetadata( psLayer, &(layer->metadata), "SRS", "wms_srs", " " ); pszHash = msLookupHashTable(&(layer->metadata), "wms_srs"); if(((pszHash == NULL) || (strcasecmp(pszHash, "") == 0)) && map->projection.numargs != 0) { pszProj = map->projection.args[map->projection.numargs-1]; if(pszProj != NULL) { if(strncasecmp(pszProj, "AUTO:", 5) == 0) { msInsertHashTable(&(layer->metadata),"wms_srs", pszProj); } else { if(strlen(pszProj) > 10) { pszProj = (char*) malloc(sizeof(char) * (strlen(pszProj))); sprintf( pszProj, "EPSG:%s", map->projection.args[map->projection.numargs-1]+10); msInsertHashTable(&(layer->metadata),"wms_srs", pszProj); } else { msDebug("Unable to set data for layer wms_srs from this" " value %s.", pszProj); } } } } /* */ /* Format */ /* */ if( nVersion >= OWS_0_1_4 ) { psFormatList = CPLGetXMLNode(psLayer, "FormatList"); } else { psFormatList = psLayer; } if(psFormatList != NULL) { for(psFormat = psFormatList->psChild; psFormat != NULL; psFormat = psFormat->psNext) { msLoadMapContextLayerFormat(psFormat, layer); } } /* end FormatList parsing */ /* Style */ if( nVersion >= OWS_0_1_4 ) { psStyleList = CPLGetXMLNode(psLayer, "StyleList"); } else { psStyleList = psLayer; } if(psStyleList != NULL) { nStyle = 0; for(psStyle = psStyleList->psChild; psStyle != NULL; psStyle = psStyle->psNext) { if(strcasecmp(psStyle->pszValue, "Style") == 0) { nStyle++; msLoadMapContextLayerStyle(psStyle, layer, nStyle); } } } /* Dimension */ psDimensionList = CPLGetXMLNode(psLayer, "DimensionList"); if(psDimensionList != NULL) { for(psDimension = psDimensionList->psChild; psDimension != NULL; psDimension = psDimension->psNext) { if(strcasecmp(psDimension->pszValue, "Dimension") == 0) { msLoadMapContextLayerDimension(psDimension, layer); } } } /* Extension */ psExtension = CPLGetXMLNode(psLayer, "Extension"); if (psExtension != NULL) { pszValue = (char*)CPLGetXMLValue(psExtension, "ol:opacity", NULL); if(pszValue != NULL) { layer->opacity = atof(pszValue)*100; } } return MS_SUCCESS; } #endif /* msLoadMapContextURL() ** ** load an OGC Web Map Context format from an URL ** ** Take a map object and a URL to a conect file in arguments */ int msLoadMapContextURL(mapObj *map, char *urlfilename, int unique_layer_names) { #if defined(USE_WMS_LYR) && defined(USE_OGR) char *pszTmpFile = NULL; int status = 0; if (!map || !urlfilename) { msSetError(MS_MAPCONTEXTERR, "Invalid map or url given.", "msGetMapContextURL()"); return MS_FAILURE; } pszTmpFile = msTmpFile(map, map->mappath, NULL, "context.xml"); if (msHTTPGetFile(urlfilename, pszTmpFile, &status,-1, 0, 0, 0) == MS_SUCCESS) { return msLoadMapContext(map, pszTmpFile, unique_layer_names); } else { msSetError(MS_MAPCONTEXTERR, "Could not open context file %s.", "msGetMapContextURL()", urlfilename); return MS_FAILURE; } #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msGetMapContextURL()"); return MS_FAILURE; #endif } /* msLoadMapContext() ** ** Get a mapfile from a OGC Web Map Context format ** ** Take as first map object and a file in arguments ** If The 2nd aregument unique_layer_names is set to MS_TRUE, the layer ** name created would be unique and be prefixed with an l plus the layers's index ** (eg l:1:park. l:2:road ...). If It is set to MS_FALSE, the layer name ** would be the same name as the layer name in the context */ int msLoadMapContext(mapObj *map, char *filename, int unique_layer_names) { #if defined(USE_WMS_LYR) && defined(USE_OGR) char *pszWholeText, *pszValue; CPLXMLNode *psRoot, *psMapContext, *psLayer, *psLayerList, *psChild; char szPath[MS_MAXPATHLEN]; int nVersion=-1; char szVersionBuf[OWS_VERSION_MAXLEN]; /* */ /* Load the raw XML file */ /* */ pszWholeText = msGetMapContextFileText( msBuildPath(szPath, map->mappath, filename)); if(pszWholeText == NULL) { msSetError( MS_MAPCONTEXTERR, "Unable to read %s", "msLoadMapContext()", filename ); return MS_FAILURE; } if( ( strstr( pszWholeText, "eType == CXT_Element && (EQUAL(psChild->pszValue,"WMS_Viewer_Context") || EQUAL(psChild->pszValue,"View_Context") || EQUAL(psChild->pszValue,"ViewContext")) ) { psMapContext = psChild; break; } else { psChild = psChild->psNext; } } if( psMapContext == NULL ) { CPLDestroyXMLNode(psRoot); msSetError( MS_MAPCONTEXTERR, "Invalid Map Context File (%s)", "msLoadMapContext()", filename ); return MS_FAILURE; } /* Fetch document version number */ pszValue = (char*)CPLGetXMLValue(psMapContext, "version", NULL); if( !pszValue ) { msDebug( "msLoadMapContext(): Mandatory data version missing in %s, assuming 0.1.4.", filename ); pszValue = "0.1.4"; } nVersion = msOWSParseVersionString(pszValue); /* Make sure this is a supported version */ switch (nVersion) { case OWS_0_1_2: case OWS_0_1_4: case OWS_0_1_7: case OWS_1_0_0: case OWS_1_1_0: /* All is good, this is a supported version. */ break; default: /* Not a supported version */ msSetError(MS_MAPCONTEXTERR, "This version of Map Context is not supported (%s).", "msLoadMapContext()", pszValue); CPLDestroyXMLNode(psRoot); return MS_FAILURE; } /* Reformat and save Version in metadata */ msInsertHashTable( &(map->web.metadata), "wms_context_version", msOWSGetVersionString(nVersion, szVersionBuf)); if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0) { if( msGetMapContextXMLHashValue(psMapContext, "fid", &(map->web.metadata), "wms_context_fid") == MS_FAILURE ) { msDebug("Mandatory data fid missing in %s.", filename); } } /* */ /* Load the General bloc */ /* */ psChild = CPLGetXMLNode( psMapContext, "General" ); if( psChild == NULL ) { CPLDestroyXMLNode(psRoot); msSetError(MS_MAPCONTEXTERR, "The Map Context document provided (%s) does not contain any " "General elements.", "msLoadMapContext()", filename); return MS_FAILURE; } if( msLoadMapContextGeneral(map, psChild, psMapContext, nVersion, filename) == MS_FAILURE ) { CPLDestroyXMLNode(psRoot); return MS_FAILURE; } /* */ /* Load the bloc LayerList */ /* */ psLayerList = CPLGetXMLNode(psMapContext, "LayerList"); if( psLayerList != NULL ) { for(psLayer = psLayerList->psChild; psLayer != NULL; psLayer = psLayer->psNext) { if(EQUAL(psLayer->pszValue, "Layer")) { if( msLoadMapContextLayer(map, psLayer, nVersion, filename, unique_layer_names) == MS_FAILURE ) { CPLDestroyXMLNode(psRoot); return MS_FAILURE; } }/* end Layer parsing */ }/* for */ } CPLDestroyXMLNode(psRoot); return MS_SUCCESS; #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msGetMapContext()"); return MS_FAILURE; #endif } /* msSaveMapContext() ** ** Save a mapfile into the OGC Web Map Context format ** ** Take a map object and a file in arguments */ int msSaveMapContext(mapObj *map, char *filename) { #if defined(USE_WMS_LYR) && defined(USE_OGR) FILE *stream; char szPath[MS_MAXPATHLEN]; int nStatus; /* open file */ if(filename != NULL && strlen(filename) > 0) { stream = fopen(msBuildPath(szPath, map->mappath, filename), "wb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msSaveMapContext()", filename); return(MS_FAILURE); } } else { msSetError(MS_IOERR, "Filename is undefined.", "msSaveMapContext()"); return MS_FAILURE; } nStatus = msWriteMapContext(map, stream); fclose(stream); return nStatus; #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msSaveMapContext()"); return MS_FAILURE; #endif } int msWriteMapContext(mapObj *map, FILE *stream) { #if defined(USE_WMS_LYR) && defined(USE_OGR) const char * version, *value; char * tabspace=NULL, *pszValue, *pszChar,*pszSLD=NULL,*pszURL,*pszSLD2=NULL; char *pszStyle, *pszCurrent, *pszStyleItem, *pszSLDBody; char *pszEncodedVal; int i, nValue, nVersion=OWS_VERSION_NOTSET; /* Dimension element */ char *pszDimension; const char *pszDimUserValue=NULL, *pszDimUnits=NULL, *pszDimDefault=NULL; const char *pszDimNearValue=NULL, *pszDimUnitSymbol=NULL; const char *pszDimMultiValue=NULL; int bDimensionList = 0; /* Decide which version we're going to return... */ version = msLookupHashTable(&(map->web.metadata), "wms_context_version"); if(version == NULL) version = "1.1.0"; nVersion = msOWSParseVersionString(version); if (nVersion == OWS_VERSION_BADFORMAT) return MS_FAILURE; /* msSetError() already called. */ /* Make sure this is a supported version */ /* Note that we don't write 0.1.2 even if we read it. */ switch (nVersion) { case OWS_0_1_4: case OWS_0_1_7: case OWS_1_0_0: case OWS_1_1_0: /* All is good, this is a supported version. */ break; default: /* Not a supported version */ msSetError(MS_MAPCONTEXTERR, "This version of Map Context is not supported (%s).", "msSaveMapContext()", version); return MS_FAILURE; } /* file header */ msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_encoding", OWS_NOERR, "\n", "ISO-8859-1"); /* set the WMS_Viewer_Context information */ pszEncodedVal = msEncodeHTMLEntities(version); if(nVersion >= OWS_1_0_0) { msIO_fprintf( stream, "= OWS_0_1_7) { msIO_fprintf( stream, "= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_context_fid", OWS_NOERR," fid=\"%s\"","0"); } if ( nVersion >= OWS_1_0_0 ) msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR, " id=\"%s\"", NULL); msIO_fprintf( stream, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); msIO_fprintf( stream, " xmlns:ogc=\"http://www.opengis.net/ogc\""); if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msIO_fprintf( stream, " xmlns:gml=\"http://www.opengis.net/gml\""); } if( nVersion >= OWS_1_0_0 ) { msIO_fprintf( stream, " xmlns:xlink=\"http://www.w3.org/1999/xlink\""); msIO_fprintf( stream, " xmlns=\"http://www.opengis.net/context\""); msIO_fprintf( stream, " xmlns:sld=\"http://www.opengis.net/sld\""); pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if( nVersion >= OWS_1_1_0 ) msIO_fprintf( stream, " xsi:schemaLocation=\"http://www.opengis.net/context %s/context/1.1.0/context.xsd\">\n", pszEncodedVal); else msIO_fprintf( stream, " xsi:schemaLocation=\"http://www.opengis.net/context %s/context/1.0.0/context.xsd\">\n", pszEncodedVal); msFree(pszEncodedVal); } else { msIO_fprintf( stream, " xmlns:xlink=\"http://www.w3.org/TR/xlink\""); pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); msIO_fprintf( stream, " xsi:noNamespaceSchemaLocation=\"%s/contexts/", pszEncodedVal ); msFree(pszEncodedVal); pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); msIO_fprintf( stream, "%s/context.xsd\">\n", pszEncodedVal); msFree(pszEncodedVal); } /* set the General information */ msIO_fprintf( stream, " \n" ); /* Window */ if( map->width != -1 || map->height != -1 ) msIO_fprintf( stream, " \n", map->width, map->height ); /* Bounding box corners and spatial reference system */ if(tabspace) free(tabspace); tabspace = msStrdup(" "); value = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_TRUE); msIO_fprintf( stream, "%s\n", tabspace ); if(!value || (strcasecmp(value, "(null)") == 0)) msIO_fprintf(stream, "\n"); pszEncodedVal = msEncodeHTMLEntities(value); msIO_fprintf( stream, "%s\n", tabspace, pszEncodedVal, map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy ); msFree(pszEncodedVal); /* Title, name */ if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR, " %s\n", NULL); } else { if (nVersion < OWS_0_1_7) msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR, " %s\n", NULL); msIO_fprintf( stream, "%s\n", tabspace ); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_title", OWS_WARN, " %s\n", map->name); } /* keyword */ if (nVersion >= OWS_1_0_0) { if (msLookupHashTable(&(map->web.metadata),"wms_keywordlist")!=NULL) { char **papszKeywords; int nKeywords, iKey; pszValue = msLookupHashTable(&(map->web.metadata), "wms_keywordlist"); papszKeywords = msStringSplit(pszValue, ',', &nKeywords); if(nKeywords > 0 && papszKeywords) { msIO_fprintf( stream, " \n"); for(iKey=0; iKey%s\n", pszEncodedVal); msFree(pszEncodedVal); } msIO_fprintf( stream, " \n"); } } } else msOWSPrintEncodeMetadataList(stream, &(map->web.metadata), NULL, "wms_keywordlist", " \n", " \n", " %s\n", NULL); /* abstract */ if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_abstract", OWS_NOERR, " %s\n", NULL); } else { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_abstract", OWS_NOERR, " %s\n", NULL); } /* LogoURL */ /* The LogoURL have a width, height, format and an URL */ msOWSPrintURLType(stream, &(map->web.metadata), "MO", "logourl", OWS_NOERR, NULL, "LogoURL", NULL, " width=\"%s\"", " height=\"%s\""," format=\"%s\"", " \n", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); /* DataURL */ msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_dataurl", OWS_NOERR, " \n \n \n", NULL); /* DescriptionURL */ /* The DescriptionURL have a width, height, format and an URL */ /* The metadata is structured like this: "width height format url" */ msOWSPrintURLType(stream, &(map->web.metadata), "MO", "descriptionurl", OWS_NOERR, NULL, "DescriptionURL", NULL, " width=\"%s\"", " height=\"%s\""," format=\"%s\"", " \n", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); /* Contact Info */ msOWSPrintContactInfo( stream, tabspace, OWS_1_1_0, &(map->web.metadata), "MO" ); /* Close General */ msIO_fprintf( stream, " \n" ); free(tabspace); /* Set the layer list */ msIO_fprintf(stream, " \n"); /* Loop on all layer */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->status != MS_DELETE && GET_LAYER(map, i)->connectiontype == MS_WMS) { if(GET_LAYER(map, i)->status == MS_OFF) nValue = 1; else nValue = 0; msIO_fprintf(stream, " \n"); } } /* Close layer list */ msIO_fprintf(stream, " \n"); /* Close Map Context */ if(nVersion >= OWS_1_0_0) { msIO_fprintf(stream, "\n"); } else if(nVersion >= OWS_0_1_7) { msIO_fprintf(stream, "\n"); } else { /* 0.1.4 */ msIO_fprintf(stream, "\n"); } return MS_SUCCESS; #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msWriteMapContext()"); return MS_FAILURE; #endif } mapserver-6.4.1/shptreevis.c0000644002461700001440000001575112261257215015665 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Utility program to visualize a quadtree * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include #ifndef _WIN32 #include #endif #include #ifdef SHPT_POLYGON #undef MAPSERVER #else #define MAPSERVER 1 #define SHPT_POLYGON SHP_POLYGON #endif char* AddFileSuffix ( const char * Filename, const char * Suffix ) { char *pszFullname, *pszBasename; int i; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(Filename)+5); strcpy( pszBasename, Filename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, Suffix); return (pszFullname); } int main( int argc, char ** argv ) { SHPHandle hSHP; DBFHandle hDBF; SHPTreeHandle qix; char *myfile = NULL; treeNodeObj *node; #ifdef MAPSERVER shapeObj shape; lineObj line[3]; pointObj pts[6]; #else SHPObject *shape; double X[6], Y[6]; #endif int result; /* char mBigEndian; int i; */ int this_rec; /* -------------------------------------------------------------------- */ /* Display a usage message. */ /* -------------------------------------------------------------------- */ if( argc <= 2 ) { printf( "shptreevis shapefile new_shapefile \n" ); exit( 1 ); } /* i = 1; if( *((unsigned char *) &i) == 1 ) mBigEndian = 0; else mBigEndian = 1; */ qix = msSHPDiskTreeOpen (AddFileSuffix(argv[1],".qix"), 0 /* no debug*/); if( qix == NULL ) { printf("unable to open index file %s \n", argv[1]); exit(-1); } /* -------------------------------------------------------------------- */ /* Open the passed shapefile. */ /* -------------------------------------------------------------------- */ myfile = AddFileSuffix(argv[2],".shp"); #ifdef MAPSERVER hSHP = msSHPCreate ( myfile, SHPT_POLYGON ); hDBF = msDBFCreate ( AddFileSuffix(argv[2],".dbf") ); #else hSHP = SHPCreate ( myfile, SHPT_POLYGON ); hDBF = DBFCreate ( AddFileSuffix(argv[2],".dbf") ); #endif if ( (!hSHP) || (!hDBF) ) { printf ("create error for %s ... exiting \n", myfile); exit (-1); } /* add fields to dbf */ #ifdef MAPSERVER msDBFAddField ( hDBF, "ITEMS", FTInteger, 15,0 ); msDBFAddField ( hDBF, "SUBNODES", FTInteger, 15,0 ); msDBFAddField ( hDBF, "FACTOR", FTInteger, 15,0 ); #else DBFAddField ( hDBF, "ITEMS", FTInteger, 15,0 ); DBFAddField ( hDBF, "SUBNODES", FTInteger, 15,0 ); DBFAddField ( hDBF, "FACTOR", FTInteger, 15,0 ); #endif #ifndef MAPSERVER SHPClose ( hSHP ); hSHP = SHPOpen ( myfile, "r+b" ); DBFClose (hDBF); hDBF = DBFOpen ( myfile, "r+b"); #endif printf ("This %s %s index supports a shapefile with %d shapes, %d depth \n", (qix->version ? "new": "old"), (qix->LSB_order? "LSB": "MSB"), (int) qix->nShapes, (int) qix->nDepth); /* -------------------------------------------------------------------- */ /* Skim over the list of shapes, printing all the vertices. */ /* -------------------------------------------------------------------- */ while( 1 ) { node = readTreeNode (qix); if (node ) { this_rec = hDBF->nRecords; #ifdef MAPSERVER msDBFWriteIntegerAttribute( hDBF, this_rec, 0, node->numshapes); msDBFWriteIntegerAttribute( hDBF, this_rec, 1, node->numsubnodes); #else DBFWriteIntegerAttribute( hDBF, this_rec, 0, node->numshapes); DBFWriteIntegerAttribute( hDBF, this_rec, 1, node->numsubnodes); #endif #ifdef MAPSERVER shape.numlines = 1; shape.type = SHPT_POLYGON; pts[0].x = node->rect.minx; pts[0].y = node->rect.miny; pts[1].x = node->rect.maxx; pts[1].y = node->rect.miny; pts[2].x = node->rect.maxx; pts[2].y = node->rect.maxy; pts[3].x = node->rect.minx; pts[3].y = node->rect.maxy; pts[4].x = node->rect.minx; pts[4].y = node->rect.miny; line[0].numpoints = 5; line[0].point = &pts[0]; shape.line = &line[0]; shape.bounds = node->rect; result = msSHPWriteShape ( hSHP, &shape ); if ( result < 0 ) { printf ("unable to write shape \n"); exit (0); } #else X[0] = node->rect.minx; X[1] = node->rect.maxx; X[2] = node->rect.maxx; X[3] = node->rect.minx; X[4] = node->rect.minx; Y[0] = node->rect.miny; Y[1] = node->rect.miny; Y[2] = node->rect.maxy; Y[3] = node->rect.maxy; Y[4] = node->rect.miny; shape = SHPCreateSimpleObject( SHPT_POLYGON, 5, X, Y, NULL); SHPWriteObject(hSHP, -1, shape); SHPDestroyObject ( shape ); #endif } else break; } #ifdef MAPSERVER msSHPClose( hSHP ); msDBFClose( hDBF ); #else SHPClose( hSHP ); DBFClose( hDBF ); #endif msSHPDiskTreeClose (qix); return(0); } mapserver-6.4.1/mapparser.c0000644002461700001440000026323012261257215015460 0ustar tbonfortusers /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.4.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 5 "/home/even/mapserver/git/mapserver/mapparser.y" /* C declarations */ #include #include #include #include #include #include "mapserver.h" /* for TRUE/FALSE and REGEX includes */ #include "maptime.h" /* for time comparison routines */ #include "mapprimitive.h" /* for shapeObj */ #include "mapparser.h" /* for YYSTYPE in the function prototype for yylex() */ int yylex(YYSTYPE *, parseObj *); /* prototype functions, defined after the grammar */ int yyerror(parseObj *, const char *); /* Line 189 of yacc.c */ #line 92 "/home/even/mapserver/git/mapserver/mapparser.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NUMBER = 258, STRING = 259, TIME = 260, SHAPE = 261, OR = 262, AND = 263, NOT = 264, IRE = 265, IEQ = 266, IN = 267, GE = 268, LE = 269, GT = 270, LT = 271, NE = 272, EQ = 273, RE = 274, DWITHIN = 275, BEYOND = 276, CONTAINS = 277, WITHIN = 278, CROSSES = 279, OVERLAPS = 280, TOUCHES = 281, DISJOINT = 282, INTERSECTS = 283, ROUND = 284, COMMIFY = 285, LENGTH = 286, AREA = 287, TOSTRING = 288, SMOOTHSIA = 289, GENERALIZE = 290, SIMPLIFYPT = 291, SIMPLIFY = 292, DIFFERENCE = 293, YYBUFFER = 294, NEG = 295 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 214 of yacc.c */ #line 30 "/home/even/mapserver/git/mapserver/mapparser.y" double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; /* Line 214 of yacc.c */ #line 178 "/home/even/mapserver/git/mapserver/mapparser.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 190 "/home/even/mapserver/git/mapserver/mapparser.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 47 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 415 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 50 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 7 /* YYNRULES -- Number of rules. */ #define YYNRULES 82 /* YYNRULES -- Number of states. */ #define YYNSTATES 201 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 295 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 44, 2, 2, 47, 48, 42, 40, 49, 41, 2, 43, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 45 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 4, 6, 8, 10, 12, 16, 20, 24, 28, 32, 36, 40, 44, 47, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 196, 200, 204, 208, 212, 216, 220, 223, 227, 232, 237, 244, 246, 250, 257, 264, 271, 278, 285, 290, 297, 306, 317, 319, 323, 327, 334, 339, 341 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 51, 0, -1, -1, 52, -1, 53, -1, 55, -1, 54, -1, 52, 7, 52, -1, 52, 8, 52, -1, 52, 7, 53, -1, 52, 8, 53, -1, 53, 7, 52, -1, 53, 8, 52, -1, 53, 7, 53, -1, 53, 8, 53, -1, 9, 52, -1, 9, 53, -1, 55, 19, 55, -1, 55, 10, 55, -1, 53, 18, 53, -1, 53, 17, 53, -1, 53, 15, 53, -1, 53, 16, 53, -1, 53, 13, 53, -1, 53, 14, 53, -1, 47, 52, 48, -1, 55, 18, 55, -1, 55, 17, 55, -1, 55, 15, 55, -1, 55, 16, 55, -1, 55, 13, 55, -1, 55, 14, 55, -1, 56, 18, 56, -1, 56, 17, 56, -1, 56, 15, 56, -1, 56, 16, 56, -1, 56, 13, 56, -1, 56, 14, 56, -1, 55, 12, 55, -1, 53, 12, 55, -1, 53, 11, 53, -1, 55, 11, 55, -1, 56, 11, 56, -1, 54, 18, 54, -1, 54, 28, 54, -1, 54, 27, 54, -1, 54, 26, 54, -1, 54, 25, 54, -1, 54, 24, 54, -1, 54, 23, 54, -1, 54, 22, 54, -1, 54, 20, 54, -1, 54, 21, 54, -1, 3, -1, 47, 53, 48, -1, 53, 40, 53, -1, 53, 41, 53, -1, 53, 42, 53, -1, 53, 44, 53, -1, 53, 43, 53, -1, 41, 53, -1, 53, 46, 53, -1, 31, 47, 55, 48, -1, 32, 47, 54, 48, -1, 29, 47, 53, 49, 53, 48, -1, 6, -1, 47, 54, 48, -1, 39, 47, 54, 49, 53, 48, -1, 38, 47, 54, 49, 54, 48, -1, 37, 47, 54, 49, 53, 48, -1, 36, 47, 54, 49, 53, 48, -1, 35, 47, 54, 49, 53, 48, -1, 34, 47, 54, 48, -1, 34, 47, 54, 49, 53, 48, -1, 34, 47, 54, 49, 53, 49, 53, 48, -1, 34, 47, 54, 49, 53, 49, 53, 49, 55, 48, -1, 4, -1, 47, 55, 48, -1, 55, 40, 55, -1, 33, 47, 53, 49, 55, 48, -1, 30, 47, 55, 48, -1, 5, -1, 47, 56, 48, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 65, 65, 66, 79, 93, 106, 117, 125, 134, 142, 151, 159, 168, 176, 185, 186, 187, 202, 217, 223, 229, 235, 241, 247, 253, 254, 262, 270, 279, 287, 295, 303, 309, 315, 321, 327, 333, 339, 360, 381, 387, 395, 402, 413, 424, 435, 446, 457, 468, 479, 490, 500, 512, 513, 514, 515, 516, 517, 518, 525, 526, 527, 528, 536, 539, 540, 541, 551, 561, 571, 581, 591, 601, 611, 621, 634, 635, 636, 640, 644, 650, 651 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "NUMBER", "STRING", "TIME", "SHAPE", "OR", "AND", "NOT", "IRE", "IEQ", "IN", "GE", "LE", "GT", "LT", "NE", "EQ", "RE", "DWITHIN", "BEYOND", "CONTAINS", "WITHIN", "CROSSES", "OVERLAPS", "TOUCHES", "DISJOINT", "INTERSECTS", "ROUND", "COMMIFY", "LENGTH", "AREA", "TOSTRING", "SMOOTHSIA", "GENERALIZE", "SIMPLIFYPT", "SIMPLIFY", "DIFFERENCE", "YYBUFFER", "'+'", "'-'", "'*'", "'/'", "'%'", "NEG", "'^'", "'('", "')'", "','", "$accept", "input", "logical_exp", "math_exp", "shape_exp", "string_exp", "time_exp", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 43, 45, 42, 47, 37, 295, 94, 40, 41, 44 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 50, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 2, 3, 4, 4, 6, 1, 3, 6, 6, 6, 6, 6, 4, 6, 8, 10, 1, 3, 3, 6, 4, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 53, 76, 81, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 6, 5, 0, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 54, 66, 77, 82, 7, 9, 8, 10, 11, 13, 12, 14, 40, 39, 23, 24, 21, 22, 20, 19, 55, 56, 57, 59, 58, 61, 43, 51, 52, 50, 49, 48, 47, 46, 45, 44, 18, 41, 38, 30, 31, 28, 29, 27, 26, 17, 78, 0, 42, 36, 37, 34, 35, 33, 32, 0, 0, 80, 62, 0, 63, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 79, 73, 0, 71, 70, 69, 68, 67, 0, 74, 0, 0, 75 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 19, 20, 21, 27, 28, 24 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -46 static const yytype_int16 yypact[] = { 85, -46, -46, -46, -46, 85, -45, -30, -24, -21, -8, 26, 40, 46, 78, 80, 81, 13, 85, 21, -3, 205, 293, 272, 253, -46, 263, 293, 272, 13, -1, -1, 167, 13, 167, 167, 167, 167, 167, 167, 13, 2, 27, 145, 274, 225, 120, -46, 85, 85, 85, 85, 13, -1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, -4, -4, -4, -4, -4, -4, 304, -1, -26, -20, 167, 82, 314, -11, 90, 101, 102, 105, 106, -33, -46, -46, -46, -46, -46, 121, 216, -46, 263, 121, 216, -46, 263, 369, 124, 369, 369, 369, 369, 369, 369, 61, 61, 2, 2, 2, 2, -46, -46, -46, -46, -46, -46, -46, -46, -46, -46, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, -46, -4, -46, -46, -46, -46, -46, -46, -46, 13, -7, -46, -46, 128, -46, -1, -46, 13, 13, 13, 13, 167, 13, 129, 324, 126, 283, 333, 342, 351, 130, 360, -46, -46, -46, 13, -46, -46, -46, -46, -46, 294, -46, -1, 127, -46 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -46, -46, 1, 7, 74, 0, 9 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { 23, 3, 29, 2, 48, 49, 25, 60, 61, 62, 63, 64, 26, 65, 86, 109, 1, 30, 45, 42, 86, 47, 166, 31, 41, 43, 32, 46, 167, 7, 96, 97, 10, 86, 48, 49, 94, 171, 172, 33, 100, 111, 6, 156, 8, 9, 95, 107, 65, 113, 115, 117, 119, 122, 17, 114, 116, 118, 120, 121, 40, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 34, 22, 108, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 35, 1, 2, 3, 4, 44, 36, 5, 165, 157, 158, 159, 160, 161, 162, 163, 62, 63, 64, 99, 65, 101, 102, 103, 104, 105, 106, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 37, 17, 38, 39, 49, 169, 87, 18, 88, 89, 90, 91, 92, 93, 173, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 174, 175, 50, 51, 176, 177, 52, 53, 54, 55, 56, 57, 58, 59, 86, 178, 86, 86, 112, 0, 180, 179, 168, 4, 188, 200, 110, 112, 194, 181, 182, 183, 184, 0, 186, 60, 61, 62, 63, 64, 0, 65, 0, 109, 0, 0, 0, 196, 199, 0, 0, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 50, 51, 98, 0, 52, 53, 54, 55, 56, 57, 58, 59, 51, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 60, 61, 62, 63, 64, 185, 65, 0, 0, 0, 0, 60, 61, 62, 63, 64, 0, 65, 0, 87, 86, 88, 89, 90, 91, 92, 93, 0, 111, 52, 53, 54, 55, 56, 57, 58, 59, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 66, 0, 67, 68, 69, 70, 71, 72, 73, 74, 75, 60, 61, 62, 63, 64, 0, 65, 0, 66, 86, 67, 68, 69, 70, 71, 72, 73, 74, 75, 110, 60, 61, 62, 63, 64, 0, 65, 0, 189, 190, 0, 60, 61, 62, 63, 64, 0, 65, 0, 197, 198, 60, 61, 62, 63, 64, 0, 65, 0, 0, 164, 60, 61, 62, 63, 64, 0, 65, 0, 0, 170, 60, 61, 62, 63, 64, 0, 65, 0, 187, 60, 61, 62, 63, 64, 0, 65, 0, 191, 60, 61, 62, 63, 64, 0, 65, 0, 192, 60, 61, 62, 63, 64, 0, 65, 0, 193, 60, 61, 62, 63, 64, 0, 65, 0, 195, 60, 61, 62, 63, 64, 0, 65 }; static const yytype_int16 yycheck[] = { 0, 5, 47, 4, 7, 8, 5, 40, 41, 42, 43, 44, 5, 46, 40, 48, 3, 47, 18, 18, 40, 0, 48, 47, 17, 18, 47, 18, 48, 30, 30, 31, 33, 40, 7, 8, 29, 48, 49, 47, 33, 48, 29, 47, 31, 32, 47, 40, 46, 48, 49, 50, 51, 53, 41, 48, 49, 50, 51, 52, 47, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 47, 0, 48, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 47, 3, 4, 5, 6, 18, 47, 9, 95, 87, 88, 89, 90, 91, 92, 93, 42, 43, 44, 32, 46, 34, 35, 36, 37, 38, 39, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 47, 41, 47, 47, 8, 48, 11, 47, 13, 14, 15, 16, 17, 18, 49, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 49, 49, 7, 8, 49, 49, 11, 12, 13, 14, 15, 16, 17, 18, 40, 156, 40, 40, 48, -1, 170, 164, 98, 6, 48, 48, 48, 48, 48, 172, 173, 174, 175, -1, 177, 40, 41, 42, 43, 44, -1, 46, -1, 48, -1, -1, -1, 190, 198, -1, -1, 34, 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, 7, 8, 47, -1, 11, 12, 13, 14, 15, 16, 17, 18, 8, -1, -1, 11, 12, 13, 14, 15, 16, 17, 18, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 40, 41, 42, 43, 44, 176, 46, -1, -1, -1, -1, 40, 41, 42, 43, 44, -1, 46, -1, 11, 40, 13, 14, 15, 16, 17, 18, -1, 48, 11, 12, 13, 14, 15, 16, 17, 18, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 18, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, 40, 41, 42, 43, 44, -1, 46, -1, 18, 40, 20, 21, 22, 23, 24, 25, 26, 27, 28, 48, 40, 41, 42, 43, 44, -1, 46, -1, 48, 49, -1, 40, 41, 42, 43, 44, -1, 46, -1, 48, 49, 40, 41, 42, 43, 44, -1, 46, -1, -1, 49, 40, 41, 42, 43, 44, -1, 46, -1, -1, 49, 40, 41, 42, 43, 44, -1, 46, -1, 48, 40, 41, 42, 43, 44, -1, 46, -1, 48, 40, 41, 42, 43, 44, -1, 46, -1, 48, 40, 41, 42, 43, 44, -1, 46, -1, 48, 40, 41, 42, 43, 44, -1, 46, -1, 48, 40, 41, 42, 43, 44, -1, 46 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 4, 5, 6, 9, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 41, 47, 51, 52, 53, 54, 55, 56, 52, 53, 54, 55, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 53, 52, 53, 54, 55, 56, 0, 7, 8, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18, 40, 41, 42, 43, 44, 46, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 40, 11, 13, 14, 15, 16, 17, 18, 53, 47, 55, 55, 47, 54, 53, 54, 54, 54, 54, 54, 54, 53, 48, 48, 48, 48, 48, 52, 53, 52, 53, 52, 53, 52, 53, 53, 55, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 47, 56, 56, 56, 56, 56, 56, 56, 49, 55, 48, 48, 54, 48, 49, 48, 49, 49, 49, 49, 49, 49, 56, 53, 55, 53, 53, 53, 53, 54, 53, 48, 48, 48, 49, 48, 48, 48, 48, 48, 53, 48, 49, 55, 48 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (p, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else # define YYLEX yylex (&yylval, p) #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value, p); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parseObj *p) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep, p) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; parseObj *p; #endif { if (!yyvaluep) return; YYUSE (p); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parseObj *p) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep, p) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; parseObj *p; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep, p); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule, parseObj *p) #else static void yy_reduce_print (yyvsp, yyrule, p) YYSTYPE *yyvsp; int yyrule; parseObj *p; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) , p); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule, p); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parseObj *p) #else static void yydestruct (yymsg, yytype, yyvaluep, p) const char *yymsg; int yytype; YYSTYPE *yyvaluep; parseObj *p; #endif { YYUSE (yyvaluep); YYUSE (p); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (parseObj *p); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (parseObj *p) #else int yyparse (p) parseObj *p; #endif #endif { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 3: /* Line 1455 of yacc.c */ #line 66 "/home/even/mapserver/git/mapserver/mapparser.y" { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): p->result.intval = (yyvsp[(1) - (1)].intval); break; case(MS_PARSE_TYPE_STRING): if((yyvsp[(1) - (1)].intval)) p->result.strval = strdup("true"); else p->result.strval = strdup("false"); break; } ;} break; case 4: /* Line 1455 of yacc.c */ #line 79 "/home/even/mapserver/git/mapserver/mapparser.y" { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if((yyvsp[(1) - (1)].dblval) != 0) p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = (char *)malloc(64); /* large enough for a double */ snprintf(p->result.strval, 64, "%g", (yyvsp[(1) - (1)].dblval)); break; } ;} break; case 5: /* Line 1455 of yacc.c */ #line 93 "/home/even/mapserver/git/mapserver/mapparser.y" { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if((yyvsp[(1) - (1)].strval)) /* string is not NULL */ p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = (yyvsp[(1) - (1)].strval); // strdup($1); break; } ;} break; case 6: /* Line 1455 of yacc.c */ #line 106 "/home/even/mapserver/git/mapserver/mapparser.y" { switch(p->type) { case(MS_PARSE_TYPE_SHAPE): p->result.shpval = (yyvsp[(1) - (1)].shpval); p->result.shpval->scratch = MS_FALSE; break; } ;} break; case 7: /* Line 1455 of yacc.c */ #line 117 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else if((yyvsp[(3) - (3)].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 8: /* Line 1455 of yacc.c */ #line 125 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].intval) == MS_TRUE) { if((yyvsp[(3) - (3)].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; ;} break; case 9: /* Line 1455 of yacc.c */ #line 134 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else if((yyvsp[(3) - (3)].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 10: /* Line 1455 of yacc.c */ #line 142 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].intval) == MS_TRUE) { if((yyvsp[(3) - (3)].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; ;} break; case 11: /* Line 1455 of yacc.c */ #line 151 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) != 0) (yyval.intval) = MS_TRUE; else if((yyvsp[(3) - (3)].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 12: /* Line 1455 of yacc.c */ #line 159 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) != 0) { if((yyvsp[(3) - (3)].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; ;} break; case 13: /* Line 1455 of yacc.c */ #line 168 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) != 0) (yyval.intval) = MS_TRUE; else if((yyvsp[(3) - (3)].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 14: /* Line 1455 of yacc.c */ #line 176 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) != 0) { if((yyvsp[(3) - (3)].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; ;} break; case 15: /* Line 1455 of yacc.c */ #line 185 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.intval) = !(yyvsp[(2) - (2)].intval); ;} break; case 16: /* Line 1455 of yacc.c */ #line 186 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.intval) = !(yyvsp[(2) - (2)].dblval); ;} break; case 17: /* Line 1455 of yacc.c */ #line 187 "/home/even/mapserver/git/mapserver/mapparser.y" { ms_regex_t re; if(ms_regcomp(&re, (yyvsp[(3) - (3)].strval), MS_REG_EXTENDED|MS_REG_NOSUB) != 0) (yyval.intval) = MS_FALSE; if(ms_regexec(&re, (yyvsp[(1) - (3)].strval), 0, NULL, 0) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ms_regfree(&re); free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 18: /* Line 1455 of yacc.c */ #line 202 "/home/even/mapserver/git/mapserver/mapparser.y" { ms_regex_t re; if(ms_regcomp(&re, (yyvsp[(3) - (3)].strval), MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) (yyval.intval) = MS_FALSE; if(ms_regexec(&re, (yyvsp[(1) - (3)].strval), 0, NULL, 0) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ms_regfree(&re); free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 19: /* Line 1455 of yacc.c */ #line 217 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) == (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 20: /* Line 1455 of yacc.c */ #line 223 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) != (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 21: /* Line 1455 of yacc.c */ #line 229 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) > (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 22: /* Line 1455 of yacc.c */ #line 235 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) < (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 23: /* Line 1455 of yacc.c */ #line 241 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) >= (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 24: /* Line 1455 of yacc.c */ #line 247 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) <= (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 25: /* Line 1455 of yacc.c */ #line 253 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.intval) = (yyvsp[(2) - (3)].intval); ;} break; case 26: /* Line 1455 of yacc.c */ #line 254 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 27: /* Line 1455 of yacc.c */ #line 262 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 28: /* Line 1455 of yacc.c */ #line 270 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) > 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; /* printf("Not freeing: %s >= %s\n",$1, $3); */ free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 29: /* Line 1455 of yacc.c */ #line 279 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) < 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 30: /* Line 1455 of yacc.c */ #line 287 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) >= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 31: /* Line 1455 of yacc.c */ #line 295 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) <= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 32: /* Line 1455 of yacc.c */ #line 303 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 33: /* Line 1455 of yacc.c */ #line 309 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 34: /* Line 1455 of yacc.c */ #line 315 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) > 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 35: /* Line 1455 of yacc.c */ #line 321 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) < 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 36: /* Line 1455 of yacc.c */ #line 327 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) >= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 37: /* Line 1455 of yacc.c */ #line 333 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) <= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 38: /* Line 1455 of yacc.c */ #line 339 "/home/even/mapserver/git/mapserver/mapparser.y" { char *delim,*bufferp; (yyval.intval) = MS_FALSE; bufferp=(yyvsp[(3) - (3)].strval); while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if(strcmp((yyvsp[(1) - (3)].strval),bufferp) == 0) { (yyval.intval) = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if((yyval.intval)==MS_FALSE && strcmp((yyvsp[(1) - (3)].strval),bufferp) == 0) // test for last (or only) item (yyval.intval) = MS_TRUE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 39: /* Line 1455 of yacc.c */ #line 360 "/home/even/mapserver/git/mapserver/mapparser.y" { char *delim,*bufferp; (yyval.intval) = MS_FALSE; bufferp=(yyvsp[(3) - (3)].strval); while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if((yyvsp[(1) - (3)].dblval) == atof(bufferp)) { (yyval.intval) = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if((yyvsp[(1) - (3)].dblval) == atof(bufferp)) // is this test necessary? (yyval.intval) = MS_TRUE; free((yyvsp[(3) - (3)].strval)); ;} break; case 40: /* Line 1455 of yacc.c */ #line 381 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(1) - (3)].dblval) == (yyvsp[(3) - (3)].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 41: /* Line 1455 of yacc.c */ #line 387 "/home/even/mapserver/git/mapserver/mapparser.y" { if(strcasecmp((yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 42: /* Line 1455 of yacc.c */ #line 395 "/home/even/mapserver/git/mapserver/mapparser.y" { if(msTimeCompare(&((yyvsp[(1) - (3)].tmval)), &((yyvsp[(3) - (3)].tmval))) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 43: /* Line 1455 of yacc.c */ #line 402 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSEquals((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Equals (EQ or ==) operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 44: /* Line 1455 of yacc.c */ #line 413 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSIntersects((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Intersects operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 45: /* Line 1455 of yacc.c */ #line 424 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSDisjoint((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Disjoint operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 46: /* Line 1455 of yacc.c */ #line 435 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSTouches((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Touches operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 47: /* Line 1455 of yacc.c */ #line 446 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSOverlaps((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Overlaps operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 48: /* Line 1455 of yacc.c */ #line 457 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSCrosses((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Crosses operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 49: /* Line 1455 of yacc.c */ #line 468 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSWithin((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Within operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 50: /* Line 1455 of yacc.c */ #line 479 "/home/even/mapserver/git/mapserver/mapparser.y" { int rval; rval = msGEOSContains((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(rval == -1) { yyerror(p, "Contains operator failed."); return(-1); } else (yyval.intval) = rval; ;} break; case 51: /* Line 1455 of yacc.c */ #line 490 "/home/even/mapserver/git/mapserver/mapparser.y" { double d; d = msGEOSDistance((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(d == 0.0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 52: /* Line 1455 of yacc.c */ #line 500 "/home/even/mapserver/git/mapserver/mapparser.y" { double d; d = msGEOSDistance((yyvsp[(1) - (3)].shpval), (yyvsp[(3) - (3)].shpval)); if((yyvsp[(1) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(1) - (3)].shpval)); if((yyvsp[(3) - (3)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (3)].shpval)); if(d > 0.0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ;} break; case 54: /* Line 1455 of yacc.c */ #line 513 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (yyvsp[(2) - (3)].dblval); ;} break; case 55: /* Line 1455 of yacc.c */ #line 514 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (yyvsp[(1) - (3)].dblval) + (yyvsp[(3) - (3)].dblval); ;} break; case 56: /* Line 1455 of yacc.c */ #line 515 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (yyvsp[(1) - (3)].dblval) - (yyvsp[(3) - (3)].dblval); ;} break; case 57: /* Line 1455 of yacc.c */ #line 516 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (yyvsp[(1) - (3)].dblval) * (yyvsp[(3) - (3)].dblval); ;} break; case 58: /* Line 1455 of yacc.c */ #line 517 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (int)(yyvsp[(1) - (3)].dblval) % (int)(yyvsp[(3) - (3)].dblval); ;} break; case 59: /* Line 1455 of yacc.c */ #line 518 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(3) - (3)].dblval) == 0.0) { yyerror(p, "Division by zero."); return(-1); } else (yyval.dblval) = (yyvsp[(1) - (3)].dblval) / (yyvsp[(3) - (3)].dblval); ;} break; case 60: /* Line 1455 of yacc.c */ #line 525 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (yyvsp[(2) - (2)].dblval); ;} break; case 61: /* Line 1455 of yacc.c */ #line 526 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = pow((yyvsp[(1) - (3)].dblval), (yyvsp[(3) - (3)].dblval)); ;} break; case 62: /* Line 1455 of yacc.c */ #line 527 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = strlen((yyvsp[(3) - (4)].strval)); ;} break; case 63: /* Line 1455 of yacc.c */ #line 528 "/home/even/mapserver/git/mapserver/mapparser.y" { if((yyvsp[(3) - (4)].shpval)->type != MS_SHAPE_POLYGON) { yyerror(p, "Area can only be computed for polygon shapes."); return(-1); } (yyval.dblval) = msGetPolygonArea((yyvsp[(3) - (4)].shpval)); if((yyvsp[(3) - (4)].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[(3) - (4)].shpval)); ;} break; case 64: /* Line 1455 of yacc.c */ #line 536 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.dblval) = (MS_NINT((yyvsp[(3) - (6)].dblval)/(yyvsp[(5) - (6)].dblval)))*(yyvsp[(5) - (6)].dblval); ;} break; case 66: /* Line 1455 of yacc.c */ #line 540 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.shpval) = (yyvsp[(2) - (3)].shpval); ;} break; case 67: /* Line 1455 of yacc.c */ #line 541 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msGEOSBuffer((yyvsp[(3) - (6)].shpval), (yyvsp[(5) - (6)].dblval)); if(!s) { yyerror(p, "Executing buffer failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 68: /* Line 1455 of yacc.c */ #line 551 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msGEOSDifference((yyvsp[(3) - (6)].shpval), (yyvsp[(5) - (6)].shpval)); if(!s) { yyerror(p, "Executing difference failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 69: /* Line 1455 of yacc.c */ #line 561 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msGEOSSimplify((yyvsp[(3) - (6)].shpval), (yyvsp[(5) - (6)].dblval)); if(!s) { yyerror(p, "Executing simplify failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 70: /* Line 1455 of yacc.c */ #line 571 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msGEOSTopologyPreservingSimplify((yyvsp[(3) - (6)].shpval), (yyvsp[(5) - (6)].dblval)); if(!s) { yyerror(p, "Executing simplifypt failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 71: /* Line 1455 of yacc.c */ #line 581 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msGeneralize((yyvsp[(3) - (6)].shpval), (yyvsp[(5) - (6)].dblval)); if(!s) { yyerror(p, "Executing generalize failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 72: /* Line 1455 of yacc.c */ #line 591 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msSmoothShapeSIA((yyvsp[(3) - (4)].shpval), 3, 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 73: /* Line 1455 of yacc.c */ #line 601 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msSmoothShapeSIA((yyvsp[(3) - (6)].shpval), (yyvsp[(5) - (6)].dblval), 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 74: /* Line 1455 of yacc.c */ #line 611 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msSmoothShapeSIA((yyvsp[(3) - (8)].shpval), (yyvsp[(5) - (8)].dblval), (yyvsp[(7) - (8)].dblval), NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 75: /* Line 1455 of yacc.c */ #line 621 "/home/even/mapserver/git/mapserver/mapparser.y" { shapeObj *s; s = msSmoothShapeSIA((yyvsp[(3) - (10)].shpval), (yyvsp[(5) - (10)].dblval), (yyvsp[(7) - (10)].dblval), (yyvsp[(9) - (10)].strval)); free((yyvsp[(9) - (10)].strval)); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; ;} break; case 77: /* Line 1455 of yacc.c */ #line 635 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.strval) = (yyvsp[(2) - (3)].strval); ;} break; case 78: /* Line 1455 of yacc.c */ #line 636 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.strval) = (char *)malloc(strlen((yyvsp[(1) - (3)].strval)) + strlen((yyvsp[(3) - (3)].strval)) + 1); sprintf((yyval.strval), "%s%s", (yyvsp[(1) - (3)].strval), (yyvsp[(3) - (3)].strval)); free((yyvsp[(1) - (3)].strval)); free((yyvsp[(3) - (3)].strval)); ;} break; case 79: /* Line 1455 of yacc.c */ #line 640 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.strval) = (char *) malloc(strlen((yyvsp[(5) - (6)].strval)) + 64); /* Plenty big? Should use snprintf below... */ sprintf((yyval.strval), (yyvsp[(5) - (6)].strval), (yyvsp[(3) - (6)].dblval)); ;} break; case 80: /* Line 1455 of yacc.c */ #line 644 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyvsp[(3) - (4)].strval) = msCommifyString((yyvsp[(3) - (4)].strval)); (yyval.strval) = (yyvsp[(3) - (4)].strval); ;} break; case 82: /* Line 1455 of yacc.c */ #line 651 "/home/even/mapserver/git/mapserver/mapparser.y" { (yyval.tmval) = (yyvsp[(2) - (3)].tmval); ;} break; /* Line 1455 of yacc.c */ #line 2620 "/home/even/mapserver/git/mapserver/mapparser.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (p, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (p, yymsg); } else { yyerror (p, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval, p); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp, p); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (p, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, p); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, p); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* Line 1675 of yacc.c */ #line 654 "/home/even/mapserver/git/mapserver/mapparser.y" /* ** Any extra C functions */ int yylex(YYSTYPE *lvalp, parseObj *p) { int token; if(p->expr->curtoken == NULL) return(0); /* done */ // fprintf(stderr, "in yylex() - curtoken=%d...\n", p->expr->curtoken->token); token = p->expr->curtoken->token; /* may override */ switch(p->expr->curtoken->token) { case MS_TOKEN_LITERAL_NUMBER: token = NUMBER; (*lvalp).dblval = p->expr->curtoken->tokenval.dblval; break; case MS_TOKEN_LITERAL_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->expr->curtoken->tokenval.shpval)); (*lvalp).shpval = p->expr->curtoken->tokenval.shpval; break; case MS_TOKEN_LITERAL_STRING: // printf("token value = %s\n", p->expr->curtoken->tokenval.strval); token = STRING; (*lvalp).strval = strdup(p->expr->curtoken->tokenval.strval); break; case MS_TOKEN_LITERAL_TIME: token = TIME; (*lvalp).tmval = p->expr->curtoken->tokenval.tmval; break; case MS_TOKEN_COMPARISON_EQ: token = EQ; break; case MS_TOKEN_COMPARISON_IEQ: token = IEQ; break; case MS_TOKEN_COMPARISON_NE: token = NE; break; case MS_TOKEN_COMPARISON_LT: token = LT; break; case MS_TOKEN_COMPARISON_GT: token = GT; break; case MS_TOKEN_COMPARISON_LE: token = LE; break; case MS_TOKEN_COMPARISON_GE: token = GE; break; case MS_TOKEN_COMPARISON_RE: token = RE; break; case MS_TOKEN_COMPARISON_IRE: token = IRE; break; case MS_TOKEN_COMPARISON_INTERSECTS: token = INTERSECTS; break; case MS_TOKEN_COMPARISON_DISJOINT: token = DISJOINT; break; case MS_TOKEN_COMPARISON_TOUCHES: token = TOUCHES; break; case MS_TOKEN_COMPARISON_OVERLAPS: token = OVERLAPS; break; case MS_TOKEN_COMPARISON_CROSSES: token = CROSSES; break; case MS_TOKEN_COMPARISON_WITHIN: token = WITHIN; break; case MS_TOKEN_COMPARISON_CONTAINS: token = CONTAINS; break; case MS_TOKEN_COMPARISON_BEYOND: token = BEYOND; break; case MS_TOKEN_COMPARISON_DWITHIN: token = DWITHIN; break; case MS_TOKEN_LOGICAL_AND: token = AND; break; case MS_TOKEN_LOGICAL_OR: token = OR; break; case MS_TOKEN_LOGICAL_NOT: token = NOT; break; case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: token = NUMBER; (*lvalp).dblval = atof(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_STRING: token = STRING; (*lvalp).strval = strdup(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->shape)); (*lvalp).shpval = p->shape; break; case MS_TOKEN_BINDING_MAP_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval; break; case MS_TOKEN_BINDING_DATA_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval2; break; case MS_TOKEN_BINDING_TIME: token = TIME; msTimeInit(&((*lvalp).tmval)); if(msParseTime(p->shape->values[p->expr->curtoken->tokenval.bindval.index], &((*lvalp).tmval)) != MS_TRUE) { yyerror(p, "Parsing time value failed."); return(-1); } break; case MS_TOKEN_FUNCTION_AREA: token = AREA; break; case MS_TOKEN_FUNCTION_LENGTH: token = LENGTH; break; case MS_TOKEN_FUNCTION_TOSTRING: token = TOSTRING; break; case MS_TOKEN_FUNCTION_COMMIFY: token = COMMIFY; break; case MS_TOKEN_FUNCTION_ROUND: token = ROUND; break; case MS_TOKEN_FUNCTION_BUFFER: token = YYBUFFER; break; case MS_TOKEN_FUNCTION_DIFFERENCE: token = DIFFERENCE; break; case MS_TOKEN_FUNCTION_SIMPLIFY: token = SIMPLIFY; break; case MS_TOKEN_FUNCTION_SIMPLIFYPT: token = SIMPLIFYPT; break; case MS_TOKEN_FUNCTION_GENERALIZE: token = GENERALIZE; break; case MS_TOKEN_FUNCTION_SMOOTHSIA: token = SMOOTHSIA; break; default: break; } p->expr->curtoken = p->expr->curtoken->next; /* re-position */ return(token); } int yyerror(parseObj *p, const char *s) { msSetError(MS_PARSEERR, "%s", "yyparse()", s); return(0); } mapserver-6.4.1/run_code_coverage_upload.sh0000755002461700001440000000303312261257215020667 0ustar tbonfortusers#!/bin/bash lcov --directory . --capture --output-file mapserver.info cp /usr/bin/genhtml . # to remove date and occurences number, so that only real differences show up patch -p0 < genhtml.patch ./genhtml -o ./mapserver_coverage_html --num-spaces 2 mapserver.info # build the chunks of the private key together # This is a bashism ! echo -n $id_rsa_{00..30} >> ~/.ssh/id_rsa-upstream-msautotest-coverage-results_base64 base64 --decode --ignore-garbage ~/.ssh/id_rsa-upstream-msautotest-coverage-results_base64 > ~/.ssh/id_rsa-upstream-msautotest-coverage-results chmod 600 ~/.ssh/id_rsa-upstream-msautotest-coverage-results echo "Host foo.github.com" >> ~/.ssh/config echo " StrictHostKeyChecking no" >> ~/.ssh/config echo " Hostname github.com" >> ~/.ssh/config echo " IdentityFile ~/.ssh/id_rsa-upstream-msautotest-coverage-results" >> ~/.ssh/config mkdir msautotest-coverage-results cd msautotest-coverage-results git init git config user.email "mapserverbot@mapserver.bot" git config user.name "MapServer coveragebot" git config push.default matching git remote add origin git@foo.github.com:mapserver/coverage.git git fetch git pull origin master rm -rf * cp -r ../mapserver_coverage_html . echo "Results of coverage of MapServer msautotest" > README.md echo "See http://rawgithub.com/mapserver/coverage/master/mapserver_coverage_html/home/travis/build/mapserver/mapserver/index.html" >> README.md git add -A git commit -m "update with results of commit https://github.com/mapserver/mapserver/commit/$TRAVIS_COMMIT" git push origin master mapserver-6.4.1/mapsde.c0000644002461700001440000021303112261257215014731 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements SDE CONNECTIONTYPE. * Author: Steve Lime and Howard Butler * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include #include #include "mapserver.h" #include "maperror.h" #include "maptime.h" #include "mapthread.h" #ifdef USE_SDE #include /* ESRI SDE Client Includes */ #include #define MS_SDE_MAXBLOBSIZE 1024*50 /* 50 kbytes */ #define MS_SDE_NULLSTRING "" #define MS_SDE_SHAPESTRING "" #define MS_SDE_TIMEFMTSIZE 128 /* bytes */ #define MS_SDE_TIMEFMT "%H:%M:%S %m/%d/%Y" #define MS_SDE_ROW_ID_COLUMN "SE_ROW_ID" typedef struct { SE_CONNECTION connection; SE_STREAM stream; } msSDEConnPoolInfo; typedef struct { msSDEConnPoolInfo *connPoolInfo; SE_CONNECTION connection; SE_LAYERINFO layerinfo; SE_COORDREF coordref; SE_STREAM stream; SE_INT32 state_id; char *table; char *column; char *row_id_column; char *join_table; rectObj* extent; SE_COLUMN_DEF *basedefs; SE_COLUMN_DEF *joindefs; short *nBaseColumns; short *nJoinColumns; int bBigEndian; } msSDELayerInfo; typedef struct { SE_INT32 layerId; char *table; char *column; char *connection; } layerId; /* * Layer ID caching section. */ static int lcacheCount = 0; static int lcacheMax = 0; static layerId *lcache = NULL; #endif /* -------------------------------------------------------------------- */ /* msSDELayerIsOpen */ /* -------------------------------------------------------------------- */ /* Returns MS_TRUE if layer is already opened, MS_FALSE otherwise */ /* -------------------------------------------------------------------- */ int msSDELayerIsOpen(layerObj *layer) { #ifdef USE_SDE if(layer->layerinfo) return(MS_TRUE); return MS_FALSE; #else msSetError(MS_MISCERR, "SDE support is not available.", "msSDELayerIsOpen()"); return(MS_FALSE); #endif } #ifdef USE_SDE /************************************************************************/ /* Start SDE/MapServer helper functions. */ /* */ /************************************************************************/ /* -------------------------------------------------------------------- */ /* msSDECloseConnection */ /* -------------------------------------------------------------------- */ /* Closes the SDE connection handle, which is given as a callback */ /* function to the connection pooling API */ /* -------------------------------------------------------------------- */ static void msSDECloseConnection( void *conn_handle ) { long status; msSDEConnPoolInfo *poolinfo = conn_handle; if (poolinfo) { if (poolinfo->stream) { SE_stream_free(poolinfo->stream); } if (poolinfo->connection) { status = SE_connection_free_all_locks (poolinfo->connection); if (status == SE_SUCCESS) { SE_connection_free(poolinfo->connection); } } msFree(poolinfo); } } /* -------------------------------------------------------------------- */ /* sde_error */ /* -------------------------------------------------------------------- */ /* Reports more detailed error information from SDE */ /* -------------------------------------------------------------------- */ static void sde_error(long error_code, char *routine, char *sde_routine) { char error_string[SE_MAX_MESSAGE_LENGTH]; error_string[0] = '\0'; SE_error_get_string(error_code, error_string); msSetError( MS_SDEERR, "%s: %s. (%ld)", routine, sde_routine, error_string, error_code); return; } /* -------------------------------------------------------------------- */ /* msSDELayerGetRowIDColumn */ /* -------------------------------------------------------------------- */ /* A helper function to return unique row ID column for */ /* an opened SDE layer. The caller owns the string. */ /* -------------------------------------------------------------------- */ char *msSDELayerGetRowIDColumn(layerObj *layer) { #ifdef USE_SDE SE_INT32 status, column_type; char* column_name; char* full_column_name; char* proc_key; SE_REGINFO registration; msSDELayerInfo *sde=NULL; sde = layer->layerinfo; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerGetRowIDColumn()"); return NULL; } column_name = (char*) msSmallMalloc(SE_QUALIFIED_COLUMN_LEN+1); column_name[0]='\0'; proc_key = msLayerGetProcessingKey(layer,"OBJECTID"); if (proc_key) strcpy(column_name,proc_key); if (proc_key) { if (layer->debug) msDebug("msSDELayerGetRowIDColumn(): Column was manually set to %s\n", column_name); return column_name; } full_column_name = (char*) msSmallMalloc(SE_QUALIFIED_COLUMN_LEN+1); full_column_name[0]='\0'; /* ** if the state_id is the SE_DEFAULT_STATE_ID, we are ** assuming no versioned queries are happening at all ** and we are using the hardcoded row_id column. */ if (sde->state_id == SE_DEFAULT_STATE_ID) { if(layer->debug) { msDebug("msSDELayerGetRowIDColumn(): State ID was " "SE_DEFAULT_STATE_ID, reverting to %s.\n", MS_SDE_ROW_ID_COLUMN); } strcpy(column_name,MS_SDE_ROW_ID_COLUMN); } /* ** if the state_id was not set to SE_DEFAULT_STATE_ID, ** check if the table is registered, and if so, use the ** registration info to tell us what the row_id column is. */ status = SE_reginfo_create (®istration); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerGetRowIDColumn()", "SE_reginfo_create()"); return(NULL); } status = SE_registration_get_info ( sde->connPoolInfo->connection, sde->table, registration); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerGetRowIDColumn()", "SE_registration_get_info()"); SE_reginfo_free(registration); return(NULL); } status= SE_reginfo_get_rowid_column ( registration, column_name, &column_type); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerGetRowIDColumn()", "SE_reginfo_get_rowid_column()"); SE_reginfo_free(registration); return(NULL); } /* Free up the reginfo now that we're done with it */ SE_reginfo_free(registration); /* if the table wasn't registered, return the hard-coded row_id column. */ if (column_type == SE_REGISTRATION_ROW_ID_COLUMN_TYPE_NONE) { if(layer->debug) { msDebug("msSDELayerGetRowIDColumn(): Table was not registered, " "returning %s.\n", MS_SDE_ROW_ID_COLUMN); } strcpy(column_name, MS_SDE_ROW_ID_COLUMN); } proc_key = msLayerGetProcessingKey(layer,"ATTRIBUTE_QUALIFIED"); if (sde->join_table || (proc_key && strcasecmp( proc_key, "TRUE") == 0)) { strcat(full_column_name, sde->table); strcat(full_column_name, "."); strcat(full_column_name, column_name); msFree(column_name); } else { strcpy(full_column_name, column_name); msFree(column_name); } if (full_column_name) { return (full_column_name); } else { msFree(full_column_name); return(msStrdup(MS_SDE_ROW_ID_COLUMN)); } #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerGetRowIDColumn()"); return(NULL); #endif } /* -------------------------------------------------------------------- */ /* msSDELCacheAdd */ /* -------------------------------------------------------------------- */ /* Adds a SDE layer to the global layer cache. */ /* -------------------------------------------------------------------- */ long msSDELCacheAdd( layerObj *layer, SE_LAYERINFO layerinfo, char *tableName, char *columnName, char *connectionString) { layerId *lid = NULL; SE_INT32 status = 0; msAcquireLock( TLOCK_SDE ); if (layer->debug) { msDebug( "%s: Caching id for %s, %s, %s\n", "msSDELCacheAdd()", tableName, columnName, connectionString); } /* Ensure the cache is large enough to hold the new item. */ if(lcacheCount == lcacheMax) { lcacheMax += 10; lcache = (layerId *)realloc(lcache, sizeof(layerId) * lcacheMax); if(lcache == NULL) { msReleaseLock( TLOCK_SDE ); msSetError(MS_MEMERR, NULL, "msSDELCacheAdd()"); return (MS_FAILURE); } } /* Population the new lcache object. */ lid = lcache + lcacheCount; lcacheCount++; status = SE_layerinfo_get_id(layerinfo, &lid->layerId); if(status != SE_SUCCESS) { msReleaseLock( TLOCK_SDE ); sde_error(status, "msSDELCacheAdd()", "SE_layerinfo_get_id()"); return(MS_FAILURE); } lid->table = msStrdup(tableName); lid->column = msStrdup(columnName); lid->connection = msStrdup(connectionString); msReleaseLock( TLOCK_SDE ); return (MS_SUCCESS); } /* -------------------------------------------------------------------- */ /* msSDEGetLayerInfo */ /* -------------------------------------------------------------------- */ /* Get a LayerInfo for the layer. Cached layer is used if it */ /* exists in the cache. */ /* -------------------------------------------------------------------- */ long msSDEGetLayerInfo(layerObj *layer, SE_CONNECTION conn, char *tableName, char *columnName, char *connectionString, SE_LAYERINFO layerinfo) { int i; long status; layerId *lid = NULL; /* If table or column are null, nothing can be done. */ if(tableName == NULL) { msSetError( MS_MISCERR, "Missing table name.\n", "msSDEGetLayerInfo()"); return (MS_FAILURE); } if(columnName == NULL) { msSetError( MS_MISCERR, "Missing column name.\n", "msSDEGetLayerInfo()"); return (MS_FAILURE); } if(connectionString == NULL) { msSetError( MS_MISCERR, "Missing connection string.\n", "msSDEGetLayerInfo()"); return (MS_FAILURE); } if (layer->debug) { msDebug("%s: Looking for layer by %s, %s, %s\n", "msSDEGetLayerInfo()", tableName, columnName, connectionString); } /* Search the lcache for the layer id. */ for(i = 0; i < lcacheCount; i++) { lid = lcache + i; if(strcasecmp(lid->table, tableName) == 0 && strcasecmp(lid->column, columnName) == 0 && strcasecmp(lid->connection, connectionString) == 0) { status = SE_layer_get_info_by_id(conn, lid->layerId, layerinfo); if(status != SE_SUCCESS) { sde_error(status, "msSDEGetLayerInfo()", "SE_layer_get_info()"); return(MS_FAILURE); } if (layer->debug) { msDebug( "%s: Matched layer to id %i.\n", "msSDEGetLayerId()", lid->layerId); } return (MS_SUCCESS); } } if (layer->debug) { msDebug("%s: No cached layerid found.\n", "msSDEGetLayerInfo()"); } /* No matches found, create one. */ status = SE_layer_get_info( conn, tableName, columnName, layerinfo ); if(status != SE_SUCCESS) { sde_error(status, "msSDEGetLayerInfo()", "SE_layer_get_info()"); return(MS_FAILURE); } status = msSDELCacheAdd(layer, layerinfo, tableName, columnName, connectionString); return(MS_SUCCESS); } /* -------------------------------------------------------------------- */ /* sdeShapeCopy */ /* -------------------------------------------------------------------- */ /* Copies a SDE shape into a MapServer shapeObj */ /* -------------------------------------------------------------------- */ static int sdeShapeCopy(SE_SHAPE inshp, shapeObj *outshp) { SE_POINT *points=NULL; SE_ENVELOPE envelope; SE_INT32 type, status; SE_INT32 *part_offsets = NULL; SE_INT32 *subpart_offsets = NULL; SE_INT32 num_parts = -1; SE_INT32 num_subparts = -1; SE_INT32 num_points = -1; lineObj line= {0,NULL}; int i,j,k; status = SE_shape_get_type(inshp, &type); if(status != SE_SUCCESS) { sde_error(status, "sdeShapeCopy()", "SE_shape_get_type()"); return(MS_FAILURE); } switch(type) { case(SG_NIL_SHAPE): return(MS_SUCCESS); /* skip null shapes */ break; case(SG_POINT_SHAPE): case(SG_MULTI_POINT_SHAPE): outshp->type = MS_SHAPE_POINT; break; case(SG_LINE_SHAPE): case(SG_SIMPLE_LINE_SHAPE): case(SG_MULTI_LINE_SHAPE): case(SG_MULTI_SIMPLE_LINE_SHAPE): outshp->type = MS_SHAPE_LINE; break; case(SG_AREA_SHAPE): case(SG_MULTI_AREA_SHAPE): outshp->type = MS_SHAPE_POLYGON; break; default: msSetError( MS_SDEERR, "Unsupported SDE shape type.", "sdeShapeCopy()"); return(MS_FAILURE); } status = SE_shape_get_num_parts (inshp, &num_parts, &num_subparts); if(status != SE_SUCCESS) { sde_error(status, "sdeShapeCopy()", "SE_shape_get_num_parts()"); return(MS_FAILURE); } status = SE_shape_get_num_points (inshp, 0, 0, &num_points); if(status != SE_SUCCESS) { sde_error(status, "sdeShapeCopy()", "SE_shape_get_num_points()"); return(MS_FAILURE); } part_offsets = (SE_INT32 *) msSmallMalloc( (num_parts + 1) * sizeof(SE_INT32)); subpart_offsets = (SE_INT32 *) msSmallMalloc( (num_subparts + 1) * sizeof(SE_INT32)); part_offsets[num_parts] = num_subparts; subpart_offsets[num_subparts] = num_points; points = (SE_POINT *) msSmallMalloc (num_points*sizeof(SE_POINT)); if(!points) { msSetError( MS_MEMERR, "Unable to allocate points array.", "sdeShapeCopy()"); return(MS_FAILURE); } status = SE_shape_get_all_points(inshp, SE_DEFAULT_ROTATION, part_offsets, subpart_offsets, points, NULL, NULL); if(status != SE_SUCCESS) { sde_error(status, "sdeCopyShape()", "SE_shape_get_all_points()"); return(MS_FAILURE); } k = 0; /* overall point counter */ for(i=0; ibounds.minx = envelope.minx; outshp->bounds.miny = envelope.miny; outshp->bounds.maxx = envelope.maxx; outshp->bounds.maxy = envelope.maxy; return(MS_SUCCESS); } /* -------------------------------------------------------------------- */ /* sdeGetRecord */ /* -------------------------------------------------------------------- */ /* Retrieves the current row as setup via the SDE stream query */ /* or row fetch routines. */ /* -------------------------------------------------------------------- */ static int sdeGetRecord(layerObj *layer, shapeObj *shape) { int i; SE_INT32 status; double doubleval; SE_INT32 longval; struct tm dateval; short shortval; /* new gdv */ float floatval; SE_COLUMN_DEF *itemdefs; SE_SHAPE shapeval=0; msSDELayerInfo *sde; SE_BLOB_INFO blobval; #ifdef SE_CLOB_TYPE SE_CLOB_INFO clobval; #endif #ifdef SE_NCLOB_TYPE SE_NCLOB_INFO nclobval; SE_WCHAR* nclobstring; /* null terminated */ #endif #ifdef SE_NSTRING_TYPE SE_WCHAR* wide=NULL; #endif if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "sdeGetRecord()"); return MS_FAILURE; } sde = layer->layerinfo; if(layer->numitems > 0) { shape->numvalues = layer->numitems; shape->values = (char **) malloc (sizeof(char *)*layer->numitems); MS_CHECK_ALLOC(shape->values, sizeof(char *)*layer->numitems, MS_FAILURE); } status = SE_shape_create(NULL, &shapeval); if(status != SE_SUCCESS) { sde_error(status, "sdeGetRecord()", "SE_shape_create()"); return(MS_FAILURE); } itemdefs = layer->iteminfo; for(i=0; inumitems; i++) { /* do something special */ if(strcmp(layer->items[i],sde->row_id_column) == 0) { SE_INT32 shape_index; status = SE_stream_get_integer(sde->connPoolInfo->stream, (short)(i+1), &shape_index); if(status != SE_SUCCESS) { sde_error(status, "sdeGetRecord()", "SE_stream_get_integer()"); return(MS_FAILURE); } shape->index = shape_index; shape->values[i] = (char *)msSmallMalloc(64); /* should be enough */ sprintf(shape->values[i], "%ld", shape->index); continue; } switch(itemdefs[i].sde_type) { case SE_SMALLINT_TYPE: /* changed by gdv */ status = SE_stream_get_smallint(sde->connPoolInfo->stream, (short)(i+1), &shortval); if(status == SE_SUCCESS) shape->values[i] = msLongToString(shortval); else if(status == SE_NULL_VALUE) shape->values[i] = msStrdup(MS_SDE_NULLSTRING); else { sde_error(status, "sdeGetRecord()", "SE_stream_get_smallint()"); return(MS_FAILURE); } break; case SE_INTEGER_TYPE: status = SE_stream_get_integer(sde->connPoolInfo->stream, (short)(i+1), &longval); if(status == SE_SUCCESS) shape->values[i] = msLongToString(longval); else if(status == SE_NULL_VALUE) shape->values[i] = msStrdup(MS_SDE_NULLSTRING); else { sde_error(status, "sdeGetRecord()", "SE_stream_get_integer()"); return(MS_FAILURE); } break; case SE_FLOAT_TYPE: status = SE_stream_get_float(sde->connPoolInfo->stream, (short)(i+1), &floatval); if(status == SE_SUCCESS) shape->values[i] = msDoubleToString(floatval, MS_FALSE); else if(status == SE_NULL_VALUE) shape->values[i] = msStrdup(MS_SDE_NULLSTRING); else { sde_error( status, "sdeGetRecord()", "SE_stream_get_float()"); return(MS_FAILURE); } break; case SE_DOUBLE_TYPE: status = SE_stream_get_double(sde->connPoolInfo->stream, (short) (i+1), &doubleval); if(status == SE_SUCCESS) shape->values[i] = msDoubleToString(doubleval, MS_FALSE); else if(status == SE_NULL_VALUE) shape->values[i] = msStrdup(MS_SDE_NULLSTRING); else { sde_error(status, "sdeGetRecord()", "SE_stream_get_double()"); return(MS_FAILURE); } break; case SE_STRING_TYPE: shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size+1); status = SE_stream_get_string( sde->connPoolInfo->stream, (short) (i+1), shape->values[i]); if(status == SE_NULL_VALUE) shape->values[i][0] = '\0'; /* empty string */ else if(status != SE_SUCCESS) { sde_error( status, "sdeGetRecord()", "SE_stream_get_string()"); return(MS_FAILURE); } break; #ifdef SE_NSTRING_TYPE case SE_NSTRING_TYPE: wide = (SE_WCHAR *)msSmallMalloc(itemdefs[i].size*2*sizeof(SE_WCHAR)+1); memset(wide, 0, itemdefs[i].size*2*sizeof(SE_WCHAR)+1); status = SE_stream_get_nstring( sde->connPoolInfo->stream, (short) (i+1), wide); if(status == SE_NULL_VALUE) { shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size*sizeof(char)+1); shape->values[i][0] = '\0'; /* empty string */ msFree(wide); } else if(status != SE_SUCCESS) { sde_error( status, "sdeGetRecord()", "SE_stream_get_string()"); return(MS_FAILURE); } else { if (sde->bBigEndian) shape->values[i] = msConvertWideStringToUTF8((const wchar_t*) wide, "UTF-16BE"); else shape->values[i] = msConvertWideStringToUTF8((const wchar_t*) wide, "UTF-16LE"); msFree(wide); if (!shape->values[i]) { /* There was an error */ msSetError( MS_SDEERR, "msConvertWideStringToUTF8()==NULL.", "sdeGetRecord()"); shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size*sizeof(char)+1); shape->values[i][0] = '\0'; /* empty string */ } } break; #endif #ifdef SE_UUID_TYPE case SE_UUID_TYPE: shape->values[i] = (char *)msSmallMalloc(itemdefs[i].size+1); status = SE_stream_get_uuid ( sde->connPoolInfo->stream, (short) (i+1), shape->values[i]); if(status == SE_NULL_VALUE) shape->values[i][0] = '\0'; /* empty string */ else if(status != SE_SUCCESS) { sde_error( status, "sdeGetRecord()", "SE_stream_get_uuid()"); return(MS_FAILURE); } break; #endif #ifdef SE_CLOB_TYPE case SE_CLOB_TYPE: memset(&clobval, 0, sizeof(clobval)); /* to prevent from the crash in SE_stream_get_clob */ status = SE_stream_get_clob(sde->connPoolInfo->stream, (short) (i+1), &clobval); if(status == SE_SUCCESS) { shape->values[i] = (char *)msSmallMalloc(sizeof(char)*clobval.clob_length); shape->values[i] = memcpy( shape->values[i], clobval.clob_buffer, clobval.clob_length); SE_clob_free(&clobval); } else if (status == SE_NULL_VALUE) { shape->values[i] = msStrdup(MS_SDE_NULLSTRING); } else { sde_error( status, "sdeGetRecord()", "SE_stream_get_clob()"); return(MS_FAILURE); } break; #endif #ifdef SE_CLOB_TYPE case SE_NCLOB_TYPE: memset(&nclobval, 0, sizeof(nclobval)); /* to prevent from the crash in SE_stream_get_nclob */ status = SE_stream_get_nclob(sde->connPoolInfo->stream, (short) (i+1), &nclobval); if(status == SE_SUCCESS) { /* the returned string is not null-terminated */ nclobstring = (SE_WCHAR*)malloc(sizeof(char)*(nclobval.nclob_length+2)); memcpy(nclobstring, nclobval.nclob_buffer, nclobval.nclob_length); nclobstring[nclobval.nclob_length / 2] = '\0'; if (sde->bBigEndian) shape->values[i] = msConvertWideStringToUTF8((const wchar_t*) nclobstring, "UTF-16BE"); else shape->values[i] = msConvertWideStringToUTF8((const wchar_t*) nclobstring, "UTF-16LE"); if (!shape->values[i]) { /* There was an error */ msSetError( MS_SDEERR, "msConvertWideStringToUTF8()==NULL.", "sdeGetRecord()"); shape->values[i] = (char *)malloc(itemdefs[i].size*sizeof(char)+1); shape->values[i][0] = '\0'; /* empty string */ } SE_nclob_free(&nclobval); msFree(nclobstring); } else if (status == SE_NULL_VALUE) { shape->values[i] = msStrdup(MS_SDE_NULLSTRING); } else { sde_error( status, "sdeGetRecord()", "SE_stream_get_nclob()"); return(MS_FAILURE); } break; #endif case SE_BLOB_TYPE: status = SE_stream_get_blob(sde->connPoolInfo->stream, (short) (i+1), &blobval); if(status == SE_SUCCESS) { shape->values[i] = (char *)msSmallMalloc(sizeof(char)*blobval.blob_length); shape->values[i] = memcpy( shape->values[i], blobval.blob_buffer, blobval.blob_length); SE_blob_free(&blobval); } else if (status == SE_NULL_VALUE) { shape->values[i] = msStrdup(MS_SDE_NULLSTRING); } else { sde_error( status, "sdeGetRecord()", "SE_stream_get_blob()"); return(MS_FAILURE); } break; case SE_DATE_TYPE: status = SE_stream_get_date(sde->connPoolInfo->stream, (short)(i+1), &dateval); if(status == SE_SUCCESS) { shape->values[i] = (char *)msSmallMalloc(sizeof(char)*MS_SDE_TIMEFMTSIZE); strftime( shape->values[i], MS_SDE_TIMEFMTSIZE, MS_SDE_TIMEFMT, &dateval); } else if(status == SE_NULL_VALUE) shape->values[i] = msStrdup(MS_SDE_NULLSTRING); else { sde_error( status, "sdeGetRecord()", "SE_stream_get_date()"); return(MS_FAILURE); } break; case SE_SHAPE_TYPE: status = SE_stream_get_shape(sde->connPoolInfo->stream, (short)(i+1), shapeval); if(status == SE_SUCCESS) shape->values[i] = msStrdup(MS_SDE_SHAPESTRING); else if(status == SE_NULL_VALUE) shape->values[i] = msStrdup(MS_SDE_NULLSTRING); else { sde_error( status, "sdeGetRecord()", "SE_stream_get_shape()"); return(MS_FAILURE); } break; default: msSetError( MS_SDEERR, "Unknown SDE column type.", "sdeGetRecord()"); return(MS_FAILURE); break; } /* switch(itemdefs[i].sde_type) */ } /* for(i=0; inumitems; i++) { */ if(SE_shape_is_nil(shapeval)) return(MS_SUCCESS); /* copy sde shape to a mapserver shape */ status = sdeShapeCopy(shapeval, shape); if(status != MS_SUCCESS) return(MS_FAILURE); /* clean up */ SE_shape_free(shapeval); return(MS_SUCCESS); } static SE_QUERYINFO getSDEQueryInfo(layerObj *layer) { SE_QUERYINFO query_info; long status; msSDELayerInfo *sde=NULL; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "getSDEQueryInfo()"); return(NULL); } sde = layer->layerinfo; /* ** See http://forums.esri.com/Thread.asp?c=2&f=59&t=108929&mc=4#msgid310273 ** SE_queryinfo is a new SDE struct in ArcSDE 8.x that is a bit easier ** (and faster) to use. HCB */ status = SE_queryinfo_create (&query_info); if(status != SE_SUCCESS) { sde_error( status, "getSDEQueryInfo()", "SE_queryinfo_create()"); return(NULL); } /* set the tables -- just one at this point */ status = SE_queryinfo_set_tables ( query_info, 1, (const CHAR **) &(sde->table), NULL); if(status != SE_SUCCESS) { sde_error( status, "getSDEQueryInfo()", "SE_queryinfo_create()"); return(NULL); } /* set the "where" clause */ if(!(layer->filter.string)) /* set to empty string */ status = SE_queryinfo_set_where_clause (query_info, (const CHAR * ) ""); else /* set to the layer's filter.string */ status = SE_queryinfo_set_where_clause (query_info, (const CHAR * ) (layer->filter.string)); if(status != SE_SUCCESS) { sde_error( status, "getSDEQueryInfo()", "SE_queryinfo_set_where_clause()"); return(NULL); } status = SE_queryinfo_set_columns( query_info, layer->numitems, (const char **)layer->items); if(status != SE_SUCCESS) { sde_error( status, "getSDEQueryInfo()", "SE_queryinfo_set_columns()"); return(NULL); } /* Join the spatial and feature tables. If we specify the type of join */ /* we'll query faster than querying all tables individually (old method) */ status = SE_queryinfo_set_query_type (query_info,SE_QUERYTYPE_JSF); if(status != SE_SUCCESS) { sde_error( status, "getSDEQueryInfo()", "SE_queryinfo_set_query_type()"); return(NULL); } return query_info; } static SE_SQL_CONSTRUCT* getSDESQLConstructInfo(layerObj *layer, long* id) { SE_SQL_CONSTRUCT* sql; char *full_filter=NULL; char *pszId=NULL; long status; msSDELayerInfo *sde=NULL; full_filter = (char*) msSmallMalloc((1000+1)*sizeof (char)); full_filter[0] = '\0'; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "getSDESQLConstructInfo()"); return(NULL); } sde = layer->layerinfo; if (!sde->join_table) { msSetError( MS_SDEERR, "Join table is null, we should be using QueryInfo.", "getSDESQLConstructInfo()"); return(NULL); } status = SE_sql_construct_alloc( 2, &sql); if(status != SE_SUCCESS) { sde_error( status, "getSDESQLConstructInfo()", "SE_sql_construct_alloc()"); return(NULL); } strcpy(sql->tables[0], sde->table); /* main table */ strcpy(sql->tables[1], sde->join_table); /* join table */ /* If we were given an ID *and* we have a join, we need to set our FILTER statement to reflect this. */ if ((sde->join_table) && (id != NULL)) { pszId = msLongToString(*id); strcat(full_filter, layer->filter.string); strcat(full_filter, " AND "); strcat(full_filter, sde->row_id_column); strcat(full_filter, "="); strcat(full_filter, pszId); msFree(pszId); sql->where = msStrdup(full_filter); } else { sql->where = layer->filter.string; } msFree(full_filter); if (layer->debug) msDebug("WHERE statement: %s\n", sql->where); return sql; } #endif /************************************************************************/ /* Start SDE/MapServer library functions. */ /* */ /************************************************************************/ /* -------------------------------------------------------------------- */ /* msSDELayerOpen */ /* -------------------------------------------------------------------- */ /* Connects to SDE using the SDE C API. Connections are pooled */ /* using the MapServer pooling API. After a connection is made, */ /* a query stream is created, using the SDE version specified in */ /* the DATA string, or SDE.DEFAULT if not specified. It is */ /* important to note that the SE_CONNECTION is shared across data */ /* layers, but the state_id for a layer's version is different, */ /* even for layers with the same version name. These are *not* */ /* shared across layers. */ /* -------------------------------------------------------------------- */ int msSDELayerOpen(layerObj *layer) { #ifdef USE_SDE long status=-1; int endian_test=1; char **params=NULL; char **data_params=NULL; char *join_table=NULL; int numparams=0; SE_ERROR hSDEError; SE_STATEINFO state; SE_VERSIONINFO version; SE_ENVELOPE envelope; msSDELayerInfo *sde = NULL; msSDEConnPoolInfo *poolinfo; /* allocate space for SDE structures */ sde = (msSDELayerInfo *) malloc(sizeof(msSDELayerInfo)); MS_CHECK_ALLOC(sde, sizeof(msSDELayerInfo), MS_FAILURE); sde->state_id = SE_BASE_STATE_ID; /* initialize the table and spatial column names */ sde->table = NULL; sde->column = NULL; sde->row_id_column = NULL; sde->join_table = NULL; sde->basedefs = NULL; sde->joindefs = NULL; sde->extent = (rectObj *) msSmallMalloc(sizeof(rectObj)); sde->nBaseColumns = (short *) msSmallMalloc(1*sizeof(short)); *(sde->nBaseColumns) = 0; sde->nJoinColumns = (short *) msSmallMalloc(1*sizeof(short)); *(sde->nJoinColumns) = 0; if(!sde->extent) { msSetError( MS_MEMERR, "Error allocating extent for SDE layer", "msSDELayerOpen()"); return(MS_FAILURE); } /* request a connection and stream from the pool */ poolinfo = (msSDEConnPoolInfo *)msConnPoolRequest( layer ); #ifdef SE_connection_test_server /* check the connection */ if (poolinfo && (SE_connection_test_server(poolinfo->connection, 30) != SE_SUCCESS)) { msSDECloseConnection(poolinfo->connection); } #endif /* If we weren't returned a connection and stream, initialize new ones */ if (!poolinfo) { char *conn_decrypted; if (layer->debug) msDebug("msSDELayerOpen(): " "Layer %s opened from scratch.\n", layer->name); poolinfo = (msSDEConnPoolInfo *)malloc(sizeof *poolinfo); MS_CHECK_ALLOC(poolinfo, sizeof *poolinfo, MS_FAILURE); /* Decrypt any encrypted token in the connection string */ conn_decrypted = msDecryptStringTokens(layer->map, layer->connection); /* An error should already have been produced */ if (conn_decrypted == NULL) { return(MS_FAILURE); } /* Split the connection parameters and make sure we have enough of them */ params = msStringSplit(conn_decrypted, ',', &numparams); if(!params) { msSetError( MS_MEMERR, "Error splitting SDE connection information.", "msSDELayerOpen()"); msFree(conn_decrypted); return(MS_FAILURE); } msFree(conn_decrypted); conn_decrypted = NULL; if(numparams < 5) { msSetError( MS_SDEERR, "Not enough SDE connection parameters specified.", "msSDELayerOpen()"); return(MS_FAILURE); } /* Create the connection handle and put into poolinfo->connection */ status = SE_connection_create(params[0], params[1], params[2], params[3], params[4], &(hSDEError), &(poolinfo->connection)); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_connection_create()"); return(MS_FAILURE); } /* ------------------------------------------------------------------------- */ /* Set the concurrency type for the connection. SE_UNPROTECTED_POLICY is */ /* suitable when only one thread accesses the specified connection. */ /* ------------------------------------------------------------------------- */ status = SE_connection_set_concurrency( poolinfo->connection, SE_UNPROTECTED_POLICY); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_connection_set_concurrency()"); return(MS_FAILURE); } status = SE_stream_create(poolinfo->connection, &(poolinfo->stream)); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_stream_create()"); return(MS_FAILURE); } /* Register the connection with the connection pooling API. Give */ /* msSDECloseConnection as the function to call when we run out of layer */ /* instances using it */ msConnPoolRegister(layer, poolinfo, msSDECloseConnection); msFreeCharArray(params, numparams); /* done with parameter list */ } /* !poolinfo */ /* Split the DATA member into its parameters using the comma */ /* Periods (.) are used to denote table names and schemas in SDE, */ /* as are underscores (_). */ data_params = msStringSplit(layer->data, ',', &numparams); if(!data_params) { msSetError( MS_MEMERR, "Error splitting SDE layer information.", "msSDELayerOpen()"); return(MS_FAILURE); } if(numparams < 2) { msSetError( MS_SDEERR, "Not enough SDE layer parameters specified.", "msSDELayerOpen()"); return(MS_FAILURE); } sde->table = msStrdup(data_params[0]); sde->column = msStrdup(data_params[1]); join_table = msLayerGetProcessingKey(layer,"JOINTABLE"); if (join_table) { sde->join_table = msStrdup(join_table); /* msFree(join_table); */ } if (numparams < 3) { /* User didn't specify a version, we won't use one */ if (layer->debug) { msDebug("msSDELayerOpen(): Layer %s did not have a " "specified version.\n", layer->name); } sde->state_id = SE_DEFAULT_STATE_ID; } else { /* A version was specified... obtain the state_id */ /* for it. */ if (layer->debug) { msDebug("msSDELayerOpen(): Layer %s specified version %s.\n", layer->name, data_params[2]); } status = SE_versioninfo_create (&(version)); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_versioninfo_create()"); return(MS_FAILURE); } status = SE_version_get_info(poolinfo->connection, data_params[2], version); if(status != SE_SUCCESS) { if (status == SE_INVALID_RELEASE) { /* The user has incongruent versions of SDE, ie 8.2 client and */ /* 8.3 server set the state_id to SE_DEFAULT_STATE_ID, which means */ /* no version queries are done */ sde->state_id = SE_DEFAULT_STATE_ID; } else { sde_error( status, "msSDELayerOpen()", "SE_version_get_info()"); SE_versioninfo_free(version); return(MS_FAILURE); } } /* couldn't get version info */ } /* version was specified */ /* Get the STATEID from the given version and set the stream to */ /* that if we didn't already set it to SE_DEFAULT_STATE_ID. */ if (sde->state_id != SE_DEFAULT_STATE_ID) { status = SE_versioninfo_get_state_id(version, &sde->state_id); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_versioninfo_get_state_id()"); SE_versioninfo_free(version); return(MS_FAILURE); } SE_versioninfo_free(version); status = SE_stateinfo_create (&state); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_stateinfo_create()"); return(MS_FAILURE); } status = SE_state_get_info( poolinfo->connection, sde->state_id, state); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerOpen()", "SE_state_get_info()"); SE_stateinfo_free (state); return(MS_FAILURE); } if (SE_stateinfo_is_open (state)) { /* If the state is open for edits, we shouldn't be querying from it */ sde_error( status, "msSDELayerOpen()", "SE_stateinfo_is_open() -- State for version is open"); SE_stateinfo_free (state); return(MS_FAILURE); } SE_stateinfo_free (state); } /* if (!(sde->state_id == SE_DEFAULT_STATE_ID)) */ /* done with the DATA stuff now */ msFreeCharArray(data_params, numparams); status = SE_layerinfo_create(NULL, &(sde->layerinfo)); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerOpen()", "SE_layerinfo_create()"); return(MS_FAILURE); } status = msSDEGetLayerInfo( layer, poolinfo->connection, sde->table, sde->column, layer->connection, sde->layerinfo); if(status != MS_SUCCESS) { sde_error(status, "msSDELayerOpen()", "msSDEGetLayerInfo()"); return(MS_FAILURE); } status = SE_coordref_create(&(sde->coordref)); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerOpen()", "SE_coordref_create()"); return(MS_FAILURE); } status = SE_layerinfo_get_coordref(sde->layerinfo, sde->coordref); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerOpen()", "SE_layerinfo_get_coordref()"); return(MS_FAILURE); } /* Get the layer extent and hang it on the layerinfo */ status = SE_layerinfo_get_envelope(sde->layerinfo, &envelope); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerOpen()", "SE_layerinfo_get_envelope()"); return(MS_FAILURE); } sde->extent->minx = envelope.minx; sde->extent->miny = envelope.miny; sde->extent->maxx = envelope.maxx; sde->extent->maxy = envelope.maxy; /* reset the stream */ status = SE_stream_close(poolinfo->stream, 1); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerOpen()", "SE_stream_close()"); return(MS_FAILURE); } /* Determine if we are big or little- endian for */ /* working with the encoding */ if( *((unsigned char *) &endian_test) == 1 ) sde->bBigEndian = MS_FALSE; else sde->bBigEndian = MS_TRUE; /* point to the SDE layer information */ /* (note this might actually be in another layer) */ layer->layerinfo = sde; sde->connPoolInfo = poolinfo; return(MS_SUCCESS); #else msSetError(MS_MISCERR, "SDE support is not available.", "msSDELayerOpen()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerClose */ /* -------------------------------------------------------------------- */ /* Closes the MapServer layer. This doesn't necessarily close the */ /* connection to the layer. */ /* -------------------------------------------------------------------- */ int msSDELayerClose(layerObj *layer) { #ifdef USE_SDE msSDELayerInfo *sde=NULL; sde = layer->layerinfo; /* Silently return if layer not opened. */ if (!msSDELayerIsOpen(layer)) return MS_SUCCESS; if(layer->debug) msDebug("msSDELayerClose(): Closing layer %s.\n", layer->name); if (sde->layerinfo) SE_layerinfo_free(sde->layerinfo); if (sde->coordref) SE_coordref_free(sde->coordref); if (sde->table) msFree(sde->table); if (sde->column) msFree(sde->column); if (sde->row_id_column) msFree(sde->row_id_column); if (sde->join_table) msFree(sde->join_table); if (sde->extent) msFree(sde->extent); if (sde->nBaseColumns) msFree(sde->nBaseColumns); if (sde->nJoinColumns) msFree(sde->nJoinColumns); msConnPoolRelease( layer, sde->connPoolInfo ); if (layer->layerinfo) msFree(layer->layerinfo); layer->layerinfo = NULL; return MS_SUCCESS; #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerClose()"); return(MS_FALSE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerCloseConnection */ /* -------------------------------------------------------------------- */ /* Virtual table function */ /* -------------------------------------------------------------------- */ int msSDELayerCloseConnection(layerObj *layer) { #ifdef USE_SDE msSDELayerInfo *sde=NULL; if(!msSDELayerIsOpen(layer)) { return MS_SUCCESS; /* already closed */ } sde = layer->layerinfo; if(layer->debug) msDebug("msSDELayerCloseConnection(): Closing connection for layer %s.\n", layer->name); msConnPoolRelease( layer, sde->connPoolInfo ); sde->connPoolInfo = NULL; return (MS_SUCCESS); #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerClose()"); return MS_FAILURE; #endif return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* msSDELayerWhichShapes */ /* -------------------------------------------------------------------- */ /* starts a stream query using spatial filter. Also limits the */ /* query by the layer's FILTER item as well. */ /* -------------------------------------------------------------------- */ int msSDELayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifdef USE_SDE long status; SE_ENVELOPE envelope; SE_SHAPE shape=0; SE_FILTER constraint; SE_QUERYINFO query_info = NULL; SE_SQL_CONSTRUCT* sql = NULL; char* proc_value=NULL; int query_order=SE_SPATIAL_FIRST; msSDELayerInfo *sde=NULL; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerWhichShapes()"); return(MS_FAILURE); } sde = layer->layerinfo; /* use the cached layer's extent. */ /* there is NO overlap, return MS_DONE */ /* (FIX: use this in ALL which shapes functions) */ if(sde->extent->minx > rect.maxx) return(MS_DONE); if(sde->extent->maxx < rect.minx) return(MS_DONE); if(sde->extent->miny > rect.maxy) return(MS_DONE); if(sde->extent->maxy < rect.miny) return(MS_DONE); /* set spatial constraint search shape */ /* crop against SDE layer extent *argh* */ envelope.minx = MS_MAX(rect.minx, sde->extent->minx); envelope.miny = MS_MAX(rect.miny, sde->extent->miny); envelope.maxx = MS_MIN(rect.maxx, sde->extent->maxx); envelope.maxy = MS_MIN(rect.maxy, sde->extent->maxy); if( envelope.minx == envelope.maxx && envelope.miny == envelope.maxy) { /* fudge a rectangle so we have a valid one for generate_rectangle */ /* FIXME: use the real shape for the query and set the filter_type to be an appropriate type */ envelope.minx = envelope.minx - 0.001; envelope.maxx = envelope.maxx + 0.001; envelope.miny = envelope.miny - 0.001; envelope.maxy = envelope.maxy + 0.001; } status = SE_shape_create(sde->coordref, &shape); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerWhichShapes()", "SE_shape_create()"); return(MS_FAILURE); } status = SE_shape_generate_rectangle(&envelope, shape); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerWhichShapes()", "SE_shape_generate_rectangle()"); return(MS_FAILURE); } constraint.filter.shape = shape; /* set spatial constraint column and table */ strcpy(constraint.table, sde->table); strcpy(constraint.column, sde->column); /* set a couple of other spatial constraint properties */ constraint.method = SM_ENVP; constraint.filter_type = SE_SHAPE_FILTER; constraint.truth = TRUE; if (!sde->join_table) { query_info = getSDEQueryInfo(layer); if (!query_info) { sde_error( status, "msSDELayerWhichShapes()", "getSDEQueryInfo()"); return(MS_FAILURE); } } else { if (!layer->filter.string) { sde_error( -51, "msSDELayerWhichShapes()", "A join table is specified, but no FILTER is" " defined that joins the two tables together"); return(MS_FAILURE); } sql = getSDESQLConstructInfo(layer, NULL); } /* reset the stream */ status = SE_stream_close(sde->connPoolInfo->stream, 1); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerWhichShapes()", "SE_stream_close()"); return(MS_FAILURE); } /* Set the stream state back to the state_id of our user-specified version */ /* This must be done every time after the stream is reset before the */ /* query happens. */ if (sde->state_id != SE_DEFAULT_STATE_ID) { status = SE_stream_set_state(sde->connPoolInfo->stream, sde->state_id, sde->state_id, SE_STATE_DIFF_NOCHECK); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerOpen()", "SE_stream_set_state()"); return(MS_FAILURE); } } if (!sql) { status = SE_stream_query_with_info(sde->connPoolInfo->stream, query_info); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerWhichShapes()", "SE_stream_query_with_info()"); return(MS_FAILURE); } } else { status = SE_stream_query(sde->connPoolInfo->stream, layer->numitems, (const CHAR**) layer->items, sql); if(status != SE_SUCCESS) { sde_error(status, "msSDELayerWhichShapes()", "SE_stream_query()"); return(MS_FAILURE); } /* Free up the sql now that we've queried */ SE_sql_construct_free(sql); } proc_value = msLayerGetProcessingKey(layer,"QUERYORDER"); if(proc_value && strcasecmp(proc_value, "ATTRIBUTE") == 0) query_order = SE_ATTRIBUTE_FIRST; status = SE_stream_set_spatial_constraints( sde->connPoolInfo->stream, query_order, FALSE, 1, &constraint); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerWhichShapes()", "SE_stream_set_spatial_constraints()"); return(MS_FAILURE); } /* *should* be ready to step through shapes now */ status = SE_stream_execute(sde->connPoolInfo->stream); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerWhichShapes()", "SE_stream_execute()"); return(MS_FAILURE); } /* clean-up */ SE_shape_free(shape); SE_queryinfo_free (query_info); return(MS_SUCCESS); #else msSetError(MS_MISCERR, "SDE support is not available.", "msSDELayerWhichShapes()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerNextShape */ /* -------------------------------------------------------------------- */ /* Recursively gets the shapes for the SDE layer */ /* -------------------------------------------------------------------- */ int msSDELayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_SDE long status; msSDELayerInfo *sde=NULL; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerNextShape()"); return(MS_FAILURE); } sde = layer->layerinfo; /* fetch the next record from the stream */ status = SE_stream_fetch(sde->connPoolInfo->stream); if(status == SE_FINISHED) return(MS_DONE); else if(status != MS_SUCCESS) { sde_error( status, "msSDELayerNextShape()", "SE_stream_fetch()"); return(MS_FAILURE); } /* get the shape and values (first column is the shape id, */ /* second is the shape itself) */ status = sdeGetRecord(layer, shape); if(status != MS_SUCCESS) return(MS_FAILURE); /* something went wrong fetching the record/shape */ if(shape->numlines == 0) /* null shape, skip it */ return(msSDELayerNextShape(layer, shape)); return(MS_SUCCESS); #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerNextShape()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerGetExtent */ /* -------------------------------------------------------------------- */ /* Returns the extent of the SDE layer */ /* -------------------------------------------------------------------- */ int msSDELayerGetExtent(layerObj *layer, rectObj *extent) { #ifdef USE_SDE msSDELayerInfo *sde = NULL; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerGetExtent()"); return(MS_FAILURE); } sde = layer->layerinfo; /* copy our cached extent members into the caller's extent */ extent->minx = sde->extent->minx; extent->miny = sde->extent->miny; extent->maxx = sde->extent->maxx; extent->maxy = sde->extent->maxy; return(MS_SUCCESS); #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerGetExtent()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerGetShape */ /* -------------------------------------------------------------------- */ /* Queries SDE for a shape (and its attributes, if requested) */ /* given the ID (which is the MS_SDE_ROW_ID_COLUMN column */ /* -------------------------------------------------------------------- */ int msSDELayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifdef USE_SDE long status; SE_SQL_CONSTRUCT* sql; msSDELayerInfo *sde=NULL; long shapeindex = record->shapeindex; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerGetShape()"); return(MS_FAILURE); } sde = layer->layerinfo; /* must be at least one thing to retrieve (i.e. spatial column) */ if(layer->numitems < 1) { msSetError( MS_MISCERR, "No items requested, SDE requires at least one item.", "msSDELayerGetShape()"); return(MS_FAILURE); } /* reset the stream */ status = SE_stream_close(sde->connPoolInfo->stream, 1); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerGetShape()", "SE_stream_close()"); return(MS_FAILURE); } if (!sde->join_table) { status = SE_stream_fetch_row( sde->connPoolInfo->stream, sde->table, shapeindex, (short)(layer->numitems), (const char **)layer->items); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerGetShape()", "SE_stream_fetch_row()"); return(MS_FAILURE); } } else { sql = getSDESQLConstructInfo(layer, &shapeindex); status = SE_stream_query(sde->connPoolInfo->stream, layer->numitems, (const CHAR**) layer->items, sql); ; if(status != SE_SUCCESS) { sde_error(status, "msSDELayerWhichShapes()", "SE_stream_query()"); return(MS_FAILURE); } /* Free up the sql now that we've queried */ SE_sql_construct_free(sql); /* *should* be ready to step through shapes now */ status = SE_stream_execute(sde->connPoolInfo->stream); if(status != SE_SUCCESS) { sde_error(status, "SE_stream_execute()", "SE_stream_execute()"); return(MS_FAILURE); } /* fetch the next record from the stream */ status = SE_stream_fetch(sde->connPoolInfo->stream); } status = sdeGetRecord(layer, shape); if(status != MS_SUCCESS) return(MS_FAILURE); /* something went wrong fetching the record/shape */ return(MS_SUCCESS); #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerGetShape()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerGetSpatialColumn */ /* -------------------------------------------------------------------- */ /* A helper function to return the spatial column for */ /* an opened SDE layer */ /* */ /* The caller owns the string after it is returned. */ /* -------------------------------------------------------------------- */ char *msSDELayerGetSpatialColumn(layerObj *layer) { #ifdef USE_SDE msSDELayerInfo *sde=NULL; if(!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerGetSpatialColumn()"); return NULL; } sde = layer->layerinfo; return(msStrdup(sde->column)); #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerGetSpatialColumn()"); return(NULL); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerInitItemInfo */ /* -------------------------------------------------------------------- */ /* Connects to SDE and returns the column names and SDE's column */ /* descriptions. It stores them on layer->items and layer->iteminfo */ /* If a join table has been specified through the processing option, */ /* it's column definitions are appended to both lists. */ /* -------------------------------------------------------------------- */ int msSDELayerInitItemInfo(layerObj *layer) { #ifdef USE_SDE int i,j; /* short nBaseColumns, nJoinColumns; */ long status; short nbasecol, njoincol; SE_COLUMN_DEF *all_itemdefs = NULL; msSDELayerInfo *sde = NULL; /* nBaseColumns = 0; */ /* nJoinColumns = 0; */ char *proc_key = NULL; if (!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerInitItemInfo()"); return(MS_FAILURE); } sde = layer->layerinfo; /* ** This insanity is because we keep around the number of ** columns we have along with the layer info. If the total ** number of columns that we have doesn't match when we're ** called the second time around, we have to throw an error or ** msWhichShape will add an item onto our layer->items list, which ** in turn doesn't match the layer->iteminfo list of SDE column definitions. */ nbasecol =*(sde->nBaseColumns); njoincol =*(sde->nJoinColumns); /* Hop right out again if we've already gotten the layer->iteminfo */ if (layer->iteminfo && layer->items) { if (layer->debug) msDebug("Column information has already been gotten..." " returning from msSDELayerInitItemInfo\n"); if (layer->numitems != ( nbasecol+ njoincol)) { /* if someone has modified the size of the items list, ** it is because it didn't find a column name (and we have ** already given them all because we have iteminfo and items ** If this is the case, we can't continue. */ msSetError( MS_SDEERR, "A specified CLASSITEM, FILTERITEM, or expression key cannot be found", "msSDELayerInitItemInfo()"); return(MS_FAILURE); } return (MS_SUCCESS); } if (layer->debug) msDebug("Getting all column information in msSDELayerInitItemInfo\n"); if (!(sde->row_id_column)) { sde->row_id_column = msSDELayerGetRowIDColumn(layer); } else { /* Don't think this should happen. If it does, it'd be good to know why. */ if (layer->debug) msDebug ("RowID column has already been gotten... msSDELayerInitItemInfo\n"); } status = SE_table_describe( sde->connPoolInfo->connection, sde->table, (short*)&(nbasecol), &(sde->basedefs)); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerInitItemInfo()", "SE_table_describe() (base table)"); return(MS_FAILURE); } if (sde->join_table) { status = SE_table_describe( sde->connPoolInfo->connection, sde->join_table, (short*)&(njoincol), &(sde->joindefs)); if(status != SE_SUCCESS) { sde_error( status, "msSDELayerInitItemInfo()", "SE_table_describe() (join table). Did you specify the name of the join table properly?"); return(MS_FAILURE); } } layer->numitems = nbasecol + njoincol; /* combine the itemdefs of both tables into one */ all_itemdefs = (SE_COLUMN_DEF *) calloc( layer->numitems, sizeof(SE_COLUMN_DEF)); MS_CHECK_ALLOC(all_itemdefs, sizeof(SE_COLUMN_DEF), MS_FAILURE); for(i=0; ibasedefs[i]; if (njoincol > 0) { for(i=0; ijoindefs[i]; } } if (!layer->iteminfo) { layer->iteminfo = (SE_COLUMN_DEF *) calloc( layer->numitems, sizeof(SE_COLUMN_DEF)); if(!layer->iteminfo) { msSetError( MS_MEMERR, "Error allocating SDE item information.", "msSDELayerInitItemInfo()"); free(all_itemdefs); return(MS_FAILURE); } } else { /* Don't think this should happen. If it does, it'd be good to know why. */ if (layer->debug) msDebug ("layer->iteminfo has already been initialized... msSDELayerInitItemInfo\n"); } if (!(layer->items)) { /* gather up all of the column names and put them onto layer->items */ layer->items = (char **)malloc(layer->numitems*sizeof(char *)+10); MS_CHECK_ALLOC(layer->items, layer->numitems*sizeof(char *)+10, MS_FAILURE); } else { msDebug("layer->items has already been initialized!!!"); } proc_key = msLayerGetProcessingKey(layer,"ATTRIBUTE_QUALIFIED"); if (!sde->join_table && (proc_key == NULL || strcasecmp( proc_key, "TRUE") != 0)) { for(i=0; inumitems; i++) layer->items[i] = msStrdup(all_itemdefs[i].column_name); for(i=0; inumitems; i++) { /* requested columns */ for(j=0; jnumitems; j++) { /* all columns */ if(strcasecmp(layer->items[i], all_itemdefs[j].column_name) == 0) { /* found it */ ((SE_COLUMN_DEF *)(layer->iteminfo))[i] = all_itemdefs[j]; break; } } } } else { for(i=0; iitems[i] = (char*) msSmallMalloc((SE_QUALIFIED_COLUMN_LEN+1)*sizeof (char)); layer->items[i][0] = '\0'; strcat(layer->items[i], sde->table); strcat(layer->items[i], "."); strcat(layer->items[i], all_itemdefs[i].column_name); ((SE_COLUMN_DEF *)(layer->iteminfo))[i] = all_itemdefs[i]; } for(i=nbasecol; inumitems; i++) { layer->items[i] = (char*) msSmallMalloc((SE_QUALIFIED_COLUMN_LEN+1)*sizeof (char)); layer->items[i][0] = '\0'; strcat(layer->items[i], sde->join_table); strcat(layer->items[i], "."); strcat(layer->items[i], all_itemdefs[i].column_name); ((SE_COLUMN_DEF *)(layer->iteminfo))[i] = all_itemdefs[i]; } } /* Tell the user which columns we've gotten */ if (layer->debug) for(i=0; inumitems; i++) msDebug("msSDELayerInitItemInfo(): getting info for %s\n", layer->items[i]); *(sde->nJoinColumns) = njoincol; *(sde->nBaseColumns) = nbasecol; msFree(all_itemdefs); return MS_SUCCESS; #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerInitItemInfo()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerCreateItems */ /* -------------------------------------------------------------------- */ /* Inits the stuff we'll be querying from SDE */ /* -------------------------------------------------------------------- */ int msSDELayerCreateItems(layerObj *layer, int nt) { int status; /* status = msSDELayerCreateItems(layer, 0); */ status = msSDELayerInitItemInfo(layer); if (status != MS_SUCCESS) { msSetError( MS_MISCERR, "Unable to create SDE column info", "msSDELayerCreateItemsInfo()"); return(MS_FAILURE); } return (MS_SUCCESS); } /* -------------------------------------------------------------------- */ /* msSDELayerGetItems */ /* -------------------------------------------------------------------- */ /* Queries the SDE table's column names into layer->iteminfo */ /* -------------------------------------------------------------------- */ int msSDELayerGetItems(layerObj *layer) { #ifdef USE_SDE int status; status = msSDELayerInitItemInfo(layer); if (status != MS_SUCCESS) { msSetError( MS_MISCERR, "Unable to create SDE column info", "msSDELayerGetItems()"); return(MS_FAILURE); } return (MS_SUCCESS); #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerGetItems()"); return(MS_FAILURE); #endif } /* -------------------------------------------------------------------- */ /* msSDELayerFreeItemInfo */ /* -------------------------------------------------------------------- */ void msSDELayerFreeItemInfo(layerObj *layer) { #ifdef USE_SDE msSDELayerInfo *sde = NULL; int i; if (!msSDELayerIsOpen(layer)) { msSetError( MS_SDEERR, "SDE layer has not been opened.", "msSDELayerFreeItemInfo()"); } sde = layer->layerinfo; if (sde != NULL && sde->basedefs) { SE_table_free_descriptions(sde->basedefs); sde->basedefs = NULL; } if (sde != NULL && sde->joindefs) { SE_table_free_descriptions(sde->joindefs); sde->joindefs = NULL; } if (layer->iteminfo) { msFree(layer->iteminfo); layer->iteminfo = NULL; } if (layer->items) { for (i=0; i< layer->numitems; i++) { msFree(layer->items[i]); } msFree(layer->items); layer->items = NULL; layer->numitems = 0; } #else msSetError( MS_MISCERR, "SDE support is not available.", "msSDELayerFreeItemInfo()"); #endif } #ifdef USE_SDE_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); vtable->LayerInitItemInfo = msSDELayerInitItemInfo; vtable->LayerFreeItemInfo = msSDELayerFreeItemInfo; vtable->LayerOpen = msSDELayerOpen; vtable->LayerIsOpen = msSDELayerIsOpen; vtable->LayerWhichShapes = msSDELayerWhichShapes; vtable->LayerNextShape = msSDELayerNextShape; vtable->LayerGetShape = msSDELayerGetShape; vtable->LayerClose = msSDELayerClose; vtable->LayerGetItems = msSDELayerGetItems; vtable->LayerGetExtent = msSDELayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* SDE uses pooled connections, close from msCloseConnections */ vtable->LayerCloseConnection = msSDELayerCloseConnection; vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; vtable->LayerCreateItems = msSDELayerCreateItems; /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } #endif int msSDELayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msSDELayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msSDELayerFreeItemInfo; layer->vtable->LayerOpen = msSDELayerOpen; layer->vtable->LayerIsOpen = msSDELayerIsOpen; layer->vtable->LayerWhichShapes = msSDELayerWhichShapes; layer->vtable->LayerNextShape = msSDELayerNextShape; layer->vtable->LayerGetShape = msSDELayerGetShape; layer->vtable->LayerClose = msSDELayerClose; layer->vtable->LayerGetItems = msSDELayerGetItems; layer->vtable->LayerGetExtent = msSDELayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ layer->vtable->LayerCloseConnection = msSDELayerCloseConnection; /* SDE uses pooled connections, close from msCloseConnections */ layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; layer->vtable->LayerCreateItems = msSDELayerCreateItems; /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } mapserver-6.4.1/stablemerge.sh0000644002461700001440000000134512261257215016145 0ustar tbonfortusers#!/bin/bash git checkout branch-5-0 if test $? -ne 0; then exit; fi git merge branch-4-10 if test $? -ne 0; then exit; fi git checkout branch-5-2 if test $? -ne 0; then exit; fi git merge branch-5-0 if test $? -ne 0; then exit; fi git checkout branch-5-4 if test $? -ne 0; then exit; fi git merge branch-5-2 if test $? -ne 0; then exit; fi git checkout branch-5-6 if test $? -ne 0; then exit; fi git merge branch-5-4 if test $? -ne 0; then exit; fi git checkout branch-6-0 if test $? -ne 0; then exit; fi git merge branch-5-6 if test $? -ne 0; then exit; fi git checkout branch-6-2 if test $? -ne 0; then exit; fi git merge branch-6-0 if test $? -ne 0; then exit; fi git checkout master if test $? -ne 0; then exit; fi git merge branch-6-2 mapserver-6.4.1/mapogcfiltercommon.c0000644002461700001440000005226112261257215017353 0ustar tbonfortusers/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Filter Encoding implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * 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 ****************************************************************************/ #ifdef USE_OGR #include "cpl_minixml.h" #endif #include "mapogcfilter.h" #include "mapserver.h" #include "mapowscommon.h" #ifdef USE_OGR char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode) { const size_t bufferSize = 1024; char szBuffer[1024]; char szTmp[256]; char *pszValue = NULL; char *pszWild = NULL; char *pszSingle = NULL; char *pszEscape = NULL; int bCaseInsensitive = 0; int nLength=0, i=0, iTmp=0; if (!psFilterNode || !psFilterNode->pOther || !psFilterNode->psLeftNode || !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue) return NULL; pszWild = ((FEPropertyIsLike *)psFilterNode->pOther)->pszWildCard; pszSingle = ((FEPropertyIsLike *)psFilterNode->pOther)->pszSingleChar; pszEscape = ((FEPropertyIsLike *)psFilterNode->pOther)->pszEscapeChar; bCaseInsensitive = ((FEPropertyIsLike *)psFilterNode->pOther)->bCaseInsensitive; if (!pszWild || strlen(pszWild) == 0 || !pszSingle || strlen(pszSingle) == 0 || !pszEscape || strlen(pszEscape) == 0) return NULL; /* -------------------------------------------------------------------- */ /* Use operand with regular expressions. */ /* -------------------------------------------------------------------- */ szBuffer[0] = '\0'; sprintf(szTmp, "%s", " (\"["); szTmp[4] = '\0'; strlcat(szBuffer, szTmp, bufferSize); /* attribute */ strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize); szBuffer[strlen(szBuffer)] = '\0'; /*#3521 */ if(bCaseInsensitive == 1) sprintf(szTmp, "%s", "]\" ~* \""); else sprintf(szTmp, "%s", "]\" ~ \""); szTmp[7] = '\0'; strlcat(szBuffer, szTmp, bufferSize); szBuffer[strlen(szBuffer)] = '\0'; pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); iTmp =0; if (nLength > 0 && pszValue[0] != pszWild[0] && pszValue[0] != pszSingle[0] && pszValue[0] != pszEscape[0]) { szTmp[iTmp]= '^'; iTmp++; } for (i=0; ipszValue, "PropertyIsBetween") == 0)) return NULL; if (psFilterNode->psLeftNode == NULL || psFilterNode->psRightNode == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Get the bounds value which are stored like boundmin;boundmax */ /* -------------------------------------------------------------------- */ aszBounds = msStringSplit(psFilterNode->psRightNode->pszValue, ';', &nBounds); if (nBounds != 2) { if (aszBounds) msFreeCharArray(aszBounds, nBounds); return NULL; } /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (aszBounds[0]) { snprintf(szBuffer, bufferSize, "%s_type", psFilterNode->psLeftNode->pszValue); if (msOWSLookupMetadata(&(lp->metadata), "OFG", szBuffer) != NULL && (strcasecmp(msOWSLookupMetadata(&(lp->metadata), "OFG", szBuffer), "Character") == 0)) bString = 1; else if (FLTIsNumeric(aszBounds[0]) == MS_FALSE) bString = 1; } if (!bString) { if (aszBounds[1]) { if (FLTIsNumeric(aszBounds[1]) == MS_FALSE) bString = 1; } } /* -------------------------------------------------------------------- */ /* build expresssion. */ /* -------------------------------------------------------------------- */ /* attribute */ if (bString) sprintf(szBuffer, "%s", " (\"["); else sprintf(szBuffer, "%s", " (["); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); if (bString) sprintf(szBuffer, "%s", "]\" "); else sprintf(szBuffer, "%s", "] "); pszExpression = msStringConcatenate(pszExpression, szBuffer); sprintf(szBuffer, "%s", " >= "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { sprintf(szBuffer,"%s", "\""); pszExpression = msStringConcatenate(pszExpression, szBuffer); } pszTmpEscaped = msStringEscape(aszBounds[0]); snprintf(szBuffer, bufferSize, "%s", pszTmpEscaped); if(pszTmpEscaped != aszBounds[0] ) msFree(pszTmpEscaped); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { sprintf(szBuffer, "%s", "\""); pszExpression = msStringConcatenate(pszExpression, szBuffer); } sprintf(szBuffer, "%s", " AND "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) sprintf(szBuffer, "%s", " \"["); else sprintf(szBuffer, "%s", " ["); pszExpression = msStringConcatenate(pszExpression, szBuffer); /* attribute */ pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); if (bString) sprintf(szBuffer, "%s", "]\" "); else sprintf(szBuffer, "%s", "] "); pszExpression = msStringConcatenate(pszExpression, szBuffer); sprintf(szBuffer, "%s", " <= "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { sprintf(szBuffer,"%s", "\""); pszExpression = msStringConcatenate(pszExpression, szBuffer); } pszTmpEscaped = msStringEscape(aszBounds[1]); snprintf(szBuffer, bufferSize, "%s", pszTmpEscaped); if(pszTmpEscaped != aszBounds[1] ) msFree(pszTmpEscaped); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { sprintf(szBuffer,"\""); pszExpression = msStringConcatenate(pszExpression, szBuffer); } sprintf(szBuffer, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (aszBounds) msFreeCharArray(aszBounds, nBounds); return pszExpression; } char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char szTmp[1024]; char *pszExpression = NULL, *pszTmpEscaped; int bString; if (psFilterNode == NULL) return NULL; /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (psFilterNode->psRightNode->pszValue) { snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); if (msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp) != NULL && (strcasecmp(msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp), "Character") == 0)) bString = 1; else if (FLTIsNumeric(psFilterNode->psRightNode->pszValue) == MS_FALSE) bString = 1; } /* specical case to be able to have empty strings in the expression. */ /*propertyislike is always treated as string*/ if (psFilterNode->psRightNode->pszValue == NULL || strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) bString = 1; /* attribute */ if (bString) sprintf(szTmp, "%s", " (\"["); else sprintf(szTmp, "%s"," (["); pszExpression = msStringConcatenate(pszExpression, szTmp); pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); if (bString) sprintf(szTmp, "%s","]\" "); else sprintf(szTmp, "%s", "] "); pszExpression = msStringConcatenate(pszExpression, szTmp); if (strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0) { /*case insensitive set ? */ if (psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) { sprintf(szTmp, "%s", "=*"); } else sprintf(szTmp, "%s", "="); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0) sprintf(szTmp, "%s", " != "); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0) sprintf(szTmp, "%s", " < "); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0) sprintf(szTmp, "%s", " > "); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0) sprintf(szTmp, "%s", " <= "); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) sprintf(szTmp, "%s", " >= "); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) sprintf(szTmp, "%s", " ~ "); pszExpression = msStringConcatenate(pszExpression, szTmp); /* value */ if (bString) { sprintf(szTmp, "%s", "\""); pszExpression = msStringConcatenate(pszExpression, szTmp); } if (psFilterNode->psRightNode->pszValue) { pszTmpEscaped = msStringEscape(psFilterNode->psRightNode->pszValue); pszExpression = msStringConcatenate(pszExpression, pszTmpEscaped); if(pszTmpEscaped != psFilterNode->psRightNode->pszValue ) msFree(pszTmpEscaped); } if (bString) { sprintf(szTmp, "%s", "\""); pszExpression = msStringConcatenate(pszExpression, szTmp); } sprintf(szTmp, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szTmp); return pszExpression; } char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; char *pszTmp = NULL; char szBuffer[256]; if (!psFilterNode || !FLTIsLogicalFilterType(psFilterNode->pszValue)) return NULL; /* -------------------------------------------------------------------- */ /* OR and AND */ /* -------------------------------------------------------------------- */ if (psFilterNode->psLeftNode && psFilterNode->psRightNode) { pszTmp = FLTGetCommonExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; sprintf(szBuffer, "%s", " ("); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); sprintf(szBuffer, "%s", " "); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, psFilterNode->pszValue); sprintf(szBuffer, "%s", " "); pszTmp = FLTGetCommonExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); sprintf(szBuffer, "%s", ") "); pszExpression = msStringConcatenate(pszExpression, szBuffer); } /* -------------------------------------------------------------------- */ /* NOT */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszTmp = FLTGetCommonExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; sprintf(szBuffer, "%s", " (NOT "); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); sprintf(szBuffer, "%s", ") "); pszExpression = msStringConcatenate(pszExpression, szBuffer); } return pszExpression; } char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp) { char *pszExpression = NULL; shapeObj *psQueryShape = NULL; double dfDistance = -1; int nUnit = -1; char *pszWktText = NULL; char szBuffer[256]; char *pszTmp=NULL; projectionObj sProjTmp; char *pszEPSG= NULL; rectObj sQueryRect; shapeObj *psTmpShape=NULL, *psBufferShape=NULL; int bBBoxQuery = 0; if (psNode == NULL || lp == NULL) return NULL; if (psNode->eType != FILTER_NODE_TYPE_SPATIAL) return NULL; /* get the shape*/ /*BBOX case: replace it with NOT DISJOINT.*/ if(FLTIsBBoxFilter(psNode)) { pszEPSG = FLTGetBBOX(psNode, &sQueryRect); /*this should be removed and bbox should parse and strore the srs properly, using now legacy code*/ if (pszEPSG) psNode->pszSRS = msStrdup(pszEPSG); psTmpShape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(psTmpShape); msRectToPolygon(sQueryRect, psTmpShape); bBBoxQuery = 1; } else { /*other geos type operations*/ /*project shape to layer projection. If the proj is not part of the filter query, assume that the cooredinates are in the map projection*/ psQueryShape = FLTGetShape(psNode, &dfDistance, &nUnit); if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0 ) && dfDistance > 0) { if (nUnit >=0 && nUnit != lp->map->units) dfDistance *= msInchesPerUnit(nUnit,0)/msInchesPerUnit(lp->map->units,0); psBufferShape = msGEOSBuffer(psQueryShape, dfDistance); } if (psBufferShape) psTmpShape = psBufferShape; else psTmpShape = psQueryShape; } if (psTmpShape) { if( lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS && FLTParseEpsgString(psNode->pszSRS, &sProjTmp)) { msProjectShape(&sProjTmp, &lp->projection, psTmpShape); } else if (lp->map->projection.numargs > 0) msProjectShape(&lp->map->projection, &lp->projection, psTmpShape); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } /* ==================================================================== */ /* use within for bbox. Not Disjoint does not work. */ /* ==================================================================== */ if (bBBoxQuery) sprintf(szBuffer, "%s", " ([shape] "); /* sprintf(szBuffer, "%s", " (NOT ([shape] "); */ else sprintf(szBuffer, "%s", " ([shape] "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bBBoxQuery) { sprintf(szBuffer, " %s ", "intersects"); } else { if (strncasecmp(psNode->pszValue, "intersect", 9) == 0) sprintf(szBuffer, " %s ", "intersects"); else if (strncasecmp(psNode->pszValue, "equals", 6) == 0) sprintf(szBuffer, " %s ", "eq"); else { pszTmp = msStrdup(psNode->pszValue); msStringToLower(pszTmp); sprintf(szBuffer, " %s ", pszTmp); msFree(pszTmp); } } pszExpression = msStringConcatenate(pszExpression, szBuffer); pszWktText = msGEOSShapeToWKT(psTmpShape); sprintf(szBuffer, "%s", " fromText('"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszWktText); sprintf(szBuffer, "%s", "')"); pszExpression = msStringConcatenate(pszExpression, szBuffer); msGEOSFreeWKT(pszWktText); } if (psBufferShape) { msFreeShape(psBufferShape); msFree(psBufferShape); } if(bBBoxQuery) { msFreeShape(psTmpShape); msFree(psTmpShape); } sprintf(szBuffer, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (0) { /* bBBoxQuery */ sprintf(szBuffer, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szBuffer); } return pszExpression; } char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; int nTokens = 0, i=0, bString=0; char **tokens = NULL; const char *pszAttribute=NULL; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode->pszValue) { pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if (pszAttribute) { tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); if (tokens && nTokens > 0) { for (i=0; ieType == FILTER_NODE_TYPE_COMPARISON) { if ( psFilterNode->psLeftNode && psFilterNode->psRightNode) { if (FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) pszExpression = FLTGetBinaryComparisonCommonExpression(psFilterNode, lp); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) pszExpression = FLTGetIsLikeComparisonCommonExpression(psFilterNode); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0) pszExpression = FLTGetIsBetweenComparisonCommonExpresssion(psFilterNode, lp); } } else if (psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL) pszExpression = FLTGetLogicalComparisonCommonExpression(psFilterNode, lp); else if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL) pszExpression = FLTGetSpatialComparisonCommonExpression(psFilterNode, lp); else if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID) pszExpression = FLTGetFeatureIdCommonExpression(psFilterNode, lp); return pszExpression; } int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, char *pszExpression) { int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.filter = (expressionObj *) msSmallMalloc(sizeof(expressionObj)); initExpression( map->query.filter); map->query.filter->string = msStrdup(pszExpression); map->query.filter->type = 2000; map->query.layer = iLayerIndex; /*TODO: if there is a bbox in the node, get it and set the map extent*/ map->query.rect = map->extent; retval = msQueryByFilter(map); return retval; } #endif mapserver-6.4.1/.gitmodules0000644002461700001440000000013512261257215015470 0ustar tbonfortusers[submodule "msautotest"] path = msautotest url = git://github.com/mapserver/msautotest.git mapserver-6.4.1/mapkmlrenderer.cpp0000644002461700001440000012275212261257215017041 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Google Earth KML output * Author: David Kana and the MapServer team * ****************************************************************************** * Copyright (c) 1996-2009 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. *****************************************************************************/ #include "mapserver-config.h" #ifdef USE_KML #include "mapserver.h" #include "maperror.h" #include "mapkmlrenderer.h" #include "mapio.h" #if defined(USE_OGR) # include "cpl_conv.h" # include "cpl_vsi.h" #endif #define KML_MAXFEATURES_TODRAW 1000 KmlRenderer::KmlRenderer(int width, int height, outputFormatObj *format, colorObj* color/*=NULL*/) : Width(width), Height(height), MapCellsize(1.0), XmlDoc(NULL), LayerNode(NULL), GroundOverlayNode(NULL), PlacemarkNode(NULL), GeomNode(NULL), Items(NULL), NumItems(0), FirstLayer(MS_TRUE), map(NULL), currentLayer(NULL), mElevationFromAttribute( false ), mElevationAttributeIndex( -1 ), mCurrentElevationValue(0.0) { /*private variables*/ pszLayerDescMetadata = NULL; papszLayerIncludeItems = NULL; nIncludeItems=0; papszLayerExcludeItems = NULL; nExcludeItems=0; pszLayerNameAttributeMetadata = NULL; /*metadata to use for a name for each feature*/ LineStyle = NULL; numLineStyle = 0; xmlNodePtr styleNode; xmlNodePtr listStyleNode; /* Create document.*/ XmlDoc = xmlNewDoc(BAD_CAST "1.0"); xmlNodePtr rootNode = xmlNewNode(NULL, BAD_CAST "kml"); /* Name spaces*/ xmlSetNs(rootNode, xmlNewNs(rootNode, BAD_CAST "http://www.opengis.net/kml/2.2", NULL)); xmlDocSetRootElement(XmlDoc, rootNode); DocNode = xmlNewChild(rootNode, NULL, BAD_CAST "Document", NULL); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_check"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "check"); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_checkHideChildren"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "checkHideChildren"); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_checkOffOnly"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "checkOffOnly"); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_radioFolder"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "radioFolder"); StyleHashTable = msCreateHashTable(); } KmlRenderer::~KmlRenderer() { if (XmlDoc) xmlFreeDoc(XmlDoc); if (StyleHashTable) msFreeHashTable(StyleHashTable); if(LineStyle) msFree(LineStyle); xmlCleanupParser(); } imageObj* KmlRenderer::createImage(int, int, outputFormatObj*, colorObj*) { return NULL; } int KmlRenderer::saveImage(imageObj *, FILE *fp, outputFormatObj *format) { /* -------------------------------------------------------------------- */ /* Write out the document. */ /* -------------------------------------------------------------------- */ int bufSize = 0; xmlChar *buf = NULL; msIOContext *context = NULL; int chunkSize = 4096; #if defined(CPL_ZIP_API_OFFERED) int bZip = MS_FALSE; #endif if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; xmlDocDumpFormatMemoryEnc(XmlDoc, &buf, &bufSize, "UTF-8", 1); #if defined(USE_OGR) if (format && format->driver && strcasecmp(format->driver, "kmz") == 0) { #if defined(CPL_ZIP_API_OFFERED) bZip = MS_TRUE; #else msSetError( MS_MISCERR, "kmz format support unavailable, perhaps you need to upgrade to GDAL/OGR 1.8?", "KmlRenderer::saveImage()"); xmlFree(buf); return MS_FAILURE; #endif } #if defined(CPL_ZIP_API_OFFERED) if (bZip) { VSILFILE *fpZip; int bytes_read; char buffer[1024]; char *zip_filename =NULL; void *hZip=NULL; zip_filename = msTmpFile(NULL, NULL, "/vsimem/kmlzip/", "kmz" ); hZip = CPLCreateZip( zip_filename, NULL ); CPLCreateFileInZip( hZip, "mapserver.kml", NULL ); for (int i=0; i bufSize) size = bufSize - i; CPLWriteFileInZip( hZip, buf+i, size); } CPLCloseFileInZip( hZip ); CPLCloseZip( hZip ); context = msIO_getHandler(fp); fpZip = VSIFOpenL( zip_filename, "r" ); while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fpZip )) > 0 ) { if (context) msIO_contextWrite(context, buffer, bytes_read); else msIO_fwrite( buffer, 1, bytes_read, fp ); } VSIFCloseL( fpZip ); msFree( zip_filename); xmlFree(buf); return(MS_SUCCESS); } #endif #endif context = msIO_getHandler(fp); for (int i=0; i bufSize) size = bufSize - i; if (context) msIO_contextWrite(context, buf+i, size); else msIO_fwrite(buf+i, 1, size, fp); } xmlFree(buf); return(MS_SUCCESS); } /************************************************************************/ /* processLayer */ /* */ /* Set parameters that make sense to a kml output. */ /************************************************************************/ void KmlRenderer::processLayer(layerObj *layer, outputFormatObj *format) { int i; const char *asRaster = NULL; int nMaxFeatures = -1; const char *pszTmp; char szTmp[10]; if (!layer) return; /*turn of labelcache*/ layer->labelcache = MS_OFF; /*if there are labels we want the coordinates to be the center of the element.*/ for(i=0; inumclasses; i++) if(layer->_class[i]->numlabels > 0) layer->_class[i]->labels[0]->position = MS_XY; /*we do not want to draw multiple styles. the new rendering architecture does not allow to know if we are dealing with a multi-style. So here we remove all styles beside the first one*/ for(i=0; inumclasses; i++) { while (layer->_class[i]->numstyles > 1) msDeleteStyle(layer->_class[i], layer->_class[i]->numstyles-1); } /*if layer has a metadata KML_OUTPUTASRASTER set to true, add a processing directive to use an agg driver*/ asRaster = msLookupHashTable(&layer->metadata, "kml_outputasraster"); if (!asRaster) asRaster = msLookupHashTable(&(layer->map->web.metadata), "kml_outputasraster"); if (asRaster && (strcasecmp(asRaster, "true") == 0 || strcasecmp(asRaster, "yes") == 0)) msLayerAddProcessing(layer, "RENDERER=png24"); /*set a maxfeaturestodraw, if not already set*/ pszTmp = msLookupHashTable(&layer->metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); else { pszTmp = msLookupHashTable(&layer->map->web.metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); } if (nMaxFeatures < 0 && format) nMaxFeatures = atoi(msGetOutputFormatOption( format, "maxfeaturestodraw", "-1")); if (nMaxFeatures < 0 && format) { snprintf(szTmp, sizeof(szTmp), "%d", KML_MAXFEATURES_TODRAW); msSetOutputFormatOption( format, "maxfeaturestodraw", szTmp); } } /************************************************************************/ /* getLayerName */ /* */ /* Internal utility function to build name used fo rthe layer. */ /************************************************************************/ char* KmlRenderer::getLayerName(layerObj *layer) { char stmp[20]; const char *name=NULL;; if (!layer) return NULL; name = msLookupHashTable(&layer->metadata, "ows_name"); if (name && strlen(name) > 0) return msStrdup(name); if (layer->name && strlen(layer->name) > 0) return msStrdup(layer->name); sprintf(stmp, "Layer%d",layer->index); return msStrdup(stmp); } const char* KmlRenderer::getAliasName(layerObj *lp, char *pszItemName, const char *namespaces) { const char *pszAlias = NULL; if (lp && pszItemName && strlen(pszItemName) > 0) { char szTmp[256]; snprintf(szTmp, sizeof(szTmp), "%s_alias", pszItemName); pszAlias = msOWSLookupMetadata(&(lp->metadata), namespaces, szTmp); } return pszAlias; } int KmlRenderer::startNewLayer(imageObj *img, layerObj *layer) { char *layerName=NULL; const char *value=NULL; LayerNode = xmlNewNode(NULL, BAD_CAST "Folder"); layerName = getLayerName(layer); xmlNewChild(LayerNode, NULL, BAD_CAST "name", BAD_CAST layerName); msFree(layerName); const char *layerVisibility = layer->status != MS_OFF ? "1" : "0"; xmlNewChild(LayerNode, NULL, BAD_CAST "visibility", BAD_CAST layerVisibility); const char *layerDsiplayFolder = msLookupHashTable(&(layer->metadata), "kml_folder_display"); if (layerDsiplayFolder == NULL) layerDsiplayFolder = msLookupHashTable(&(layer->map->web.metadata), "kml_folder_display"); if (!layerDsiplayFolder || strlen(layerDsiplayFolder)<=0) { xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_check"); } else { if (strcasecmp(layerDsiplayFolder, "checkHideChildren") == 0) xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_checkHideChildren"); else if (strcasecmp(layerDsiplayFolder, "checkOffOnly") == 0) xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_checkOffOnly"); else if (strcasecmp(layerDsiplayFolder, "radioFolder") == 0) xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_radioFolder"); else xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_check"); } /*Init few things on the first layer*/ if (FirstLayer) { FirstLayer = MS_FALSE; map = layer->map; if (layer->map->mappath) snprintf(MapPath, sizeof(MapPath), "%s", layer->map->mappath); /*First rendered layer - check mapfile projection*/ checkProjection(layer->map); /*check for image path and image url*/ if (layer->map->debug && (layer->map->web.imageurl == NULL || layer->map->web.imagepath == NULL)) msDebug("KmlRenderer::startNewLayer: imagepath and imageurl sould be set in the web object\n"); /*map rect for ground overlay*/ MapExtent = layer->map->extent; MapCellsize = layer->map->cellsize; BgColor = layer->map->imagecolor; xmlNewChild(DocNode, NULL, BAD_CAST "name", BAD_CAST layer->map->name); aggFormat = msSelectOutputFormat( layer->map, "png24"); aggFormat->transparent = MS_TRUE; } currentLayer = layer; if (!msLayerIsOpen(layer)) { if (msLayerOpen(layer) != MS_SUCCESS) { msSetError(MS_MISCERR, "msLayerOpen failed", "KmlRenderer::startNewLayer" ); } } /*pre process the layer to set things that make sense for kml output*/ if (img) processLayer(layer, img->format); else processLayer(layer, NULL); if (msLookupHashTable(&layer->metadata, "kml_description")) pszLayerDescMetadata = msLookupHashTable(&layer->metadata, "kml_description"); else if (msLookupHashTable(&layer->metadata, "ows_description")) pszLayerDescMetadata = msLookupHashTable(&layer->metadata, "ows_description"); value=msLookupHashTable(&layer->metadata, "kml_include_items"); if (!value) value=msLookupHashTable(&layer->metadata, "ows_include_items"); if (value) papszLayerIncludeItems = msStringSplit(value, ',', &nIncludeItems); value=msLookupHashTable(&layer->metadata, "kml_exclude_items"); if (!value) value=msLookupHashTable(&layer->metadata, "ows_exclude_items"); if (value) papszLayerExcludeItems = msStringSplit(value, ',', &nExcludeItems); if (msLookupHashTable(&layer->metadata, "kml_name_item")) pszLayerNameAttributeMetadata = msLookupHashTable(&layer->metadata, "kml_name_item"); /*get all attributes*/ msLayerWhichItems(layer, MS_TRUE, NULL); NumItems = layer->numitems; if (NumItems) { Items = (char **)msSmallCalloc(NumItems, sizeof(char *)); for (int i=0; iitems[i]); } char* elevationAttribute = msLookupHashTable(&layer->metadata, "kml_elevation_attribute"); if( elevationAttribute ) { mElevationFromAttribute = true; for( int i = 0; i < layer->numitems; ++i ) { if( strcasecmp( layer->items[i], elevationAttribute ) == 0 ) { mElevationAttributeIndex = i; } } } setupRenderingParams(&layer->metadata); return MS_SUCCESS; } int KmlRenderer::closeNewLayer(imageObj *img, layerObj *layer) { flushPlacemark(); xmlAddChild(DocNode, LayerNode); if(Items) { msFreeCharArray(Items, NumItems); Items = NULL; NumItems = 0; } if (pszLayerDescMetadata) pszLayerDescMetadata = NULL; if (pszLayerNameAttributeMetadata) pszLayerNameAttributeMetadata = NULL; if (papszLayerIncludeItems && nIncludeItems>0) msFreeCharArray(papszLayerIncludeItems, nIncludeItems); papszLayerIncludeItems=NULL; if (papszLayerExcludeItems && nExcludeItems>0) msFreeCharArray(papszLayerExcludeItems, nExcludeItems); papszLayerExcludeItems=NULL; return MS_SUCCESS; } int KmlRenderer::mergeRasterBuffer(imageObj *image, rasterBufferObj *rb) { assert(rb && rb->type == MS_BUFFER_BYTE_RGBA); char *tmpFileName = NULL; char *tmpUrl = NULL; FILE *tmpFile = NULL; tmpFileName = msTmpFile(NULL, MapPath, image->imagepath, "png"); tmpFile = fopen(tmpFileName,"wb"); if (tmpFile) { if (!aggFormat->vtable) msInitializeRendererVTable(aggFormat); msSaveRasterBuffer(map,rb,tmpFile,aggFormat); tmpUrl = msStrdup( image->imageurl); tmpUrl = msStringConcatenate(tmpUrl, (char *)(msGetBasename(tmpFileName))); tmpUrl = msStringConcatenate(tmpUrl, ".png"); createGroundOverlayNode(LayerNode, tmpUrl, currentLayer); msFree(tmpFileName); msFree(tmpUrl); fclose(tmpFile); return MS_SUCCESS; } else { msSetError(MS_IOERR,"Failed to create file for kml overlay","KmlRenderer::mergeRasterBuffer()"); return MS_FAILURE; } } void KmlRenderer::setupRenderingParams(hashTableObj *layerMetadata) { AltitudeMode = 0; Extrude = 0; Tessellate = 0; char *altitudeModeVal = msLookupHashTable(layerMetadata, "kml_altitudeMode"); if (altitudeModeVal) { if(strcasecmp(altitudeModeVal, "absolute") == 0) AltitudeMode = absolute; else if(strcasecmp(altitudeModeVal, "relativeToGround") == 0) AltitudeMode = relativeToGround; else if(strcasecmp(altitudeModeVal, "clampToGround") == 0) AltitudeMode = clampToGround; } char *extrudeVal = msLookupHashTable(layerMetadata, "kml_extrude"); if (altitudeModeVal) { Extrude = atoi(extrudeVal); } char *tessellateVal = msLookupHashTable(layerMetadata, "kml_tessellate"); if (tessellateVal) { Tessellate = atoi(tessellateVal); } } int KmlRenderer::checkProjection(mapObj *map) { projectionObj *projection= &map->projection; #ifdef USE_PROJ if (projection && projection->numargs > 0 && pj_is_latlong(projection->proj)) { return MS_SUCCESS; } else { char epsg_string[100]; rectObj sRect; projectionObj out; /* for layer the do not have any projection set, set them with the current map projection*/ if (projection && projection->numargs > 0) { layerObj *lp = NULL; int i =0; char *pszMapProjectString = msGetProjectionString(projection); if (pszMapProjectString) { for(i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if (lp->projection.numargs == 0 && lp->transform == MS_TRUE) { msFreeProjection(&lp->projection); msLoadProjectionString(&lp->projection, pszMapProjectString); } } msFree(pszMapProjectString); } } strcpy(epsg_string, "epsg:4326" ); msInitProjection(&out); msLoadProjectionString(&out, epsg_string); sRect = map->extent; msProjectRect(projection, &out, &sRect); msFreeProjection(projection); msLoadProjectionString(projection, epsg_string); /*change also units and extents*/ map->extent = sRect; map->units = MS_DD; if (map->debug) msDebug("KmlRenderer::checkProjection: Mapfile projection set to epsg:4326\n"); return MS_SUCCESS; } #else msSetError(MS_MISCERR, "Projection support not enabled", "KmlRenderer::checkProjection" ); return MS_FAILURE; #endif } xmlNodePtr KmlRenderer::createPlacemarkNode(xmlNodePtr parentNode, char *styleUrl) { xmlNodePtr placemarkNode = xmlNewChild(parentNode, NULL, BAD_CAST "Placemark", NULL); /*always add a name. It will be replaced by a text value if available*/ char tmpid[100]; char *stmp=NULL, *layerName=NULL; if (CurrentShapeName && strlen(CurrentShapeName)>0) { xmlNewChild(placemarkNode, NULL, BAD_CAST "name", BAD_CAST CurrentShapeName); } else { sprintf(tmpid, ".%d", CurrentShapeIndex); layerName = getLayerName(currentLayer); stmp = msStringConcatenate(stmp, layerName); stmp = msStringConcatenate(stmp, tmpid); xmlNewChild(placemarkNode, NULL, BAD_CAST "name", BAD_CAST stmp); } msFree(layerName); msFree(stmp); if (styleUrl) xmlNewChild(placemarkNode, NULL, BAD_CAST "styleUrl", BAD_CAST styleUrl); return placemarkNode; } void KmlRenderer::renderLine(imageObj*, shapeObj *p, strokeStyleObj *style) { if (p->numlines == 0) return; if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); if (!PlacemarkNode) return; addLineStyleToList(style); SymbologyFlag[Line] = 1; /*p->index > CurrentDrawnShapeIndexneed to be reviewd. Added since the hight level code caches shapes when rendering lines*/ if (CurrentDrawnShapeIndex == -1 || p->index > CurrentDrawnShapeIndex) { xmlNodePtr geomNode = getGeomParentNode("LineString"); addAddRenderingSpecifications(geomNode); addCoordsNode(geomNode, p->line[0].point, p->line[0].numpoints); /* more than one line => MultiGeometry*/ if (p->numlines > 1) { geomNode = getGeomParentNode("LineString"); // returns MultiGeom Node for (int i=1; inumlines; i++) { xmlNodePtr lineStringNode = xmlNewChild(geomNode, NULL, BAD_CAST "LineString", NULL); addAddRenderingSpecifications(lineStringNode); addCoordsNode(lineStringNode, p->line[i].point, p->line[i].numpoints); } } CurrentDrawnShapeIndex = p->index; } } void KmlRenderer::renderPolygon(imageObj*, shapeObj *p, colorObj *color) { if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); if (!PlacemarkNode) return; memcpy(&PolygonColor, color, sizeof(colorObj)); SymbologyFlag[Polygon] = 1; if (p->index != CurrentDrawnShapeIndex) { xmlNodePtr geomParentNode = getGeomParentNode("Polygon"); for (int i=0; inumlines; i++) { xmlNodePtr bdryNode = NULL; if (i==0) /* __TODO__ check ring order*/ bdryNode = xmlNewChild(geomParentNode, NULL, BAD_CAST "outerBoundaryIs", NULL); else bdryNode = xmlNewChild(geomParentNode, NULL, BAD_CAST "innerBoundaryIs", NULL); xmlNodePtr ringNode = xmlNewChild(bdryNode, NULL, BAD_CAST "LinearRing", NULL); addAddRenderingSpecifications(ringNode); addCoordsNode(ringNode, p->line[i].point, p->line[i].numpoints); } CurrentDrawnShapeIndex = p->index; } } void KmlRenderer::addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts) { char lineBuf[128]; xmlNodePtr coordsNode = xmlNewChild(parentNode, NULL, BAD_CAST "coordinates", NULL); xmlNodeAddContent(coordsNode, BAD_CAST "\n"); for (int i=0; ichildren; node; node = node->next) { if (node->type != XML_ELEMENT_NODE) continue; if (strcmp((char *)node->name, "name") == 0) { xmlNodeSetContent(node, BAD_CAST text); break; } } /*xmlNewChild(PlacemarkNode, NULL, BAD_CAST "name", BAD_CAST text);*/ xmlNodePtr geomNode = getGeomParentNode("Point"); addAddRenderingSpecifications(geomNode); pointObj pt; pt.x = x; pt.y = y; addCoordsNode(geomNode, &pt, 1); } void KmlRenderer::addAddRenderingSpecifications(xmlNodePtr node) { /* 0 0 clampToGround */ if (Extrude) xmlNewChild(node, NULL, BAD_CAST "extrude", BAD_CAST "1"); if (Tessellate) xmlNewChild(node, NULL, BAD_CAST "tessellate", BAD_CAST "1"); if (AltitudeMode == absolute) xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "absolute"); else if (AltitudeMode == relativeToGround) xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "relativeToGround"); else if (AltitudeMode == clampToGround) xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "clampToGround"); } imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorObj * bg); int KmlRenderer::createIconImage(char *fileName, symbolObj *symbol, symbolStyleObj *symstyle) { pointObj p; imageObj *tmpImg = NULL; tmpImg = agg2CreateImage((int)(symbol->sizex*symstyle->scale), (int)(symbol->sizey*symstyle->scale), aggFormat, NULL); tmpImg->format = aggFormat; if (!aggFormat->vtable) msInitializeRendererVTable(aggFormat); p.x = symbol->sizex * symstyle->scale / 2; p.y = symbol->sizey *symstyle->scale / 2; #ifdef USE_POINT_Z_M p.z = 0.0; #endif msDrawMarkerSymbol(&map->symbolset,tmpImg, &p, symstyle->style, 1); return msSaveImage(map, tmpImg, fileName); } void KmlRenderer::renderSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); if (!PlacemarkNode) return; snprintf(SymbolUrl, sizeof(SymbolUrl), "%s", lookupSymbolUrl(img, symbol, style)); SymbologyFlag[Symbol] = 1; xmlNodePtr geomNode = getGeomParentNode("Point"); addAddRenderingSpecifications(geomNode); pointObj pt; pt.x = x; pt.y = y; addCoordsNode(geomNode, &pt, 1); } void KmlRenderer::renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } void KmlRenderer::renderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } void KmlRenderer::renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } void KmlRenderer::renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } xmlNodePtr KmlRenderer::createGroundOverlayNode(xmlNodePtr parentNode, char *imageHref, layerObj *layer) { /* GroundOverlay.kml 7fffffff 1 http://www.google.com/intl/en/images/logo.gif onInterval 86400 0.75 37.83234 37.832122 -122.373033 -122.373724 45 */ char layerHexColor[32]; xmlNodePtr groundOverlayNode = xmlNewChild(parentNode, NULL, BAD_CAST "GroundOverlay", NULL); char *layerName = getLayerName(layer); xmlNewChild(groundOverlayNode, NULL, BAD_CAST "name", BAD_CAST layerName); if (layer->opacity > 0 && layer->opacity < 100) { sprintf(layerHexColor, "%02xffffff", (unsigned int)MS_NINT(layer->opacity*2.55)); xmlNewChild(groundOverlayNode, NULL, BAD_CAST "color", BAD_CAST layerHexColor); } else xmlNewChild(groundOverlayNode, NULL, BAD_CAST "color", BAD_CAST "ffffffff"); char stmp[20]; sprintf(stmp, "%d",layer->index); xmlNewChild(groundOverlayNode, NULL, BAD_CAST "drawOrder", BAD_CAST stmp); if (imageHref) { xmlNodePtr iconNode = xmlNewChild(groundOverlayNode, NULL, BAD_CAST "Icon", NULL); xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST imageHref); } char crdStr[64]; rectObj mapextent; if (map->gt.need_geotransform == MS_TRUE) mapextent = currentLayer->map->saved_extent; else mapextent = currentLayer->map->extent; xmlNodePtr latLonBoxNode = xmlNewChild(groundOverlayNode, NULL, BAD_CAST "LatLonBox", NULL); sprintf(crdStr, "%.8f", mapextent.maxy); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "north", BAD_CAST crdStr); sprintf(crdStr, "%.8f", mapextent.miny); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "south", BAD_CAST crdStr); sprintf(crdStr, "%.8f", mapextent.minx); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "west", BAD_CAST crdStr); sprintf(crdStr, "%.8f", mapextent.maxx); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "east", BAD_CAST crdStr); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "rotation", BAD_CAST "0.0"); return groundOverlayNode; } void KmlRenderer::startShape(imageObj *, shapeObj *shape) { if (PlacemarkNode) flushPlacemark(); CurrentShapeIndex=-1; CurrentDrawnShapeIndex = -1; CurrentShapeName=NULL; /*should be done at endshape but the plugin architecture does not call endshape yet*/ if(LineStyle) { msFree(LineStyle); LineStyle = NULL; numLineStyle = 0; } if (shape) { CurrentShapeIndex = shape->index; if (pszLayerNameAttributeMetadata) { for (int i=0; inumitems; i++) { if (strcasecmp(currentLayer->items[i], pszLayerNameAttributeMetadata) == 0 && shape->values[i]) { CurrentShapeName = msStrdup(shape->values[i]); break; } } } } PlacemarkNode = NULL; GeomNode = NULL; DescriptionNode = createDescriptionNode(shape); if( mElevationFromAttribute && shape->numvalues > mElevationAttributeIndex && mElevationAttributeIndex >= 0 && shape->values[mElevationAttributeIndex]) { mCurrentElevationValue = atof( shape->values[mElevationAttributeIndex] ); } memset(SymbologyFlag, 0, NumSymbologyFlag); } void KmlRenderer::endShape(imageObj*, shapeObj*) { CurrentShapeIndex = -1; if (CurrentShapeName) msFree(CurrentShapeName); CurrentShapeName = NULL; } xmlNodePtr KmlRenderer::getGeomParentNode(const char *geomName) { /*we do not need a multi-geometry for point layers*/ if (currentLayer->type != MS_LAYER_POINT && currentLayer->type != MS_LAYER_ANNOTATION && GeomNode) { /*placemark geometry already defined, we need multigeometry node*/ xmlNodePtr multiGeomNode = xmlNewNode(NULL, BAD_CAST "MultiGeometry"); xmlAddChild(multiGeomNode, GeomNode); GeomNode = multiGeomNode; xmlNodePtr geomNode = xmlNewChild(multiGeomNode, NULL, BAD_CAST geomName, NULL); return geomNode; } else { GeomNode = xmlNewNode(NULL, BAD_CAST geomName); return GeomNode; } } char* KmlRenderer::lookupSymbolUrl(imageObj *img, symbolObj *symbol, symbolStyleObj *symstyle) { char symbolHexColor[32]; /* */ sprintf(symbolHexColor,"%02x%02x%02x%02x", symstyle->style->color.alpha, symstyle->style->color.blue, symstyle->style->color.green, symstyle->style->color.red); snprintf(SymbolName, sizeof(SymbolName), "symbol_%s_%.1f_%s", symbol->name, symstyle->scale, symbolHexColor); char *symbolUrl = msLookupHashTable(StyleHashTable, SymbolName); if (!symbolUrl) { char iconFileName[MS_MAXPATHLEN]; char iconUrl[MS_MAXPATHLEN]; if (img->imagepath) { char *tmpFileName = msTmpFile(NULL, MapPath, img->imagepath, "png"); snprintf(iconFileName, sizeof(iconFileName), "%s", tmpFileName); msFree(tmpFileName); } else { sprintf(iconFileName, "symbol_%s_%.1f.%s", symbol->name, symstyle->scale, "png"); } if (createIconImage(iconFileName, symbol, symstyle) != MS_SUCCESS) { msSetError(MS_IOERR, "Error creating icon file '%s'", "KmlRenderer::lookupSymbolStyle()", iconFileName); return NULL; } if (img->imageurl) sprintf(iconUrl, "%s%s.%s", img->imageurl, msGetBasename(iconFileName), "png"); else snprintf(iconUrl, sizeof(iconUrl), "%s", iconFileName); hashObj *hash = msInsertHashTable(StyleHashTable, SymbolName, iconUrl); symbolUrl = hash->data; } return symbolUrl; } char* KmlRenderer::lookupPlacemarkStyle() { char lineHexColor[32]; char polygonHexColor[32]; char labelHexColor[32]; char *styleName=NULL; styleName = msStringConcatenate(styleName, "style"); if (SymbologyFlag[Line]) { /* ffffffff normal 1 */ for (int i=0; iopacity > 0 && currentLayer->opacity < 100 && LineStyle[i].color->alpha == 255) LineStyle[i].color->alpha = MS_NINT(currentLayer->opacity*2.55); sprintf(lineHexColor,"%02x%02x%02x%02x", LineStyle[i].color->alpha, LineStyle[0].color->blue, LineStyle[i].color->green, LineStyle[i].color->red); char lineStyleName[32]; sprintf(lineStyleName, "_line_%s_w%.1f", lineHexColor, LineStyle[i].width); styleName = msStringConcatenate(styleName, lineStyleName); } } if (SymbologyFlag[Polygon]) { /* ffffffff normal 1 1 */ if (currentLayer && currentLayer->opacity > 0 && currentLayer->opacity < 100 && PolygonColor.alpha == 255) PolygonColor.alpha = MS_NINT(currentLayer->opacity*2.55); sprintf(polygonHexColor,"%02x%02x%02x%02x", PolygonColor.alpha, PolygonColor.blue, PolygonColor.green, PolygonColor.red); char polygonStyleName[64]; sprintf(polygonStyleName, "_polygon_%s", polygonHexColor); styleName = msStringConcatenate(styleName, polygonStyleName); } if (SymbologyFlag[Label]) { /* ffffffff normal 1 */ if (currentLayer && currentLayer->opacity > 0 && currentLayer->opacity < 100 && LabelStyle.color->alpha == 255) LabelStyle.color->alpha = MS_NINT(currentLayer->opacity*2.55); sprintf(labelHexColor,"%02x%02x%02x%02x", LabelStyle.color->alpha, LabelStyle.color->blue, LabelStyle.color->green, LabelStyle.color->red); // __TODO__ add label scale char labelStyleName[64]; sprintf(labelStyleName, "_label_%s", labelHexColor); styleName = msStringConcatenate(styleName, labelStyleName); } if (SymbologyFlag[Symbol]) { /* */ /* __TODO__ add label scale */ styleName = msStringConcatenate(styleName, "_"); styleName = msStringConcatenate(styleName, SymbolName); } char *styleUrl = msLookupHashTable(StyleHashTable, styleName); if (!styleUrl) { char *styleValue=NULL; styleValue = msStringConcatenate(styleValue, "#"); styleValue = msStringConcatenate(styleValue, styleName); hashObj *hash = msInsertHashTable(StyleHashTable, styleName, styleValue); styleUrl = hash->data; msFree(styleValue); /* Insert new Style node into Document node*/ xmlNodePtr styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST styleName); if (SymbologyFlag[Polygon]) { xmlNodePtr polyStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "PolyStyle", NULL); xmlNewChild(polyStyleNode, NULL, BAD_CAST "color", BAD_CAST polygonHexColor); } if (SymbologyFlag[Line]) { for (int i=0; ialpha, LineStyle[i].color->blue, LineStyle[i].color->green, LineStyle[i].color->red); xmlNewChild(lineStyleNode, NULL, BAD_CAST "color", BAD_CAST lineHexColor); char width[16]; sprintf(width, "%.1f", LineStyle[i].width); xmlNewChild(lineStyleNode, NULL, BAD_CAST "width", BAD_CAST width); } } if (SymbologyFlag[Symbol]) { xmlNodePtr iconStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "IconStyle", NULL); xmlNodePtr iconNode = xmlNewChild(iconStyleNode, NULL, BAD_CAST "Icon", NULL); xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST SymbolUrl); /*char scale[16]; sprintf(scale, "%.1f", style->scale); xmlNewChild(iconStyleNode, NULL, BAD_CAST "scale", BAD_CAST scale);*/ } else { const char *value=msLookupHashTable(¤tLayer->metadata, "kml_default_symbol_href"); if (value && strlen(value) > 0) { xmlNodePtr iconStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "IconStyle", NULL); xmlNodePtr iconNode = xmlNewChild(iconStyleNode, NULL, BAD_CAST "Icon", NULL); xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST value); } } if (SymbologyFlag[Label]) { xmlNodePtr labelStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "LabelStyle", NULL); xmlNewChild(labelStyleNode, NULL, BAD_CAST "color", BAD_CAST labelHexColor); /*char scale[16]; sprintf(scale, "%.1f", style->scale); xmlNewChild(iconStyleNode, NULL, BAD_CAST "scale", BAD_CAST scale);*/ } } if (styleName) msFree(styleName); return styleUrl; } void KmlRenderer::flushPlacemark() { if (PlacemarkNode) { char *styleUrl = lookupPlacemarkStyle(); xmlNewChild(PlacemarkNode, NULL, BAD_CAST "styleUrl", BAD_CAST styleUrl); if (DescriptionNode) xmlAddChild(PlacemarkNode, DescriptionNode); if (GeomNode) xmlAddChild(PlacemarkNode, GeomNode); } } xmlNodePtr KmlRenderer::createDescriptionNode(shapeObj *shape) { /* */ /*description nodes for vector layers: - if kml_description is set, use it - if not, dump the attributes */ if (pszLayerDescMetadata) { char *pszTmp=NULL; char *pszTmpDesc = NULL; size_t bufferSize = 0; pszTmpDesc = msStrdup(pszLayerDescMetadata); for (int i=0; inumitems; i++) { bufferSize = strlen(currentLayer->items[i]) + 3; pszTmp = (char *)msSmallMalloc(bufferSize); snprintf(pszTmp, bufferSize, "%%%s%%",currentLayer->items[i]); if (strcasestr(pszTmpDesc, pszTmp)) pszTmpDesc = msCaseReplaceSubstring(pszTmpDesc, pszTmp, shape->values[i]); msFree(pszTmp); } xmlNodePtr descriptionNode = xmlNewNode(NULL, BAD_CAST "description"); xmlNodeAddContent(descriptionNode, BAD_CAST pszTmpDesc); msFree(pszTmpDesc); return descriptionNode; } else if ((papszLayerIncludeItems && nIncludeItems > 0) || (papszLayerExcludeItems && nExcludeItems > 0)) { /* -------------------------------------------------------------------- */ /* preffered way is to use the ExtendedData tag (#3728) */ /* http://code.google.com/apis/kml/documentation/extendeddata.html */ /* -------------------------------------------------------------------- */ xmlNodePtr extendedDataNode = xmlNewNode(NULL, BAD_CAST "ExtendedData"); xmlNodePtr dataNode = NULL; const char*pszAlias=NULL; int bIncludeAll = MS_FALSE; if(papszLayerIncludeItems && nIncludeItems == 1 && strcasecmp(papszLayerIncludeItems[0], "all") == 0) bIncludeAll = MS_TRUE; for (int i=0; inumitems; i++) { int j=0,k=0; /*TODO optimize to calculate this only once per layer*/ for (j=0; jitems[i], papszLayerIncludeItems[j]) == 0) break; } if (j 0) { for (k=0; kitems[i], papszLayerExcludeItems[k]) == 0) break; } } if (nExcludeItems == 0 || k == nExcludeItems) { dataNode = xmlNewNode(NULL, BAD_CAST "Data"); xmlNewProp(dataNode, BAD_CAST "name", BAD_CAST currentLayer->items[i]); pszAlias = getAliasName(currentLayer, currentLayer->items[i], "GO"); if (pszAlias) xmlNewChild(dataNode, NULL, BAD_CAST "displayName", BAD_CAST pszAlias); else xmlNewChild(dataNode, NULL, BAD_CAST "displayName", BAD_CAST currentLayer->items[i]); if (shape->values[i] && strlen(shape->values[i])) xmlNewChild(dataNode, NULL, BAD_CAST "value", BAD_CAST shape->values[i]); else xmlNewChild(dataNode, NULL, BAD_CAST "value", NULL); xmlAddChild(extendedDataNode, dataNode); } } } return extendedDataNode; } return NULL; } void KmlRenderer::addLineStyleToList(strokeStyleObj *style) { /*actually this is not necessary. kml only uses the last LineStyle so we should not bother keeping them all*/ int i =0; for (i=0; iwidth == LineStyle[i].width && LineStyle[i].color->alpha == style->color->alpha && LineStyle[i].color->red == style->color->red && LineStyle[i].color->green == style->color->green && LineStyle[i].color->blue == style->color->blue) break; } if (i == numLineStyle) { numLineStyle++; if (LineStyle == NULL) LineStyle = (strokeStyleObj *)msSmallMalloc(sizeof(strokeStyleObj)); else LineStyle = (strokeStyleObj *)msSmallRealloc(LineStyle, sizeof(strokeStyleObj)*numLineStyle); memcpy(&LineStyle[numLineStyle-1], style, sizeof(strokeStyleObj)); } } #endif mapserver-6.4.1/maprendering.c0000644002461700001440000011167112261257215016142 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Rendering utility functions * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2011 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. *****************************************************************************/ #include "mapserver.h" #include "mapcopy.h" int computeLabelStyle(labelStyleObj *s, labelObj *l, fontSetObj *fontset, double scalefactor, double resolutionfactor) { INIT_LABEL_STYLE(*s); if(!MS_VALID_COLOR(l->color)) return MS_FAILURE; if(l->size == -1) return MS_FAILURE; s->size = l->size; if(l->type == MS_TRUETYPE) { s->size *= scalefactor; s->size = MS_MAX(s->size, l->minsize*resolutionfactor); s->size = MS_MIN(s->size, l->maxsize*resolutionfactor); if (!fontset) { msSetError(MS_TTFERR, "No fontset defined.","computeLabelStyle()"); return (MS_FAILURE); } if (!l->font || !(*l->font)) { return (MS_FAILURE); } if(MS_FAILURE == msFontsetLookupFonts(l->font,&s->numfonts,fontset,s->fonts)) { return MS_FAILURE; } } s->rotation = l->angle * MS_DEG_TO_RAD; s->antialias = l->antialias; return MS_SUCCESS; } void computeSymbolStyle(symbolStyleObj *s, styleObj *src, symbolObj *symbol, double scalefactor, double resolutionfactor) { double default_size; double target_size; double style_size; default_size = msSymbolGetDefaultSize(symbol); style_size = (src->size==-1)?default_size:src->size; INIT_SYMBOL_STYLE(*s); if(symbol->type == MS_SYMBOL_PIXMAP) { s->color = s->outlinecolor = NULL; } else if(symbol->filled || symbol->type == MS_SYMBOL_TRUETYPE) { if(MS_VALID_COLOR(src->color)) s->color = &src->color; if(MS_VALID_COLOR(src->outlinecolor)) s->outlinecolor = &src->outlinecolor; } else { if(MS_VALID_COLOR(src->color)) s->outlinecolor = &(src->color); else if(MS_VALID_COLOR(src->outlinecolor)) s->outlinecolor = &(src->outlinecolor); s->color = NULL; } if(MS_VALID_COLOR(src->backgroundcolor)) { s->backgroundcolor = &(src->backgroundcolor); } target_size = style_size * scalefactor; target_size = MS_MAX(target_size, src->minsize*resolutionfactor); target_size = MS_MIN(target_size, src->maxsize*resolutionfactor); s->scale = target_size / default_size; s->gap = src->gap * target_size / style_size; if(s->outlinecolor) { s->outlinewidth = src->width * scalefactor; s->outlinewidth = MS_MAX(s->outlinewidth, src->minwidth*resolutionfactor); s->outlinewidth = MS_MIN(s->outlinewidth, src->maxwidth*resolutionfactor); } else { s->outlinewidth = 0; } s->rotation = src->angle * MS_DEG_TO_RAD; } #define COMPARE_COLORS(a,b) (\ ((a).red==(b).red) && \ ((a).green==(b).green) && \ ((a).blue==(b).blue) && \ ((a).alpha==(b).alpha)) tileCacheObj *searchTileCache(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int width, int height) { tileCacheObj *cur = img->tilecache; while(cur != NULL) { if( cur->width == width && cur->height == height && cur->symbol == symbol && cur->outlinewidth == s->outlinewidth && cur->rotation == s->rotation && cur->scale == s->scale && (!s->color || COMPARE_COLORS(cur->color,*s->color)) && (!s->backgroundcolor || COMPARE_COLORS(cur->backgroundcolor,*s->backgroundcolor)) && (!s->outlinecolor || COMPARE_COLORS(cur->outlinecolor,*s->outlinecolor))) return cur; cur = cur->next; } return NULL; } int preloadSymbol(symbolSetObj *symbolset, symbolObj *symbol, rendererVTableObj *renderer) { switch(symbol->type) { case MS_SYMBOL_VECTOR: case MS_SYMBOL_ELLIPSE: case MS_SYMBOL_SIMPLE: break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) return msPreloadSVGSymbol(symbol); #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "preloadSymbol()"); return MS_FAILURE; #endif break; case (MS_SYMBOL_TRUETYPE): { if(!symbol->full_font_path) symbol->full_font_path = msStrdup(msLookupHashTable(&(symbolset->fontset->fonts), symbol->font)); if(!symbol->full_font_path) { msSetError(MS_MEMERR,"allocation error", "preloadSymbol()"); return MS_FAILURE; } } break; case (MS_SYMBOL_PIXMAP): { if(!symbol->pixmap_buffer) { if(MS_SUCCESS != msPreloadImageSymbol(renderer,symbol)) return MS_FAILURE; } } break; default: msSetError(MS_MISCERR,"unsupported symbol type %d", "preloadSymbol()", symbol->type); return MS_FAILURE; } return MS_SUCCESS; } /* add a cached tile to the current image's cache */ tileCacheObj *addTileCache(imageObj *img, imageObj *tile, symbolObj *symbol, symbolStyleObj *style, int width, int height) { tileCacheObj *cachep; if(img->ntiles >= MS_IMAGECACHESIZE) { /* remove last element, size stays the same */ cachep = img->tilecache; /*go to the before last cache object*/ while(cachep->next && cachep->next->next) cachep = cachep->next; /*free the last tile's data*/ msFreeImage(cachep->next->image); /*reuse the last tile object*/ /* make the cache point to the start of the list*/ cachep->next->next = img->tilecache; /* point the global cache to the new first */ img->tilecache = cachep->next; /* the before last cache is now last, so it has no successor*/ cachep->next = NULL; } else { img->ntiles += 1; cachep = (tileCacheObj*)malloc(sizeof(tileCacheObj)); MS_CHECK_ALLOC(cachep, sizeof(tileCacheObj), NULL); cachep->next = img->tilecache; img->tilecache = cachep; } cachep = img->tilecache; cachep->image = tile; cachep->outlinewidth = style->outlinewidth; cachep->scale = style->scale; cachep->rotation = style->rotation; cachep->outlinewidth = style->outlinewidth; if(style->color) MS_COPYCOLOR(&cachep->color,style->color); if(style->outlinecolor) MS_COPYCOLOR(&cachep->outlinecolor,style->outlinecolor); if(style->backgroundcolor) MS_COPYCOLOR(&cachep->backgroundcolor,style->backgroundcolor); cachep->width = width; cachep->height = height; cachep->symbol = symbol; return(cachep); } imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int width, int height, int seamlessmode) { tileCacheObj *tile; rendererVTableObj *renderer = img->format->vtable; if(width==-1 || height == -1) { width=height=MS_MAX(symbol->sizex,symbol->sizey); } tile = searchTileCache(img,symbol,s,width,height); if(tile==NULL) { imageObj *tileimg; double p_x,p_y; tileimg = msImageCreate(width,height,img->format,NULL,NULL,img->resolution, img->resolution, NULL); if(!seamlessmode) { p_x = width/2.0; p_y = height/2.0; switch(symbol->type) { case (MS_SYMBOL_TRUETYPE): renderer->renderTruetypeSymbol(tileimg, p_x, p_y, symbol, s); break; case (MS_SYMBOL_PIXMAP): renderer->renderPixmapSymbol(tileimg, p_x, p_y, symbol, s); break; case (MS_SYMBOL_ELLIPSE): renderer->renderEllipseSymbol(tileimg, p_x, p_y,symbol, s); break; case (MS_SYMBOL_VECTOR): renderer->renderVectorSymbol(tileimg, p_x, p_y, symbol, s); break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (renderer->supports_svg) { if(renderer->renderSVGSymbol(tileimg, p_x, p_y, symbol, s) != MS_SUCCESS) { return NULL; } } else { if (msRenderRasterizedSVGSymbol(tileimg,p_x,p_y,symbol, s) != MS_SUCCESS) { return NULL; } } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "getTile()"); return NULL; #endif break; default: break; } } else { /* * in seamless mode, we render the the symbol 9 times on a 3x3 grid to account for * antialiasing blending from one tile to the next. We finally keep the center tile */ imageObj *tile3img = msImageCreate(width*3,height*3,img->format,NULL,NULL, img->resolution, img->resolution, NULL); int i,j; rasterBufferObj tmpraster; for(i=1; i<=3; i++) { p_x = (i+0.5)*width; for(j=1; j<=3; j++) { p_y = (j+0.5) * height; switch(symbol->type) { case (MS_SYMBOL_VECTOR): renderer->renderVectorSymbol(tile3img, p_x, p_y, symbol, s); break; default: msSetError(MS_SYMERR, "BUG: Seamless mode is only for vector symbols", "getTile()"); return NULL; } } } MS_IMAGE_RENDERER(tile3img)->getRasterBufferHandle(tile3img,&tmpraster); renderer->mergeRasterBuffer(tileimg, &tmpraster, 1.0,width,height,0,0,width,height ); msFreeImage(tile3img); } tile = addTileCache(img,tileimg,symbol,s,width,height); } return tile->image; } int msImagePolylineMarkers(imageObj *image, shapeObj *p, symbolObj *symbol, symbolStyleObj *style, double spacing, double initialgap, int auto_angle) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); int i,j; pointObj point; double original_rotation = style->rotation; double symbol_width,symbol_height; int ret = MS_FAILURE; if(symbol->type != MS_SYMBOL_TRUETYPE) { symbol_width = MS_MAX(1,symbol->sizex*style->scale); symbol_height = MS_MAX(1,symbol->sizey*style->scale); } else { rectObj rect; if(MS_SUCCESS != renderer->getTruetypeTextBBox(renderer,&symbol->full_font_path,1,style->scale, symbol->character,&rect,NULL,0)) return MS_FAILURE; symbol_width=rect.maxx-rect.minx; symbol_height=rect.maxy-rect.miny; } for(i=0; inumlines; i++) { int line_in = 0; double line_length=0; double current_length; if(initialgap < 0) { current_length = spacing/2.0; /* initial padding for each line */ } else { current_length = initialgap; /* initial padding for each line */ } for(j=1; jline[i].numpoints; j++) { double rx,ry,theta,length; length = sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2))); line_length += length; if(length==0)continue; rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length; ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length; if (auto_angle) { theta = asin(ry); if(rx < 0) { theta += MS_PI; } else theta = -theta; style->rotation = original_rotation + theta; } while (current_length <= length) { point.x = p->line[i].point[j - 1].x + current_length * rx; point.y = p->line[i].point[j - 1].y + current_length * ry; if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) { double ox, oy; ox = (0.5 - symbol->anchorpoint_x) * symbol_width; oy = (0.5 - symbol->anchorpoint_y) * symbol_height; if(style->rotation != 0) { double sina,cosa; double rox,roy; sina = sin(-style->rotation); cosa = cos(-style->rotation); rox = ox * cosa - oy * sina; roy = ox * sina + oy * cosa; point.x += rox; point.y += roy; } else { point.x += ox; point.y += oy; } } /* if the point is not in the map extent, skip it. (POLYLINE_NO_CLIP) */ if ( (point.x < -(symbol_width) || point.x > (image->width+symbol_width)) || (point.y < -(symbol_height) || point.y > (image->height+symbol_height)) ) { current_length += spacing; line_in=1; continue; } switch (symbol->type) { case MS_SYMBOL_PIXMAP: ret = renderer->renderPixmapSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_ELLIPSE: ret = renderer->renderEllipseSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_VECTOR: ret = renderer->renderVectorSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_TRUETYPE: ret = renderer->renderTruetypeSymbol(image, point.x, point.y, symbol, style); break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (renderer->supports_svg) { ret = renderer->renderSVGSymbol(image, point.x, point.y, symbol, style); } else { ret = msRenderRasterizedSVGSymbol(image,point.x,point.y,symbol, style); } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msImagePolylineMarkers()()"); ret = MS_FAILURE; #endif break; } if( ret != MS_SUCCESS) return ret; current_length += spacing; line_in=1; } current_length -= length; } /* * if we couldn't place a symbol on the line and no initialgap was * specified, add one now we don't add the symbol if the line is shorter * than the length of the symbol itself */ if(initialgap < 0 && !line_in && line_length>symbol_width) { /* total lengths of beginnning and end of current segment */ double before_length=0,after_length=0; /*optimize*/ line_length /= 2.0; for(j=1; jline[i].numpoints; j++) { double length; length = sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2))); after_length += length; if(after_length>line_length) { double rx,ry,theta; /* offset where the symbol should be drawn on the current * segment */ double offset = line_length - before_length; rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length; ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length; if (auto_angle) { theta = asin(ry); if(rx < 0) { theta += MS_PI; } else theta = -theta; style->rotation = original_rotation + theta; } point.x = p->line[i].point[j - 1].x + offset * rx; point.y = p->line[i].point[j - 1].y + offset * ry; switch (symbol->type) { case MS_SYMBOL_PIXMAP: ret = renderer->renderPixmapSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_ELLIPSE: ret = renderer->renderEllipseSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_VECTOR: ret = renderer->renderVectorSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_TRUETYPE: ret = renderer->renderTruetypeSymbol(image, point.x, point.y, symbol, style); break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (renderer->supports_svg) { ret = renderer->renderSVGSymbol(image, point.x, point.y, symbol, style); } else { ret = msRenderRasterizedSVGSymbol(image,point.x,point.y,symbol, style); } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msImagePolylineMarkers()()"); ret = MS_FAILURE; #endif break; } break; /* we have rendered the single marker for this line */ } before_length += length; } } } return ret; } int msDrawLineSymbol(symbolSetObj *symbolset, imageObj *image, shapeObj *p, styleObj *style, double scalefactor) { if (image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; symbolObj *symbol; shapeObj *offsetLine = p; int i; double width; double finalscalefactor; if (p->numlines == 0) return MS_SUCCESS; if (style->symbol >= symbolset->numsymbols || style->symbol < 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ symbol = symbolset->symbol[style->symbol]; /* store a reference to the renderer to be used for freeing */ symbol->renderer = renderer; width = style->width * scalefactor; width = MS_MIN(width,style->maxwidth*image->resolutionfactor); width = MS_MAX(width,style->minwidth*image->resolutionfactor); if(style->width != 0) { finalscalefactor = width / style->width; } else { finalscalefactor = 1.0; } if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) { offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_SINGLE_SIDED_OFFSET); } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) { offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET); } else if(style->offsetx!=0 || style->offsety!=0) { offsetLine = msOffsetPolyline(p, style->offsetx * finalscalefactor, style->offsety * finalscalefactor); } if(style->symbol == 0 || (symbol->type==MS_SYMBOL_SIMPLE)) { strokeStyleObj s; s.linecap = style->linecap; s.linejoin = style->linejoin; s.linejoinmaxsize = style->linejoinmaxsize; s.width = width; s.patternlength = style->patternlength; for(i=0; ipattern[i] * finalscalefactor; s.patternoffset = (style->initialgap<=0) ? 0 : (style->initialgap * finalscalefactor); if(MS_VALID_COLOR(style->color)) s.color = &style->color; else if(MS_VALID_COLOR(style->outlinecolor)) s.color = &style->outlinecolor; else { /* msSetError(MS_MISCERR,"no color defined for line styling","msDrawLineSymbol()"); * not really an error */ return MS_SUCCESS; } renderer->renderLine(image,offsetLine,&s); } else { symbolStyleObj s; if(preloadSymbol(symbolset, symbol, renderer) != MS_SUCCESS) { return MS_FAILURE; } INIT_SYMBOL_STYLE(s); computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; /* compute a markerStyle and use it on the line */ if(style->gap<0) { /* special function that treats any other symbol used as a marker, not a brush */ msImagePolylineMarkers(image,offsetLine,symbol,&s,-s.gap, style->initialgap * finalscalefactor, 1); } else if(style->gap>0) { msImagePolylineMarkers(image,offsetLine,symbol,&s,s.gap, style->initialgap * finalscalefactor,0); } else { if(renderer->renderLineTiled != NULL) { int pw,ph; imageObj* tile=NULL; if(s.scale != 1) { pw = MS_NINT(symbol->sizex * s.scale); ph = MS_NINT(symbol->sizey * s.scale); } else { pw = symbol->sizex; ph = symbol->sizey; } if(pw<1) pw=1; if(ph<1) ph=1; tile = getTile(image, symbol,&s,pw,ph,0); renderer->renderLineTiled(image, offsetLine, tile); } else { msSetError(MS_RENDERERERR, "renderer does not support brushed lines", "msDrawLineSymbol()"); return MS_FAILURE; } } } if(offsetLine!=p) { msFreeShape(offsetLine); msFree(offsetLine); } } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawLineSymbolIM(symbolset, image, p, style, scalefactor); else { msSetError(MS_RENDERERERR, "unsupported renderer", "msDrawShadeSymbol()"); return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } int msDrawShadeSymbol(symbolSetObj *symbolset, imageObj *image, shapeObj *p, styleObj *style, double scalefactor) { int ret = MS_SUCCESS; if (!p) return MS_SUCCESS; if (p->numlines <= 0) return MS_SUCCESS; if (style->symbol >= symbolset->numsymbols || style->symbol < 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ /* * if only an outlinecolor was defined, and not a color, * switch to the line drawing function * * this behavior is kind of a mapfile hack, and must be * kept for backwards compatibility */ if (symbolset->symbol[style->symbol]->type != MS_SYMBOL_PIXMAP && symbolset->symbol[style->symbol]->type != MS_SYMBOL_SVG ) { if (!MS_VALID_COLOR(style->color)) { if(MS_VALID_COLOR(style->outlinecolor)) return msDrawLineSymbol(symbolset, image, p, style, scalefactor); else { /* just do nothing if no color has been set */ return MS_SUCCESS; } } } if (image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; shapeObj *offsetPolygon = NULL; symbolObj *symbol = symbolset->symbol[style->symbol]; /* store a reference to the renderer to be used for freeing */ if(style->symbol) symbol->renderer = renderer; if (style->offsetx != 0 || style->offsety != 0) { if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) { offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor, MS_STYLE_SINGLE_SIDED_OFFSET); } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) { offsetPolygon = msOffsetPolyline(p,style->offsetx * scalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET); } else { offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor,style->offsety*scalefactor); } } else { offsetPolygon=p; } /* simple polygon drawing, without any specific symbol. * also draws an optional outline */ if(style->symbol == 0 || symbol->type == MS_SYMBOL_SIMPLE) { ret = renderer->renderPolygon(image,offsetPolygon,&style->color); if(ret != MS_SUCCESS) goto cleanup; if(MS_VALID_COLOR(style->outlinecolor)) { strokeStyleObj s; INIT_STROKE_STYLE(s); s.color = &style->outlinecolor; s.color->alpha = style->color.alpha; s.width = (style->width == 0)?scalefactor:style->width*scalefactor; s.width = MS_MIN(s.width, style->maxwidth); s.width = MS_MAX(s.width, style->minwidth); ret = renderer->renderLine(image,offsetPolygon,&s); } goto cleanup; /*finished plain polygon*/ } else if(symbol->type == MS_SYMBOL_HATCH) { double width, spacing; double pattern[MS_MAXPATTERNLENGTH]; int i; if(MS_VALID_COLOR(style->backgroundcolor)) { ret = renderer->renderPolygon(image,offsetPolygon, &style->backgroundcolor); if(ret != MS_SUCCESS) goto cleanup; } width = (style->width <= 0)?scalefactor:style->width*scalefactor; width = MS_MIN(width, style->maxwidth*image->resolutionfactor); width = MS_MAX(width, style->minwidth*image->resolutionfactor); spacing = (style->size <= 0)?scalefactor:style->size*scalefactor; spacing = MS_MIN(spacing, style->maxsize*image->resolutionfactor); spacing = MS_MAX(spacing, style->minsize*image->resolutionfactor); /* scale the pattern by the factor applied to the width */ for(i=0; ipatternlength; i++) { pattern[i] = style->pattern[i]*width/style->width; } ret = msHatchPolygon(image,offsetPolygon,spacing,width,pattern,style->patternlength,style->angle, &style->color); goto cleanup; } else { symbolStyleObj s; int pw,ph; imageObj *tile; int seamless = 0; if(preloadSymbol(symbolset,symbol,renderer) != MS_SUCCESS) { return MS_FAILURE; } INIT_SYMBOL_STYLE(s); computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; if (!s.color && !s.outlinecolor && symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG) { ret = MS_SUCCESS; /* nothing to do (colors are required except for PIXMAP symbols */ goto cleanup; } if(s.backgroundcolor) { ret = renderer->renderPolygon(image,offsetPolygon, s.backgroundcolor); if(ret != MS_SUCCESS) goto cleanup; } if(s.scale != 1) { if (s.gap > 0) { pw = MS_MAX(MS_NINT(s.gap),symbol->sizex * s.scale); ph = MS_MAX(MS_NINT(s.gap),symbol->sizey * s.scale); } else { pw = MS_NINT(symbol->sizex * s.scale); ph = MS_NINT(symbol->sizey * s.scale); } } else { if (s.gap > 0) { pw = MS_MAX(s.gap,symbol->sizex); ph = MS_MAX(s.gap,symbol->sizey); } else { pw = symbol->sizex; ph = symbol->sizey; } } if(pw<1) pw=1; if(ph<1) ph=1; /* if we're doing vector symbols with an antialiased pixel rendererer, we want to enable * seamless mode, i.e. comute a tile that accounts for the blending of neighbouring * tiles at the tile border */ if(symbol->type == MS_SYMBOL_VECTOR && style->gap == 0 && (image->format->renderer == MS_RENDER_WITH_AGG || image->format->renderer == MS_RENDER_WITH_CAIRO_RASTER)) { seamless = 1; } tile = getTile(image,symbol,&s,pw,ph,seamless); ret = renderer->renderPolygonTiled(image,offsetPolygon, tile); } cleanup: if (offsetPolygon != p) { msFreeShape(offsetPolygon); msFree(offsetPolygon); } return ret; } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawShadeSymbolIM(symbolset, image, p, style, scalefactor); } return ret; } int msDrawMarkerSymbol(symbolSetObj *symbolset,imageObj *image, pointObj *p, styleObj *style, double scalefactor) { int ret = MS_SUCCESS; if (!p) return MS_SUCCESS; if (style->symbol >= symbolset->numsymbols || style->symbol <= 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ if (image) { if(MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; symbolStyleObj s; double p_x,p_y; symbolObj *symbol = symbolset->symbol[style->symbol]; /* store a reference to the renderer to be used for freeing */ symbol->renderer = renderer; if(preloadSymbol(symbolset,symbol,renderer) != MS_SUCCESS) { return MS_FAILURE; } computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; if (!s.color && !s.outlinecolor && symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG) { return MS_SUCCESS; // nothing to do if no color, except for pixmap symbols } if(s.scale == 0) { return MS_SUCCESS; } /* TODO: skip the drawing of the symbol if it's smaller than a pixel ? if (s.size < 1) return; // size too small */ p_x = p->x; p_y = p->y; if (style->polaroffsetpixel != 0 || style->polaroffsetangle != 0) { double angle = style->polaroffsetangle * MS_DEG_TO_RAD; p_x += (style->polaroffsetpixel * cos(-angle)) * scalefactor; p_y += (style->polaroffsetpixel * sin(-angle)) * scalefactor; } p_x += style->offsetx * scalefactor; p_y += style->offsety * scalefactor; if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) { double sx,sy; double ox, oy; msGetMarkerSize(symbolset, style, &sx, &sy, scalefactor); ox = (0.5 - symbol->anchorpoint_x) * sx; oy = (0.5 - symbol->anchorpoint_y) * sy; if(s.rotation != 0) { double sina, cosa; double rox,roy; sina = sin(-s.rotation); cosa = cos(-s.rotation); rox = ox * cosa - oy * sina; roy = ox * sina + oy * cosa; p_x += rox; p_y += roy; } else { p_x += ox; p_y += oy; } } if(renderer->use_imagecache) { imageObj *tile = getTile(image, symbol, &s, -1, -1,0); if(tile!=NULL) return renderer->renderTile(image, tile, p_x, p_y); else { msSetError(MS_RENDERERERR, "problem creating cached tile", "msDrawMarkerSymbol()"); return MS_FAILURE; } } switch (symbol->type) { case (MS_SYMBOL_TRUETYPE): { assert(symbol->full_font_path); ret = renderer->renderTruetypeSymbol(image, p_x, p_y, symbol, &s); } break; case (MS_SYMBOL_PIXMAP): { assert(symbol->pixmap_buffer); ret = renderer->renderPixmapSymbol(image,p_x,p_y,symbol,&s); } break; case (MS_SYMBOL_ELLIPSE): { ret = renderer->renderEllipseSymbol(image, p_x, p_y,symbol, &s); } break; case (MS_SYMBOL_VECTOR): { ret = renderer->renderVectorSymbol(image, p_x, p_y, symbol, &s); } break; case (MS_SYMBOL_SVG): { if (renderer->supports_svg) { ret = renderer->renderSVGSymbol(image, p_x, p_y, symbol, &s); } else { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) ret = msRenderRasterizedSVGSymbol(image, p_x,p_y, symbol, &s); #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msDrawMarkerSymbol()"); return MS_FAILURE; #endif } } break; default: break; } return ret; } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawMarkerSymbolIM(symbolset, image, p, style, scalefactor); } return ret; } /* ** Render the text (no background effects) for a label. */ int msDrawText(imageObj *image, pointObj labelPnt, char *string, labelObj *label, fontSetObj *fontset, double scalefactor) { int nReturnVal = -1; if (image) { if (MS_RENDERER_PLUGIN(image->format)) { labelStyleObj s; rendererVTableObj *renderer = image->format->vtable; double x, y; if (!string || !strlen(string)) return (0); /* not errors, just don't want to do anything */ if(computeLabelStyle(&s,label,fontset,scalefactor,image->resolutionfactor) == MS_FAILURE) { return MS_FAILURE; } if(s.rotation == 0 && !MS_RENDERER_KML(image->format)) { x = MS_NINT(labelPnt.x); y = MS_NINT(labelPnt.y); } else { x = labelPnt.x; y = labelPnt.y; } if (label->type == MS_TRUETYPE) { if(MS_VALID_COLOR(label->shadowcolor)) { s.color = &label->shadowcolor; /* FIXME labelpoint for rotated label */ renderer->renderGlyphs(image, x + scalefactor * label->shadowsizex,y + scalefactor * label->shadowsizey, &s,string); } s.color= &label->color; if(MS_VALID_COLOR(label->outlinecolor)) { s.outlinecolor = &label->outlinecolor; s.outlinewidth = label->outlinewidth * s.size/label->size; } return renderer->renderGlyphs(image,x,y,&s,string); } else if(label->type == MS_BITMAP) { s.size = MS_NINT(s.size); s.color= &label->color; s.size = MS_MIN(s.size,5); /* only have 5 bitmap fonts */ if(!renderer->supports_bitmap_fonts || !renderer->bitmapFontMetrics[MS_NINT(s.size)]) { msSetError(MS_RENDERERERR, "selected renderer does not support bitmap fonts or this particular size", "msDrawText()"); return MS_FAILURE; } return renderer->renderBitmapGlyphs(image,x,y,&s,string); } } else if( MS_RENDERER_IMAGEMAP(image->format) ) nReturnVal = msDrawTextIM(image, labelPnt, string, label, fontset, scalefactor); } return nReturnVal; } int msDrawTextLine(imageObj *image, char *string, labelObj *label, labelPathObj *labelpath, fontSetObj *fontset, double scalefactor) { int nReturnVal = MS_SUCCESS; if(image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; labelStyleObj s; if (!string || !strlen(string)) return (MS_SUCCESS); /* not errors, just don't want to do anything */ if(computeLabelStyle(&s, label, fontset, scalefactor,image->resolutionfactor) != MS_SUCCESS) return MS_FAILURE; if (label->type == MS_TRUETYPE) { if(renderer->renderGlyphsLine) { if(MS_VALID_COLOR(label->outlinecolor)) { s.outlinecolor = &(label->outlinecolor); s.outlinewidth = s.size/label->size * label->outlinewidth; } else { s.outlinewidth = 0; s.outlinecolor = NULL; } s.color = &(label->color); nReturnVal = renderer->renderGlyphsLine(image,labelpath,&s,string); } else { /* * if the renderer doesn't support direct labelPath usage, * decompose the string and send it down character by character */ const char* string_ptr = string; int i; double x, y; char glyph[11]; /* * we first render all the outlines if present, so that the * joining of characters stays correct */ if(MS_VALID_COLOR(label->outlinecolor)) { s.outlinecolor = &(label->outlinecolor); s.outlinewidth = s.size/label->size * label->outlinewidth; for (i = 0; i < labelpath->path.numpoints; i++) { if (msGetNextGlyph(&string_ptr, glyph) == -1) break; /* Premature end of string??? */ s.rotation = labelpath->angles[i]; x = labelpath->path.point[i].x; y = labelpath->path.point[i].y; nReturnVal = renderer->renderGlyphs(image, x, y, &s, glyph); if(nReturnVal != MS_SUCCESS) { return nReturnVal; } } string_ptr = string; /* reset to beginning of string */ } s.outlinecolor = NULL; s.outlinewidth = 0; s.color = &(label->color); for (i = 0; i < labelpath->path.numpoints; i++) { if (msGetNextGlyph(&string_ptr, glyph) == -1) break; /* Premature end of string??? */ s.rotation = labelpath->angles[i]; x = labelpath->path.point[i].x; y = labelpath->path.point[i].y; nReturnVal = renderer->renderGlyphs(image, x, y, &s, glyph); if(nReturnVal != MS_SUCCESS) { return nReturnVal; } } } } } } return nReturnVal; } int msCircleDrawShadeSymbol(symbolSetObj *symbolset, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor) { shapeObj *circle; if (!image) return MS_FAILURE; circle = msRasterizeArc(p->x, p->y, r, 0, 360, 0); if (!circle) return MS_FAILURE; msDrawShadeSymbol(symbolset, image, circle, style, scalefactor); msFreeShape(circle); msFree(circle); return MS_SUCCESS; } int msDrawPieSlice(symbolSetObj *symbolset, imageObj *image, pointObj *p, styleObj *style, double radius, double start, double end) { shapeObj *circle; double center_x = p->x; double center_y = p->y; if (!image) return MS_FAILURE; if(style->offsetx>0) { center_x+=style->offsetx*cos(((-start-end)*MS_PI/360.)); center_y-=style->offsetx*sin(((-start-end)*MS_PI/360.)); } circle = msRasterizeArc(center_x, center_y, radius, start, end, 1); if (!circle) return MS_FAILURE; msDrawShadeSymbol(symbolset, image, circle, style, 1.0); msFreeShape(circle); msFree(circle); return MS_SUCCESS; } mapserver-6.4.1/tile4ms.c0000644002461700001440000002176212261257215015051 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Create shapefile of rectangles from extents of several shapefiles * (=tiles) * Create DBF with file names for shape tiles, in column LOCATION as * required by mapserv. * For use with Mapserv tiling capability. * Author: Herbie Freytag hfreytag@dlwc.nsw.gov.au * * Note: * Resulting shape files do not display in ArcView. * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ /* * This is a modified version of Herbie's program that works with MapServer's * shapelib and should be using the MapServer makefile. * */ #include "mapserver.h" #include /***********************************************************************/ int process_shapefiles(char *metaFileNameP, char *tileFileNameP, int tile_path_only) { SHPHandle hSHP, tileSHP; rectObj extentRect; lineObj line; shapeObj shapeRect; DBFHandle tileDBF; DBFHandle shpDBF; typedef struct DBFFieldDef_struct { DBFFieldType type; char name[12]; int width; int decimals; } DBFFieldDef; DBFFieldDef *theFields = NULL; char fldname[256]; int width; int decimals; int fieldCnt; int i; FILE *metaFP = NULL; char *p; char tileshapeName[256]; char tiledbfName[256]; char shapeFileName[256]; int entityNum; int tilesFound = 0; int tilesProcessed = 0; msInitShape(&shapeRect); line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5); line.numpoints = 5; /* open metafile */ /* ------------- */ if (NULL==(metaFP=fopen(metaFileNameP, "r"))) { printf( "Unable to open:%s\n", metaFileNameP); return(1); } /* create new tileindex shapefiles and create a header */ /* -------------------------------------------------- */ snprintf(tileshapeName, sizeof(tileshapeName), "%s.shp", tileFileNameP); if(NULL==(tileSHP=msSHPCreate(tileFileNameP, SHP_POLYGON))) { fclose(metaFP); printf("Unable to create %s.shp (.shx)\n", tileFileNameP); return(1); } /* create new tileindex dbf-file */ /* ----------------------------- */ snprintf(tiledbfName, sizeof(tiledbfName), "%s.dbf", tileFileNameP); if (NULL==(tileDBF=msDBFCreate(tiledbfName))) { fclose(metaFP); msSHPClose(tileSHP); printf("DBFCreate(%s) failed.\n", tiledbfName); return(1); } if(msDBFAddField(tileDBF, "LOCATION", FTString, 255, 0 )== -1 ) { fclose(metaFP); msSHPClose(tileSHP); msDBFClose(tileDBF); printf("DBFAddField(fieldname='LOCATION') failed.\n"); return(1); } /* loop through files listed in metafile */ /* ===================================== */ while (fgets(shapeFileName, 255, metaFP)) { if ((p=strchr(shapeFileName, '\n')) != NULL) *p='\0'; if (!strlen(shapeFileName)) break; tilesFound++; /* read the DBFFields for this shapefile */ /* and save them if the first, otherwise compare them */ shpDBF = msDBFOpen(shapeFileName, "rb"); if( shpDBF == NULL ) { printf( "Aborted. Unable to open DBF:%s\n", shapeFileName); break; } if( theFields == NULL ) { fieldCnt = msDBFGetFieldCount(shpDBF); theFields = (DBFFieldDef *) msSmallCalloc(fieldCnt, sizeof(DBFFieldDef)); for (i=0; i 4 && (p=shapeFileName+strlen(shapeFileName)-4) && strcasecmp(p, ".shp") == 0) *p = '\0'; if (!strlen(shapeFileName)) break; /* read extent from shapefile */ /* -------------------------- */ hSHP = msSHPOpen(shapeFileName, "rb"); if( hSHP == NULL ) { printf( "Aborted. Unable to open SHP:%s\n", shapeFileName); break; } msSHPReadBounds(hSHP, -1, &extentRect); /* SHPGetInfo(hSHP, &nEntities, &nShapeType, adfBndsMin, adfBndsMax); */ /* printf("File: %s Bounds 0/1: (%15.10lg,%15.10lg)\n\t(%15.10lg,%15.10lg)\n", shapeFileName, adfBndsMin[0], adfBndsMin[1], adfBndsMax[0], adfBndsMax[1] ); */ msSHPClose(hSHP); /* create rectangle describing current shapefile extent */ /* ---------------------------------------------------- */ line.point[0].x = line.point[4].x = extentRect.minx; /* bottom left */ line.point[0].y = line.point[4].y = extentRect.miny; line.point[1].x = extentRect.minx; /* top left */ line.point[1].y = extentRect.maxy; line.point[2].x = extentRect.maxx; /* top left */ line.point[2].y = extentRect.maxy; line.point[3].x = extentRect.maxx; /* bottom right */ line.point[3].y = extentRect.miny; /* create and add shape object. Returns link to entry in DBF file */ /* --------------------------------------------------------------- */ shapeRect.type = MS_SHAPE_POLYGON; msAddLine(&shapeRect, &line); entityNum = msSHPWriteShape( tileSHP, &shapeRect ); msFreeShape(&shapeRect); /* store filepath of current shapefile as attribute of rectangle */ /* ------------------------------------------------------------- */ /* Strip off filename if requested */ if (tile_path_only) { char *pszTmp; if ((pszTmp = strrchr(shapeFileName, '/')) != NULL || (pszTmp = strrchr(shapeFileName, '\\')) != NULL ) { *(pszTmp+1) = '\0'; /* Keep the trailing '/' only. */ } } msDBFWriteStringAttribute(tileDBF, entityNum, 0, shapeFileName); tilesProcessed++; } msSHPClose(tileSHP); msDBFClose(tileDBF); fclose(metaFP); free(line.point); printf("Processed %i of %i files\n", tilesProcessed, tilesFound); return (0); } /***********************************************************************/ void print_usage_and_exit(void) { printf("\nusage: tile4ms [-tile-path-only]\n"); printf("\tINPUT file containing list of shapefile names\n\t\t(complete paths 255 chars max, no extension)\n"); printf("\tOUTPUT shape file of extent rectangles and names\n\t\tof tiles in .dbf\n"); printf("-tile-path-only\tOptional flag. If specified then only the path to the \n\t\tshape files will be stored in the LOCATION field\n\t\tinstead of storing the full filename.\n\n"); exit(1); } /***********************************************************************/ int main( int argc, char **argv ) { int tile_path_only = 0; /* stun user with existence of help */ /* -------------------------------- */ if ((argc == 2)&&(strstr(argv[1], "-h"))) { print_usage_and_exit(); } /* check arguments */ /* --------------- */ if( argc < 3 ) { print_usage_and_exit(); } if ( argc == 4 && strcmp(argv[3],"-tile-path-only") == 0) { tile_path_only = 1; } process_shapefiles(argv[1], argv[2], tile_path_only); exit(0); } mapserver-6.4.1/mapdummyrenderer.c0000644002461700001440000002331712261257215017046 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Dummy functions to implement when using a pluggable renderer * Author: Thomas Bonfort, thomas.bonfort@gmail.com * ****************************************************************************** * Copyright (c) 2010, Thomas Bonfort * * 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. *****************************************************************************/ #include "mapserver.h" int renderLineDummy(imageObj *img, shapeObj *p, strokeStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } int renderPolygonDummy(imageObj *img, shapeObj *p, colorObj *color) { msSetError(MS_RENDERERERR,"renderPolygon not implemented","renderPolygon()"); return MS_FAILURE; } int renderPolygonTiledDummy(imageObj *img, shapeObj *p, imageObj *tile) { msSetError(MS_RENDERERERR,"renderPolygonTiled not implemented","renderPolygonTiled()"); return MS_FAILURE; } int renderLineTiledDummy(imageObj *img, shapeObj *p, imageObj *tile) { msSetError(MS_RENDERERERR,"renderLineTiled not implemented","renderLineTiled()"); return MS_FAILURE; } int renderRasterGlyphsDummy(imageObj *img, double x, double y, int fontIndex, colorObj *color, char* text) { msSetError(MS_RENDERERERR,"renderRasterGlyphs not implemented","renderRasterGlyphs()"); return MS_FAILURE; } int renderGlyphsDummy(imageObj *img, double x, double y, labelStyleObj *style, char *text) { msSetError(MS_RENDERERERR,"renderGlyphs not implemented","renderGlyphs()"); return MS_FAILURE; } int renderGlyphsLineDummy(imageObj *img,labelPathObj *labelpath, labelStyleObj *style, char *text) { msSetError(MS_RENDERERERR,"renderGlyphsLine not implemented","renderGlyphsLine()"); return MS_FAILURE; } int renderVectorSymbolDummy(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderVectorSymbol not implemented","renderVectorSymbol()"); return MS_FAILURE; } void* createVectorSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"createVectorSymbolTile not implemented","createVectorSymbolTile()"); return NULL; } int renderPixmapSymbolDummy(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } void* createPixmapSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return NULL; } int renderEllipseSymbolDummy(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } void* createEllipseSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return NULL; } int renderTruetypeSymbolDummy(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } void* createTruetypeSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return NULL; } int renderTileDummy(imageObj *img, imageObj *tile, double x, double y) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } rasterBufferObj* loadImageFromFileDummy(char *path) { msSetError(MS_RENDERERERR,"loadImageFromFile not implemented","loadImageFromFile()"); return NULL; } int getRasterBufferHandleDummy(imageObj *img, rasterBufferObj *rb) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } int getRasterBufferCopyDummy(imageObj *img, rasterBufferObj *rb) { msSetError(MS_RENDERERERR,"getRasterBufferCopy not implemented","getRasterBufferCopy()"); return MS_FAILURE; } rasterBufferObj* createRasterBufferDummy(int width, int height) { msSetError(MS_RENDERERERR,"createRasterBuffer not implemented","createRasterBuffer()"); return NULL; } int mergeRasterBufferDummy(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { msSetError(MS_RENDERERERR,"mergeRasterBuffer not implemented","mergeRasterBuffer()"); return MS_FAILURE; } int initializeRasterBufferDummy(rasterBufferObj *rb, int width, int height, int mode) { msSetError(MS_RENDERERERR,"initializeRasterBuffer not implemented","initializeRasterBuffer()"); return MS_FAILURE; } /* image i/o */ imageObj* createImageDummy(int width, int height, outputFormatObj *format, colorObj* bg) { msSetError(MS_RENDERERERR,"createImage not implemented","createImage()"); return NULL; } int saveImageDummy(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { msSetError(MS_RENDERERERR,"saveImage not implemented","saveImage()"); return MS_FAILURE; } /*...*/ /* helper functions */ int getTruetypeTextBBoxDummy(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string,rectObj *rect, double **advances, int bAdjustBaseline) { msSetError(MS_RENDERERERR,"getTruetypeTextBBox not implemented","getTruetypeTextBBox()"); return MS_FAILURE; } int startLayerDummy(imageObj *img, mapObj *map, layerObj *layer) { msSetError(MS_RENDERERERR,"startLayer not implemented","startLayer()"); return MS_FAILURE; } int endLayerDummy(imageObj *img, mapObj *map, layerObj *layer) { msSetError(MS_RENDERERERR,"endLayer not implemented","endLayer()"); return MS_FAILURE; } int startShapeDummy(imageObj *img, shapeObj *shape) { msSetError(MS_RENDERERERR,"startShape not implemented","startShape()"); return MS_FAILURE; } int endShapeDummy(imageObj *img, shapeObj *shape) { msSetError(MS_RENDERERERR,"endShape not implemented","endShape()"); return MS_FAILURE; } int setClipDummy(imageObj *img, rectObj clipRect) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } int resetClipDummy(imageObj *img) { msSetError(MS_RENDERERERR,"resetClip not implemented","resetClip()"); return MS_FAILURE; } int freeImageDummy(imageObj *image) { msSetError(MS_RENDERERERR,"freeImage not implemented","freeImage()"); return MS_FAILURE; } int freeTileDummy(imageObj *tile) { msSetError(MS_RENDERERERR,"freeTile not implemented","freeTile()"); return MS_FAILURE; } int freeSymbolDummy(symbolObj *symbol) { msSetError(MS_RENDERERERR,"freeSymbol not implemented","freeSymbol()"); return MS_FAILURE; } int cleanupDummy(void *renderer_data) { return MS_SUCCESS; } int msInitializeDummyRenderer(rendererVTableObj *renderer) { renderer->use_imagecache = 0; renderer->supports_pixel_buffer = 0; renderer->supports_transparent_layers = 0; renderer->supports_clipping = 0; renderer->supports_bitmap_fonts = 0; renderer->supports_svg = 0; renderer->renderer_data = NULL; renderer->transform_mode = MS_TRANSFORM_SIMPLIFY; renderer->startLayer = &startLayerDummy; renderer->endLayer = &endLayerDummy; renderer->renderLine=&renderLineDummy; renderer->renderLineTiled = NULL; renderer->createImage=&createImageDummy; renderer->saveImage=&saveImageDummy; renderer->getRasterBufferHandle=&getRasterBufferHandleDummy; renderer->getRasterBufferCopy=getRasterBufferCopyDummy; renderer->initializeRasterBuffer=initializeRasterBufferDummy; renderer->renderPolygon=&renderPolygonDummy; renderer->renderGlyphs=&renderGlyphsDummy; renderer->renderGlyphsLine = NULL; renderer->renderBitmapGlyphs = &renderGlyphsDummy; renderer->freeImage=&freeImageDummy; renderer->renderEllipseSymbol = &renderEllipseSymbolDummy; renderer->renderVectorSymbol = &renderVectorSymbolDummy; renderer->renderTruetypeSymbol = &renderTruetypeSymbolDummy; renderer->renderPixmapSymbol = &renderPixmapSymbolDummy; renderer->mergeRasterBuffer = &mergeRasterBufferDummy; renderer->getTruetypeTextBBox = &getTruetypeTextBBoxDummy; renderer->renderTile = &renderTileDummy; renderer->renderPolygonTiled = &renderPolygonTiledDummy; renderer->freeSymbol = &freeSymbolDummy; renderer->cleanup = &cleanupDummy; renderer->startShape = NULL; renderer->endShape = NULL; return MS_SUCCESS; } mapserver-6.4.1/mapserver.h0000644002461700001440000035746712261257215015517 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Primary MapServer include file. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * 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 MAP_H #define MAP_H #include "mapserver-config.h" /* ** Main includes. If a particular header was needed by several .c files then ** I just put it here. What the hell, it works and it's all right here. -SDL- */ #if defined(HAVE_STRCASESTR) && !defined(_GNU_SOURCE) #define _GNU_SOURCE /* Required for strcasestr() defn */ #endif #include #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #include #include #else #include #endif #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #define USE_MSFREE #else #define MS_DLL_EXPORT #endif /* definition of ms_int32/ms_uint32 */ #include #ifndef _WIN32 #include #endif #ifdef _WIN32 #ifndef SIZE_MAX #ifdef _WIN64 #define SIZE_MAX _UI64_MAX #else #define SIZE_MAX UINT_MAX #endif #endif #endif #if ULONG_MAX == 0xffffffff typedef long ms_int32; typedef unsigned long ms_uint32; #elif UINT_MAX == 0xffffffff typedef int ms_int32; typedef unsigned int ms_uint32; #else typedef int32_t ms_int32; typedef uint32_t ms_uint32; #endif #if defined(_WIN32) && !defined(__CYGWIN__) /* Need to use _vsnprintf() with VS2003 */ #define vsnprintf _vsnprintf #endif #include "mapserver-api.h" /*forward declaration of rendering object*/ typedef struct rendererVTableObj rendererVTableObj; typedef struct tileCacheObj tileCacheObj; #ifndef SWIG #endif /* ms_bitarray is used by the bit mask in mapbit.c */ typedef ms_uint32 * ms_bitarray; #include "maperror.h" #include "mapprimitive.h" #include "mapshape.h" #include "mapsymbol.h" #include "maptree.h" /* quadtree spatial index */ #include "maphash.h" #include "mapio.h" #include #include "mapproject.h" #include "cgiutil.h" #ifdef USE_GD #include #endif #include /* regular expression support */ /* The regex lib from the system and the regex lib from PHP needs to * be separated here. We separate here via its directory location. */ #include "mapregex.h" #ifdef USE_OGR #define CPL_SUPRESS_CPLUSPLUS #include "ogr_api.h" #endif /* EQUAL and EQUALN are defined in cpl_port.h, so add them in here if ogr was not included */ #ifndef EQUAL #if defined(WIN32) || defined(WIN32CE) # define EQUAL(a,b) (stricmp(a,b)==0) #else # define EQUAL(a,b) (strcasecmp(a,b)==0) #endif #endif #ifndef EQUALN #if defined(WIN32) || defined(WIN32CE) # define EQUALN(a,b,n) (strnicmp(a,b,n)==0) #else # define EQUALN(a,b,n) (strncasecmp(a,b,n)==0) #endif #endif #if defined(_WIN32) && !defined(__CYGWIN__) #define snprintf _snprintf #endif #ifdef __cplusplus extern "C" { #endif // hide from swig or ruby will choke on the __FUNCTION__ name #ifndef SWIG /* Memory allocation check utility */ #ifndef __FUNCTION__ # define __FUNCTION__ "MapServer" #endif #endif #define MS_CHECK_ALLOC(var, size, retval) \ if (!var) { \ msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", __FUNCTION__, \ __FILE__, __LINE__, (unsigned int)(size)); \ return retval; \ } #define MS_CHECK_ALLOC_NO_RET(var, size) \ if (!var) { \ msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", __FUNCTION__, \ __FILE__, __LINE__, (unsigned int)(size)); \ return; \ } /* General defines, wrapable */ #define MS_TRUE 1 /* logical control variables */ #define MS_FALSE 0 #define MS_UNKNOWN -1 #define MS_ON 1 #define MS_OFF 0 #define MS_DEFAULT 2 #define MS_EMBED 3 #define MS_DELETE 4 #define MS_YES 1 #define MS_NO 0 /* For layer transparency, allows alpha transparent pixmaps to be used with RGB map images */ #define MS_GD_ALPHA 1000 /* Number of layer, class and style ptrs to alloc at once in the corresponding msGrow...() functions. Replaces former MS_MAXLAYERS, MS_MAXCLASSES and MS_MAXSTYLES with dynamic allocation (see RFC-17). */ #define MS_LAYER_ALLOCSIZE 64 #define MS_CLASS_ALLOCSIZE 8 #define MS_STYLE_ALLOCSIZE 4 #define MS_LABEL_ALLOCSIZE 2 /* not too common */ #define MS_MAX_LABEL_PRIORITY 10 #define MS_MAX_LABEL_FONTS 5 #define MS_DEFAULT_LABEL_PRIORITY 1 #define MS_LABEL_FORCE_GROUP 2 /* other values are MS_ON/MS_OFF */ /* General defines, not wrapable */ #ifndef SWIG #ifdef USE_XMLMAPFILE #define MS_DEFAULT_MAPFILE_PATTERN "\\.(map|xml)$" #define MS_DEFAULT_XMLMAPFILE_PATTERN "\\.xml$" #else #define MS_DEFAULT_MAPFILE_PATTERN "\\.map$" #endif #define MS_TEMPLATE_MAGIC_STRING "MapServer Template" #define MS_TEMPLATE_EXPR "\\.(xml|wml|html|htm|svg|kml|gml|js|tmpl)$" #define MS_INDEX_EXTENSION ".qix" #define MS_QUERY_RESULTS_MAGIC_STRING "MapServer Query Results" #define MS_QUERY_PARAMS_MAGIC_STRING "MapServer Query Params" #define MS_QUERY_EXTENSION ".qy" #define MS_DEG_TO_RAD .0174532925199432958 #define MS_RAD_TO_DEG 57.29577951 #define MS_DEFAULT_RESOLUTION 72 #define MS_RED 0 #define MS_GREEN 1 #define MS_BLUE 2 #define MS_MAXCOLORS 256 #define MS_MISSING_DATA_IGNORE 0 #define MS_MISSING_DATA_FAIL 1 #define MS_MISSING_DATA_LOG 2 #define MS_BUFFER_LENGTH 2048 /* maximum input line length */ #define MS_URL_LENGTH 1024 #define MS_MAXPATHLEN 1024 #define MS_MAXIMAGESIZE_DEFAULT 2048 #define MS_MAXPROJARGS 20 #define MS_MAXJOINS 20 #define MS_ITEMNAMELEN 32 #define MS_NAMELEN 20 #define MS_MINSYMBOLSIZE 0 /* in pixels */ #define MS_MAXSYMBOLSIZE 500 #define MS_MINSYMBOLWIDTH 0 /* in pixels */ #define MS_MAXSYMBOLWIDTH 32 #define MS_URL 0 /* template types */ #define MS_FILE 1 #define MS_MINFONTSIZE 4 #define MS_MAXFONTSIZE 256 #define MS_LABELCACHEINITSIZE 100 #define MS_LABELCACHEINCREMENT 10 #define MS_RESULTCACHEINITSIZE 10 #define MS_RESULTCACHEINCREMENT 10 #define MS_FEATUREINITSIZE 10 /* how many points initially can a feature have */ #define MS_FEATUREINCREMENT 10 #define MS_EXPRESSION 2000 /* todo: make this an enum */ #define MS_REGEX 2001 #define MS_STRING 2002 #define MS_NUMBER 2003 #define MS_COMMENT 2004 #define MS_IREGEX 2005 #define MS_ISTRING 2006 #define MS_BINDING 2007 #define MS_LIST 2008 /* string split flags */ #define MS_HONOURSTRINGS 0x0001 #define MS_ALLOWEMPTYTOKENS 0x0002 #define MS_PRESERVEQUOTES 0x0004 #define MS_PRESERVEESCAPES 0x0008 #define MS_STRIPLEADSPACES 0x0010 #define MS_STRIPENDSPACES 0x0020 /* boolean options for the expression object. */ #define MS_EXP_INSENSITIVE 1 /* General macro definitions */ #define MS_MIN(a,b) (((a)<(b))?(a):(b)) #define MS_MAX(a,b) (((a)>(b))?(a):(b)) #define MS_ABS(a) (((a)<0) ? -(a) : (a)) #define MS_SGN(a) (((a)<0) ? -1 : 1) #define MS_NINT_GENERIC(x) ((x) >= 0.0 ? ((long) ((x)+.5)) : ((long) ((x)-.5))) #ifdef _MSC_VER #define msIsNan(x) _isnan(x) #else #define msIsNan(x) isnan(x) #endif /* see http://mega-nerd.com/FPcast/ for some discussion of fast conversion to nearest int. We avoid lrint() for now because it would be hard to include math.h "properly". */ #if defined(HAVE_LRINT) && !defined(USE_GENERIC_MS_NINT) # define MS_NINT(x) lrint(x) /*# define MS_NINT(x) lround(x) */ #elif defined(_MSC_VER) && defined(_WIN32) && !defined(USE_GENERIC_MS_NINT) static __inline long int MS_NINT (double flt) { int intgr; _asm { fld flt fistp intgr } ; return intgr ; } #elif defined(i386) && defined(__GNUC_PREREQ) && !defined(USE_GENERIC_MS_NINT) static __inline long int MS_NINT( double __x ) { long int __lrintres; __asm__ __volatile__ ("fistpl %0" : "=m" (__lrintres) : "t" (__x) : "st"); return __lrintres; } #else # define MS_NINT(x) MS_NINT_GENERIC(x) #endif #define MS_PEN_TRANSPARENT -1 #define MS_PEN_UNSET -4 /* #define MS_VALID_EXTENT(minx, miny, maxx, maxy) (((minxmimetype ? format->mimetype : "unknown") #define MS_IMAGE_EXTENSION(format) (format->extension ? format->extension : "unknown") #ifdef USE_GD #define MS_DRIVER_GD(format) (strncasecmp((format)->driver,"gd/",3)==0) #endif #define MS_DRIVER_SWF(format) (strncasecmp((format)->driver,"swf",3)==0) #define MS_DRIVER_GDAL(format) (strncasecmp((format)->driver,"gdal/",5)==0) #define MS_DRIVER_IMAGEMAP(format) (strncasecmp((format)->driver,"imagemap",8)==0) #define MS_DRIVER_AGG(format) (strncasecmp((format)->driver,"agg/",4)==0) #define MS_DRIVER_CAIRO(format) (strncasecmp((format)->driver,"cairo/",6)==0) #define MS_DRIVER_OGL(format) (strncasecmp((format)->driver,"ogl/",4)==0) #define MS_DRIVER_TEMPLATE(format) (strncasecmp((format)->driver,"template",8)==0) #endif /*SWIG*/ #define MS_RENDER_WITH_SWF 2 #define MS_RENDER_WITH_RAWDATA 3 #define MS_RENDER_WITH_IMAGEMAP 5 #define MS_RENDER_WITH_TEMPLATE 8 /* query results only */ #define MS_RENDER_WITH_OGR 16 #define MS_RENDER_WITH_PLUGIN 100 #define MS_RENDER_WITH_CAIRO_RASTER 101 #define MS_RENDER_WITH_CAIRO_PDF 102 #define MS_RENDER_WITH_CAIRO_SVG 103 #define MS_RENDER_WITH_OGL 104 #define MS_RENDER_WITH_AGG 105 #define MS_RENDER_WITH_GD 106 #define MS_RENDER_WITH_KML 107 #ifndef SWIG #define MS_RENDERER_SWF(format) ((format)->renderer == MS_RENDER_WITH_SWF) #define MS_RENDERER_RAWDATA(format) ((format)->renderer == MS_RENDER_WITH_RAWDATA) #define MS_RENDERER_IMAGEMAP(format) ((format)->renderer == MS_RENDER_WITH_IMAGEMAP) #define MS_RENDERER_TEMPLATE(format) ((format)->renderer == MS_RENDER_WITH_TEMPLATE) #define MS_RENDERER_KML(format) ((format)->renderer == MS_RENDER_WITH_KML) #define MS_RENDERER_OGR(format) ((format)->renderer == MS_RENDER_WITH_OGR) #define MS_RENDERER_PLUGIN(format) ((format)->renderer > MS_RENDER_WITH_PLUGIN) #define MS_CELLSIZE(min,max,d) ((max - min)/(d-1)) /* where min/max are from an MapServer pixel center-to-pixel center extent */ #define MS_OWS_CELLSIZE(min,max,d) ((max - min)/d) /* where min/max are from an OGC pixel outside edge-to-pixel outside edge extent */ #define MS_MAP2IMAGE_X(x,minx,cx) (MS_NINT((x - minx)/cx)) #define MS_MAP2IMAGE_Y(y,maxy,cy) (MS_NINT((maxy - y)/cy)) #define MS_IMAGE2MAP_X(x,minx,cx) (minx + cx*x) #define MS_IMAGE2MAP_Y(y,maxy,cy) (maxy - cy*y) /* these versions of MS_MAP2IMAGE takes 1/cellsize and is much faster */ #define MS_MAP2IMAGE_X_IC(x,minx,icx) (MS_NINT((x - minx)*icx)) #define MS_MAP2IMAGE_Y_IC(y,maxy,icy) (MS_NINT((maxy - y)*icy)) #define MS_MAP2IMAGE_X_IC_DBL(x,minx,icx) ((x - minx)*icx) #define MS_MAP2IMAGE_Y_IC_DBL(y,maxy,icy) ((maxy - y)*icy) #define MS_MAP2IMAGE_X_IC_SNAP(x,minx,icx,res) ((MS_NINT((x - minx)*icx*res))/(res)) #define MS_MAP2IMAGE_Y_IC_SNAP(y,maxy,icy,res) ((MS_NINT((maxy - y)*icy*res))/(res)) /* For CARTO symbols */ #define MS_PI 3.14159265358979323846 #define MS_PI2 1.57079632679489661923 /* (MS_PI / 2) */ #define MS_3PI2 4.71238898038468985769 /* (3 * MS_PI2) */ #define MS_2PI 6.28318530717958647693 /* (2 * MS_PI) */ #define MS_ENCRYPTION_KEY_SIZE 16 /* Key size: 128 bits = 16 bytes */ #define GET_LAYER(map, pos) map->layers[pos] #define GET_CLASS(map, lid, cid) map->layers[lid]->class[cid] #if defined(HAVE_SYNC_FETCH_AND_ADD) #define MS_REFCNT_INCR(obj) __sync_fetch_and_add(&obj->refcount, +1) #define MS_REFCNT_DECR(obj) __sync_sub_and_fetch(&obj->refcount, +1) #define MS_REFCNT_INIT(obj) obj->refcount=1, __sync_synchronize() #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) #pragma intrinsic (_InterlockedExchangeAdd) #if defined(_MSC_VER) && (_MSC_VER <= 1200) #define MS_REFCNT_INCR(obj) ( _InterlockedExchangeAdd((long*)(&obj->refcount), (long)(+1)) +1 ) #define MS_REFCNT_DECR(obj) ( _InterlockedExchangeAdd((long*)(&obj->refcount), (long)(-1)) -1 ) #define MS_REFCNT_INIT(obj) obj->refcount=1 #else #define MS_REFCNT_INCR(obj) ( _InterlockedExchangeAdd((volatile long*)(&obj->refcount), (long)(+1)) +1 ) #define MS_REFCNT_DECR(obj) ( _InterlockedExchangeAdd((volatile long*)(&obj->refcount), (long)(-1)) -1 ) #define MS_REFCNT_INIT(obj) obj->refcount=1 #endif #elif defined(__MINGW32__) && defined(__i386__) #define MS_REFCNT_INCR(obj) ( InterlockedExchangeAdd((long*)(&obj->refcount), (long)(+1)) +1 ) #define MS_REFCNT_DECR(obj) ( InterlockedExchangeAdd((long*)(&obj->refcount), (long)(-1)) -1 ) #define MS_REFCNT_INIT(obj) obj->refcount=1 #else // unsafe fallback #define MS_REFCNT_INCR(obj) obj->refcount++ #define MS_REFCNT_DECR(obj) (--(obj->refcount)) #define MS_REFCNT_INIT(obj) obj->refcount=1 #endif // close if defined(_MSC.. #define MS_REFCNT_DECR_IS_NOT_ZERO(obj) (MS_REFCNT_DECR(obj))>0 #define MS_REFCNT_DECR_IS_ZERO(obj) (MS_REFCNT_DECR(obj))<=0 #define MS_IS_VALID_ARRAY_INDEX(index, size) ((index<0 || index>=size)?MS_FALSE:MS_TRUE) #define MS_CONVERT_UNIT(src_unit, dst_unit, value) (value * msInchesPerUnit(src_unit,0) / msInchesPerUnit(dst_unit,0)) #endif /* General enumerated types - needed by scripts */ enum MS_FILE_TYPE {MS_FILE_MAP, MS_FILE_SYMBOL}; enum MS_UNITS {MS_INCHES, MS_FEET, MS_MILES, MS_METERS, MS_KILOMETERS, MS_DD, MS_PIXELS, MS_PERCENTAGES, MS_NAUTICALMILES}; enum MS_SHAPE_TYPE {MS_SHAPE_POINT, MS_SHAPE_LINE, MS_SHAPE_POLYGON, MS_SHAPE_NULL}; enum MS_LAYER_TYPE {MS_LAYER_POINT, MS_LAYER_LINE, MS_LAYER_POLYGON, MS_LAYER_RASTER, MS_LAYER_ANNOTATION, MS_LAYER_QUERY, MS_LAYER_CIRCLE, MS_LAYER_TILEINDEX, MS_LAYER_CHART}; enum MS_FONT_TYPE {MS_TRUETYPE, MS_BITMAP}; #define MS_POSITIONS_LENGTH 14 enum MS_POSITIONS_ENUM {MS_UL=101, MS_LR, MS_UR, MS_LL, MS_CR, MS_CL, MS_UC, MS_LC, MS_CC, MS_AUTO, MS_XY, MS_FOLLOW, MS_NONE, MS_AUTO2}; /* Added MS_FOLLOW for bug #1620 implementation. */ enum MS_BITMAP_FONT_SIZES {MS_TINY , MS_SMALL, MS_MEDIUM, MS_LARGE, MS_GIANT}; enum MS_QUERYMAP_STYLES {MS_NORMAL, MS_HILITE, MS_SELECTED}; enum MS_CONNECTION_TYPE {MS_INLINE, MS_SHAPEFILE, MS_TILED_SHAPEFILE, MS_SDE, MS_OGR, MS_UNUSED_1, MS_POSTGIS, MS_WMS, MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_MYSQL, MS_RASTER, MS_PLUGIN, MS_UNION, MS_UVRASTER, MS_CONTOUR }; enum MS_JOIN_CONNECTION_TYPE {MS_DB_XBASE, MS_DB_CSV, MS_DB_MYSQL, MS_DB_ORACLE, MS_DB_POSTGRES}; enum MS_JOIN_TYPE {MS_JOIN_ONE_TO_ONE, MS_JOIN_ONE_TO_MANY}; #define MS_SINGLE 0 /* modes for searching (spatial/database) */ #define MS_MULTIPLE 1 enum MS_QUERY_MODE {MS_QUERY_SINGLE, MS_QUERY_MULTIPLE}; enum MS_QUERY_TYPE {MS_QUERY_IS_NULL, MS_QUERY_BY_POINT, MS_QUERY_BY_RECT, MS_QUERY_BY_SHAPE, MS_QUERY_BY_ATTRIBUTE, MS_QUERY_BY_INDEX, MS_QUERY_BY_FILTER}; enum MS_ALIGN_VALUE {MS_ALIGN_LEFT, MS_ALIGN_CENTER, MS_ALIGN_RIGHT}; enum MS_CAPS_JOINS_AND_CORNERS {MS_CJC_NONE, MS_CJC_BEVEL, MS_CJC_BUTT, MS_CJC_MITER, MS_CJC_ROUND, MS_CJC_SQUARE, MS_CJC_TRIANGLE}; #define MS_CJC_DEFAULT_CAPS MS_CJC_ROUND #define MS_CJC_DEFAULT_JOINS MS_CJC_NONE #define MS_CJC_DEFAULT_JOIN_MAXSIZE 3 enum MS_RETURN_VALUE {MS_SUCCESS, MS_FAILURE, MS_DONE}; enum MS_IMAGEMODE { MS_IMAGEMODE_PC256, MS_IMAGEMODE_RGB, MS_IMAGEMODE_RGBA, MS_IMAGEMODE_INT16, MS_IMAGEMODE_FLOAT32, MS_IMAGEMODE_BYTE, MS_IMAGEMODE_FEATURE, MS_IMAGEMODE_NULL }; enum MS_GEOS_OPERATOR {MS_GEOS_EQUALS, MS_GEOS_DISJOINT, MS_GEOS_TOUCHES, MS_GEOS_OVERLAPS, MS_GEOS_CROSSES, MS_GEOS_INTERSECTS, MS_GEOS_WITHIN, MS_GEOS_CONTAINS, MS_GEOS_BEYOND, MS_GEOS_DWITHIN}; #define MS_FILE_DEFAULT MS_FILE_MAP /* coordinate to pixel simplification modes, used in msTransformShape */ enum MS_TRANSFORM_MODE { MS_TRANSFORM_NONE, /* no geographic to pixel transformation */ MS_TRANSFORM_ROUND, /* round to integer, might create degenerate geometries (used for GD)*/ MS_TRANSFORM_SNAPTOGRID, /* snap to a grid, should be user configurable in the future*/ MS_TRANSFORM_FULLRESOLUTION, /* keep full resolution */ MS_TRANSFORM_SIMPLIFY /* keep full resolution */ }; #ifndef SWIG /* Filter object */ typedef enum { FILTER_NODE_TYPE_UNDEFINED = -1, FILTER_NODE_TYPE_LOGICAL = 0, FILTER_NODE_TYPE_SPATIAL = 1, FILTER_NODE_TYPE_COMPARISON = 2, FILTER_NODE_TYPE_PROPERTYNAME = 3, FILTER_NODE_TYPE_BBOX = 4, FILTER_NODE_TYPE_LITERAL = 5, FILTER_NODE_TYPE_BOUNDARY = 6, FILTER_NODE_TYPE_GEOMETRY_POINT = 7, FILTER_NODE_TYPE_GEOMETRY_LINE = 8, FILTER_NODE_TYPE_GEOMETRY_POLYGON = 9, FILTER_NODE_TYPE_FEATUREID = 10 } FilterNodeType; /************************************************************************/ /* FilterEncodingNode */ /************************************************************************/ typedef struct _FilterNode { FilterNodeType eType; char *pszValue; void *pOther; char *pszSRS; struct _FilterNode *psLeftNode; struct _FilterNode *psRightNode; } FilterEncodingNode; #endif /*SWIG*/ /* Define supported bindings here (only covers existing bindings at first). Not accessible directly using MapScript. */ #define MS_STYLE_BINDING_LENGTH 12 enum MS_STYLE_BINDING_ENUM { MS_STYLE_BINDING_SIZE, MS_STYLE_BINDING_WIDTH, MS_STYLE_BINDING_ANGLE, MS_STYLE_BINDING_COLOR, MS_STYLE_BINDING_OUTLINECOLOR, MS_STYLE_BINDING_SYMBOL, MS_STYLE_BINDING_OUTLINEWIDTH, MS_STYLE_BINDING_OPACITY, MS_STYLE_BINDING_OFFSET_X, MS_STYLE_BINDING_OFFSET_Y, MS_STYLE_BINDING_POLAROFFSET_PIXEL, MS_STYLE_BINDING_POLAROFFSET_ANGLE }; #define MS_LABEL_BINDING_LENGTH 9 enum MS_LABEL_BINDING_ENUM { MS_LABEL_BINDING_SIZE, MS_LABEL_BINDING_ANGLE, MS_LABEL_BINDING_COLOR, MS_LABEL_BINDING_OUTLINECOLOR, MS_LABEL_BINDING_FONT, MS_LABEL_BINDING_PRIORITY, MS_LABEL_BINDING_POSITION, MS_LABEL_BINDING_SHADOWSIZEX, MS_LABEL_BINDING_SHADOWSIZEY }; /************************************************************************/ /* attributeBindingObj */ /************************************************************************/ #ifndef SWIG typedef struct { char *item; int index; } attributeBindingObj; #endif /*SWIG*/ /************************************************************************/ /* labelPathObj */ /* */ /* Label path object - used to hold path and bounds of curved */ /* labels - Bug #1620 implementation. */ /************************************************************************/ #ifndef SWIG typedef struct { multipointObj path; shapeObj bounds; double *angles; } labelPathObj; #endif /*SWIG*/ /************************************************************************/ /* fontSetObj */ /* */ /* used to hold aliases for TRUETYPE fonts */ /************************************************************************/ typedef struct { #ifdef SWIG %immutable; #endif char *filename; int numfonts; hashTableObj fonts; #ifdef SWIG %mutable; #endif #ifndef SWIG struct mapObj *map; #endif } fontSetObj; /************************************************************************/ /* featureListNodeObj */ /* */ /* for inline features, shape caches and queries */ /************************************************************************/ #ifndef SWIG typedef struct listNode { shapeObj shape; struct listNode *next; struct listNode *tailifhead; /* this is the tail node in the list, if this is the head element, otherwise NULL */ } featureListNodeObj; typedef featureListNodeObj * featureListNodeObjPtr; #endif /************************************************************************/ /* paletteObj */ /* */ /* used to hold colors while a map file is read */ /************************************************************************/ #ifndef SWIG typedef struct { colorObj colors[MS_MAXCOLORS-1]; int colorvalue[MS_MAXCOLORS-1]; int numcolors; } paletteObj; #endif /************************************************************************/ /* expressionObj & tokenObj */ /************************************************************************/ enum MS_TOKEN_LOGICAL_ENUM { MS_TOKEN_LOGICAL_AND=300, MS_TOKEN_LOGICAL_OR, MS_TOKEN_LOGICAL_NOT }; enum MS_TOKEN_LITERAL_ENUM { MS_TOKEN_LITERAL_NUMBER=310, MS_TOKEN_LITERAL_STRING, MS_TOKEN_LITERAL_TIME, MS_TOKEN_LITERAL_SHAPE }; enum MS_TOKEN_COMPARISON_ENUM { MS_TOKEN_COMPARISON_EQ=320, MS_TOKEN_COMPARISON_NE, MS_TOKEN_COMPARISON_GT, MS_TOKEN_COMPARISON_LT, MS_TOKEN_COMPARISON_LE, MS_TOKEN_COMPARISON_GE, MS_TOKEN_COMPARISON_IEQ, MS_TOKEN_COMPARISON_RE, MS_TOKEN_COMPARISON_IRE, MS_TOKEN_COMPARISON_IN, MS_TOKEN_COMPARISON_LIKE, MS_TOKEN_COMPARISON_INTERSECTS, MS_TOKEN_COMPARISON_DISJOINT, MS_TOKEN_COMPARISON_TOUCHES, MS_TOKEN_COMPARISON_OVERLAPS, MS_TOKEN_COMPARISON_CROSSES, MS_TOKEN_COMPARISON_WITHIN, MS_TOKEN_COMPARISON_CONTAINS, MS_TOKEN_COMPARISON_BEYOND, MS_TOKEN_COMPARISON_DWITHIN }; enum MS_TOKEN_FUNCTION_ENUM { MS_TOKEN_FUNCTION_LENGTH=340, MS_TOKEN_FUNCTION_TOSTRING, MS_TOKEN_FUNCTION_COMMIFY, MS_TOKEN_FUNCTION_AREA, MS_TOKEN_FUNCTION_ROUND, MS_TOKEN_FUNCTION_FROMTEXT, MS_TOKEN_FUNCTION_BUFFER, MS_TOKEN_FUNCTION_DIFFERENCE, MS_TOKEN_FUNCTION_SIMPLIFY, MS_TOKEN_FUNCTION_SIMPLIFYPT, MS_TOKEN_FUNCTION_GENERALIZE, MS_TOKEN_FUNCTION_SMOOTHSIA }; enum MS_TOKEN_BINDING_ENUM { MS_TOKEN_BINDING_DOUBLE=360, MS_TOKEN_BINDING_INTEGER, MS_TOKEN_BINDING_STRING, MS_TOKEN_BINDING_TIME, MS_TOKEN_BINDING_SHAPE, MS_TOKEN_BINDING_MAP_CELLSIZE, MS_TOKEN_BINDING_DATA_CELLSIZE }; enum MS_PARSE_TYPE_ENUM { MS_PARSE_TYPE_BOOLEAN, MS_PARSE_TYPE_STRING, MS_PARSE_TYPE_SHAPE }; #ifndef SWIG typedef union { int intval; char *strval; shapeObj *shpval; } parseResultObj; typedef union { double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; attributeBindingObj bindval; } tokenValueObj; typedef struct tokenListNode { int token; tokenValueObj tokenval; struct tokenListNode *next; struct tokenListNode *tailifhead; /* this is the tail node in the list if this is the head element, otherwise NULL */ } tokenListNodeObj; typedef tokenListNodeObj * tokenListNodeObjPtr; typedef struct { char *string; int type; /* container for expression options such as case-insensitiveness */ /* This is a boolean container. */ int flags; /* logical expression options */ tokenListNodeObjPtr tokens; tokenListNodeObjPtr curtoken; /* regular expression options */ ms_regex_t regex; /* compiled regular expression to be matched */ int compiled; } expressionObj; typedef struct { colorObj *pixel; /* for raster layers */ shapeObj *shape; /* for vector layers */ double dblval; /* for map cellsize used by simplify */ double dblval2; /* for data cellsize */ expressionObj *expr; /* expression to be evaluated (contains tokens) */ int type; /* type of parse: boolean, string/text or shape/geometry */ parseResultObj result; /* parse result */ } parseObj; #endif /* MS RFC 69*/ typedef struct { double maxdistance; /* max distance between clusters */ double buffer; /* the buffer size around the selection area */ char* region; /* type of the cluster region (rectangle or ellipse) */ #ifndef SWIG expressionObj group; /* expression to identify the groups */ expressionObj filter; /* expression for filtering the shapes */ #endif } clusterObj; /************************************************************************/ /* joinObj */ /* */ /* simple way to access other XBase files, one-to-one or */ /* one-to-many supported */ /************************************************************************/ #ifndef SWIG typedef struct { char *name; char **items, **values; /* items/values (process 1 record at a time) */ int numitems; char *table; char *from, *to; /* item names */ void *joininfo; /* vendor specific (i.e. XBase, MySQL, etc.) stuff to allow for persistant access */ char *header, *footer; #ifndef __cplusplus char *template; #else char *_template; #endif enum MS_JOIN_TYPE type; char *connection; enum MS_JOIN_CONNECTION_TYPE connectiontype; } joinObj; #endif /************************************************************************/ /* outputFormatObj */ /* */ /* see mapoutput.c for most related code. */ /************************************************************************/ typedef struct { #ifndef SWIG int refcount; char **formatoptions; #endif /* SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ int numformatoptions; #ifdef SWIG %mutable; #endif /* SWIG */ char *name; char *mimetype; char *driver; char *extension; int renderer; /* MS_RENDER_WITH_* */ int imagemode; /* MS_IMAGEMODE_* value. */ int transparent; int bands; int inmapfile; /* boolean value for writing */ #ifndef SWIG rendererVTableObj *vtable; void *device; /* for supporting direct rendering onto a device context */ #endif } outputFormatObj; /* The following is used for "don't care" values in transparent, interlace and imagequality values. */ #define MS_NOOVERRIDE -1111 /************************************************************************/ /* queryObj */ /* */ /* encapsulates the information necessary to perform a query */ /************************************************************************/ #ifndef SWIG typedef struct { int type; /* MS_QUERY_TYPE */ int mode; /* MS_QUERY_MODE */ int layer; pointObj point; /* by point */ double buffer; int maxresults; rectObj rect; /* by rect */ shapeObj *shape; /* by shape & operator (OGC filter) */ long shapeindex; /* by index */ long tileindex; int clear_resultcache; int maxfeatures; /* global maxfeatures */ int startindex; char *item; /* by attribute */ char *str; expressionObj *filter; /* by filter */ int slayer; /* selection layer, used for msQueryByFeatures() (note this is not a query mode per se) */ } queryObj; #endif /************************************************************************/ /* queryMapObj */ /* */ /* used to visualize query results */ /************************************************************************/ typedef struct { int height, width; int status; int style; /* HILITE, SELECTED or NORMAL */ colorObj color; } queryMapObj; /************************************************************************/ /* webObj */ /* */ /* holds parameters for a mapserver/mapscript interface */ /************************************************************************/ typedef struct { char *log; char *imagepath, *imageurl, *temppath; #ifdef SWIG %immutable; #endif /* SWIG */ struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef __cplusplus char *template; #else char *_template; #endif char *header, *footer; char *empty, *error; /* error handling */ rectObj extent; /* clipping extent */ double minscaledenom, maxscaledenom; char *mintemplate, *maxtemplate; char *queryformat; /* what format is the query to be returned, given as a MIME type */ char *legendformat; char *browseformat; #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj metadata; hashTableObj validation; #ifdef SWIG %mutable; #endif /* SWIG */ } webObj; /************************************************************************/ /* styleObj */ /* */ /* holds parameters for symbolization, multiple styles may be */ /* applied within a classObj */ /************************************************************************/ struct styleObj{ #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG /* private vars for rfc 48 & 64 */ expressionObj _geomtransform; #endif /*should an angle be automatically computed*/ int autoangle; colorObj color; colorObj backgroundcolor; colorObj outlinecolor; int opacity; /* Stuff to handle Color Range Styles */ colorObj mincolor; colorObj maxcolor; double minvalue; double maxvalue; char *rangeitem; int rangeitemindex; int symbol; char *symbolname; double size; double minsize, maxsize; int patternlength; /*moved from symbolObj in version 6.0*/ double pattern[MS_MAXPATTERNLENGTH]; /*moved from symbolObj in version 6.0*/ double gap; /*moved from symbolObj in version 6.0*/ double initialgap; int position; /*moved from symbolObj in version 6.0*/ int linecap, linejoin; /*moved from symbolObj in version 6.0*/ double linejoinmaxsize; /*moved from symbolObj in version 6.0*/ double width; double outlinewidth; double minwidth, maxwidth; double offsetx, offsety; /* for shadows, hollow symbols, etc... */ double polaroffsetpixel, polaroffsetangle; double angle; int antialias; double minscaledenom, maxscaledenom; #ifndef SWIG attributeBindingObj bindings[MS_STYLE_BINDING_LENGTH]; int numbindings; #endif }; #define MS_STYLE_SINGLE_SIDED_OFFSET -99 #define MS_STYLE_DOUBLE_SIDED_OFFSET -999 #define IS_PARALLEL_OFFSET(offsety) ((offsety) == MS_STYLE_SINGLE_SIDED_OFFSET || (offsety) == MS_STYLE_DOUBLE_SIDED_OFFSET) /********************************************************************/ /* labelLeaderObj */ /* */ /* parameters defining how a label or a group of labels may be */ /* offsetted from its original position */ /********************************************************************/ typedef struct { int maxdistance; int gridstep; #ifndef SWIG styleObj **styles; int maxstyles; #endif #ifdef SWIG %immutable; #endif int numstyles; #ifdef SWIG %mutable; #endif } labelLeaderObj; /************************************************************************/ /* labelObj */ /* */ /* parameters needed to annotate a layer, legend or scalebar */ /************************************************************************/ struct labelObj{ #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; #ifdef SWIG %mutable; #endif /* SWIG */ char *font; enum MS_FONT_TYPE type; colorObj color; colorObj outlinecolor; int outlinewidth; colorObj shadowcolor; int shadowsizex, shadowsizey; double size; double minsize, maxsize; int position; int offsetx, offsety; double angle; int anglemode; int buffer; /* space to reserve around a label */ int antialias; int align; char wrap; int maxlength; int minlength; double space_size_10; /*cached size of a single space character used for label text alignment of rfc40 */ int minfeaturesize; /* minimum feature size (in pixels) to label */ int autominfeaturesize; /* true or false */ double minscaledenom, maxscaledenom; int mindistance; int repeatdistance; double maxoverlapangle; int partials; /* can labels run of an image */ int force; /* labels *must* be drawn */ char *encoding; int priority; /* Priority level 1 to MS_MAX_LABEL_PRIORITY, default=1 */ int status; #ifndef SWIG expressionObj expression; expressionObj text; #endif #ifndef SWIG styleObj **styles; int maxstyles; #endif int numstyles; #ifndef SWIG attributeBindingObj bindings[MS_LABEL_BINDING_LENGTH]; int numbindings; #endif /* book keeping variable- used on a feature-by-feature basis (similar to bindings) */ char *annotext; pointObj annopoint; shapeObj *annopoly; labelLeaderObj leader; }; #define MS_LABEL_PERPENDICULAR_OFFSET -99 #define MS_LABEL_PERPENDICULAR_TOP_OFFSET 99 #define IS_PERPENDICULAR_OFFSET(offsety) ((offsety) == MS_LABEL_PERPENDICULAR_OFFSET || (offsety) == MS_LABEL_PERPENDICULAR_TOP_OFFSET) /************************************************************************/ /* classObj */ /* */ /* basic symbolization and classification information */ /************************************************************************/ struct classObj { #ifndef SWIG expressionObj expression; /* the expression to be matched */ #endif int status; #ifndef SWIG styleObj **styles; int maxstyles; #endif #ifdef SWIG %immutable; #endif int numstyles; #ifdef SWIG %mutable; #endif #ifndef SWIG labelObj **labels; int maxlabels; #endif int numlabels; /* should be immutable */ char *name; /* should be unique within a layer */ char *title; /* used for legend labeling */ #ifndef SWIG expressionObj text; #endif /* not SWIG */ #ifndef __cplusplus char *template; #else /* __cplusplus */ char *_template; #endif /* __cplusplus */ int type; #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj metadata; hashTableObj validation; #ifdef SWIG %mutable; #endif /* SWIG */ double minscaledenom, maxscaledenom; int minfeaturesize; /* minimum feature size (in pixels) to shape */ #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; struct layerObj *layer; #ifdef SWIG %mutable; #endif /* SWIG */ int debug; char *keyimage; char *group; labelLeaderObj leader; }; /************************************************************************/ /* labelCacheMemberObj */ /* */ /* structures to implement label caching and collision */ /* avoidance etc */ /* */ /* Note: These are scriptable, but are read only. */ /************************************************************************/ #ifdef SWIG %immutable; #endif /* SWIG */ typedef struct { double featuresize; styleObj *styles; /* copied from the classObj, only present if there is a marker to be drawn */ int numstyles; labelObj *labels; /* copied from the classObj (1 or more depending on situation) */ int numlabels; int layerindex; /* indexes */ int classindex; int shapetype; /* source geometry type, can be removed once annotation layers are dropped */ pointObj point; /* label point */ shapeObj *poly; /* label bounding box, accumulation of individual label's bounding boxes */ int status; /* has this label been drawn or not */ #ifndef SWIG labelPathObj *labelpath; /* Path & bounds of curved labels. Bug #1620 implementation */ #endif /* SWIG */ int markerid; /* corresponding marker (POINT layers only) */ lineObj *leaderline; rectObj *leaderbbox; } labelCacheMemberObj; /************************************************************************/ /* markerCacheMemberObj */ /************************************************************************/ typedef struct { int id; /* corresponding label */ shapeObj *poly; /* marker bounding box (POINT layers only) */ } markerCacheMemberObj; /************************************************************************/ /* labelCacheSlotObj */ /************************************************************************/ typedef struct { labelCacheMemberObj *labels; int numlabels; int cachesize; markerCacheMemberObj *markers; int nummarkers; int markercachesize; } labelCacheSlotObj; /************************************************************************/ /* labelCacheObj */ /************************************************************************/ typedef struct { /* One labelCacheSlotObj for each priority level */ labelCacheSlotObj slots[MS_MAX_LABEL_PRIORITY]; /* numlabels is deprecated, maintained only for backwards compatibility * between MS 4.10 and 5.0 and should be removed in a future release. * The slots[].numlabels are the real values to rely on. */ int numlabels; int gutter; /* space in pixels around the image where labels cannot be placed */ } labelCacheObj; /************************************************************************/ /* resultObj */ /************************************************************************/ typedef struct { long shapeindex; int tileindex; int resultindex; int classindex; } resultObj; #ifdef SWIG %mutable; #endif /* SWIG */ /************************************************************************/ /* resultCacheObj */ /************************************************************************/ typedef struct { #ifndef SWIG resultObj *results; int cachesize; #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ int numresults; rectObj bounds; #ifdef SWIG %mutable; #endif /* SWIG */ /* TODO: remove for 6.0, confirm with Assefa */ /*used to force the result retreiving to use getshape instead of resultgetshape*/ int usegetshape; } resultCacheObj; /************************************************************************/ /* symbolSetObj */ /************************************************************************/ typedef struct { char *filename; int imagecachesize; #ifdef SWIG %immutable; #endif /* SWIG */ int numsymbols; int maxsymbols; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG int refcount; symbolObj** symbol; struct mapObj *map; fontSetObj *fontset; /* a pointer to the main mapObj version */ struct imageCacheObj *imagecache; #endif /* not SWIG */ } symbolSetObj; /************************************************************************/ /* referenceMapObj */ /************************************************************************/ typedef struct { rectObj extent; int height, width; colorObj color; colorObj outlinecolor; char *image; int status; int marker; char *markername; int markersize; int minboxsize; int maxboxsize; #ifdef SWIG %immutable; #endif /* SWIG */ struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ } referenceMapObj; /************************************************************************/ /* scalebarObj */ /************************************************************************/ typedef struct { colorObj imagecolor; int height, width; int style; int intervals; labelObj label; colorObj color; colorObj backgroundcolor; colorObj outlinecolor; int units; int status; /* ON, OFF or EMBED */ int position; /* for embeded scalebars */ #ifndef SWIG int transparent; int interlace; #endif /* not SWIG */ int postlabelcache; int align; } scalebarObj; /************************************************************************/ /* legendObj */ /************************************************************************/ typedef struct { colorObj imagecolor; #ifdef SWIG %immutable; #endif labelObj label; #ifdef SWIG %mutable; #endif int keysizex, keysizey; int keyspacingx, keyspacingy; colorObj outlinecolor; /* Color of outline of box, -1 for no outline */ int status; /* ON, OFF or EMBED */ int height, width; int position; /* for embeded legends */ #ifndef SWIG int transparent; int interlace; #endif /* not SWIG */ int postlabelcache; #ifndef __cplusplus char *template; #else /* __cplusplus */ char *_template; #endif /* __cplusplus */ #ifdef SWIG %immutable; #endif /* SWIG */ struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ } legendObj; /************************************************************************/ /* graticuleObj */ /************************************************************************/ #ifndef SWIG typedef struct { double dwhichlatitude; double dwhichlongitude; double dstartlatitude; double dstartlongitude; double dendlatitude; double dendlongitude; double dincrementlatitude; double dincrementlongitude; double minarcs; double maxarcs; double minincrement; double maxincrement; double minsubdivides; double maxsubdivides; int bvertical; int blabelaxes; int ilabelstate; int ilabeltype; rectObj extent; lineObj *pboundinglines; pointObj *pboundingpoints; char *labelformat; } graticuleObj; typedef struct { int nTop; pointObj *pasTop; char **papszTopLabels; int nBottom; pointObj *pasBottom; char **papszBottomLabels; int nLeft; pointObj *pasLeft; char **papszLeftLabels; int nRight; pointObj *pasRight; char **papszRightLabels; } graticuleIntersectionObj; struct layerVTable; typedef struct layerVTable layerVTableObj; #endif /*SWIG*/ /************************************************************************/ /* imageObj */ /* */ /* A wrapper for GD and other images. */ /************************************************************************/ struct imageObj{ #ifdef SWIG %immutable; #endif int width, height; double resolution; double resolutionfactor; char *imagepath, *imageurl; outputFormatObj *format; #ifndef SWIG tileCacheObj *tilecache; int ntiles; #endif #ifdef SWIG %mutable; #endif #ifndef SWIG int size; #endif #ifndef SWIG union { void *plugin; char *imagemap; short *raw_16bit; float *raw_float; unsigned char *raw_byte; } img; ms_bitarray img_mask; pointObj refpt; #endif }; /************************************************************************/ /* layerObj */ /* */ /* base unit of a map. */ /************************************************************************/ typedef struct { double minscale; double maxscale; char *value; } scaleTokenEntryObj; typedef struct { char *name; int n_entries; scaleTokenEntryObj *tokens; } scaleTokenObj; struct layerObj { char *classitem; /* .DBF item to be used for symbol lookup */ #ifndef SWIG int classitemindex; resultCacheObj *resultcache; /* holds the results of a query against this layer */ int annotate; /* boolean flag for annotation */ double scalefactor; /* computed, not set */ #ifndef __cplusplus classObj **class; /* always at least 1 class */ #else /* __cplusplus */ classObj **_class; #endif /* __cplusplus */ #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ /* reference counting, RFC24 */ int refcount; int numclasses; int maxclasses; int index; struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ char *header, *footer; /* only used with multi result queries */ #ifndef __cplusplus char *template; /* global template, used across all classes */ #else /* __cplusplus */ char *_template; #endif /* __cplusplus */ char *name; /* should be unique */ char *group; /* shouldn't be unique it's supposed to be a group right? */ int status; /* on or off */ #ifndef SWIG /* RFC86 Scale-dependent token replacements */ scaleTokenObj *scaletokens; int numscaletokens; /* The following store original members if they have been modified at runtime by a rfc86 scaletoken */ char *orig_data; char *orig_tileitem; char *orig_tileindex; char *orig_filteritem; char *orig_filter; #endif char *data; /* filename, can be relative or full path */ enum MS_LAYER_TYPE type; double tolerance; /* search buffer for point and line queries (in toleranceunits) */ int toleranceunits; double symbolscaledenom; /* scale at which symbols are default size */ double minscaledenom, maxscaledenom; int minfeaturesize; /* minimum feature size (in pixels) to shape */ double labelminscaledenom, labelmaxscaledenom; double mingeowidth, maxgeowidth; /* map width (in map units) at which the layer should be drawn */ int sizeunits; /* applies to all classes */ int maxfeatures; int startindex; colorObj offsite; /* transparent pixel value for raster images */ int transform; /* does this layer have to be transformed to file coordinates */ int labelcache, postlabelcache; /* on or off */ char *labelitem; #ifndef SWIG int labelitemindex; #endif /* not SWIG */ char *tileitem; char *tileindex; /* layer index file for tiling support */ char *tilesrs; #ifndef SWIG int tileitemindex; projectionObj projection; /* projection information for the layer */ int project; /* boolean variable, do we need to project this layer or not */ #endif /* not SWIG */ int units; /* units of the projection */ #ifndef SWIG featureListNodeObjPtr features; /* linked list so we don't need a counter */ featureListNodeObjPtr currentfeature; /* pointer to the current feature */ #endif /* SWIG */ char *connection; char *plugin_library; char *plugin_library_original; /* this is needed for mapfile writing */ enum MS_CONNECTION_TYPE connectiontype; #ifndef SWIG layerVTableObj *vtable; /* SDL has converted OracleSpatial, SDE, Graticules */ void *layerinfo; /* all connection types should use this generic pointer to a vendor specific structure */ void *wfslayerinfo; /* For WFS layers, will contain a msWFSLayerInfo struct */ #endif /* not SWIG */ /* attribute/classification handling components */ #ifdef SWIG %immutable; #endif /* SWIG */ int numitems; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG char **items; void *iteminfo; /* connection specific information necessary to retrieve values */ expressionObj filter; /* connection specific attribute filter */ int bandsitemindex; int filteritemindex; int styleitemindex; #endif /* not SWIG */ char *bandsitem; /* which item in a tile contains bands to use (tiled raster data only) */ char *filteritem; char *styleitem; /* item to be used for style lookup - can also be 'AUTO' */ char *requires; /* context expressions, simple enough to not use expressionObj */ char *labelrequires; #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj metadata; hashTableObj validation; hashTableObj bindvals; clusterObj cluster; #ifdef SWIG %mutable; #endif /* SWIG */ int opacity; /* opacity (was transparency) value 0-100 */ int dump; int debug; #ifndef SWIG char **processing; joinObj *joins; #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ rectObj extent; int numprocessing; int numjoins; #ifdef SWIG %mutable; #endif /* SWIG */ char *classgroup; #ifndef SWIG imageObj *maskimage; #endif char *mask; #ifndef SWIG expressionObj _geomtransform; #endif }; /************************************************************************/ /* mapObj */ /* */ /* encompasses everything used in an Internet mapping */ /* application. */ /************************************************************************/ /* MAP OBJECT - */ struct mapObj { /* structure for a map */ char *name; /* small identifier for naming etc. */ int status; /* is map creation on or off */ int height, width; int maxsize; #ifndef SWIG layerObj **layers; #endif /* SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ /* reference counting, RFC24 */ int refcount; int numlayers; /* number of layers in mapfile */ int maxlayers; /* allocated size of layers[] array */ symbolSetObj symbolset; fontSetObj fontset; labelCacheObj labelcache; /* we need this here so multiple feature processors can access it */ #ifdef SWIG %mutable; #endif /* SWIG */ int transparent; /* TODO - Deprecated */ int interlace; /* TODO - Deprecated */ int imagequality; /* TODO - Deprecated */ rectObj extent; /* map extent array */ double cellsize; /* in map units */ #ifndef SWIG geotransformObj gt; /* rotation / geotransform */ rectObj saved_extent; #endif /*SWIG*/ enum MS_UNITS units; /* units of the projection */ double scaledenom; /* scale of the output image */ double resolution; double defresolution; /* default resolution: used for calculate the scalefactor */ char *shapepath; /* where are the shape files located */ char *mappath; /* path of the mapfile, all path are relative to this path */ #ifndef SWIG paletteObj palette; /* holds a map palette */ #endif /*SWIG*/ colorObj imagecolor; /* holds the initial image color value */ #ifdef SWIG %immutable; #endif /* SWIG */ int numoutputformats; #ifndef SWIG outputFormatObj **outputformatlist; #endif /*SWIG*/ outputFormatObj *outputformat; char *imagetype; /* name of current outputformat */ #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG projectionObj projection; /* projection information for output map */ projectionObj latlon; /* geographic projection definition */ #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ referenceMapObj reference; scalebarObj scalebar; legendObj legend; queryMapObj querymap; webObj web; #ifdef SWIG %mutable; #endif /* SWIG */ int *layerorder; int debug; char *datapattern, *templatepattern; /* depricated, use VALIDATION ... END block instead */ #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj configoptions; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG /* Private encryption key information - see mapcrypto.c */ int encryption_key_loaded; /* MS_TRUE once key has been loaded */ unsigned char encryption_key[MS_ENCRYPTION_KEY_SIZE]; /* 128bits encryption key */ queryObj query; #endif }; /************************************************************************/ /* layerVTable */ /* */ /* contains function pointers to the layer operations. If you */ /* add new functions to here, remember to update */ /* populateVirtualTable in maplayer.c */ /************************************************************************/ #ifndef SWIG struct layerVTable { int (*LayerSupportsCommonFilters)(layerObj *layer); int (*LayerInitItemInfo)(layerObj *layer); void (*LayerFreeItemInfo)(layerObj *layer); int (*LayerOpen)(layerObj *layer); int (*LayerIsOpen)(layerObj *layer); int (*LayerWhichShapes)(layerObj *layer, rectObj rect, int isQuery); int (*LayerNextShape)(layerObj *layer, shapeObj *shape); int (*LayerGetShape)(layerObj *layer, shapeObj *shape, resultObj *record); int (*LayerClose)(layerObj *layer); int (*LayerGetItems)(layerObj *layer); int (*LayerGetExtent)(layerObj *layer, rectObj *extent); int (*LayerGetAutoStyle)(mapObj *map, layerObj *layer, classObj *c, shapeObj *shape); int (*LayerCloseConnection)(layerObj *layer); int (*LayerSetTimeFilter)(layerObj *layer, const char *timestring, const char *timefield); int (*LayerApplyFilterToLayer)(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); int (*LayerCreateItems)(layerObj *layer, int nt); int (*LayerGetNumFeatures)(layerObj *layer); int (*LayerGetAutoProjection)(layerObj *layer, projectionObj *projection); char* (*LayerEscapeSQLParam)(layerObj *layer, const char* pszString); char* (*LayerEscapePropertyName)(layerObj *layer, const char* pszString); void (*LayerEnablePaging)(layerObj *layer, int value); int (*LayerGetPaging)(layerObj *layer); }; #endif /*SWIG*/ /* Function prototypes, wrapable */ MS_DLL_EXPORT int msSaveImage(mapObj *map, imageObj *img, char *filename); MS_DLL_EXPORT void msFreeImage(imageObj *img); MS_DLL_EXPORT int msSetup(void); MS_DLL_EXPORT void msCleanup(int signal); MS_DLL_EXPORT mapObj *msLoadMapFromString(char *buffer, char *new_mappath); /* Function prototypes, not wrapable */ #ifndef SWIG /* ** helper functions not part of the general API but needed in ** a few other places (like mapscript)... found in mapfile.c */ int getString(char **s); int getDouble(double *d); int getInteger(int *i); int getSymbol(int n, ...); int getCharacter(char *c); int msBuildPluginLibraryPath(char **dest, const char *lib_str, mapObj *map); MS_DLL_EXPORT int hex2int(char *hex); MS_DLL_EXPORT void initJoin(joinObj *join); MS_DLL_EXPORT void initSymbol(symbolObj *s); MS_DLL_EXPORT int initMap(mapObj *map); MS_DLL_EXPORT layerObj *msGrowMapLayers( mapObj *map ); MS_DLL_EXPORT int initLayer(layerObj *layer, mapObj *map); MS_DLL_EXPORT int freeLayer( layerObj * ); MS_DLL_EXPORT classObj *msGrowLayerClasses( layerObj *layer ); MS_DLL_EXPORT scaleTokenObj *msGrowLayerScaletokens( layerObj *layer ); MS_DLL_EXPORT int initScaleToken(scaleTokenObj *scaleToken); MS_DLL_EXPORT int initClass(classObj *_class); MS_DLL_EXPORT int freeClass( classObj * ); MS_DLL_EXPORT styleObj *msGrowClassStyles( classObj *_class ); MS_DLL_EXPORT labelObj *msGrowClassLabels( classObj *_class ); MS_DLL_EXPORT styleObj *msGrowLabelStyles( labelObj *label ); MS_DLL_EXPORT styleObj *msGrowLeaderStyles( labelLeaderObj *leader ); MS_DLL_EXPORT int msMaybeAllocateClassStyle(classObj* c, int idx); MS_DLL_EXPORT void initLabel(labelObj *label); MS_DLL_EXPORT int freeLabel(labelObj *label); MS_DLL_EXPORT void resetClassStyle(classObj *_class); MS_DLL_EXPORT int initStyle(styleObj *style); MS_DLL_EXPORT int freeStyle(styleObj *style); MS_DLL_EXPORT void initReferenceMap(referenceMapObj *ref); MS_DLL_EXPORT void initScalebar(scalebarObj *scalebar); MS_DLL_EXPORT void initGrid( graticuleObj *pGraticule ); MS_DLL_EXPORT void initWeb(webObj *web); MS_DLL_EXPORT void freeWeb(webObj *web); MS_DLL_EXPORT void initResultCache(resultCacheObj *resultcache); MS_DLL_EXPORT featureListNodeObjPtr insertFeatureList(featureListNodeObjPtr *list, shapeObj *shape); MS_DLL_EXPORT void freeFeatureList(featureListNodeObjPtr list); /* To be used *only* within the mapfile loading phase */ MS_DLL_EXPORT int loadExpressionString(expressionObj *exp, char *value); /* Use this next, thread safe wrapper, function everywhere else */ MS_DLL_EXPORT int msLoadExpressionString(expressionObj *exp, char *value); MS_DLL_EXPORT char *msGetExpressionString(expressionObj *exp); MS_DLL_EXPORT void initExpression(expressionObj *exp); MS_DLL_EXPORT void freeExpressionTokens(expressionObj *exp); MS_DLL_EXPORT void freeExpression(expressionObj *exp); MS_DLL_EXPORT void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs); MS_DLL_EXPORT void msApplyDefaultSubstitutions(mapObj *map); MS_DLL_EXPORT int getClassIndex(layerObj *layer, char *str); /* For maplabel */ int intersectLabelPolygons(shapeObj *p1, shapeObj *p2); pointObj get_metrics_line(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, lineObj *poly); pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly); double dist(pointObj a, pointObj b); /* ** Main API Functions */ /* mapobject.c */ MS_DLL_EXPORT void msFreeMap(mapObj *map); MS_DLL_EXPORT mapObj *msNewMapObj(void); MS_DLL_EXPORT const char *msGetConfigOption( mapObj *map, const char *key); MS_DLL_EXPORT int msSetConfigOption( mapObj *map, const char *key, const char *value); MS_DLL_EXPORT int msTestConfigOption( mapObj *map, const char *key, int default_result ); MS_DLL_EXPORT void msApplyMapConfigOptions( mapObj *map ); MS_DLL_EXPORT int msMapComputeGeotransform( mapObj *map ); MS_DLL_EXPORT void msMapPixelToGeoref( mapObj *map, double *x, double *y ); MS_DLL_EXPORT void msMapGeorefToPixel( mapObj *map, double *x, double *y ); MS_DLL_EXPORT int msMapSetExtent(mapObj *map, double minx, double miny, double maxx, double maxy); MS_DLL_EXPORT int msMapOffsetExtent( mapObj *map, double x, double y); MS_DLL_EXPORT int msMapScaleExtent( mapObj *map, double zoomfactor, double minscaledenom, double maxscaledenom); MS_DLL_EXPORT int msMapSetCenter( mapObj *map, pointObj *center); MS_DLL_EXPORT int msMapSetRotation( mapObj *map, double rotation_angle ); MS_DLL_EXPORT int msMapSetSize( mapObj *map, int width, int height ); MS_DLL_EXPORT int msMapSetSize( mapObj *map, int width, int height ); MS_DLL_EXPORT int msMapSetFakedExtent( mapObj *map ); MS_DLL_EXPORT int msMapRestoreRealExtent( mapObj *map ); MS_DLL_EXPORT int msMapLoadOWSParameters( mapObj *map, cgiRequestObj *request, const char *wmtver_string ); MS_DLL_EXPORT int msMapIgnoreMissingData( mapObj *map ); /* mapfile.c */ MS_DLL_EXPORT int msValidateParameter(char *value, char *pattern1, char *pattern2, char *pattern3, char *pattern4); MS_DLL_EXPORT int msGetLayerIndex(mapObj *map, char *name); MS_DLL_EXPORT int msGetSymbolIndex(symbolSetObj *set, char *name, int try_addimage_if_notfound); MS_DLL_EXPORT mapObj *msLoadMap(char *filename, char *new_mappath); MS_DLL_EXPORT int msTransformXmlMapfile(const char *stylesheet, const char *xmlMapfile, FILE *tmpfile); MS_DLL_EXPORT int msSaveMap(mapObj *map, char *filename); MS_DLL_EXPORT void msFreeCharArray(char **array, int num_items); MS_DLL_EXPORT int msUpdateScalebarFromString(scalebarObj *scalebar, char *string, int url_string); MS_DLL_EXPORT int msUpdateQueryMapFromString(queryMapObj *querymap, char *string, int url_string); MS_DLL_EXPORT int msUpdateLabelFromString(labelObj *label, char *string, int url_string); MS_DLL_EXPORT int msUpdateClusterFromString(clusterObj *cluster, char *string); MS_DLL_EXPORT int msUpdateReferenceMapFromString(referenceMapObj *ref, char *string, int url_string); MS_DLL_EXPORT int msUpdateLegendFromString(legendObj *legend, char *string, int url_string); MS_DLL_EXPORT int msUpdateWebFromString(webObj *web, char *string, int url_string); MS_DLL_EXPORT int msUpdateStyleFromString(styleObj *style, char *string, int url_string); MS_DLL_EXPORT int msUpdateClassFromString(classObj *_class, char *string, int url_string); MS_DLL_EXPORT int msUpdateLayerFromString(layerObj *layer, char *string, int url_string); MS_DLL_EXPORT int msUpdateMapFromURL(mapObj *map, char *variable, char *string); MS_DLL_EXPORT char *msWriteLayerToString(layerObj *layer); MS_DLL_EXPORT char *msWriteMapToString(mapObj *map); MS_DLL_EXPORT char *msWriteClassToString(classObj *_class); MS_DLL_EXPORT char *msWriteStyleToString(styleObj *style); MS_DLL_EXPORT char *msWriteLabelToString(labelObj *label); MS_DLL_EXPORT char *msWriteWebToString(webObj *web); MS_DLL_EXPORT char *msWriteScalebarToString(scalebarObj *scalebar); MS_DLL_EXPORT char *msWriteQueryMapToString(queryMapObj *querymap); MS_DLL_EXPORT char *msWriteReferenceMapToString(referenceMapObj *ref); MS_DLL_EXPORT char *msWriteLegendToString(legendObj *legend); MS_DLL_EXPORT char *msWriteClusterToString(clusterObj *cluster); MS_DLL_EXPORT int msEvalRegex(char *e, char *s); #ifdef USE_MSFREE MS_DLL_EXPORT void msFree(void *p); #else #define msFree free #endif MS_DLL_EXPORT char **msTokenizeMap(char *filename, int *numtokens); MS_DLL_EXPORT int msInitLabelCache(labelCacheObj *cache); MS_DLL_EXPORT int msFreeLabelCache(labelCacheObj *cache); MS_DLL_EXPORT int msCheckConnection(layerObj * layer); /* connection pooling functions (mapfile.c) */ MS_DLL_EXPORT void msCloseConnections(mapObj *map); MS_DLL_EXPORT void msOGRInitialize(void); MS_DLL_EXPORT void msOGRCleanup(void); MS_DLL_EXPORT void msGDALCleanup(void); MS_DLL_EXPORT void msGDALInitialize(void); MS_DLL_EXPORT imageObj *msDrawScalebar(mapObj *map); /* in mapscale.c */ MS_DLL_EXPORT int msCalculateScale(rectObj extent, int units, int width, int height, double resolution, double *scaledenom); MS_DLL_EXPORT double GetDeltaExtentsUsingScale(double scale, int units, double centerLat, int width, double resolution); MS_DLL_EXPORT double Pix2Georef(int nPixPos, int nPixMin, int nPixMax, double dfGeoMin, double dfGeoMax, int bULisYOrig); MS_DLL_EXPORT double Pix2LayerGeoref(mapObj *map, layerObj *layer, int value); MS_DLL_EXPORT double msInchesPerUnit(int units, double center_lat); MS_DLL_EXPORT int msEmbedScalebar(mapObj *map, imageObj *img); MS_DLL_EXPORT int msPointInRect(pointObj *p, rectObj *rect); /* in mapsearch.c */ MS_DLL_EXPORT int msRectOverlap(rectObj *a, rectObj *b); MS_DLL_EXPORT int msRectContained(rectObj *a, rectObj *b); MS_DLL_EXPORT int msRectIntersect(rectObj *a, const rectObj *b); MS_DLL_EXPORT void msRectToFormattedString(rectObj *rect, char *format, char *buffer, int buffer_length); MS_DLL_EXPORT void msPointToFormattedString(pointObj *point, const char*format, char *buffer, int buffer_length); MS_DLL_EXPORT int msIsDegenerateShape(shapeObj *shape); MS_DLL_EXPORT void msMergeRect(rectObj *a, rectObj *b); MS_DLL_EXPORT double msDistancePointToPoint(pointObj *a, pointObj *b); MS_DLL_EXPORT double msSquareDistancePointToPoint(pointObj *a, pointObj *b); MS_DLL_EXPORT double msDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b); MS_DLL_EXPORT double msSquareDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b); MS_DLL_EXPORT double msDistancePointToShape(pointObj *p, shapeObj *shape); MS_DLL_EXPORT double msSquareDistancePointToShape(pointObj *p, shapeObj *shape); MS_DLL_EXPORT double msDistanceSegmentToSegment(pointObj *pa, pointObj *pb, pointObj *pc, pointObj *pd); MS_DLL_EXPORT double msDistanceShapeToShape(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msIntersectSegments(pointObj *a, pointObj *b, pointObj *c, pointObj *d); MS_DLL_EXPORT int msPointInPolygon(pointObj *p, lineObj *c); MS_DLL_EXPORT int msIntersectMultipointPolygon(shapeObj *multipoint, shapeObj *polygon); MS_DLL_EXPORT int msIntersectPointPolygon(pointObj *p, shapeObj *polygon); MS_DLL_EXPORT int msIntersectPolylinePolygon(shapeObj *line, shapeObj *poly); MS_DLL_EXPORT int msIntersectPolygons(shapeObj *p1, shapeObj *p2); MS_DLL_EXPORT int msIntersectPolylines(shapeObj *line1, shapeObj *line2); MS_DLL_EXPORT int msInitQuery(queryObj *query); /* in mapquery.c */ MS_DLL_EXPORT void msFreeQuery(queryObj *query); MS_DLL_EXPORT int msSaveQuery(mapObj *map, char *filename, int results); MS_DLL_EXPORT int msLoadQuery(mapObj *map, char *filename); MS_DLL_EXPORT int msExecuteQuery(mapObj *map); MS_DLL_EXPORT int msQueryByIndex(mapObj *map); /* various query methods, all rely on the queryObj hung off the mapObj */ MS_DLL_EXPORT int msQueryByAttributes(mapObj *map); MS_DLL_EXPORT int msQueryByPoint(mapObj *map); MS_DLL_EXPORT int msQueryByRect(mapObj *map); MS_DLL_EXPORT int msQueryByFeatures(mapObj *map); MS_DLL_EXPORT int msQueryByShape(mapObj *map); MS_DLL_EXPORT int msQueryByFilter(mapObj *map); MS_DLL_EXPORT int msGetQueryResultBounds(mapObj *map, rectObj *bounds); MS_DLL_EXPORT int msIsLayerQueryable(layerObj *lp); MS_DLL_EXPORT void msQueryFree(mapObj *map, int qlayer); /* todo: rename */ MS_DLL_EXPORT int msRasterQueryByShape(mapObj *map, layerObj *layer, shapeObj *selectshape); MS_DLL_EXPORT int msRasterQueryByRect(mapObj *map, layerObj *layer, rectObj queryRect); MS_DLL_EXPORT int msRasterQueryByPoint(mapObj *map, layerObj *layer, int mode, pointObj p, double buffer, int maxresults ); /* in mapstring.c */ MS_DLL_EXPORT void msStringTrim(char *str); MS_DLL_EXPORT void msStringTrimBlanks(char *string); MS_DLL_EXPORT char *msStringTrimLeft(char *string); MS_DLL_EXPORT char *msStringChop(char *string); MS_DLL_EXPORT void msStringTrimEOL(char *string); MS_DLL_EXPORT char *msReplaceSubstring(char *str, const char *old, const char *sznew); MS_DLL_EXPORT void msReplaceChar(char *str, char old, char sznew); MS_DLL_EXPORT char *msCaseReplaceSubstring(char *str, const char *old, const char *sznew); MS_DLL_EXPORT char *msStripPath(char *fn); MS_DLL_EXPORT char *msGetPath(char *fn); MS_DLL_EXPORT char *msBuildPath(char *pszReturnPath, const char *abs_path, const char *path); MS_DLL_EXPORT char *msBuildPath3(char *pszReturnPath, const char *abs_path, const char *path1, const char *path2); MS_DLL_EXPORT char *msTryBuildPath(char *szReturnPath, const char *abs_path, const char *path); MS_DLL_EXPORT char *msTryBuildPath3(char *szReturnPath, const char *abs_path, const char *path1, const char *path2); MS_DLL_EXPORT char **msStringSplit(const char *string, char cd, int *num_tokens); MS_DLL_EXPORT char ** msStringSplitComplex( const char * pszString, const char * pszDelimiters, int *num_tokens, int nFlags); MS_DLL_EXPORT int msStringArrayContains(char **array, const char *element, int numElements); MS_DLL_EXPORT char **msStringTokenize( const char *pszLine, const char *pszDelim, int *num_tokens, int preserve_quote); MS_DLL_EXPORT int msCountChars(char *str, char ch); MS_DLL_EXPORT char *msLongToString(long value); MS_DLL_EXPORT char *msDoubleToString(double value, int force_f); MS_DLL_EXPORT char *msIntToString(int value); MS_DLL_EXPORT void msStringToUpper(char *string); MS_DLL_EXPORT void msStringToLower(char *string); MS_DLL_EXPORT int msEncodeChar(const char); MS_DLL_EXPORT char *msEncodeUrlExcept(const char*, const char); MS_DLL_EXPORT char *msEncodeUrl(const char*); MS_DLL_EXPORT char *msEncodeHTMLEntities(const char *string); MS_DLL_EXPORT void msDecodeHTMLEntities(const char *string); MS_DLL_EXPORT int msIsXMLTagValid(const char *string); MS_DLL_EXPORT char *msStringConcatenate(char *pszDest, const char *pszSrc); MS_DLL_EXPORT char *msJoinStrings(char **array, int arrayLength, const char *delimeter); MS_DLL_EXPORT char *msHashString(const char *pszStr); MS_DLL_EXPORT char *msCommifyString(char *str); MS_DLL_EXPORT int msHexToInt(char *hex); MS_DLL_EXPORT char *msGetEncodedString(const char *string, const char *encoding); MS_DLL_EXPORT char *msConvertWideStringToUTF8 (const wchar_t* string, const char* encoding); MS_DLL_EXPORT int msGetNextGlyph(const char **in_ptr, char *out_string); MS_DLL_EXPORT int msGetNumGlyphs(const char *in_ptr); MS_DLL_EXPORT int msGetUnicodeEntity(const char *inptr, int *unicode); MS_DLL_EXPORT int msStringIsInteger(const char *string); MS_DLL_EXPORT int msUTF8ToUniChar(const char *str, int *chPtr); /* maptclutf.c */ MS_DLL_EXPORT char* msStringEscape( const char * pszString ); MS_DLL_EXPORT int msStringInArray( const char * pszString, char **array, int numelements); #ifndef HAVE_STRDUP MS_DLL_EXPORT char *strdup(char *s); #endif /* NEED_STRDUP */ #ifndef HAVE_STRRSTR MS_DLL_EXPORT char *strrstr(char *string, char *find); #endif /* NEED_STRRSTR */ #ifndef HAVE_STRCASESTR MS_DLL_EXPORT char *strcasestr(const char *s, const char *find); #endif /* NEED_STRCASESTR */ #ifndef HAVE_STRNCASECMP MS_DLL_EXPORT int strncasecmp(const char *s1, const char *s2, int len); #endif /* NEED_STRNCASECMP */ #ifndef HAVE_STRCASECMP MS_DLL_EXPORT int strcasecmp(const char *s1, const char *s2); #endif /* NEED_STRCASECMP */ #ifndef HAVE_STRLCAT MS_DLL_EXPORT size_t strlcat(char *dst, const char *src, size_t siz); #endif /* NEED_STRLCAT */ #ifndef HAVE_STRLCPY MS_DLL_EXPORT size_t strlcpy(char *dst, const char *src, size_t siz); #endif /* NEED_STRLCAT */ MS_DLL_EXPORT char *msStrdup( const char * pszString ); #include "hittest.h" /* in mapsymbol.c */ /* Use this function *only* with mapfile loading phase */ MS_DLL_EXPORT int loadSymbolSet(symbolSetObj *symbolset, mapObj *map); /* Use this threadsafe wrapper everywhere else */ MS_DLL_EXPORT int msLoadSymbolSet(symbolSetObj *symbolset, mapObj *map); MS_DLL_EXPORT int msCopySymbol(symbolObj *dst, symbolObj *src, mapObj *map); MS_DLL_EXPORT int msCopySymbolSet(symbolSetObj *dst, symbolSetObj *src, mapObj *map); MS_DLL_EXPORT int msCopyHashTable(hashTableObj *dst, hashTableObj *src); MS_DLL_EXPORT void msInitSymbolSet(symbolSetObj *symbolset); MS_DLL_EXPORT symbolObj *msGrowSymbolSet( symbolSetObj *symbolset ); MS_DLL_EXPORT int msAddImageSymbol(symbolSetObj *symbolset, char *filename); MS_DLL_EXPORT int msFreeSymbolSet(symbolSetObj *symbolset); MS_DLL_EXPORT int msFreeSymbol(symbolObj *symbol); MS_DLL_EXPORT int msAddNewSymbol(mapObj *map, char *name); MS_DLL_EXPORT int msAppendSymbol(symbolSetObj *symbolset, symbolObj *symbol); MS_DLL_EXPORT symbolObj *msRemoveSymbol(symbolSetObj *symbolset, int index); MS_DLL_EXPORT int msSaveSymbolSet(symbolSetObj *symbolset, const char *filename); MS_DLL_EXPORT int msLoadImageSymbol(symbolObj *symbol, const char *filename); MS_DLL_EXPORT int msPreloadImageSymbol(rendererVTableObj *renderer, symbolObj *symbol); MS_DLL_EXPORT int msPreloadSVGSymbol(symbolObj *symbol); MS_DLL_EXPORT symbolObj *msRotateSymbol(symbolObj *symbol, double angle); MS_DLL_EXPORT int msGetMarkerSize(symbolSetObj *symbolset, styleObj *style, double *width, double *height, double scalefactor); /* MS_DLL_EXPORT int msGetCharacterSize(char *character, int size, char *font, rectObj *rect); */ MS_DLL_EXPORT double msSymbolGetDefaultSize(symbolObj *s); MS_DLL_EXPORT void freeImageCache(struct imageCacheObj *ic); MS_DLL_EXPORT imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest); /* in maplegend.c */ MS_DLL_EXPORT int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_y, int *alayers, int numl_ayer, map_hittest *hittest, int resolutionfactor); MS_DLL_EXPORT int msEmbedLegend(mapObj *map, imageObj *img); MS_DLL_EXPORT int msDrawLegendIcon(mapObj* map, layerObj* lp, classObj* myClass, int width, int height, imageObj *img, int dstX, int dstY, int scale_independant, class_hittest *hittest); MS_DLL_EXPORT imageObj *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* myClass, int width, int height, int scale_independant); MS_DLL_EXPORT int msLoadFontSet(fontSetObj *fontSet, mapObj *map); /* in maplabel.c */ MS_DLL_EXPORT int msInitFontSet(fontSetObj *fontset); MS_DLL_EXPORT int msFreeFontSet(fontSetObj *fontset); MS_DLL_EXPORT char *msFontsetLookupFont(fontSetObj *fontset, char *fontKey); MS_DLL_EXPORT int msFontsetLookupFonts(char* fontstring, int *numfonts, fontSetObj *fontset, char **lookedUpFonts); MS_DLL_EXPORT char *msTransformLabelText(mapObj *map, labelObj *label, char *text); MS_DLL_EXPORT int msGetTruetypeTextBBox(rendererVTableObj *renderer, char* fontstring, fontSetObj *fontset, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline); MS_DLL_EXPORT int msGetLabelSize(mapObj *map, labelObj *label, char *string, double size, rectObj *rect, double **advances); MS_DLL_EXPORT int msAddLabel(mapObj *map, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, labelPathObj *labelpath, double featuresize); MS_DLL_EXPORT int msAddLabelGroup(mapObj *map, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize); MS_DLL_EXPORT int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, shapeObj *poly, int mindistance, int current_priority, int current_label); MS_DLL_EXPORT labelCacheMemberObj *msGetLabelCacheMember(labelCacheObj *labelcache, int i); MS_DLL_EXPORT void msFreeShape(shapeObj *shape); /* in mapprimitive.c */ MS_DLL_EXPORT void msFreeLabelPathObj(labelPathObj *path); MS_DLL_EXPORT shapeObj *msShapeFromWKT(const char *string); MS_DLL_EXPORT char *msShapeToWKT(shapeObj *shape); MS_DLL_EXPORT void msInitShape(shapeObj *shape); MS_DLL_EXPORT void msShapeDeleteLine( shapeObj *shape, int line ); MS_DLL_EXPORT int msCopyShape(shapeObj *from, shapeObj *to); MS_DLL_EXPORT int msIsOuterRing(shapeObj *shape, int r); MS_DLL_EXPORT int *msGetOuterList(shapeObj *shape); MS_DLL_EXPORT int *msGetInnerList(shapeObj *shape, int r, int *outerlist); MS_DLL_EXPORT void msComputeBounds(shapeObj *shape); MS_DLL_EXPORT void msRectToPolygon(rectObj rect, shapeObj *poly); MS_DLL_EXPORT void msClipPolylineRect(shapeObj *shape, rectObj rect); MS_DLL_EXPORT void msClipPolygonRect(shapeObj *shape, rectObj rect); MS_DLL_EXPORT void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image); MS_DLL_EXPORT void msTransformPoint(pointObj *point, rectObj *extent, double cellsize, imageObj *image); MS_DLL_EXPORT void msOffsetPointRelativeTo(pointObj *point, layerObj *layer); MS_DLL_EXPORT void msOffsetShapeRelativeTo(shapeObj *shape, layerObj *layer); MS_DLL_EXPORT void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution); MS_DLL_EXPORT void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msTransformPixelToShape(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msPolylineComputeLineSegments(shapeObj *shape, double ***segment_lengths, double **line_lengths, int *max_line_index, double *max_line_length, int *segment_index, double *total_length); MS_DLL_EXPORT pointObj** msPolylineLabelPoint(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int center_on_longest_segment); MS_DLL_EXPORT pointObj** msPolylineLabelPointExtended(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int *regularLines, int numlines, int center_on_longest_segment); MS_DLL_EXPORT void msPolylineLabelPointLineString(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, double** segment_lengths, int line_index, double line_length, double total_length, int segment_index, int* labelpoints_index, int* labelpoints_size, pointObj ***labelpoints, int center_on_longest_segment); MS_DLL_EXPORT labelPathObj** msPolylineLabelPath(mapObj *map, imageObj *img, shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int *numpaths, int** regular_lines, int* num_regular_Lines); MS_DLL_EXPORT void msPolylineLabelPathLineString(mapObj *map, imageObj *img, shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int line_index, double** segment_lengths, double line_length, double total_length, int* labelpaths_index, int* labelpaths_size, labelPathObj ***labelpaths, int** regular_lines, int *regular_lines_index, int* regular_lines_size); MS_DLL_EXPORT int msPolygonLabelPoint(shapeObj *p, pointObj *lp, double min_dimension); MS_DLL_EXPORT int msAddLine(shapeObj *p, lineObj *new_line); MS_DLL_EXPORT int msAddLineDirectly(shapeObj *p, lineObj *new_line); MS_DLL_EXPORT int msAddPointToLine(lineObj *line, pointObj *point ); MS_DLL_EXPORT double msGetPolygonArea(shapeObj *p); MS_DLL_EXPORT int msGetPolygonCentroid(shapeObj *p, pointObj *lp, double *miny, double *maxy); MS_DLL_EXPORT int msDrawRasterLayer(mapObj *map, layerObj *layer, imageObj *image); /* in mapraster.c */ MS_DLL_EXPORT imageObj *msDrawReferenceMap(mapObj *map); /* mapbits.c - bit array handling functions and macros */ #define MS_ARRAY_BIT 32 #define MS_GET_BIT(array,i) (array[i>>5] & (1 <<(i & 0x3f))) #define MS_SET_BIT(array,i) {array[i>>5] |= (1 <<(i & 0x3f));} #define MS_CLR_BIT(array,i) {array[i>>5] &= (~(1 <<(i & 0x3f)));} MS_DLL_EXPORT size_t msGetBitArraySize(int numbits); /* in mapbits.c */ MS_DLL_EXPORT ms_bitarray msAllocBitArray(int numbits); MS_DLL_EXPORT int msGetBit(ms_bitarray array, int index); MS_DLL_EXPORT void msSetBit(ms_bitarray array, int index, int value); MS_DLL_EXPORT void msSetAllBits(ms_bitarray array, int index, int value); MS_DLL_EXPORT void msFlipBit(ms_bitarray array, int index); MS_DLL_EXPORT int msGetNextBit(ms_bitarray array, int index, int size); /* maplayer.c - layerObj api */ MS_DLL_EXPORT int msLayerInitItemInfo(layerObj *layer); MS_DLL_EXPORT void msLayerFreeItemInfo(layerObj *layer); MS_DLL_EXPORT int msLayerOpen(layerObj *layer); /* in maplayer.c */ MS_DLL_EXPORT int msLayerApplyScaletokens(layerObj *layer, double scale); MS_DLL_EXPORT int msLayerRestoreFromScaletokens(layerObj *layer); MS_DLL_EXPORT int msClusterLayerOpen(layerObj *layer); /* in mapcluster.c */ MS_DLL_EXPORT int msLayerIsOpen(layerObj *layer); MS_DLL_EXPORT void msLayerClose(layerObj *layer); MS_DLL_EXPORT int msLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); MS_DLL_EXPORT int msLayerGetItemIndex(layerObj *layer, char *item); MS_DLL_EXPORT int msLayerWhichItems(layerObj *layer, int get_all, char *metadata); MS_DLL_EXPORT int msLayerNextShape(layerObj *layer, shapeObj *shape); MS_DLL_EXPORT int msLayerGetItems(layerObj *layer); MS_DLL_EXPORT int msLayerSetItems(layerObj *layer, char **items, int numitems); MS_DLL_EXPORT int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record); MS_DLL_EXPORT int msLayerGetExtent(layerObj *layer, rectObj *extent); MS_DLL_EXPORT int msLayerSetExtent( layerObj *layer, double minx, double miny, double maxx, double maxy); MS_DLL_EXPORT int msLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape); MS_DLL_EXPORT int msLayerGetFeatureStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape); MS_DLL_EXPORT void msLayerAddProcessing( layerObj *layer, const char *directive ); MS_DLL_EXPORT void msLayerSetProcessingKey( layerObj *layer, const char *key, const char *value); MS_DLL_EXPORT char *msLayerGetProcessing( layerObj *layer, int proc_index); MS_DLL_EXPORT char *msLayerGetProcessingKey( layerObj *layer, const char *); MS_DLL_EXPORT int msLayerClearProcessing( layerObj *layer ); MS_DLL_EXPORT char* msLayerGetFilterString( layerObj *layer ); MS_DLL_EXPORT int msLayerSupportsCommonFilters(layerObj *layer); MS_DLL_EXPORT int msTokenizeExpression(expressionObj *expression, char **list, int *listsize); MS_DLL_EXPORT int msLayerSetTimeFilter(layerObj *lp, const char *timestring, const char *timefield); /* Helper functions for layers */ MS_DLL_EXPORT int msLayerMakeBackticsTimeFilter(layerObj *lp, const char *timestring, const char *timefield); MS_DLL_EXPORT int msLayerMakePlainTimeFilter(layerObj *lp, const char *timestring, const char *timefield); MS_DLL_EXPORT int msLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT int msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); /* maplayer.c */ MS_DLL_EXPORT int msLayerGetNumFeatures(layerObj *layer); MS_DLL_EXPORT int msLayerSupportsPaging(layerObj *layer); MS_DLL_EXPORT void msLayerEnablePaging(layerObj *layer, int value); MS_DLL_EXPORT int msLayerGetPaging(layerObj *layer); MS_DLL_EXPORT int msLayerGetMaxFeaturesToDraw(layerObj *layer, outputFormatObj *format); MS_DLL_EXPORT char *msLayerEscapeSQLParam(layerObj *layer, const char* pszString); MS_DLL_EXPORT char *msLayerEscapePropertyName(layerObj *layer, const char* pszString); /* These are special because SWF is using these */ int msOGRLayerNextShape(layerObj *layer, shapeObj *shape); int msOGRLayerGetItems(layerObj *layer); void msOGRLayerFreeItemInfo(layerObj *layer); int msOGRLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record); int msOGRLayerGetExtent(layerObj *layer, rectObj *extent); #ifdef USE_OGR MS_DLL_EXPORT int msOGRGeometryToShape(OGRGeometryH hGeometry, shapeObj *shape, OGRwkbGeometryType type); #endif /* USE_OGR */ MS_DLL_EXPORT int msInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msConnectLayer(layerObj *layer, const int connectiontype, const char *library_str); MS_DLL_EXPORT int msINLINELayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msSHPLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msTiledSHPLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msSDELayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msOGRLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msPostGISLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msWFSLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msGraticuleLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msRASTERLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msUVRASTERLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msContourLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msPluginLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msUnionLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT void msPluginFreeVirtualTableFactory(void); /* ==================================================================== */ /* Prototypes for functions in mapdraw.c */ /* ==================================================================== */ MS_DLL_EXPORT void msClearLayerPenValues(layerObj *layer); MS_DLL_EXPORT void msClearScalebarPenValues(scalebarObj *scalebar); MS_DLL_EXPORT void msClearLegendPenValues(legendObj *legend); MS_DLL_EXPORT void msClearReferenceMapPenValues(referenceMapObj *referencemap); MS_DLL_EXPORT void msClearQueryMapPenValues(queryMapObj *querymap); MS_DLL_EXPORT void msClearPenValues(mapObj *map); MS_DLL_EXPORT imageObj *msPrepareImage(mapObj *map, int allow_nonsquare); MS_DLL_EXPORT imageObj *msDrawMap(mapObj *map, int querymap); MS_DLL_EXPORT int msLayerIsVisible(mapObj *map, layerObj *layer); MS_DLL_EXPORT int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawWMSLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawWFSLayer(mapObj *map, layerObj *layer, imageObj *image); #define MS_DRAWMODE_FEATURES 0x00001 #define MS_DRAW_FEATURES(mode) (MS_DRAWMODE_FEATURES&(mode)) #define MS_DRAWMODE_LABELS 0x00002 #define MS_DRAW_LABELS(mode) (MS_DRAWMODE_LABELS&(mode)) #define MS_DRAWMODE_SINGLESTYLE 0x00004 #define MS_DRAW_SINGLESTYLE(mode) (MS_DRAWMODE_SINGLESTYLE&(mode)) #define MS_DRAWMODE_QUERY 0x00008 #define MS_DRAW_QUERY(mode) (MS_DRAWMODE_QUERY&(mode)) #define MS_DRAWMODE_UNCLIPPEDLABELS 0x00010 #define MS_DRAW_UNCLIPPED_LABELS(mode) (MS_DRAWMODE_UNCLIPPEDLABELS&(mode)) #define MS_DRAWMODE_UNCLIPPEDLINES 0x00020 #define MS_DRAW_UNCLIPPED_LINES(mode) (MS_DRAWMODE_UNCLIPPEDLINES&(mode)) MS_DLL_EXPORT int msDrawShape(mapObj *map, layerObj *layer, shapeObj *shape, imageObj *image, int style, int mode); MS_DLL_EXPORT int msDrawPoint(mapObj *map, layerObj *layer, pointObj *point, imageObj *image, int classindex, char *labeltext); /*Range Support*/ MS_DLL_EXPORT int msShapeToRange(styleObj *style, shapeObj *shape); MS_DLL_EXPORT int msValueToRange(styleObj *style, double fieldVal); MS_DLL_EXPORT int msDrawMarkerSymbol(symbolSetObj *symbolset,imageObj *image, pointObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int msDrawLineSymbol(symbolSetObj *symbolset, imageObj *image, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int msDrawShadeSymbol(symbolSetObj *symbolset, imageObj *image, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int msCircleDrawShadeSymbol(symbolSetObj *symbolset, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor); MS_DLL_EXPORT int msDrawPieSlice(symbolSetObj *symbolset, imageObj *image, pointObj *p, styleObj *style, double radius, double start, double end); MS_DLL_EXPORT int msDrawLabel(mapObj *map, imageObj *image, pointObj labelPnt, char *string, labelObj *label, double scalefactor); MS_DLL_EXPORT int msDrawText(imageObj *image, pointObj labelPnt, char *string, labelObj *label, fontSetObj *fontset, double scalefactor); MS_DLL_EXPORT int msDrawTextLine(imageObj *image, char *string, labelObj *label, labelPathObj *labelpath, fontSetObj *fontset, double scalefactor); MS_DLL_EXPORT int msDrawLabelCache(imageObj *image, mapObj *map); MS_DLL_EXPORT void msImageStartLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT void msImageEndLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT void msDrawStartShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape); MS_DLL_EXPORT void msDrawEndShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape); /* ==================================================================== */ /* End of Prototypes for functions in mapdraw.c */ /* ==================================================================== */ /* ==================================================================== */ /* Prototypes for functions in mapgeomutil.cpp */ /* ==================================================================== */ MS_DLL_EXPORT shapeObj *msRasterizeArc(double x0, double y0, double radius, double startAngle, double endAngle, int isSlice); MS_DLL_EXPORT int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width, double *pattern, int patternlength, double angle, colorObj *color); /* ==================================================================== */ /* Prototypes for functions in mapimagemap.c */ /* ==================================================================== */ MS_DLL_EXPORT imageObj *msImageCreateIM(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution); #ifdef USE_GD MS_DLL_EXPORT imageObj *msImageLoadGD( const char *filename ); MS_DLL_EXPORT imageObj *msImageLoadGDCtx( gdIOCtx *ctx, const char *driver ); MS_DLL_EXPORT int msGDSetup(); MS_DLL_EXPORT void msGDCleanup(int signal); #else //#define gdIOCtx void* #endif MS_DLL_EXPORT void msImageStartLayerIM(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msSaveImageIM(imageObj* img, char *filename, outputFormatObj *format); MS_DLL_EXPORT void msFreeImageIM(imageObj* img); MS_DLL_EXPORT void msDrawMarkerSymbolIM(symbolSetObj *symbolset, imageObj* img, pointObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT void msDrawLineSymbolIM(symbolSetObj *symbolset, imageObj* img, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT void msDrawShadeSymbolIM(symbolSetObj *symbolset, imageObj* img, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int msDrawTextIM(imageObj* img, pointObj labelPnt, char *string, labelObj *label, fontSetObj *fontset, double scalefactor); /* ==================================================================== */ /* End of Prototypes for functions in mapimagemap.c */ /* ==================================================================== */ /* various JOIN functions (in mapjoin.c) */ MS_DLL_EXPORT int msJoinConnect(layerObj *layer, joinObj *join); MS_DLL_EXPORT int msJoinPrepare(joinObj *join, shapeObj *shape); MS_DLL_EXPORT int msJoinNext(joinObj *join); MS_DLL_EXPORT int msJoinClose(joinObj *join); /*in mapraster.c */ MS_DLL_EXPORT int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb ); #ifdef USE_GD MS_DLL_EXPORT int msAddColorGD(mapObj *map, gdImagePtr img, int cmt, int r, int g, int b); #endif MS_DLL_EXPORT int msGetClass(layerObj *layer, colorObj *color, int colormap_index); MS_DLL_EXPORT int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue ); /* in mapdrawgdal.c */ MS_DLL_EXPORT int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid ); MS_DLL_EXPORT int msGetGDALGeoTransform(void *hDS, mapObj *map, layerObj *layer, double *padfGeoTransform ); MS_DLL_EXPORT int *msGetGDALBandList( layerObj *layer, void *hDS, int max_bands, int *band_count ); MS_DLL_EXPORT double msGetGDALNoDataValue( layerObj *layer, void *hBand, int *pbGotNoData ); /* in mapchart.c */ MS_DLL_EXPORT int msDrawChartLayer(mapObj *map, layerObj *layer, imageObj *image); /* ==================================================================== */ /* End of prototypes for functions in mapgd.c */ /* ==================================================================== */ /* ==================================================================== */ /* Prototypes for functions in maputil.c */ /* ==================================================================== */ MS_DLL_EXPORT int msScaleInBounds(double scale, double minscale, double maxscale); MS_DLL_EXPORT void *msSmallMalloc( size_t nSize ); MS_DLL_EXPORT void * msSmallRealloc( void * pData, size_t nNewSize ); MS_DLL_EXPORT void *msSmallCalloc( size_t nCount, size_t nSize ); MS_DLL_EXPORT int msIntegerInArray(const int value, int *array, int numelements); MS_DLL_EXPORT int msExtentsOverlap(mapObj *map, layerObj *layer); MS_DLL_EXPORT char *msBuildOnlineResource(mapObj *map, cgiRequestObj *req); /* For mapswf */ MS_DLL_EXPORT int getRgbColor(mapObj *map,int i,int *r,int *g,int *b); /* maputil.c */ MS_DLL_EXPORT int msBindLayerToShape(layerObj *layer, shapeObj *shape, int querymapMode); MS_DLL_EXPORT int msValidateContexts(mapObj *map); MS_DLL_EXPORT int msEvalContext(mapObj *map, layerObj *layer, char *context); MS_DLL_EXPORT int msEvalExpression(layerObj *layer, shapeObj *shape, expressionObj *expression, int itemindex); MS_DLL_EXPORT int msShapeGetClass(layerObj *layer, mapObj *map, shapeObj *shape, int *classgroup, int numclasses); MS_DLL_EXPORT int msShapeGetAnnotation(layerObj *layer, shapeObj *shape); MS_DLL_EXPORT int msShapeCheckSize(shapeObj *shape, double minfeaturesize); MS_DLL_EXPORT int msAdjustImage(rectObj rect, int *width, int *height); MS_DLL_EXPORT double msAdjustExtent(rectObj *rect, int width, int height); MS_DLL_EXPORT int msConstrainExtent(rectObj *bounds, rectObj *rect, double overlay); MS_DLL_EXPORT int *msGetLayersIndexByGroup(mapObj *map, char *groupname, int *nCount); MS_DLL_EXPORT unsigned char *msSaveImageBuffer(imageObj* image, int *size_ptr, outputFormatObj *format); MS_DLL_EXPORT shapeObj* msOffsetPolyline(shapeObj* shape, double offsetx, double offsety); MS_DLL_EXPORT int msMapSetLayerProjections(mapObj* map); /* Functions to chnage the drawing order of the layers. */ /* Defined in mapobject.c */ MS_DLL_EXPORT int msMoveLayerUp(mapObj *map, int nLayerIndex); MS_DLL_EXPORT int msMoveLayerDown(mapObj *map, int nLayerIndex); MS_DLL_EXPORT int msSetLayersdrawingOrder(mapObj *self, int *panIndexes); MS_DLL_EXPORT int msInsertLayer(mapObj *map, layerObj *layer, int nIndex); MS_DLL_EXPORT layerObj *msRemoveLayer(mapObj *map, int nIndex); /* Defined in layerobject.c */ MS_DLL_EXPORT int msInsertClass(layerObj *layer,classObj *classobj,int nIndex); MS_DLL_EXPORT classObj *msRemoveClass(layerObj *layer, int nIndex); MS_DLL_EXPORT int msMoveClassUp(layerObj *layer, int nClassIndex); MS_DLL_EXPORT int msMoveClassDown(layerObj *layer, int nClassIndex); /* classobject.c */ MS_DLL_EXPORT int msAddLabelToClass(classObj *classo, labelObj *label); MS_DLL_EXPORT labelObj *msRemoveLabelFromClass(classObj *classo, int nLabelIndex); MS_DLL_EXPORT int msMoveStyleUp(classObj *classo, int nStyleIndex); MS_DLL_EXPORT int msMoveStyleDown(classObj *classo, int nStyleIndex); MS_DLL_EXPORT int msDeleteStyle(classObj *classo, int nStyleIndex); MS_DLL_EXPORT int msInsertStyle(classObj *classo, styleObj *style, int nStyleIndex); MS_DLL_EXPORT styleObj *msRemoveStyle(classObj *classo, int index); /* maplabel.c */ MS_DLL_EXPORT int msInsertLabelStyle(labelObj *label, styleObj *style, int nStyleIndex); MS_DLL_EXPORT int msMoveLabelStyleUp(labelObj *label, int nStyleIndex); MS_DLL_EXPORT int msMoveLabelStyleDown(labelObj *label, int nStyleIndex); MS_DLL_EXPORT int msDeleteLabelStyle(labelObj *label, int nStyleIndex); MS_DLL_EXPORT styleObj *msRemoveLabelStyle(labelObj *label, int nStyleIndex); /* Measured shape utility functions. */ MS_DLL_EXPORT pointObj *msGetPointUsingMeasure(shapeObj *shape, double m); MS_DLL_EXPORT pointObj *msGetMeasureUsingPoint(shapeObj *shape, pointObj *point); MS_DLL_EXPORT char **msGetAllGroupNames(mapObj* map, int *numTok); MS_DLL_EXPORT char *msTmpFile(mapObj *map, const char *mappath, const char *tmppath, const char *ext); MS_DLL_EXPORT char *msTmpPath(mapObj *map, const char *mappath, const char *tmppath); MS_DLL_EXPORT char *msTmpFilename(const char *ext); MS_DLL_EXPORT void msForceTmpFileBase( const char *new_base ); MS_DLL_EXPORT imageObj *msImageCreate(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution, colorObj *bg); MS_DLL_EXPORT void msAlphaBlend( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ); MS_DLL_EXPORT void msAlphaBlendPM( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ); MS_DLL_EXPORT int msCheckParentPointer(void* p, char* objname); MS_DLL_EXPORT int *msAllocateValidClassGroups(layerObj *lp, int *nclasses); MS_DLL_EXPORT void msFreeRasterBuffer(rasterBufferObj *b); MS_DLL_EXPORT shapeObj* msGeneralize(shapeObj * shape, double tolerance); /* ==================================================================== */ /* End of prototypes for functions in maputil.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapoutput.c */ /* ==================================================================== */ MS_DLL_EXPORT void msApplyDefaultOutputFormats( mapObj * ); MS_DLL_EXPORT void msFreeOutputFormat( outputFormatObj * ); MS_DLL_EXPORT int msGetOutputFormatIndex(mapObj *map, const char *imagetype); MS_DLL_EXPORT int msRemoveOutputFormat(mapObj *map, const char *imagetype); MS_DLL_EXPORT int msAppendOutputFormat(mapObj *map, outputFormatObj *format); MS_DLL_EXPORT outputFormatObj *msSelectOutputFormat( mapObj *map, const char *imagetype ); MS_DLL_EXPORT void msApplyOutputFormat( outputFormatObj **target, outputFormatObj *format, int transparent, int interlaced, int imagequality ); MS_DLL_EXPORT const char *msGetOutputFormatOption( outputFormatObj *format, const char *optionkey, const char *defaultresult ); MS_DLL_EXPORT outputFormatObj *msCreateDefaultOutputFormat( mapObj *map, const char *driver, const char *name ); MS_DLL_EXPORT int msPostMapParseOutputFormatSetup( mapObj *map ); MS_DLL_EXPORT void msSetOutputFormatOption( outputFormatObj *format, const char *key, const char *value ); MS_DLL_EXPORT void msGetOutputFormatMimeList( mapObj *map, char **mime_list, int max_mime ); MS_DLL_EXPORT void msGetOutputFormatMimeListImg( mapObj *map, char **mime_list, int max_mime ); MS_DLL_EXPORT void msGetOutputFormatMimeListWMS( mapObj *map, char **mime_list, int max_mime ); MS_DLL_EXPORT outputFormatObj *msCloneOutputFormat( outputFormatObj *format ); MS_DLL_EXPORT int msOutputFormatValidate( outputFormatObj *format, int issue_error ); /* ==================================================================== */ /* End of prototypes for functions in mapoutput.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapgdal.c */ /* ==================================================================== */ MS_DLL_EXPORT int msSaveImageGDAL( mapObj *map, imageObj *image, char *filename ); MS_DLL_EXPORT int msInitDefaultGDALOutputFormat( outputFormatObj *format ); /* ==================================================================== */ /* prototypes for functions in mapogroutput.c */ /* ==================================================================== */ MS_DLL_EXPORT int msInitDefaultOGROutputFormat( outputFormatObj *format ); MS_DLL_EXPORT int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders ); /* ==================================================================== */ /* Public prototype for mapogr.cpp functions. */ /* ==================================================================== */ int MS_DLL_EXPORT msOGRLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); int MS_DLL_EXPORT msOGRLayerOpen(layerObj *layer, const char *pszOverrideConnection); /* in mapogr.cpp */ int MS_DLL_EXPORT msOGRLayerClose(layerObj *layer); char MS_DLL_EXPORT *msOGRShapeToWKT(shapeObj *shape); shapeObj MS_DLL_EXPORT *msOGRShapeFromWKT(const char *string); int msOGRUpdateStyleFromString(mapObj *map, layerObj *layer, classObj *c, const char *stylestring); /* ==================================================================== */ /* prototypes for functions in mapcopy */ /* ==================================================================== */ MS_DLL_EXPORT int msCopyMap(mapObj *dst, mapObj *src); MS_DLL_EXPORT int msCopyLayer(layerObj *dst, layerObj *src); MS_DLL_EXPORT int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst); MS_DLL_EXPORT int msCopyPoint(pointObj *dst, pointObj *src); MS_DLL_EXPORT int msCopyFontSet(fontSetObj *dst, fontSetObj *src, mapObj *map); MS_DLL_EXPORT void copyProperty(void *dst, void *src, int size); MS_DLL_EXPORT char *copyStringProperty(char **dst, char *src); MS_DLL_EXPORT int msCopyClass(classObj *dst, classObj *src, layerObj *layer); MS_DLL_EXPORT int msCopyStyle(styleObj *dst, styleObj *src); MS_DLL_EXPORT int msCopyLabel(labelObj *dst, labelObj *src); MS_DLL_EXPORT int msCopyLine(lineObj *dst, lineObj *src); MS_DLL_EXPORT int msCopyProjection(projectionObj *dst, projectionObj *src); int msCopyExpression(expressionObj *dst, expressionObj *src); int msCopyProjection(projectionObj *dst, projectionObj *src); /* ==================================================================== */ /* end prototypes for functions in mapcopy */ /* ==================================================================== */ /* ==================================================================== */ /* mappool.c: connection pooling API. */ /* ==================================================================== */ MS_DLL_EXPORT void *msConnPoolRequest( layerObj *layer ); MS_DLL_EXPORT void msConnPoolRelease( layerObj *layer, void * ); MS_DLL_EXPORT void msConnPoolRegister( layerObj *layer, void *conn_handle, void (*close)( void * ) ); MS_DLL_EXPORT void msConnPoolCloseUnreferenced( void ); MS_DLL_EXPORT void msConnPoolFinalCleanup( void ); /* ==================================================================== */ /* prototypes for functions in mapcpl.c */ /* ==================================================================== */ MS_DLL_EXPORT const char *msGetBasename( const char *pszFullFilename ); MS_DLL_EXPORT void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint); /* ==================================================================== */ /* include definitions from mapows.h */ /* ==================================================================== */ #include "mapows.h" /* ==================================================================== */ /* prototypes for functions in mapgeos.c */ /* ==================================================================== */ MS_DLL_EXPORT void msGEOSSetup(void); MS_DLL_EXPORT void msGEOSCleanup(void); MS_DLL_EXPORT void msGEOSFreeGeometry(shapeObj *shape); MS_DLL_EXPORT shapeObj *msGEOSShapeFromWKT(const char *string); MS_DLL_EXPORT char *msGEOSShapeToWKT(shapeObj *shape); MS_DLL_EXPORT void msGEOSFreeWKT(char* pszGEOSWKT); MS_DLL_EXPORT shapeObj *msGEOSBuffer(shapeObj *shape, double width); MS_DLL_EXPORT shapeObj *msGEOSSimplify(shapeObj *shape, double tolerance); MS_DLL_EXPORT shapeObj *msGEOSTopologyPreservingSimplify(shapeObj *shape, double tolerance); MS_DLL_EXPORT shapeObj *msGEOSConvexHull(shapeObj *shape); MS_DLL_EXPORT shapeObj *msGEOSBoundary(shapeObj *shape); MS_DLL_EXPORT pointObj *msGEOSGetCentroid(shapeObj *shape); MS_DLL_EXPORT shapeObj *msGEOSUnion(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSIntersection(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSDifference(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSSymDifference(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset); MS_DLL_EXPORT int msGEOSContains(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSOverlaps(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSWithin(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSCrosses(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSIntersects(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSTouches(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSEquals(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSDisjoint(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT double msGEOSArea(shapeObj *shape); MS_DLL_EXPORT double msGEOSLength(shapeObj *shape); MS_DLL_EXPORT double msGEOSDistance(shapeObj *shape1, shapeObj *shape2); /* ==================================================================== */ /* prototypes for functions in mapcrypto.c */ /* ==================================================================== */ MS_DLL_EXPORT int msGenerateEncryptionKey(unsigned char *k); MS_DLL_EXPORT int msReadEncryptionKeyFromFile(const char *keyfile, unsigned char *k); MS_DLL_EXPORT void msEncryptStringWithKey(const unsigned char *key, const char *in, char *out); MS_DLL_EXPORT void msDecryptStringWithKey(const unsigned char *key, const char *in, char *out); MS_DLL_EXPORT char *msDecryptStringTokens(mapObj *map, const char *in); MS_DLL_EXPORT void msHexEncode(const unsigned char *in, char *out, int numbytes); MS_DLL_EXPORT int msHexDecode(const char *in, unsigned char *out, int numchars); /* ==================================================================== */ /* prototypes for functions in mapxmp.c */ /* ==================================================================== */ MS_DLL_EXPORT int msXmpPresent(mapObj *map); MS_DLL_EXPORT int msXmpWrite(mapObj *map, const char *filename); /* ==================================================================== */ /* prototypes for functions in mapgeomtransform.c */ /* ==================================================================== */ enum MS_GEOMTRANSFORM_TYPE { MS_GEOMTRANSFORM_NONE, MS_GEOMTRANSFORM_EXPRESSION, MS_GEOMTRANSFORM_START, MS_GEOMTRANSFORM_END, MS_GEOMTRANSFORM_VERTICES, MS_GEOMTRANSFORM_BBOX, MS_GEOMTRANSFORM_CENTROID, MS_GEOMTRANSFORM_BUFFER, MS_GEOMTRANSFORM_CONVEXHULL, MS_GEOMTRANSFORM_LABELPOINT, MS_GEOMTRANSFORM_LABELPOLY }; MS_DLL_EXPORT int msDrawTransformedShape(mapObj *map, symbolSetObj *symbolset, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor); MS_DLL_EXPORT void msStyleSetGeomTransform(styleObj *s, char *transform); MS_DLL_EXPORT char *msStyleGetGeomTransform(styleObj *style); MS_DLL_EXPORT int msGeomTransformShape(mapObj *map, layerObj *layer, shapeObj *shape); /* ==================================================================== */ /* end of prototypes for functions in mapgeomtransform.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapgraticule.c */ /* ==================================================================== */ MS_DLL_EXPORT graticuleIntersectionObj *msGraticuleLayerGetIntersectionPoints(mapObj *map, layerObj *layer); MS_DLL_EXPORT void msGraticuleLayerFreeIntersectionPoints( graticuleIntersectionObj *psValue); /* ==================================================================== */ /* end of prototypes for functions in mapgraticule.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapsmoothing.c */ /* ==================================================================== */ MS_DLL_EXPORT shapeObj* msSmoothShapeSIA(shapeObj *shape, int ss, int si, char *preprocessing); /* ==================================================================== */ /* end of prototypes for functions in mapsmoothing.c */ /* ==================================================================== */ #endif /* * strokeStyleObj */ typedef struct { double width; /* line width in pixels */ /* line pattern, e.g. dots, dashes, etc.. */ int patternlength; double pattern[MS_MAXPATTERNLENGTH]; double patternoffset; /* must be a valid color if not NULL */ /* color.alpha must be used if supported by the renderer */ colorObj *color; int linecap; /* MS_CJC_TRIANGLE, MS_CJC_SQUARE, MS_CJC_ROUND, MS_CJC_BUTT */ int linejoin; /* MS_CJC_BEVEL MS_CJC_ROUND MS_CJC_MITER */ double linejoinmaxsize; } strokeStyleObj; #define INIT_STROKE_STYLE(s) { (s).width=0; (s).patternlength=0; (s).color=NULL; (s).linecap=MS_CJC_ROUND; (s).linejoin=MS_CJC_ROUND; (s).linejoinmaxsize=0;} /* * symbolStyleObj */ typedef struct { /* must be valid colors if not NULL */ /* color.alpha must be used if supported by the renderer */ colorObj *color; colorObj *backgroundcolor; double outlinewidth; colorObj *outlinecolor; /* scalefactor to be applied on the tile or symbol*/ double scale; /* rotation to apply on the symbol (and the tile?) * in radians */ double rotation; /* the gap to space symbols appart when used as a polygon tile */ double gap; /* style object, necessary for vector type renderers to be able * to render symbols through other renders such as cairo/agg */ styleObj *style; } symbolStyleObj; #define INIT_SYMBOL_STYLE(s) {(s).color=NULL; (s).backgroundcolor=NULL; (s).outlinewidth=0; (s).outlinecolor=NULL; (s).scale=1.0; (s).rotation=0; (s).style=NULL;} struct tileCacheObj { symbolObj *symbol; int width; int height; colorObj color, outlinecolor, backgroundcolor; double outlinewidth, rotation,scale; imageObj *image; tileCacheObj *next; }; /* * labelStyleObj */ typedef struct { /* full paths to truetype font file */ char* fonts[MS_MAX_LABEL_FONTS]; int numfonts; double size; double rotation; colorObj *color; double outlinewidth; colorObj *outlinecolor; int antialias; /*only for GD*/ } labelStyleObj; #define INIT_LABEL_STYLE(s) {memset(&(s),'\0',sizeof(labelStyleObj));} #ifndef SWIG MS_DLL_EXPORT int msInitializeDummyRenderer(rendererVTableObj *vtable); MS_DLL_EXPORT int msInitializeRendererVTable(outputFormatObj *outputformat); MS_DLL_EXPORT int msPopulateRendererVTableCairoRaster( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableCairoSVG( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableCairoPDF( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableOGL( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableAGG( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableGD( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableKML( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableOGR( rendererVTableObj *renderer ); #ifdef USE_CAIRO MS_DLL_EXPORT void msCairoCleanup(void); #endif /* allocate 50k for starters */ #define MS_DEFAULT_BUFFER_ALLOC 50000 typedef struct _autobuffer { unsigned char *data; size_t size; size_t available; size_t _next_allocation_size; } bufferObj; /* in mapimageio.c */ int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette, rgbaPixel *forced_palette, int num_forced_palette_entries, unsigned int *palette_scaling_maxval); int msClassifyRasterBuffer(rasterBufferObj *rb, rasterBufferObj *qrb); int msSaveRasterBuffer(mapObj *map, rasterBufferObj *data, FILE *stream, outputFormatObj *format); int msSaveRasterBufferToBuffer(rasterBufferObj *data, bufferObj *buffer, outputFormatObj *format); int msLoadMSRasterBufferFromFile(char *path, rasterBufferObj *rb); #ifdef USE_GD int msLoadGDRasterBufferFromFile(char *path, rasterBufferObj *rb); int saveGdImage(gdImagePtr ip, FILE *fp, outputFormatObj *format); int saveGdImageBuffer(gdImagePtr ip, bufferObj *buffer, outputFormatObj *format); #endif void msBufferInit(bufferObj *buffer); void msBufferResize(bufferObj *buffer, size_t target_size); MS_DLL_EXPORT void msBufferFree(bufferObj *buffer); MS_DLL_EXPORT void msBufferAppend(bufferObj *buffer, void *data, size_t length); typedef struct { int charWidth, charHeight; } fontMetrics; struct rendererVTableObj { int supports_transparent_layers; int supports_pixel_buffer; int supports_clipping; int supports_bitmap_fonts; int supports_svg; int use_imagecache; enum MS_TRANSFORM_MODE default_transform_mode; enum MS_TRANSFORM_MODE transform_mode; double default_approximation_scale; double approximation_scale; void *renderer_data; fontMetrics* bitmapFontMetrics[5]; int (*renderLine)(imageObj *img, shapeObj *p, strokeStyleObj *style); int (*renderPolygon)(imageObj *img, shapeObj *p, colorObj *color); int (*renderPolygonTiled)(imageObj *img, shapeObj *p, imageObj *tile); int (*renderLineTiled)(imageObj *img, shapeObj *p, imageObj *tile); int (*renderBitmapGlyphs)(imageObj *img, double x, double y, labelStyleObj *style, char *text); int (*renderGlyphs)(imageObj *img, double x, double y, labelStyleObj *style, char *text); int (*renderGlyphsLine)(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text); int (*renderVectorSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void* (*createVectorSymbolTile)(int width, int height, symbolObj *symbol, symbolStyleObj *style); int (*renderPixmapSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void* (*createPixmapSymbolTile)(int width, int height, symbolObj *symbol, symbolStyleObj *style); int (*renderEllipseSymbol)(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style); void* (*createEllipseSymbolTile)(int width, int height, symbolObj *symbol, symbolStyleObj *style); int (*renderTruetypeSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void* (*createTruetypeSymbolTile)(int width, int height, symbolObj *symbol, symbolStyleObj *style); int (*renderSVGSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void* (*createSVGSymbolTile)(int width, int height, symbolObj *symbol, symbolStyleObj *style); int (*renderTile)(imageObj *img, imageObj *tile, double x, double y); int (*loadImageFromFile)(char *path, rasterBufferObj *rb); int (*getRasterBufferHandle)(imageObj *img, rasterBufferObj *rb); int (*getRasterBufferCopy)(imageObj *img, rasterBufferObj *rb); int (*initializeRasterBuffer)(rasterBufferObj *rb, int width, int height, int mode); int (*mergeRasterBuffer)(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height); /* image i/o */ imageObj* (*createImage)(int width, int height, outputFormatObj *format, colorObj* bg); int (*saveImage)(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format); unsigned char* (*saveImageBuffer)(imageObj *img, int *size_ptr, outputFormatObj *format); /*...*/ /* helper functions */ int (*getTruetypeTextBBox)(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline); int (*startLayer)(imageObj *img, mapObj *map, layerObj *layer); int (*endLayer)(imageObj *img, mapObj *map, layerObj *layer); int (*startShape)(imageObj *img, shapeObj *shape); int (*endShape)(imageObj *img, shapeObj *shape); int (*setClip)(imageObj *img, rectObj clipRect); int (*resetClip)(imageObj *img); int (*freeImage)(imageObj *image); int (*freeSymbol)(symbolObj *symbol); int (*cleanup)(void *renderer_data); } ; MS_DLL_EXPORT int msRenderRasterizedSVGSymbol(imageObj* img, double x, double y, symbolObj* symbol, symbolStyleObj* style); #define MS_IMAGE_RENDERER(im) ((im)->format->vtable) #define MS_RENDERER_CACHE(renderer) ((renderer)->renderer_data) #define MS_IMAGE_RENDERER_CACHE(im) MS_RENDERER_CACHE(MS_IMAGE_RENDERER((im))) #define MS_MAP_RENDERER(map) ((map)->outputformat->vtable) shapeObj *msOffsetCurve(shapeObj *p, double offset); #if defined USE_GEOS && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)) shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset); #endif #endif /* SWIG */ #ifdef __cplusplus } #endif #endif /* MAP_H */ mapserver-6.4.1/mapxmp.c0000644002461700001440000002123712261257215014767 0ustar tbonfortusers/****************************************************************************** * $Id: mapchart.c 11880 2011-07-07 19:51:37Z sdlime $ * * Project: MapServer * Purpose: XMP embedded image metadata (MS-RFC-7X) * Author: Paul Ramsey * ****************************************************************************** * 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. ****************************************************************************/ #include "mapserver.h" #ifdef USE_EXEMPI /* To pull parts out of hash keys */ #include /* To write the XMP XML into the files */ #include #include /** * Get standard Exempi namespace URI for a given namespace string */ static const char* msXmpUri(char *ns_name) { /* Creative Commons */ if( strcmp(ns_name, "cc") == 0 ) return NS_CC; /* Dublin Core */ else if( strcmp(ns_name, "dc") == 0 ) return NS_DC; /* XMP Meta */ else if( strcmp(ns_name, "meta") == 0 ) return NS_XMP_META; /* XMP Rights */ else if( strcmp(ns_name, "rights") == 0 ) return NS_XAP_RIGHTS; /* EXIF */ else if( strcmp(ns_name, "exif") == 0 ) return NS_EXIF; /* TIFF */ else if( strcmp(ns_name, "tiff") == 0 ) return NS_TIFF; /* Photoshop Camera Raw Schema */ else if( strcmp(ns_name, "crs") == 0 ) return NS_CAMERA_RAW_SETTINGS; /* Photoshop */ else if( strcmp(ns_name, "photoshop") == 0 ) return NS_PHOTOSHOP; else return NULL; } #endif /** * Is there any XMP metadata in the map file for us to worry about? */ int msXmpPresent( mapObj *map ) { #ifdef USE_EXEMPI /* Read the WEB.METADATA */ hashTableObj hash_metadata = map->web.metadata; const char *key = NULL; int rv = MS_FALSE; /* Check all the keys for "xmp_" start pattern */ key = msFirstKeyFromHashTable(&hash_metadata); /* No first key? No license info. */ if ( ! key ) return MS_FALSE; do { /* Found one! Break out and return true */ if ( strcasestr(key, "xmp_") == key ) { rv = MS_TRUE; break; } } while( (key = msNextKeyFromHashTable(&hash_metadata, key)) ); return rv; #else return MS_FALSE; #endif } /** * Is there any XMP metadata in the map file for us to worry about? */ int msXmpWrite( mapObj *map, const char *filename ) { #ifdef USE_EXEMPI /* Should hold our keys */ hashTableObj hash_metadata = map->web.metadata; /* Temporary place for custom name spaces */ hashTableObj hash_ns; /* We use regex to strip out the namespace and XMP key value from the metadata key */ regex_t xmp_regex; const char *xmp_ns_str = "^xmp_(.+)_namespace$"; const char *xmp_tag_str = "^xmp_(.+)_(.+)$"; const char *key = NULL; static int regflags = REG_ICASE | REG_EXTENDED; /* XMP object and file pointers */ XmpPtr xmp; XmpFilePtr f; /* Force the hash table to empty */ hash_ns.numitems = 0; /* Prepare XMP library */ xmp_init(); f = xmp_files_open_new(filename, XMP_OPEN_FORUPDATE); if ( ! f ) { msSetError( MS_MISCERR, "Unable to open temporary file '%s' to write XMP info", "msXmpWrite()", filename ); return MS_FAILURE; } /* Create a new XMP structure if the file doesn't already have one */ xmp = xmp_files_get_new_xmp(f); if ( xmp == NULL ) xmp = xmp_new_empty(); /* Check we can write to the file */ if ( ! xmp_files_can_put_xmp(f, xmp) ) { msSetError( MS_MISCERR, "Unable to write XMP information to '%s'", "msXmpWrite()", filename ); return MS_FAILURE; } /* Compile our "xmp_*_namespace" regex */ if ( regcomp(&xmp_regex, xmp_ns_str, regflags) ) { msSetError( MS_MISCERR, "Unable compile regex '%s'", "msXmpWrite()", xmp_ns_str ); return MS_FAILURE; } /* Check all the keys for "xmp_*_namespace" pattern */ initHashTable(&hash_ns); key = msFirstKeyFromHashTable(&hash_metadata); /* No first key? No license info. We shouldn't get here. */ if ( ! key ) return MS_SUCCESS; do { /* Our regex has one match slot */ regmatch_t matches[2]; /* Found a custom namespace entry! Store it for later. */ if ( 0 == regexec(&xmp_regex, key, 2, matches, 0) ) { size_t ns_size = 0; char *ns_name = NULL; const char *ns_uri; /* Copy in the namespace name */ ns_size = matches[1].rm_eo - matches[1].rm_so; ns_name = msSmallMalloc(ns_size + 1); memcpy(ns_name, key + matches[1].rm_so, ns_size); ns_name[ns_size] = 0; /* null terminate */ /* Copy in the namespace uri */ ns_uri = msLookupHashTable(&hash_metadata, key); msInsertHashTable(&hash_ns, ns_name, ns_uri); xmp_register_namespace(ns_uri, ns_name, NULL); msFree(ns_name); } } while( (key = msNextKeyFromHashTable(&hash_metadata, key)) ); /* Clean up regex */ regfree(&xmp_regex); /* Compile our "xmp_*_*" regex */ if ( regcomp(&xmp_regex, xmp_tag_str, regflags) ) { msFreeHashItems(&hash_ns); msSetError( MS_MISCERR, "Unable compile regex '%s'", "msXmpWrite()", xmp_tag_str ); return MS_FAILURE; } /* Check all the keys for "xmp_*_*" pattern */ key = msFirstKeyFromHashTable(&hash_metadata); do { /* Our regex has two match slots */ regmatch_t matches[3]; /* Found a namespace entry! Write it into XMP. */ if ( 0 == regexec(&xmp_regex, key, 3, matches, 0) ) { /* Get the namespace and tag name */ size_t ns_name_size = matches[1].rm_eo - matches[1].rm_so; size_t ns_tag_size = matches[2].rm_eo - matches[2].rm_so; char *ns_name = msSmallMalloc(ns_name_size + 1); char *ns_tag = msSmallMalloc(ns_tag_size + 1); const char *ns_uri = NULL; memcpy(ns_name, key + matches[1].rm_so, ns_name_size); memcpy(ns_tag, key + matches[2].rm_so, ns_tag_size); ns_name[ns_name_size] = 0; /* null terminate */ ns_tag[ns_tag_size] = 0; /* null terminate */ if ( strcmp(ns_tag,"namespace") == 0 ) { msFree(ns_name); msFree(ns_tag); continue; } /* If this is a default name space?... */ if ( (ns_uri = msXmpUri(ns_name)) ) { xmp_register_namespace(ns_uri, ns_name, NULL); xmp_set_property(xmp, ns_uri, ns_tag, msLookupHashTable(&hash_metadata, key), 0); } /* Or maybe it's a custom one?... */ else if ( (ns_uri = msLookupHashTable(&hash_ns, ns_name)) ) { xmp_set_property(xmp, ns_uri, ns_tag, msLookupHashTable(&hash_metadata, key), 0); } /* Or perhaps we're screwed. */ else { msSetError( MS_MISCERR, "Unable to identify XMP namespace '%s' in metadata key '%s'", "msXmpWrite()", ns_name, key ); msFreeHashItems(&hash_ns); msFree(ns_name); msFree(ns_tag); return MS_FAILURE; } msFree(ns_name); msFree(ns_tag); } } while( (key = msNextKeyFromHashTable(&hash_metadata, key)) ); /* Clean up regex */ regfree(&xmp_regex); /* Write out the XMP */ if ( !xmp_files_put_xmp(f, xmp) ) { msFreeHashItems(&hash_ns); msSetError( MS_MISCERR, "Unable to execute '%s' on pointer %p", "msXmpWrite()", "xmp_files_put_xmp", f ); return MS_FAILURE; } /* Write out the file and flush */ if ( !xmp_files_close(f, XMP_CLOSE_SAFEUPDATE) ) { msFreeHashItems(&hash_ns); msSetError( MS_MISCERR, "Unable to execute '%s' on pointer %p", "msXmpWrite()", "xmp_files_close", f ); return MS_FAILURE; } msFreeHashItems(&hash_ns); xmp_free(xmp); xmp_terminate(); return MS_SUCCESS; #else return MS_FAILURE; #endif } mapserver-6.4.1/sym2img.c0000644002461700001440000001245512261257216015057 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Commandline utility to render symbols to a raster. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include #include #include "mapserver.h" #define MAXCOLORS 256 #define CELLSIZE 100 #define NCOLS 5 #define RATIO .5 #define LBUF 5 /* space to reserve around line symbols */ int main(int argc, char *argv[]) { FILE *stream; int ns,n,k; gdImagePtr img; shapeObj p; int i,j; int ncols,nrows; char buffer[256]; int gray, green, red, black, white; classObj class; symbolSetObj symbolSet; /* ---- check the number of arguments, return syntax if not correct ---- */ if( argc < 2 ) { fprintf(stdout, "Syntax: sym2img [symbolset] [outfile]\n" ); exit(0); } /* Initialize the polygon/polyline */ p.line = (lineObj *)malloc(sizeof(lineObj)); p.numlines = 1; p.line[0].point = (pointObj *)malloc(sizeof(pointObj)*4); p.line[0].numpoints = 4; /* Initialize the symbol and font sets */ symbolSet.filename = msStrdup(argv[1]); /* ** load the symbol file */ if(msLoadSymbolSet(&symbolSet) == -1) { msWriteError(stderr); exit(1); } ns = symbolSet.numsymbols; if(ns < NCOLS) { ncols = ns; nrows = 1; } else { ncols = NCOLS; nrows = (int)ceil((double)ns/NCOLS); } img = gdImageCreate(ncols*CELLSIZE, nrows*CELLSIZE); gray = gdImageColorAllocate(img, 222, 222, 222); white = gdImageColorAllocate(img, 255, 255, 255); green = gdImageColorAllocate(img, 40, 170, 40); black = gdImageColorAllocate(img, 0, 0, 0); red = gdImageColorAllocate(img, 255, 0, 0); class.color = red; class.backgroundcolor = white; class.outlinecolor = black; n=0; for(i=0; nname) snprintf(buffer, sizeof(buffer), "%d - %s", n, symbolSet.symbol[n]->name); else snprintf(buffer, sizeof(buffer), "%d", n); gdImageString(img, gdFontTiny, j+1, i+1, buffer, black); n++; } } if((stream = fopen(argv[2],"wb")) == NULL) { /* open the file */ fprintf(stderr, "Unable to open output file: %s\n", argv[2]); exit(1); } #ifndef USE_GD_GIF gdImageGif(img, stream); #else gdImagePng(img, stream); #endif gdImageDestroy(img); free(symbolSet.filename); fclose(stream); return(MS_TRUE); } mapserver-6.4.1/mapcluster.c0000644002461700001440000013430012261257215015640 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of the cluster layer data provider (RFC-69). * Author: Tamas Szekeres (szekerest@gmail.com). * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #define _CRT_SECURE_NO_WARNINGS 1 /* $Id$ */ #include #include "mapserver.h" #ifdef USE_CLUSTER_PLUGIN #define USE_CLUSTER_EXTERNAL #endif /* custom attributes provided by this layer data source */ #define MSCLUSTER_NUMITEMS 2 #define MSCLUSTER_FEATURECOUNT "Cluster:FeatureCount" #define MSCLUSTER_FEATURECOUNTINDEX -100 #define MSCLUSTER_GROUP "Cluster:Group" #define MSCLUSTER_GROUPINDEX -101 typedef struct cluster_tree_node clusterTreeNode; typedef struct cluster_info clusterInfo; typedef struct cluster_layer_info msClusterLayerInfo; /* forward declarations */ void msClusterLayerCopyVirtualTable(layerVTableObj* vtable); static void clusterTreeNodeDestroy(msClusterLayerInfo* layerinfo, clusterTreeNode *node); /* cluster compare func */ typedef int (*clusterCompareRegionFunc)(clusterInfo* current, clusterInfo* other); /* quadtree constants */ #define SPLITRATIO 0.55 #define TREE_MAX_DEPTH 10 /* cluster data */ struct cluster_info { double x; /* x position of the current point */ double y; /* y position of the current point */ double avgx; /* average x positions of this cluster */ double avgy; /* average y positions of this cluster */ double varx; /* variance of the x positions of this cluster */ double vary; /* variance of the y positions of this cluster */ shapeObj shape; /* current shape */ rectObj bounds; /* clustering region */ /* number of the neighbouring shapes */ int numsiblings; /* diagnostics */ int numcollected; int numremoved; int index; clusterTreeNode* node; /* collection of the siblings */ clusterInfo* siblings; /* next shape in the linked list */ clusterInfo* next; /* current group */ char* group; int filter; }; /* quadtree node */ struct cluster_tree_node { /* area covered by this node */ rectObj rect; /* linked list of the shapes stored at this node. */ int numshapes; int index; int position; clusterInfo* shapes; /* quad tree subnodes */ clusterTreeNode* subnode[4]; }; /* layeinfo */ struct cluster_layer_info { /* array of features (finalized clusters) */ clusterInfo* finalized; clusterInfo* finalizedSiblings; clusterInfo* filtered; int numFeatures; int numFinalized; int numFinalizedSiblings; int numFiltered; /* variables for collecting the best cluster and iterating with NextShape */ clusterInfo* current; /* check whether all shapes should be returned behind a cluster */ int get_all_shapes; double rank; /* root node of the quad tree */ clusterTreeNode* root; int numNodes; clusterTreeNode* finalizedNodes; int numFinalizedNodes; /* map extent used for building cluster data */ rectObj searchRect; /* source layer parameters */ layerObj srcLayer; /* distance comparator function */ clusterCompareRegionFunc fnCompare; /* diagnostics */ int depth; }; extern int yyparse(parseObj *p); /* evaluate the filter expression */ int msClusterEvaluateFilter(expressionObj* expression, shapeObj *shape) { if (expression->type == MS_EXPRESSION) { int status; parseObj p; p.shape = shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse expression: %s", "msClusterEvaluateFilter", expression->string); return 0; } return p.result.intval; } return 0; } /* get the group text when creating the clusters */ char *msClusterGetGroupText(expressionObj* expression, shapeObj *shape) { char *tmpstr=NULL; if(expression->string) { switch(expression->type) { case(MS_STRING): tmpstr = msStrdup(expression->string); break; case(MS_EXPRESSION): { int status; parseObj p; p.shape = shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_STRING; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process text expression: %s", "msClusterGetGroupText", expression->string); return NULL; } tmpstr = p.result.strval; break; } default: break; } } return(tmpstr); } int CompareEllipseRegion(clusterInfo* current, clusterInfo* other) { if (current->group && other->group && !EQUAL(current->group, other->group)) return MS_FALSE; if ((other->x - current->x) * (other->x - current->x) / ((current->bounds.maxx - current->x) * (current->bounds.maxx - current->x)) + (other->y - current->y) * (other->y - current->y) / ((current->bounds.maxy - current->y) * (current->bounds.maxy - current->y)) > 1) return MS_FALSE; return MS_TRUE; } int CompareRectangleRegion(clusterInfo* current, clusterInfo* other) { if (current->group && other->group && !EQUAL(current->group, other->group)) return MS_FALSE; if (other->x < current->bounds.minx) return MS_FALSE; if (other->x > current->bounds.maxx) return MS_FALSE; if (other->y < current->bounds.miny) return MS_FALSE; if (other->y > current->bounds.maxy) return MS_FALSE; return MS_TRUE; } static void treeSplitBounds( rectObj *in, rectObj *out1, rectObj *out2) { double range; /* -------------------------------------------------------------------- */ /* The output bounds will be very similar to the input bounds, */ /* so just copy over to start. */ /* -------------------------------------------------------------------- */ memcpy(out1, in, sizeof(rectObj)); memcpy(out2, in, sizeof(rectObj)); /* -------------------------------------------------------------------- */ /* Split in X direction. */ /* -------------------------------------------------------------------- */ if((in->maxx - in->minx) > (in->maxy - in->miny)) { range = in->maxx - in->minx; out1->maxx = in->minx + range * SPLITRATIO; out2->minx = in->maxx - range * SPLITRATIO; } /* -------------------------------------------------------------------- */ /* Otherwise split in Y direction. */ /* -------------------------------------------------------------------- */ else { range = in->maxy - in->miny; out1->maxy = in->miny + range * SPLITRATIO; out2->miny = in->maxy - range * SPLITRATIO; } } /* alloc memory for a new tentative cluster */ static clusterInfo *clusterInfoCreate(msClusterLayerInfo* layerinfo) { clusterInfo* feature = (clusterInfo*)msSmallMalloc(sizeof(clusterInfo)); msInitShape(&feature->shape); feature->numsiblings = 0; feature->numcollected = 0; feature->numremoved = 0; feature->next = NULL; feature->group = NULL; feature->node = NULL; feature->siblings = NULL; feature->index = layerinfo->numFeatures; feature->filter = -1; /* not yet calculated */ ++layerinfo->numFeatures; return feature; } /* destroy memory of the cluster list */ static void clusterInfoDestroyList(msClusterLayerInfo* layerinfo, clusterInfo* feature) { clusterInfo* s = feature; clusterInfo* next; /* destroy the shapes added to this node */ while (s) { next = s->next; if (s->siblings) { clusterInfoDestroyList(layerinfo, s->siblings); } msFreeShape(&s->shape); msFree(s->group); msFree(s); --layerinfo->numFeatures; s = next; } } /* alloc memory for a new treenode */ static clusterTreeNode *clusterTreeNodeCreate(msClusterLayerInfo* layerinfo, rectObj rect) { clusterTreeNode* node = (clusterTreeNode*)msSmallMalloc(sizeof(clusterTreeNode)); node->rect = rect; node->numshapes = 0; node->shapes = NULL; node->subnode[0] = node->subnode[1] = node->subnode[2] = node->subnode[3] = NULL; node->index = layerinfo->numNodes; node->position = 0; ++layerinfo->numNodes; return node; } /* traverse the quadtree and destroy all sub elements */ static void clusterTreeNodeDestroy(msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; /* destroy the shapes added to this node */ clusterInfoDestroyList(layerinfo, node->shapes); /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) clusterTreeNodeDestroy(layerinfo, node->subnode[i]); } msFree(node); --layerinfo->numNodes; } /* destroy memory of the cluster finalized list (without recursion) */ static void clusterTreeNodeDestroyList(msClusterLayerInfo* layerinfo, clusterTreeNode *node) { clusterTreeNode* n = node; clusterTreeNode* next; /* destroy the list of nodes */ while (n) { next = n->subnode[0]; n->subnode[0] = NULL; clusterTreeNodeDestroy(layerinfo, n); --layerinfo->numFinalizedNodes; n = next; } } void clusterDestroyData(msClusterLayerInfo *layerinfo) { if (layerinfo->finalized) { clusterInfoDestroyList(layerinfo, layerinfo->finalized); layerinfo->finalized = NULL; } layerinfo->numFinalized = 0; if (layerinfo->finalizedSiblings) { clusterInfoDestroyList(layerinfo, layerinfo->finalizedSiblings); layerinfo->finalizedSiblings = NULL; } layerinfo->numFinalizedSiblings = 0; if (layerinfo->filtered) { clusterInfoDestroyList(layerinfo, layerinfo->filtered); layerinfo->filtered = NULL; } layerinfo->numFiltered = 0; if (layerinfo->finalizedNodes) { clusterTreeNodeDestroyList(layerinfo, layerinfo->finalizedNodes); layerinfo->finalizedNodes = NULL; } layerinfo->numFinalizedNodes = 0; if (layerinfo->root) { clusterTreeNodeDestroy(layerinfo, layerinfo->root); layerinfo->root = NULL; } layerinfo->numNodes = 0; } /* traverse the quadtree to find the neighbouring shapes and update some data on the related shapes (when adding a new feature)*/ static void findRelatedShapes(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* s; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, ¤t->bounds)) return; /* Modify the feature count of the related shapes */ s = node->shapes; while (s) { if (layerinfo->fnCompare(current, s)) { ++current->numsiblings; /* calculating the average positions */ current->avgx = (current->avgx * current->numsiblings + s->x) / (current->numsiblings + 1); current->avgy = (current->avgy * current->numsiblings + s->y) / (current->numsiblings + 1); /* calculating the variance */ current->varx = current->varx * current->numsiblings / (current->numsiblings + 1) + (s->x - current->avgx) * (s->x - current->avgx) / (current->numsiblings + 1); current->vary = current->vary * current->numsiblings / (current->numsiblings + 1) + (s->y - current->avgy) * (s->y - current->avgy) / (current->numsiblings + 1); if (layerinfo->fnCompare(s, current)) { /* this feature falls into the region of the other as well */ ++s->numsiblings; /* calculating the average positions */ s->avgx = (s->avgx * s->numsiblings + current->x) / (s->numsiblings + 1); s->avgy = (s->avgy * s->numsiblings + current->y) / (s->numsiblings + 1); /* calculating the variance */ s->varx = s->varx * s->numsiblings / (s->numsiblings + 1) + (current->x - s->avgx) * (current->x - s->avgx) / (s->numsiblings + 1); s->vary = s->vary * s->numsiblings / (s->numsiblings + 1) + (current->y - s->avgy) * (current->y - s->avgy) / (s->numsiblings + 1); } } s = s->next; } if (node->subnode[0] == NULL) return; /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findRelatedShapes(layerinfo, node->subnode[i], current); } } /* traverse the quadtree to find the neighbouring shapes and update some data on the related shapes (when removing a feature) */ static void findRelatedShapesRemove(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* s; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, ¤t->bounds)) return; /* Modify the feature count of the related shapes */ s = node->shapes; while (s) { if (layerinfo->fnCompare(current, s)) { if (s->numsiblings > 0) { /* calculating the average positions */ s->avgx = (s->avgx * (s->numsiblings + 1) - current->x) / s->numsiblings; s->avgy = (s->avgy * (s->numsiblings + 1) - current->y) / s->numsiblings; /* calculating the variance */ s->varx = (s->varx - (current->x - s->avgx) * (current->x - s->avgx) / s->numsiblings) * (s->numsiblings + 1) / s->numsiblings; s->vary = (s->vary - (current->y - s->avgy) * (current->y - s->avgy) / s->numsiblings) * (s->numsiblings + 1) / s->numsiblings; --s->numsiblings; ++s->numremoved; } } s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findRelatedShapesRemove(layerinfo, node->subnode[i], current); } } /* setting the aggregated attributes */ static void InitShapeAttributes(layerObj* layer, clusterInfo* base) { int i; int* itemindexes = layer->iteminfo; for (i = 0; i < layer->numitems; i++) { if (base->shape.numvalues <= i) break; if (itemindexes[i] == MSCLUSTER_FEATURECOUNTINDEX) { if (base->shape.values[i]) msFree(base->shape.values[i]); base->shape.values[i] = msIntToString(base->numsiblings + 1); } else if (itemindexes[i] == MSCLUSTER_GROUPINDEX) { if (base->shape.values[i]) msFree(base->shape.values[i]); if (base->group) base->shape.values[i] = msStrdup(base->group); else base->shape.values[i] = msStrdup(""); } else if (EQUALN(layer->items[i], "Count:", 6)) { if (base->shape.values[i]) msFree(base->shape.values[i]); base->shape.values[i] = msStrdup("1"); /* initial count */ } } } /* update the shape attributes (aggregate) */ static void UpdateShapeAttributes(layerObj* layer, clusterInfo* base, clusterInfo* current) { int i; int* itemindexes = layer->iteminfo; for (i = 0; i < layer->numitems; i++) { if (base->shape.numvalues <= i) break; if (itemindexes[i] == MSCLUSTER_FEATURECOUNTINDEX || itemindexes[i] == MSCLUSTER_GROUPINDEX) continue; if (current->shape.numvalues <= i) break; if (current->shape.values[i]) { if (EQUALN(layer->items[i], "Min:", 4)) { if (strcasecmp(base->shape.values[i], current->shape.values[i]) > 0) { msFree(base->shape.values[i]); base->shape.values[i] = msStrdup(current->shape.values[i]); } } else if (EQUALN(layer->items[i], "Max:", 4)) { if (strcasecmp(base->shape.values[i], current->shape.values[i]) < 0) { msFree(base->shape.values[i]); base->shape.values[i] = msStrdup(current->shape.values[i]); } } else if (EQUALN(layer->items[i], "Sum:", 4)) { double sum = atof(base->shape.values[i]) + atof(current->shape.values[i]); msFree(base->shape.values[i]); base->shape.values[i] = msDoubleToString(sum, MS_FALSE); } else if (EQUALN(layer->items[i], "Count:", 6)) { int count = atoi(base->shape.values[i]) + 1; msFree(base->shape.values[i]); base->shape.values[i] = msIntToString(count); } else if (!EQUAL(base->shape.values[i], current->shape.values[i]) && !EQUAL(base->shape.values[i], "")) { /* clear the value if that doesn't match */ msFree(base->shape.values[i]); base->shape.values[i] = msStrdup(""); } } } } static int BuildFeatureAttributes(layerObj* layer, msClusterLayerInfo* layerinfo, shapeObj* shape) { char** values; int i; int* itemindexes = layer->iteminfo; if (layer->numitems == layerinfo->srcLayer.numitems) return MS_SUCCESS; /* we don't have custom attributes, no need to reconstruct the array */ values = msSmallMalloc(sizeof(char*) * (layer->numitems)); for (i = 0; i < layer->numitems; i++) { if (itemindexes[i] == MSCLUSTER_FEATURECOUNTINDEX) { values[i] = NULL; /* not yet assigned */ } else if (itemindexes[i] == MSCLUSTER_GROUPINDEX) { values[i] = NULL; /* not yet assigned */ } else if (shape->values[itemindexes[i]]) values[i] = msStrdup(shape->values[itemindexes[i]]); else values[i] = msStrdup(""); } if (shape->values) msFreeCharArray(shape->values, shape->numvalues); shape->values = values; shape->numvalues = layer->numitems; return MS_SUCCESS; } /* traverse the quadtree to find the best renking cluster */ static void findBestCluster(layerObj* layer, msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; double rank; clusterInfo* s = node->shapes; while (s) { if (s->filter < 0 && layer->cluster.filter.string != NULL) { InitShapeAttributes(layer, s); s->filter = msClusterEvaluateFilter(&layer->cluster.filter, &s->shape); } if (s->numsiblings == 0 || s->filter == 0) { /* individual or filtered shapes must be removed for sure */ layerinfo->current = s; return; } /* calculating the rank */ rank = (s->x - s->avgx) * (s->x - s->avgx) + (s->y - s->avgy) * (s->y - s->avgy) /*+ s->varx + s->vary*/ + (double)1/ (1 + s->numsiblings); if (rank < layerinfo->rank) { layerinfo->current = s; layerinfo->rank = rank; } s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findBestCluster(layer, layerinfo, node->subnode[i]); } } /* adding the shape based on the shape bounds (point) */ static int treeNodeAddShape(msClusterLayerInfo* layerinfo, clusterTreeNode* node, clusterInfo* shape, int depth) { int i; /* -------------------------------------------------------------------- */ /* If there are subnodes, then consider whether this object */ /* will fit in them. */ /* -------------------------------------------------------------------- */ if( depth > 1 && node->subnode[0] != NULL ) { for(i = 0; i < 4; i++ ) { if( msRectContained(&shape->shape.bounds, &node->subnode[i]->rect)) { return treeNodeAddShape( layerinfo, node->subnode[i], shape, depth-1); } } } /* -------------------------------------------------------------------- */ /* Otherwise, consider creating four subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ else if( depth > 1 && node->subnode[0] == NULL ) { rectObj half1, half2, quad1, quad2, quad3, quad4; int subnode = -1; treeSplitBounds(&node->rect, &half1, &half2); treeSplitBounds(&half1, &quad1, &quad2); treeSplitBounds(&half2, &quad3, &quad4); if(msRectContained(&shape->shape.bounds, &quad1)) subnode = 0; else if(msRectContained(&shape->shape.bounds, &quad2)) subnode = 1; else if(msRectContained(&shape->shape.bounds, &quad3)) subnode = 2; else if(msRectContained(&shape->shape.bounds, &quad4)) subnode = 3; if (subnode >= 0) { if ((node->subnode[0] = clusterTreeNodeCreate(layerinfo, quad1)) == NULL) return MS_FAILURE; node->subnode[0]->position = node->position * 4; if ((node->subnode[1] = clusterTreeNodeCreate(layerinfo, quad2)) == NULL) return MS_FAILURE; node->subnode[1]->position = node->position * 4 + 1; if ((node->subnode[2] = clusterTreeNodeCreate(layerinfo, quad3)) == NULL) return MS_FAILURE; node->subnode[2]->position = node->position * 4 + 2; if ((node->subnode[3] = clusterTreeNodeCreate(layerinfo, quad4)) == NULL) return MS_FAILURE; node->subnode[3]->position = node->position * 4 + 3; /* add to subnode */ return treeNodeAddShape(layerinfo, node->subnode[subnode], shape, depth-1); } } /* found the right place, add this shape to the node */ node->numshapes++; shape->next = node->shapes; node->shapes = shape; shape->node = node; return MS_SUCCESS; } /* collecting the cluster shapes, returns true if this subnode must be removed */ static int collectClusterShapes(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* prev = NULL; clusterInfo* s = node->shapes; if(!msRectOverlap(&node->rect, ¤t->bounds)) return (!node->shapes && !node->subnode[0] && !node->subnode[1] && !node->subnode[2] && !node->subnode[3]); /* removing the shapes from this node if overlap with the cluster */ while (s) { if (s == current || layerinfo->fnCompare(current, s)) { if (s != current && current->filter == 0) { /* skip siblings of the filtered shapes */ prev = s; s = prev->next; continue; } /* removing from the list */ if (!prev) node->shapes = s->next; else prev->next = s->next; ++current->numcollected; /* adding the shape to the finalization list */ if (s == current) { if (s->filter) { s->next = layerinfo->finalized; layerinfo->finalized = s; ++layerinfo->numFinalized; } else { /* this shape is filtered */ s->next = layerinfo->filtered; layerinfo->filtered = s; ++layerinfo->numFiltered; } } else { s->next = layerinfo->finalizedSiblings; layerinfo->finalizedSiblings = s; ++layerinfo->numFinalizedSiblings; } if (!prev) s = node->shapes; else s = prev->next; } else { prev = s; s = prev->next; } } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i] && collectClusterShapes(layerinfo, node->subnode[i], current)) { /* placing this empty node to the finalization queue */ node->subnode[i]->subnode[0] = layerinfo->finalizedNodes; layerinfo->finalizedNodes = node->subnode[i]; node->subnode[i] = NULL; ++layerinfo->numFinalizedNodes; } } /* returns true is this subnode must be removed */ return (!node->shapes && !node->subnode[0] && !node->subnode[1] && !node->subnode[2] && !node->subnode[3]); } int selectClusterShape(layerObj* layer, long shapeindex) { int i; clusterInfo* current; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer not open: %s", "selectClusterShape()", layer->name); return MS_FAILURE; } i = 0; current = layerinfo->finalized; while (current && i < shapeindex) { ++i; current = current->next; } current->next = current->siblings; layerinfo->current = current; current->shape.line[0].point[0].x = current->shape.bounds.minx = current->shape.bounds.maxx = current->avgx; current->shape.line[0].point[0].y = current->shape.bounds.miny = current->shape.bounds.maxy = current->avgy; return MS_SUCCESS; } /* update the parameters from the related shapes */ #ifndef NDEBUG static void UpdateClusterParameters(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo *shape) { int i; clusterInfo* s = node->shapes; while (s) { if (layerinfo->fnCompare(shape, s)) { shape->avgx += s->x; shape->avgy += s->y; ++shape->numsiblings; } s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) UpdateClusterParameters(layerinfo, node->subnode[i], shape); } } /* check for the validity of the clusters added to the tree (for debug purposes) */ static int ValidateTree(msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; int isValid = MS_TRUE; clusterInfo* s = node->shapes; while (s) { double avgx = s->avgx; double avgy = s->avgy; int numsiblings = s->numsiblings; s->avgx = 0; s->avgy = 0; s->numsiblings = 0; UpdateClusterParameters(layerinfo, layerinfo->root, s); if (numsiblings + 1 != s->numsiblings) isValid = MS_FALSE; else if ((avgx * s->numsiblings - s->avgx) / s->avgx > 0.000001) isValid = MS_FALSE; else if ((avgy * s->numsiblings - s->avgy) / s->avgy > 0.000001) isValid = MS_FALSE; s->avgx = avgx; s->avgy = avgy; s->numsiblings = numsiblings; if (isValid == MS_FALSE) return MS_FALSE; s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i] && ValidateTree(layerinfo, node->subnode[i]) == MS_FALSE) return MS_FALSE; } /* returns true if this node contains only valid clusters */ return MS_TRUE; } #endif /* rebuild the clusters according to the current extent */ int RebuildClusters(layerObj *layer, int isQuery) { mapObj* map; layerObj* srcLayer; double distance, maxDistanceX, maxDistanceY, cellSizeX, cellSizeY; rectObj searchrect; int status; clusterInfo* current; int depth; #ifdef USE_CLUSTER_EXTERNAL int layerIndex; #endif msClusterLayerInfo* layerinfo = layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer is not open: %s", "RebuildClusters()", layer->name); return MS_FAILURE; } if (!layer->map) { msSetError(MS_MISCERR, "No map associated with this layer: %s", "RebuildClusters()", layer->name); return MS_FAILURE; } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Clustering started.\n"); map = layer->map; layerinfo->current = layerinfo->finalized; /* restart */ /* check whether all shapes should be returned from a query */ if(msLayerGetProcessingKey(layer, "CLUSTER_GET_ALL_SHAPES") != NULL) layerinfo->get_all_shapes = MS_TRUE; else layerinfo->get_all_shapes = MS_FALSE; /* identify the current extent */ if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } if (searchrect.minx == layerinfo->searchRect.minx && searchrect.miny == layerinfo->searchRect.miny && searchrect.maxx == layerinfo->searchRect.maxx && searchrect.maxy == layerinfo->searchRect.maxy) { /* already built */ return MS_SUCCESS; } /* destroy previous data*/ clusterDestroyData(layerinfo); layerinfo->searchRect = searchrect; /* reproject the rectangle to layer coordinates */ #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif /* determine the compare method */ layerinfo->fnCompare = CompareRectangleRegion; if (layer->cluster.region) { if (EQUAL(layer->cluster.region, "ellipse")) layerinfo->fnCompare = CompareEllipseRegion; } /* trying to find a reasonable quadtree depth */ depth = 0; distance = layer->cluster.maxdistance; while ((distance < map->width || distance < map->height) && depth <= TREE_MAX_DEPTH) { distance *= 2; ++depth; } layerinfo->depth = depth; cellSizeX = MS_CELLSIZE(searchrect.minx, searchrect.maxx, map->width); cellSizeY = MS_CELLSIZE(searchrect.miny, searchrect.maxy, map->height); maxDistanceX = layer->cluster.maxdistance * cellSizeX; maxDistanceY = layer->cluster.maxdistance * cellSizeY; /* increase the search rectangle so that the neighbouring shapes are also retrieved */ searchrect.minx -= layer->cluster.buffer * cellSizeX; searchrect.maxx += layer->cluster.buffer * cellSizeX; searchrect.miny -= layer->cluster.buffer * cellSizeY; searchrect.maxy += layer->cluster.buffer * cellSizeY; /* create the root node */ if (layerinfo->root) clusterTreeNodeDestroy(layerinfo, layerinfo->root); layerinfo->root = clusterTreeNodeCreate(layerinfo, searchrect); srcLayer = &layerinfo->srcLayer; /* start retrieving the shapes */ status = msLayerWhichShapes(srcLayer, searchrect, isQuery); if(status == MS_DONE) { /* no overlap */ return MS_SUCCESS; } else if(status != MS_SUCCESS) { return MS_FAILURE; } /* step through the source shapes and populate the quadtree with the tentative clusters */ if ((current = clusterInfoCreate(layerinfo)) == NULL) return MS_FAILURE; while((status = msLayerNextShape(srcLayer, ¤t->shape)) == MS_SUCCESS) { #if defined(USE_PROJ) && defined(USE_CLUSTER_EXTERNAL) /* transform the shape to the projection of this layer */ if(srcLayer->transform == MS_TRUE && srcLayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srcLayer->projection), &(layer->projection))) msProjectShape(&srcLayer->projection, &layer->projection, ¤t->shape); #endif /* set up positions and variance */ current->avgx = current->x = current->shape.bounds.minx; current->avgy = current->y = current->shape.bounds.miny; current->varx = current->vary = 0; /* set up the area of interest when searching for the neighboring shapes */ current->bounds.minx = current->x - maxDistanceX; current->bounds.miny = current->y - maxDistanceY; current->bounds.maxx = current->x + maxDistanceX; current->bounds.maxy = current->y + maxDistanceY; /* if the shape doesn't overlap we must skip it to avoid further issues */ if(!msRectOverlap(&searchrect, ¤t->bounds)) { msFreeShape(¤t->shape); msInitShape(¤t->shape); msDebug("Skipping an invalid shape falling outside of the given extent\n"); continue; } /* construct the item array */ if (layer->iteminfo) BuildFeatureAttributes(layer, layerinfo, ¤t->shape); /* evaluate the group expression */ if (layer->cluster.group.string) current->group = msClusterGetGroupText(&layer->cluster.group, ¤t->shape); /*start a query for the related shapes */ findRelatedShapes(layerinfo, layerinfo->root, current); /* add this shape to the tree */ if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } if ((current = clusterInfoCreate(layerinfo)) == NULL) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } } clusterInfoDestroyList(layerinfo, current); while (layerinfo->root) { #ifdef TESTCOUNT int n; double avgx, avgy; #endif /* pick up the best cluster from the tree and do the finalization */ /* the initial rank must be big enough */ layerinfo->rank = (searchrect.maxx - searchrect.minx) * (searchrect.maxx - searchrect.minx) + (searchrect.maxy - searchrect.miny) * (searchrect.maxy - searchrect.miny) + 1; layerinfo->current = NULL; findBestCluster(layer, layerinfo, layerinfo->root); if (layerinfo->current == NULL) { if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Clustering terminated.\n"); break; /* completed */ } /* Update the feature count of the shape */ InitShapeAttributes(layer, layerinfo->current); /* collecting the shapes of the cluster */ collectClusterShapes(layerinfo, layerinfo->root, layerinfo->current); if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("processing cluster %p: rank=%lf fcount=%d ncoll=%d nfin=%d nfins=%d nflt=%d bounds={%lf %lf %lf %lf}\n", layerinfo->current, layerinfo->rank, layerinfo->current->numsiblings + 1, layerinfo->current->numcollected, layerinfo->numFinalized, layerinfo->numFinalizedSiblings, layerinfo->numFiltered, layerinfo->current->bounds.minx, layerinfo->current->bounds.miny, layerinfo->current->bounds.maxx, layerinfo->current->bounds.maxy); if (layerinfo->current->node) { char pszBuffer[TREE_MAX_DEPTH + 1]; clusterTreeNode* node = layerinfo->current->node; int position = node->position; int i = 1; while (position > 0 && i <= TREE_MAX_DEPTH) { pszBuffer[TREE_MAX_DEPTH - i] = '0' + (position % 4); position = position >> 2; ++i; } pszBuffer[TREE_MAX_DEPTH] = 0; msDebug(" ->node %p: count=%d index=%d pos=%s subn={%p %p %p %p} rect={%lf %lf %lf %lf}\n", node, node->numshapes, node->index, pszBuffer + TREE_MAX_DEPTH - i + 1, node->subnode[0], node->subnode[1], node->subnode[2], node->subnode[3], node->rect.minx, node->rect.miny, node->rect.maxx, node->rect.maxy); } } #ifdef TESTCOUNT avgx = layerinfo->current->x; avgy = layerinfo->current->y; n = 0; #endif if (layerinfo->current->numsiblings > 0) { /* update the parameters due to the shape removal */ findRelatedShapesRemove(layerinfo, layerinfo->root, layerinfo->current); if (layerinfo->current->filter == 0) { /* filtered shapes has no siblings */ layerinfo->current->numsiblings = 0; layerinfo->current->avgx = layerinfo->current->x; layerinfo->current->avgy = layerinfo->current->y; } /* update the parameters of the related shapes if any */ if (layerinfo->finalizedSiblings) { current = layerinfo->finalizedSiblings; while(current) { /* update the parameters due to the shape removal */ findRelatedShapesRemove(layerinfo, layerinfo->root, current); UpdateShapeAttributes(layer, layerinfo->current, current); #ifdef TESTCOUNT avgx += current->x; avgy += current->y; ++n; #endif /* setting the average position to the same value */ current->avgx = layerinfo->current->avgx; current->avgy = layerinfo->current->avgy; if (current->next == NULL) { if (layerinfo->get_all_shapes == MS_TRUE) { /* insert the siblings into the finalization list */ current->next = layerinfo->finalized; layerinfo->finalized = layerinfo->finalizedSiblings; } else { /* preserve the clustered siblings for later use */ layerinfo->current->siblings = layerinfo->finalizedSiblings; } break; } current = current->next; } layerinfo->finalizedSiblings = NULL; } } #ifdef TESTCOUNT avgx /= (n + 1); avgy /= (n + 1); if (layerinfo->current->numsiblings != n) layerinfo->current->numsiblings = n; if (fabs(layerinfo->current->avgx - avgx) / avgx > 0.000000001 || fabs(layerinfo->current->avgy - avgy) / avgy > 0.000000001) { layerinfo->current->avgx = avgx; layerinfo->current->avgy = avgy; } #endif } /* set the pointer to the first shape */ layerinfo->current = layerinfo->finalized; return MS_SUCCESS; } /* Close the the combined layer */ int msClusterLayerClose(layerObj *layer) { msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) return MS_SUCCESS; clusterDestroyData(layerinfo); msLayerClose(&layerinfo->srcLayer); freeLayer(&layerinfo->srcLayer); msFree(layerinfo); layer->layerinfo = NULL; #ifndef USE_CLUSTER_EXTERNAL /* switch back to the source layer vtable */ msInitializeVirtualTable(layer); #endif return MS_SUCCESS; } /* Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msClusterLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return(MS_TRUE); else return(MS_FALSE); } /* Free the itemindexes array in a layer. */ void msClusterLayerFreeItemInfo(layerObj *layer) { msFree(layer->iteminfo); layer->iteminfo = NULL; } /* allocate the iteminfo index array - same order as the item list */ int msClusterLayerInitItemInfo(layerObj *layer) { int i, numitems; int *itemindexes; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if(layer->numitems == 0) { return MS_SUCCESS; } if (!layerinfo) return MS_FAILURE; /* Cleanup any previous item selection */ msClusterLayerFreeItemInfo(layer); layer->iteminfo = (int *) msSmallMalloc(sizeof(int) * layer->numitems); itemindexes = layer->iteminfo; /* check whether we require attributes from the source layers also */ numitems = 0; for (i = 0; i < layer->numitems; i++) { if (EQUAL(layer->items[i], MSCLUSTER_FEATURECOUNT)) itemindexes[i] = MSCLUSTER_FEATURECOUNTINDEX; else if (EQUAL(layer->items[i], MSCLUSTER_GROUP)) itemindexes[i] = MSCLUSTER_GROUPINDEX; else itemindexes[i] = numitems++; } msLayerFreeItemInfo(&layerinfo->srcLayer); if(layerinfo->srcLayer.items) { msFreeCharArray(layerinfo->srcLayer.items, layerinfo->srcLayer.numitems); layerinfo->srcLayer.items = NULL; layerinfo->srcLayer.numitems = 0; } if (numitems > 0) { /* now allocate and set the layer item parameters */ layerinfo->srcLayer.items = (char **)msSmallMalloc(sizeof(char *)*numitems); layerinfo->srcLayer.numitems = numitems; for (i = 0; i < layer->numitems; i++) { if (itemindexes[i] >= 0) { if (EQUALN(layer->items[i], "Min:", 4)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 4); else if (EQUALN(layer->items[i], "Max:", 4)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 4); else if (EQUALN(layer->items[i], "Sum:", 4)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 4); else if (EQUALN(layer->items[i], "Count:", 6)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 6); else layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i]); } } if (msLayerInitItemInfo(&layerinfo->srcLayer) != MS_SUCCESS) return MS_FAILURE; } return MS_SUCCESS; } /* Execute a query for this layer */ int msClusterLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { /* rebuild the cluster database */ return RebuildClusters(layer, isQuery); } static int prepareShape(layerObj* layer, msClusterLayerInfo* layerinfo, clusterInfo* current, shapeObj* shape) { if (msCopyShape(&(current->shape), shape) != MS_SUCCESS) { msSetError(MS_SHPERR, "Cannot retrieve inline shape. There some problem with the shape", "msClusterLayerNextShape()"); return MS_FAILURE; } /* update the positions of the cluster shape */ shape->line[0].point[0].x = shape->bounds.minx = shape->bounds.maxx = current->avgx; shape->line[0].point[0].y = shape->bounds.miny = shape->bounds.maxy = current->avgy; return MS_SUCCESS; } /* Execute a query on the DB based on fid. */ int msClusterLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { clusterInfo* current; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer not open: %s", "msClusterLayerGetShape()", layer->name); return MS_FAILURE; } current = layerinfo->finalized; while (current) { if (record->shapeindex == current->shape.index && record->tileindex == current->shape.tileindex) break; current = current->next; } if (current == NULL) { msSetError(MS_SHPERR, "No feature with this index.", "msClusterLayerGetShape()"); return MS_FAILURE; } return prepareShape(layer, layerinfo, current, shape); } /* find the next shape with the appropriate shape type */ /* also, load in the attribute data */ /* MS_DONE => no more data */ int msClusterLayerNextShape(layerObj *layer, shapeObj *shape) { int rv; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer not open: %s", "msClusterLayerNextShape()", layer->name); return MS_FAILURE; } if (!layerinfo->current) return MS_DONE; rv = prepareShape(layer, layerinfo, layerinfo->current, shape); layerinfo->current = layerinfo->current->next; return rv; } /* Query for the items collection */ int msClusterLayerGetItems(layerObj *layer) { /* we support certain built in attributes */ layer->numitems = MSCLUSTER_NUMITEMS; layer->items = msSmallMalloc(sizeof(char*) * (layer->numitems)); layer->items[0] = msStrdup(MSCLUSTER_FEATURECOUNT); layer->items[1] = msStrdup(MSCLUSTER_GROUP); return msClusterLayerInitItemInfo(layer); } int msClusterLayerGetNumFeatures(layerObj *layer) { msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) return -1; return layerinfo->numFinalized; } static int msClusterLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { /* TODO */ return MS_SUCCESS; } msClusterLayerInfo* msClusterInitialize(layerObj *layer) { msClusterLayerInfo *layerinfo =(msClusterLayerInfo*)msSmallMalloc(sizeof(msClusterLayerInfo)); layer->layerinfo = layerinfo; layerinfo->searchRect.minx = -1; layerinfo->searchRect.miny = -1; layerinfo->searchRect.maxx = -1; layerinfo->searchRect.maxy = -1; layerinfo->root = NULL; layerinfo->get_all_shapes = MS_FALSE; layerinfo->numFeatures = 0; layerinfo->numNodes = 0; layerinfo->finalized = NULL; layerinfo->numFinalized = 0; layerinfo->finalizedSiblings = NULL; layerinfo->numFinalizedSiblings = 0; layerinfo->filtered = NULL; layerinfo->numFiltered = 0; layerinfo->finalizedNodes = NULL; layerinfo->numFinalizedNodes = 0; return layerinfo; } int msClusterLayerOpen(layerObj *layer) { msClusterLayerInfo* layerinfo; if (layer->type != MS_LAYER_POINT) { msSetError(MS_MISCERR, "Only point layers are supported for clustering: %s", "msClusterLayerOpen()", layer->name); return MS_FAILURE; } if (!layer->map) return MS_FAILURE; if (layer->layerinfo) return MS_SUCCESS; /* already open */ layerinfo = msClusterInitialize(layer); if (!layer->layerinfo) return MS_FAILURE; /* prepare the source layer */ if(initLayer(&layerinfo->srcLayer, layer->map) == -1) return MS_FAILURE; #ifdef USE_CLUSTER_EXTERNAL if (!layer->map) return MS_FAILURE; layerIndex = msGetLayerIndex(layer->map, layer->connection); if (layerIndex < 0 && layerIndex >= layer->map->numlayers) { msSetError(MS_MISCERR, "No source layers specified in layer: %s", "msClusterLayerOpen()", layer->name); return MS_FAILURE; } if (layer->map->layers[layerIndex]->type != MS_LAYER_POINT) { msSetError(MS_MISCERR, "Only point layers are supported for cluster data source: %s", "msClusterLayerOpen()", layer->name); return MS_FAILURE; } if (msCopyLayer(&layerinfo->srcLayer, layer->map->layers[layerIndex]) != MS_SUCCESS) return(MS_FAILURE); #else /* hook the vtable to this driver, will be restored in LayerClose*/ if (!layer->vtable) { if (msInitializeVirtualTable(layer) != MS_SUCCESS) return MS_FAILURE; } msClusterLayerCopyVirtualTable(layer->vtable); if (msCopyLayer(&layerinfo->srcLayer, layer) != MS_SUCCESS) return(MS_FAILURE); #endif /* disable the connection pool for this layer */ msLayerSetProcessingKey(&layerinfo->srcLayer, "CLOSE_CONNECTION", "ALWAYS"); /* open the source layer */ if ( !layerinfo->srcLayer.vtable) { if (msInitializeVirtualTable(&layerinfo->srcLayer) != MS_SUCCESS) return MS_FAILURE; } if (layerinfo->srcLayer.vtable->LayerOpen(&layerinfo->srcLayer) != MS_SUCCESS) { return MS_FAILURE; } return MS_SUCCESS; } void msClusterLayerCopyVirtualTable(layerVTableObj* vtable) { vtable->LayerInitItemInfo = msClusterLayerInitItemInfo; vtable->LayerFreeItemInfo = msClusterLayerFreeItemInfo; vtable->LayerOpen = msClusterLayerOpen; vtable->LayerIsOpen = msClusterLayerIsOpen; vtable->LayerWhichShapes = msClusterLayerWhichShapes; vtable->LayerNextShape = msClusterLayerNextShape; vtable->LayerGetShape = msClusterLayerGetShape; vtable->LayerClose = msClusterLayerClose; vtable->LayerGetItems = msClusterLayerGetItems; vtable->LayerCloseConnection = msClusterLayerClose; vtable->LayerGetNumFeatures = msClusterLayerGetNumFeatures; vtable->LayerGetAutoStyle = msClusterLayerGetAutoStyle; } #ifdef USE_CLUSTER_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); msClusterLayerCopyVirtualTable(vtable); return MS_SUCCESS; } #endif int msClusterLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); msClusterLayerCopyVirtualTable(layer->vtable); return MS_SUCCESS; } mapserver-6.4.1/mapparser.y0000644002461700001440000005446712261257215015520 0ustar tbonfortusers/* ** Parser for the mapserver */ %{ /* C declarations */ #include #include #include #include #include #include "mapserver.h" /* for TRUE/FALSE and REGEX includes */ #include "maptime.h" /* for time comparison routines */ #include "mapprimitive.h" /* for shapeObj */ #include "mapparser.h" /* for YYSTYPE in the function prototype for yylex() */ int yylex(YYSTYPE *, parseObj *); /* prototype functions, defined after the grammar */ int yyerror(parseObj *, const char *); %} /* Bison/Yacc declarations */ /* %define api.pure */ %pure_parser %parse-param {parseObj *p} %lex-param {parseObj *p} %union { double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; } %token NUMBER %token STRING %token TIME %token SHAPE %left OR %left AND %left NOT %left RE EQ NE LT GT LE GE IN IEQ IRE %left INTERSECTS DISJOINT TOUCHES OVERLAPS CROSSES WITHIN CONTAINS BEYOND DWITHIN %left AREA LENGTH COMMIFY ROUND %left TOSTRING %left YYBUFFER DIFFERENCE SIMPLIFY SIMPLIFYPT GENERALIZE SMOOTHSIA %left '+' '-' %left '*' '/' '%' %left NEG %right '^' %type logical_exp %type math_exp %type string_exp %type time_exp %type shape_exp /* Bison/Yacc grammar */ %% input: /* empty string */ | logical_exp { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): p->result.intval = $1; break; case(MS_PARSE_TYPE_STRING): if($1) p->result.strval = strdup("true"); else p->result.strval = strdup("false"); break; } } | math_exp { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if($1 != 0) p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = (char *)malloc(64); /* large enough for a double */ snprintf(p->result.strval, 64, "%g", $1); break; } } | string_exp { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if($1) /* string is not NULL */ p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = $1; // strdup($1); break; } } | shape_exp { switch(p->type) { case(MS_PARSE_TYPE_SHAPE): p->result.shpval = $1; p->result.shpval->scratch = MS_FALSE; break; } } ; logical_exp: logical_exp OR logical_exp { if($1 == MS_TRUE) $$ = MS_TRUE; else if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } | logical_exp AND logical_exp { if($1 == MS_TRUE) { if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | logical_exp OR math_exp { if($1 == MS_TRUE) $$ = MS_TRUE; else if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | logical_exp AND math_exp { if($1 == MS_TRUE) { if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | math_exp OR logical_exp { if($1 != 0) $$ = MS_TRUE; else if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp AND logical_exp { if($1 != 0) { if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | math_exp OR math_exp { if($1 != 0) $$ = MS_TRUE; else if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp AND math_exp { if($1 != 0) { if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | NOT logical_exp { $$ = !$2; } | NOT math_exp { $$ = !$2; } | string_exp RE string_exp { ms_regex_t re; if(ms_regcomp(&re, $3, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) $$ = MS_FALSE; if(ms_regexec(&re, $1, 0, NULL, 0) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; ms_regfree(&re); free($1); free($3); } | string_exp IRE string_exp { ms_regex_t re; if(ms_regcomp(&re, $3, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) $$ = MS_FALSE; if(ms_regexec(&re, $1, 0, NULL, 0) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; ms_regfree(&re); free($1); free($3); } | math_exp EQ math_exp { if($1 == $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp NE math_exp { if($1 != $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp GT math_exp { if($1 > $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp LT math_exp { if($1 < $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp GE math_exp { if($1 >= $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp LE math_exp { if($1 <= $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | '(' logical_exp ')' { $$ = $2; } | string_exp EQ string_exp { if(strcmp($1, $3) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp NE string_exp { if(strcmp($1, $3) != 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp GT string_exp { if(strcmp($1, $3) > 0) $$ = MS_TRUE; else $$ = MS_FALSE; /* printf("Not freeing: %s >= %s\n",$1, $3); */ free($1); free($3); } | string_exp LT string_exp { if(strcmp($1, $3) < 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp GE string_exp { if(strcmp($1, $3) >= 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp LE string_exp { if(strcmp($1, $3) <= 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | time_exp EQ time_exp { if(msTimeCompare(&($1), &($3)) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp NE time_exp { if(msTimeCompare(&($1), &($3)) != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp GT time_exp { if(msTimeCompare(&($1), &($3)) > 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp LT time_exp { if(msTimeCompare(&($1), &($3)) < 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp GE time_exp { if(msTimeCompare(&($1), &($3)) >= 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp LE time_exp { if(msTimeCompare(&($1), &($3)) <= 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | string_exp IN string_exp { char *delim,*bufferp; $$ = MS_FALSE; bufferp=$3; while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if(strcmp($1,bufferp) == 0) { $$ = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if($$==MS_FALSE && strcmp($1,bufferp) == 0) // test for last (or only) item $$ = MS_TRUE; free($1); free($3); } | math_exp IN string_exp { char *delim,*bufferp; $$ = MS_FALSE; bufferp=$3; while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if($1 == atof(bufferp)) { $$ = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if($1 == atof(bufferp)) // is this test necessary? $$ = MS_TRUE; free($3); } | math_exp IEQ math_exp { if($1 == $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | string_exp IEQ string_exp { if(strcasecmp($1, $3) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | time_exp IEQ time_exp { if(msTimeCompare(&($1), &($3)) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | shape_exp EQ shape_exp { int rval; rval = msGEOSEquals($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Equals (EQ or ==) operator failed."); return(-1); } else $$ = rval; } | shape_exp INTERSECTS shape_exp { int rval; rval = msGEOSIntersects($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Intersects operator failed."); return(-1); } else $$ = rval; } | shape_exp DISJOINT shape_exp { int rval; rval = msGEOSDisjoint($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Disjoint operator failed."); return(-1); } else $$ = rval; } | shape_exp TOUCHES shape_exp { int rval; rval = msGEOSTouches($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Touches operator failed."); return(-1); } else $$ = rval; } | shape_exp OVERLAPS shape_exp { int rval; rval = msGEOSOverlaps($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Overlaps operator failed."); return(-1); } else $$ = rval; } | shape_exp CROSSES shape_exp { int rval; rval = msGEOSCrosses($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Crosses operator failed."); return(-1); } else $$ = rval; } | shape_exp WITHIN shape_exp { int rval; rval = msGEOSWithin($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Within operator failed."); return(-1); } else $$ = rval; } | shape_exp CONTAINS shape_exp { int rval; rval = msGEOSContains($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Contains operator failed."); return(-1); } else $$ = rval; } | shape_exp DWITHIN shape_exp { double d; d = msGEOSDistance($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(d == 0.0) $$ = MS_TRUE; else $$ = MS_FALSE; } | shape_exp BEYOND shape_exp { double d; d = msGEOSDistance($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(d > 0.0) $$ = MS_TRUE; else $$ = MS_FALSE; } ; math_exp: NUMBER | '(' math_exp ')' { $$ = $2; } | math_exp '+' math_exp { $$ = $1 + $3; } | math_exp '-' math_exp { $$ = $1 - $3; } | math_exp '*' math_exp { $$ = $1 * $3; } | math_exp '%' math_exp { $$ = (int)$1 % (int)$3; } | math_exp '/' math_exp { if($3 == 0.0) { yyerror(p, "Division by zero."); return(-1); } else $$ = $1 / $3; } | '-' math_exp %prec NEG { $$ = $2; } | math_exp '^' math_exp { $$ = pow($1, $3); } | LENGTH '(' string_exp ')' { $$ = strlen($3); } | AREA '(' shape_exp ')' { if($3->type != MS_SHAPE_POLYGON) { yyerror(p, "Area can only be computed for polygon shapes."); return(-1); } $$ = msGetPolygonArea($3); if($3->scratch == MS_TRUE) msFreeShape($3); } | ROUND '(' math_exp ',' math_exp ')' { $$ = (MS_NINT($3/$5))*$5; } ; shape_exp: SHAPE | '(' shape_exp ')' { $$ = $2; } | YYBUFFER '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGEOSBuffer($3, $5); if(!s) { yyerror(p, "Executing buffer failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | DIFFERENCE '(' shape_exp ',' shape_exp ')' { shapeObj *s; s = msGEOSDifference($3, $5); if(!s) { yyerror(p, "Executing difference failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SIMPLIFY '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGEOSSimplify($3, $5); if(!s) { yyerror(p, "Executing simplify failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SIMPLIFYPT '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGEOSTopologyPreservingSimplify($3, $5); if(!s) { yyerror(p, "Executing simplifypt failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | GENERALIZE '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGeneralize($3, $5); if(!s) { yyerror(p, "Executing generalize failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, 3, 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, $5, 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ',' math_exp ',' math_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, $5, $7, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ',' math_exp ',' math_exp ',' string_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, $5, $7, $9); free($9); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } ; string_exp: STRING | '(' string_exp ')' { $$ = $2; } | string_exp '+' string_exp { $$ = (char *)malloc(strlen($1) + strlen($3) + 1); sprintf($$, "%s%s", $1, $3); free($1); free($3); } | TOSTRING '(' math_exp ',' string_exp ')' { $$ = (char *) malloc(strlen($5) + 64); /* Plenty big? Should use snprintf below... */ sprintf($$, $5, $3); } | COMMIFY '(' string_exp ')' { $3 = msCommifyString($3); $$ = $3; } ; time_exp: TIME | '(' time_exp ')' { $$ = $2; } ; %% /* ** Any extra C functions */ int yylex(YYSTYPE *lvalp, parseObj *p) { int token; if(p->expr->curtoken == NULL) return(0); /* done */ // fprintf(stderr, "in yylex() - curtoken=%d...\n", p->expr->curtoken->token); token = p->expr->curtoken->token; /* may override */ switch(p->expr->curtoken->token) { case MS_TOKEN_LITERAL_NUMBER: token = NUMBER; (*lvalp).dblval = p->expr->curtoken->tokenval.dblval; break; case MS_TOKEN_LITERAL_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->expr->curtoken->tokenval.shpval)); (*lvalp).shpval = p->expr->curtoken->tokenval.shpval; break; case MS_TOKEN_LITERAL_STRING: // printf("token value = %s\n", p->expr->curtoken->tokenval.strval); token = STRING; (*lvalp).strval = strdup(p->expr->curtoken->tokenval.strval); break; case MS_TOKEN_LITERAL_TIME: token = TIME; (*lvalp).tmval = p->expr->curtoken->tokenval.tmval; break; case MS_TOKEN_COMPARISON_EQ: token = EQ; break; case MS_TOKEN_COMPARISON_IEQ: token = IEQ; break; case MS_TOKEN_COMPARISON_NE: token = NE; break; case MS_TOKEN_COMPARISON_LT: token = LT; break; case MS_TOKEN_COMPARISON_GT: token = GT; break; case MS_TOKEN_COMPARISON_LE: token = LE; break; case MS_TOKEN_COMPARISON_GE: token = GE; break; case MS_TOKEN_COMPARISON_RE: token = RE; break; case MS_TOKEN_COMPARISON_IRE: token = IRE; break; case MS_TOKEN_COMPARISON_INTERSECTS: token = INTERSECTS; break; case MS_TOKEN_COMPARISON_DISJOINT: token = DISJOINT; break; case MS_TOKEN_COMPARISON_TOUCHES: token = TOUCHES; break; case MS_TOKEN_COMPARISON_OVERLAPS: token = OVERLAPS; break; case MS_TOKEN_COMPARISON_CROSSES: token = CROSSES; break; case MS_TOKEN_COMPARISON_WITHIN: token = WITHIN; break; case MS_TOKEN_COMPARISON_CONTAINS: token = CONTAINS; break; case MS_TOKEN_COMPARISON_BEYOND: token = BEYOND; break; case MS_TOKEN_COMPARISON_DWITHIN: token = DWITHIN; break; case MS_TOKEN_LOGICAL_AND: token = AND; break; case MS_TOKEN_LOGICAL_OR: token = OR; break; case MS_TOKEN_LOGICAL_NOT: token = NOT; break; case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: token = NUMBER; (*lvalp).dblval = atof(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_STRING: token = STRING; (*lvalp).strval = strdup(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->shape)); (*lvalp).shpval = p->shape; break; case MS_TOKEN_BINDING_MAP_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval; break; case MS_TOKEN_BINDING_DATA_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval2; break; case MS_TOKEN_BINDING_TIME: token = TIME; msTimeInit(&((*lvalp).tmval)); if(msParseTime(p->shape->values[p->expr->curtoken->tokenval.bindval.index], &((*lvalp).tmval)) != MS_TRUE) { yyerror(p, "Parsing time value failed."); return(-1); } break; case MS_TOKEN_FUNCTION_AREA: token = AREA; break; case MS_TOKEN_FUNCTION_LENGTH: token = LENGTH; break; case MS_TOKEN_FUNCTION_TOSTRING: token = TOSTRING; break; case MS_TOKEN_FUNCTION_COMMIFY: token = COMMIFY; break; case MS_TOKEN_FUNCTION_ROUND: token = ROUND; break; case MS_TOKEN_FUNCTION_BUFFER: token = YYBUFFER; break; case MS_TOKEN_FUNCTION_DIFFERENCE: token = DIFFERENCE; break; case MS_TOKEN_FUNCTION_SIMPLIFY: token = SIMPLIFY; break; case MS_TOKEN_FUNCTION_SIMPLIFYPT: token = SIMPLIFYPT; break; case MS_TOKEN_FUNCTION_GENERALIZE: token = GENERALIZE; break; case MS_TOKEN_FUNCTION_SMOOTHSIA: token = SMOOTHSIA; break; default: break; } p->expr->curtoken = p->expr->curtoken->next; /* re-position */ return(token); } int yyerror(parseObj *p, const char *s) { msSetError(MS_PARSEERR, "%s", "yyparse()", s); return(0); } mapserver-6.4.1/mapxbase.c0000644002461700001440000010232412261257215015262 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: .dbf access API. Derived from shapelib, and relicensed with * permission of Frank Warmerdam (shapelib author). * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #define _FILE_OFFSET_BITS 64 #include "mapserver.h" #include /* for atof() and atoi() */ #include /* try to use a large file version of fseek for files up to 4GB (#3514) */ #if _MSC_VER > 1310 # define safe_fseek _fseeki64 #elif defined(fseeko) # define safe_fseek fseeko #else # define safe_fseek fseek #endif /************************************************************************/ /* SfRealloc() */ /* */ /* A realloc cover function that will access a NULL pointer as */ /* a valid input. */ /************************************************************************/ static void * SfRealloc( void * pMem, int nNewSize ) { if( pMem == NULL ) return( (void *) malloc(nNewSize) ); else return( (void *) realloc(pMem,nNewSize) ); } /************************************************************************/ /* writeHeader() */ /* */ /* This is called to write out the file header, and field */ /* descriptions before writing any actual data records. This */ /* also computes all the DBFDataSet field offset/size/decimals */ /* and so forth values. */ /************************************************************************/ static void writeHeader(DBFHandle psDBF) { uchar abyHeader[32]; int i; if( !psDBF->bNoHeader ) return; psDBF->bNoHeader = MS_FALSE; /* -------------------------------------------------------------------- */ /* Initialize the file header information. */ /* -------------------------------------------------------------------- */ for( i = 0; i < 32; i++ ) abyHeader[i] = 0; abyHeader[0] = 0x03; /* memo field? - just copying */ /* date updated on close, record count preset at zero */ abyHeader[8] = psDBF->nHeaderLength % 256; abyHeader[9] = psDBF->nHeaderLength / 256; abyHeader[10] = psDBF->nRecordLength % 256; abyHeader[11] = psDBF->nRecordLength / 256; /* -------------------------------------------------------------------- */ /* Write the initial 32 byte file header, and all the field */ /* descriptions. */ /* -------------------------------------------------------------------- */ fseek( psDBF->fp, 0, 0 ); fwrite( abyHeader, 32, 1, psDBF->fp ); fwrite( psDBF->pszHeader, 32, psDBF->nFields, psDBF->fp ); /* -------------------------------------------------------------------- */ /* Write out the newline character if there is room for it. */ /* -------------------------------------------------------------------- */ if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 ) { char cNewline; cNewline = 0x0d; fwrite( &cNewline, 1, 1, psDBF->fp ); } } /************************************************************************/ /* flushRecord() */ /* */ /* Write out the current record if there is one. */ /************************************************************************/ static void flushRecord( DBFHandle psDBF ) { unsigned int nRecordOffset; if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 ) { psDBF->bCurrentRecordModified = MS_FALSE; nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord + psDBF->nHeaderLength; safe_fseek( psDBF->fp, nRecordOffset, 0 ); fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); } } /************************************************************************/ /* msDBFOpen() */ /* */ /* Open a .dbf file. */ /************************************************************************/ DBFHandle msDBFOpen( const char * pszFilename, const char * pszAccess ) { DBFHandle psDBF; uchar *pabyBuf; int nFields, nRecords, nHeadLen, nRecLen, iField; char *pszDBFFilename; /* -------------------------------------------------------------------- */ /* We only allow the access strings "rb" and "r+". */ /* -------------------------------------------------------------------- */ if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0 && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"r+b") != 0 ) return( NULL ); /* -------------------------------------------------------------------- */ /* Ensure the extension is converted to dbf or DBF if it is */ /* currently .shp or .shx. */ /* -------------------------------------------------------------------- */ pszDBFFilename = (char *) msSmallMalloc(strlen(pszFilename)+1); strcpy( pszDBFFilename, pszFilename ); if( strcmp(pszFilename+strlen(pszFilename)-4,".shp") == 0 || strcmp(pszFilename+strlen(pszFilename)-4,".shx") == 0 ) { strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".dbf"); } else if( strcmp(pszFilename+strlen(pszFilename)-4,".SHP") == 0 || strcmp(pszFilename+strlen(pszFilename)-4,".SHX") == 0 ) { strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".DBF"); } /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) ); MS_CHECK_ALLOC(psDBF, sizeof(DBFInfo), NULL); psDBF->fp = fopen( pszDBFFilename, pszAccess ); if( psDBF->fp == NULL ) { if( strcmp(pszDBFFilename+strlen(pszDBFFilename)-4,".dbf") == 0 ) { strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".DBF"); psDBF->fp = fopen( pszDBFFilename, pszAccess ); } } if( psDBF->fp == NULL ) return( NULL ); psDBF->bNoHeader = MS_FALSE; psDBF->nCurrentRecord = -1; psDBF->bCurrentRecordModified = MS_FALSE; psDBF->pszStringField = NULL; psDBF->nStringFieldLen = 0; free( pszDBFFilename ); /* -------------------------------------------------------------------- */ /* Read Table Header info */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) msSmallMalloc(500); fread( pabyBuf, 32, 1, psDBF->fp ); psDBF->nRecords = nRecords = pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256; psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256; psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256; psDBF->nFields = nFields = (nHeadLen - 32) / 32; psDBF->pszCurrentRecord = (char *) msSmallMalloc(nRecLen); /* -------------------------------------------------------------------- */ /* Read in Field Definitions */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) SfRealloc(pabyBuf,nHeadLen); psDBF->pszHeader = (char *) pabyBuf; fseek( psDBF->fp, 32, 0 ); fread( pabyBuf, nHeadLen, 1, psDBF->fp ); psDBF->panFieldOffset = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->panFieldSize = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->panFieldDecimals = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->pachFieldType = (char *) msSmallMalloc(sizeof(char) * nFields); for( iField = 0; iField < nFields; iField++ ) { uchar *pabyFInfo; pabyFInfo = pabyBuf+iField*32; if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' ) { psDBF->panFieldSize[iField] = pabyFInfo[16]; psDBF->panFieldDecimals[iField] = pabyFInfo[17]; } else { psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256; psDBF->panFieldDecimals[iField] = 0; } psDBF->pachFieldType[iField] = (char) pabyFInfo[11]; if( iField == 0 ) psDBF->panFieldOffset[iField] = 1; else psDBF->panFieldOffset[iField] = psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1]; } return( psDBF ); } /************************************************************************/ /* msDBFClose() */ /************************************************************************/ void msDBFClose(DBFHandle psDBF) { /* -------------------------------------------------------------------- */ /* Write out header if not already written. */ /* -------------------------------------------------------------------- */ if( psDBF->bNoHeader ) writeHeader( psDBF ); flushRecord( psDBF ); /* -------------------------------------------------------------------- */ /* Update last access date, and number of records if we have */ /* write access. */ /* -------------------------------------------------------------------- */ if( psDBF->bUpdated ) { uchar abyFileHeader[32]; fseek( psDBF->fp, 0, 0 ); fread( abyFileHeader, 32, 1, psDBF->fp ); abyFileHeader[1] = 95; /* YY */ abyFileHeader[2] = 7; /* MM */ abyFileHeader[3] = 26; /* DD */ abyFileHeader[4] = psDBF->nRecords % 256; abyFileHeader[5] = (psDBF->nRecords/256) % 256; abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256; abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256; fseek( psDBF->fp, 0, 0 ); fwrite( abyFileHeader, 32, 1, psDBF->fp ); } /* -------------------------------------------------------------------- */ /* Close, and free resources. */ /* -------------------------------------------------------------------- */ fclose( psDBF->fp ); if( psDBF->panFieldOffset != NULL ) { free( psDBF->panFieldOffset ); free( psDBF->panFieldSize ); free( psDBF->panFieldDecimals ); free( psDBF->pachFieldType ); } free( psDBF->pszHeader ); free( psDBF->pszCurrentRecord ); if(psDBF->pszStringField) free(psDBF->pszStringField); free( psDBF ); } /************************************************************************/ /* msDBFCreate() */ /* */ /* Create a new .dbf file. */ /************************************************************************/ DBFHandle msDBFCreate( const char * pszFilename ) { DBFHandle psDBF; FILE *fp; /* -------------------------------------------------------------------- */ /* Create the file. */ /* -------------------------------------------------------------------- */ fp = fopen( pszFilename, "wb" ); if( fp == NULL ) return( NULL ); fputc( 0, fp ); fclose( fp ); fp = fopen( pszFilename, "rb+" ); if( fp == NULL ) return( NULL ); /* -------------------------------------------------------------------- */ /* Create the info structure. */ /* -------------------------------------------------------------------- */ psDBF = (DBFHandle) malloc(sizeof(DBFInfo)); if (psDBF == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDBFCreate()", __FILE__, __LINE__, (unsigned int)sizeof(DBFInfo)); fclose(fp); return NULL; } psDBF->fp = fp; psDBF->nRecords = 0; psDBF->nFields = 0; psDBF->nRecordLength = 1; psDBF->nHeaderLength = 33; psDBF->panFieldOffset = NULL; psDBF->panFieldSize = NULL; psDBF->panFieldDecimals = NULL; psDBF->pachFieldType = NULL; psDBF->pszHeader = NULL; psDBF->nCurrentRecord = -1; psDBF->bCurrentRecordModified = MS_FALSE; psDBF->pszCurrentRecord = NULL; psDBF->pszStringField = NULL; psDBF->nStringFieldLen = 0; psDBF->bNoHeader = MS_TRUE; psDBF->bUpdated = MS_FALSE; return( psDBF ); } /************************************************************************/ /* msDBFAddField() */ /* */ /* Add a field to a newly created .dbf file before any records */ /* are written. */ /************************************************************************/ int msDBFAddField(DBFHandle psDBF, const char * pszFieldName, DBFFieldType eType, int nWidth, int nDecimals ) { char *pszFInfo; int i; /* -------------------------------------------------------------------- */ /* Do some checking to ensure we can add records to this file. */ /* -------------------------------------------------------------------- */ if( psDBF->nRecords > 0 ) return( MS_FALSE ); if( !psDBF->bNoHeader ) return( MS_FALSE ); if( eType != FTDouble && nDecimals != 0 ) return( MS_FALSE ); /* -------------------------------------------------------------------- */ /* SfRealloc all the arrays larger to hold the additional field */ /* information. */ /* -------------------------------------------------------------------- */ psDBF->nFields++; psDBF->panFieldOffset = (int *) SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ); psDBF->panFieldSize = (int *) SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ); psDBF->panFieldDecimals = (int *) SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ); psDBF->pachFieldType = (char *) SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ); /* -------------------------------------------------------------------- */ /* Assign the new field information fields. */ /* -------------------------------------------------------------------- */ psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength; psDBF->nRecordLength += nWidth; psDBF->panFieldSize[psDBF->nFields-1] = nWidth; psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals; if( eType == FTString ) psDBF->pachFieldType[psDBF->nFields-1] = 'C'; else psDBF->pachFieldType[psDBF->nFields-1] = 'N'; /* -------------------------------------------------------------------- */ /* Extend the required header information. */ /* -------------------------------------------------------------------- */ psDBF->nHeaderLength += 32; psDBF->bUpdated = MS_FALSE; psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32); pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1); for( i = 0; i < 32; i++ ) pszFInfo[i] = '\0'; if( strlen(pszFieldName) < 10 ) strncpy( pszFInfo, pszFieldName, strlen(pszFieldName)); else strncpy( pszFInfo, pszFieldName, 10); pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1]; if( eType == FTString ) { pszFInfo[16] = nWidth % 256; pszFInfo[17] = nWidth / 256; } else { pszFInfo[16] = nWidth; pszFInfo[17] = nDecimals; } /* -------------------------------------------------------------------- */ /* Make the current record buffer appropriately larger. */ /* -------------------------------------------------------------------- */ psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord, psDBF->nRecordLength); return( psDBF->nFields-1 ); } /************************************************************************/ /* DBFIsValueNULL() */ /* */ /* Return TRUE if value is NULL (in DBF terms). */ /* */ /* Based on DBFIsAttributeNULL of shapelib */ /************************************************************************/ int DBFIsValueNULL( const char* pszValue, char type ) { switch(type) { case 'N': case 'F': /* NULL numeric fields have value "****************" */ return pszValue[0] == '*'; case 'D': /* NULL date fields have value "00000000" */ return strncmp(pszValue,"00000000",8) == 0; case 'L': /* NULL boolean fields have value "?" */ return pszValue[0] == '?'; default: /* empty string fields are considered NULL */ return strlen(pszValue) == 0; } } /************************************************************************/ /* msDBFReadAttribute() */ /* */ /* Read one of the attribute fields of a record. */ /************************************************************************/ static char *msDBFReadAttribute(DBFHandle psDBF, int hEntity, int iField ) { int i; unsigned int nRecordOffset; uchar *pabyRec; char *pReturnField = NULL; /* -------------------------------------------------------------------- */ /* Is the request valid? */ /* -------------------------------------------------------------------- */ if( iField < 0 || iField >= psDBF->nFields ) { msSetError(MS_DBFERR, "Invalid field index %d.", "msDBFReadAttribute()",iField ); return( NULL ); } if( hEntity < 0 || hEntity >= psDBF->nRecords ) { msSetError(MS_DBFERR, "Invalid record number %d.", "msDBFReadAttribute()",hEntity ); return( NULL ); } /* -------------------------------------------------------------------- */ /* Have we read the record? */ /* -------------------------------------------------------------------- */ if( psDBF->nCurrentRecord != hEntity ) { flushRecord( psDBF ); nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength; safe_fseek( psDBF->fp, nRecordOffset, 0 ); fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); psDBF->nCurrentRecord = hEntity; } pabyRec = (uchar *) psDBF->pszCurrentRecord; /* DEBUG */ /* printf("CurrentRecord(%c):%s\n", psDBF->pachFieldType[iField], pabyRec); */ /* -------------------------------------------------------------------- */ /* Ensure our field buffer is large enough to hold this buffer. */ /* -------------------------------------------------------------------- */ if( psDBF->panFieldSize[iField]+1 > psDBF->nStringFieldLen ) { psDBF->nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10; psDBF->pszStringField = (char *) SfRealloc(psDBF->pszStringField,psDBF->nStringFieldLen); } /* -------------------------------------------------------------------- */ /* Extract the requested field. */ /* -------------------------------------------------------------------- */ strncpy( psDBF->pszStringField,(char *) pabyRec+psDBF->panFieldOffset[iField], psDBF->panFieldSize[iField] ); psDBF->pszStringField[psDBF->panFieldSize[iField]] = '\0'; /* ** Trim trailing blanks (SDL Modification) */ for(i=strlen(psDBF->pszStringField)-1; i>=0; i--) { if(psDBF->pszStringField[i] != ' ') { psDBF->pszStringField[i+1] = '\0'; break; } } if(i == -1) psDBF->pszStringField[0] = '\0'; /* whole string is blank (SDL fix) */ /* ** Trim/skip leading blanks (SDL/DM Modification - only on numeric types) */ if( psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F' || psDBF->pachFieldType[iField] == 'D' ) { for(i=0; psDBF->pszStringField[i] != '\0' ; i++) { if(psDBF->pszStringField[i] != ' ') break; } pReturnField = psDBF->pszStringField+i; } else pReturnField = psDBF->pszStringField; /* detect null values */ if ( DBFIsValueNULL( pReturnField, psDBF->pachFieldType[iField] ) ) { if (psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F' || psDBF->pachFieldType[iField] == 'D') pReturnField="0"; } return( pReturnField ); } /************************************************************************/ /* msDBFReadIntAttribute() */ /* */ /* Read an integer attribute. */ /************************************************************************/ int msDBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField ) { return(atoi(msDBFReadAttribute( psDBF, iRecord, iField ))); } /************************************************************************/ /* msDBFReadDoubleAttribute() */ /* */ /* Read a double attribute. */ /************************************************************************/ double msDBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField ) { return(atof(msDBFReadAttribute( psDBF, iRecord, iField ))); } /************************************************************************/ /* msDBFReadStringAttribute() */ /* */ /* Read a string attribute. */ /************************************************************************/ const char *msDBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField ) { return( msDBFReadAttribute( psDBF, iRecord, iField ) ); } /************************************************************************/ /* msDBFGetFieldCount() */ /* */ /* Return the number of fields in this table. */ /************************************************************************/ int msDBFGetFieldCount( DBFHandle psDBF ) { return( psDBF->nFields ); } /************************************************************************/ /* msDBFGetRecordCount() */ /* */ /* Return the number of records in this table. */ /************************************************************************/ int msDBFGetRecordCount( DBFHandle psDBF ) { return( psDBF->nRecords ); } /************************************************************************/ /* msDBFGetFieldInfo() */ /* */ /* Return any requested information about the field. */ /************************************************************************/ DBFFieldType msDBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName, int * pnWidth, int * pnDecimals ) { if( iField < 0 || iField >= psDBF->nFields ) return( FTInvalid ); if( pnWidth != NULL ) *pnWidth = psDBF->panFieldSize[iField]; if( pnDecimals != NULL ) *pnDecimals = psDBF->panFieldDecimals[iField]; if( pszFieldName != NULL ) { int i; strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 ); pszFieldName[11] = '\0'; for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- ) pszFieldName[i] = '\0'; } if( psDBF->pachFieldType[iField] == 'N' || psDBF->pachFieldType[iField] == 'F' || psDBF->pachFieldType[iField] == 'D' ) { if( psDBF->panFieldDecimals[iField] > 0 ) return( FTDouble ); else return( FTInteger ); } else { return( FTString ); } } /************************************************************************/ /* msDBFWriteAttribute() */ /* */ /* Write an attribute record to the file. */ /************************************************************************/ static int msDBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, void * pValue ) { unsigned int nRecordOffset; int i, j; uchar *pabyRec; char szSField[40], szFormat[12]; /* -------------------------------------------------------------------- */ /* Is this a valid record? */ /* -------------------------------------------------------------------- */ if( hEntity < 0 || hEntity > psDBF->nRecords ) return( MS_FALSE ); if( psDBF->bNoHeader ) writeHeader(psDBF); /* -------------------------------------------------------------------- */ /* Is this a brand new record? */ /* -------------------------------------------------------------------- */ if( hEntity == psDBF->nRecords ) { flushRecord( psDBF ); psDBF->nRecords++; for( i = 0; i < psDBF->nRecordLength; i++ ) psDBF->pszCurrentRecord[i] = ' '; psDBF->nCurrentRecord = hEntity; } /* -------------------------------------------------------------------- */ /* Is this an existing record, but different than the last one */ /* we accessed? */ /* -------------------------------------------------------------------- */ if( psDBF->nCurrentRecord != hEntity ) { flushRecord( psDBF ); nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength; safe_fseek( psDBF->fp, nRecordOffset, 0 ); fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp ); psDBF->nCurrentRecord = hEntity; } pabyRec = (uchar *) psDBF->pszCurrentRecord; /* -------------------------------------------------------------------- */ /* Assign all the record fields. */ /* -------------------------------------------------------------------- */ switch( psDBF->pachFieldType[iField] ) { case 'D': case 'N': case 'F': if( psDBF->panFieldDecimals[iField] == 0 ) { snprintf( szFormat, sizeof(szFormat), "%%%dd", psDBF->panFieldSize[iField] ); snprintf(szSField, sizeof(szSField), szFormat, (int) *((double *) pValue) ); if( (int) strlen(szSField) > psDBF->panFieldSize[iField] ) szSField[psDBF->panFieldSize[iField]] = '\0'; strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), szSField, strlen(szSField) ); } else { snprintf( szFormat, sizeof(szFormat), "%%%d.%df", psDBF->panFieldSize[iField], psDBF->panFieldDecimals[iField] ); snprintf(szSField, sizeof(szSField), szFormat, *((double *) pValue) ); if( (int) strlen(szSField) > psDBF->panFieldSize[iField] ) szSField[psDBF->panFieldSize[iField]] = '\0'; strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), szSField, strlen(szSField) ); } break; default: if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] ) j = psDBF->panFieldSize[iField]; else j = strlen((char *) pValue); strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), (char *) pValue, j ); break; } psDBF->bCurrentRecordModified = MS_TRUE; psDBF->bUpdated = MS_TRUE; return( MS_TRUE ); } /************************************************************************/ /* msDBFWriteDoubleAttribute() */ /* */ /* Write a double attribute. */ /************************************************************************/ int msDBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField, double dValue ) { return( msDBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) ); } /************************************************************************/ /* msDBFWriteIntegerAttribute() */ /* */ /* Write a integer attribute. */ /************************************************************************/ int msDBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField, int nValue ) { double dValue = nValue; return( msDBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) ); } /************************************************************************/ /* msDBFWriteStringAttribute() */ /* */ /* Write a string attribute. */ /************************************************************************/ int msDBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField, const char * pszValue ) { return( msDBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) ); } /* ** Which column number in the .DBF file does the item correspond to */ int msDBFGetItemIndex(DBFHandle dbffile, char *name) { int i; int fWidth,fnDecimals; /* field width and number of decimals */ char fName[32]; /* field name */ if(!name) { msSetError(MS_MISCERR, "NULL item name passed.", "msGetItemIndex()"); return(-1); } /* does name exist as a field? */ for(i=0; i #include #include #ifndef _WIN32 #include #endif /* * Definitions */ #define MS_WCS_GML_COVERAGETYPE_RECTIFIED_GRID_COVERAGE "RectifiedGridCoverage" enum { MS_WCS_GET_CAPABILITIES, MS_WCS_DESCRIBE_COVERAGE, MS_WCS_GET_COVERAGE }; /* ** Structure to hold metadata taken from the image or image tile index */ typedef struct { const char *srs; char srs_urn[500]; rectObj extent, llextent; double geotransform[6]; int xsize, ysize; double xresolution, yresolution; int bandcount; int imagemode; const char *bandinterpretation[10]; } coverageMetadataObj; typedef struct { char *version; /* 1.0.0 for now */ char *updatesequence; /* string, int or timestampe */ char *request; /* GetCapabilities|DescribeCoverage|GetCoverage */ char *service; /* MUST be WCS */ char *section; /* of capabilities document: /WCS_Capabilities/Service|/WCS_Capabilities/Capability|/WCS_Capabilities/ContentMetadata */ char **coverages; /* NULL terminated list of coverages (in the case of a GetCoverage there will only be 1) */ char *crs; /* request coordinate reference system */ char *response_crs; /* response coordinate reference system */ rectObj bbox; /* subset bounding box (3D), although we'll only use 2D */ char *time; long width, height, depth; /* image dimensions */ double originx, originy; /* WCS 1.1 GridOrigin */ double resx, resy, resz; /* resolution */ char *interpolation; /* interpolationMethod */ char *format; char *exceptions; /* exception MIME type, (default application=vnd.ogc.se_xml) */ } wcsParamsObj; /* -------------------------------------------------------------------- */ /* Prototypes from mapwcs.c used in mapwcs11.c. */ /* */ /* Note, all prototypes are deliberately not exported from DLL */ /* since they are for internal use within the core. */ /* -------------------------------------------------------------------- */ void msWCSFreeParams(wcsParamsObj *params); int msWCSException(mapObj *map, const char *code, const char *locator, const char *version); int msWCSIsLayerSupported(layerObj *layer); int msWCSGetCoverageMetadata( layerObj *layer, coverageMetadataObj *cm ); void msWCSSetDefaultBandsRangeSetInfo( wcsParamsObj *params, coverageMetadataObj *cm, layerObj *lp ); const char *msWCSGetRequestParameter(cgiRequestObj *request, char *name); /* -------------------------------------------------------------------- */ /* Some WCS 1.1 specific functions from mapwcs11.c */ /* -------------------------------------------------------------------- */ int msWCSGetCapabilities11(mapObj *map, wcsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request); int msWCSDescribeCoverage11(mapObj *map, wcsParamsObj *params, owsRequestObj *ows_request); int msWCSReturnCoverage11( wcsParamsObj *params, mapObj *map, imageObj *image); int msWCSGetCoverageBands11( mapObj *map, cgiRequestObj *request, wcsParamsObj *params, layerObj *lp, char **p_bandlist ); int msWCSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version); /* -------------------------------------------------------------------- */ /* Some WCS 2.0 specific functions and structs from mapwcs20.c */ /* -------------------------------------------------------------------- */ enum { MS_WCS20_TRIM = 0, MS_WCS20_SLICE = 1 }; enum { MS_WCS20_ERROR_VALUE = -1, MS_WCS20_SCALAR_VALUE = 0, MS_WCS20_TIME_VALUE = 1, MS_WCS20_UNDEFINED_VALUE = 2 }; #define MS_WCS20_UNBOUNDED DBL_MAX #define MS_WCS20_UNBOUNDED_TIME 0xFFFFFFFF typedef struct { union { double scalar; time_t time; }; int unbounded; /* 0 if bounded, 1 if unbounded */ } timeScalarUnion; typedef struct { char *axis; /* the name of the subsetted axis */ int operation; /* Either TRIM or SLICE */ char *crs; /* optional CRS to use */ int timeOrScalar; /* 0 if scalar value, 1 if time value */ timeScalarUnion min; /* Minimum and Maximum of the subsetted axis;*/ timeScalarUnion max; } wcs20SubsetObj; typedef wcs20SubsetObj * wcs20SubsetObjPtr; typedef struct { char *name; /* name of the axis */ int size; /* pixelsize of the axis */ double resolution; /* resolution of the axis */ char *resolutionUOM; /* resolution units of measure */ wcs20SubsetObjPtr subset; } wcs20AxisObj; typedef wcs20AxisObj * wcs20AxisObjPtr; typedef struct { char *version; /* 2.0.0 v 2.0.1 */ char *request; /* GetCapabilities|DescribeCoverage|GetCoverage */ char *service; /* MUST be WCS */ char **accept_versions; /* NULL terminated list of Accepted versions */ char **sections; /* NULL terminated list of GetCapabilities sections */ char *updatesequence; /* GetCapabilities updatesequence */ char **ids; /* NULL terminated list of coverages (in the case of a GetCoverage there will only be 1) */ long width, height; /* image dimensions */ double resolutionX; /* image resolution in X axis */ double resolutionY; /* image resolution in Y axis */ char *resolutionUnits; /* Units of Measure for resolution */ char *format; /* requested output format */ int multipart; /* flag for multipart GML+image */ char *interpolation; /* requested interpolation method */ char *outputcrs; /* requested CRS for output */ char *subsetcrs; /* determined CRS of the subsets */ rectObj bbox; /* determined Bounding Box */ int numaxes; /* number of axes */ wcs20AxisObjPtr *axes; /* list of axes, NULL if none*/ char **range_subset; } wcs20ParamsObj; typedef wcs20ParamsObj * wcs20ParamsObjPtr; typedef struct { union { struct { char *name; char *interpretation; char *uom; char *definition; char *description; }; char *values[5]; }; double interval_min; double interval_max; int significant_figures; } wcs20rasterbandMetadataObj; typedef wcs20rasterbandMetadataObj * wcs20rasterbandMetadataObjPtr; typedef struct { char *native_format; /* mime type of the native format */ const char *srs; char srs_uri[200]; rectObj extent; double geotransform[6]; double xresolution; double yresolution; int xsize; int ysize; int imagemode; size_t numnilvalues; char **nilvalues; char **nilvalues_reasons; size_t numbands; wcs20rasterbandMetadataObjPtr bands; } wcs20coverageMetadataObj; typedef wcs20coverageMetadataObj * wcs20coverageMetadataObjPtr; #define MS_WCS_20_PROFILE_CORE "http://www.opengis.net/spec/WCS/2.0/conf/core" #define MS_WCS_20_PROFILE_KVP "http://www.opengis.net/spec/WCS_protocol-binding_get-kvp/1.0/conf/get-kvp" #define MS_WCS_20_PROFILE_POST "http://www.opengis.net/spec/WCS_protocol-binding_post-xml/1.0/conf/post-xml" #define MS_WCS_20_PROFILE_GML "http://www.opengis.net/spec/GMLCOV/1.0/conf/gml-coverage" #define MS_WCS_20_PROFILE_GML_MULTIPART "http://www.opengis.net/spec/GMLCOV/1.0/conf/multipart" #define MS_WCS_20_PROFILE_GML_SPECIAL "http://www.opengis.net/spec/GMLCOV/1.0/conf/special-format" #define MS_WCS_20_PROFILE_GML_GEOTIFF "http://www.opengis.net/spec/GMLCOV_geotiff-coverages/1.0/conf/geotiff-coverage" #define MS_WCS_20_PROFILE_GEOTIFF "http://www.opengis.net/spec/WCS_geotiff-coverages/1.0/conf/geotiff-coverage" #define MS_WCS_20_PROFILE_CRS "http://www.opengis.net/spec/WCS_service-model_crs-predefined/1.0/conf/crs-predefined" #define MS_WCS_20_PROFILE_SCALING "http://www.opengis.net/spec/WCS_service-model_scaling+interpolation/1.0/conf/scaling+interpolation" #define MS_WCS_20_PROFILE_RANGESUBSET "http://www.opengis.net/spec/WCS_service-model_band-subsetting/1.0/conf/band-subsetting" /* -------------------------------------------------------------------- */ /* WCS 2.0 function prototypes. */ /* -------------------------------------------------------------------- */ wcs20ParamsObjPtr msWCSCreateParamsObj20(); void msWCSFreeParamsObj20(wcs20ParamsObjPtr params); int msWCSParseRequest20(mapObj *map, cgiRequestObj *request, owsRequestObj *ows_request, wcs20ParamsObjPtr params); int msWCSException20(mapObj *map, const char *locator, const char *exceptionCode, const char *version); int msWCSGetCapabilities20(mapObj *map, cgiRequestObj *req, wcs20ParamsObjPtr params, owsRequestObj *ows_request); int msWCSDescribeCoverage20(mapObj *map, wcs20ParamsObjPtr params, owsRequestObj *ows_request); int msWCSGetCoverage20(mapObj *map, cgiRequestObj *request, wcs20ParamsObjPtr params, owsRequestObj *ows_request); /* -------------------------------------------------------------------- */ /* XML parsing helper macros. */ /* -------------------------------------------------------------------- */ #define XML_FOREACH_CHILD(parent_node, child_node) \ for(child_node = parent_node->children; child_node != NULL; child_node = child_node->next) /* Makro to continue the iteration over an xml structure */ /* when the current node has the type 'text' or 'comment' */ #define XML_LOOP_IGNORE_COMMENT_OR_TEXT(node) \ if(xmlNodeIsText(node) || node->type == XML_COMMENT_NODE) \ { \ continue; \ } /* Makro to set an XML error that an unknown node type */ /* occurred. */ #define XML_UNKNOWN_NODE_ERROR(node) \ msSetError(MS_WCSERR, "Unknown XML element '%s'.", \ __FUNCTION__, (char *)node->name); \ return MS_FAILURE; #define XML_ASSERT_NODE_NAME(node,nodename) \ if(EQUAL((char *)node->name, nodename) == MS_FALSE) \ { \ XML_UNKNOWN_NODE_ERROR(node); \ } #define MS_WCS_20_CAPABILITIES_INCLUDE_SECTION(params,section) \ (params->sections == NULL \ || CSLFindString(params->sections, "All") != -1 \ || CSLFindString(params->sections, section) != -1) #endif /* nef MAPWCS_H */ mapserver-6.4.1/shptreetst.c0000644002461700001440000001225412261257215015671 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Utility program to visualize a quadtree search * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include #ifndef _WIN32 #include #endif #include #ifdef SHPT_POLYGON #undef MAPSERVER #else #define MAPSERVER 1 #define SHPT_POLYGON MS_SHP_POLYGON #endif char* AddFileSuffix ( const char * Filename, const char * Suffix ) { char *pszFullname, *pszBasename; int i; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(Filename)+5); strcpy( pszBasename, Filename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, Suffix); return (pszFullname); } int main( int argc, char ** argv ) { SHPTreeHandle qix; int i,j; rectObj rect; int pos; ms_bitarray bitmap = NULL; /* char mBigEndian; */ treeNodeObj *node = NULL; /* -------------------------------------------------------------------- */ /* Display a usage message. */ /* -------------------------------------------------------------------- */ if( argc <= 1 ) { printf( "shptreetst shapefile {minx miny maxx maxy}\n" ); exit( 1 ); } /* i = 1; if( *((unsigned char *) &i) == 1 ) mBigEndian = 0; else mBigEndian = 1; */ qix = msSHPDiskTreeOpen (AddFileSuffix(argv[1],".qix"), 0 /* no debug*/); if( qix == NULL ) { printf("unable to open index file %s \n", argv[1]); exit(-1); } printf ("This %s %s index supports a shapefile with %d shapes, %d depth \n", (qix->version ? "new": "old"), (qix->LSB_order? "LSB": "MSB"), (int) qix->nShapes, (int) qix->nDepth); /* -------------------------------------------------------------------- */ /* Skim over the list of shapes, printing all the vertices. */ /* -------------------------------------------------------------------- */ pos = ftell (qix->fp); j = 0; while( pos && j < 20) { j ++; /* fprintf (stderr,"box %d, at %d pos \n", j, (int) ftell(qix)); */ node = readTreeNode (qix); if (node ) { fprintf (stdout,"shapes %d, node %d, %f,%f,%f,%f \n",(int) node->numshapes,node->numsubnodes,node->rect.minx, node->rect.miny, node->rect.maxx, node->rect.maxy); } else { pos = 0; } } printf ("read entire file now at quad box rec %d file pos %ld\n", j, ftell (qix->fp)); j = qix->nShapes; msSHPDiskTreeClose (qix); if( argc >= 5 ) { rect.minx = atof (argv[2]); rect.miny = atof (argv[3]); rect.maxx = atof (argv[4]); rect.maxy = atof (argv[5]); } else { printf ("using last read box as a search \n"); rect.minx = node->rect.minx; rect.miny = node->rect.miny; rect.maxx = node->rect.maxx; rect.maxy = node->rect.maxy; } bitmap = msSearchDiskTree( argv[1], rect, 0 /* no debug*/ ); if ( bitmap ) { printf ("result of rectangle search was \n"); for ( i=0; i * * 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. **********************************************************************/ #include #include "mapserver.h" #include "mapproject.h" #include "mapthread.h" #if defined(USE_OGR) # define __USE_LARGEFILE64 1 # include "ogr_api.h" # include "ogr_srs_api.h" # include "cpl_conv.h" # include "cpl_vsi.h" # include "cpl_string.h" #endif #ifdef USE_OGR /************************************************************************/ /* msInitDefaultOGROutputFormat() */ /************************************************************************/ int msInitDefaultOGROutputFormat( outputFormatObj *format ) { OGRSFDriverH hDriver; msOGRInitialize(); /* -------------------------------------------------------------------- */ /* check that this driver exists. Note visiting drivers should */ /* be pretty threadsafe so don't bother acquiring the GDAL */ /* lock. */ /* -------------------------------------------------------------------- */ hDriver = OGRGetDriverByName( format->driver+4 ); if( hDriver == NULL ) { msSetError( MS_MISCERR, "No OGR driver named `%s' available.", "msInitDefaultOGROutputFormat()", format->driver+4 ); return MS_FAILURE; } if( !OGR_Dr_TestCapability( hDriver, ODrCCreateDataSource ) ) { msSetError( MS_MISCERR, "OGR `%s' driver does not support output.", "msInitDefaultOGROutputFormat()", format->driver+4 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Initialize the object. */ /* -------------------------------------------------------------------- */ format->imagemode = MS_IMAGEMODE_FEATURE; format->renderer = MS_RENDER_WITH_OGR; /* perhaps we should eventually hardcode mimetypes and extensions for some formats? */ return MS_SUCCESS; } /************************************************************************/ /* msOGRRecursiveFileList() */ /* */ /* Collect a list of all files under the named directory, */ /* including those in subdirectories. */ /************************************************************************/ char **msOGRRecursiveFileList( const char *path ) { char **file_list; char **result_list = NULL; int i, count, change; file_list = CPLReadDir( path ); count = CSLCount(file_list); /* -------------------------------------------------------------------- */ /* Sort the file list so we always get them back in the same */ /* order - it makes autotests more stable. */ /* -------------------------------------------------------------------- */ do { change = 0; for( i = 0; i < count-1; i++ ) { if( strcasecmp(file_list[i],file_list[i+1]) > 0 ) { char *temp = file_list[i]; file_list[i] = file_list[i+1]; file_list[i+1] = temp; change = 1; } } } while( change ); /* -------------------------------------------------------------------- */ /* collect names we want and process subdirectories. */ /* -------------------------------------------------------------------- */ for( i = 0; i < count; i++ ) { char full_filename[MS_MAXPATHLEN]; VSIStatBufL sStatBuf; if( EQUAL(file_list[i],".") || EQUAL(file_list[i],"..") ) continue; strlcpy( full_filename, CPLFormFilename( path, file_list[i], NULL ), sizeof(full_filename) ); VSIStatL( full_filename, &sStatBuf ); if( VSI_ISREG( sStatBuf.st_mode ) ) { result_list = CSLAddString( result_list, full_filename ); } else if( VSI_ISDIR( sStatBuf.st_mode ) ) { char **subfiles = msOGRRecursiveFileList( full_filename ); result_list = CSLMerge( result_list, subfiles ); CSLDestroy( subfiles ); } } CSLDestroy( file_list ); return result_list; } /************************************************************************/ /* msOGRCleanupDS() */ /************************************************************************/ static void msOGRCleanupDS( const char *datasource_name ) { char **file_list; char path[MS_MAXPATHLEN]; int i; strlcpy( path, CPLGetPath( datasource_name ), sizeof(path) ); file_list = CPLReadDir( path ); for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) { char full_filename[MS_MAXPATHLEN]; VSIStatBufL sStatBuf; if( EQUAL(file_list[i],".") || EQUAL(file_list[i],"..") ) continue; strlcpy( full_filename, CPLFormFilename( path, file_list[i], NULL ), sizeof(full_filename) ); VSIStatL( full_filename, &sStatBuf ); if( VSI_ISREG( sStatBuf.st_mode ) ) { VSIUnlink( full_filename ); } else if( VSI_ISDIR( sStatBuf.st_mode ) ) { char fake_ds_name[MS_MAXPATHLEN]; strlcpy( fake_ds_name, CPLFormFilename( full_filename, "abc.dat", NULL ), sizeof(fake_ds_name) ); msOGRCleanupDS( fake_ds_name ); } } CSLDestroy( file_list ); VSIRmdir( path ); } /************************************************************************/ /* msOGRSetPoints() */ /************************************************************************/ static void msOGRSetPoints( OGRGeometryH hGeom, lineObj *line, int bWant2DOutput) { int i; if( bWant2DOutput ) { for( i = 0; i < line->numpoints; i++ ) { OGR_G_SetPoint_2D( hGeom, i, line->point[i].x, line->point[i].y ); } } else { for( i = 0; i < line->numpoints; i++ ) { OGR_G_SetPoint( hGeom, i, line->point[i].x, line->point[i].y, #ifdef USE_POINT_Z_M line->point[i].z #else 0.0 #endif ); } } } /************************************************************************/ /* msOGRWriteShape() */ /************************************************************************/ static int msOGRWriteShape( layerObj *map_layer, OGRLayerH hOGRLayer, shapeObj *shape, gmlItemListObj *item_list ) { OGRGeometryH hGeom = NULL; OGRFeatureH hFeat; OGRErr eErr; int i, out_field; OGRwkbGeometryType eLayerGType, eFlattenLayerGType; OGRFeatureDefnH hLayerDefn; int bWant2DOutput; hLayerDefn = OGR_L_GetLayerDefn( hOGRLayer ); eLayerGType = OGR_FD_GetGeomType(hLayerDefn); eFlattenLayerGType = wkbFlatten(eLayerGType); bWant2DOutput = (eLayerGType == eFlattenLayerGType); /* -------------------------------------------------------------------- */ /* Transform point geometry. */ /* -------------------------------------------------------------------- */ if( shape->type == MS_SHAPE_POINT ) { OGRGeometryH hMP = NULL; int j; if( shape->numlines < 1 ) { msSetError(MS_MISCERR, "Failed on odd point geometry.", "msOGRWriteShape()"); return MS_FAILURE; } if( shape->numlines > 1 ) hMP = OGR_G_CreateGeometry( wkbMultiPoint ); for( j = 0; j < shape->numlines; j++ ) { if( shape->line[j].numpoints != 1 ) { msSetError(MS_MISCERR, "Failed on odd point geometry.", "msOGRWriteShape()"); return MS_FAILURE; } hGeom = OGR_G_CreateGeometry( wkbPoint ); if( bWant2DOutput ) { OGR_G_SetPoint_2D( hGeom, 0, shape->line[j].point[0].x, shape->line[j].point[0].y ); } else { OGR_G_SetPoint( hGeom, 0, shape->line[j].point[0].x, shape->line[j].point[0].y, #ifdef USE_POINT_Z_M shape->line[j].point[0].z #else 0.0 #endif ); } if( hMP != NULL ) { OGR_G_AddGeometryDirectly( hMP, hGeom ); hGeom = hMP; } } } /* -------------------------------------------------------------------- */ /* Transform line geometry. */ /* -------------------------------------------------------------------- */ else if( shape->type == MS_SHAPE_LINE ) { OGRGeometryH hML = NULL; int j; if( shape->numlines < 1 || shape->line[0].numpoints < 2 ) { msSetError(MS_MISCERR, "Failed on odd line geometry.", "msOGRWriteShape()"); return MS_FAILURE; } if( shape->numlines > 1 ) hML = OGR_G_CreateGeometry( wkbMultiLineString ); for( j = 0; j < shape->numlines; j++ ) { hGeom = OGR_G_CreateGeometry( wkbLineString ); msOGRSetPoints( hGeom, &(shape->line[j]), bWant2DOutput); if( hML != NULL ) { OGR_G_AddGeometryDirectly( hML, hGeom ); hGeom = hML; } } } /* -------------------------------------------------------------------- */ /* Transform polygon geometry. */ /* -------------------------------------------------------------------- */ else if( shape->type == MS_SHAPE_POLYGON ) { int iRing, iOuter; int *outer_flags; OGRGeometryH hMP; if( shape->numlines < 1 ) { msSetError(MS_MISCERR, "Failed on odd polygon geometry.", "msOGRWriteShape()"); return MS_FAILURE; } outer_flags = msGetOuterList( shape ); hMP = OGR_G_CreateGeometry( wkbMultiPolygon ); for( iOuter = 0; iOuter < shape->numlines; iOuter++ ) { int *inner_flags; OGRGeometryH hRing; if( !outer_flags[iOuter] ) continue; hGeom = OGR_G_CreateGeometry( wkbPolygon ); /* handle outer ring */ hRing = OGR_G_CreateGeometry( wkbLinearRing ); msOGRSetPoints( hRing, &(shape->line[iOuter]), bWant2DOutput); OGR_G_AddGeometryDirectly( hGeom, hRing ); /* handle inner rings (holes) */ inner_flags = msGetInnerList( shape, iOuter, outer_flags ); for( iRing = 0; iRing < shape->numlines; iRing++ ) { if( !inner_flags[iRing] ) continue; hRing = OGR_G_CreateGeometry( wkbLinearRing ); msOGRSetPoints( hRing, &(shape->line[iRing]), bWant2DOutput); OGR_G_AddGeometryDirectly( hGeom, hRing ); } free(inner_flags); OGR_G_AddGeometryDirectly( hMP, hGeom ); } free(outer_flags); if( OGR_G_GetGeometryCount( hMP ) == 1 ) { hGeom = OGR_G_Clone( OGR_G_GetGeometryRef( hMP, 0 ) ); OGR_G_DestroyGeometry( hMP ); } else { hGeom = hMP; } } /* -------------------------------------------------------------------- */ /* Consider trying to force the geometry to a new type if it */ /* doesn't match the layer. */ /* -------------------------------------------------------------------- */ #if defined(GDAL_VERSION_NUM) && (GDAL_VERSION_NUM >= 1800) if( hGeom != NULL ) { OGRwkbGeometryType eFlattenFeatureGType = wkbFlatten(OGR_G_GetGeometryType( hGeom )); if( eFlattenFeatureGType != eFlattenLayerGType ) { if( eFlattenLayerGType == wkbPolygon ) hGeom = OGR_G_ForceToPolygon( hGeom ); else if( eFlattenLayerGType == wkbMultiPolygon ) hGeom = OGR_G_ForceToMultiPolygon( hGeom ); else if( eFlattenLayerGType == wkbMultiPoint ) hGeom = OGR_G_ForceToMultiPoint( hGeom ); else if( eFlattenLayerGType == wkbMultiLineString ) hGeom = OGR_G_ForceToMultiLineString( hGeom ); } } #endif /* GDAL/OGR 1.8 or later */ /* -------------------------------------------------------------------- */ /* Consider flattening the geometry to 2D if we want 2D */ /* output. */ /* Note: this shouldn't be called in recent OGR versions where */ /* OGR_G_SetPoint_2D is properly honoured. */ /* -------------------------------------------------------------------- */ if( bWant2DOutput && hGeom != NULL ) { OGRwkbGeometryType eFeatureGType = OGR_G_GetGeometryType( hGeom ); if( eFeatureGType != wkbFlatten(eFeatureGType) ) OGR_G_FlattenTo2D( hGeom ); } /* -------------------------------------------------------------------- */ /* Create the feature, and attach the geometry. */ /* -------------------------------------------------------------------- */ hFeat = OGR_F_Create( hLayerDefn ); OGR_F_SetGeometryDirectly( hFeat, hGeom ); /* -------------------------------------------------------------------- */ /* Set attributes. */ /* -------------------------------------------------------------------- */ out_field = 0; for( i = 0; i < item_list->numitems; i++ ) { gmlItemObj *item = item_list->items + i; if( !item->visible ) continue; /* Avoid setting empty strings for numeric fields, so that OGR */ /* doesn't take them as 0. (#4633) */ if( shape->values[i][0] == '\0' ) { OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn(hLayerDefn, out_field); OGRFieldType eFieldType = OGR_Fld_GetType(hFieldDefn); if( eFieldType == OFTInteger || eFieldType == OFTReal ) { out_field++; continue; } } OGR_F_SetFieldString( hFeat, out_field++, shape->values[i] ); } /* -------------------------------------------------------------------- */ /* Write out and cleanup. */ /* -------------------------------------------------------------------- */ eErr = OGR_L_CreateFeature( hOGRLayer, hFeat ); OGR_F_Destroy( hFeat ); if( eErr != OGRERR_NONE ) { msSetError( MS_OGRERR, "Attempt to write feature failed (code=%d):\n%s", "msOGRWriteShape()", (int) eErr, CPLGetLastErrorMsg() ); } if( eErr == OGRERR_NONE ) return MS_SUCCESS; else return MS_FAILURE; } #endif /* def USE_OGR */ /************************************************************************/ /* msOGRWriteFromQuery() */ /************************************************************************/ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders ) { #ifndef USE_OGR msSetError(MS_OGRERR, "OGR support is not available.", "msOGRWriteFromQuery()"); return MS_FAILURE; #else /* -------------------------------------------------------------------- */ /* Variable declarations. */ /* -------------------------------------------------------------------- */ OGRSFDriverH hDriver; OGRDataSourceH hDS; const char *storage; const char *fo_filename; const char *form; char datasource_name[MS_MAXPATHLEN]; char base_dir[MS_MAXPATHLEN]; char *request_dir = NULL; char **ds_options = NULL; char **layer_options = NULL; char **file_list = NULL; int iLayer, i; /* -------------------------------------------------------------------- */ /* Fetch the output format driver. */ /* -------------------------------------------------------------------- */ msOGRInitialize(); hDriver = OGRGetDriverByName( format->driver+4 ); if( hDriver == NULL ) { msSetError( MS_MISCERR, "No OGR driver named `%s' available.", "msOGRWriteFromQuery()", format->driver+4 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Capture datasource and layer creation options. */ /* -------------------------------------------------------------------- */ for( i=0; i < format->numformatoptions; i++ ) { if( strncasecmp(format->formatoptions[i],"LCO:",4) == 0 ) layer_options = CSLAddString( layer_options, format->formatoptions[i] + 4 ); if( strncasecmp(format->formatoptions[i],"DSCO:",5) == 0 ) ds_options = CSLAddString( ds_options, format->formatoptions[i] + 5 ); } /* ==================================================================== */ /* Determine the output datasource name to use. */ /* ==================================================================== */ storage = msGetOutputFormatOption( format, "STORAGE", "filesystem" ); /* -------------------------------------------------------------------- */ /* Where are we putting stuff? */ /* -------------------------------------------------------------------- */ if( EQUAL(storage,"filesystem") ) { base_dir[0] = '\0' ; } else if( EQUAL(storage,"memory") ) { strcpy( base_dir, "/vsimem/ogr_out/" ); } else if( EQUAL(storage,"stream") ) { /* handled later */ } else { msSetError( MS_MISCERR, "STORAGE=%s value not supported.", "msOGRWriteFromQuery()", storage ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Create a subdirectory to handle this request. */ /* -------------------------------------------------------------------- */ if( !EQUAL(storage,"stream") ) { if (strlen(base_dir) > 0) request_dir = msTmpFile(map, NULL, base_dir, "" ); else request_dir = msTmpFile(map, NULL, NULL, "" ); if( request_dir[strlen(request_dir)-1] == '.' ) request_dir[strlen(request_dir)-1] = '\0'; if( VSIMkdir( request_dir, 0777 ) != 0 ) { msSetError( MS_MISCERR, "Attempt to create directory '%s' failed.", "msOGRWriteFromQuery()", request_dir ); return MS_FAILURE; } } else /* handled later */; /* -------------------------------------------------------------------- */ /* Setup the full datasource name. */ /* -------------------------------------------------------------------- */ fo_filename = msGetOutputFormatOption( format, "FILENAME", "result.dat" ); /* Validate that the filename does not contain any directory */ /* information, which might lead to removal of unwanted files. (#4086) */ if( strchr(fo_filename, '/') != NULL || strchr(fo_filename, ':') != NULL || strchr(fo_filename, '\\') != NULL ) { msSetError( MS_MISCERR, "Invalid value for FILENAME option. " "It must not contain any directory information.", "msOGRWriteFromQuery()" ); return MS_FAILURE; } if( !EQUAL(storage,"stream") ) msBuildPath( datasource_name, request_dir, fo_filename ); else strcpy( datasource_name, "/vsistdout/" ); msFree( request_dir ); request_dir = NULL; /* -------------------------------------------------------------------- */ /* Emit content type headers for stream output now. */ /* -------------------------------------------------------------------- */ if( EQUAL(storage,"stream") ) { if( sendheaders && format->mimetype ) { msIO_setHeader("Content-Type","%s",format->mimetype); msIO_sendHeaders(); } else msIO_fprintf( stdout, "%c", 10 ); } /* ==================================================================== */ /* Create the datasource. */ /* ==================================================================== */ hDS = OGR_Dr_CreateDataSource( hDriver, datasource_name, ds_options ); CSLDestroy( ds_options ); if( hDS == NULL ) { msOGRCleanupDS( datasource_name ); msSetError( MS_MISCERR, "OGR CreateDataSource failed for '%s' with driver '%s'.", "msOGRWriteFromQuery()", datasource_name, format->driver+4 ); return MS_FAILURE; } /* ==================================================================== */ /* Process each layer with a resultset. */ /* ==================================================================== */ for( iLayer = 0; iLayer < map->numlayers; iLayer++ ) { int status; layerObj *layer = GET_LAYER(map, iLayer); shapeObj resultshape; OGRLayerH hOGRLayer; OGRwkbGeometryType eGeomType; OGRSpatialReferenceH srs = NULL; gmlItemListObj *item_list = NULL; const char *value; char *pszWKT; int reproject = MS_FALSE; if( !layer->resultcache || layer->resultcache->numresults == 0 ) continue; /* -------------------------------------------------------------------- */ /* Will we need to reproject? */ /* -------------------------------------------------------------------- */ if(layer->transform == MS_TRUE && layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection)) ) reproject = MS_TRUE; /* -------------------------------------------------------------------- */ /* Establish the geometry type to use for the created layer. */ /* First we consult the wfs_geomtype field and fallback to */ /* deriving something from the type of the mapserver layer. */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata(&(layer->metadata), "FOG", "geomtype"); if( value == NULL ) { if( layer->type == MS_LAYER_POINT ) value = "Point"; else if( layer->type == MS_LAYER_LINE ) value = "LineString"; else if( layer->type == MS_LAYER_POLYGON ) value = "Polygon"; else value = "Geometry"; } if( strcasecmp(value,"Point") == 0 ) eGeomType = wkbPoint; else if( strcasecmp(value,"LineString") == 0 ) eGeomType = wkbLineString; else if( strcasecmp(value,"Polygon") == 0 ) eGeomType = wkbPolygon; else if( strcasecmp(value,"MultiPoint") == 0 ) eGeomType = wkbMultiPoint; else if( strcasecmp(value,"MultiLineString") == 0 ) eGeomType = wkbMultiLineString; else if( strcasecmp(value,"MultiPolygon") == 0 ) eGeomType = wkbMultiPolygon; else if( strcasecmp(value,"GeometryCollection") == 0 ) eGeomType = wkbGeometryCollection; else if( strcasecmp(value,"Point25D") == 0 ) eGeomType = wkbPoint25D; else if( strcasecmp(value,"LineString25D") == 0 ) eGeomType = wkbLineString25D; else if( strcasecmp(value,"Polygon25D") == 0 ) eGeomType = wkbPolygon25D; else if( strcasecmp(value,"MultiPoint25D") == 0 ) eGeomType = wkbMultiPoint25D; else if( strcasecmp(value,"MultiLineString25D") == 0 ) eGeomType = wkbMultiLineString25D; else if( strcasecmp(value,"MultiPolygon25D") == 0 ) eGeomType = wkbMultiPolygon25D; else if( strcasecmp(value,"GeometryCollection25D") == 0 ) eGeomType = wkbGeometryCollection25D; else if( strcasecmp(value,"Unknown") == 0 || strcasecmp(value,"Geometry") == 0 ) eGeomType = wkbUnknown; else if( strcasecmp(value,"None") == 0 ) eGeomType = wkbNone; else eGeomType = wkbUnknown; /* -------------------------------------------------------------------- */ /* Create a spatial reference. */ /* -------------------------------------------------------------------- */ pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { srs = OSRNewSpatialReference( pszWKT ); msFree( pszWKT ); } /* -------------------------------------------------------------------- */ /* Create the corresponding OGR Layer. */ /* -------------------------------------------------------------------- */ hOGRLayer = OGR_DS_CreateLayer( hDS, layer->name, srs, eGeomType, layer_options ); if( hOGRLayer == NULL ) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); msSetError( MS_MISCERR, "OGR CreateDataSource failed for '%s' with driver '%s'.", "msOGRWriteFromQuery()", datasource_name, format->driver+4 ); return MS_FAILURE; } if( srs != NULL ) OSRDestroySpatialReference( srs ); /* -------------------------------------------------------------------- */ /* Create appropriate attributes on this layer. */ /* -------------------------------------------------------------------- */ item_list = msGMLGetItems( layer, "G" ); assert( item_list->numitems == layer->numitems ); for( i = 0; i < layer->numitems; i++ ) { OGRFieldDefnH hFldDefn; OGRErr eErr; const char *name; gmlItemObj *item = item_list->items + i; OGRFieldType eType; if( !item->visible ) continue; if( item->alias ) name = item->alias; else name = item->name; if( item->type == NULL ) eType = OFTString; else if( EQUAL(item->type,"Integer") ) eType = OFTInteger; else if( EQUAL(item->type,"Real") ) eType = OFTReal; else if( EQUAL(item->type,"Character") ) eType = OFTString; else if( EQUAL(item->type,"Date") ) eType = OFTDateTime; else if( EQUAL(item->type,"Boolean") ) eType = OFTInteger; else eType = OFTString; hFldDefn = OGR_Fld_Create( name, eType ); if( item->width != 0 ) OGR_Fld_SetWidth( hFldDefn, item->width ); if( item->precision != 0 ) OGR_Fld_SetPrecision( hFldDefn, item->precision ); eErr = OGR_L_CreateField( hOGRLayer, hFldDefn, TRUE ); OGR_Fld_Destroy( hFldDefn ); if( eErr != OGRERR_NONE ) { msSetError( MS_OGRERR, "Failed to create field '%s' in output feature schema:\n%s", "msOGRWriteFromQuery()", layer->items[i], CPLGetLastErrorMsg() ); OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } } /* -------------------------------------------------------------------- */ /* Setup joins if needed. This is likely untested. */ /* -------------------------------------------------------------------- */ if(layer->numjoins > 0) { int j; for(j=0; jnumjoins; j++) { status = msJoinConnect(layer, &(layer->joins[j])); if(status != MS_SUCCESS) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); return status; } } } msInitShape( &resultshape ); /* -------------------------------------------------------------------- */ /* Loop over all the shapes in the resultcache. */ /* -------------------------------------------------------------------- */ for(i=0; i < layer->resultcache->numresults; i++) { msFreeShape(&resultshape); /* init too */ /* ** Read the shape. */ status = msLayerGetShape(layer, &resultshape, &(layer->resultcache->results[i])); if(status != MS_SUCCESS) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); return status; } /* ** Perform classification, and some annotation related magic. */ resultshape.classindex = msShapeGetClass(layer, map, &resultshape, NULL, -1); if( resultshape.classindex >= 0 && (layer->class[resultshape.classindex]->text.string || layer->labelitem) && layer->class[resultshape.classindex]->numlabels > 0 && layer->class[resultshape.classindex]->labels[0]->size != -1 ) { msShapeGetAnnotation(layer, &resultshape); /* TODO RFC77: check return value */ resultshape.text = msStrdup(layer->class[resultshape.classindex]->labels[0]->annotext); } /* ** prepare any necessary JOINs here (one-to-one only) */ if( layer->numjoins > 0) { int j; for(j=0; j < layer->numjoins; j++) { if(layer->joins[j].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(layer->joins[j]), &resultshape); msJoinNext(&(layer->joins[j])); /* fetch the first row */ } } } if( reproject ) { status = msProjectShape(&layer->projection, &layer->map->projection, &resultshape); } /* ** Write out the feature to OGR. */ if( status == MS_SUCCESS ) status = msOGRWriteShape( layer, hOGRLayer, &resultshape, item_list ); if(status != MS_SUCCESS) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); return status; } } msGMLFreeItems(item_list); msFreeShape(&resultshape); /* init too */ } /* -------------------------------------------------------------------- */ /* Close the datasource. */ /* -------------------------------------------------------------------- */ OGR_DS_Destroy( hDS ); /* -------------------------------------------------------------------- */ /* Get list of resulting files. */ /* -------------------------------------------------------------------- */ #if !defined(CPL_ZIP_API_OFFERED) form = msGetOutputFormatOption( format, "FORM", "multipart" ); #else form = msGetOutputFormatOption( format, "FORM", "zip" ); #endif if( EQUAL(form,"simple") ) { file_list = CSLAddString( NULL, datasource_name ); } else { char datasource_path[MS_MAXPATHLEN]; strcpy( datasource_path, CPLGetPath( datasource_name ) ); file_list = msOGRRecursiveFileList( datasource_path ); } /* -------------------------------------------------------------------- */ /* If our "storage" is stream then the output has already been */ /* sent back to the client and we don't need to copy it now. */ /* -------------------------------------------------------------------- */ if( EQUAL(storage,"stream") ) { /* already done */ } /* -------------------------------------------------------------------- */ /* Handle case of simple file written to stdout. */ /* -------------------------------------------------------------------- */ else if( EQUAL(form,"simple") ) { char buffer[1024]; int bytes_read; FILE *fp; if( sendheaders ) { msIO_setHeader("Content-Disposition","attachment; filename=%s", CPLGetFilename( file_list[0] ) ); if( format->mimetype ) msIO_setHeader("Content-Type","%s",format->mimetype); msIO_sendHeaders(); } else msIO_fprintf( stdout, "%c", 10 ); fp = VSIFOpenL( file_list[0], "r" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open result file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) msIO_fwrite( buffer, 1, bytes_read, stdout ); VSIFCloseL( fp ); } /* -------------------------------------------------------------------- */ /* Handle the case of a multi-part result. */ /* -------------------------------------------------------------------- */ else if( EQUAL(form,"multipart") ) { static const char *boundary = "xxOGRBoundaryxx"; msIO_setHeader("Content-Type","multipart/mixed; boundary=%s",boundary); msIO_sendHeaders(); msIO_fprintf(stdout,"--%s\r\n",boundary ); for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) { FILE *fp; int bytes_read; char buffer[1024]; if( sendheaders ) msIO_fprintf( stdout, "Content-Disposition: attachment; filename=%s\r\n" "Content-Type: application/binary\r\n" "Content-Transfer-Encoding: binary\r\n\r\n", CPLGetFilename( file_list[i] )); fp = VSIFOpenL( file_list[i], "r" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open result file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) msIO_fwrite( buffer, 1, bytes_read, stdout ); VSIFCloseL( fp ); if (file_list[i+1] == NULL) msIO_fprintf( stdout, "\r\n--%s--\r\n", boundary ); else msIO_fprintf( stdout, "\r\n--%s\r\n", boundary ); } } /* -------------------------------------------------------------------- */ /* Handle the case of a zip file result. */ /* -------------------------------------------------------------------- */ else if( EQUAL(form,"zip") ) { #if !defined(CPL_ZIP_API_OFFERED) msSetError( MS_MISCERR, "FORM=zip selected, but CPL ZIP support unavailable, perhaps you need to upgrade to GDAL/OGR 1.8?", "msOGRWriteFromQuery()"); msOGRCleanupDS( datasource_name ); return MS_FAILURE; #else FILE *fp; char *zip_filename = msTmpFile(map, NULL, "/vsimem/ogrzip/", "zip" ); void *hZip; int bytes_read; char buffer[1024]; hZip = CPLCreateZip( zip_filename, NULL ); for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) { CPLCreateFileInZip( hZip, CPLGetFilename(file_list[i]), NULL ); fp = VSIFOpenL( file_list[i], "r" ); if( fp == NULL ) { CPLCloseZip( hZip ); msSetError( MS_MISCERR, "Failed to open result file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) { CPLWriteFileInZip( hZip, buffer, bytes_read ); } VSIFCloseL( fp ); CPLCloseFileInZip( hZip ); } CPLCloseZip( hZip ); if( sendheaders ) { msIO_setHeader("Content-Disposition","attachment; filename=%s",fo_filename); msIO_setHeader("Content-Type","application/zip"); msIO_sendHeaders(); } fp = VSIFOpenL( zip_filename, "r" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open zip file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) msIO_fwrite( buffer, 1, bytes_read, stdout ); VSIFCloseL( fp ); msFree( zip_filename ); #endif /* defined(CPL_ZIP_API_OFFERED) */ } /* -------------------------------------------------------------------- */ /* Handle illegal form value. */ /* -------------------------------------------------------------------- */ else { msSetError( MS_MISCERR, "Unsupported FORM=%s value.", "msOGRWriteFromQuery()", form ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } msOGRCleanupDS( datasource_name ); CSLDestroy( layer_options ); CSLDestroy( file_list ); return MS_SUCCESS; #endif /* def USE_OGR */ } /************************************************************************/ /* msPopulateRenderVTableOGR() */ /************************************************************************/ int msPopulateRendererVTableOGR( rendererVTableObj *renderer ) { #ifdef USE_OGR /* we aren't really a normal renderer so we leave everything default */ return MS_SUCCESS; #else msSetError(MS_OGRERR, "OGR Driver requested but is not built in", "msPopulateRendererVTableOGR()"); return MS_FAILURE; #endif } mapserver-6.4.1/release-notes.sh0000755002461700001440000000051512261257215016422 0ustar tbonfortusers#!/bin/bash commitdiff=$1 if test -z $commitdiff; then echo "usage: $0 startcommit..endcommit" exit fi git --no-pager log --no-merges --pretty=format:'%s (%an) : `%h `__' $commitdiff | gsed 's!#\([0-9]\+\)! `#\1 `__ !g' mapserver-6.4.1/mapfile.c0000644002461700001440000073370412261257215015113 0ustar tbonfortusers/****************************************************************************** * $id: mapfile.c 7854 2008-08-14 19:22:48Z dmorissette $ * * Project: MapServer * Purpose: High level Map file parsing code. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #define _GNU_SOURCE #include #include #include #include #include "mapserver.h" #include "mapfile.h" #include "mapthread.h" #include "maptime.h" #ifdef USE_GDAL # include "cpl_conv.h" # include "gdal.h" #endif extern int msyylex(void); extern void msyyrestart(FILE *); extern int msyylex_destroy(void); extern double msyynumber; extern int msyylineno; extern FILE *msyyin; extern int msyysource; extern int msyystate; extern char *msyystring; extern char *msyybasepath; extern int msyyreturncomments; extern char *msyystring_buffer; extern char msyystring_icase; extern int loadSymbol(symbolObj *s, char *symbolpath); /* in mapsymbol.c */ extern void writeSymbol(symbolObj *s, FILE *stream); /* in mapsymbol.c */ static int loadGrid( layerObj *pLayer ); static int loadStyle(styleObj *style); static void writeStyle(FILE* stream, int indent, styleObj *style); static int resolveSymbolNames(mapObj *map); static int loadExpression(expressionObj *exp); static void writeExpression(FILE *stream, int indent, const char *name, expressionObj *exp); /* ** Symbol to string static arrays needed for writing map files. ** Must be kept in sync with enumerations and defines found in mapserver.h. */ /* static char *msUnits[9]={"INCHES", "FEET", "MILES", "METERS", "KILOMETERS", "DD", "PIXELS", "PERCENTAGES", "NAUTICALMILES"}; */ /* static char *msLayerTypes[9]={"POINT", "LINE", "POLYGON", "RASTER", "ANNOTATION", "QUERY", "CIRCLE", "TILEINDEX","CHART"}; */ char *msPositionsText[MS_POSITIONS_LENGTH] = {"UL", "LR", "UR", "LL", "CR", "CL", "UC", "LC", "CC", "AUTO", "XY", "FOLLOW"}; /* msLabelPositions[] also used in mapsymbols.c (not static) */ /* static char *msBitmapFontSizes[5]={"TINY", "SMALL", "MEDIUM", "LARGE", "GIANT"}; */ /* static char *msQueryMapStyles[4]={"NORMAL", "HILITE", "SELECTED", "INVERTED"}; */ /* static char *msStatus[4]={"OFF", "ON", "DEFAULT", "EMBED"}; */ /* static char *msOnOff[2]={"OFF", "ON"}; */ /* static char *msTrueFalse[2]={"FALSE", "TRUE"}; */ /* static char *msYesNo[2]={"NO", "YES"}; */ /* static char *msJoinType[2]={"ONE-TO-ONE", "ONE-TO-MANY"}; */ /* static char *msAlignValue[3]={"LEFT","CENTER","RIGHT"}; */ /* ** Validates a string (value) against a series of patterns. We support up to four to allow cascading from classObj to ** layerObj to webObj plus a legacy pattern like TEMPLATEPATTERN. */ int msValidateParameter(char *value, char *pattern1, char *pattern2, char *pattern3, char *pattern4) { if(msEvalRegex(pattern1, value) == MS_TRUE) return MS_SUCCESS; if(msEvalRegex(pattern2, value) == MS_TRUE) return MS_SUCCESS; if(msEvalRegex(pattern3, value) == MS_TRUE) return MS_SUCCESS; if(msEvalRegex(pattern4, value) == MS_TRUE) return MS_SUCCESS; msSetError(MS_REGEXERR, "Parameter pattern validation failed." , "msValidateParameter()"); return(MS_FAILURE); } int msEvalRegex(char *e, char *s) { ms_regex_t re; if(!e || !s) return(MS_FALSE); if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e); return(MS_FALSE); } if(ms_regexec(&re, s, 0, NULL, 0) != 0) { /* no match */ ms_regfree(&re); msSetError(MS_REGEXERR, "String failed expression test.", "msEvalRegex()"); return(MS_FALSE); } ms_regfree(&re); return(MS_TRUE); } #ifdef USE_MSFREE void msFree(void *p) { if(p) free(p); } #endif /* ** Free memory allocated for a character array */ void msFreeCharArray(char **array, int num_items) { int i; for(i=0; iconfigoptions), "MS_PLUGIN_DIR"); /* do nothing on windows, filename without .dll will be loaded by default*/ #if !defined(_WIN32) if (lib_str) { size_t len = strlen(lib_str); if (3 < len && strcmp(lib_str + len-3, ".so")) { strlcpy(szLibPathExt, lib_str, MS_MAXPATHLEN); strlcat(szLibPathExt, ".so", MS_MAXPATHLEN); lib_str = szLibPathExt; } } #endif /* !defined(_WIN32) */ if (NULL == msBuildPath(szLibPath, plugin_dir, lib_str)) { return MS_FAILURE; } *dest = msStrdup(szLibPath); return MS_SUCCESS; } /* ** Returns the index of specified symbol or -1 if not found. ** ** If try_addimage_if_notfound==MS_TRUE then msAddImageSymbol() will be called ** to try to allocate the symbol as an image symbol. */ int msGetSymbolIndex(symbolSetObj *symbols, char *name, int try_addimage_if_notfound) { int i; if(!symbols || !name) return(-1); /* symbol 0 has no name */ for(i=1; inumsymbols; i++) { if(symbols->symbol[i]->name) if(strcasecmp(symbols->symbol[i]->name, name) == 0) return(i); } if (try_addimage_if_notfound) return(msAddImageSymbol(symbols, name)); /* make sure it's not a filename */ return(-1); } /* ** Return the index number for a given layer based on its name. */ int msGetLayerIndex(mapObj *map, char *name) { int i; if(!name) return(-1); for(i=0; inumlayers; i++) { if(!GET_LAYER(map, i)->name) /* skip it */ continue; if(strcmp(name, GET_LAYER(map, i)->name) == 0) return(i); } return(-1); } int msGetClassIndex(layerObj *layer, char *name) { int i; if(!name) return(-1); for(i=0; inumclasses; i++) { if(!layer->class[i]->name) /* skip it */ continue; if(strcmp(name, layer->class[i]->name) == 0) return(i); } return(-1); } int loadColor(colorObj *color, attributeBindingObj *binding) { int symbol; char hex[2]; if(binding) { if((symbol = getSymbol(3, MS_NUMBER, MS_BINDING, MS_STRING)) == -1) return MS_FAILURE; } else { if((symbol = getSymbol(2, MS_NUMBER, MS_STRING)) == -1) return MS_FAILURE; } color->alpha=255; if(symbol == MS_NUMBER) { color->red = (int) msyynumber; if(getInteger(&(color->green)) == -1) return MS_FAILURE; if(getInteger(&(color->blue)) == -1) return MS_FAILURE; } else if(symbol == MS_STRING) { int len = strlen(msyystring_buffer); if(msyystring_buffer[0] == '#' && (len == 7 || len == 9)) { /* got a hex color w/optional alpha */ hex[0] = msyystring_buffer[1]; hex[1] = msyystring_buffer[2]; color->red = msHexToInt(hex); hex[0] = msyystring_buffer[3]; hex[1] = msyystring_buffer[4]; color->green = msHexToInt(hex); hex[0] = msyystring_buffer[5]; hex[1] = msyystring_buffer[6]; color->blue = msHexToInt(hex); if(len == 9) { hex[0] = msyystring_buffer[7]; hex[1] = msyystring_buffer[8]; color->alpha = msHexToInt(hex); } } else { /* TODO: consider named colors here */ msSetError(MS_SYMERR, "Invalid hex color (%s):(line %d)", "loadColor()", msyystring_buffer, msyylineno); return MS_FAILURE; } } else { binding->item = msStrdup(msyystring_buffer); binding->index = -1; } return MS_SUCCESS; } #if ALPHACOLOR_ENABLED int loadColorWithAlpha(colorObj *color) { char hex[2]; if(getInteger(&(color->red)) == -1) { if(msyystring_buffer[0] == '#' && strlen(msyystring_buffer) == 7) { /* got a hex color */ hex[0] = msyystring_buffer[1]; hex[1] = msyystring_buffer[2]; color->red = msHexToInt(hex); hex[0] = msyystring_buffer[3]; hex[1] = msyystring_buffer[4]; color->green = msHexToInt(hex); hex[0] = msyystring_buffer[5]; hex[1] = msyystring_buffer[6]; color->blue = msHexToInt(hex); color->alpha = 0; return(MS_SUCCESS); } else if(msyystring_buffer[0] == '#' && strlen(msyystring_buffer) == 9) { /* got a hex color with alpha */ hex[0] = msyystring_buffer[1]; hex[1] = msyystring_buffer[2]; color->red = msHexToInt(hex); hex[0] = msyystring_buffer[3]; hex[1] = msyystring_buffer[4]; color->green = msHexToInt(hex); hex[0] = msyystring_buffer[5]; hex[1] = msyystring_buffer[6]; color->blue = msHexToInt(hex); hex[0] = msyystring_buffer[7]; hex[1] = msyystring_buffer[8]; color->alpha = msHexToInt(hex); return(MS_SUCCESS); } return(MS_FAILURE); } if(getInteger(&(color->green)) == -1) return(MS_FAILURE); if(getInteger(&(color->blue)) == -1) return(MS_FAILURE); if(getInteger(&(color->alpha)) == -1) return(MS_FAILURE); return(MS_SUCCESS); } #endif /* ** Helper functions for writing mapfiles. */ static void writeLineFeed(FILE *stream) { msIO_fprintf(stream, "\n"); } static void writeIndent(FILE *stream, int indent) { const char *str=" "; /* change this string to define the indent */ int i; for(i=0; iitem) return; writeIndent(stream, ++indent); msIO_fprintf(stream, "%s [%s]\n", name, binding->item); } static void writeColor(FILE *stream, int indent, const char *name, colorObj *defaultColor, colorObj *color) { if (!defaultColor && !MS_VALID_COLOR(*color)) return; else if(defaultColor && MS_COMPARE_COLOR(*defaultColor, *color)) return; /* if defaultColor has the same value than the color, return.*/ writeIndent(stream, ++indent); #if ALPHACOLOR_ENABLED msIO_fprintf(stream, "%s %d %d %d\n", name, color->red, color->green, color->blue, color->alpha); #else if(color->alpha != 255) { char buffer[9]; sprintf(buffer, "%02x", color->red); sprintf(buffer+2, "%02x", color->green); sprintf(buffer+4, "%02x", color->blue); sprintf(buffer+6, "%02x", color->alpha); *(buffer+8) = 0; msIO_fprintf(stream, "%s \"#%s\"\n", name, buffer); } else { msIO_fprintf(stream, "%s %d %d %d\n", name, color->red, color->green, color->blue); } #endif } /* todo: deal with alpha's... */ static void writeColorRange(FILE *stream, int indent, const char *name, colorObj *mincolor, colorObj *maxcolor) { if(!MS_VALID_COLOR(*mincolor) || !MS_VALID_COLOR(*maxcolor)) return; writeIndent(stream, ++indent); msIO_fprintf(stream, "%s %d %d %d %d %d %d\n", name, mincolor->red, mincolor->green, mincolor->blue, maxcolor->red, maxcolor->green, maxcolor->blue); } /* ** Initialize, load and free a single join */ void initJoin(joinObj *join) { join->numitems = 0; join->name = NULL; /* unique join name, used for variable substitution */ join->items = NULL; /* array to hold item names for the joined table */ join->values = NULL; /* arrays of strings to holds one record worth of data */ join->table = NULL; join->joininfo = NULL; join->from = NULL; /* join items */ join->to = NULL; join->header = NULL; join->template = NULL; /* only html type templates are supported */ join->footer = NULL; join->type = MS_JOIN_ONE_TO_ONE; join->connection = NULL; join->connectiontype = MS_DB_XBASE; } void freeJoin(joinObj *join) { msFree(join->name); msFree(join->table); msFree(join->from); msFree(join->to); msFree(join->header); msFree(join->template); msFree(join->footer); msFreeCharArray(join->items, join->numitems); /* these may have been free'd elsewhere */ msFreeCharArray(join->values, join->numitems); join->numitems = 0; msJoinClose(join); msFree(join->connection); } int loadJoin(joinObj *join) { initJoin(join); for(;;) { switch(msyylex()) { case(CONNECTION): if(getString(&join->connection) == MS_FAILURE) return(-1); break; case(CONNECTIONTYPE): if((join->connectiontype = getSymbol(5, MS_DB_XBASE, MS_DB_MYSQL, MS_DB_ORACLE, MS_DB_POSTGRES, MS_DB_CSV)) == -1) return(-1); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadJoin()"); return(-1); case(END): if((join->from == NULL) || (join->to == NULL) || (join->table == NULL)) { msSetError(MS_EOFERR, "Join must define table, name, from and to properties.", "loadJoin()"); return(-1); } if((join->type == MS_MULTIPLE) && ((join->template == NULL) || (join->name == NULL))) { msSetError(MS_EOFERR, "One-to-many joins must define template and name properties.", "loadJoin()"); return(-1); } return(0); case(FOOTER): if(getString(&join->footer) == MS_FAILURE) return(-1); break; case(FROM): if(getString(&join->from) == MS_FAILURE) return(-1); break; case(HEADER): if(getString(&join->header) == MS_FAILURE) return(-1); break; case(JOIN): break; /* for string loads */ case(NAME): if(getString(&join->name) == MS_FAILURE) return(-1); break; case(TABLE): if(getString(&join->table) == MS_FAILURE) return(-1); break; case(TEMPLATE): if(getString(&join->template) == MS_FAILURE) return(-1); break; case(TO): if(getString(&join->to) == MS_FAILURE) return(-1); break; case(TYPE): if((join->type = getSymbol(2, MS_JOIN_ONE_TO_ONE, MS_JOIN_ONE_TO_MANY)) == -1) return(-1); break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadJoin()", msyystring_buffer, msyylineno); return(-1); } } /* next token */ } static void writeScaleToken(FILE *stream, int indent, scaleTokenObj *token) { int i; indent++; writeBlockBegin(stream,indent,"SCALETOKEN"); writeString(stream, indent, "NAME", NULL, token->name); indent++; writeBlockBegin(stream,indent,"VALUES"); for(i=0;in_entries;i++) { char minscale[32]; sprintf(minscale,"%g",token->tokens[i].minscale); writeNameValuePair(stream, indent, minscale, token->tokens[i].value); } writeBlockEnd(stream,indent,"VALUES"); indent--; writeBlockEnd(stream,indent,"SCALETOKEN"); } static void writeJoin(FILE *stream, int indent, joinObj *join) { indent++; writeBlockBegin(stream, indent, "JOIN"); writeString(stream, indent, "FOOTER", NULL, join->footer); writeString(stream, indent, "FROM", NULL, join->from); writeString(stream, indent, "HEADER", NULL, join->header); writeString(stream, indent, "NAME", NULL, join->name); writeString(stream, indent, "TABLE", NULL, join->table); writeString(stream, indent, "TEMPLATE", NULL, join->template); writeString(stream, indent, "TO", NULL, join->to); writeKeyword(stream, indent, "CONNECTIONTYPE", join->connectiontype, 3, MS_DB_CSV, "CSV", MS_DB_POSTGRES, "POSTRESQL", MS_DB_MYSQL, "MYSQL"); writeKeyword(stream, indent, "TYPE", join->type, 1, MS_JOIN_ONE_TO_MANY, "ONE-TO-MANY"); writeBlockEnd(stream, indent, "JOIN"); } /* inserts a feature at the end of the list, can create a new list */ featureListNodeObjPtr insertFeatureList(featureListNodeObjPtr *list, shapeObj *shape) { featureListNodeObjPtr node; node = (featureListNodeObjPtr) malloc(sizeof(featureListNodeObj)); MS_CHECK_ALLOC(node, sizeof(featureListNodeObj), NULL); msInitShape(&(node->shape)); if(msCopyShape(shape, &(node->shape)) == -1) return(NULL); /* AJS - alans@wunderground.com O(n^2) -> O(n) conversion, keep a pointer to the end */ /* set the tailifhead to NULL, since it is only set for the head of the list */ node->tailifhead = NULL; node->next = NULL; /* if we are at the head of the list, we need to set the list to node, before pointing tailifhead somewhere */ if(*list == NULL) { *list=node; } else { if((*list)->tailifhead!=NULL) /* this should never be NULL, but just in case */ (*list)->tailifhead->next=node; /* put the node at the end of the list */ } /* repoint the head of the list to the end - our new element this causes a loop if we are at the head, be careful not to walk in a loop */ (*list)->tailifhead = node; return(node); /* a pointer to last object in the list */ } void freeFeatureList(featureListNodeObjPtr list) { featureListNodeObjPtr listNext = NULL; while (list!=NULL) { listNext = list->next; msFreeShape(&(list->shape)); msFree(list); list = listNext; } } /* lineObj = multipointObj */ static int loadFeaturePoints(lineObj *points) { int buffer_size=0; points->point = (pointObj *)malloc(sizeof(pointObj)*MS_FEATUREINITSIZE); MS_CHECK_ALLOC(points->point, sizeof(pointObj)*MS_FEATUREINITSIZE, MS_FAILURE); points->numpoints = 0; buffer_size = MS_FEATUREINITSIZE; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadFeaturePoints()"); return(MS_FAILURE); case(END): return(MS_SUCCESS); case(MS_NUMBER): if(points->numpoints == buffer_size) { /* just add it to the end */ points->point = (pointObj *) realloc(points->point, sizeof(pointObj)*(buffer_size+MS_FEATUREINCREMENT)); MS_CHECK_ALLOC(points->point, sizeof(pointObj)*(buffer_size+MS_FEATUREINCREMENT), MS_FAILURE); buffer_size+=MS_FEATUREINCREMENT; } points->point[points->numpoints].x = atof(msyystring_buffer); if(getDouble(&(points->point[points->numpoints].y)) == -1) return(MS_FAILURE); points->numpoints++; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadFeaturePoints()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } } static int loadFeature(layerObj *player, int type) { int status=MS_SUCCESS; featureListNodeObjPtr *list = &(player->features); featureListNodeObjPtr node; multipointObj points= {0,NULL}; shapeObj *shape=NULL; shape = (shapeObj *) malloc(sizeof(shapeObj)); MS_CHECK_ALLOC(shape, sizeof(shapeObj), MS_FAILURE); msInitShape(shape); shape->type = type; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadFeature()"); return(MS_FAILURE); case(END): if(player->features != NULL && player->features->tailifhead != NULL) shape->index = player->features->tailifhead->shape.index + 1; else shape->index = 0; if((node = insertFeatureList(list, shape)) == NULL) status = MS_FAILURE; msFreeShape(shape); /* clean up */ msFree(shape); return(status); case(FEATURE): break; /* for string loads */ case(POINTS): if(loadFeaturePoints(&points) == MS_FAILURE) return(MS_FAILURE); /* no clean up necessary, just return */ status = msAddLine(shape, &points); msFree(points.point); /* clean up */ points.numpoints = 0; if(status == MS_FAILURE) return(MS_FAILURE); break; case(ITEMS): { char *string=NULL; if(getString(&string) == MS_FAILURE) return(MS_FAILURE); if (string) { if(shape->values) msFreeCharArray(shape->values, shape->numvalues); shape->values = msStringSplit(string, ';', &shape->numvalues); msFree(string); /* clean up */ } break; } case(TEXT): if(getString(&shape->text) == MS_FAILURE) return(MS_FAILURE); break; case(WKT): { char *string=NULL; /* todo, what do we do with multiple WKT property occurances? */ if(getString(&string) == MS_FAILURE) return(MS_FAILURE); msFreeShape(shape); msFree(shape); if((shape = msShapeFromWKT(string)) == NULL) status = MS_FAILURE; msFree(string); /* clean up */ if(status == MS_FAILURE) return(MS_FAILURE); break; } default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadfeature()", msyystring_buffer, msyylineno); return(MS_FAILURE); } } /* next token */ } static void writeFeature(FILE *stream, int indent, shapeObj *feature) { int i,j; indent++; writeBlockBegin(stream, indent, "FEATURE"); indent++; for(i=0; inumlines; i++) { writeBlockBegin(stream, indent, "POINTS"); for(j=0; jline[i].numpoints; j++) { writeIndent(stream, indent); msIO_fprintf(stream, "%.15g %.15g\n", feature->line[i].point[j].x, feature->line[i].point[j].y); } writeBlockEnd(stream, indent, "POINTS"); } indent--; if (feature->numvalues) { writeIndent(stream, indent); msIO_fprintf(stream, "ITEMS \""); for (i=0; inumvalues; i++) { if (i == 0) msIO_fprintf(stream, "%s", feature->values[i]); else msIO_fprintf(stream, ";%s", feature->values[i]); } msIO_fprintf(stream, "\"\n"); } writeString(stream, indent, "TEXT", NULL, feature->text); writeBlockEnd(stream, indent, "FEATURE"); } void initGrid( graticuleObj *pGraticule ) { memset( pGraticule, 0, sizeof( graticuleObj ) ); } static int loadGrid( layerObj *pLayer ) { for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadGrid()"); return(-1); case(END): return(0); case(GRID): break; /* for string loads */ case( LABELFORMAT ): if(getString(&((graticuleObj *)pLayer->layerinfo)->labelformat) == MS_FAILURE) { if(strcasecmp(msyystring_buffer, "DD") == 0) /* DD triggers a symbol to be returned instead of a string so check for this special case */ ((graticuleObj *)pLayer->layerinfo)->labelformat = msStrdup("DD"); else return(-1); } break; case( MINARCS ): if(getDouble(&((graticuleObj *)pLayer->layerinfo)->minarcs) == -1) return(-1); break; case( MAXARCS ): if(getDouble(&((graticuleObj *)pLayer->layerinfo)->maxarcs) == -1) return(-1); break; case( MININTERVAL ): if(getDouble(&((graticuleObj *)pLayer->layerinfo)->minincrement) == -1) return(-1); break; case( MAXINTERVAL ): if(getDouble(&((graticuleObj *)pLayer->layerinfo)->maxincrement) == -1) return(-1); break; case( MINSUBDIVIDE ): if(getDouble(&((graticuleObj *)pLayer->layerinfo)->minsubdivides) == -1) return(-1); break; case( MAXSUBDIVIDE ): if(getDouble(&((graticuleObj *)pLayer->layerinfo)->maxsubdivides) == -1) return(-1); break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadGrid()", msyystring_buffer, msyylineno); return(-1); } } } static void writeGrid(FILE *stream, int indent, graticuleObj *pGraticule) { if(!pGraticule) return; indent++; writeBlockBegin(stream, indent, "GRID"); writeString(stream, indent, "LABELFORMAT", NULL, pGraticule->labelformat); writeNumber(stream, indent, "MAXARCS", 0, pGraticule->maxarcs); writeNumber(stream, indent, "MAXSUBDIVIDE", 0, pGraticule->maxsubdivides); writeNumber(stream, indent, "MAXINTERVAL", 0, pGraticule->maxincrement); writeNumber(stream, indent, "MINARCS", 0, pGraticule->minarcs); writeNumber(stream, indent, "MININTERVAL", 0, pGraticule->minincrement); writeNumber(stream, indent, "MINSUBDIVIDE", 0, pGraticule->minsubdivides); writeBlockEnd(stream, indent, "GRID"); } /* ** Initialize, load and free a projectionObj structure */ int msInitProjection(projectionObj *p) { p->gt.need_geotransform = MS_FALSE; p->numargs = 0; p->args = NULL; p->wellknownprojection = wkp_none; #ifdef USE_PROJ p->proj = NULL; p->args = (char **)malloc(MS_MAXPROJARGS*sizeof(char *)); MS_CHECK_ALLOC(p->args, MS_MAXPROJARGS*sizeof(char *), -1); #if PJ_VERSION >= 480 p->proj_ctx = NULL; #endif #endif return(0); } void msFreeProjection(projectionObj *p) { #ifdef USE_PROJ if(p->proj) { pj_free(p->proj); p->proj = NULL; } #if PJ_VERSION >= 480 if(p->proj_ctx) { pj_ctx_free(p->proj_ctx); p->proj_ctx = NULL; } #endif msFreeCharArray(p->args, p->numargs); p->args = NULL; p->numargs = 0; #endif } /* ** Handle OGC WMS/WFS AUTO projection in the format: ** "AUTO:proj_id,units_id,lon0,lat0" */ #ifdef USE_PROJ static int _msProcessAutoProjection(projectionObj *p) { char **args; int numargs, nProjId, nUnitsId, nZone; double dLat0, dLon0; const char *pszUnits = "m"; char szProjBuf[512]=""; /* WMS/WFS AUTO projection: "AUTO:proj_id,units_id,lon0,lat0" */ args = msStringSplit(p->args[0], ',', &numargs); if (numargs != 4 || (strncasecmp(args[0], "AUTO:", 5) != 0 && strncasecmp(args[0], "AUTO2:", 6) != 0)) { msSetError(MS_PROJERR, "WMS/WFS AUTO/AUTO2 PROJECTION must be in the format " "'AUTO:proj_id,units_id,lon0,lat0' or 'AUTO2:crs_id,factor,lon0,lat0'(got '%s').\n", "_msProcessAutoProjection()", p->args[0]); return -1; } if (strncasecmp(args[0], "AUTO:", 5)==0) nProjId = atoi(args[0]+5); else nProjId = atoi(args[0]+6); nUnitsId = atoi(args[1]); dLon0 = atof(args[2]); dLat0 = atof(args[3]); /*There is no unit parameter for AUTO2. The 2nd parameter is factor. Set the units to always be meter*/ if (strncasecmp(args[0], "AUTO2:", 6) == 0) nUnitsId = 9001; msFreeCharArray(args, numargs); /* Handle EPSG Units. Only meters for now. */ switch(nUnitsId) { case 9001: /* Meters */ pszUnits = "m"; break; default: msSetError(MS_PROJERR, "WMS/WFS AUTO PROJECTION: EPSG Units %d not supported.\n", "_msProcessAutoProjection()", nUnitsId); return -1; } /* Build PROJ4 definition. * This is based on the definitions found in annex E of the WMS 1.1.1 * spec and online at http://www.digitalearth.org/wmt/auto.html * The conversion from the original WKT definitions to PROJ4 format was * done using the MapScript setWKTProjection() function (based on OGR). */ switch(nProjId) { case 42001: /** WGS 84 / Auto UTM **/ nZone = (int) floor( (dLon0 + 180.0) / 6.0 ) + 1; sprintf( szProjBuf, "+proj=tmerc+lat_0=0+lon_0=%.16g+k=0.999600+x_0=500000" "+y_0=%.16g+ellps=WGS84+datum=WGS84+units=%s", -183.0 + nZone * 6.0, (dLat0 >= 0.0) ? 0.0 : 10000000.0, pszUnits); break; case 42002: /** WGS 84 / Auto Tr. Mercator **/ sprintf( szProjBuf, "+proj=tmerc+lat_0=0+lon_0=%.16g+k=0.999600+x_0=500000" "+y_0=%.16g+ellps=WGS84+datum=WGS84+units=%s", dLon0, (dLat0 >= 0.0) ? 0.0 : 10000000.0, pszUnits); break; case 42003: /** WGS 84 / Auto Orthographic **/ sprintf( szProjBuf, "+proj=ortho+lon_0=%.16g+lat_0=%.16g+x_0=0+y_0=0" "+ellps=WGS84+datum=WGS84+units=%s", dLon0, dLat0, pszUnits ); break; case 42004: /** WGS 84 / Auto Equirectangular **/ /* Note that we have to pass lon_0 as lon_ts for this one to */ /* work. Either a PROJ4 bug or a PROJ4 documentation issue. */ sprintf( szProjBuf, "+proj=eqc+lon_ts=%.16g+lat_ts=%.16g+x_0=0+y_0=0" "+ellps=WGS84+datum=WGS84+units=%s", dLon0, dLat0, pszUnits); break; case 42005: /** WGS 84 / Auto Mollweide **/ sprintf( szProjBuf, "+proj=moll+lon_0=%.16g+x_0=0+y_0=0+ellps=WGS84" "+datum=WGS84+units=%s", dLon0, pszUnits); break; default: msSetError(MS_PROJERR, "WMS/WFS AUTO PROJECTION %d not supported.\n", "_msProcessAutoProjection()", nProjId); return -1; } /* msDebug("%s = %s\n", p->args[0], szProjBuf); */ /* OK, pass the definition to pj_init() */ args = msStringSplit(szProjBuf, '+', &numargs); msAcquireLock( TLOCK_PROJ ); if( !(p->proj = pj_init(numargs, args)) ) { int *pj_errno_ref = pj_get_errno_ref(); msReleaseLock( TLOCK_PROJ ); msSetError(MS_PROJERR, "proj error \"%s\" for \"%s\"", "msProcessProjection()", pj_strerrno(*pj_errno_ref), szProjBuf) ; return(-1); } msReleaseLock( TLOCK_PROJ ); msFreeCharArray(args, numargs); return(0); } #endif /* USE_PROJ */ int msProcessProjection(projectionObj *p) { #ifdef USE_PROJ assert( p->proj == NULL ); if( strcasecmp(p->args[0],"GEOGRAPHIC") == 0 ) { msSetError(MS_PROJERR, "PROJECTION 'GEOGRAPHIC' no longer supported.\n" "Provide explicit definition.\n" "ie. proj=latlong\n" " ellps=clrk66\n", "msProcessProjection()"); return(-1); } if (strcasecmp(p->args[0], "AUTO") == 0) { p->proj = NULL; return 0; } if (strncasecmp(p->args[0], "AUTO:", 5) == 0 || strncasecmp(p->args[0], "AUTO2:", 6) == 0) { /* WMS/WFS AUTO projection: "AUTO:proj_id,units_id,lon0,lat0" */ /*WMS 1.3.0: AUTO2:auto_crs_id,factor,lon0,lat0*/ return _msProcessAutoProjection(p); } msAcquireLock( TLOCK_PROJ ); #if PJ_VERSION < 480 if( !(p->proj = pj_init(p->numargs, p->args)) ) { #else p->proj_ctx = pj_ctx_alloc(); if( !(p->proj=pj_init_ctx(p->proj_ctx, p->numargs, p->args)) ) { #endif int *pj_errno_ref = pj_get_errno_ref(); msReleaseLock( TLOCK_PROJ ); if(p->numargs>1) { msSetError(MS_PROJERR, "proj error \"%s\" for \"%s:%s\"", "msProcessProjection()", pj_strerrno(*pj_errno_ref), p->args[0],p->args[1]) ; } else { msSetError(MS_PROJERR, "proj error \"%s\" for \"%s\"", "msProcessProjection()", pj_strerrno(*pj_errno_ref), p->args[0]) ; } return(-1); } msReleaseLock( TLOCK_PROJ ); #ifdef USE_PROJ_FASTPATHS if(strcasestr(p->args[0],"epsg:4326")) { p->wellknownprojection = wkp_lonlat; } else if(strcasestr(p->args[0],"epsg:3857")) { p->wellknownprojection = wkp_gmerc; } else { p->wellknownprojection = wkp_none; } #endif return(0); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProcessProjection()"); return(-1); #endif } static int loadProjection(projectionObj *p) { #ifdef USE_PROJ int i=0; #endif p->gt.need_geotransform = MS_FALSE; #ifdef USE_PROJ if ( p->proj != NULL ) { msSetError(MS_MISCERR, "Projection is already initialized. Multiple projection definitions are not allowed in this object. (line %d)", "loadProjection()", msyylineno); return(-1); } for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadProjection()"); return(-1); case(END): if( i == 1 && strstr(p->args[0],"+") != NULL ) { char *one_line_def = p->args[0]; int result; p->args[0] = NULL; result = msLoadProjectionString( p, one_line_def ); free( one_line_def ); return result; } else { p->numargs = i; if(p->numargs != 0) return msProcessProjection(p); else return 0; } break; case(MS_STRING): case(MS_AUTO): p->args[i] = msStrdup(msyystring_buffer); p->automatic = MS_TRUE; i++; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadProjection()", msyystring_buffer, msyylineno); return(-1); } } /* next token */ #else msSetError(MS_PROJERR, "Projection support is not available.", "loadProjection()"); return(-1); #endif } /************************************************************************/ /* msLoadProjectionStringEPSG */ /* */ /* Checks fro EPSG type projection and set the axes for a */ /* certain code ranges. */ /* Use for now in WMS 1.3.0 */ /************************************************************************/ int msLoadProjectionStringEPSG(projectionObj *p, const char *value) { #ifdef USE_PROJ if(p) msFreeProjection(p); p->gt.need_geotransform = MS_FALSE; #ifdef USE_PROJ_FASTPATHS if(strcasestr(value,"epsg:4326")) { p->wellknownprojection = wkp_lonlat; } else if(strcasestr(value,"epsg:3857")) { p->wellknownprojection = wkp_gmerc; } else { p->wellknownprojection = wkp_none; } #endif if (strncasecmp(value, "EPSG:", 5) == 0) { size_t buffer_size = 10 + strlen(value+5) + 1; char *init_string = (char*)msSmallMalloc(buffer_size); /* translate into PROJ.4 format. */ snprintf(init_string, buffer_size, "init=epsg:%s", value+5 ); p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = init_string; p->numargs = 1; if( msIsAxisInverted(atoi(value+5))) { p->args[1] = msStrdup("+epsgaxis=ne"); p->numargs = 2; } return msProcessProjection( p ); } return msLoadProjectionString(p, value); #else msSetError(MS_PROJERR, "Projection support is not available.", "msLoadProjectionStringEPSG()"); return(-1); #endif } int msLoadProjectionString(projectionObj *p, const char *value) { p->gt.need_geotransform = MS_FALSE; #ifdef USE_PROJ if(p) msFreeProjection(p); /* * Handle new style definitions, the same as they would be given to * the proj program. * eg. * "+proj=utm +zone=11 +ellps=WGS84" */ if( value[0] == '+' ) { char *trimmed; int i, i_out=0; trimmed = msStrdup(value+1); for( i = 1; value[i] != '\0'; i++ ) { if( !isspace( value[i] ) ) trimmed[i_out++] = value[i]; } trimmed[i_out] = '\0'; p->args = msStringSplit(trimmed,'+', &p->numargs); free( trimmed ); } else if (strncasecmp(value, "AUTO:", 5) == 0 || strncasecmp(value, "AUTO2:", 6) == 0) { /* WMS/WFS AUTO projection: "AUTO:proj_id,units_id,lon0,lat0" */ /* WMS 1.3.0 projection: "AUTO2:auto_crs_id,factor,lon0,lat0"*/ /* Keep the projection defn into a single token for writeProjection() */ /* to work fine. */ p->args = (char**)msSmallMalloc(sizeof(char*)); p->args[0] = msStrdup(value); p->numargs = 1; } else if (strncasecmp(value, "EPSG:", 5) == 0) { size_t buffer_size = 10 + strlen(value+5) + 1; char *init_string = (char*)msSmallMalloc(buffer_size); /* translate into PROJ.4 format. */ snprintf( init_string, buffer_size, "init=epsg:%s", value+5); p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = init_string; p->numargs = 1; } else if (strncasecmp(value, "urn:ogc:def:crs:EPSG:",21) == 0) { /* this is very preliminary urn support ... expand later */ size_t buffer_size = 0; char *init_string = NULL; const char *code; code = value + 21; while( *code != ':' && *code != '\0' ) code++; if( *code == ':' ) code++; buffer_size = 10 + strlen(code) + 1; init_string = (char*)msSmallMalloc(buffer_size); /* translate into PROJ.4 format. */ snprintf( init_string, buffer_size, "init=epsg:%s", code ); p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = init_string; p->numargs = 1; if( msIsAxisInverted(atoi(code))) { p->args[1] = msStrdup("+epsgaxis=ne"); p->numargs = 2; } } else if (strncasecmp(value, "urn:x-ogc:def:crs:EPSG:",23) == 0) { /*this case is to account for OGC CITE tests where x-ogc was used before the ogc name became an official NID. Note also we also account for the fact that a space for the version of the espg is not used with CITE tests. (Syntax used could be urn:ogc:def:objectType:authority:code)*/ size_t buffer_size = 0; char *init_string = NULL; const char *code; if (value[23] == ':') code = value + 23; else code = value + 22; while( *code != ':' && *code != '\0' ) code++; if( *code == ':' ) code++; buffer_size = 10 + strlen(code) + 1; init_string = (char*)msSmallMalloc(buffer_size); /* translate into PROJ.4 format. */ snprintf( init_string, buffer_size, "init=epsg:%s", code ); p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = init_string; p->numargs = 1; if( msIsAxisInverted(atoi(code))) { p->args[1] = msStrdup("+epsgaxis=ne"); p->numargs = 2; } } else if (strncasecmp(value, "urn:ogc:def:crs:OGC:",20) == 0 ) { /* this is very preliminary urn support ... expand later */ char init_string[100]; const char *id; id = value + 20; while( *id != ':' && *id == '\0' ) id++; if( *id == ':' ) id++; init_string[0] = '\0'; if( strcasecmp(id,"CRS84") == 0 ) strncpy( init_string, "init=epsg:4326", sizeof(init_string) ); else if( strcasecmp(id,"CRS83") == 0 ) strncpy( init_string, "init=epsg:4269", sizeof(init_string) ); else if( strcasecmp(id,"CRS27") == 0 ) strncpy( init_string, "init=epsg:4267", sizeof(init_string) ); else { msSetError( MS_PROJERR, "Unrecognised OGC CRS def '%s'.", "msLoadProjectionString()", value ); return -1; } p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = msStrdup(init_string); p->numargs = 1; } /* URI projection support */ else if (EQUALN("http://www.opengis.net/def/crs/EPSG/", value, 36)) { /* this is very preliminary urn support ... expand later */ char init_string[100]; const char *code; code = value + 36; while( *code != '/' && *code != '\0' ) code++; if( *code == '/' ) code++; /* translate into PROJ.4 format. */ snprintf( init_string, sizeof(init_string), "init=epsg:%s", code ); p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = msStrdup(init_string); p->numargs = 1; if( msIsAxisInverted(atoi(code))) { p->args[1] = msStrdup("+epsgaxis=ne"); p->numargs = 2; } } else if (EQUALN("http://www.opengis.net/def/crs/OGC/", value, 35) ) { char init_string[100]; const char *id; id = value + 35; while( *id != '/' && *id == '\0' ) id++; if( *id == '/' ) id++; init_string[0] = '\0'; if( strcasecmp(id,"CRS84") == 0 ) strncpy( init_string, "init=epsg:4326", sizeof(init_string) ); else if( strcasecmp(id,"CRS83") == 0 ) strncpy( init_string, "init=epsg:4269", sizeof(init_string) ); else if( strcasecmp(id,"CRS27") == 0 ) strncpy( init_string, "init=epsg:4267", sizeof(init_string) ); else { msSetError( MS_PROJERR, "Unrecognised OGC CRS def '%s'.", "msLoadProjectionString()", value ); return -1; } p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = msStrdup(init_string); p->numargs = 1; /* Mandatory support for this URI format specified in WFS1.1 (also in 1.0?) */ } else if (EQUALN("http://www.opengis.net/gml/srs/epsg.xml#", value, 40)) { /* We assume always lon/lat ordering, as that is what GeoServer does... */ const char *code; code = value + 40; p->args = (char **) msSmallMalloc(sizeof(char *)); /* translate into PROJ.4 format as we go */ p->args[0] = (char *) msSmallMalloc(11 + strlen(code)); snprintf(p->args[0], 11 + strlen(code), "init=epsg:%s", code); p->numargs = 1; } else if (strncasecmp(value, "CRS:",4) == 0 ) { char init_string[100]; init_string[0] = '\0'; if (atoi(value+4) == 84) strncpy( init_string, "init=epsg:4326", sizeof(init_string) ); else if (atoi(value+4) == 83) strncpy( init_string, "init=epsg:4269", sizeof(init_string) ); else if (atoi(value+4) == 27) strncpy( init_string, "init=epsg:4267", sizeof(init_string) ); else { msSetError( MS_PROJERR, "Unrecognised OGC CRS def '%s'.", "msLoadProjectionString()", value ); return -1; } p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = msStrdup(init_string); p->numargs = 1; } /* * Handle old style comma delimited. eg. "proj=utm,zone=11,ellps=WGS84". */ else { p->args = msStringSplit(value,',', &p->numargs); } return msProcessProjection( p ); #else msSetError(MS_PROJERR, "Projection support is not available.", "msLoadProjectionString()"); return(-1); #endif } static void writeProjection(FILE *stream, int indent, projectionObj *p) { #ifdef USE_PROJ int i; if(!p || p->numargs <= 0) return; indent++; writeBlockBegin(stream, indent, "PROJECTION"); for(i=0; inumargs; i++) writeString(stream, indent, NULL, NULL, p->args[i]); writeBlockEnd(stream, indent, "PROJECTION"); #endif } void initLeader(labelLeaderObj *leader) { leader->gridstep = 5; leader->maxdistance = 0; /* Set maxstyles = 0, styles[] will be allocated as needed on first call * to msGrowLabelLeaderStyles() */ leader->numstyles = leader->maxstyles = 0; leader->styles = NULL; } /* ** Initialize, load and free a labelObj structure */ void initLabel(labelObj *label) { int i; MS_REFCNT_INIT(label); label->antialias = -1; /* off */ label->align = MS_ALIGN_LEFT; MS_INIT_COLOR(label->color, 0,0,0,255); MS_INIT_COLOR(label->outlinecolor, -1,-1,-1,255); /* don't use it */ label->outlinewidth=1; MS_INIT_COLOR(label->shadowcolor, -1,-1,-1,255); /* don't use it */ label->shadowsizex = label->shadowsizey = 1; label->font = NULL; label->type = MS_BITMAP; label->size = MS_MEDIUM; label->position = MS_CC; label->angle = 0; label->anglemode = MS_NONE; label->minsize = MS_MINFONTSIZE; label->maxsize = MS_MAXFONTSIZE; label->buffer = 0; label->offsetx = label->offsety = 0; label->minscaledenom=-1; label->maxscaledenom=-1; label->minfeaturesize = -1; /* no limit */ label->autominfeaturesize = MS_FALSE; label->mindistance = -1; /* no limit */ label->repeatdistance = 0; /* no repeat */ label->maxoverlapangle = 22.5; /* default max overlap angle */ label->partials = MS_TRUE; label->wrap = '\0'; label->maxlength = 0; label->minlength = 0; label->space_size_10=0.0; label->encoding = NULL; label->force = MS_OFF; label->priority = MS_DEFAULT_LABEL_PRIORITY; /* Set maxstyles = 0, styles[] will be allocated as needed on first call * to msGrowLabelStyles() */ label->numstyles = label->maxstyles = 0; label->styles = NULL; label->numbindings = 0; for(i=0; ibindings[i].item = NULL; label->bindings[i].index = -1; } label->status = MS_ON; initExpression(&(label->expression)); initExpression(&(label->text)); label->annotext = NULL; label->annopoly = NULL; initLeader(&(label->leader)); return; } static int freeLabelLeader(labelLeaderObj *leader) { int i; for(i=0; inumstyles; i++) { msFree(leader->styles[i]); } msFree(leader->styles); return MS_SUCCESS; } int freeLabel(labelObj *label) { int i; if( MS_REFCNT_DECR_IS_NOT_ZERO(label) ) { return MS_FAILURE; } msFree(label->font); msFree(label->encoding); for(i=0; inumstyles; i++) { /* each style */ if(label->styles[i]!=NULL) { if(freeStyle(label->styles[i]) == MS_SUCCESS) { msFree(label->styles[i]); } } } msFree(label->styles); for(i=0; ibindings[i].item); freeExpression(&(label->expression)); freeExpression(&(label->text)); /* free book keeping vars associated with the label cache */ msFree(label->annotext); if(label->annopoly) { msFreeShape(label->annopoly); msFree(label->annopoly); } freeLabelLeader(&(label->leader)); return MS_SUCCESS; } static int loadLeader(labelLeaderObj *leader) { for(;;) { switch(msyylex()) { case(END): return(0); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadLeader()"); return(-1); case GRIDSTEP: if(getInteger(&(leader->gridstep)) == -1) return(-1); break; case MAXDISTANCE: if(getInteger(&(leader->maxdistance)) == -1) return(-1); break; case STYLE: if(msGrowLeaderStyles(leader) == NULL) return(-1); initStyle(leader->styles[leader->numstyles]); if(loadStyle(leader->styles[leader->numstyles]) != MS_SUCCESS) return(-1); leader->numstyles++; break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLeader()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } static int loadLabel(labelObj *label) { int symbol; for(;;) { switch(msyylex()) { case(ANGLE): if((symbol = getSymbol(5, MS_NUMBER,MS_AUTO,MS_AUTO2,MS_FOLLOW,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) label->angle = msyynumber; else if(symbol == MS_BINDING) { if (label->bindings[MS_LABEL_BINDING_ANGLE].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_ANGLE].item); label->bindings[MS_LABEL_BINDING_ANGLE].item = msStrdup(msyystring_buffer); label->numbindings++; } else if ( symbol == MS_FOLLOW ) { label->anglemode = MS_FOLLOW; } else if ( symbol == MS_AUTO2 ) { label->anglemode = MS_AUTO2; } else label->anglemode = MS_AUTO; break; case(ALIGN): if((label->align = getSymbol(3, MS_ALIGN_LEFT,MS_ALIGN_CENTER,MS_ALIGN_RIGHT)) == -1) return(-1); break; case(ANTIALIAS): if((label->antialias = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(BUFFER): if(getInteger(&(label->buffer)) == -1) return(-1); break; case(COLOR): if(loadColor(&(label->color), &(label->bindings[MS_LABEL_BINDING_COLOR])) != MS_SUCCESS) return(-1); if(label->bindings[MS_LABEL_BINDING_COLOR].item) label->numbindings++; break; case(ENCODING): if((getString(&label->encoding)) == MS_FAILURE) return(-1); break; case(END): /* sanity check */ if(label->anglemode == MS_FOLLOW && label->type == MS_BITMAP) { msSetError(MS_MISCERR,"Follow labels not supported with bitmap fonts.", "loadLabel()"); return -1; } return(0); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadLabel()"); freeLabel(label); /* free any structures allocated before EOF */ return(-1); case(EXPRESSION): if(loadExpression(&(label->expression)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { msSetError(MS_MISCERR, "URL-based EXPRESSION configuration not supported." , "loadLabel()"); freeExpression(&(label->expression)); return(-1); } break; case(FONT): if((symbol = getSymbol(2, MS_STRING, MS_BINDING)) == -1) return(-1); if(symbol == MS_STRING) { if (label->font != NULL) msFree(label->font); label->font = msStrdup(msyystring_buffer); } else { if (label->bindings[MS_LABEL_BINDING_FONT].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_FONT].item); label->bindings[MS_LABEL_BINDING_FONT].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(FORCE): switch(msyylex()) { case MS_ON: label->force = MS_ON; break; case MS_OFF: label->force = MS_OFF; break; case GROUP: label->force = MS_LABEL_FORCE_GROUP; break; default: msSetError(MS_MISCERR, "Invalid FORCE, must be ON,OFF,or GROUP" , "loadLabel()"); return(-1); } break; case(LABEL): break; /* for string loads */ case(LEADER): msSetError(MS_MISCERR, "LABEL LEADER not implemented. LEADER goes at the CLASS level." , "loadLabel()"); return(-1); if(loadLeader(&(label->leader)) == -1) return(-1); break; case(MAXSIZE): if(getDouble(&(label->maxsize)) == -1) return(-1); break; case(MAXSCALEDENOM): if(getDouble(&(label->maxscaledenom)) == -1) return(-1); break; case(MAXLENGTH): if(getInteger(&(label->maxlength)) == -1) return(-1); break; case(MINLENGTH): if(getInteger(&(label->minlength)) == -1) return(-1); break; case(MINDISTANCE): if(getInteger(&(label->mindistance)) == -1) return(-1); break; case(REPEATDISTANCE): if(getInteger(&(label->repeatdistance)) == -1) return(-1); break; case(MAXOVERLAPANGLE): if(getDouble(&(label->maxoverlapangle)) == -1) return(-1); break; case(MINFEATURESIZE): if((symbol = getSymbol(2, MS_NUMBER,MS_AUTO)) == -1) return(-1); if(symbol == MS_NUMBER) label->minfeaturesize = (int)msyynumber; else label->autominfeaturesize = MS_TRUE; break; case(MINSCALEDENOM): if(getDouble(&(label->minscaledenom)) == -1) return(-1); break; case(MINSIZE): if(getDouble(&(label->minsize)) == -1) return(-1); break; case(OFFSET): if(getInteger(&(label->offsetx)) == -1) return(-1); if(getInteger(&(label->offsety)) == -1) return(-1); break; case(OUTLINECOLOR): if(loadColor(&(label->outlinecolor), &(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR])) != MS_SUCCESS) return(-1); if(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].item) label->numbindings++; break; case(OUTLINEWIDTH): if(getInteger(&(label->outlinewidth)) == -1) return(-1); break; case(PARTIALS): if((label->partials = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(POSITION): if((label->position = getSymbol(11, MS_UL,MS_UC,MS_UR,MS_CL,MS_CC,MS_CR,MS_LL,MS_LC,MS_LR,MS_AUTO,MS_BINDING)) == -1) return(-1); if(label->position == MS_BINDING) { if(label->bindings[MS_LABEL_BINDING_POSITION].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_POSITION].item); label->bindings[MS_LABEL_BINDING_POSITION].item = strdup(msyystring_buffer); label->numbindings++; } break; case(PRIORITY): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) { label->priority = (int) msyynumber; if(label->priority < 1 || label->priority > MS_MAX_LABEL_PRIORITY) { msSetError(MS_MISCERR, "Invalid PRIORITY, must be an integer between 1 and %d." , "loadLabel()", MS_MAX_LABEL_PRIORITY); return(-1); } } else { if (label->bindings[MS_LABEL_BINDING_PRIORITY].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_PRIORITY].item); label->bindings[MS_LABEL_BINDING_PRIORITY].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(SHADOWCOLOR): if(loadColor(&(label->shadowcolor), NULL) != MS_SUCCESS) return(-1); break; case(SHADOWSIZE): /* if(getInteger(&(label->shadowsizex)) == -1) return(-1); */ if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) { label->shadowsizex = (int) msyynumber; } else { if (label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item); label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item = msStrdup(msyystring_buffer); label->numbindings++; } /* if(getInteger(&(label->shadowsizey)) == -1) return(-1); */ if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) { label->shadowsizey = (int) msyynumber; } else { if (label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item); label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(SIZE): if(label->bindings[MS_LABEL_BINDING_SIZE].item) { msFree(label->bindings[MS_LABEL_BINDING_SIZE].item); label->bindings[MS_LABEL_BINDING_SIZE].item = NULL; label->numbindings--; } if((symbol = getSymbol(7, MS_NUMBER,MS_BINDING,MS_TINY,MS_SMALL,MS_MEDIUM,MS_LARGE,MS_GIANT)) == -1) return(-1); if(symbol == MS_NUMBER) { label->size = (double) msyynumber; } else if(symbol == MS_BINDING) { label->bindings[MS_LABEL_BINDING_SIZE].item = msStrdup(msyystring_buffer); label->numbindings++; } else label->size = symbol; break; case(STYLE): if(msGrowLabelStyles(label) == NULL) return(-1); initStyle(label->styles[label->numstyles]); if(loadStyle(label->styles[label->numstyles]) != MS_SUCCESS) return(-1); if(label->styles[label->numstyles]->_geomtransform.type == MS_GEOMTRANSFORM_NONE) label->styles[label->numstyles]->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; /* set a default, a marker? */ label->numstyles++; break; case(TEXT): if(loadExpression(&(label->text)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { msSetError(MS_MISCERR, "URL-based TEXT configuration not supported for labels." , "loadLabel()"); freeExpression(&(label->text)); return(-1); } if((label->text.type != MS_STRING) && (label->text.type != MS_EXPRESSION)) { msSetError(MS_MISCERR, "Text expressions support constant or tagged replacement strings." , "loadLabel()"); return(-1); } break; case(TYPE): if((label->type = getSymbol(2, MS_TRUETYPE,MS_BITMAP)) == -1) return(-1); break; case(WRAP): if(getCharacter(&(label->wrap)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLabel()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateLabelFromString(labelObj *label, char *string, int url_string) { if(!label || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadLabel(label) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeLeader(FILE *stream, int indent, labelLeaderObj *leader) { int i; if(leader->maxdistance == 0 && leader->numstyles == 0) { return; } indent++; writeBlockBegin(stream, indent, "LEADER"); writeNumber(stream, indent, "MAXDISTANCE", 0, leader->maxdistance); writeNumber(stream, indent, "GRIDSTEP", 5, leader->gridstep); for(i=0; inumstyles; i++) writeStyle(stream, indent, leader->styles[i]); writeBlockEnd(stream, indent, "LEADER"); } static void writeLabel(FILE *stream, int indent, labelObj *label) { int i; colorObj c; if(label->size == -1) return; /* there is no default label anymore */ indent++; writeBlockBegin(stream, indent, "LABEL"); /* ** a few attributes are bitmap or truetype only */ if(label->type == MS_BITMAP) { writeKeyword(stream, indent, "SIZE", (int)label->size, 5, MS_TINY, "TINY", MS_SMALL, "SMALL", MS_MEDIUM, "MEDIUM", MS_LARGE, "LARGE", MS_GIANT, "GIANT"); } else { if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_ANGLE].item) writeAttributeBinding(stream, indent, "ANGLE", &(label->bindings[MS_LABEL_BINDING_ANGLE])); else writeNumberOrKeyword(stream, indent, "ANGLE", 0, label->angle, label->anglemode, 3, MS_FOLLOW, "FOLLOW", MS_AUTO, "AUTO", MS_AUTO2, "AUTO2"); writeKeyword(stream, indent, "ANTIALIAS", label->antialias, 1, MS_TRUE, "TRUE"); writeExpression(stream, indent, "EXPRESSION", &(label->expression)); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_FONT].item) writeAttributeBinding(stream, indent, "FONT", &(label->bindings[MS_LABEL_BINDING_FONT])); else writeString(stream, indent, "FONT", NULL, label->font); writeNumber(stream, indent, "MAXSIZE", MS_MAXFONTSIZE, label->maxsize); writeNumber(stream, indent, "MINSIZE", MS_MINFONTSIZE, label->minsize); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_SIZE].item) writeAttributeBinding(stream, indent, "SIZE", &(label->bindings[MS_LABEL_BINDING_SIZE])); else writeNumber(stream, indent, "SIZE", -1, label->size); } writeKeyword(stream, indent, "ALIGN", label->align, 2, MS_ALIGN_CENTER, "CENTER", MS_ALIGN_RIGHT, "RIGHT"); writeNumber(stream, indent, "BUFFER", 0, label->buffer); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_COLOR].item) writeAttributeBinding(stream, indent, "COLOR", &(label->bindings[MS_LABEL_BINDING_COLOR])); else { MS_INIT_COLOR(c,0,0,0,255); writeColor(stream, indent, "COLOR", &c, &(label->color)); } writeString(stream, indent, "ENCODING", NULL, label->encoding); writeLeader(stream,indent,&(label->leader)); writeKeyword(stream, indent, "FORCE", label->force, 2, MS_TRUE, "TRUE", MS_LABEL_FORCE_GROUP, "GROUP"); writeNumber(stream, indent, "MAXLENGTH", 0, label->maxlength); writeNumber(stream, indent, "MAXSCALEDENOM", -1, label->maxscaledenom); writeNumber(stream, indent, "MINDISTANCE", -1, label->mindistance); writeNumberOrKeyword(stream, indent, "MINFEATURESIZE", -1, label->minfeaturesize, 1, label->autominfeaturesize, MS_TRUE, "AUTO"); writeNumber(stream, indent, "MINLENGTH", 0, label->minlength); writeNumber(stream, indent, "MINSCALEDENOM", -1, label->minscaledenom); writeDimension(stream, indent, "OFFSET", label->offsetx, label->offsety, NULL, NULL); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].item) writeAttributeBinding(stream, indent, "OUTLINECOLOR", &(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR])); else writeColor(stream, indent, "OUTLINECOLOR", NULL, &(label->outlinecolor)); writeNumber(stream, indent, "OUTLINEWIDTH", 1, label->outlinewidth); writeKeyword(stream, indent, "PARTIALS", label->partials, 1, MS_FALSE, "FALSE"); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_POSITION].item) writeAttributeBinding(stream, indent, "POSITION", &(label->bindings[MS_LABEL_BINDING_POSITION])); else writeKeyword(stream, indent, "POSITION", label->position, 10, MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR", MS_AUTO, "AUTO"); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_PRIORITY].item) writeAttributeBinding(stream, indent, "PRIORITY", &(label->bindings[MS_LABEL_BINDING_PRIORITY])); else writeNumber(stream, indent, "PRIORITY", MS_DEFAULT_LABEL_PRIORITY, label->priority); writeNumber(stream, indent, "REPEATDISTANCE", 0, label->repeatdistance); writeColor(stream, indent, "SHADOWCOLOR", NULL, &(label->shadowcolor)); writeDimension(stream, indent, "SHADOWSIZE", label->shadowsizex, label->shadowsizey, label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item, label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item); writeNumber(stream, indent, "MAXOVERLAPANGLE", 22.5, label->maxoverlapangle); for(i=0; inumstyles; i++) writeStyle(stream, indent, label->styles[i]); writeExpression(stream, indent, "TEXT", &(label->text)); writeKeyword(stream, indent, "TYPE", label->type, 2, MS_BITMAP, "BITMAP", MS_TRUETYPE, "TRUETYPE"); writeCharacter(stream, indent, "WRAP", '\0', label->wrap); writeBlockEnd(stream, indent, "LABEL"); } char* msWriteLabelToString(labelObj *label) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeLabel(stdout, -1, label); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } void initExpression(expressionObj *exp) { exp->type = MS_STRING; exp->string = NULL; exp->compiled = MS_FALSE; exp->flags = 0; exp->tokens = exp->curtoken = NULL; } void freeExpressionTokens(expressionObj *exp) { tokenListNodeObjPtr node = NULL; tokenListNodeObjPtr nextNode = NULL; if(!exp) return; if(exp->tokens) { node = exp->tokens; while (node != NULL) { nextNode = node->next; switch(node->token) { case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: case MS_TOKEN_BINDING_TIME: msFree(node->tokenval.bindval.item); break; case MS_TOKEN_LITERAL_TIME: /* anything to do? */ break; case MS_TOKEN_LITERAL_STRING: msFree(node->tokenval.strval); break; case MS_TOKEN_LITERAL_SHAPE: msFreeShape(node->tokenval.shpval); free(node->tokenval.shpval); break; } msFree(node); node = nextNode; } exp->tokens = exp->curtoken = NULL; } } void freeExpression(expressionObj *exp) { if(!exp) return; msFree(exp->string); if((exp->type == MS_REGEX) && exp->compiled) ms_regfree(&(exp->regex)); freeExpressionTokens(exp); initExpression(exp); /* re-initialize */ } int loadExpression(expressionObj *exp) { /* TODO: should we fall freeExpression if exp->string != NULL? We do some checking to avoid a leak but is it enough... */ msyystring_icase = MS_TRUE; if((exp->type = getSymbol(6, MS_STRING,MS_EXPRESSION,MS_REGEX,MS_ISTRING,MS_IREGEX,MS_LIST)) == -1) return(-1); if (exp->string != NULL) msFree(exp->string); exp->string = msStrdup(msyystring_buffer); if(exp->type == MS_ISTRING) { exp->flags = exp->flags | MS_EXP_INSENSITIVE; exp->type = MS_STRING; } else if(exp->type == MS_IREGEX) { exp->flags = exp->flags | MS_EXP_INSENSITIVE; exp->type = MS_REGEX; } return(0); } /* --------------------------------------------------------------------------- msLoadExpressionString and loadExpressionString msLoadExpressionString wraps call to loadExpressionString with mutex acquisition and release. This function should be used everywhere outside the mapfile loading phase of an application. loadExpressionString does not check for a mutex! It should be used only within code that has properly acquired a mutex. See bug 339 for more details -- SG. ------------------------------------------------------------------------ */ int msLoadExpressionString(expressionObj *exp, char *value) { int retval = MS_FAILURE; msAcquireLock( TLOCK_PARSER ); retval = loadExpressionString( exp, value ); msReleaseLock( TLOCK_PARSER ); return retval; } int loadExpressionString(expressionObj *exp, char *value) { msyystate = MS_TOKENIZE_STRING; msyystring = value; msyylex(); /* sets things up but processes no tokens */ freeExpression(exp); /* we're totally replacing the old expression so free (which re-inits) to start over */ msyystring_icase = MS_TRUE; if((exp->type = getSymbol2(5, MS_EXPRESSION,MS_REGEX,MS_IREGEX,MS_ISTRING,MS_LIST)) != -1) { exp->string = msStrdup(msyystring_buffer); if(exp->type == MS_ISTRING) { exp->type = MS_STRING; exp->flags = exp->flags | MS_EXP_INSENSITIVE; } else if(exp->type == MS_IREGEX) { exp->type = MS_REGEX; exp->flags = exp->flags | MS_EXP_INSENSITIVE; } } else { /* failure above is not an error since we'll consider anything not matching (like an unquoted number) as a STRING) */ exp->type = MS_STRING; if((strlen(value) - strlen(msyystring_buffer)) == 2) exp->string = msStrdup(msyystring_buffer); /* value was quoted */ else exp->string = msStrdup(value); /* use the whole value */ } return(0); } /* msGetExpressionString() * * Returns the string representation of this expression, including delimiters * and any flags (e.g. i = case-insensitive). * * Returns a newly allocated buffer that should be freed by the caller or NULL. */ char *msGetExpressionString(expressionObj *exp) { if(exp->string) { char *exprstring; size_t buffer_size; const char *case_insensitive = ""; if(exp->flags & MS_EXP_INSENSITIVE) case_insensitive = "i"; /* Alloc buffer big enough for string + 2 delimiters + 'i' + \0 */ buffer_size = strlen(exp->string)+4; exprstring = (char*)msSmallMalloc(buffer_size); switch(exp->type) { case(MS_REGEX): snprintf(exprstring, buffer_size, "/%s/%s", exp->string, case_insensitive); return exprstring; case(MS_STRING): snprintf(exprstring, buffer_size, "\"%s\"%s", exp->string, case_insensitive); return exprstring; case(MS_EXPRESSION): snprintf(exprstring, buffer_size, "(%s)", exp->string); return exprstring; case(MS_LIST): snprintf(exprstring, buffer_size, "{%s}", exp->string); return exprstring; default: /* We should never get to here really! */ free(exprstring); return NULL; } } return NULL; } static void writeExpression(FILE *stream, int indent, const char *name, expressionObj *exp) { char *string_tmp; if(!exp || !exp->string) return; writeIndent(stream, ++indent); switch(exp->type) { case(MS_LIST): fprintf(stream, "%s {%s}", name, exp->string); break; case(MS_REGEX): msIO_fprintf(stream, "%s /%s/", name, exp->string); break; case(MS_STRING): if ( (strchr(exp->string, '\'') == NULL) && (strchr(exp->string, '\"') == NULL)) msIO_fprintf(stream, "%s \"%s\"", name, exp->string); else if ( (strchr(exp->string, '\"') != NULL) && (strchr(exp->string, '\'') == NULL)) msIO_fprintf(stream, "%s \'%s\'", name, exp->string); else if ( (strchr(exp->string, '\'') != NULL) && (strchr(exp->string, '\"') == NULL)) msIO_fprintf(stream, "%s \"%s\"", name, exp->string); else { string_tmp = msStringEscape(exp->string); msIO_fprintf(stream, "%s \"%s\"", name, string_tmp); if(exp->string!=string_tmp) free(string_tmp); } break; case(MS_EXPRESSION): msIO_fprintf(stream, "%s (%s)", name, exp->string); break; } if((exp->type == MS_STRING || exp->type == MS_REGEX) && (exp->flags & MS_EXP_INSENSITIVE)) msIO_fprintf(stream, "i"); writeLineFeed(stream); } int loadHashTable(hashTableObj *ptable) { char *key=NULL, *data=NULL; if (!ptable) ptable = msCreateHashTable(); for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadHashTable()"); return(MS_FAILURE); case(END): return(MS_SUCCESS); case(MS_STRING): key = msStrdup(msyystring_buffer); /* the key is *always* a string */ if(getString(&data) == MS_FAILURE) return(MS_FAILURE); msInsertHashTable(ptable, key, data); free(key); free(data); data=NULL; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadHashTable()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } return(MS_SUCCESS); } static void writeHashTable(FILE *stream, int indent, const char *title, hashTableObj *table) { struct hashObj *tp; int i; if(!table) return; if(msHashIsEmpty(table)) return; indent++; writeBlockBegin(stream, indent, title); for (i=0; iitems[i] != NULL) { for (tp=table->items[i]; tp!=NULL; tp=tp->next) writeNameValuePair(stream, indent, tp->key, tp->data); } } writeBlockEnd(stream, indent, title); } static void writeHashTableInline(FILE *stream, int indent, char *name, hashTableObj* table) { struct hashObj *tp = NULL; int i; if(!table) return; if(msHashIsEmpty(table)) return; ++indent; for (i=0; iitems[i] != NULL) { for (tp=table->items[i]; tp!=NULL; tp=tp->next) { writeIndent(stream, indent); msIO_fprintf(stream, "%s \"%s\" \"%s\"\n", name, tp->key, tp->data); } } } } /* ** Initialize, load and free a cluster object */ void initCluster(clusterObj *cluster) { cluster->maxdistance = 10; cluster->buffer = 0; cluster->region = NULL; initExpression(&(cluster->group)); initExpression(&(cluster->filter)); } void freeCluster(clusterObj *cluster) { msFree(cluster->region); freeExpression(&(cluster->group)); freeExpression(&(cluster->filter)); } int loadCluster(clusterObj *cluster) { for(;;) { switch(msyylex()) { case(CLUSTER): break; /* for string loads */ case(MAXDISTANCE): if(getDouble(&(cluster->maxdistance)) == -1) return(-1); break; case(BUFFER): if(getDouble(&(cluster->buffer)) == -1) return(-1); break; case(REGION): if(getString(&cluster->region) == MS_FAILURE) return(-1); break; case(END): return(0); break; case(GROUP): if(loadExpression(&(cluster->group)) == -1) return(-1); break; case(FILTER): if(loadExpression(&(cluster->filter)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadCluster()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } return(MS_SUCCESS); } int msUpdateClusterFromString(clusterObj *cluster, char *string) { if(!cluster || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadCluster(cluster) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeCluster(FILE *stream, int indent, clusterObj *cluster) { if (cluster->maxdistance == 10 && cluster->buffer == 0.0 && cluster->region == NULL && cluster->group.string == NULL && cluster->filter.string == NULL) return; /* Nothing to write */ indent++; writeBlockBegin(stream, indent, "CLUSTER"); writeNumber(stream, indent, "MAXDISTANCE", 10, cluster->maxdistance); writeNumber(stream, indent, "BUFFER", 0, cluster->buffer); writeString(stream, indent, "REGION", NULL, cluster->region); writeExpression(stream, indent, "GROUP", &(cluster->group)); writeExpression(stream, indent, "FILTER", &(cluster->filter)); writeBlockEnd(stream, indent, "CLUSTER"); } char* msWriteClusterToString(clusterObj *cluster) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeCluster(stdout, -1, cluster); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a single style */ int initStyle(styleObj *style) { int i; MS_REFCNT_INIT(style); MS_INIT_COLOR(style->color, -1,-1,-1,255); /* must explictly set colors */ MS_INIT_COLOR(style->backgroundcolor, -1,-1,-1,255); MS_INIT_COLOR(style->outlinecolor, -1,-1,-1,255); /* New Color Range fields*/ MS_INIT_COLOR(style->mincolor, -1,-1,-1,255); MS_INIT_COLOR(style->maxcolor, -1,-1,-1,255); style->minvalue = 0.0; style->maxvalue = 1.0; style->rangeitem = NULL; /* End Color Range fields*/ style->symbol = 0; /* there is always a default symbol*/ style->symbolname = NULL; style->size = -1; /* in SIZEUNITS (layerObj) */ style->minsize = MS_MINSYMBOLSIZE; style->maxsize = MS_MAXSYMBOLSIZE; style->width = 1; /* in pixels */ style->outlinewidth = 0; /* in pixels */ style->minwidth = MS_MINSYMBOLWIDTH; style->maxwidth = MS_MAXSYMBOLWIDTH; style->minscaledenom=style->maxscaledenom = -1.0; style->offsetx = style->offsety = 0; /* no offset */ style->polaroffsetpixel = style->polaroffsetangle = 0; /* no polar offset */ style->antialias = MS_FALSE; style->angle = 0; style->autoangle= MS_FALSE; style->opacity = 100; /* fully opaque */ initExpression(&(style->_geomtransform)); style->_geomtransform.type = MS_GEOMTRANSFORM_NONE; style->patternlength = 0; /* solid line */ style->gap = 0; style->initialgap = -1; style->position = MS_CC; style->linecap = MS_CJC_DEFAULT_CAPS; style->linejoin = MS_CJC_DEFAULT_JOINS; style->linejoinmaxsize = MS_CJC_DEFAULT_JOIN_MAXSIZE; style->numbindings = 0; for(i=0; ibindings[i].item = NULL; style->bindings[i].index = -1; } return MS_SUCCESS; } int loadStyle(styleObj *style) { int symbol; for(;;) { switch(msyylex()) { /* New Color Range fields*/ case (COLORRANGE): /*These are both in one line now*/ if(loadColor(&(style->mincolor), NULL) != MS_SUCCESS) return(MS_FAILURE); if(loadColor(&(style->maxcolor), NULL) != MS_SUCCESS) return(MS_FAILURE); break; case(DATARANGE): /*These are both in one line now*/ if(getDouble(&(style->minvalue)) == -1) return(-1); if(getDouble(&(style->maxvalue)) == -1) return(-1); break; case(RANGEITEM): if(getString(&style->rangeitem) == MS_FAILURE) return(-1); break; /* End Range fields*/ case(ANGLE): if((symbol = getSymbol(3, MS_NUMBER,MS_BINDING,MS_AUTO)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->angle = (double) msyynumber; else if(symbol==MS_BINDING) { if (style->bindings[MS_STYLE_BINDING_ANGLE].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_ANGLE].item); style->bindings[MS_STYLE_BINDING_ANGLE].item = msStrdup(msyystring_buffer); style->numbindings++; } else { style->autoangle=MS_TRUE; } break; case(ANTIALIAS): if((style->antialias = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(MS_FAILURE); break; case(BACKGROUNDCOLOR): if(loadColor(&(style->backgroundcolor), NULL) != MS_SUCCESS) return(MS_FAILURE); break; case(COLOR): if(loadColor(&(style->color), &(style->bindings[MS_STYLE_BINDING_COLOR])) != MS_SUCCESS) return(MS_FAILURE); if(style->bindings[MS_STYLE_BINDING_COLOR].item) style->numbindings++; break; case(EOF): msSetError(MS_EOFERR, NULL, "loadStyle()"); return(MS_FAILURE); /* missing END (probably) */ case(END): { int alpha; /* apply opacity as the alpha channel color(s) */ if(style->opacity < 100) { alpha = MS_NINT(style->opacity*2.55); style->color.alpha = alpha; style->outlinecolor.alpha = alpha; style->backgroundcolor.alpha = alpha; style->mincolor.alpha = alpha; style->maxcolor.alpha = alpha; } return(MS_SUCCESS); } break; case(GAP): if((getDouble(&style->gap)) == -1) return(MS_FAILURE); break; case(INITIALGAP): if((getDouble(&style->initialgap)) == -1) return(MS_FAILURE); if(style->initialgap < 0) { msSetError(MS_MISCERR, "INITIALGAP requires a positive values", "loadStyle()"); return(MS_FAILURE); } break; case(MAXSCALEDENOM): if(getDouble(&(style->maxscaledenom)) == -1) return(MS_FAILURE); break; case(MINSCALEDENOM): if(getDouble(&(style->minscaledenom)) == -1) return(MS_FAILURE); break; case(GEOMTRANSFORM): { int s; if((s = getSymbol(2, MS_STRING, MS_EXPRESSION)) == -1) return(MS_FAILURE); if(s == MS_STRING) msStyleSetGeomTransform(style, msyystring_buffer); else { /* handle expression case here for the moment */ msFree(style->_geomtransform.string); style->_geomtransform.string = msStrdup(msyystring_buffer); style->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } } break; case(LINECAP): if((style->linecap = getSymbol(4,MS_CJC_BUTT, MS_CJC_ROUND, MS_CJC_SQUARE, MS_CJC_TRIANGLE)) == -1) return(MS_FAILURE); break; case(LINEJOIN): if((style->linejoin = getSymbol(4,MS_CJC_NONE, MS_CJC_ROUND, MS_CJC_MITER, MS_CJC_BEVEL)) == -1) return(MS_FAILURE); break; case(LINEJOINMAXSIZE): if((getDouble(&style->linejoinmaxsize)) == -1) return(MS_FAILURE); break; case(MAXSIZE): if(getDouble(&(style->maxsize)) == -1) return(MS_FAILURE); break; case(MINSIZE): if(getDouble(&(style->minsize)) == -1) return(MS_FAILURE); break; case(MAXWIDTH): if(getDouble(&(style->maxwidth)) == -1) return(MS_FAILURE); break; case(MINWIDTH): if(getDouble(&(style->minwidth)) == -1) return(MS_FAILURE); break; case(OFFSET): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->offsetx = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_OFFSET_X].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OFFSET_X].item); style->bindings[MS_STYLE_BINDING_OFFSET_X].item = msStrdup(msyystring_buffer); style->numbindings++; } if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->offsety = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_OFFSET_Y].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OFFSET_Y].item); style->bindings[MS_STYLE_BINDING_OFFSET_Y].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(OPACITY): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->opacity = MS_MAX(MS_MIN((int) msyynumber, 100), 0); /* force opacity to between 0 and 100 */ else { if (style->bindings[MS_STYLE_BINDING_OPACITY].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OPACITY].item); style->bindings[MS_STYLE_BINDING_OPACITY].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(OUTLINECOLOR): if(loadColor(&(style->outlinecolor), &(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR])) != MS_SUCCESS) return(MS_FAILURE); if(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].item) style->numbindings++; break; case(PATTERN): { int done = MS_FALSE; for(;;) { /* read till the next END */ switch(msyylex()) { case(END): if(style->patternlength < 2) { msSetError(MS_SYMERR, "Not enough pattern elements. A minimum of 2 are required", "loadStyle()"); return(MS_FAILURE); } done = MS_TRUE; break; case(MS_NUMBER): /* read the pattern values */ if(style->patternlength == MS_MAXPATTERNLENGTH) { msSetError(MS_SYMERR, "Pattern too long.", "loadStyle()"); return(-1); } style->pattern[style->patternlength] = atof(msyystring_buffer); style->patternlength++; break; default: msSetError(MS_TYPEERR, "Parsing error near (%s):(line %d)", "loadStyle()", msyystring_buffer, msyylineno); return(-1); } if(done == MS_TRUE) break; } break; } case(POSITION): /* if((s->position = getSymbol(3, MS_UC,MS_CC,MS_LC)) == -1) */ /* return(-1); */ if((style->position = getSymbol(9, MS_UL,MS_UC,MS_UR,MS_CL,MS_CC,MS_CR,MS_LL,MS_LC,MS_LR)) == -1) return(-1); break; case(OUTLINEWIDTH): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) { style->outlinewidth = (double) msyynumber; if(style->outlinewidth < 0) { msSetError(MS_MISCERR, "Invalid OUTLINEWIDTH, must be greater than 0" , "loadStyle()"); return(MS_FAILURE); } } else { if (style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item); style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(SIZE): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->size = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_SIZE].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_SIZE].item); style->bindings[MS_STYLE_BINDING_SIZE].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(STYLE): break; /* for string loads */ case(SYMBOL): if((symbol = getSymbol(3, MS_NUMBER,MS_STRING,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) { if (style->symbolname != NULL) { msFree(style->symbolname); style->symbolname = NULL; } style->symbol = (int) msyynumber; } else if(symbol == MS_STRING) { if (style->symbolname != NULL) msFree(style->symbolname); style->symbolname = msStrdup(msyystring_buffer); } else { if (style->bindings[MS_STYLE_BINDING_SYMBOL].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_SYMBOL].item); style->bindings[MS_STYLE_BINDING_SYMBOL].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(WIDTH): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->width = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_WIDTH].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_WIDTH].item); style->bindings[MS_STYLE_BINDING_WIDTH].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(POLAROFFSET): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->polaroffsetpixel = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item); style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item = msStrdup(msyystring_buffer); style->numbindings++; } if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->polaroffsetangle = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item); style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item = msStrdup(msyystring_buffer); style->numbindings++; } break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadStyle()", msyystring_buffer, msyylineno); return(MS_FAILURE); } else { return(MS_SUCCESS); /* end of a string, not an error */ } } } } int msUpdateStyleFromString(styleObj *style, char *string, int url_string) { if(!style || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadStyle(style) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } int freeStyle(styleObj *style) { int i; if( MS_REFCNT_DECR_IS_NOT_ZERO(style) ) { return MS_FAILURE; } msFree(style->symbolname); freeExpression(&style->_geomtransform); msFree(style->rangeitem); for(i=0; ibindings[i].item); return MS_SUCCESS; } void writeStyle(FILE *stream, int indent, styleObj *style) { indent++; writeBlockBegin(stream, indent, "STYLE"); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_ANGLE].item) writeAttributeBinding(stream, indent, "ANGLE", &(style->bindings[MS_STYLE_BINDING_ANGLE])); else writeNumberOrKeyword(stream, indent, "ANGLE", 0, style->angle, style->autoangle, 1, MS_TRUE, "AUTO"); writeKeyword(stream, indent, "ANTIALIAS", style->antialias, 1, MS_TRUE, "TRUE"); writeColor(stream, indent, "BACKGROUNDCOLOR", NULL, &(style->backgroundcolor)); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_COLOR].item) writeAttributeBinding(stream, indent, "COLOR", &(style->bindings[MS_STYLE_BINDING_COLOR])); else writeColor(stream, indent, "COLOR", NULL, &(style->color)); writeNumber(stream, indent, "GAP", 0, style->gap); writeNumber(stream, indent, "INITIALGAP", -1, style->initialgap); if(style->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) { writeIndent(stream, indent + 1); msIO_fprintf(stream, "GEOMTRANSFORM (%s)\n", style->_geomtransform.string); } else if(style->_geomtransform.type != MS_GEOMTRANSFORM_NONE) { writeKeyword(stream, indent, "GEOMTRANSFORM", style->_geomtransform.type, 7, MS_GEOMTRANSFORM_BBOX, "\"bbox\"", MS_GEOMTRANSFORM_END, "\"end\"", MS_GEOMTRANSFORM_LABELPOINT, "\"labelpnt\"", MS_GEOMTRANSFORM_LABELPOLY, "\"labelpoly\"", MS_GEOMTRANSFORM_START, "\"start\"", MS_GEOMTRANSFORM_VERTICES, "\"vertices\"", MS_GEOMTRANSFORM_CENTROID, "\"centroid\"" ); } if(style->linecap != MS_CJC_DEFAULT_CAPS) { writeKeyword(stream,indent,"LINECAP",(int)style->linecap,5, MS_CJC_NONE,"NONE", MS_CJC_ROUND, "ROUND", MS_CJC_SQUARE, "SQUARE", MS_CJC_BUTT, "BUTT", MS_CJC_TRIANGLE, "TRIANGLE"); } if(style->linejoin != MS_CJC_DEFAULT_JOINS) { writeKeyword(stream,indent,"LINEJOIN",(int)style->linejoin,5, MS_CJC_NONE,"NONE", MS_CJC_ROUND, "ROUND", MS_CJC_BEVEL, "BEVEL", MS_CJC_MITER, "MITER"); } writeNumber(stream, indent, "LINEJOINMAXSIZE", MS_CJC_DEFAULT_JOIN_MAXSIZE , style->linejoinmaxsize); writeNumber(stream, indent, "MAXSCALEDENOM", -1, style->maxscaledenom); writeNumber(stream, indent, "MAXSIZE", MS_MAXSYMBOLSIZE, style->maxsize); writeNumber(stream, indent, "MAXWIDTH", MS_MAXSYMBOLWIDTH, style->maxwidth); writeNumber(stream, indent, "MINSCALEDENOM", -1, style->minscaledenom); writeNumber(stream, indent, "MINSIZE", MS_MINSYMBOLSIZE, style->minsize); writeNumber(stream, indent, "MINWIDTH", MS_MINSYMBOLWIDTH, style->minwidth); if((style->numbindings > 0 && (style->bindings[MS_STYLE_BINDING_OFFSET_X].item||style->bindings[MS_STYLE_BINDING_OFFSET_Y].item))||style->offsetx!=0||style->offsety!=0) writeDimension(stream, indent, "OFFSET", style->offsetx, style->offsety, style->bindings[MS_STYLE_BINDING_OFFSET_X].item, style->bindings[MS_STYLE_BINDING_OFFSET_Y].item); if((style->numbindings > 0 && (style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item||style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item))||style->polaroffsetangle!=0||style->polaroffsetpixel!=0) writeDimension(stream, indent, "POLAROFFSET", style->polaroffsetpixel, style->polaroffsetangle, style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item, style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_OPACITY].item) writeAttributeBinding(stream, indent, "OPACITY", &(style->bindings[MS_STYLE_BINDING_OPACITY])); else writeNumber(stream, indent, "OPACITY", 100, style->opacity); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].item) writeAttributeBinding(stream, indent, "OUTLINECOLOR", &(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR])); else writeColor(stream, indent, "OUTLINECOLOR", NULL, &(style->outlinecolor)); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item) writeAttributeBinding(stream, indent, "OUTLINEWIDTH", &(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH])); else writeNumber(stream, indent, "OUTLINEWIDTH", 0, style->outlinewidth); /* PATTERN */ if(style->patternlength != 0) { int i; indent++; writeBlockBegin(stream,indent,"PATTERN"); writeIndent(stream, indent); for(i=0; ipatternlength; i++) msIO_fprintf(stream, " %.2f", style->pattern[i]); msIO_fprintf(stream,"\n"); writeBlockEnd(stream,indent,"PATTERN"); indent--; } if(style->position != MS_CC) { writeKeyword(stream, indent, "POSITION", style->position, 9, MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR"); } if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_SIZE].item) writeAttributeBinding(stream, indent, "SIZE", &(style->bindings[MS_STYLE_BINDING_SIZE])); else writeNumber(stream, indent, "SIZE", -1, style->size); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_SYMBOL].item) writeAttributeBinding(stream, indent, "SYMBOL", &(style->bindings[MS_STYLE_BINDING_SYMBOL])); else writeNumberOrString(stream, indent, "SYMBOL", 0, style->symbol, style->symbolname); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_WIDTH].item) writeAttributeBinding(stream, indent, "WIDTH", &(style->bindings[MS_STYLE_BINDING_WIDTH])); else writeNumber(stream, indent, "WIDTH", 1, style->width); if(style->rangeitem) { writeString(stream, indent, "RANGEITEM", NULL, style->rangeitem); writeColorRange(stream, indent, "COLORRANGE", &(style->mincolor), &(style->maxcolor)); writeDimension(stream, indent, "DATARANGE", style->minvalue, style->maxvalue, NULL, NULL); } writeBlockEnd(stream, indent, "STYLE"); } char* msWriteStyleToString(styleObj *style) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeStyle(stdout, -1, style); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a single class */ int initClass(classObj *class) { class->status = MS_ON; class->debug = MS_OFF; MS_REFCNT_INIT(class); initExpression(&(class->expression)); class->name = NULL; class->title = NULL; initExpression(&(class->text)); class->template = NULL; class->type = -1; initHashTable(&(class->metadata)); initHashTable(&(class->validation)); class->maxscaledenom = class->minscaledenom = -1.0; class->minfeaturesize = -1; /* no limit */ /* Set maxstyles = 0, styles[] will be allocated as needed on first call * to msGrowClassStyles() */ class->numstyles = class->maxstyles = 0; class->styles = NULL; class->numlabels = class->maxlabels = 0; class->labels = NULL; class->keyimage = NULL; class->group = NULL; initLeader(&(class->leader)); return(0); } int freeClass(classObj *class) { int i; if( MS_REFCNT_DECR_IS_NOT_ZERO(class) ) { return MS_FAILURE; } freeExpression(&(class->expression)); freeExpression(&(class->text)); msFree(class->name); msFree(class->title); msFree(class->template); msFree(class->group); if (&(class->metadata)) msFreeHashItems(&(class->metadata)); if (&(class->validation)) msFreeHashItems(&(class->validation)); for(i=0; inumstyles; i++) { /* each style */ if(class->styles[i]!=NULL) { if(freeStyle(class->styles[i]) == MS_SUCCESS) { msFree(class->styles[i]); } } } msFree(class->styles); for(i=0; inumlabels; i++) { /* each label */ if(class->labels[i]!=NULL) { if(freeLabel(class->labels[i]) == MS_SUCCESS) { msFree(class->labels[i]); } } } msFree(class->labels); msFree(class->keyimage); freeLabelLeader(&(class->leader)); return MS_SUCCESS; } /* ** Ensure there is at least one free entry in the sttyles array of this ** classObj. Grow the allocated styles array if necessary and allocate ** a new style for styles[numstyles] if there is not already one, ** setting its contents to all zero bytes (i.e. does not call initStyle() ** on it). ** ** This function is safe to use for the initial allocation of the styles[] ** array as well (i.e. when maxstyles==0 and styles==NULL) ** ** Returns a reference to the new styleObj on success, NULL on error. */ styleObj *msGrowClassStyles( classObj *class ) { /* Do we need to increase the size of styles[] by MS_STYLE_ALLOCSIZE? */ if (class->numstyles == class->maxstyles) { styleObj **newStylePtr; int i, newsize; newsize = class->maxstyles + MS_STYLE_ALLOCSIZE; /* Alloc/realloc styles */ newStylePtr = (styleObj**)realloc(class->styles, newsize*sizeof(styleObj*)); MS_CHECK_ALLOC(newStylePtr, newsize*sizeof(styleObj*), NULL); class->styles = newStylePtr; class->maxstyles = newsize; for(i=class->numstyles; imaxstyles; i++) { class->styles[i] = NULL; } } if (class->styles[class->numstyles]==NULL) { class->styles[class->numstyles]=(styleObj*)calloc(1,sizeof(styleObj)); MS_CHECK_ALLOC(class->styles[class->numstyles], sizeof(styleObj), NULL); } return class->styles[class->numstyles]; } /* exactly the same as for a classObj */ styleObj *msGrowLabelStyles( labelObj *label ) { /* Do we need to increase the size of styles[] by MS_STYLE_ALLOCSIZE? */ if (label->numstyles == label->maxstyles) { styleObj **newStylePtr; int i, newsize; newsize = label->maxstyles + MS_STYLE_ALLOCSIZE; /* Alloc/realloc styles */ newStylePtr = (styleObj**)realloc(label->styles, newsize*sizeof(styleObj*)); MS_CHECK_ALLOC(newStylePtr, newsize*sizeof(styleObj*), NULL); label->styles = newStylePtr; label->maxstyles = newsize; for(i=label->numstyles; imaxstyles; i++) { label->styles[i] = NULL; } } if (label->styles[label->numstyles]==NULL) { label->styles[label->numstyles]=(styleObj*)calloc(1,sizeof(styleObj)); MS_CHECK_ALLOC(label->styles[label->numstyles], sizeof(styleObj), NULL); } return label->styles[label->numstyles]; } /* exactly the same as for a labelLeaderObj, needs refactoring */ styleObj *msGrowLeaderStyles( labelLeaderObj *leader ) { /* Do we need to increase the size of styles[] by MS_STYLE_ALLOCSIZE? */ if (leader->numstyles == leader->maxstyles) { styleObj **newStylePtr; int i, newsize; newsize = leader->maxstyles + MS_STYLE_ALLOCSIZE; /* Alloc/realloc styles */ newStylePtr = (styleObj**)realloc(leader->styles, newsize*sizeof(styleObj*)); MS_CHECK_ALLOC(newStylePtr, newsize*sizeof(styleObj*), NULL); leader->styles = newStylePtr; leader->maxstyles = newsize; for(i=leader->numstyles; imaxstyles; i++) { leader->styles[i] = NULL; } } if (leader->styles[leader->numstyles]==NULL) { leader->styles[leader->numstyles]=(styleObj*)calloc(1,sizeof(styleObj)); MS_CHECK_ALLOC(leader->styles[leader->numstyles], sizeof(styleObj), NULL); } return leader->styles[leader->numstyles]; } /* msMaybeAllocateClassStyle() ** ** Ensure that requested style index exists and has been initialized. ** ** Returns MS_SUCCESS/MS_FAILURE. */ int msMaybeAllocateClassStyle(classObj* c, int idx) { if (c==NULL) return MS_FAILURE; if ( idx < 0 ) { msSetError(MS_MISCERR, "Invalid style index: %d", "msMaybeAllocateClassStyle()", idx); return MS_FAILURE; } /* Alloc empty styles as needed up to idx. * Nothing to do if requested style already exists */ while(c->numstyles <= idx) { if (msGrowClassStyles(c) == NULL) return MS_FAILURE; if ( initStyle(c->styles[c->numstyles]) == MS_FAILURE ) { msSetError(MS_MISCERR, "Failed to init new styleObj", "msMaybeAllocateClassStyle()"); return(MS_FAILURE); } c->numstyles++; } return MS_SUCCESS; } /* * Reset style info in the class to defaults * the only members we don't touch are name, expression, and join/query stuff * This is used with STYLEITEM before overwriting the contents of a class. */ void resetClassStyle(classObj *class) { int i; /* reset labels */ for(i=0; inumlabels; i++) { if(class->styles[i] != NULL) { if(freeLabel(class->labels[i]) == MS_SUCCESS ) { msFree(class->labels[i]); } class->labels[i] = NULL; } } class->numlabels = 0; freeExpression(&(class->text)); initExpression(&(class->text)); /* reset styles */ for(i=0; inumstyles; i++) { if(class->styles[i] != NULL) { if( freeStyle(class->styles[i]) == MS_SUCCESS ) { msFree(class->styles[i]); } class->styles[i] = NULL; } } class->numstyles = 0; class->type = -1; class->layer = NULL; } labelObj *msGrowClassLabels( classObj *class ) { /* Do we need to increase the size of labels[] by MS_LABEL_ALLOCSIZE? */ if (class->numlabels == class->maxlabels) { labelObj **newLabelPtr; int i, newsize; newsize = class->maxlabels + MS_LABEL_ALLOCSIZE; /* Alloc/realloc labels */ newLabelPtr = (labelObj**)realloc(class->labels, newsize*sizeof(labelObj*)); MS_CHECK_ALLOC(newLabelPtr, newsize*sizeof(labelObj*), NULL); class->labels = newLabelPtr; class->maxlabels = newsize; for(i=class->numlabels; imaxlabels; i++) { class->labels[i] = NULL; } } if (class->labels[class->numlabels]==NULL) { class->labels[class->numlabels]=(labelObj*)calloc(1,sizeof(labelObj)); MS_CHECK_ALLOC(class->labels[class->numlabels], sizeof(labelObj), NULL); } return class->labels[class->numlabels]; } int loadClass(classObj *class, layerObj *layer) { int state; mapObj *map=NULL; class->layer = (layerObj *) layer; if(layer && layer->map) map = layer->map; for(;;) { switch(msyylex()) { case(CLASS): break; /* for string loads */ case(DEBUG): if((class->debug = getSymbol(3, MS_ON,MS_OFF, MS_NUMBER)) == -1) return(-1); if(class->debug == MS_NUMBER) class->debug = (int) msyynumber; break; case(EOF): msSetError(MS_EOFERR, NULL, "loadClass()"); return(-1); case(END): return(0); break; case(EXPRESSION): if(loadExpression(&(class->expression)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->expression.string, msLookupHashTable(&(class->validation), "expression"), msLookupHashTable(&(layer->validation), "expression"), msLookupHashTable(&(map->web.validation), "expression"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based EXPRESSION configuration failed pattern validation." , "loadClass()"); freeExpression(&(class->expression)); return(-1); } } break; case(GROUP): if(getString(&class->group) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->group, msLookupHashTable(&(class->validation), "group"), msLookupHashTable(&(layer->validation), "group"), msLookupHashTable(&(map->web.validation), "group"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based GROUP configuration failed pattern validation." , "loadClass()"); msFree(class->group); class->group=NULL; return(-1); } } break; case(KEYIMAGE): if(getString(&class->keyimage) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->keyimage, msLookupHashTable(&(class->validation), "keyimage"), msLookupHashTable(&(layer->validation), "keyimage"), msLookupHashTable(&(map->web.validation), "keyimage"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based KEYIMAGE configuration failed pattern validation." , "loadClass()"); msFree(class->keyimage); class->keyimage=NULL; return(-1); } } break; case(LABEL): if(msGrowClassLabels(class) == NULL) return(-1); initLabel(class->labels[class->numlabels]); class->labels[class->numlabels]->size = MS_MEDIUM; /* only set a default if the LABEL section is present */ if(loadLabel(class->labels[class->numlabels]) == -1) { msFree(class->labels[class->numlabels]); return(-1); } class->numlabels++; break; case(LEADER): if(loadLeader(&(class->leader)) == -1) return(-1); break; case(MAXSCALE): case(MAXSCALEDENOM): if(getDouble(&(class->maxscaledenom)) == -1) return(-1); break; case(METADATA): if(loadHashTable(&(class->metadata)) != MS_SUCCESS) return(-1); break; case(MINSCALE): case(MINSCALEDENOM): if(getDouble(&(class->minscaledenom)) == -1) return(-1); break; case(MINFEATURESIZE): if(getInteger(&(class->minfeaturesize)) == -1) return(-1); break; case(NAME): if(getString(&class->name) == MS_FAILURE) return(-1); break; case(STATUS): if((class->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(STYLE): if(msGrowClassStyles(class) == NULL) return(-1); initStyle(class->styles[class->numstyles]); if(loadStyle(class->styles[class->numstyles]) != MS_SUCCESS) return(-1); class->numstyles++; break; case(TEMPLATE): if(getString(&class->template) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->template, msLookupHashTable(&(class->validation), "template"), msLookupHashTable(&(layer->validation), "template"), msLookupHashTable(&(map->web.validation), "template"), map->templatepattern) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEMPLATE configuration failed pattern validation." , "loadClass()"); msFree(class->template); class->template=NULL; return(-1); } } break; case(TEXT): if(loadExpression(&(class->text)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->text.string, msLookupHashTable(&(class->validation), "text"), msLookupHashTable(&(layer->validation), "text"), msLookupHashTable(&(map->web.validation), "text"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEXT configuration failed pattern validation." , "loadClass()"); freeExpression(&(class->text)); return(-1); } } if((class->text.type != MS_STRING) && (class->text.type != MS_EXPRESSION)) { msSetError(MS_MISCERR, "Text expressions support constant or tagged replacement strings." , "loadClass()"); return(-1); } break; case(TITLE): if(getString(&class->title) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->title, msLookupHashTable(&(class->validation), "title"), msLookupHashTable(&(layer->validation), "title"), msLookupHashTable(&(map->web.validation), "title"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TITLE configuration failed pattern validation." , "loadClass()"); msFree(class->title); class->title=NULL; return(-1); } } break; case(TYPE): if((class->type = getSymbol(6, MS_LAYER_POINT,MS_LAYER_LINE,MS_LAYER_RASTER,MS_LAYER_POLYGON,MS_LAYER_ANNOTATION,MS_LAYER_CIRCLE)) == -1) return(-1); break; /* ** for backwards compatability, these are shortcuts for style 0 */ case(BACKGROUNDCOLOR): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(loadColor(&(class->styles[0]->backgroundcolor), NULL) != MS_SUCCESS) return(-1); break; case(COLOR): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(loadColor(&(class->styles[0]->color), NULL) != MS_SUCCESS) return(-1); class->numstyles = 1; /* must *always* set a color or outlinecolor */ break; case(MAXSIZE): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(getDouble(&(class->styles[0]->maxsize)) == -1) return(-1); break; case(MINSIZE): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(getDouble(&(class->styles[0]->minsize)) == -1) return(-1); break; case(OUTLINECOLOR): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(loadColor(&(class->styles[0]->outlinecolor), NULL) != MS_SUCCESS) return(-1); class->numstyles = 1; /* must *always* set a color, symbol or outlinecolor */ break; case(SIZE): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(getDouble(&(class->styles[0]->size)) == -1) return(-1); break; case(SYMBOL): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if((state = getSymbol(2, MS_NUMBER,MS_STRING)) == -1) return(-1); if(state == MS_NUMBER) class->styles[0]->symbol = (int) msyynumber; else { if (class->styles[0]->symbolname != NULL) msFree(class->styles[0]->symbolname); class->styles[0]->symbolname = msStrdup(msyystring_buffer); class->numstyles = 1; } break; /* ** for backwards compatability, these are shortcuts for style 1 */ case(OVERLAYBACKGROUNDCOLOR): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(loadColor(&(class->styles[1]->backgroundcolor), NULL) != MS_SUCCESS) return(-1); break; case(OVERLAYCOLOR): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(loadColor(&(class->styles[1]->color), NULL) != MS_SUCCESS) return(-1); class->numstyles = 2; /* must *always* set a color, symbol or outlinecolor */ break; case(OVERLAYMAXSIZE): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(getDouble(&(class->styles[1]->maxsize)) == -1) return(-1); break; case(OVERLAYMINSIZE): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(getDouble(&(class->styles[1]->minsize)) == -1) return(-1); break; case(OVERLAYOUTLINECOLOR): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(loadColor(&(class->styles[1]->outlinecolor), NULL) != MS_SUCCESS) return(-1); class->numstyles = 2; /* must *always* set a color, symbol or outlinecolor */ break; case(OVERLAYSIZE): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(getDouble(&(class->styles[1]->size)) == -1) return(-1); break; case(OVERLAYSYMBOL): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if((state = getSymbol(2, MS_NUMBER,MS_STRING)) == -1) return(-1); if(state == MS_NUMBER) class->styles[1]->symbol = (int) msyynumber; else { if (class->styles[1]->symbolname != NULL) msFree(class->styles[1]->symbolname); class->styles[1]->symbolname = msStrdup(msyystring_buffer); } class->numstyles = 2; break; case(VALIDATION): if(loadHashTable(&(class->validation)) != MS_SUCCESS) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadClass()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } static int classResolveSymbolNames(classObj *class) { int i,j; /* step through styles and labels to resolve symbol names */ /* class styles */ for(i=0; inumstyles; i++) { if(class->styles[i]->symbolname) { if((class->styles[i]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->styles[i]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class, style %d of layer %s.", "classResolveSymbolNames()", class->styles[i]->symbolname, i, class->layer->name); return MS_FAILURE; } } } /* label styles */ for(i=0; inumlabels; i++) { for(j=0; jlabels[i]->numstyles; j++) { if(class->labels[i]->styles[j]->symbolname) { if((class->labels[i]->styles[j]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->labels[i]->styles[j]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class, label style %d of layer %s.", "classResolveSymbolNames()", class->labels[i]->styles[j]->symbolname, j, class->layer->name); return MS_FAILURE; } } } } return MS_SUCCESS; } int msUpdateClassFromString(classObj *class, char *string, int url_string) { if(!class || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadClass(class, class->layer) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); if(classResolveSymbolNames(class) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } static void writeClass(FILE *stream, int indent, classObj *class) { int i; if(class->status == MS_DELETE) return; indent++; writeBlockBegin(stream, indent, "CLASS"); writeString(stream, indent, "NAME", NULL, class->name); writeString(stream, indent, "GROUP", NULL, class->group); writeNumber(stream, indent, "DEBUG", 0, class->debug); writeExpression(stream, indent, "EXPRESSION", &(class->expression)); writeString(stream, indent, "KEYIMAGE", NULL, class->keyimage); for(i=0; inumlabels; i++) writeLabel(stream, indent, class->labels[i]); writeLeader(stream,indent,&(class->leader)); writeNumber(stream, indent, "MAXSCALEDENOM", -1, class->maxscaledenom); writeHashTable(stream, indent, "METADATA", &(class->metadata)); writeNumber(stream, indent, "MINSCALEDENOM", -1, class->minscaledenom); writeNumber(stream, indent, "MINFEATURESIZE", -1, class->minfeaturesize); writeKeyword(stream, indent, "STATUS", class->status, 1, MS_OFF, "OFF"); for(i=0; inumstyles; i++) writeStyle(stream, indent, class->styles[i]); writeString(stream, indent, "TEMPLATE", NULL, class->template); writeExpression(stream, indent, "TEXT", &(class->text)); writeString(stream, indent, "TITLE", NULL, class->title); writeHashTable(stream, indent, "VALIDATION", &(class->validation)); writeBlockEnd(stream, indent, "CLASS"); } char* msWriteClassToString(classObj *class) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeClass(stdout, -1, class); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a single layer structure */ int initLayer(layerObj *layer, mapObj *map) { if (layer==NULL) { msSetError(MS_MEMERR, "Layer is null", "initLayer()"); return(-1); } layer->debug = (int)msGetGlobalDebugLevel(); MS_REFCNT_INIT(layer); /* Set maxclasses = 0, class[] will be allocated as needed on first call * to msGrowLayerClasses() */ layer->numclasses = 0; layer->maxclasses = 0; layer->class = NULL; layer->name = NULL; layer->group = NULL; layer->status = MS_OFF; layer->data = NULL; layer->map = map; /* point back to the encompassing structure */ layer->type = -1; layer->annotate = MS_FALSE; layer->toleranceunits = MS_PIXELS; layer->tolerance = -1; /* perhaps this should have a different value based on type */ layer->symbolscaledenom = -1.0; /* -1 means nothing is set */ layer->scalefactor = 1.0; layer->maxscaledenom = -1.0; layer->minscaledenom = -1.0; layer->minfeaturesize = -1; /* no limit */ layer->maxgeowidth = -1.0; layer->mingeowidth = -1.0; layer->sizeunits = MS_PIXELS; layer->maxfeatures = -1; /* no quota */ layer->startindex = -1; /*used for pagination*/ layer->scaletokens = NULL; layer->numscaletokens = 0; layer->template = layer->header = layer->footer = NULL; layer->transform = MS_TRUE; layer->classitem = NULL; layer->classitemindex = -1; layer->units = MS_METERS; if(msInitProjection(&(layer->projection)) == -1) return(-1); layer->project = MS_TRUE; initCluster(&layer->cluster); MS_INIT_COLOR(layer->offsite, -1,-1,-1, 255); layer->labelcache = MS_ON; layer->postlabelcache = MS_FALSE; layer->labelitem = NULL; layer->labelitemindex = -1; layer->labelmaxscaledenom = -1; layer->labelminscaledenom = -1; layer->tileitem = msStrdup("location"); layer->tileitemindex = -1; layer->tileindex = NULL; layer->tilesrs = NULL; layer->bandsitem = NULL; layer->bandsitemindex = -1; layer->currentfeature = layer->features = NULL; layer->connection = NULL; layer->plugin_library = NULL; layer->plugin_library_original = NULL; layer->connectiontype = MS_SHAPEFILE; layer->vtable = NULL; layer->classgroup = NULL; layer->layerinfo = NULL; layer->wfslayerinfo = NULL; layer->items = NULL; layer->iteminfo = NULL; layer->numitems = 0; layer->resultcache= NULL; initExpression(&(layer->filter)); layer->filteritem = NULL; layer->filteritemindex = -1; layer->requires = layer->labelrequires = NULL; initHashTable(&(layer->metadata)); initHashTable(&(layer->bindvals)); initHashTable(&(layer->validation)); layer->dump = MS_FALSE; layer->styleitem = NULL; layer->styleitemindex = -1; layer->opacity = 100; /* fully opaque */ layer->numprocessing = 0; layer->processing = NULL; layer->numjoins = 0; layer->joins = (joinObj *) malloc(MS_MAXJOINS*sizeof(joinObj)); MS_CHECK_ALLOC(layer->joins, MS_MAXJOINS*sizeof(joinObj), -1); layer->extent.minx = -1.0; layer->extent.miny = -1.0; layer->extent.maxx = -1.0; layer->extent.maxy = -1.0; layer->mask = NULL; layer->maskimage = NULL; initExpression(&(layer->_geomtransform)); layer->_geomtransform.type = MS_GEOMTRANSFORM_NONE; return(0); } int initScaleToken(scaleTokenObj* token) { token->n_entries = 0; token->name = NULL; token->tokens = NULL; return MS_SUCCESS; } int freeScaleTokenEntry( scaleTokenEntryObj *token) { msFree(token->value); return MS_SUCCESS; } int freeScaleToken(scaleTokenObj *scaletoken) { int i; msFree(scaletoken->name); for(i=0;in_entries;i++) { freeScaleTokenEntry(&scaletoken->tokens[i]); } msFree(scaletoken->tokens); return MS_SUCCESS; } int freeLayer(layerObj *layer) { int i; if (!layer) return MS_FAILURE; if( MS_REFCNT_DECR_IS_NOT_ZERO(layer) ) { return MS_FAILURE; } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("freeLayer(): freeing layer at %p.\n",layer); if(msLayerIsOpen(layer)) msLayerClose(layer); msFree(layer->name); msFree(layer->group); msFree(layer->data); msFree(layer->classitem); msFree(layer->labelitem); msFree(layer->header); msFree(layer->footer); msFree(layer->template); msFree(layer->tileindex); msFree(layer->tileitem); msFree(layer->tilesrs); msFree(layer->bandsitem); msFree(layer->plugin_library); msFree(layer->plugin_library_original); msFree(layer->connection); msFree(layer->vtable); msFree(layer->classgroup); msFreeProjection(&(layer->projection)); freeExpression(&layer->_geomtransform); freeCluster(&layer->cluster); for(i=0; imaxclasses; i++) { if (layer->class[i] != NULL) { layer->class[i]->layer=NULL; if ( freeClass(layer->class[i]) == MS_SUCCESS ) { msFree(layer->class[i]); } } } msFree(layer->class); if(layer->numscaletokens>0) { for(i=0;inumscaletokens;i++) { freeScaleToken(&layer->scaletokens[i]); } msFree(layer->scaletokens); } if(layer->features) freeFeatureList(layer->features); if(layer->resultcache) { if(layer->resultcache->results) free(layer->resultcache->results); msFree(layer->resultcache); } msFree(layer->styleitem); msFree(layer->filteritem); freeExpression(&(layer->filter)); msFree(layer->requires); msFree(layer->labelrequires); if(&(layer->metadata)) msFreeHashItems(&(layer->metadata)); if(&(layer->validation)) msFreeHashItems(&(layer->validation)); if(&(layer->bindvals)) msFreeHashItems(&layer->bindvals); if(layer->numprocessing > 0) msFreeCharArray(layer->processing, layer->numprocessing); for(i=0; inumjoins; i++) /* each join */ freeJoin(&(layer->joins[i])); msFree(layer->joins); layer->numjoins = 0; layer->classgroup = NULL; msFree(layer->mask); if(layer->maskimage) { msFreeImage(layer->maskimage); } return MS_SUCCESS; } /* ** Ensure there is at least one free entry in the class array of this ** layerObj. Grow the allocated class array if necessary and allocate ** a new class for class[numclasses] if there is not already one, ** setting its contents to all zero bytes (i.e. does not call initClass() ** on it). ** ** This function is safe to use for the initial allocation of the class[] ** array as well (i.e. when maxclasses==0 and class==NULL) ** ** Returns a reference to the new classObj on success, NULL on error. */ classObj *msGrowLayerClasses( layerObj *layer ) { /* Do we need to increase the size of class[] by MS_CLASS_ALLOCSIZE? */ if (layer->numclasses == layer->maxclasses) { classObj **newClassPtr; int i, newsize; newsize = layer->maxclasses + MS_CLASS_ALLOCSIZE; /* Alloc/realloc classes */ newClassPtr = (classObj**)realloc(layer->class, newsize*sizeof(classObj*)); MS_CHECK_ALLOC(newClassPtr, newsize*sizeof(classObj*), NULL); layer->class = newClassPtr; layer->maxclasses = newsize; for(i=layer->numclasses; imaxclasses; i++) { layer->class[i] = NULL; } } if (layer->class[layer->numclasses]==NULL) { layer->class[layer->numclasses]=(classObj*)calloc(1,sizeof(classObj)); MS_CHECK_ALLOC(layer->class[layer->numclasses], sizeof(classObj), NULL); } return layer->class[layer->numclasses]; } scaleTokenObj *msGrowLayerScaletokens( layerObj *layer ) { layer->scaletokens = msSmallRealloc(layer->scaletokens,(layer->numscaletokens+1)*sizeof(scaleTokenObj)); memset(&layer->scaletokens[layer->numscaletokens],0,sizeof(scaleTokenObj)); return &layer->scaletokens[layer->numscaletokens]; } int loadScaletoken(scaleTokenObj *token, layerObj *layer) { for(;;) { int stop = 0; switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadScaletoken()"); return(MS_FAILURE); case(NAME): if(getString(&token->name) == MS_FAILURE) return(MS_FAILURE); break; case(VALUES): for(;;) { if(stop) break; switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadScaletoken()"); return(MS_FAILURE); case(END): stop = 1; if(token->n_entries == 0) { msSetError(MS_PARSEERR,"Scaletoken (line:%d) has no VALUES defined","loadScaleToken()",msyylineno); return(MS_FAILURE); } token->tokens[token->n_entries-1].maxscale = DBL_MAX; break; case(MS_STRING): /* we have a key */ token->tokens = msSmallRealloc(token->tokens,(token->n_entries+1)*sizeof(scaleTokenEntryObj)); if(1 != sscanf(msyystring_buffer,"%lf",&token->tokens[token->n_entries].minscale)) { msSetError(MS_PARSEERR, "failed to parse SCALETOKEN VALUE (%s):(line %d), expecting \"minscale\"", "loadScaletoken()", msyystring_buffer,msyylineno); return(MS_FAILURE); } if(token->n_entries == 0) { /* check supplied value was 0*/ if(token->tokens[0].minscale != 0) { msSetError(MS_PARSEERR, "First SCALETOKEN VALUE (%s):(line %d) must be zero, expecting \"0\"", "loadScaletoken()", msyystring_buffer,msyylineno); return(MS_FAILURE); } } else { /* set max scale of previous token */ token->tokens[token->n_entries-1].maxscale = token->tokens[token->n_entries].minscale; } token->tokens[token->n_entries].value = NULL; if(getString(&(token->tokens[token->n_entries].value)) == MS_FAILURE) return(MS_FAILURE); token->n_entries++; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } break; case(END): if(!token->name || !*(token->name)) { msSetError(MS_PARSEERR,"ScaleToken missing mandatory NAME entry (line %d)","loadScaleToken()",msyylineno); return MS_FAILURE; } if(token->n_entries == 0) { msSetError(MS_PARSEERR,"ScaleToken missing at least one VALUES entry (line %d)","loadScaleToken()",msyylineno); return MS_FAILURE; } return MS_SUCCESS; default: msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } /* next token*/ } int loadLayer(layerObj *layer, mapObj *map) { int type; layer->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(BINDVALS): if(loadHashTable(&(layer->bindvals)) != MS_SUCCESS) return(-1); break; case(CLASS): if (msGrowLayerClasses(layer) == NULL) return(-1); initClass(layer->class[layer->numclasses]); if(loadClass(layer->class[layer->numclasses], layer) == -1) return(-1); if(layer->class[layer->numclasses]->type == -1) layer->class[layer->numclasses]->type = layer->type; layer->numclasses++; break; case(CLUSTER): initCluster(&layer->cluster); if(loadCluster(&layer->cluster) == -1) return(-1); break; case(CLASSGROUP): if(getString(&layer->classgroup) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->classgroup, msLookupHashTable(&(layer->validation), "classgroup"), msLookupHashTable(&(map->web.validation), "classgroup"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based CLASSGROUP configuration failed pattern validation." , "loadLayer()"); msFree(layer->classgroup); layer->classgroup=NULL; return(-1); } } break; case(CLASSITEM): if(getString(&layer->classitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->classitem, msLookupHashTable(&(layer->validation), "classitem"), msLookupHashTable(&(map->web.validation), "classitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based CLASSITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->classitem); layer->classitem=NULL; return(-1); } } break; case(CONNECTION): if(getString(&layer->connection) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->connection, msLookupHashTable(&(layer->validation), "connection"), msLookupHashTable(&(map->web.validation), "connection"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based CONNECTION configuration failed pattern validation." , "loadLayer()"); msFree(layer->connection); layer->connection=NULL; return(-1); } } break; case(CONNECTIONTYPE): if((layer->connectiontype = getSymbol(11, MS_SDE, MS_OGR, MS_POSTGIS, MS_WMS, MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_PLUGIN, MS_UNION, MS_UVRASTER, MS_CONTOUR)) == -1) return(-1); break; case(DATA): if(getString(&layer->data) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->data, msLookupHashTable(&(layer->validation), "data"), msLookupHashTable(&(map->web.validation), "data"), map->datapattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based DATA configuration failed pattern validation." , "loadLayer()"); msFree(layer->data); layer->data=NULL; return(-1); } } break; case(DEBUG): if((layer->debug = getSymbol(3, MS_ON,MS_OFF, MS_NUMBER)) == -1) return(-1); if(layer->debug == MS_NUMBER) layer->debug = (int) msyynumber; break; case(DUMP): if((layer->dump = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadLayer()"); return(-1); break; case(END): if(layer->type == -1) { msSetError(MS_MISCERR, "Layer type not set.", "loadLayer()"); return(-1); } return(0); break; case(EXTENT): { if(getDouble(&(layer->extent.minx)) == -1) return(-1); if(getDouble(&(layer->extent.miny)) == -1) return(-1); if(getDouble(&(layer->extent.maxx)) == -1) return(-1); if(getDouble(&(layer->extent.maxy)) == -1) return(-1); if (!MS_VALID_EXTENT(layer->extent)) { msSetError(MS_MISCERR, "Given layer extent is invalid. Check that it is in the form: minx, miny, maxx, maxy", "loadLayer()"); return(-1); } break; } case(FEATURE): if(layer->type == -1) { msSetError(MS_MISCERR, "Layer type must be set before defining inline features.", "loadLayer()"); return(-1); } if(layer->type == MS_LAYER_POLYGON) type = MS_SHAPE_POLYGON; else if(layer->type == MS_LAYER_LINE) type = MS_SHAPE_LINE; else type = MS_SHAPE_POINT; layer->connectiontype = MS_INLINE; if(loadFeature(layer, type) == MS_FAILURE) return(-1); break; case(FILTER): if(loadExpression(&(layer->filter)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->filter.string, msLookupHashTable(&(layer->validation), "filter"), msLookupHashTable(&(map->web.validation), "filter"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FILTER configuration failed pattern validation." , "loadLayer()"); freeExpression(&(layer->filter)); return(-1); } } break; case(FILTERITEM): if(getString(&layer->filteritem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->filteritem, msLookupHashTable(&(layer->validation), "filteritem"), msLookupHashTable(&(map->web.validation), "filteritem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FILTERITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->filteritem); layer->filteritem=NULL; return(-1); } } break; case(FOOTER): if(getString(&layer->footer) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->footer, msLookupHashTable(&(layer->validation), "footer"), msLookupHashTable(&(map->web.validation), "footer"), map->templatepattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FOOTER configuration failed pattern validation." , "loadLayer()"); msFree(layer->footer); layer->footer=NULL; return(-1); } } break; case(GRID): layer->connectiontype = MS_GRATICULE; layer->layerinfo = (void *) malloc(sizeof(graticuleObj)); MS_CHECK_ALLOC(layer->layerinfo, sizeof(graticuleObj), -1); initGrid((graticuleObj *) layer->layerinfo); loadGrid(layer); break; case(GROUP): if(getString(&layer->group) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->group, msLookupHashTable(&(layer->validation), "group"), msLookupHashTable(&(map->web.validation), "group"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based GROUP configuration failed pattern validation." , "loadLayer()"); msFree(layer->group); layer->group=NULL; return(-1); } } break; case(GEOMTRANSFORM): { int s; if((s = getSymbol(1, MS_EXPRESSION)) == -1) return(MS_FAILURE); /* handle expression case here for the moment */ msFree(layer->_geomtransform.string); layer->_geomtransform.string = msStrdup(msyystring_buffer); layer->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } break; case(HEADER): if(getString(&layer->header) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->header, msLookupHashTable(&(layer->validation), "header"), msLookupHashTable(&(map->web.validation), "header"), map->templatepattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based HEADER configuration failed pattern validation." , "loadLayer()"); msFree(layer->header); layer->header=NULL; return(-1); } } break; case(JOIN): if(layer->numjoins == MS_MAXJOINS) { /* no room */ msSetError(MS_IDENTERR, "Maximum number of joins reached.", "loadLayer()"); return(-1); } if(loadJoin(&(layer->joins[layer->numjoins])) == -1) return(-1); layer->numjoins++; break; case(LABELCACHE): if((layer->labelcache = getSymbol(2, MS_ON, MS_OFF)) == -1) return(-1); break; case(LABELITEM): if(getString(&layer->labelitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->labelitem, msLookupHashTable(&(layer->validation), "labelitem"), msLookupHashTable(&(map->web.validation), "labelitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based LABELITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->labelitem); layer->labelitem=NULL; return(-1); } } break; case(LABELMAXSCALE): case(LABELMAXSCALEDENOM): if(getDouble(&(layer->labelmaxscaledenom)) == -1) return(-1); break; case(LABELMINSCALE): case(LABELMINSCALEDENOM): if(getDouble(&(layer->labelminscaledenom)) == -1) return(-1); break; case(LABELREQUIRES): if(getString(&layer->labelrequires) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->labelrequires, msLookupHashTable(&(layer->validation), "labelrequires"), msLookupHashTable(&(map->web.validation), "labelrequires"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based LABELREQUIRES configuration failed pattern validation." , "loadLayer()"); msFree(layer->labelrequires); layer->labelrequires=NULL; return(-1); } } break; case(LAYER): break; /* for string loads */ case(MASK): if(getString(&layer->mask) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->mask, msLookupHashTable(&(layer->validation), "mask"), msLookupHashTable(&(map->web.validation), "mask"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based MASK configuration failed pattern validation." , "loadLayer()"); msFree(layer->mask); layer->mask=NULL; return(-1); } } break; case(MAXFEATURES): if(getInteger(&(layer->maxfeatures)) == -1) return(-1); break; case(MAXSCALE): case(MAXSCALEDENOM): if(getDouble(&(layer->maxscaledenom)) == -1) return(-1); break; case(MAXGEOWIDTH): if(getDouble(&(layer->maxgeowidth)) == -1) return(-1); break; case(METADATA): if(loadHashTable(&(layer->metadata)) != MS_SUCCESS) return(-1); break; case(MINSCALE): case(MINSCALEDENOM): if(getDouble(&(layer->minscaledenom)) == -1) return(-1); break; case(MINGEOWIDTH): if(getDouble(&(layer->mingeowidth)) == -1) return(-1); break; case(MINFEATURESIZE): if(getInteger(&(layer->minfeaturesize)) == -1) return(-1); break; case(NAME): if(getString(&layer->name) == MS_FAILURE) return(-1); break; case(OFFSITE): if(loadColor(&(layer->offsite), NULL) != MS_SUCCESS) return(-1); break; case(OPACITY): case(TRANSPARENCY): /* keyword supported for mapfile backwards compatability */ if (getIntegerOrSymbol(&(layer->opacity), 1, MS_GD_ALPHA) == -1) return(-1); break; case(MS_PLUGIN): { int rv; if(getString(&layer->plugin_library_original) == MS_FAILURE) return(-1); rv = msBuildPluginLibraryPath(&layer->plugin_library, layer->plugin_library_original, map); if (rv == MS_FAILURE) return(-1); } break; case(PROCESSING): { /* NOTE: processing array maintained as size+1 with NULL terminator. This ensure that CSL (GDAL string list) functions can be used on the list for easy processing. */ char *value=NULL; if(getString(&value) == MS_FAILURE) return(-1); if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(value, msLookupHashTable(&(layer->validation), "processing"), msLookupHashTable(&(map->web.validation), "processing"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based PROCESSING configuration failed pattern validation." , "loadLayer()"); free(value); value=NULL; return(-1); } } msLayerAddProcessing( layer, value ); free(value); value=NULL; } break; case(POSTLABELCACHE): if((layer->postlabelcache = getSymbol(2, MS_TRUE, MS_FALSE)) == -1) return(-1); if(layer->postlabelcache) layer->labelcache = MS_OFF; break; case(PROJECTION): if(loadProjection(&(layer->projection)) == -1) return(-1); layer->project = MS_TRUE; break; case(REQUIRES): if(getString(&layer->requires) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->requires, msLookupHashTable(&(layer->validation), "requires"), msLookupHashTable(&(map->web.validation), "requires"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based REQUIRES configuration failed pattern validation." , "loadLayer()"); msFree(layer->requires); layer->requires=NULL; return(-1); } } break; case(SCALETOKEN): if (msGrowLayerScaletokens(layer) == NULL) return(-1); initScaleToken(&layer->scaletokens[layer->numscaletokens]); if(loadScaletoken(&layer->scaletokens[layer->numscaletokens], layer) == -1) return(-1); layer->numscaletokens++; break; case(SIZEUNITS): if((layer->sizeunits = getSymbol(8, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS)) == -1) return(-1); break; case(STATUS): if((layer->status = getSymbol(3, MS_ON,MS_OFF,MS_DEFAULT)) == -1) return(-1); break; case(STYLEITEM): if(getString(&layer->styleitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->styleitem, msLookupHashTable(&(layer->validation), "styleitem"), msLookupHashTable(&(map->web.validation), "styleitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based STYLEITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->styleitem); layer->styleitem=NULL; return(-1); } } break; case(SYMBOLSCALE): case(SYMBOLSCALEDENOM): if(getDouble(&(layer->symbolscaledenom)) == -1) return(-1); break; case(TEMPLATE): if(getString(&layer->template) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->template, msLookupHashTable(&(layer->validation), "template"), msLookupHashTable(&(map->web.validation), "template"), map->templatepattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEMPLATE configuration failed pattern validation." , "loadLayer()"); msFree(layer->template); layer->template=NULL; return(-1); } } break; case(TILEINDEX): if(getString(&layer->tileindex) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->tileindex, msLookupHashTable(&(layer->validation), "tileindex"), msLookupHashTable(&(map->web.validation), "tileindex"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TILEINDEX configuration failed pattern validation." , "loadLayer()"); msFree(layer->tileindex); layer->tileindex=NULL; return(-1); } } break; case(TILEITEM): if(getString(&layer->tileitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->tileitem, msLookupHashTable(&(layer->validation), "tileitem"), msLookupHashTable(&(map->web.validation), "tileitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TILEITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->tileitem); layer->tileitem=NULL; return(-1); } } break; case(TILESRS): if(getString(&layer->tilesrs) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->tilesrs, msLookupHashTable(&(layer->validation), "tilesrs"), msLookupHashTable(&(map->web.validation), "tilesrs"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TILESRS configuration failed pattern validation." , "loadLayer()"); msFree(layer->tilesrs); layer->tilesrs=NULL; return(-1); } } break; case(TOLERANCE): if(getDouble(&(layer->tolerance)) == -1) return(-1); break; case(TOLERANCEUNITS): if((layer->toleranceunits = getSymbol(8, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS)) == -1) return(-1); break; case(TRANSFORM): if((layer->transform = getSymbol(11, MS_TRUE,MS_FALSE, MS_UL,MS_UC,MS_UR,MS_CL,MS_CC,MS_CR,MS_LL,MS_LC,MS_LR)) == -1) return(-1); break; case(TYPE): if((layer->type = getSymbol(9, MS_LAYER_POINT,MS_LAYER_LINE,MS_LAYER_RASTER,MS_LAYER_POLYGON,MS_LAYER_ANNOTATION,MS_LAYER_QUERY,MS_LAYER_CIRCLE,MS_LAYER_CHART,TILEINDEX)) == -1) return(-1); if(layer->type == TILEINDEX) layer->type = MS_LAYER_TILEINDEX; /* TILEINDEX is also a parameter */ break; case(UNITS): if((layer->units = getSymbol(9, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS,MS_PERCENTAGES)) == -1) return(-1); break; case(VALIDATION): if(loadHashTable(&(layer->validation)) != MS_SUCCESS) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLayer()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateLayerFromString(layerObj *layer, char *string, int url_string) { int i; if(!layer || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadLayer(layer, layer->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); /* step through classes to resolve symbol names */ for(i=0; inumclasses; i++) { if(classResolveSymbolNames(layer->class[i]) != MS_SUCCESS) return MS_FAILURE; } return MS_SUCCESS; } static void writeLayer(FILE *stream, int indent, layerObj *layer) { int i; featureListNodeObjPtr current=NULL; if(layer->status == MS_DELETE) return; indent++; writeBlockBegin(stream, indent, "LAYER"); /* bindvals */ /* class - see below */ writeString(stream, indent, "CLASSGROUP", NULL, layer->classgroup); writeString(stream, indent, "CLASSITEM", NULL, layer->classitem); writeCluster(stream, indent, &(layer->cluster)); writeString(stream, indent, "CONNECTION", NULL, layer->connection); writeKeyword(stream, indent, "CONNECTIONTYPE", layer->connectiontype, 10, MS_SDE, "SDE", MS_OGR, "OGR", MS_POSTGIS, "POSTGIS", MS_WMS, "WMS", MS_ORACLESPATIAL, "ORACLESPATIAL", MS_WFS, "WFS", MS_PLUGIN, "PLUGIN", MS_UNION, "UNION", MS_UVRASTER, "UVRASTER", MS_CONTOUR, "CONTOUR"); writeString(stream, indent, "DATA", NULL, layer->data); writeNumber(stream, indent, "DEBUG", 0, layer->debug); /* is this right? see loadLayer() */ writeExtent(stream, indent, "EXTENT", layer->extent); writeExpression(stream, indent, "FILTER", &(layer->filter)); writeString(stream, indent, "FILTERITEM", NULL, layer->filteritem); writeString(stream, indent, "FOOTER", NULL, layer->footer); writeString(stream, indent, "GROUP", NULL, layer->group); if(layer->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) { writeIndent(stream, indent + 1); fprintf(stream, "GEOMTRANSFORM (%s)\n", layer->_geomtransform.string); } writeString(stream, indent, "HEADER", NULL, layer->header); /* join - see below */ writeKeyword(stream, indent, "LABELCACHE", layer->labelcache, 1, MS_OFF, "OFF"); writeString(stream, indent, "LABELITEM", NULL, layer->labelitem); writeNumber(stream, indent, "LABELMAXSCALEDENOM", -1, layer->labelmaxscaledenom); writeNumber(stream, indent, "LABELMINSCALEDENOM", -1, layer->labelminscaledenom); writeString(stream, indent, "LABELREQUIRES", NULL, layer->labelrequires); writeNumber(stream, indent, "MAXFEATURES", -1, layer->maxfeatures); writeNumber(stream, indent, "MAXGEOWIDTH", -1, layer->maxgeowidth); writeNumber(stream, indent, "MAXSCALEDENOM", -1, layer->maxscaledenom); writeString(stream, indent, "MASK", NULL, layer->mask); writeHashTable(stream, indent, "METADATA", &(layer->metadata)); writeNumber(stream, indent, "MINGEOWIDTH", -1, layer->mingeowidth); writeNumber(stream, indent, "MINSCALEDENOM", -1, layer->minscaledenom); writeNumber(stream, indent, "MINFEATURESIZE", -1, layer->minfeaturesize); writeString(stream, indent, "NAME", NULL, layer->name); writeColor(stream, indent, "OFFSITE", NULL, &(layer->offsite)); writeString(stream, indent, "PLUGIN", NULL, layer->plugin_library_original); writeKeyword(stream, indent, "POSTLABELCACHE", layer->postlabelcache, 1, MS_TRUE, "TRUE"); for(i=0; inumprocessing; i++) writeString(stream, indent, "PROCESSING", NULL, layer->processing[i]); writeProjection(stream, indent, &(layer->projection)); writeString(stream, indent, "REQUIRES", NULL, layer->requires); writeKeyword(stream, indent, "SIZEUNITS", layer->sizeunits, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeKeyword(stream, indent, "STATUS", layer->status, 3, MS_ON, "ON", MS_OFF, "OFF", MS_DEFAULT, "DEFAULT"); writeString(stream, indent, "STYLEITEM", NULL, layer->styleitem); writeNumber(stream, indent, "SYMBOLSCALEDENOM", -1, layer->symbolscaledenom); writeString(stream, indent, "TEMPLATE", NULL, layer->template); writeString(stream, indent, "TILEINDEX", NULL, layer->tileindex); writeString(stream, indent, "TILEITEM", NULL, layer->tileitem); writeString(stream, indent, "TILESRS", NULL, layer->tilesrs); writeNumber(stream, indent, "TOLERANCE", -1, layer->tolerance); writeKeyword(stream, indent, "TOLERANCEUNITS", layer->toleranceunits, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeKeyword(stream, indent, "TRANSFORM", layer->transform, 10, MS_FALSE, "FALSE", MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR"); writeNumberOrKeyword(stream, indent, "OPACITY", 100, layer->opacity, (int)layer->opacity, 1, MS_GD_ALPHA, "ALPHA"); writeKeyword(stream, indent, "TYPE", layer->type, 9, MS_LAYER_POINT, "POINT", MS_LAYER_LINE, "LINE", MS_LAYER_POLYGON, "POLYGON", MS_LAYER_RASTER, "RASTER", MS_LAYER_ANNOTATION, "ANNOTATION", MS_LAYER_QUERY, "QUERY", MS_LAYER_CIRCLE, "CIRCLE", MS_LAYER_TILEINDEX, "TILEINDEX", MS_LAYER_CHART, "CHART"); writeKeyword(stream, indent, "UNITS", layer->units, 9, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD", MS_PIXELS, "PIXELS", MS_PERCENTAGES, "PERCENTATGES"); writeHashTable(stream, indent, "VALIDATION", &(layer->validation)); /* write potentially multiply occuring objects last */ for(i=0; inumscaletokens; i++) writeScaleToken(stream, indent, &(layer->scaletokens[i])); for(i=0; inumjoins; i++) writeJoin(stream, indent, &(layer->joins[i])); for(i=0; inumclasses; i++) writeClass(stream, indent, layer->class[i]); if( layer->layerinfo && layer->connectiontype == MS_GRATICULE) writeGrid(stream, indent, (graticuleObj *) layer->layerinfo); else { current = layer->features; while(current != NULL) { writeFeature(stream, indent, &(current->shape)); current = current->next; } } writeBlockEnd(stream, indent, "LAYER"); writeLineFeed(stream); } char* msWriteLayerToString(layerObj *layer) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeLayer(stdout, -1, layer); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a referenceMapObj structure */ void initReferenceMap(referenceMapObj *ref) { ref->height = ref->width = 0; ref->extent.minx = ref->extent.miny = ref->extent.maxx = ref->extent.maxy = -1.0; ref->image = NULL; MS_INIT_COLOR(ref->color, 255, 0, 0, 255); MS_INIT_COLOR(ref->outlinecolor, 0, 0, 0, 255); ref->status = MS_OFF; ref->marker = 0; ref->markername = NULL; ref->markersize = 0; ref->minboxsize = 3; ref->maxboxsize = 0; ref->map = NULL; } void freeReferenceMap(referenceMapObj *ref) { msFree(ref->image); msFree(ref->markername); } int loadReferenceMap(referenceMapObj *ref, mapObj *map) { int state; ref->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadReferenceMap()"); return(-1); case(END): if(!ref->image) { msSetError(MS_MISCERR, "No image defined for the reference map.", "loadReferenceMap()"); return(-1); } if(ref->width == 0 || ref->height == 0) { msSetError(MS_MISCERR, "No image size defined for the reference map.", "loadReferenceMap()"); return(-1); } return(0); break; case(COLOR): if(loadColor(&(ref->color), NULL) != MS_SUCCESS) return(-1); break; case(EXTENT): if(getDouble(&(ref->extent.minx)) == -1) return(-1); if(getDouble(&(ref->extent.miny)) == -1) return(-1); if(getDouble(&(ref->extent.maxx)) == -1) return(-1); if(getDouble(&(ref->extent.maxy)) == -1) return(-1); if (!MS_VALID_EXTENT(ref->extent)) { msSetError(MS_MISCERR, "Given reference extent is invalid. Check that it " \ "is in the form: minx, miny, maxx, maxy", "loadReferenceMap()"); return(-1); } break; case(IMAGE): if(getString(&ref->image) == MS_FAILURE) return(-1); break; case(OUTLINECOLOR): if(loadColor(&(ref->outlinecolor), NULL) != MS_SUCCESS) return(-1); break; case(SIZE): if(getInteger(&(ref->width)) == -1) return(-1); if(getInteger(&(ref->height)) == -1) return(-1); break; case(STATUS): if((ref->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(MARKER): if((state = getSymbol(2, MS_NUMBER,MS_STRING)) == -1) return(-1); if(state == MS_NUMBER) ref->marker = (int) msyynumber; else { if (ref->markername != NULL) msFree(ref->markername); ref->markername = msStrdup(msyystring_buffer); } break; case(MARKERSIZE): if(getInteger(&(ref->markersize)) == -1) return(-1); break; case(MINBOXSIZE): if(getInteger(&(ref->minboxsize)) == -1) return(-1); break; case(MAXBOXSIZE): if(getInteger(&(ref->maxboxsize)) == -1) return(-1); break; case(REFERENCE): break; /* for string loads */ default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadReferenceMap()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateReferenceMapFromString(referenceMapObj *ref, char *string, int url_string) { if(!ref || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadReferenceMap(ref, ref->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeReferenceMap(FILE *stream, int indent, referenceMapObj *ref) { colorObj c; if(!ref->image) return; indent++; writeBlockBegin(stream, indent, "REFERENCE"); MS_INIT_COLOR(c,255,0,0,255); writeColor(stream, indent, "COLOR", &c, &(ref->color)); writeExtent(stream, indent, "EXTENT", ref->extent); writeString(stream, indent, "IMAGE", NULL, ref->image); MS_INIT_COLOR(c,0,0,0,255); writeColor(stream, indent, "OUTLINECOLOR", &c, &(ref->outlinecolor)); writeDimension(stream, indent, "SIZE", ref->width, ref->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", ref->status, 2, MS_ON, "ON", MS_OFF, "OFF"); writeNumberOrString(stream, indent, "MARKER", 0, ref->marker, ref->markername); writeNumber(stream, indent, "MARKERSIZE", -1, ref->markersize); writeNumber(stream, indent, "MAXBOXSIZE", -1, ref->maxboxsize); writeNumber(stream, indent, "MINBOXSIZE", -1, ref->minboxsize); writeBlockEnd(stream, indent, "REFERENCE"); writeLineFeed(stream); } char* msWriteReferenceMapToString(referenceMapObj *ref) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeReferenceMap(stdout, -1, ref); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } #define MAX_FORMATOPTIONS 100 static int loadOutputFormat(mapObj *map) { char *name = NULL; char *mimetype = NULL; char *driver = NULL; char *extension = NULL; int imagemode = MS_NOOVERRIDE; int transparent = MS_NOOVERRIDE; char *formatoptions[MAX_FORMATOPTIONS]; int numformatoptions = 0; char *value = NULL; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadOutputFormat()"); return(-1); case(END): { outputFormatObj *format; if( driver == NULL ) { msSetError(MS_MISCERR, "OUTPUTFORMAT clause lacks DRIVER keyword near (%s):(%d)", "loadOutputFormat()", msyystring_buffer, msyylineno ); return -1; } format = msCreateDefaultOutputFormat( map, driver, name ); msFree( name ); name = NULL; if( format == NULL ) { msSetError(MS_MISCERR, "OUTPUTFORMAT clause references driver %s, but this driver isn't configured.", "loadOutputFormat()", driver ); return -1; } msFree( driver ); if( transparent != MS_NOOVERRIDE ) format->transparent = transparent; if( extension != NULL ) { msFree( format->extension ); format->extension = extension; } if( mimetype != NULL ) { msFree( format->mimetype ); format->mimetype = mimetype; } if( imagemode != MS_NOOVERRIDE ) { #ifndef USE_GD /* don't override a GD format if GD isn't configured in */ if(imagemode != MS_IMAGEMODE_PC256) #endif format->imagemode = imagemode; if( transparent == MS_NOOVERRIDE ) { if( imagemode == MS_IMAGEMODE_RGB ) format->transparent = MS_FALSE; else if( imagemode == MS_IMAGEMODE_RGBA ) format->transparent = MS_TRUE; } if( format->imagemode == MS_IMAGEMODE_INT16 || format->imagemode == MS_IMAGEMODE_FLOAT32 || format->imagemode == MS_IMAGEMODE_BYTE ) format->renderer = MS_RENDER_WITH_RAWDATA; #ifdef USE_GD if( format->imagemode == MS_IMAGEMODE_PC256 ) format->renderer = MS_RENDER_WITH_GD; #endif } format->numformatoptions = numformatoptions; if( numformatoptions > 0 ) { format->formatoptions = (char **) msSmallMalloc(sizeof(char *)*numformatoptions ); memcpy( format->formatoptions, formatoptions, sizeof(char *)*numformatoptions ); } format->inmapfile = MS_TRUE; msOutputFormatValidate( format, MS_FALSE ); return(0); } case(NAME): msFree( name ); if((name = getToken()) == NULL) return(-1); break; case(MIMETYPE): if(getString(&mimetype) == MS_FAILURE) return(-1); break; case(DRIVER): { int s; if((s = getSymbol(2, MS_STRING, TEMPLATE)) == -1) return -1; /* allow the template to be quoted or not in the mapfile */ if(s == MS_STRING) driver = msStrdup(msyystring_buffer); else driver = msStrdup("TEMPLATE"); } break; case(EXTENSION): if(getString(&extension) == MS_FAILURE) return(-1); if( extension[0] == '.' ) { char *temp = msStrdup(extension+1); free( extension ); extension = temp; } break; case(FORMATOPTION): if(getString(&value) == MS_FAILURE) return(-1); if( numformatoptions < MAX_FORMATOPTIONS ) formatoptions[numformatoptions++] = msStrdup(value); free(value); value=NULL; break; case(IMAGEMODE): value = getToken(); if( strcasecmp(value,"PC256") == 0 ) imagemode = MS_IMAGEMODE_PC256; else if( strcasecmp(value,"RGB") == 0 ) imagemode = MS_IMAGEMODE_RGB; else if( strcasecmp(value,"RGBA") == 0) imagemode = MS_IMAGEMODE_RGBA; else if( strcasecmp(value,"INT16") == 0) imagemode = MS_IMAGEMODE_INT16; else if( strcasecmp(value,"FLOAT32") == 0) imagemode = MS_IMAGEMODE_FLOAT32; else if( strcasecmp(value,"BYTE") == 0) imagemode = MS_IMAGEMODE_BYTE; else if( strcasecmp(value,"FEATURE") == 0) imagemode = MS_IMAGEMODE_FEATURE; else { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d), expected PC256, RGB, RGBA, FEATURE, BYTE, INT16, or FLOAT32 for IMAGEMODE.", "loadOutputFormat()", msyystring_buffer, msyylineno); return -1; } free(value); value=NULL; break; case(TRANSPARENT): if((transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadOutputFormat()", msyystring_buffer, msyylineno); return(-1); } } /* next token */ } /* ** utility function to write an output format structure to file */ static void writeOutputformatobject(FILE *stream, int indent, outputFormatObj *outputformat) { int i = 0; if(!outputformat) return; indent++; writeBlockBegin(stream, indent, "OUTPUTFORMAT"); writeString(stream, indent, "NAME", NULL, outputformat->name); writeString(stream, indent, "MIMETYPE", NULL, outputformat->mimetype); writeString(stream, indent, "DRIVER", NULL, outputformat->driver); writeString(stream, indent, "EXTENSION", NULL, outputformat->extension); writeKeyword(stream, indent, "IMAGEMODE", outputformat->imagemode, 7, MS_IMAGEMODE_PC256, "PC256", MS_IMAGEMODE_RGB, "RGB", MS_IMAGEMODE_RGBA, "RGBA", MS_IMAGEMODE_INT16, "INT16", MS_IMAGEMODE_FLOAT32, "FLOAT32", MS_IMAGEMODE_BYTE, "BYTE", MS_IMAGEMODE_FEATURE, "FEATURE"); writeKeyword(stream, indent, "TRANSPARENT", outputformat->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); for (i=0; inumformatoptions; i++) writeString(stream, indent, "FORMATOPTION", NULL, outputformat->formatoptions[i]); writeBlockEnd(stream, indent, "OUTPUTFORMAT"); writeLineFeed(stream); } /* ** Write the output formats to file */ static void writeOutputformat(FILE *stream, int indent, mapObj *map) { int i=0; if(!map->outputformat) return; writeOutputformatobject(stream, indent, map->outputformat); for(i=0; inumoutputformats; i++) { if(map->outputformatlist[i]->inmapfile == MS_TRUE && strcmp(map->outputformatlist[i]->name, map->outputformat->name) != 0) writeOutputformatobject(stream, indent, map->outputformatlist[i]); } } /* ** Initialize, load and free a legendObj structure */ void initLegend(legendObj *legend) { legend->height = legend->width = 0; MS_INIT_COLOR(legend->imagecolor, 255,255,255,255); /* white */ MS_INIT_COLOR(legend->outlinecolor, -1,-1,-1,255); initLabel(&legend->label); legend->label.position = MS_XY; /* override */ legend->keysizex = 20; legend->keysizey = 10; legend->keyspacingx = 5; legend->keyspacingy = 5; legend->status = MS_OFF; legend->transparent = MS_NOOVERRIDE; legend->interlace = MS_NOOVERRIDE; legend->position = MS_LL; legend->postlabelcache = MS_FALSE; /* draw with labels */ legend->template = NULL; legend->map = NULL; } void freeLegend(legendObj *legend) { if (legend->template) free(legend->template); freeLabel(&(legend->label)); } int loadLegend(legendObj *legend, mapObj *map) { legend->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadLegend()"); return(-1); case(END): legend->label.position = MS_XY; /* overrides go here */ return(0); break; case(IMAGECOLOR): if(loadColor(&(legend->imagecolor), NULL) != MS_SUCCESS) return(-1); break; case(INTERLACE): if((legend->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(KEYSIZE): if(getInteger(&(legend->keysizex)) == -1) return(-1); if(getInteger(&(legend->keysizey)) == -1) return(-1); break; case(KEYSPACING): if(getInteger(&(legend->keyspacingx)) == -1) return(-1); if(getInteger(&(legend->keyspacingy)) == -1) return(-1); break; case(LABEL): if(loadLabel(&(legend->label)) == -1) return(-1); legend->label.angle = 0; /* force */ break; case(LEGEND): break; /* for string loads */ case(OUTLINECOLOR): if(loadColor(&(legend->outlinecolor), NULL) != MS_SUCCESS) return(-1); break; case(POSITION): if((legend->position = getSymbol(6, MS_UL,MS_UR,MS_LL,MS_LR,MS_UC,MS_LC)) == -1) return(-1); break; case(POSTLABELCACHE): if((legend->postlabelcache = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(STATUS): if((legend->status = getSymbol(3, MS_ON,MS_OFF,MS_EMBED)) == -1) return(-1); break; case(TRANSPARENT): if((legend->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(TEMPLATE): if(getString(&legend->template) == MS_FAILURE) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLegend()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateLegendFromString(legendObj *legend, char *string, int url_string) { if(!legend || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadLegend(legend, legend->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeLegend(FILE *stream, int indent, legendObj *legend) { colorObj c; indent++; writeBlockBegin(stream, indent, "LEGEND"); MS_INIT_COLOR(c,255,255,255,255); writeColor(stream, indent, "IMAGECOLOR", &c, &(legend->imagecolor)); writeKeyword(stream, indent, "INTERLACE", legend->interlace, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeDimension(stream, indent, "KEYSIZE", legend->keysizex, legend->keysizey, NULL, NULL); writeDimension(stream, indent, "KEYSPACING", legend->keyspacingx, legend->keyspacingy, NULL, NULL); writeLabel(stream, indent, &(legend->label)); writeColor(stream, indent, "OUTLINECOLOR", NULL, &(legend->outlinecolor)); if(legend->status == MS_EMBED) writeKeyword(stream, indent, "POSITION", legend->position, 6, MS_LL, "LL", MS_UL, "UL", MS_UR, "UR", MS_LR, "LR", MS_UC, "UC", MS_LC, "LC"); writeKeyword(stream, indent, "POSTLABELCACHE", legend->postlabelcache, 1, MS_TRUE, "TRUE"); writeKeyword(stream, indent, "STATUS", legend->status, 3, MS_ON, "ON", MS_OFF, "OFF", MS_EMBED, "EMBED"); writeKeyword(stream, indent, "TRANSPARENT", legend->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeString(stream, indent, "TEMPLATE", NULL, legend->template); writeBlockEnd(stream, indent, "LEGEND"); writeLineFeed(stream); } char* msWriteLegendToString(legendObj *legend) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeLegend(stdout, -1, legend); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a scalebarObj structure */ void initScalebar(scalebarObj *scalebar) { MS_INIT_COLOR(scalebar->imagecolor, -1,-1,-1,255); scalebar->width = 200; scalebar->height = 3; scalebar->style = 0; /* only 2 styles at this point */ scalebar->intervals = 4; initLabel(&scalebar->label); scalebar->label.position = MS_XY; /* override */ MS_INIT_COLOR(scalebar->backgroundcolor, -1,-1,-1,255); /* if not set, scalebar creation needs to set this to match the background color */ MS_INIT_COLOR(scalebar->color, 0,0,0,255); /* default to black */ MS_INIT_COLOR(scalebar->outlinecolor, -1,-1,-1,255); scalebar->units = MS_MILES; scalebar->status = MS_OFF; scalebar->position = MS_LL; scalebar->transparent = MS_NOOVERRIDE; /* no transparency */ scalebar->interlace = MS_NOOVERRIDE; scalebar->postlabelcache = MS_FALSE; /* draw with labels */ scalebar->align = MS_ALIGN_CENTER; } void freeScalebar(scalebarObj *scalebar) { freeLabel(&(scalebar->label)); } int loadScalebar(scalebarObj *scalebar) { for(;;) { switch(msyylex()) { case(ALIGN): if((scalebar->align = getSymbol(3, MS_ALIGN_LEFT,MS_ALIGN_CENTER,MS_ALIGN_RIGHT)) == -1) return(-1); break; case(BACKGROUNDCOLOR): if(loadColor(&(scalebar->backgroundcolor), NULL) != MS_SUCCESS) return(-1); break; case(COLOR): if(loadColor(&(scalebar->color), NULL) != MS_SUCCESS) return(-1); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadScalebar()"); return(-1); case(END): return(0); break; case(IMAGECOLOR): if(loadColor(&(scalebar->imagecolor), NULL) != MS_SUCCESS) return(-1); break; case(INTERLACE): if((scalebar->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(INTERVALS): if(getInteger(&(scalebar->intervals)) == -1) return(-1); break; case(LABEL): if(loadLabel(&(scalebar->label)) == -1) return(-1); scalebar->label.angle = 0; break; case(OUTLINECOLOR): if(loadColor(&(scalebar->outlinecolor), NULL) != MS_SUCCESS) return(-1); break; case(POSITION): if((scalebar->position = getSymbol(6, MS_UL,MS_UR,MS_LL,MS_LR,MS_UC,MS_LC)) == -1) return(-1); break; case(POSTLABELCACHE): if((scalebar->postlabelcache = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(SCALEBAR): break; /* for string loads */ case(SIZE): if(getInteger(&(scalebar->width)) == -1) return(-1); if(getInteger(&(scalebar->height)) == -1) return(-1); break; case(STATUS): if((scalebar->status = getSymbol(3, MS_ON,MS_OFF,MS_EMBED)) == -1) return(-1); break; case(STYLE): if(getInteger(&(scalebar->style)) == -1) return(-1); break; case(TRANSPARENT): if((scalebar->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(UNITS): if((scalebar->units = getSymbol(6, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadScalebar()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateScalebarFromString(scalebarObj *scalebar, char *string, int url_string) { if(!scalebar || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadScalebar(scalebar) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeScalebar(FILE *stream, int indent, scalebarObj *scalebar) { colorObj c; indent++; writeBlockBegin(stream, indent, "SCALEBAR"); writeKeyword(stream, indent, "ALIGN", scalebar->align, 2, MS_ALIGN_LEFT, "LEFT", MS_ALIGN_RIGHT, "RIGHT"); writeColor(stream, indent, "BACKGROUNDCOLOR", NULL, &(scalebar->backgroundcolor)); MS_INIT_COLOR(c,0,0,0,255); writeColor(stream, indent, "COLOR", &c, &(scalebar->color)); writeColor(stream, indent, "IMAGECOLOR", NULL, &(scalebar->imagecolor)); writeKeyword(stream, indent, "INTERLACE", scalebar->interlace, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeNumber(stream, indent, "INTERVALS", -1, scalebar->intervals); writeLabel(stream, indent, &(scalebar->label)); writeColor(stream, indent, "OUTLINECOLOR", NULL, &(scalebar->outlinecolor)); if(scalebar->status == MS_EMBED) writeKeyword(stream, indent, "POSITION", scalebar->position, 6, MS_LL, "LL", MS_UL, "UL", MS_UR, "UR", MS_LR, "LR", MS_UC, "UC", MS_LC, "LC"); writeKeyword(stream, indent, "POSTLABELCACHE", scalebar->postlabelcache, 1, MS_TRUE, "TRUE"); writeDimension(stream, indent, "SIZE", scalebar->width, scalebar->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", scalebar->status, 3, MS_ON, "ON", MS_OFF, "OFF", MS_EMBED, "EMBED"); writeNumber(stream, indent, "STYLE", 0, scalebar->style); writeKeyword(stream, indent, "TRANSPARENT", scalebar->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeKeyword(stream, indent, "UNITS", scalebar->units, 6, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES"); writeBlockEnd(stream, indent, "SCALEBAR"); writeLineFeed(stream); } char* msWriteScalebarToString(scalebarObj *scalebar) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeScalebar(stdout, -1, scalebar); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize a queryMapObj structure */ void initQueryMap(queryMapObj *querymap) { querymap->width = querymap->height = -1; querymap->style = MS_HILITE; querymap->status = MS_OFF; MS_INIT_COLOR(querymap->color, 255,255,0,255); /* yellow */ } int loadQueryMap(queryMapObj *querymap) { for(;;) { switch(msyylex()) { case(QUERYMAP): break; /* for string loads */ case(COLOR): loadColor(&(querymap->color), NULL); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadQueryMap()"); return(-1); case(END): return(0); break; case(SIZE): if(getInteger(&(querymap->width)) == -1) return(-1); if(getInteger(&(querymap->height)) == -1) return(-1); break; case(STATUS): if((querymap->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(STYLE): case(TYPE): if((querymap->style = getSymbol(3, MS_NORMAL,MS_HILITE,MS_SELECTED)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadQueryMap()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } int msUpdateQueryMapFromString(queryMapObj *querymap, char *string, int url_string) { if(!querymap || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadQueryMap(querymap) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeQueryMap(FILE *stream, int indent, queryMapObj *querymap) { colorObj c; indent++; writeBlockBegin(stream, indent, "QUERYMAP"); MS_INIT_COLOR(c,255,255,0,255); writeColor(stream, indent, "COLOR", &c, &(querymap->color)); writeDimension(stream, indent, "SIZE", querymap->width, querymap->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", querymap->status, 2, MS_ON, "ON", MS_OFF, "OFF"); writeKeyword(stream, indent, "STYLE", querymap->style, 3, MS_NORMAL, "NORMAL", MS_HILITE, "HILITE", MS_SELECTED, "SELECTED"); writeBlockEnd(stream, indent, "QUERYMAP"); writeLineFeed(stream); } char* msWriteQueryMapToString(queryMapObj *querymap) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeQueryMap(stdout, -1, querymap); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize a webObj structure */ void initWeb(webObj *web) { web->extent.minx = web->extent.miny = web->extent.maxx = web->extent.maxy = -1.0; web->template = NULL; web->header = web->footer = NULL; web->error = web->empty = NULL; web->mintemplate = web->maxtemplate = NULL; web->minscaledenom = web->maxscaledenom = -1; web->log = NULL; web->imagepath = msStrdup(""); web->temppath = NULL; web->imageurl = msStrdup(""); initHashTable(&(web->metadata)); initHashTable(&(web->validation)); web->map = NULL; web->queryformat = msStrdup("text/html"); web->legendformat = msStrdup("text/html"); web->browseformat = msStrdup("text/html"); } void freeWeb(webObj *web) { msFree(web->template); msFree(web->header); msFree(web->footer); msFree(web->error); msFree(web->empty); msFree(web->maxtemplate); msFree(web->mintemplate); msFree(web->log); msFree(web->imagepath); msFree(web->temppath); msFree(web->imageurl); msFree(web->queryformat); msFree(web->legendformat); msFree(web->browseformat); if(&(web->metadata)) msFreeHashItems(&(web->metadata)); if(&(web->validation)) msFreeHashItems(&(web->validation)); } static void writeWeb(FILE *stream, int indent, webObj *web) { indent++; writeBlockBegin(stream, indent, "WEB"); writeString(stream, indent, "BROWSEFORMAT", "text/html", web->browseformat); writeString(stream, indent, "EMPTY", NULL, web->empty); writeString(stream, indent, "ERROR", NULL, web->error); writeExtent(stream, indent, "EXTENT", web->extent); writeString(stream, indent, "FOOTER", NULL, web->footer); writeString(stream, indent, "HEADER", NULL, web->header); writeString(stream, indent, "IMAGEPATH", "", web->imagepath); writeString(stream, indent, "TEMPPATH", NULL, web->temppath); writeString(stream, indent, "IMAGEURL", "", web->imageurl); writeString(stream, indent, "LEGENDFORMAT", "text/html", web->legendformat); writeString(stream, indent, "LOG", NULL, web->log); writeNumber(stream, indent, "MAXSCALEDENOM", -1, web->maxscaledenom); writeString(stream, indent, "MAXTEMPLATE", NULL, web->maxtemplate); writeHashTable(stream, indent, "METADATA", &(web->metadata)); writeNumber(stream, indent, "MINSCALEDENOM", -1, web->minscaledenom); writeString(stream, indent, "MINTEMPLATE", NULL, web->mintemplate); writeString(stream, indent, "QUERYFORMAT", "text/html", web->queryformat); writeString(stream, indent, "TEMPLATE", NULL, web->template); writeHashTable(stream, indent, "VALIDATION", &(web->validation)); writeBlockEnd(stream, indent, "WEB"); writeLineFeed(stream); } char* msWriteWebToString(webObj *web) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeWeb(stdout, -1, web); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } int loadWeb(webObj *web, mapObj *map) { web->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(BROWSEFORMAT): /* change to use validation in 6.0 */ free(web->browseformat); web->browseformat = NULL; /* there is a default */ if(getString(&web->browseformat) == MS_FAILURE) return(-1); break; case(EMPTY): if(getString(&web->empty) == MS_FAILURE) return(-1); break; case(WEB): break; /* for string loads */ case(EOF): msSetError(MS_EOFERR, NULL, "loadWeb()"); return(-1); case(END): return(0); break; case(ERROR): if(getString(&web->error) == MS_FAILURE) return(-1); break; case(EXTENT): if(getDouble(&(web->extent.minx)) == -1) return(-1); if(getDouble(&(web->extent.miny)) == -1) return(-1); if(getDouble(&(web->extent.maxx)) == -1) return(-1); if(getDouble(&(web->extent.maxy)) == -1) return(-1); if (!MS_VALID_EXTENT(web->extent)) { msSetError(MS_MISCERR, "Given web extent is invalid. Check that it is in the form: minx, miny, maxx, maxy", "loadWeb()"); return(-1); } break; case(FOOTER): if(getString(&web->footer) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(web->footer, msLookupHashTable(&(web->validation), "footer"), map->templatepattern, NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FOOTER configuration failed pattern validation." , "loadWeb()"); msFree(web->footer); web->footer=NULL; return(-1); } } break; case(HEADER): if(getString(&web->header) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(web->header, msLookupHashTable(&(web->validation), "header"), map->templatepattern, NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based HEADER configuration failed pattern validation." , "loadWeb()"); msFree(web->header); web->header=NULL; return(-1); } } break; case(IMAGEPATH): if(getString(&web->imagepath) == MS_FAILURE) return(-1); break; case(TEMPPATH): if(getString(&web->temppath) == MS_FAILURE) return(-1); break; case(IMAGEURL): if(getString(&web->imageurl) == MS_FAILURE) return(-1); break; case(LEGENDFORMAT): /* change to use validation in 6.0 */ free(web->legendformat); web->legendformat = NULL; /* there is a default */ if(getString(&web->legendformat) == MS_FAILURE) return(-1); break; case(LOG): if(getString(&web->log) == MS_FAILURE) return(-1); break; case(MAXSCALE): case(MAXSCALEDENOM): if(getDouble(&web->maxscaledenom) == -1) return(-1); break; case(MAXTEMPLATE): if(getString(&web->maxtemplate) == MS_FAILURE) return(-1); break; case(METADATA): if(loadHashTable(&(web->metadata)) != MS_SUCCESS) return(-1); break; case(MINSCALE): case(MINSCALEDENOM): if(getDouble(&web->minscaledenom) == -1) return(-1); break; case(MINTEMPLATE): if(getString(&web->mintemplate) == MS_FAILURE) return(-1); break; case(QUERYFORMAT): /* change to use validation in 6.0 */ free(web->queryformat); web->queryformat = NULL; /* there is a default */ if(getString(&web->queryformat) == MS_FAILURE) return(-1); break; case(TEMPLATE): if(getString(&web->template) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(web->template, msLookupHashTable(&(web->validation), "template"), map->templatepattern, NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEMPLATE configuration failed pattern validation." , "loadWeb()"); msFree(web->template); web->template=NULL; return(-1); } } break; case(VALIDATION): if(loadHashTable(&(web->validation)) != MS_SUCCESS) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadWeb()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } int msUpdateWebFromString(webObj *web, char *string, int url_string) { if(!web || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadWeb(web, web->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } /* ** Initialize, load and free a mapObj structure ** ** This really belongs in mapobject.c, but currently it also depends on ** lots of other init methods in this file. */ int initMap(mapObj *map) { int i=0; MS_REFCNT_INIT(map); map->debug = (int)msGetGlobalDebugLevel(); /* Set maxlayers = 0, layers[] and layerorder[] will be allocated as needed, * on the first call to msGrowMapLayers() */ map->numlayers = 0; map->maxlayers = 0; map->layers = NULL; map->layerorder = NULL; /* used to modify the order in which the layers are drawn */ map->status = MS_ON; map->name = msStrdup("MS"); map->extent.minx = map->extent.miny = map->extent.maxx = map->extent.maxy = -1.0; map->scaledenom = -1.0; map->resolution = MS_DEFAULT_RESOLUTION; /* pixels per inch */ map->defresolution = MS_DEFAULT_RESOLUTION; /* pixels per inch */ map->height = map->width = -1; map->maxsize = MS_MAXIMAGESIZE_DEFAULT; map->gt.need_geotransform = MS_FALSE; map->gt.rotation_angle = 0.0; map->units = MS_METERS; map->cellsize = 0; map->shapepath = NULL; map->mappath = NULL; MS_INIT_COLOR(map->imagecolor, 255,255,255,255); /* white */ map->numoutputformats = 0; map->outputformatlist = NULL; map->outputformat = NULL; /* map->configoptions = msCreateHashTable();; */ initHashTable(&(map->configoptions)); map->imagetype = NULL; map->palette.numcolors = 0; map->transparent = MS_NOOVERRIDE; map->interlace = MS_NOOVERRIDE; map->imagequality = MS_NOOVERRIDE; for(i=0; ilabelcache.slots[i].labels = NULL; /* cache is initialize at draw time */ map->labelcache.slots[i].cachesize = 0; map->labelcache.slots[i].numlabels = 0; map->labelcache.slots[i].markers = NULL; map->labelcache.slots[i].markercachesize = 0; map->labelcache.slots[i].nummarkers = 0; } map->labelcache.numlabels = 0; map->fontset.filename = NULL; map->fontset.numfonts = 0; /* map->fontset.fonts = NULL; */ initHashTable(&(map->fontset.fonts)); msInitSymbolSet(&map->symbolset); map->symbolset.fontset = &(map->fontset); map->symbolset.map = map; initLegend(&map->legend); initScalebar(&map->scalebar); initWeb(&map->web); initReferenceMap(&map->reference); initQueryMap(&map->querymap); #ifdef USE_PROJ if(msInitProjection(&(map->projection)) == -1) return(-1); if(msInitProjection(&(map->latlon)) == -1) return(-1); /* initialize a default "geographic" projection */ map->latlon.numargs = 2; map->latlon.args[0] = msStrdup("proj=latlong"); map->latlon.args[1] = msStrdup("ellps=WGS84"); /* probably want a different ellipsoid */ if(msProcessProjection(&(map->latlon)) == -1) return(-1); #endif map->templatepattern = map->datapattern = NULL; /* Encryption key information - see mapcrypto.c */ map->encryption_key_loaded = MS_FALSE; msInitQuery(&(map->query)); return(0); } /* ** Ensure there is at least one free entry in the layers and layerorder ** arrays of this mapObj. Grow the allocated layers/layerorder arrays if ** necessary and allocate a new layer for layers[numlayers] if there is ** not already one, setting its contents to all zero bytes (i.e. does not ** call initLayer() on it). ** ** This function is safe to use for the initial allocation of the layers[] ** and layerorder[] arrays as well (i.e. when maxlayers==0 and layers==NULL) ** ** Returns a reference to the new layerObj on success, NULL on error. */ layerObj *msGrowMapLayers( mapObj *map ) { /* Do we need to increase the size of layers/layerorder by * MS_LAYER_ALLOCSIZE? */ if (map->numlayers == map->maxlayers) { layerObj **newLayersPtr; int *newLayerorderPtr; int i, newsize; newsize = map->maxlayers + MS_LAYER_ALLOCSIZE; /* Alloc/realloc layers */ newLayersPtr = (layerObj**)realloc(map->layers, newsize*sizeof(layerObj*)); MS_CHECK_ALLOC(newLayersPtr, newsize*sizeof(layerObj*), NULL); map->layers = newLayersPtr; /* Alloc/realloc layerorder */ newLayerorderPtr = (int *)realloc(map->layerorder, newsize*sizeof(int)); MS_CHECK_ALLOC(newLayerorderPtr, newsize*sizeof(int), NULL); map->layerorder = newLayerorderPtr; map->maxlayers = newsize; for(i=map->numlayers; imaxlayers; i++) { map->layers[i] = NULL; map->layerorder[i] = 0; } } if (map->layers[map->numlayers]==NULL) { map->layers[map->numlayers]=(layerObj*)calloc(1,sizeof(layerObj)); MS_CHECK_ALLOC(map->layers[map->numlayers], sizeof(layerObj), NULL); } return map->layers[map->numlayers]; } int msFreeLabelCacheSlot(labelCacheSlotObj *cacheslot) { int i, j; /* free the labels */ if (cacheslot->labels) { for(i=0; inumlabels; i++) { if (cacheslot->labels[i].labelpath) msFreeLabelPathObj(cacheslot->labels[i].labelpath); for(j=0; jlabels[i].numlabels; j++) freeLabel(&(cacheslot->labels[i].labels[j])); msFree(cacheslot->labels[i].labels); if(cacheslot->labels[i].poly) { msFreeShape(cacheslot->labels[i].poly); /* empties the shape */ msFree(cacheslot->labels[i].poly); /* free's the pointer */ } for(j=0; jlabels[i].numstyles; j++) freeStyle(&(cacheslot->labels[i].styles[j])); msFree(cacheslot->labels[i].styles); if(cacheslot->labels[i].leaderline) { msFree(cacheslot->labels[i].leaderline->point); msFree(cacheslot->labels[i].leaderline); msFree(cacheslot->labels[i].leaderbbox); } } } msFree(cacheslot->labels); cacheslot->labels = NULL; cacheslot->cachesize = 0; cacheslot->numlabels = 0; /* free the markers */ if (cacheslot->markers) { for(i=0; inummarkers; i++) { msFreeShape(cacheslot->markers[i].poly); msFree(cacheslot->markers[i].poly); } } msFree(cacheslot->markers); cacheslot->markers = NULL; cacheslot->markercachesize = 0; cacheslot->nummarkers = 0; return(MS_SUCCESS); } int msFreeLabelCache(labelCacheObj *cache) { int p; for(p=0; pslots[p])) != MS_SUCCESS) return MS_FAILURE; } cache->numlabels = 0; return MS_SUCCESS; } int msInitLabelCacheSlot(labelCacheSlotObj *cacheslot) { if(cacheslot->labels || cacheslot->markers) msFreeLabelCacheSlot(cacheslot); cacheslot->labels = (labelCacheMemberObj *)malloc(sizeof(labelCacheMemberObj)*MS_LABELCACHEINITSIZE); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*MS_LABELCACHEINITSIZE, MS_FAILURE); cacheslot->cachesize = MS_LABELCACHEINITSIZE; cacheslot->numlabels = 0; cacheslot->markers = (markerCacheMemberObj *)malloc(sizeof(markerCacheMemberObj)*MS_LABELCACHEINITSIZE); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*MS_LABELCACHEINITSIZE, MS_FAILURE); cacheslot->markercachesize = MS_LABELCACHEINITSIZE; cacheslot->nummarkers = 0; return(MS_SUCCESS); } int msInitLabelCache(labelCacheObj *cache) { int p; for(p=0; pslots[p])) != MS_SUCCESS) return MS_FAILURE; } cache->numlabels = 0; cache->gutter = 0; return MS_SUCCESS; } static void writeMap(FILE *stream, int indent, mapObj *map) { int i; colorObj c; writeBlockBegin(stream, indent, "MAP"); writeHashTableInline(stream, indent, "CONFIG", &(map->configoptions)); writeString(stream, indent, "DATAPATTERN", NULL, map->datapattern); /* depricated */ writeNumber(stream, indent, "DEBUG", 0, map->debug); writeNumber(stream, indent, "DEFRESOLUTION", 72.0, map->defresolution); writeExtent(stream, indent, "EXTENT", map->extent); writeString(stream, indent, "FONTSET", NULL, map->fontset.filename); MS_INIT_COLOR(c,255,255,255,255); writeColor(stream, indent, "IMAGECOLOR", &c, &(map->imagecolor)); writeString(stream, indent, "IMAGETYPE", NULL, map->imagetype); writeKeyword(stream, indent, "INTERLACE", map->interlace, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeNumber(stream, indent, "MAXSIZE", MS_MAXIMAGESIZE_DEFAULT, map->maxsize); writeString(stream, indent, "NAME", NULL, map->name); writeNumber(stream, indent, "RESOLUTION", 72.0, map->resolution); writeString(stream, indent, "SHAPEPATH", NULL, map->shapepath); writeDimension(stream, indent, "SIZE", map->width, map->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", map->status, 2, MS_ON, "ON", MS_OFF, "OFF"); writeString(stream, indent, "SYMBOLSET", NULL, map->symbolset.filename); writeString(stream, indent, "TEMPLATEPATTERN", NULL, map->templatepattern); /* depricated */ writeKeyword(stream, indent, "TRANSPARENT", map->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeKeyword(stream, indent, "UNITS", map->units, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeLineFeed(stream); writeOutputformat(stream, indent, map); /* write symbol with INLINE tag in mapfile */ for(i=0; isymbolset.numsymbols; i++) { if(map->symbolset.symbol[i]->inmapfile) writeSymbol(map->symbolset.symbol[i], stream); } writeProjection(stream, indent, &(map->projection)); writeLegend(stream, indent, &(map->legend)); writeQueryMap(stream, indent, &(map->querymap)); writeReferenceMap(stream, indent, &(map->reference)); writeScalebar(stream, indent, &(map->scalebar)); writeWeb(stream, indent, &(map->web)); for(i=0; inumlayers; i++) writeLayer(stream, indent, GET_LAYER(map, map->layerorder[i])); writeBlockEnd(stream, indent, "MAP"); } char* msWriteMapToString(mapObj *map) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeMap(stdout, 0, map); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } int msSaveMap(mapObj *map, char *filename) { FILE *stream; char szPath[MS_MAXPATHLEN]; if(!map) { msSetError(MS_MISCERR, "Map is undefined.", "msSaveMap()"); return(-1); } if(!filename) { msSetError(MS_MISCERR, "Filename is undefined.", "msSaveMap()"); return(-1); } stream = fopen(msBuildPath(szPath, map->mappath, filename), "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msSaveMap()", filename); return(-1); } writeMap(stream, 0, map); fclose(stream); return(0); } static int loadMapInternal(mapObj *map) { int foundMapToken=MS_FALSE; int token; for(;;) { token = msyylex(); if(!foundMapToken && token != MAP) { msSetError(MS_IDENTERR, "First token must be MAP, this doesn't look like a mapfile.", "msLoadMap()"); return(MS_FAILURE); } switch(token) { case(CONFIG): { char *key=NULL, *value=NULL; if( getString(&key) == MS_FAILURE ) return MS_FAILURE; if( getString(&value) == MS_FAILURE ) { free(key); return MS_FAILURE; } if (msSetConfigOption( map, key, value ) == MS_FAILURE) { free(key); free(value); return MS_FAILURE; } free( key ); free( value ); } break; case(DATAPATTERN): if(getString(&map->datapattern) == MS_FAILURE) return MS_FAILURE; break; case(DEBUG): if((map->debug = getSymbol(3, MS_ON,MS_OFF, MS_NUMBER)) == -1) return MS_FAILURE; if(map->debug == MS_NUMBER) map->debug = (int) msyynumber; break; case(END): if(msyyin) { fclose(msyyin); msyyin = NULL; } /*** Make config options current ***/ msApplyMapConfigOptions( map ); /*** Compute rotated extent info if applicable ***/ msMapComputeGeotransform( map ); /*** OUTPUTFORMAT related setup ***/ if( msPostMapParseOutputFormatSetup( map ) == MS_FAILURE ) return MS_FAILURE; if(loadSymbolSet(&(map->symbolset), map) == -1) return MS_FAILURE; if (resolveSymbolNames(map) == MS_FAILURE) return MS_FAILURE; if(msLoadFontSet(&(map->fontset), map) == -1) return MS_FAILURE; return MS_SUCCESS; break; case(EOF): msSetError(MS_EOFERR, NULL, "msLoadMap()"); return MS_FAILURE; case(EXTENT): { if(getDouble(&(map->extent.minx)) == -1) return MS_FAILURE; if(getDouble(&(map->extent.miny)) == -1) return MS_FAILURE; if(getDouble(&(map->extent.maxx)) == -1) return MS_FAILURE; if(getDouble(&(map->extent.maxy)) == -1) return MS_FAILURE; if (!MS_VALID_EXTENT(map->extent)) { msSetError(MS_MISCERR, "Given map extent is invalid. Check that it " \ "is in the form: minx, miny, maxx, maxy", "loadMapInternal()"); return MS_FAILURE; } } break; case(ANGLE): { double rotation_angle; if(getDouble(&(rotation_angle)) == -1) return MS_FAILURE; msMapSetRotation( map, rotation_angle ); } break; case(TEMPLATEPATTERN): if(getString(&map->templatepattern) == MS_FAILURE) return MS_FAILURE; break; case(FONTSET): if(getString(&map->fontset.filename) == MS_FAILURE) return MS_FAILURE; break; case(IMAGECOLOR): if(loadColor(&(map->imagecolor), NULL) != MS_SUCCESS) return MS_FAILURE; break; case(IMAGEQUALITY): if(getInteger(&(map->imagequality)) == -1) return MS_FAILURE; break; case(IMAGETYPE): map->imagetype = getToken(); break; case(INTERLACE): if((map->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE; break; case(LATLON): msFreeProjection(&map->latlon); if(loadProjection(&map->latlon) == -1) return MS_FAILURE; break; case(LAYER): if(msGrowMapLayers(map) == NULL) return MS_FAILURE; if(initLayer((GET_LAYER(map, map->numlayers)), map) == -1) return MS_FAILURE; if(loadLayer((GET_LAYER(map, map->numlayers)), map) == -1) return MS_FAILURE; GET_LAYER(map, map->numlayers)->index = map->numlayers; /* save the index */ /* Update the layer order list with the layer's index. */ map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; break; case(OUTPUTFORMAT): if(loadOutputFormat(map) == -1) return MS_FAILURE; break; case(LEGEND): if(loadLegend(&(map->legend), map) == -1) return MS_FAILURE; break; case(MAP): foundMapToken = MS_TRUE; break; case(MAXSIZE): if(getInteger(&(map->maxsize)) == -1) return MS_FAILURE; break; case(NAME): free(map->name); map->name = NULL; /* erase default */ if(getString(&map->name) == MS_FAILURE) return MS_FAILURE; break; case(PROJECTION): if(loadProjection(&map->projection) == -1) return MS_FAILURE; break; case(QUERYMAP): if(loadQueryMap(&(map->querymap)) == -1) return MS_FAILURE; break; case(REFERENCE): if(loadReferenceMap(&(map->reference), map) == -1) return MS_FAILURE; break; case(RESOLUTION): if(getDouble(&(map->resolution)) == -1) return MS_FAILURE; break; case(DEFRESOLUTION): if(getDouble(&(map->defresolution)) == -1) return MS_FAILURE; break; case(SCALE): case(SCALEDENOM): if(getDouble(&(map->scaledenom)) == -1) return MS_FAILURE; break; case(SCALEBAR): if(loadScalebar(&(map->scalebar)) == -1) return MS_FAILURE; break; case(SHAPEPATH): if(getString(&map->shapepath) == MS_FAILURE) return MS_FAILURE; break; case(SIZE): if(getInteger(&(map->width)) == -1) return MS_FAILURE; if(getInteger(&(map->height)) == -1) return MS_FAILURE; break; case(STATUS): if((map->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE; break; case(SYMBOL): if(msGrowSymbolSet(&(map->symbolset)) == NULL) return MS_FAILURE; if((loadSymbol(map->symbolset.symbol[map->symbolset.numsymbols], map->mappath) == -1)) return MS_FAILURE; map->symbolset.symbol[map->symbolset.numsymbols]->inmapfile = MS_TRUE; map->symbolset.numsymbols++; break; case(SYMBOLSET): if(getString(&map->symbolset.filename) == MS_FAILURE) return MS_FAILURE; break; case(TRANSPARENT): if((map->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE; break; case(UNITS): if((map->units = getSymbol(7, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD)) == -1) return MS_FAILURE; break; case(WEB): if(loadWeb(&(map->web), map) == -1) return MS_FAILURE; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "msLoadMap()", msyystring_buffer, msyylineno); return MS_FAILURE; } } /* next token */ } /* ** Sets up string-based mapfile loading and calls loadMapInternal to do the work. */ mapObj *msLoadMapFromString(char *buffer, char *new_mappath) { mapObj *map; struct mstimeval starttime, endtime; char szPath[MS_MAXPATHLEN], szCWDPath[MS_MAXPATHLEN]; char *mappath=NULL; int debuglevel; debuglevel = (int)msGetGlobalDebugLevel(); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, track time spent loading/parsing mapfile. */ msGettimeofday(&starttime, NULL); } if(!buffer) { msSetError(MS_MISCERR, "No buffer to load.", "msLoadMapFromString()"); return(NULL); } /* ** Allocate mapObj structure */ map = (mapObj *)calloc(sizeof(mapObj),1); MS_CHECK_ALLOC(map, sizeof(mapObj), NULL); if(initMap(map) == -1) { /* initialize this map */ msFree(map); return(NULL); } msAcquireLock( TLOCK_PARSER ); /* might need to move this lock a bit higher, yup (bug 2108) */ msyystate = MS_TOKENIZE_STRING; msyystring = buffer; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 (do lines mean anything here?) */ /* If new_mappath is provided then use it, otherwise use the CWD */ if(NULL == getcwd(szCWDPath, MS_MAXPATHLEN)) { msSetError(MS_MISCERR, "getcwd() returned a too long path", "msLoadMapFromString()"); msFreeMap(map); msReleaseLock( TLOCK_PARSER ); } if (new_mappath) { mappath = msStrdup(new_mappath); map->mappath = msStrdup(msBuildPath(szPath, szCWDPath, mappath)); } else map->mappath = msStrdup(szCWDPath); msyybasepath = map->mappath; /* for INCLUDEs */ if(loadMapInternal(map) != MS_SUCCESS) { msFreeMap(map); msReleaseLock( TLOCK_PARSER ); if(mappath != NULL) free(mappath); return NULL; } if (mappath != NULL) free(mappath); msyylex_destroy(); msReleaseLock( TLOCK_PARSER ); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, report time spent loading/parsing mapfile. */ msGettimeofday(&endtime, NULL); msDebug("msLoadMap(): %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } if (resolveSymbolNames(map) == MS_FAILURE) return NULL; return map; } /* ** Sets up file-based mapfile loading and calls loadMapInternal to do the work. */ mapObj *msLoadMap(char *filename, char *new_mappath) { mapObj *map; struct mstimeval starttime, endtime; char szPath[MS_MAXPATHLEN], szCWDPath[MS_MAXPATHLEN]; int debuglevel; debuglevel = (int)msGetGlobalDebugLevel(); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, track time spent loading/parsing mapfile. */ msGettimeofday(&starttime, NULL); } if(!filename) { msSetError(MS_MISCERR, "Filename is undefined.", "msLoadMap()"); return(NULL); } if(getenv("MS_MAPFILE_PATTERN")) { /* user override */ if(msEvalRegex(getenv("MS_MAPFILE_PATTERN"), filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } else { /* check the default */ if(msEvalRegex(MS_DEFAULT_MAPFILE_PATTERN, filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_DEFAULT_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } /* ** Allocate mapObj structure */ map = (mapObj *)calloc(sizeof(mapObj),1); MS_CHECK_ALLOC(map, sizeof(mapObj), NULL); if(initMap(map) == -1) { /* initialize this map */ msFree(map); return(NULL); } msAcquireLock( TLOCK_PARSER ); /* Steve: might need to move this lock a bit higher; Umberto: done */ #ifdef USE_XMLMAPFILE /* If the mapfile is an xml mapfile, transform it */ if ((getenv("MS_XMLMAPFILE_XSLT")) && (msEvalRegex(MS_DEFAULT_XMLMAPFILE_PATTERN, filename) == MS_TRUE)) { msyyin = tmpfile(); if (msyyin == NULL) { msSetError(MS_IOERR, "tmpfile() failed to create temporary file", "msLoadMap()"); msReleaseLock( TLOCK_PARSER ); } if (msTransformXmlMapfile(getenv("MS_XMLMAPFILE_XSLT"), filename, msyyin) != MS_SUCCESS) { fclose(msyyin); return NULL; } fseek ( msyyin , 0 , SEEK_SET ); } else { #endif if((msyyin = fopen(filename,"r")) == NULL) { msSetError(MS_IOERR, "(%s)", "msLoadMap()", filename); msReleaseLock( TLOCK_PARSER ); return NULL; } #ifdef USE_XMLMAPFILE } #endif msyystate = MS_TOKENIZE_FILE; msyylex(); /* sets things up, but doesn't process any tokens */ msyyrestart(msyyin); /* start at line begining, line 1 */ msyylineno = 1; /* If new_mappath is provided then use it, otherwise use the location */ /* of the mapfile as the default path */ if(NULL == getcwd(szCWDPath, MS_MAXPATHLEN)) { msSetError(MS_MISCERR, "getcwd() returned a too long path", "msLoadMap()"); msFreeMap(map); msReleaseLock( TLOCK_PARSER ); } if (new_mappath) map->mappath = msStrdup(msBuildPath(szPath, szCWDPath, msStrdup(new_mappath))); else { char *path = msGetPath(filename); map->mappath = msStrdup(msBuildPath(szPath, szCWDPath, path)); if( path ) free( path ); } msyybasepath = map->mappath; /* for INCLUDEs */ if(loadMapInternal(map) != MS_SUCCESS) { msFreeMap(map); msReleaseLock( TLOCK_PARSER ); if( msyyin ) { fclose(msyyin); msyyin = NULL; } return NULL; } msReleaseLock( TLOCK_PARSER ); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, report time spent loading/parsing mapfile. */ msGettimeofday(&endtime, NULL); msDebug("msLoadMap(): %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } return map; } /* ** Loads mapfile snippets via a URL (only via the CGI so don't worry about thread locks) */ int msUpdateMapFromURL(mapObj *map, char *variable, char *string) { int i, j, k, s; errorObj *ms_error; /* make sure this configuration can be modified */ if(msLookupHashTable(&(map->web.validation), "immutable")) return(MS_SUCCESS); /* fail silently */ msyystate = MS_TOKENIZE_URL_VARIABLE; /* set lexer state and input to tokenize */ msyystring = variable; msyylineno = 1; ms_error = msGetErrorObj(); ms_error->code = MS_NOERR; /* init error code */ switch(msyylex()) { case(MAP): switch(msyylex()) { case(CONFIG): { char *key=NULL, *value=NULL; if((getString(&key) != MS_FAILURE) && (getString(&value) != MS_FAILURE)) { msSetConfigOption( map, key, value ); free( key ); key=NULL; free( value ); value=NULL; } } break; case(EXTENT): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(map->extent.minx)) == -1) break; if(getDouble(&(map->extent.miny)) == -1) break; if(getDouble(&(map->extent.maxx)) == -1) break; if(getDouble(&(map->extent.maxy)) == -1) break; if (!MS_VALID_EXTENT(map->extent)) { msSetError(MS_MISCERR, "Given map extent is invalid. Check that it is in the form: minx, miny, maxx, maxy", "msLoadMapParameterFromUrl()"); break; } msMapComputeGeotransform( map ); break; case(ANGLE): { double rotation_angle; msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(rotation_angle)) == -1) break; msMapSetRotation( map, rotation_angle ); } break; case(IMAGECOLOR): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(loadColor(&(map->imagecolor), NULL) != MS_SUCCESS) break; break; case(IMAGETYPE): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); /* TODO: should validate or does msPostMapParseOutputFormatSetup() do enough? */ map->imagetype = getToken(); msPostMapParseOutputFormatSetup( map ); break; case(LAYER): if((s = getSymbol(2, MS_NUMBER, MS_STRING)) == -1) { return MS_FAILURE; } if(s == MS_STRING) i = msGetLayerIndex(map, msyystring_buffer); else i = (int) msyynumber; if(i>=map->numlayers || i<0) { msSetError(MS_MISCERR, "Layer to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } /* make sure this layer can be modified */ if(msLookupHashTable(&(GET_LAYER(map, i)->validation), "immutable")) return(MS_SUCCESS); /* fail silently */ if(msyylex() == CLASS) { if((s = getSymbol(2, MS_NUMBER, MS_STRING)) == -1) return MS_FAILURE; if(s == MS_STRING) j = msGetClassIndex(GET_LAYER(map, i), msyystring_buffer); else j = (int) msyynumber; if(j>=GET_LAYER(map, i)->numclasses || j<0) { msSetError(MS_MISCERR, "Class to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } /* make sure this class can be modified */ if(msLookupHashTable(&(GET_LAYER(map, i)->class[j]->validation), "immutable")) return(MS_SUCCESS); /* fail silently */ switch(msyylex()) { case STYLE: if(getInteger(&k) == -1) return MS_FAILURE; if(k>=GET_LAYER(map, i)->class[j]->numstyles || k<0) { msSetError(MS_MISCERR, "Style to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } if(msUpdateStyleFromString((GET_LAYER(map, i))->class[j]->styles[k], string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; break; case LABEL: if(getInteger(&k) == -1) return MS_FAILURE; if(k>=GET_LAYER(map, i)->class[j]->numlabels || k<0) { msSetError(MS_MISCERR, "Label to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } if(msUpdateLabelFromString((GET_LAYER(map, i))->class[j]->labels[k], string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; break; default: if(msUpdateClassFromString((GET_LAYER(map, i))->class[j], string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } } else { if(msUpdateLayerFromString((GET_LAYER(map, i)), string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } /* make sure any symbol names for this layer have been resolved (bug #2700) */ for(j=0; jnumclasses; j++) { for(k=0; kclass[j]->numstyles; k++) { if(GET_LAYER(map, i)->class[j]->styles[k]->symbolname && GET_LAYER(map, i)->class[j]->styles[k]->symbol == 0) { if((GET_LAYER(map, i)->class[j]->styles[k]->symbol = msGetSymbolIndex(&(map->symbolset), GET_LAYER(map, i)->class[j]->styles[k]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class %d, style %d of layer %s.", "msUpdateMapFromURL()", GET_LAYER(map, i)->class[j]->styles[k]->symbolname, j, k, GET_LAYER(map, i)->name); return MS_FAILURE; } } if(!MS_IS_VALID_ARRAY_INDEX(GET_LAYER(map, i)->class[j]->styles[k]->symbol, map->symbolset.numsymbols)) { msSetError(MS_MISCERR, "Invalid symbol index in class %d, style %d of layer %s.", "msUpdateMapFromURL()", j, k, GET_LAYER(map, i)->name); return MS_FAILURE; } } } break; case(LEGEND): if(msyylex() == LABEL) { return msUpdateLabelFromString(&map->legend.label, string, MS_TRUE); } else { return msUpdateLegendFromString(&(map->legend), string, MS_TRUE); } case(PROJECTION): msLoadProjectionString(&(map->projection), string); break; case(QUERYMAP): return msUpdateQueryMapFromString(&(map->querymap), string, MS_TRUE); case(REFERENCE): return msUpdateReferenceMapFromString(&(map->reference), string, MS_TRUE); case(RESOLUTION): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(map->resolution)) == -1) break; break; case(DEFRESOLUTION): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(map->defresolution)) == -1) break; break; case(SCALEBAR): return msUpdateScalebarFromString(&(map->scalebar), string, MS_TRUE); case(SIZE): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getInteger(&(map->width)) == -1) break; if(getInteger(&(map->height)) == -1) break; if(map->width > map->maxsize || map->height > map->maxsize || map->width < 0 || map->height < 0) { msSetError(MS_WEBERR, "Image size out of range.", "msUpdateMapFromURL()"); break; } msMapComputeGeotransform( map ); break; case(TRANSPARENT): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if((map->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) break; msPostMapParseOutputFormatSetup( map ); break; case(UNITS): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if((map->units = getSymbol(7, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD)) == -1) break; break; case(WEB): return msUpdateWebFromString(&(map->web), string, MS_TRUE); default: break; /* malformed string */ } break; default: break; } /* msyystate = 3; */ /* restore lexer state */ /* msyylex(); */ if(ms_error->code != MS_NOERR) return(MS_FAILURE); return(MS_SUCCESS); } static int classNeedsSubstitutions(classObj *class, char *from) { if(class->expression.string && (strcasestr(class->expression.string, from) != NULL)) return MS_TRUE; if(class->text.string && (strcasestr(class->text.string, from) != NULL)) return MS_TRUE; if(class->title && (strcasestr(class->title, from) != NULL)) return MS_TRUE; return MS_FALSE; } static int layerNeedsSubstitutions(layerObj *layer, char *from) { if(layer->data && (strcasestr(layer->data, from) != NULL)) return MS_TRUE; if(layer->tileindex && (strcasestr(layer->tileindex, from) != NULL)) return MS_TRUE; if(layer->connection && (strcasestr(layer->connection, from) != NULL)) return MS_TRUE; if(layer->filter.string && (strcasestr(layer->filter.string, from) != NULL)) return MS_TRUE; if(!msHashIsEmpty(&layer->bindvals)) return MS_TRUE; return MS_FALSE; } static void classSubstituteString(classObj *class, char *from, char *to) { if(class->expression.string) class->expression.string = msCaseReplaceSubstring(class->expression.string, from, to); if(class->text.string) class->text.string = msCaseReplaceSubstring(class->text.string, from, to); if(class->title) class->title = msCaseReplaceSubstring(class->title, from, to); } static void layerSubstituteString(layerObj *layer, char *from, char *to) { char *bindvals_key, *bindvals_val; if(layer->data) layer->data = msCaseReplaceSubstring(layer->data, from, to); if(layer->tileindex) layer->tileindex = msCaseReplaceSubstring(layer->tileindex, from, to); if(layer->connection) layer->connection = msCaseReplaceSubstring(layer->connection, from, to); if(layer->filter.string) layer->filter.string = msCaseReplaceSubstring(layer->filter.string, from, to); /* The bindvalues are most useful when able to substitute values from the URL */ bindvals_key = (char*)msFirstKeyFromHashTable(&layer->bindvals); while(bindvals_key != NULL) { bindvals_val = msStrdup((char*)msLookupHashTable(&layer->bindvals, bindvals_key)); msInsertHashTable(&layer->bindvals, bindvals_key, msCaseReplaceSubstring(bindvals_val, from, to)); bindvals_key = (char*)msNextKeyFromHashTable(&layer->bindvals, bindvals_key); } } static void applyOutputFormatDefaultSubstitutions(outputFormatObj *format, const char *option, hashTableObj *table) { const char *filename; filename = msGetOutputFormatOption(format, option, NULL); if(filename && strlen(filename)>0) { char *tmpfilename = msStrdup(filename); const char *default_key = msFirstKeyFromHashTable(table); while(default_key) { if(!strncmp(default_key,"default_",8)) { char *new_filename = NULL; size_t buffer_size = (strlen(default_key)-5); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); new_filename = msStrdup(tmpfilename); new_filename = msCaseReplaceSubstring(new_filename, tag, msLookupHashTable(table, default_key)); free(tag); msSetOutputFormatOption(format, option, new_filename); free(new_filename); } default_key = msNextKeyFromHashTable(table, default_key); } msFree(tmpfilename); } return; } static void applyClassDefaultSubstitutions(classObj *class, hashTableObj *table) { const char *default_key = msFirstKeyFromHashTable(table); while(default_key) { if(!strncmp(default_key,"default_",8)) { size_t buffer_size = (strlen(default_key)-5); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); classSubstituteString(class, tag, msLookupHashTable(table, default_key)); free(tag); } default_key = msNextKeyFromHashTable(table, default_key); } return; } static void applyLayerDefaultSubstitutions(layerObj *layer, hashTableObj *table) { int i; const char *default_key = msFirstKeyFromHashTable(table); while(default_key) { if(!strncmp(default_key,"default_",8)) { size_t buffer_size = (strlen(default_key)-5); char *to = msLookupHashTable(table, default_key); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); for(i=0; inumclasses; i++) { classSubstituteString(layer->class[i], tag, to); } layerSubstituteString(layer, tag, to); free(tag); } default_key = msNextKeyFromHashTable(table, default_key); } return; } /* ** Loop through layer metadata for keys that have a default_%key% pattern to replace ** remaining %key% entries by their default value. */ void msApplyDefaultSubstitutions(mapObj *map) { int i,j; /* output formats (#3751) */ for(i=0; inumoutputformats; i++) { applyOutputFormatDefaultSubstitutions(map->outputformatlist[i], "filename", &(map->web.validation)); } for(i=0; inumlayers; i++) { layerObj *layer = GET_LAYER(map, i); for(j=0; jnumclasses; j++) { /* class settings take precedence... */ classObj *class = GET_CLASS(map, i, j); applyClassDefaultSubstitutions(class, &(class->validation)); } applyLayerDefaultSubstitutions(layer, &(layer->validation)); /* ...then layer settings... */ applyLayerDefaultSubstitutions(layer, &(map->web.validation)); /* ...and finally web settings */ } } void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs) { int i,j,k; char *tag=NULL; for(i=0; inumoutputformats; j++) { const char *filename = msGetOutputFormatOption(map->outputformatlist[j], "FILENAME", NULL); if(filename && (strcasestr(filename, tag) != NULL)) { if(msValidateParameter(values[i], msLookupHashTable(&(map->web.validation), names[i]), NULL, NULL, NULL) == MS_SUCCESS) { char *new_filename = msStrdup(filename); new_filename = msCaseReplaceSubstring(new_filename, tag, values[i]); msSetOutputFormatOption(map->outputformatlist[j], "FILENAME", new_filename); free(new_filename); } } } for(j=0; jnumlayers; j++) { layerObj *layer = GET_LAYER(map, j); /* perform class level substitutions (#4596) */ for(k=0; knumclasses; k++) { classObj *class = GET_CLASS(map, j, k); if(!classNeedsSubstitutions(class, tag)) continue; if(layer->debug >= MS_DEBUGLEVEL_V) msDebug( " runtime substitution - Layer %s, Class %s, tag %s...\n", layer->name, class->name, tag); if (msLookupHashTable(&(class->validation), names[i])) { if (msValidateParameter(values[i], msLookupHashTable(&(class->validation), names[i]), NULL, NULL, NULL) != MS_SUCCESS) { /* skip as the name exists in the class validation but does not validate */ continue; } } else if (msLookupHashTable(&(layer->validation), names[i])) { if (msValidateParameter(values[i], msLookupHashTable(&(layer->validation), names[i]), NULL, NULL, NULL) != MS_SUCCESS) { /* skip as the name exists in the layer validation but does not validate */ continue; } } else if (msValidateParameter(values[i], msLookupHashTable(&(map->web.validation), names[i]), NULL, NULL, NULL) != MS_SUCCESS) { /* skip as the web validation fails */ continue; } /* validation has succeeded in either class, layer or web */ classSubstituteString(class, tag, values[i]); } if(!layerNeedsSubstitutions(layer, tag)) continue; if(layer->debug >= MS_DEBUGLEVEL_V) msDebug( " runtime substitution - Layer %s, tag %s...\n", layer->name, tag); if (msLookupHashTable(&(layer->validation), names[i])) { if (msValidateParameter(values[i], msLookupHashTable(&(layer->validation), names[i]), NULL, NULL, NULL) != MS_SUCCESS) { /* skip as the name exists in the layer validation but does not validate */ continue; } } else if (msValidateParameter(values[i], msLookupHashTable(&(map->web.validation), names[i]), NULL, NULL, NULL) != MS_SUCCESS) { /* skip as the web validation fails */ continue; } /* validation has succeeded in either layer or web */ layerSubstituteString(layer, tag, values[i]); } msFree(tag); } /* next name/value pair */ } /* ** Returns an array with one entry per mapfile token. Useful to manipulate ** mapfiles in MapScript. ** ** The returned array should be freed using msFreeCharArray(). */ static char **tokenizeMapInternal(char *filename, int *ret_numtokens) { char **tokens = NULL; int numtokens=0, numtokens_allocated=0; size_t buffer_size = 0; *ret_numtokens = 0; if(!filename) { msSetError(MS_MISCERR, "Filename is undefined.", "msTokenizeMap()"); return NULL; } /* ** Check map filename to make sure it's legal */ if(getenv("MS_MAPFILE_PATTERN")) { /* user override */ if(msEvalRegex(getenv("MS_MAPFILE_PATTERN"), filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } else { /* check the default */ if(msEvalRegex(MS_DEFAULT_MAPFILE_PATTERN, filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_DEFAULT_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } if((msyyin = fopen(filename,"r")) == NULL) { msSetError(MS_IOERR, "(%s)", "msTokenizeMap()", filename); return NULL; } msyystate = MS_TOKENIZE_FILE; /* restore lexer state to INITIAL, and do return comments */ msyylex(); msyyreturncomments = 1; /* want all tokens, including comments */ msyyrestart(msyyin); /* start at line begining, line 1 */ msyylineno = 1; numtokens = 0; numtokens_allocated = 256; tokens = (char **) malloc(numtokens_allocated*sizeof(char*)); if(tokens == NULL) { msSetError(MS_MEMERR, NULL, "msTokenizeMap()"); fclose(msyyin); return NULL; } for(;;) { if(numtokens_allocated <= numtokens) { numtokens_allocated *= 2; /* double size of the array every time we reach the limit */ tokens = (char **)realloc(tokens, numtokens_allocated*sizeof(char*)); if(tokens == NULL) { msSetError(MS_MEMERR, "Realloc() error.", "msTokenizeMap()"); fclose(msyyin); return NULL; } } switch(msyylex()) { case(EOF): /* This is the normal way out... cleanup and exit */ fclose(msyyin); *ret_numtokens = numtokens; return(tokens); break; case(MS_STRING): buffer_size = strlen(msyystring_buffer)+2+1; tokens[numtokens] = (char*) msSmallMalloc(buffer_size); snprintf(tokens[numtokens], buffer_size, "\"%s\"", msyystring_buffer); break; case(MS_EXPRESSION): buffer_size = strlen(msyystring_buffer)+2+1; tokens[numtokens] = (char*) msSmallMalloc(buffer_size); snprintf(tokens[numtokens], buffer_size, "(%s)", msyystring_buffer); break; case(MS_REGEX): buffer_size = strlen(msyystring_buffer)+2+1; tokens[numtokens] = (char*) msSmallMalloc(buffer_size); snprintf(tokens[numtokens], buffer_size, "/%s/", msyystring_buffer); break; default: tokens[numtokens] = msStrdup(msyystring_buffer); break; } if(tokens[numtokens] == NULL) { msSetError(MS_MEMERR, NULL, "msTokenizeMap()"); fclose(msyyin); return NULL; } numtokens++; } return NULL; /* should never get here */ } /* ** Wraps tokenizeMapInternal */ char **msTokenizeMap(char *filename, int *numtokens) { char **tokens; msAcquireLock( TLOCK_PARSER ); tokens = tokenizeMapInternal( filename, numtokens ); msReleaseLock( TLOCK_PARSER ); return tokens; } void msCloseConnections(mapObj *map) { int i; layerObj *lp; for (i=0; inumlayers; i++) { lp = (GET_LAYER(map, i)); /* If the vtable is null, then the layer is never accessed or used -> skip it */ if (lp->vtable) { lp->vtable->LayerCloseConnection(lp); } } } void initResultCache(resultCacheObj *resultcache) { if (resultcache) { resultcache->results = NULL; resultcache->numresults = 0; resultcache->cachesize = 0; resultcache->bounds.minx = resultcache->bounds.miny = resultcache->bounds.maxx = resultcache->bounds.maxy = -1; resultcache->usegetshape = MS_FALSE; } } static int resolveSymbolNames(mapObj* map) { int i, j; /* step through layers and classes to resolve symbol names */ for(i=0; inumlayers; i++) { for(j=0; jnumclasses; j++) { if(classResolveSymbolNames(GET_LAYER(map, i)->class[j]) != MS_SUCCESS) return MS_FAILURE; } } return MS_SUCCESS; } mapserver-6.4.1/msautotest/0000755002461700001440000000000012261257215015524 5ustar tbonfortusersmapserver-6.4.1/mapunion.c0000644002461700001440000005623512261257215015321 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of the union layer data provider (RFC-68). * Author: Tamas Szekeres (szekerest@gmail.com). * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #define _CRT_SECURE_NO_WARNINGS 1 /* $Id$ */ #include #include "mapserver.h" #define MSUNION_NUMITEMS 3 #define MSUNION_SOURCELAYERNAME "Union:SourceLayerName" #define MSUNION_SOURCELAYERNAMEINDEX -100 #define MSUNION_SOURCELAYERGROUP "Union:SourceLayerGroup" #define MSUNION_SOURCELAYERGROUPINDEX -101 #define MSUNION_SOURCELAYERVISIBLE "Union:SourceLayerVisible" #define MSUNION_SOURCELAYERVISIBLEINDEX -102 typedef struct { int layerIndex; /* current source layer index */ int classIndex; /* current class index */ char* classText; /* current class text (autostyle) */ int layerCount; /* number of the source layers */ layerObj* layers; /* structure to the source layers */ int *status; /* the layer status */ int *classgroup; /* current array of the valid classes */ int nclasses; /* number of the valid classes */ } msUnionLayerInfo; /* Close the the combined layer */ int msUnionLayerClose(layerObj *layer) { int i; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo) return MS_SUCCESS; if (!layer->map) return MS_FAILURE; for (i = 0; i < layerinfo->layerCount; i++) { msLayerClose(&layerinfo->layers[i]); freeLayer(&layerinfo->layers[i]); } msFree(layerinfo->layers); msFree(layerinfo->status); msFree(layerinfo->classgroup); msFree(layerinfo->classText); msFree(layerinfo); layer->layerinfo = NULL; return MS_SUCCESS; } int isScaleInRange(mapObj* map, layerObj *layer) { if(map->scaledenom > 0) { int i; /* layer scale boundaries should be checked first */ if((layer->maxscaledenom > 0) && (map->scaledenom > layer->maxscaledenom)) return MS_FALSE; if((layer->minscaledenom > 0) && (map->scaledenom <= layer->minscaledenom)) return MS_FALSE; /* now check class scale boundaries (all layers *must* pass these tests) */ if(layer->numclasses > 0) { for(i=0; inumclasses; i++) { if((layer->class[i]->maxscaledenom > 0) && (map->scaledenom > layer->class[i]->maxscaledenom)) continue; /* can skip this one, next class */ if((layer->class[i]->minscaledenom > 0) && (map->scaledenom <= layer->class[i]->minscaledenom)) continue; /* can skip this one, next class */ break; /* can't skip this class (or layer for that matter) */ } if(i == layer->numclasses) return MS_FALSE; } if (layer->maxscaledenom <= 0 && layer->minscaledenom <= 0) { if((layer->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > layer->maxgeowidth)) return MS_FALSE; if((layer->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < layer->mingeowidth)) return MS_FALSE; } } return MS_TRUE; } int msUnionLayerOpen(layerObj *layer) { msUnionLayerInfo *layerinfo; char **layerNames; mapObj* map; int i; int layerCount; const char* pkey; int status_check; int scale_check; if (layer->layerinfo != NULL) { return MS_SUCCESS; /* Nothing to do... layer is already opened */ } if (!layer->connection) { msSetError(MS_MISCERR, "The CONNECTION option is not specified for layer: %s", "msUnionLayerOpen()", layer->name); return MS_FAILURE; } if (!layer->map) { msSetError(MS_MISCERR, "No map assigned to this layer: %s", "msUnionLayerOpen()", layer->name); return MS_FAILURE; } map = layer->map; layerinfo =(msUnionLayerInfo*)malloc(sizeof(msUnionLayerInfo)); MS_CHECK_ALLOC(layerinfo, sizeof(msUnionLayerInfo), MS_FAILURE); layer->layerinfo = layerinfo; layerinfo->layerIndex = 0; layerinfo->classgroup = NULL; layerinfo->nclasses = 0; layerinfo->layerCount = 0; layerinfo->classText = NULL; pkey = msLayerGetProcessingKey(layer, "UNION_STATUS_CHECK"); if(pkey && strcasecmp(pkey, "true") == 0) status_check = MS_TRUE; else status_check = MS_FALSE; pkey = msLayerGetProcessingKey(layer, "UNION_SCALE_CHECK"); if(pkey && strcasecmp(pkey, "false") == 0) scale_check = MS_FALSE; else scale_check = MS_TRUE; pkey = msLayerGetProcessingKey(layer, "UNION_SRCLAYER_CLOSE_CONNECTION"); layerNames = msStringSplit(layer->connection, ',', &layerCount); if (layerCount == 0) { msSetError(MS_MISCERR, "No source layers specified in layer: %s", "msUnionLayerOpen()", layer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } layerinfo->layers =(layerObj*)malloc(layerCount * sizeof(layerObj)); MS_CHECK_ALLOC(layerinfo->layers, layerCount * sizeof(layerObj), MS_FAILURE); layerinfo->status =(int*)malloc(layerCount * sizeof(int)); MS_CHECK_ALLOC(layerinfo->status, layerCount * sizeof(int), MS_FAILURE); for(i=0; i < layerCount; i++) { int layerindex = msGetLayerIndex(map, layerNames[i]); if (layerindex >= 0 && layerindex < map->numlayers) { layerObj* srclayer = map->layers[layerindex]; if (srclayer->type != layer->type) { msSetError(MS_MISCERR, "The type of the source layer doesn't match with the union layer: %s", "msUnionLayerOpen()", srclayer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } /* we need to create a new layer in order make the singlepass query to work */ if(initLayer(&layerinfo->layers[i], map) == -1) { msSetError(MS_MISCERR, "Cannot initialize source layer: %s", "msUnionLayerOpen()", srclayer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } ++layerinfo->layerCount; if (msCopyLayer(&layerinfo->layers[i], srclayer) != MS_SUCCESS) { msSetError(MS_MISCERR, "Cannot copy source layer: %s", "msUnionLayerOpen()", srclayer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } if (pkey) { /* override connection flag */ msLayerSetProcessingKey(&layerinfo->layers[i], "CLOSE_CONNECTION", pkey); } /* check is we should skip this source (status check) */ if (status_check && layerinfo->layers[i].status == MS_OFF) { layerinfo->status[i] = MS_DONE; continue; } /* check is we should skip this source (scale check) */ if (scale_check && isScaleInRange(map, &layerinfo->layers[i]) == MS_FALSE) { layerinfo->status[i] = MS_DONE; continue; } layerinfo->status[i] = msLayerOpen(&layerinfo->layers[i]); if (layerinfo->status[i] != MS_SUCCESS) { if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } } else { msSetError(MS_MISCERR, "Invalid layer: %s", "msUnionLayerOpen()", layerNames[i]); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } } if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); return MS_SUCCESS; } /* Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msUnionLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return(MS_TRUE); else return(MS_FALSE); } /* Free the itemindexes array in a layer. */ void msUnionLayerFreeItemInfo(layerObj *layer) { int i; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return; msFree(layer->iteminfo); layer->iteminfo = NULL; for (i = 0; i < layerinfo->layerCount; i++) { msLayerFreeItemInfo(&layerinfo->layers[i]); if(layerinfo->layers[i].items) { /* need to remove the source layer items */ msFreeCharArray(layerinfo->layers[i].items, layerinfo->layers[i].numitems); layerinfo->layers[i].items = NULL; layerinfo->layers[i].numitems = 0; } } } /* clean up expression tokens */ void msUnionLayerFreeExpressionTokens(layerObj *layer) { int i,j; freeExpressionTokens(&(layer->filter)); freeExpressionTokens(&(layer->cluster.group)); freeExpressionTokens(&(layer->cluster.filter)); for(i=0; inumclasses; i++) { freeExpressionTokens(&(layer->class[i]->expression)); freeExpressionTokens(&(layer->class[i]->text)); for(j=0; jclass[i]->numstyles; j++) freeExpressionTokens(&(layer->class[i]->styles[j]->_geomtransform)); } } /* allocate the iteminfo index array - same order as the item list */ int msUnionLayerInitItemInfo(layerObj *layer) { int i, numitems; int *itemindexes; char* itemlist = NULL; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if(layer->numitems == 0) { return MS_SUCCESS; } if (!layerinfo || !layer->map) return MS_FAILURE; /* Cleanup any previous item selection */ msUnionLayerFreeItemInfo(layer); layer->iteminfo = (int *) malloc(sizeof(int) * layer->numitems); MS_CHECK_ALLOC(layer->iteminfo, sizeof(int) * layer->numitems, MS_FAILURE); itemindexes = (int*)layer->iteminfo; /* check whether we require attributes from the source layers also */ numitems = 0; for (i = 0; i < layer->numitems; i++) { if (EQUAL(layer->items[i], MSUNION_SOURCELAYERNAME)) itemindexes[i] = MSUNION_SOURCELAYERNAMEINDEX; else if (EQUAL(layer->items[i], MSUNION_SOURCELAYERGROUP)) itemindexes[i] = MSUNION_SOURCELAYERGROUPINDEX; else if (EQUAL(layer->items[i], MSUNION_SOURCELAYERVISIBLE)) itemindexes[i] = MSUNION_SOURCELAYERVISIBLEINDEX; else { itemindexes[i] = numitems++; if (itemlist) { itemlist = msStringConcatenate(itemlist, ","); itemlist = msStringConcatenate(itemlist, layer->items[i]); } else { itemlist = msStrdup(layer->items[i]); } } } for (i = 0; i < layerinfo->layerCount; i++) { layerObj* srclayer = &layerinfo->layers[i]; if (layerinfo->status[i] != MS_SUCCESS) continue; /* skip empty layers */ msUnionLayerFreeExpressionTokens(srclayer); if (itemlist) { /* get items requested by the union layer plus the required items */ msLayerSetProcessingKey(srclayer, "ITEMS", itemlist); if (msLayerWhichItems(srclayer, MS_TRUE, NULL) != MS_SUCCESS) { msFree(itemlist); return MS_FAILURE; } } else { /* get only the required items */ if (msLayerWhichItems(srclayer, MS_FALSE, NULL) != MS_SUCCESS) return MS_FAILURE; } } msFree(itemlist); return MS_SUCCESS; } int msUnionLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i; layerObj* srclayer; rectObj srcRect; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; for (i = 0; i < layerinfo->layerCount; i++) { layerObj* srclayer = &layerinfo->layers[i]; if (layerinfo->status[i] != MS_SUCCESS) continue; /* skip empty layers */ if (layer->styleitem && layer->numitems == 0) { /* need to initialize items */ msUnionLayerFreeExpressionTokens(srclayer); /* get only the required items */ if (msLayerWhichItems(srclayer, MS_FALSE, NULL) != MS_SUCCESS) return MS_FAILURE; } srcRect = rect; #ifdef USE_PROJ if(srclayer->transform == MS_TRUE && srclayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srclayer->projection), &(layer->projection))) msProjectRect(&layer->projection, &srclayer->projection, &srcRect); /* project the searchrect to source coords */ #endif layerinfo->status[i] = msLayerWhichShapes(srclayer, srcRect, isQuery); if (layerinfo->status[i] == MS_FAILURE) return MS_FAILURE; } layerinfo->layerIndex = 0; srclayer = &layerinfo->layers[0]; msFree(layerinfo->classgroup); layerinfo->classgroup = NULL; layerinfo->nclasses = 0; if (srclayer->classgroup && srclayer->numclasses > 0) layerinfo->classgroup = msAllocateValidClassGroups(srclayer, &layerinfo->nclasses); return MS_SUCCESS; } static int BuildFeatureAttributes(layerObj *layer, layerObj* srclayer, shapeObj *shape) { int i; char **values; int* itemindexes = layer->iteminfo; values = malloc(sizeof(char*) * (layer->numitems)); MS_CHECK_ALLOC(values, layer->numitems * sizeof(char*), MS_FAILURE);; for (i = 0; i < layer->numitems; i++) { if (itemindexes[i] == MSUNION_SOURCELAYERNAMEINDEX) values[i] = msStrdup(srclayer->name); else if (itemindexes[i] == MSUNION_SOURCELAYERGROUPINDEX) values[i] = msStrdup(srclayer->group); else if (itemindexes[i] == MSUNION_SOURCELAYERVISIBLEINDEX) { if (srclayer->status == MS_OFF) values[i] = msStrdup("0"); else values[i] = msStrdup("1"); } else if (shape->values[itemindexes[i]]) values[i] = msStrdup(shape->values[itemindexes[i]]); else values[i] = msStrdup(""); } if (shape->values) msFreeCharArray(shape->values, shape->numvalues); shape->values = values; shape->numvalues = layer->numitems; return MS_SUCCESS; } /* find the next shape with the appropriate shape type */ /* also, load in the attribute data */ /* MS_DONE => no more data */ int msUnionLayerNextShape(layerObj *layer, shapeObj *shape) { int rv; layerObj* srclayer; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; if (layerinfo->layerIndex < 0 || layerinfo->layerIndex >= layerinfo->layerCount) return MS_FAILURE; rv = MS_DONE; while (layerinfo->layerIndex < layerinfo->layerCount) { srclayer = &layerinfo->layers[layerinfo->layerIndex]; if (layerinfo->status[layerinfo->layerIndex] == MS_SUCCESS) { while ((rv = srclayer->vtable->LayerNextShape(srclayer, shape)) == MS_SUCCESS) { if(layer->styleitem) { /* need to retrieve the source layer classindex if styleitem AUTO is set */ layerinfo->classIndex = msShapeGetClass(srclayer, layer->map, shape, layerinfo->classgroup, layerinfo->nclasses); if(layerinfo->classIndex < 0 || layerinfo->classIndex >= srclayer->numclasses) { /* this shape is not visible, skip it */ msFreeShape(shape); if (rv == MS_SUCCESS) continue; else break; } if(srclayer->styleitem && strcasecmp(srclayer->styleitem, "AUTO") != 0) { /* Generic feature style handling as per RFC-61 */ msLayerGetFeatureStyle(layer->map, srclayer, srclayer->class[layerinfo->classIndex], shape); } /* set up annotation */ msFree(layerinfo->classText); if(srclayer->class[layerinfo->classIndex]->numlabels > 0) { msShapeGetAnnotation(srclayer, shape); layerinfo->classText = msStrdup(srclayer->class[layerinfo->classIndex]->labels[0]->annotext); /* pull text from the first label only */ } else layerinfo->classText = NULL; } #ifdef USE_PROJ /* reproject to the target layer */ if(srclayer->project && msProjectionsDiffer(&(srclayer->projection), &(layer->projection))) msProjectShape(&(srclayer->projection), &(layer->projection), shape); else srclayer->project = MS_FALSE; #endif /* update the layer styles with the bound values */ if(msBindLayerToShape(srclayer, shape, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; shape->tileindex = layerinfo->layerIndex; /* construct the item array */ if (layer->iteminfo) rv = BuildFeatureAttributes(layer, srclayer, shape); /* check the layer filter condition */ if(layer->filter.string != NULL && layer->numitems > 0 && layer->iteminfo) { if (layer->filter.type == MS_EXPRESSION && layer->filter.tokens == NULL) msTokenizeExpression(&(layer->filter), layer->items, &(layer->numitems)); if (!msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex)) { /* this shape is filtered */ msFreeShape(shape); continue; } } return rv; } } ++layerinfo->layerIndex; if (layerinfo->layerIndex == layerinfo->layerCount) { layerinfo->layerIndex = 0; return MS_DONE; } /* allocate the classgroups for the next layer */ msFree(layerinfo->classgroup); layerinfo->classgroup = NULL; layerinfo->nclasses = 0; if (srclayer->classgroup && srclayer->numclasses > 0) layerinfo->classgroup = msAllocateValidClassGroups(srclayer, &layerinfo->nclasses); } return rv; } /* Random access of the feature. */ int msUnionLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { int rv; layerObj* srclayer; long tile = record->tileindex; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; if (tile < 0 || tile >= layerinfo->layerCount) { msSetError(MS_MISCERR, "Invalid tile index: %s", "msUnionLayerGetShape()", layer->name); return MS_FAILURE; } srclayer = &layerinfo->layers[tile]; record->tileindex = 0; rv = srclayer->vtable->LayerGetShape(srclayer, shape, record); record->tileindex = tile; if (rv == MS_SUCCESS) { #ifdef USE_PROJ /* reproject to the target layer */ if(srclayer->project && msProjectionsDiffer(&(srclayer->projection), &(layer->projection))) msProjectShape(&(srclayer->projection), &(layer->projection), shape); else srclayer->project = MS_FALSE; #endif shape->tileindex = tile; /* construct the item array */ if (layer->iteminfo) rv = BuildFeatureAttributes(layer, srclayer, shape); } return rv; } /* Query for the items collection */ int msUnionLayerGetItems(layerObj *layer) { /* we support certain built in attributes */ layer->numitems = 2; layer->items = malloc(sizeof(char*) * (layer->numitems)); MS_CHECK_ALLOC(layer->items, layer->numitems * sizeof(char*), MS_FAILURE); layer->items[0] = msStrdup(MSUNION_SOURCELAYERNAME); layer->items[1] = msStrdup(MSUNION_SOURCELAYERGROUP); return msUnionLayerInitItemInfo(layer); } int msUnionLayerGetNumFeatures(layerObj *layer) { int i, c, numFeatures; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return 0; numFeatures = 0; for (i = 0; i < layerinfo->layerCount; i++) { if (layerinfo->status[i] != MS_SUCCESS) continue; /* skip empty layers */ c = msLayerGetNumFeatures(&layerinfo->layers[i]); if (c > 0) numFeatures += c; } return numFeatures; } static int msUnionLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { layerObj* srclayer; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; if (shape->tileindex < 0 || shape->tileindex >= layerinfo->layerCount) { msSetError(MS_MISCERR, "Invalid tile index: %s", "msUnionLayerGetAutoStyle()", layer->name); return MS_FAILURE; } srclayer = &layerinfo->layers[shape->tileindex]; if(srclayer->styleitem && strcasecmp(srclayer->styleitem, "AUTO") == 0) { int rv; int tileindex = shape->tileindex; shape->tileindex = 0; rv = msLayerGetAutoStyle(map, srclayer, c, shape); shape->tileindex = tileindex; return rv; } else { int i,j; classObj* src = srclayer->class[layerinfo->classIndex]; /* copy the style from the current class index */ /* free any previous styles on the dst layer */ resetClassStyle(c); for (i = 0; i < src->numstyles; i++) { if (msMaybeAllocateClassStyle(c, i)) return MS_FAILURE; if (msCopyStyle(c->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msUnionLayerGetAutoStyle()"); return MS_FAILURE; } /* remove the bindings on the style */ for(j=0; jstyles[i]->bindings[j].item); c->styles[i]->bindings[j].item = NULL; } c->styles[i]->numbindings = 0; } for (i = 0; i < src->numlabels; i++) { // RFC77 TODO: allocation need to be done, but is the right way (from mapcopy.c)? if (msGrowClassLabels(c) == NULL) return MS_FAILURE; initLabel(c->labels[i]); if (msCopyLabel(c->labels[i], src->labels[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.", "msUnionLayerGetAutoStyle()"); return MS_FAILURE; } /* remove the bindings on the label */ for(j=0; jlabels[i]->bindings[j].item); c->labels[i]->bindings[j].item = NULL; } c->labels[i]->numbindings = 0; } c->numlabels = src->numlabels; c->type = src->type; c->layer = layer; c->text.string = layerinfo->classText; layerinfo->classText = NULL; } return MS_SUCCESS; } int msUnionLayerCopyVirtualTable(layerVTableObj* vtable) { vtable->LayerInitItemInfo = msUnionLayerInitItemInfo; vtable->LayerFreeItemInfo = msUnionLayerFreeItemInfo; vtable->LayerOpen = msUnionLayerOpen; vtable->LayerIsOpen = msUnionLayerIsOpen; vtable->LayerWhichShapes = msUnionLayerWhichShapes; vtable->LayerNextShape = msUnionLayerNextShape; vtable->LayerGetShape = msUnionLayerGetShape; vtable->LayerClose = msUnionLayerClose; vtable->LayerGetItems = msUnionLayerGetItems; vtable->LayerCloseConnection = msUnionLayerClose; vtable->LayerGetAutoStyle = msUnionLayerGetAutoStyle; vtable->LayerGetNumFeatures = msUnionLayerGetNumFeatures; return MS_SUCCESS; } int msUnionLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); return msUnionLayerCopyVirtualTable(layer->vtable); } mapserver-6.4.1/maplabel.c0000644002461700001440000014161712261257215015247 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Labeling Implementation. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ /* ** maplabel.c: Routines to enable text drawing, BITMAP or TRUETYPE. */ #include "mapserver.h" /** * replace wrap characters with \n , respecting maximal line length. * * returns a pointer to the newly allocated text. memory is controlled * inside this function, so the caller MUST use the pointer returned by * the function: * text = msWrapText(label,text); * * TODO/FIXME: function will produce erroneous/crashing? results * if the wrap character is encoded with multiple bytes * * see http://mapserver.org/development/rfc/ms-rfc-40.html * for a summary of how wrap/maxlength interact on the result * of the text transformation */ char *msWrapText(labelObj *label, char *text) { char wrap; int maxlength; if(!text) /*not an error if no text*/ return text; wrap = label->wrap; maxlength = label->maxlength; if(maxlength == 0) { if(wrap!='\0') { /* if maxlength = 0 *and* a wrap character was specified, * replace all wrap characters by \n * this is the traditional meaning of the wrap character */ msReplaceChar(text, wrap, '\n'); } /* if neither maxlength, nor wrap were specified, * don't transform this text */ return text; } else if(maxlength>0) { if(wrap!='\0') { /* split input text at the wrap character, only if * the current line length is over maxlength */ /* TODO: check if the wrap character is a valid byte * inside a multibyte utf8 glyph. if so, the msCountChars * will return an erroneous value */ int numwrapchars = msCountChars(text,wrap); if(numwrapchars > 0) { if(label->encoding) { /* we have to use utf decoding functions here, so as not to * split a text line on a multibyte character */ int num_cur_glyph_on_line = 0; /*count for the number of glyphs on the current line*/ char *textptr = text; char glyph[11]; /*storage for unicode fetching function*/ int glyphlen = 0; /*size of current glyph in bytes*/ while((glyphlen = msGetNextGlyph((const char**)&textptr,glyph))>0) { num_cur_glyph_on_line++; if(*glyph == wrap && num_cur_glyph_on_line>=(maxlength)) { /*FIXME (if wrap becomes something other than char):*/ *(textptr-1)='\n'; /*replace wrap char with a \n*/ num_cur_glyph_on_line=0; /*reset count*/ } } } else { int cur_char_on_line = 0; char *textptr = text; while(*textptr != 0) { cur_char_on_line++; if(*textptr == wrap && cur_char_on_line>=maxlength) { *textptr='\n'; /*replace wrap char with a \n*/ cur_char_on_line=0; /*reset count*/ } textptr++; } } return text; } else { /*there are no characters available for wrapping*/ return text; } } else { /* if no wrap character was specified, but a maxlength was, * don't draw this label if it is longer than the specified maxlength*/ if(msGetNumGlyphs(text)>maxlength) { free(text); return NULL; } else { return text; } } } else { /* negative maxlength: we split lines unconditionally, i.e. without loooking for a wrap character*/ int numglyphs,numlines; maxlength = -maxlength; /* use a positive value*/ numglyphs = msGetNumGlyphs(text); numlines = (numglyphs-1) / maxlength + 1; /*count total number of lines needed after splitting*/ if(numlines>1) { char *newtext = msSmallMalloc(strlen(text)+numlines+1); char *newtextptr = newtext; char *textptr = text; int glyphlen = 0, num_cur_glyph = 0; while((glyphlen = msGetNextGlyph((const char**)&textptr,newtextptr))>0) { num_cur_glyph++; newtextptr += glyphlen; if(num_cur_glyph%maxlength == 0 && num_cur_glyph != numglyphs) { /*we're at a split location, insert a newline*/ *newtextptr = '\n'; newtextptr++; } } free(text); return newtext; } else { /*no splitting needed, return the original*/ return text; } } } char *msAlignText(mapObj *map, labelObj *label, char *text) { double spacewidth=0.0; /*size of a single space, in fractional pixels*/ int numlines; char **textlines,*newtext,*newtextptr; int *textlinelengths,*numspacesforpadding; int numspacestoadd,maxlinelength,i; rectObj label_rect; if(!msCountChars(text,'\n')) return text; /*only one line*/ /*split text into individual lines * TODO: check if splitting on \n is utf8 safe*/ textlines = msStringSplit(text,'\n',&numlines); /* * label->space_size_10 contains a cache for the horizontal size of a single * 'space' character, at size 10 for the current label * FIXME: in case of attribute binding for the FONT of the label, this cache will * be wrong for labels where the attributed font is different than the first * computed font. This shouldn't happen too often, and hopefully the size of a * space character shouldn't vary too much between different fonts*/ if(label->space_size_10 == 0.0) { /*if the cache hasn't been initialized yet, or with pixmap fonts*/ /* compute the size of 16 adjacent spaces. we can't do this for just one space, * as the labelSize computing functions return integer bounding boxes. we assume * that the integer rounding for such a number of spaces will be negligeable * compared to the actual size of thoses spaces */ if(msGetLabelSize(map,label,". .",10.0,&label_rect,NULL) != MS_SUCCESS) { /*error computing label size, we can't continue*/ /*free the previously allocated split text*/ while(numlines--) free(textlines[numlines]); free(textlines); return text; } /* this is the size of a single space character. for truetype fonts, * it's the size of a 10pt space. For pixmap fonts, it's the size * for the current label */ spacewidth = (label_rect.maxx-label_rect.minx)/16.0; if(label->type == MS_TRUETYPE) { label->space_size_10=spacewidth; /*cache the computed size*/ /*size of a space for current label size*/ spacewidth = spacewidth * (double)label->size/10.0; } } else { spacewidth = label->space_size_10 * (double)label->size/10.0; } spacewidth = MS_MAX(1,spacewidth); /*length in pixels of each line*/ textlinelengths = (int*)msSmallMalloc(numlines*sizeof(int)); /*number of spaces that need to be added to each line*/ numspacesforpadding = (int*)msSmallMalloc(numlines*sizeof(int)); /*total number of spaces that need to be added*/ numspacestoadd=0; /*length in pixels of the longest line*/ maxlinelength=0; for(i=0; isize, &label_rect,NULL)) { msFreeCharArray(textlines,numlines); msFree(textlinelengths); msFree(numspacesforpadding); return text; } textlinelengths[i] = label_rect.maxx-label_rect.minx; if(maxlinelengthalign == MS_ALIGN_CENTER) { numspacesforpadding[i]=MS_NINT(nfracspaces/2.0); } else { if(label->align == MS_ALIGN_RIGHT) { numspacesforpadding[i]=MS_NINT(nfracspaces); } } numspacestoadd+=numspacesforpadding[i]; } /*allocate new text with room for the additional spaces needed*/ newtext = (char*)msSmallMalloc(strlen(text)+1+numspacestoadd); newtextptr=newtext; for(i=0; iencoding) newtext = msGetEncodedString(text, label->encoding); else newtext=msStrdup(text); if(newtext && (label->wrap!='\0' || label->maxlength!=0)) { newtext = msWrapText(label, newtext); } if(newtext && label->align!=MS_ALIGN_LEFT ) { newtext = msAlignText(map, label, newtext); } return newtext; } int msAddLabelGroup(mapObj *map, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize) { int i, priority, numactivelabels=0; labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; layerPtr = (GET_LAYER(map, layerindex)); /* set up a few pointers for clarity */ classPtr = GET_LAYER(map, layerindex)->class[classindex]; if(classPtr->numlabels == 0) return MS_SUCCESS; /* not an error just nothing to do */ for(i=0; inumlabels; i++) { if(classPtr->labels[i]->status == MS_ON) { numactivelabels++; } } if(numactivelabels == 0) return MS_SUCCESS; /* if the number of labels is 1 then call msAddLabel() accordingly */ if(numactivelabels == 1) { for(i=0; inumlabels; i++) { if(classPtr->labels[i]->status == MS_ON) return msAddLabel(map, classPtr->labels[i], layerindex, classindex, shape, point, NULL, featuresize); } } if (layerPtr->type == MS_LAYER_ANNOTATION && (cachePtr->numlabels > 1 || classPtr->leader.maxdistance)) { msSetError(MS_MISCERR, "Multiple Labels and/or LEADERs are not supported with annotation layers", "msAddLabelGroup()"); return MS_FAILURE; } /* check that the label intersects the layer mask */ if(layerPtr->mask) { int maskLayerIdx = msGetLayerIndex(map,layerPtr->mask); layerObj *maskLayer = GET_LAYER(map,maskLayerIdx); unsigned char *alphapixptr; if(maskLayer->maskimage && MS_IMAGE_RENDERER(maskLayer->maskimage)->supports_pixel_buffer) { rasterBufferObj rb; int x,y; memset(&rb,0,sizeof(rasterBufferObj)); MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,&rb); x = MS_NINT(point->x); y = MS_NINT(point->y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { #ifdef USE_GD if(rb.type == MS_BUFFER_BYTE_RGBA) { alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } } else { if(!gdImageGetPixel(rb.data.gd_img,x,y)) return MS_SUCCESS; } #else assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } #endif } } else { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msAddLabelGroup()", layerPtr->name); return (MS_FAILURE); } } /* Validate label priority value and get ref on label cache for it */ priority = classPtr->labels[0]->priority; /* take priority from the first label */ if (priority < 1) priority = 1; else if (priority > MS_MAX_LABEL_PRIORITY) priority = MS_MAX_LABEL_PRIORITY; cacheslot = &(map->labelcache.slots[priority-1]); if(cacheslot->numlabels == cacheslot->cachesize) { /* just add it to the end */ cacheslot->labels = (labelCacheMemberObj *) realloc(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->cachesize += MS_LABELCACHEINCREMENT; } cachePtr = &(cacheslot->labels[cacheslot->numlabels]); cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */ cachePtr->classindex = classindex; if(shape) { cachePtr->shapetype = shape->type; } else { cachePtr->shapetype = MS_SHAPE_POINT; } cachePtr->point = *point; /* the actual label point */ cachePtr->labelpath = NULL; cachePtr->leaderline = NULL; cachePtr->leaderbbox = NULL; // cachePtr->text = msStrdup(string); /* the actual text */ /* TODO: perhaps we can get rid of this next section and just store a marker size? Why do we cache the styles for a point layer? */ /* copy the styles (only if there is an accompanying marker) * We cannot simply keep refs because the rendering code might alters some members of the style objects */ cachePtr->styles = NULL; cachePtr->numstyles = 0; if(layerPtr->type == MS_LAYER_ANNOTATION && classPtr->numstyles > 0) { cachePtr->numstyles = classPtr->numstyles; cachePtr->styles = (styleObj *) msSmallMalloc(sizeof(styleObj)*classPtr->numstyles); if (classPtr->numstyles > 0) { for(i=0; inumstyles; i++) { initStyle(&(cachePtr->styles[i])); msCopyStyle(&(cachePtr->styles[i]), classPtr->styles[i]); } } } /* ** copy the labels (we are guaranteed to have more than one): ** we cannot simply keep refs because the rendering code alters some members of the style objects */ cachePtr->numlabels = 0; cachePtr->labels = (labelObj *) msSmallMalloc(sizeof(labelObj)*numactivelabels); for(i=0; inumlabels; i++) { if(classPtr->labels[i]->status == MS_OFF) continue; initLabel(&(cachePtr->labels[cachePtr->numlabels])); msCopyLabel(&(cachePtr->labels[cachePtr->numlabels]), classPtr->labels[i]); cachePtr->numlabels++; } assert(cachePtr->numlabels == numactivelabels); cachePtr->markerid = -1; cachePtr->featuresize = featuresize; //cachePtr->poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); //msInitShape(cachePtr->poly); cachePtr->poly = NULL; cachePtr->status = MS_FALSE; if(layerPtr->type == MS_LAYER_POINT && classPtr->numstyles > 0) { /* cache the marker placement, it's already on the map */ /* TO DO: at the moment only checks the bottom style, perhaps should check all of them */ /* #2347: after RFC-24 classPtr->styles could be NULL so we check it */ rectObj rect; double w, h; if(msGetMarkerSize(&map->symbolset, classPtr->styles[0], &w, &h, layerPtr->scalefactor) != MS_SUCCESS) return(MS_FAILURE); if(cacheslot->nummarkers == cacheslot->markercachesize) { /* just add it to the end */ cacheslot->markers = (markerCacheMemberObj *) realloc(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->markercachesize+=MS_LABELCACHEINCREMENT; } i = cacheslot->nummarkers; cacheslot->markers[i].poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(cacheslot->markers[i].poly); rect.minx = (point->x - .5 * w); rect.miny = (point->y - .5 * h); rect.maxx = rect.minx + (w-1); rect.maxy = rect.miny + (h-1); msRectToPolygon(rect, cacheslot->markers[i].poly); cacheslot->markers[i].id = cacheslot->numlabels; cachePtr->markerid = i; cacheslot->nummarkers++; } cacheslot->numlabels++; /* Maintain main labelCacheObj.numlabels only for backwards compatibility */ map->labelcache.numlabels++; return(MS_SUCCESS); } int msAddLabel(mapObj *map, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, labelPathObj *labelpath, double featuresize) { int i; labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; if(!label) return(MS_FAILURE); // RFC 77 TODO: set a proper message if(label->status == MS_OFF) return(MS_SUCCESS); /* not an error */ if(!label->annotext) { /* check if we have a labelpnt style */ for(i=0; inumstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) break; } if(i==label->numstyles) { /* label has no text or marker symbols */ return MS_SUCCESS; } } layerPtr = (GET_LAYER(map, layerindex)); /* set up a few pointers for clarity */ classPtr = GET_LAYER(map, layerindex)->class[classindex]; if(classPtr->leader.maxdistance) { if (layerPtr->type == MS_LAYER_ANNOTATION) { msSetError(MS_MISCERR, "LEADERs are not supported on annotation layers", "msAddLabel()"); return MS_FAILURE; } if(labelpath) { msSetError(MS_MISCERR, "LEADERs are not supported on ANGLE FOLLOW labels", "msAddLabel()"); return MS_FAILURE; } } /* check that the label intersects the layer mask */ if (layerPtr->mask) { int maskLayerIdx = msGetLayerIndex(map, layerPtr->mask); layerObj *maskLayer = GET_LAYER(map, maskLayerIdx); unsigned char *alphapixptr; if (maskLayer->maskimage && MS_IMAGE_RENDERER(maskLayer->maskimage)->supports_pixel_buffer) { rasterBufferObj rb; memset(&rb, 0, sizeof (rasterBufferObj)); MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage, &rb); if (point) { int x = MS_NINT(point->x); int y = MS_NINT(point->y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { #ifdef USE_GD if(rb.type == MS_BUFFER_BYTE_RGBA) { alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } } else { if(!gdImageGetPixel(rb.data.gd_img,x,y)) { return MS_SUCCESS; } } #else assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } #endif } } else if (labelpath) { int i = 0; for (i = 0; i < labelpath->path.numpoints; i++) { int x = MS_NINT(labelpath->path.point[i].x); int y = MS_NINT(labelpath->path.point[i].y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { #ifdef USE_GD if (rb.type == MS_BUFFER_BYTE_RGBA) { alphapixptr = rb.data.rgba.a + rb.data.rgba.row_step * y + rb.data.rgba.pixel_step*x; if (!*alphapixptr) { /* label point does not intersect mask */ msFreeLabelPathObj(labelpath); return MS_SUCCESS; } } else { if (!gdImageGetPixel(rb.data.gd_img, x, y)) { msFreeLabelPathObj(labelpath); return MS_SUCCESS; } } #else assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a + rb.data.rgba.row_step * y + rb.data.rgba.pixel_step*x; if (!*alphapixptr) { /* label point does not intersect mask */ msFreeLabelPathObj(labelpath); return MS_SUCCESS; } #endif } } } } else { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msAddLabel()", layerPtr->name); return (MS_FAILURE); } } /* Validate label priority value and get ref on label cache for it */ if (label->priority < 1) label->priority = 1; else if (label->priority > MS_MAX_LABEL_PRIORITY) label->priority = MS_MAX_LABEL_PRIORITY; cacheslot = &(map->labelcache.slots[label->priority-1]); if(cacheslot->numlabels == cacheslot->cachesize) { /* just add it to the end */ cacheslot->labels = (labelCacheMemberObj *) realloc(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->cachesize += MS_LABELCACHEINCREMENT; } cachePtr = &(cacheslot->labels[cacheslot->numlabels]); cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */ cachePtr->classindex = classindex; if(shape) { cachePtr->shapetype = shape->type; } else { cachePtr->shapetype = MS_SHAPE_POINT; } cachePtr->leaderline = NULL; cachePtr->leaderbbox = NULL; /* Store the label point or the label path (Bug #1620) */ if ( point ) { cachePtr->point = *point; /* the actual label point */ cachePtr->labelpath = NULL; } else { assert(labelpath); cachePtr->labelpath = labelpath; /* Use the middle point of the labelpath for mindistance calculations */ cachePtr->point = labelpath->path.point[labelpath->path.numpoints / 2]; } /* TODO: perhaps we can get rid of this next section and just store a marker size? Why do we cache the styles for a point layer? */ /* copy the styles (only if there is an accompanying marker) * We cannot simply keeep refs because the rendering code alters some members of the style objects */ cachePtr->styles = NULL; cachePtr->numstyles = 0; if(layerPtr->type == MS_LAYER_ANNOTATION && classPtr->numstyles > 0) { cachePtr->numstyles = classPtr->numstyles; cachePtr->styles = (styleObj *) msSmallMalloc(sizeof(styleObj)*classPtr->numstyles); if (classPtr->numstyles > 0) { for(i=0; inumstyles; i++) { initStyle(&(cachePtr->styles[i])); msCopyStyle(&(cachePtr->styles[i]), classPtr->styles[i]); } } } /* copy the label */ cachePtr->numlabels = 1; cachePtr->labels = (labelObj *) msSmallMalloc(sizeof(labelObj)); initLabel(cachePtr->labels); msCopyLabel(cachePtr->labels, label); cachePtr->markerid = -1; cachePtr->featuresize = featuresize; //cachePtr->poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); //msInitShape(cachePtr->poly); cachePtr->poly = NULL; cachePtr->status = MS_FALSE; if(layerPtr->type == MS_LAYER_POINT && classPtr->numstyles > 0) { /* cache the marker placement, it's already on the map */ rectObj rect; double w, h; if(cacheslot->nummarkers == cacheslot->markercachesize) { /* just add it to the end */ cacheslot->markers = (markerCacheMemberObj *) realloc(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->markercachesize+=MS_LABELCACHEINCREMENT; } i = cacheslot->nummarkers; cacheslot->markers[i].poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(cacheslot->markers[i].poly); /* TO DO: at the moment only checks the bottom style, perhaps should check all of them */ /* #2347: after RFC-24 classPtr->styles could be NULL so we check it */ if(classPtr->styles != NULL) { if(msGetMarkerSize(&map->symbolset, classPtr->styles[0], &w, &h, layerPtr->scalefactor) != MS_SUCCESS) return(MS_FAILURE); rect.minx = point->x - .5 * w; rect.miny = point->y - .5 * h; rect.maxx = rect.minx + (w-1); rect.maxy = rect.miny + (h-1); msRectToPolygon(rect, cacheslot->markers[i].poly); cacheslot->markers[i].id = cacheslot->numlabels; cachePtr->markerid = i; cacheslot->nummarkers++; } } cacheslot->numlabels++; /* Maintain main labelCacheObj.numlabels only for backwards compatibility */ map->labelcache.numlabels++; return(MS_SUCCESS); } /* ** Is a label completely in the image, reserving a gutter (in pixels) inside ** image for no labels (effectively making image larger. The gutter can be ** negative in cases where a label has a buffer around it. */ static int labelInImage(int width, int height, shapeObj *lpoly, int gutter) { int i,j; /* do a bbox test first */ if(lpoly->bounds.minx >= gutter && lpoly->bounds.miny >= gutter && lpoly->bounds.maxx < width-gutter && lpoly->bounds.maxy < height-gutter) { return MS_TRUE; } for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { if(lpoly->line[i].point[j].x < gutter) return(MS_FALSE); if(lpoly->line[i].point[j].x >= width-gutter) return(MS_FALSE); if(lpoly->line[i].point[j].y < gutter) return(MS_FALSE); if(lpoly->line[i].point[j].y >= height-gutter) return(MS_FALSE); } } return(MS_TRUE); } /* msTestLabelCacheCollisions() ** ** Compares current label against labels already drawn and markers from cache and discards it ** by setting cachePtr->status=MS_FALSE if it is a duplicate, collides with another label, ** or collides with a marker. ** ** This function is used by the various msDrawLabelCacheXX() implementations. int msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, int mapwidth, int mapheight, int buffer, labelCacheMemberObj *cachePtr, int current_priority, int current_label, int mindistance, double label_size); */ int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, shapeObj *poly, int mindistance, int current_priority, int current_label) { labelCacheObj *labelcache = &(map->labelcache); int i, p, ll, pp; double label_width = 0; labelCacheMemberObj *curCachePtr=NULL; /* * Check against image bounds first */ if(!cachePtr->labels[0].partials) { if(labelInImage(map->width, map->height, poly, labelcache->gutter) == MS_FALSE) { return MS_FALSE; } } /* compute start index of first label to test: only test against rendered labels */ if(current_label>=0) { i = current_label+1; } else { i = 0; current_label = -current_label; } /* Compare against all rendered markers from this priority level and higher. ** Labels can overlap their own marker and markers from lower priority levels */ for (p=current_priority; p < MS_MAX_LABEL_PRIORITY; p++) { labelCacheSlotObj *markerslot; markerslot = &(labelcache->slots[p]); for ( ll = 0; ll < markerslot->nummarkers; ll++ ) { if ( !(p == current_priority && current_label == markerslot->markers[ll].id ) ) { /* labels can overlap their own marker */ if ( intersectLabelPolygons(markerslot->markers[ll].poly, poly ) == MS_TRUE ) { return MS_FALSE; } } } } if(mindistance > 0) label_width = poly->bounds.maxx - poly->bounds.minx; for(p=current_priority; pslots[p]); for( ; i < cacheslot->numlabels; i++) { curCachePtr = &(cacheslot->labels[i]); if(curCachePtr->status == MS_TRUE) { /* compare bounding polygons and check for duplicates */ /* skip testing against ourself */ assert(p!=current_priority || i != current_label); /* ** Note 1: We add the label_size to the mindistance value when comparing because we do want the mindistance ** value between the labels and not only from point to point. ** ** Note 2: We only check the first label (could be multiples (RFC 77)) since that is *by far* the most common ** use case. Could change in the future but it's not worth the overhead at this point. */ if(mindistance >0 && (cachePtr->layerindex == curCachePtr->layerindex) && (cachePtr->classindex == curCachePtr->classindex) && (cachePtr->labels[0].annotext && curCachePtr->labels[0].annotext && strcmp(cachePtr->labels[0].annotext, curCachePtr->labels[0].annotext) == 0) && (msDistancePointToPoint(&(cachePtr->point), &(curCachePtr->point)) <= (mindistance + label_width))) { /* label is a duplicate */ return MS_FALSE; } if(intersectLabelPolygons(curCachePtr->poly, poly) == MS_TRUE) { /* polys intersect */ return MS_FALSE; } if(curCachePtr->leaderline) { /* our poly against rendered leader lines */ /* first do a bbox check */ if(msRectOverlap(curCachePtr->leaderbbox, &(poly->bounds))) { /* look for intersecting line segments */ for(ll=0; llnumlines; ll++) for(pp=1; ppline[ll].numpoints; pp++) if(msIntersectSegments( &(poly->line[ll].point[pp-1]), &(poly->line[ll].point[pp]), &(curCachePtr->leaderline->point[0]), &(curCachePtr->leaderline->point[1])) == MS_TRUE) { return(MS_FALSE); } } } if(cachePtr->leaderline) { /* does our leader intersect current label */ /* first do a bbox check */ if(msRectOverlap(cachePtr->leaderbbox, &(curCachePtr->poly->bounds))) { /* look for intersecting line segments */ for(ll=0; llpoly->numlines; ll++) for(pp=1; pppoly->line[ll].numpoints; pp++) if(msIntersectSegments( &(curCachePtr->poly->line[ll].point[pp-1]), &(curCachePtr->poly->line[ll].point[pp]), &(cachePtr->leaderline->point[0]), &(cachePtr->leaderline->point[1])) == MS_TRUE) { return(MS_FALSE); } } if(curCachePtr->leaderline) { /* TODO: check intersection of leader lines, not only bbox test ? */ if(msRectOverlap(curCachePtr->leaderbbox, cachePtr->leaderbbox)) { return MS_FALSE; } } } } } /* i */ i = 0; /* Start over with 1st label of next slot */ } /* p */ return MS_TRUE; } /* msGetLabelCacheMember() ** ** Returns label cache members by index, making all members of the cache ** appear as if they were stored in a single array indexed from 0 to numlabels. ** ** Returns NULL if requested index is out of range. */ labelCacheMemberObj *msGetLabelCacheMember(labelCacheObj *labelcache, int i) { if(i >= 0 && i < labelcache->numlabels) { int p; for(p=0; pslots[p].numlabels ) return &(labelcache->slots[p].labels[i]); /* Found it */ else i -= labelcache->slots[p].numlabels; /* Check next slots */ } } /* Out of range / not found */ return NULL; } int msInitFontSet(fontSetObj *fontset) { fontset->filename = NULL; /* fontset->fonts = NULL; */ initHashTable(&(fontset->fonts)); fontset->numfonts = 0; fontset->map = NULL; return( 0 ); } int msFreeFontSet(fontSetObj *fontset) { if (fontset->filename) free(fontset->filename); fontset->filename = NULL; if (&(fontset->fonts)) msFreeHashItems(&(fontset->fonts)); /* fontset->fonts = NULL; */ fontset->numfonts = 0; return( 0 ); } int msLoadFontSet(fontSetObj *fontset, mapObj *map) { FILE *stream; char buffer[MS_BUFFER_LENGTH]; char alias[64], file1[MS_PATH_LENGTH], file2[MS_PATH_LENGTH]; char *path; char szPath[MS_MAXPATHLEN]; int i; int bFullPath = 0; if(fontset->numfonts != 0) /* already initialized */ return(0); if(!fontset->filename) return(0); fontset->map = (mapObj *)map; path = msGetPath(fontset->filename); /* fontset->fonts = msCreateHashTable(); // create font hash */ /* if(!fontset->fonts) { */ /* msSetError(MS_HASHERR, "Error initializing font hash.", "msLoadFontSet()"); */ /* return(-1); */ /* } */ stream = fopen( msBuildPath(szPath, fontset->map->mappath, fontset->filename), "r"); if(!stream) { msSetError(MS_IOERR, "Error opening fontset %s.", "msLoadFontset()", fontset->filename); return(-1); } i = 0; while(fgets(buffer, MS_BUFFER_LENGTH, stream)) { /* while there's something to load */ if(buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '\r' || buffer[0] == ' ') continue; /* skip comments and blank lines */ sscanf(buffer,"%s %s", alias, file1); if (!(*file1) || !(*alias) || (strlen(file1) <= 0)) continue; bFullPath = 0; #if defined(_WIN32) && !defined(__CYGWIN__) if (file1[0] == '\\' || (strlen(file1) > 1 && (file1[1] == ':'))) bFullPath = 1; #else if(file1[0] == '/') bFullPath = 1; #endif if(bFullPath) { /* already full path */ msInsertHashTable(&(fontset->fonts), alias, file1); } else { snprintf(file2, sizeof(file2), "%s%s", path, file1); /* msInsertHashTable(fontset->fonts, alias, file2); */ /* ** msBuildPath is use here, but if we have to save the fontset file ** the msBuildPath must be done everywhere the fonts are used and ** removed here. */ msInsertHashTable(&(fontset->fonts), alias, msBuildPath(szPath, fontset->map->mappath, file2)); } i++; } fontset->numfonts = i; fclose(stream); /* close the file */ free(path); return(0); } int msGetTruetypeTextBBox(rendererVTableObj *renderer, char* fontstring, fontSetObj *fontset, double size, char *string, rectObj *rect, double **advances, int bAdjustbaseline) { outputFormatObj *format = NULL; int ret = MS_FAILURE; char *lookedUpFonts[MS_MAX_LABEL_FONTS]; int numfonts; if(!renderer) { outputFormatObj *format = msCreateDefaultOutputFormat(NULL,"AGG/PNG","tmp"); if(!format) { goto tt_cleanup; } msInitializeRendererVTable(format); renderer = format->vtable; } if(MS_FAILURE == msFontsetLookupFonts(fontstring, &numfonts, fontset, lookedUpFonts)) goto tt_cleanup; ret = renderer->getTruetypeTextBBox(renderer,lookedUpFonts,numfonts,size,string,rect,advances,bAdjustbaseline); tt_cleanup: if(format) { msFreeOutputFormat(format); } return ret; } int msGetRasterTextBBox(rendererVTableObj *renderer, int size, char *string, rectObj *rect) { if(renderer && renderer->supports_bitmap_fonts) { int num_lines=1, cur_line_length=0, max_line_length=0; char *stringPtr = string; fontMetrics *fontPtr; if((fontPtr=renderer->bitmapFontMetrics[size]) == NULL) { msSetError(MS_MISCERR, "selected renderer does not support bitmap font size %d", "msGetRasterTextBBox()",size); return MS_FAILURE; } while(*stringPtr) { if(*stringPtr=='\n') { max_line_length = MS_MAX(cur_line_length,max_line_length); num_lines++; cur_line_length=0; } else { if(*stringPtr!='\r') cur_line_length++; } stringPtr++; } max_line_length = MS_MAX(cur_line_length,max_line_length); rect->minx = 0; rect->miny = -fontPtr->charHeight; rect->maxx = fontPtr->charWidth * max_line_length; rect->maxy = fontPtr->charHeight * (num_lines-1); return MS_SUCCESS; } else if(!renderer) { int ret = MS_FAILURE; outputFormatObj *format = msCreateDefaultOutputFormat(NULL,"AGG/PNG","tmp"); if(!format) { msSetError(MS_MISCERR, "failed to create default format", "msGetRasterTextBBox()"); return MS_FAILURE; } msInitializeRendererVTable(format); renderer = format->vtable; ret = msGetRasterTextBBox(renderer,size,string,rect); msFreeOutputFormat(format); return ret; } else { msSetError(MS_MISCERR, "selected renderer does not support raster fonts", "msGetRasterTextBBox()"); return MS_FAILURE; } } char *msFontsetLookupFont(fontSetObj *fontset, char *fontKey) { char *font; if(!fontKey) { msSetError(MS_TTFERR, "Requested font (NULL) not found.", "msFontsetLookupFont()"); return NULL; } font = msLookupHashTable(&(fontset->fonts), fontKey); if(!font) { msSetError(MS_TTFERR, "Requested font (%s) not found.", "msFontsetLookupFont()", fontKey); return NULL; } return font; } int msFontsetLookupFonts(char* fontstring, int *numfonts, fontSetObj *fontset, char **lookedUpFonts) { char *start,*ptr; *numfonts = 0; start = ptr = fontstring; while(*numfontsfonts), start); *ptr = ','; if (!lookedUpFonts[*numfonts]) { msSetError(MS_TTFERR, "Requested font (%s) not found.","msFontsetLookupFonts()", fontstring); return MS_FAILURE; } start = ++ptr; (*numfonts)++; } else if(*ptr==0) { if(start==ptr) { /* last char of string was a comma */ return MS_SUCCESS; } lookedUpFonts[*numfonts] = msLookupHashTable(&(fontset->fonts), start); if (!lookedUpFonts[*numfonts]) { msSetError(MS_TTFERR, "Requested font (%s) not found.","msFontsetLookupFonts()", fontstring); return (MS_FAILURE); } (*numfonts)++; return MS_SUCCESS; } else { ptr++; } } msSetError(MS_TTFERR, "Requested font (%s) not has too many members (max is %d)", "msFontsetLookupFonts()", fontstring, MS_MAX_LABEL_FONTS); return MS_FAILURE; } /* ** Note: All these routines assume a reference point at the LL corner of the text. GD's ** bitmapped fonts use UL and this is compensated for. Note the rect is relative to the ** LL corner of the text to be rendered, this is first line for TrueType fonts. */ /* assumes an angle of 0 regardless of what's in the label object */ int msGetLabelSize(mapObj *map, labelObj *label, char *string, double size, rectObj *rect, double **advances) { rendererVTableObj *renderer = NULL; if (map) renderer =MS_MAP_RENDERER(map); if(label->type == MS_TRUETYPE) { if(!label->font) { msSetError(MS_MISCERR, "label has no true type font", "msGetLabelSize()"); return MS_FAILURE; } return msGetTruetypeTextBBox(renderer,label->font,&(map->fontset),size,string,rect,advances,1); } else if(label->type == MS_BITMAP) { if(renderer->supports_bitmap_fonts) return msGetRasterTextBBox(renderer,MS_NINT(label->size),string,rect); else { msSetError(MS_MISCERR, "renderer does not support bitmap fonts", "msGetLabelSize()"); return MS_FAILURE; } } else { msSetError(MS_MISCERR, "unknown label type", "msGetLabelSize()"); return MS_FAILURE; } } #define MARKER_SLOP 2 /*pointObj get_metrics_line(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, lineObj *poly) * called by get_metrics and drawLabelCache * the poly lineObj MUST have at least 5 points allocated in poly->point * it should also probably have poly->numpoints set to 5 */ pointObj get_metrics_line(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, lineObj *poly) { pointObj q; double x1=0, y1=0, x2=0, y2=0; double sin_a,cos_a; double w, h, x, y; w = rect.maxx - rect.minx; h = rect.maxy - rect.miny; switch(position) { case MS_UL: x1 = -w - ox; y1 = -oy; break; case MS_UC: x1 = -(w/2.0); y1 = -oy - MARKER_SLOP; break; case MS_UR: x1 = ox; y1 = -oy; break; case MS_CL: x1 = -w - ox - MARKER_SLOP; y1 = (h/2.0); break; case MS_CC: x1 = -(w/2.0) + ox; y1 = (h/2.0) + oy; break; case MS_CR: x1 = ox + MARKER_SLOP; y1 = (h/2.0); break; case MS_LL: x1 = -w - ox; y1 = h + oy; break; case MS_LC: x1 = -(w/2.0); y1 = h + oy + MARKER_SLOP; break; case MS_LR: x1 = ox; y1 = h + oy; break; } sin_a = sin(MS_DEG_TO_RAD*angle); cos_a = cos(MS_DEG_TO_RAD*angle); x = x1 - rect.minx; y = rect.maxy - y1; q.x = p->x + (x * cos_a - (y) * sin_a); q.y = p->y - (x * sin_a + (y) * cos_a); if(poly) { /* * here we should/could have a test asserting that the poly lineObj * has at least 5 points available. */ x2 = x1 - buffer; /* ll */ y2 = y1 + buffer; poly->point[0].x = p->x + (x2 * cos_a - (-y2) * sin_a); poly->point[0].y = p->y - (x2 * sin_a + (-y2) * cos_a); x2 = x1 - buffer; /* ul */ y2 = y1 - h - buffer; poly->point[1].x = p->x + (x2 * cos_a - (-y2) * sin_a); poly->point[1].y = p->y - (x2 * sin_a + (-y2) * cos_a); x2 = x1 + w + buffer; /* ur */ y2 = y1 - h - buffer; poly->point[2].x = p->x + (x2 * cos_a - (-y2) * sin_a); poly->point[2].y = p->y - (x2 * sin_a + (-y2) * cos_a); x2 = x1 + w + buffer; /* lr */ y2 = y1 + buffer; poly->point[3].x = p->x + (x2 * cos_a - (-y2) * sin_a); poly->point[3].y = p->y - (x2 * sin_a + (-y2) * cos_a); poly->point[4].x = poly->point[0].x; poly->point[4].y = poly->point[0].y; } return(q); } /* static pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly) */ pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly) { lineObj newline; pointObj newpoints[5]; pointObj rp; newline.numpoints=5; newline.point=newpoints; rp = get_metrics_line(p, position, rect, ox,oy, angle, buffer, &newline); if(poly) { msAddLine(poly,&newline); msComputeBounds(poly); } return rp; } /* ** Variation on msIntersectPolygons. Label polygons aren't like shapefile polygons. They ** have no holes, and often do have overlapping parts (i.e. road symbols). */ /* static int intersectLabelPolygons(shapeObj *p1, shapeObj *p2) { */ int intersectLabelPolygons(shapeObj *p1, shapeObj *p2) { int c1,v1,c2,v2; pointObj *point; /* STEP 0: check bounding boxes */ if(!msRectOverlap(&p1->bounds, &p2->bounds)) { /* from alans@wunderground.com */ return(MS_FALSE); } /* STEP 1: look for intersecting line segments */ for(c1=0; c1numlines; c1++) for(v1=1; v1line[c1].numpoints; v1++) for(c2=0; c2numlines; c2++) for(v2=1; v2line[c2].numpoints; v2++) if(msIntersectSegments(&(p1->line[c1].point[v1-1]), &(p1->line[c1].point[v1]), &(p2->line[c2].point[v2-1]), &(p2->line[c2].point[v2])) == MS_TRUE) { return(MS_TRUE); } /* STEP 2: polygon one completely contains two (only need to check one point from each part) */ for(c2=0; c2numlines; c2++) { point = &(p2->line[c2].point[0]); for(c1=0; c1numlines; c1++) { if(msPointInPolygon(point, &p1->line[c1]) == MS_TRUE) /* ok, the point is in a polygon */ return(MS_TRUE); } } /* STEP 3: polygon two completely contains one (only need to check one point from each part) */ for(c1=0; c1numlines; c1++) { point = &(p1->line[c1].point[0]); for(c2=0; c2numlines; c2++) { if(msPointInPolygon(point, &p2->line[c2]) == MS_TRUE) /* ok, the point is in a polygon */ return(MS_TRUE); } } return(MS_FALSE); } /* For MapScript, exactly the same the msInsertStyle */ int msInsertLabelStyle(labelObj *label, styleObj *style, int nStyleIndex) { int i; if (!style) { msSetError(MS_CHILDERR, "Can't insert a NULL Style", "msInsertLabelStyle()"); return -1; } /* Ensure there is room for a new style */ if (msGrowLabelStyles(label) == NULL) { return -1; } /* Catch attempt to insert past end of styles array */ else if (nStyleIndex >= label->numstyles) { msSetError(MS_CHILDERR, "Cannot insert style beyond index %d", "insertLabelStyle()", label->numstyles-1); return -1; } else if (nStyleIndex < 0) { /* Insert at the end by default */ label->styles[label->numstyles]=style; MS_REFCNT_INCR(style); label->numstyles++; return label->numstyles-1; } else if (nStyleIndex >= 0 && nStyleIndex < label->numstyles) { /* Move styles existing at the specified nStyleIndex or greater */ /* to a higher nStyleIndex */ for (i=label->numstyles-1; i>=nStyleIndex; i--) { label->styles[i+1] = label->styles[i]; } label->styles[nStyleIndex]=style; MS_REFCNT_INCR(style); label->numstyles++; return nStyleIndex; } else { msSetError(MS_CHILDERR, "Invalid nStyleIndex", "insertLabelStyle()"); return -1; } } /** * Move the style up inside the array of styles. */ int msMoveLabelStyleUp(labelObj *label, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (label && nStyleIndex < label->numstyles && nStyleIndex >0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, label->styles[nStyleIndex]); msCopyStyle(label->styles[nStyleIndex], label->styles[nStyleIndex-1]); msCopyStyle(label->styles[nStyleIndex-1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLabelStyleUp()", nStyleIndex); return (MS_FAILURE); } /** * Move the style down inside the array of styles. */ int msMoveLabelStyleDown(labelObj *label, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (label && nStyleIndex < label->numstyles-1 && nStyleIndex >=0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, label->styles[nStyleIndex]); msCopyStyle(label->styles[nStyleIndex], label->styles[nStyleIndex+1]); msCopyStyle(label->styles[nStyleIndex+1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLabelStyleDown()", nStyleIndex); return (MS_FAILURE); } /** * Delete the style identified by the index and shift * styles that follows the deleted style. */ int msDeleteLabelStyle(labelObj *label, int nStyleIndex) { int i = 0; if (label && nStyleIndex < label->numstyles && nStyleIndex >=0) { if (freeStyle(label->styles[nStyleIndex]) == MS_SUCCESS) msFree(label->styles[nStyleIndex]); for (i=nStyleIndex; i< label->numstyles-1; i++) { label->styles[i] = label->styles[i+1]; } label->styles[label->numstyles-1] = NULL; label->numstyles--; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msDeleteLabelStyle()", nStyleIndex); return (MS_FAILURE); } styleObj *msRemoveLabelStyle(labelObj *label, int nStyleIndex) { int i; styleObj *style; if (nStyleIndex < 0 || nStyleIndex >= label->numstyles) { msSetError(MS_CHILDERR, "Cannot remove style, invalid nStyleIndex %d", "removeLabelStyle()", nStyleIndex); return NULL; } else { style=label->styles[nStyleIndex]; for (i=nStyleIndex; inumstyles-1; i++) { label->styles[i]=label->styles[i+1]; } label->styles[label->numstyles-1]=NULL; label->numstyles--; MS_REFCNT_DECR(style); return style; } } mapserver-6.4.1/maperror.c0000644002461700001440000004150112261257215015310 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of msSetError(), msDebug() and related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 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. ****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include "maptime.h" #include #ifndef _WIN32 #include #include #endif #include static char *ms_errorCodes[MS_NUMERRORCODES] = {"", "Unable to access file.", "Memory allocation error.", "Incorrect data type.", "Symbol definition error.", "Regular expression error.", "TrueType Font error.", "DBASE file error.", "GD library error.", "Unknown identifier.", "Premature End-of-File.", "Projection library error.", "General error message.", "CGI error.", "Web application error.", "Image handling error.", "Hash table error.", "Join error.", "Search returned no results.", "Shapefile error.", "Expression parser error.", "SDE error.", "OGR error.", "Query error.", "WMS server error.", "WMS connection error.", "OracleSpatial error.", "WFS server error.", "WFS connection error.", "WMS Map Context error.", "HTTP request error.", "Child array error.", "WCS server error.", "GEOS library error.", "Invalid rectangle.", "Date/time error.", "GML encoding error.", "SOS server error.", "NULL parent pointer error.", "AGG library error.", "OWS error.", "OpenGL renderer error.", "Renderer error." }; #ifndef USE_THREAD errorObj *msGetErrorObj() { static errorObj ms_error = {MS_NOERR, "", "", MS_FALSE, NULL}; return &ms_error; } #endif #ifdef USE_THREAD typedef struct te_info { struct te_info *next; int thread_id; errorObj ms_error; } te_info_t; static te_info_t *error_list = NULL; errorObj *msGetErrorObj() { te_info_t *link; int thread_id; errorObj *ret_obj; msAcquireLock( TLOCK_ERROROBJ ); thread_id = msGetThreadId(); /* find link for this thread */ for( link = error_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} /* If the target thread link is already at the head of the list were ok */ if( error_list != NULL && error_list->thread_id == thread_id ) { } /* We don't have one ... initialize one. */ else if( link == NULL || link->next == NULL ) { te_info_t *new_link; errorObj error_obj = { MS_NOERR, "", "", 0 }; new_link = (te_info_t *) malloc(sizeof(te_info_t)); new_link->next = error_list; new_link->thread_id = thread_id; new_link->ms_error = error_obj; error_list = new_link; } /* If the link is not already at the head of the list, promote it */ else if( link != NULL && link->next != NULL ) { te_info_t *target = link->next; link->next = link->next->next; target->next = error_list; error_list = target; } ret_obj = &(error_list->ms_error); msReleaseLock( TLOCK_ERROROBJ ); return ret_obj; } #endif /* msInsertErrorObj() ** ** We maintain a chained list of errorObj in which the first errorObj is ** the most recent (i.e. a stack). msErrorReset() should be used to clear ** the list. ** ** Note that since some code in MapServer will fetch the head of the list and ** keep a handle on it for a while, the head of the chained list is static ** and never changes. ** A new errorObj is always inserted after the head, and only if the ** head of the list already contains some information. i.e. If the static ** errorObj at the head of the list is empty then it is returned directly, ** otherwise a new object is inserted after the head and the data that was in ** the head is moved to the new errorObj, freeing the head errorObj to receive ** the new error information. */ static errorObj *msInsertErrorObj(void) { errorObj *ms_error; ms_error = msGetErrorObj(); if (ms_error->code != MS_NOERR) { /* Head of the list already in use, insert a new errorObj after the head * and move head contents to this new errorObj, freeing the errorObj * for reuse. */ errorObj *new_error; new_error = (errorObj *)malloc(sizeof(errorObj)); /* Note: if malloc() failed then we simply do nothing and the head will * be overwritten by the caller... we cannot produce an error here * since we are already inside a msSetError() call. */ if (new_error) { new_error->next = ms_error->next; new_error->code = ms_error->code; new_error->isreported = ms_error->isreported; strlcpy(new_error->routine, ms_error->routine, sizeof(new_error->routine)); strlcpy(new_error->message, ms_error->message, sizeof(new_error->message)); ms_error->next = new_error; ms_error->code = MS_NOERR; ms_error->isreported = MS_FALSE; ms_error->routine[0] = '\0'; ms_error->message[0] = '\0'; } } return ms_error; } /* msResetErrorList() ** ** Clear the list of error objects. */ void msResetErrorList() { errorObj *ms_error, *this_error; ms_error = msGetErrorObj(); this_error = ms_error->next; while( this_error != NULL) { errorObj *next_error; next_error = this_error->next; msFree(this_error); this_error = next_error; } ms_error->next = NULL; ms_error->code = MS_NOERR; ms_error->routine[0] = '\0'; ms_error->message[0] = '\0'; /* -------------------------------------------------------------------- */ /* Cleanup our entry in the thread list. This is mainly */ /* imprortant when msCleanup() calls msResetErrorList(). */ /* -------------------------------------------------------------------- */ #ifdef USE_THREAD { int thread_id = msGetThreadId(); te_info_t *link; msAcquireLock( TLOCK_ERROROBJ ); /* find link for this thread */ for( link = error_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} if( link->thread_id == thread_id ) { /* presumably link is at head of list. */ if( error_list == link ) error_list = link->next; free( link ); } else if( link->next != NULL && link->next->thread_id == thread_id ) { te_info_t *next_link = link->next; link->next = link->next->next; free( next_link ); } msReleaseLock( TLOCK_ERROROBJ ); } #endif } char *msGetErrorCodeString(int code) { if(code<0 || code>MS_NUMERRORCODES-1) return("Invalid error code."); return(ms_errorCodes[code]); } /* -------------------------------------------------------------------- */ /* Adding the displayable error string to a given string */ /* and reallocates the memory enough to hold the characters. */ /* If source is null returns a newly allocated string */ /* -------------------------------------------------------------------- */ char *msAddErrorDisplayString(char *source, errorObj *error) { if((source = msStringConcatenate(source, error->routine)) == NULL) return(NULL); if((source = msStringConcatenate(source, ": ")) == NULL) return(NULL); if((source = msStringConcatenate(source, ms_errorCodes[error->code])) == NULL) return(NULL); if((source = msStringConcatenate(source, " ")) == NULL) return(NULL); if((source = msStringConcatenate(source, error->message)) == NULL) return(NULL); return source; } char *msGetErrorString(char *delimiter) { char *errstr=NULL; errorObj *error = msGetErrorObj(); if(!delimiter || !error) return(NULL); while(error && error->code != MS_NOERR) { if((errstr = msAddErrorDisplayString(errstr, error)) == NULL) return(NULL); if(error->next && error->next->code != MS_NOERR) { /* (peek ahead) more errors, use delimiter */ if((errstr = msStringConcatenate(errstr, delimiter)) == NULL) return(NULL); } error = error->next; } return(errstr); } void msSetError(int code, const char *message_fmt, const char *routine, ...) { errorObj *ms_error = msInsertErrorObj(); va_list args; ms_error->code = code; if(!routine) strcpy(ms_error->routine, ""); else { strlcpy(ms_error->routine, routine, sizeof(ms_error->routine)); } if(!message_fmt) strcpy(ms_error->message, ""); else { va_start(args, routine); vsnprintf( ms_error->message, MESSAGELENGTH, message_fmt, args ); va_end(args); } /* Log a copy of errors to MS_ERRORFILE if set (handled automatically inside msDebug()) */ msDebug("%s: %s %s\n", ms_error->routine, ms_errorCodes[ms_error->code], ms_error->message); } void msWriteError(FILE *stream) { errorObj *ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { msIO_fprintf(stream, "%s: %s %s
\n", ms_error->routine, ms_errorCodes[ms_error->code], ms_error->message); ms_error->isreported = MS_TRUE; ms_error = ms_error->next; } } void msWriteErrorXML(FILE *stream) { char *message; errorObj *ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { message = msEncodeHTMLEntities(ms_error->message); msIO_fprintf(stream, "%s: %s %s\n", ms_error->routine, ms_errorCodes[ms_error->code], message); ms_error->isreported = MS_TRUE; ms_error = ms_error->next; msFree(message); } } void msWriteErrorImage(mapObj *map, char *filename, int blank) { imageObj *img; rendererVTableObj *renderer; int font_index = 0; int width=400, height=300; int nMargin =5; int nTextLength = 0; int nUsableWidth = 0; int nMaxCharsPerLine = 0; int nLines = 0; int i = 0; int nStart = 0; int nEnd = 0; int nLength = 0; char **papszLines = NULL; int nXPos = 0; int nYPos = 0; int nWidthTxt = 0; outputFormatObj *format = NULL; char *errormsg = msGetErrorString("; "); errorObj *error = msGetErrorObj(); fontMetrics *font = NULL; char *imagepath = NULL, *imageurl = NULL; labelStyleObj ls; colorObj labelcolor, labeloutlinecolor, imagecolor, *imagecolorptr=NULL; ls.color = &labelcolor; ls.outlinecolor = &labeloutlinecolor; if(!errormsg) { errormsg = msStrdup("No error found sorry. This is likely a bug"); } if (map) { if( map->width > 0 && map->height > 0 ) { width = map->width; height = map->height; } format = map->outputformat; imagepath = map->web.imagepath; imageurl = map->web.imageurl; } /* Default to GIF if no suitable GD output format set */ if (format == NULL || !MS_RENDERER_PLUGIN(format) || !format->vtable->supports_bitmap_fonts) format = msCreateDefaultOutputFormat( NULL, "AGG/PNG8", "png" ); if(!format->transparent) { if(map && MS_VALID_COLOR(map->imagecolor)) { imagecolorptr = &map->imagecolor; } else { MS_INIT_COLOR(imagecolor,255,255,255,255); imagecolorptr = &imagecolor; } } img = msImageCreate(width,height,format,imagepath,imageurl,MS_DEFAULT_RESOLUTION,MS_DEFAULT_RESOLUTION,imagecolorptr); renderer = MS_IMAGE_RENDERER(img); for(i=0; i<5; i++) { /* use the first font we find */ if((font = renderer->bitmapFontMetrics[font_index]) != NULL) { ls.size = i; MS_INIT_COLOR(*ls.color,0,0,0,255); MS_INIT_COLOR(*ls.outlinecolor,255,255,255,255); ls.outlinewidth = 1; break; } } /* if no font found we can't do much. this shouldn't happen */ if(font) { nTextLength = strlen(errormsg); nWidthTxt = nTextLength * font->charWidth; nUsableWidth = width - (nMargin*2); /* Check to see if it all fits on one line. If not, split the text on several lines. */ if(!blank) { if (nWidthTxt > nUsableWidth) { nMaxCharsPerLine = nUsableWidth/font->charWidth; nLines = (int) ceil ((double)nTextLength / (double)nMaxCharsPerLine); if (nLines > 0) { papszLines = (char **)malloc(nLines*sizeof(char *)); for (i=0; i nTextLength) nEnd = nTextLength; nLength = nEnd-nStart; strncpy(papszLines[i], errormsg+nStart, nLength); papszLines[i][nLength] = '\0'; } } } else { nLines = 1; papszLines = (char **)malloc(nLines*sizeof(char *)); papszLines[0] = msStrdup(errormsg); } for (i=0; icharHeight) * ((i*2) +1); nXPos = font->charWidth;; renderer->renderBitmapGlyphs(img, nXPos, nYPos, &ls, papszLines[i]); } if (papszLines) { for (i=0; icode != MS_NOERR) { error->isreported = MS_TRUE; error = error->next; } if (format->refcount == 0) msFreeOutputFormat(format); msFree(errormsg); } char *msGetVersion() { static char version[1024]; sprintf(version, "MapServer version %s", MS_VERSION); #ifdef USE_GD_GIF strcat(version, " OUTPUT=GIF"); #endif #if (defined USE_GD_PNG || defined USE_PNG) strcat(version, " OUTPUT=PNG"); #endif #if (defined USE_GD_JPEG || defined USE_JPEG) strcat(version, " OUTPUT=JPEG"); #endif #ifdef USE_KML strcat(version, " OUTPUT=KML"); #endif #ifdef USE_PROJ strcat(version, " SUPPORTS=PROJ"); #endif #ifdef USE_GD strcat(version, " SUPPORTS=GD"); #endif strcat(version, " SUPPORTS=AGG"); strcat(version, " SUPPORTS=FREETYPE"); #ifdef USE_CAIRO strcat(version, " SUPPORTS=CAIRO"); #endif #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) strcat(version, " SUPPORTS=SVG_SYMBOLS"); #ifdef USE_SVG_CAIRO strcat(version, " SUPPORTS=SVGCAIRO"); #else strcat(version, " SUPPORTS=RSVG"); #endif #endif #ifdef USE_OGL strcat(version, " SUPPORTS=OPENGL"); #endif #ifdef USE_ICONV strcat(version, " SUPPORTS=ICONV"); #endif #ifdef USE_EXEMPI strcat(version, " SUPPORTS=XMP"); #endif #ifdef USE_FRIBIDI strcat(version, " SUPPORTS=FRIBIDI"); #endif #ifdef USE_WMS_SVR strcat(version, " SUPPORTS=WMS_SERVER"); #endif #ifdef USE_WMS_LYR strcat(version, " SUPPORTS=WMS_CLIENT"); #endif #ifdef USE_WFS_SVR strcat(version, " SUPPORTS=WFS_SERVER"); #endif #ifdef USE_WFS_LYR strcat(version, " SUPPORTS=WFS_CLIENT"); #endif #ifdef USE_WCS_SVR strcat(version, " SUPPORTS=WCS_SERVER"); #endif #ifdef USE_SOS_SVR strcat(version, " SUPPORTS=SOS_SERVER"); #endif #ifdef USE_FASTCGI strcat(version, " SUPPORTS=FASTCGI"); #endif #ifdef USE_THREAD strcat(version, " SUPPORTS=THREADS"); #endif #ifdef USE_GEOS strcat(version, " SUPPORTS=GEOS"); #endif #ifdef USE_POINT_Z_M strcat(version, " SUPPORTS=POINT_Z_M"); #endif #ifdef USE_JPEG strcat(version, " INPUT=JPEG"); #endif #ifdef USE_SDE strcat(version, " INPUT=SDE"); #endif #ifdef USE_POSTGIS strcat(version, " INPUT=POSTGIS"); #endif #ifdef USE_ORACLESPATIAL strcat(version, " INPUT=ORACLESPATIAL"); #endif #ifdef USE_OGR strcat(version, " INPUT=OGR"); #endif #ifdef USE_GDAL strcat(version, " INPUT=GDAL"); #endif strcat(version, " INPUT=SHAPEFILE"); return(version); } int msGetVersionInt() { return MS_VERSION_NUM; } mapserver-6.4.1/cmake/0000755002461700001440000000000012261257215014374 5ustar tbonfortusersmapserver-6.4.1/cmake/FindPHP5.cmake0000644002461700001440000000563612261257215016725 0ustar tbonfortusers# - Find PHP5 # This module finds if PHP5 is installed and determines where the include files # and libraries are. It also determines what the name of the library is. This # code sets the following variables: # # PHP5_INCLUDE_PATH = path to where php.h can be found # PHP5_EXECUTABLE = full path to the php4 binary # # file is derived from FindPHP4.cmake # SET(PHP5_FOUND "NO") SET(PHP5_POSSIBLE_INCLUDE_PATHS /usr/include/php5 /usr/local/include/php5 /usr/include/php /usr/local/include/php /usr/local/apache/php ) SET(PHP5_POSSIBLE_LIB_PATHS /usr/lib ) #FIND_PATH(PHP5_FOUND_INCLUDE_PATH main/php.h # ${PHP5_POSSIBLE_INCLUDE_PATHS}) # #IF(PHP5_FOUND_INCLUDE_PATH) # SET(php5_paths "${PHP5_POSSIBLE_INCLUDE_PATHS}") # FOREACH(php5_path Zend main TSRM) # SET(php5_paths ${php5_paths} "${PHP5_FOUND_INCLUDE_PATH}/${php5_path}") # ENDFOREACH(php5_path Zend main TSRM) # SET(PHP5_INCLUDE_PATH "${php5_paths}" INTERNAL "PHP5 include paths") #ENDIF(PHP5_FOUND_INCLUDE_PATH) FIND_PROGRAM(PHP5_EXECUTABLE NAMES php5 php PATHS /usr/local/bin ) MARK_AS_ADVANCED( PHP5_EXECUTABLE PHP5_FOUND_INCLUDE_PATH ) IF( NOT PHP5_CONFIG_EXECUTABLE ) FIND_PROGRAM(PHP5_CONFIG_EXECUTABLE NAMES php5-config php-config ) ENDIF( NOT PHP5_CONFIG_EXECUTABLE ) IF(PHP5_CONFIG_EXECUTABLE) EXECUTE_PROCESS(COMMAND ${PHP5_CONFIG_EXECUTABLE} --version OUTPUT_VARIABLE PHP5_VERSION) STRING(REPLACE "\n" "" PHP5_VERSION "${PHP5_VERSION}") EXECUTE_PROCESS(COMMAND ${PHP5_CONFIG_EXECUTABLE} --extension-dir OUTPUT_VARIABLE PHP5_EXTENSION_DIR) STRING(REPLACE "\n" "" PHP5_EXTENSION_DIR "${PHP5_EXTENSION_DIR}") EXECUTE_PROCESS(COMMAND ${PHP5_CONFIG_EXECUTABLE} --includes OUTPUT_VARIABLE PHP5_INCLUDES) STRING(REPLACE "-I" "" PHP5_INCLUDES "${PHP5_INCLUDES}") STRING(REPLACE " " ";" PHP5_INCLUDES "${PHP5_INCLUDES}") STRING(REPLACE "\n" "" PHP5_INCLUDES "${PHP5_INCLUDES}") LIST(GET PHP5_INCLUDES 0 PHP5_INCLUDE_DIR) set(PHP5_MAIN_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/main) set(PHP5_TSRM_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/TSRM) set(PHP5_ZEND_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/Zend) set(PHP5_REGEX_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/regex) set(PHP5_EXT_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/ext) set(PHP5_DATE_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/ext/date/lib) set(PHP5_STANDARD_INCLUDE_DIR ${PHP5_INCLUDE_DIR}/ext/standard) MESSAGE(STATUS ${PHP5_MAIN_INCLUDE_DIR}) IF(PHP5_VERSION LESS 5) MESSAGE(FATAL_ERROR "PHP version is not 5 or later") ENDIF(PHP5_VERSION LESS 5) IF(PHP5_EXECUTABLE AND PHP5_INCLUDES) set(PHP5_FOUND "yes") MESSAGE(STATUS "Found PHP5-Version ${PHP5_VERSION} (using ${PHP5_CONFIG_EXECUTABLE})") ENDIF(PHP5_EXECUTABLE AND PHP5_INCLUDES) FIND_PROGRAM(PHPUNIT_EXECUTABLE NAMES phpunit phpunit2 PATHS /usr/local/bin ) IF(PHPUNIT_EXECUTABLE) MESSAGE(STATUS "Found phpunit: ${PHPUNIT_EXECUTABLE}") ENDIF(PHPUNIT_EXECUTABLE) ENDIF(PHP5_CONFIG_EXECUTABLE) mapserver-6.4.1/cmake/FindGDAL.cmake0000644002461700001440000000626212261257215016714 0ustar tbonfortusers# Locate gdal # # This module accepts the following environment variables: # # GDAL_DIR or GDAL_ROOT - Specify the location of GDAL # # This module defines the following CMake variables: # # GDAL_FOUND - True if libgdal is found # GDAL_LIBRARY - A variable pointing to the GDAL library # GDAL_INCLUDE_DIR - Where to find the headers #============================================================================= # Copyright 2007-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # # $GDALDIR is an environment variable that would # correspond to the ./configure --prefix=$GDAL_DIR # used in building gdal. # # Created by Eric Wing. I'm not a gdal user, but OpenSceneGraph uses it # for osgTerrain so I whipped this module together for completeness. # I actually don't know the conventions or where files are typically # placed in distros. # Any real gdal users are encouraged to correct this (but please don't # break the OS X framework stuff when doing so which is what usually seems # to happen). # This makes the presumption that you are include gdal.h like # #include "gdal.h" find_path(GDAL_INCLUDE_DIR gdal.h HINTS ENV GDAL_DIR ENV GDAL_ROOT PATH_SUFFIXES gdal GDAL gdal1 PATHS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt ) if(UNIX) # Use gdal-config to obtain the library version (this should hopefully # allow us to -lgdal1.x.y where x.y are correct version) # For some reason, libgdal development packages do not contain # libgdal.so... find_program(GDAL_CONFIG gdal-config HINTS ENV GDAL_DIR ENV GDAL_ROOT PATH_SUFFIXES bin PATHS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt ) if(GDAL_CONFIG) exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS) if(GDAL_CONFIG_LIBS) string(REGEX MATCHALL "-l[^ ]+" _gdal_dashl ${GDAL_CONFIG_LIBS}) string(REGEX REPLACE "-l" "" _gdal_lib "${_gdal_dashl}") string(REGEX MATCHALL "-L[^ ]+" _gdal_dashL ${GDAL_CONFIG_LIBS}) string(REGEX REPLACE "-L" "" _gdal_libpath "${_gdal_dashL}") endif() endif() endif() find_library(GDAL_LIBRARY NAMES ${_gdal_lib} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL HINTS ENV GDAL_DIR ENV GDAL_ROOT ${_gdal_libpath} PATH_SUFFIXES lib PATHS /sw /opt/local /opt/csw /opt /usr/freeware ) set(GDAL_LIBRARIES ${GDAL_LIBRARY}) set(GDAL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GDAL DEFAULT_MSG GDAL_LIBRARY GDAL_INCLUDE_DIR) MARK_AS_ADVANCED(GDAL_LIBRARY GDAL_INCLUDE_DIR GDAL_CONFIG) mapserver-6.4.1/cmake/FindCairo.cmake0000644002461700001440000000632212261257215017237 0ustar tbonfortusers# - Try to find Cairo # Once done, this will define # # CAIRO_FOUND - system has Cairo # CAIRO_INCLUDE_DIR - the Cairo include directories # CAIRO_LIBRARY - link these to use Cairo # # Copyright (C) 2012 Raphael Kubo da Costa # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. FIND_PACKAGE(PkgConfig) PKG_CHECK_MODULES(PC_CAIRO cairo) # FIXME: After we require CMake 2.8.2 we can pass QUIET to this call. FIND_PATH(CAIRO_INCLUDE_DIR NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo ) IF(APPLE) #On Mountain Lion we need this for the XQuartz supplied version of cairo PKG_CHECK_MODULES(PC_FONTCONFIG fontconfig) # FIXME: After we require CMake 2.8.2 we can pass QUIET to this call. FIND_PATH(FC_INCLUDE_DIR NAMES fontconfig/fontconfig.h HINTS ${PC_FONTCONFIG_INCLUDEDIR} ) ENDIF(APPLE) FIND_LIBRARY(CAIRO_LIBRARY NAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS} ) IF (CAIRO_INCLUDE_DIR) IF (EXISTS "${CAIRO_INCLUDE_DIR}/cairo-version.h") FILE(READ "${CAIRO_INCLUDE_DIR}/cairo-version.h" CAIRO_VERSION_CONTENT) STRING(REGEX MATCH "#define +CAIRO_VERSION_MAJOR +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}") SET(CAIRO_VERSION_MAJOR "${CMAKE_MATCH_1}") STRING(REGEX MATCH "#define +CAIRO_VERSION_MINOR +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}") SET(CAIRO_VERSION_MINOR "${CMAKE_MATCH_1}") STRING(REGEX MATCH "#define +CAIRO_VERSION_MICRO +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}") SET(CAIRO_VERSION_MICRO "${CMAKE_MATCH_1}") SET(CAIRO_VERSION "${CAIRO_VERSION_MAJOR}.${CAIRO_VERSION_MINOR}.${CAIRO_VERSION_MICRO}") ENDIF () ENDIF () set(CAIRO_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR} ${FC_INCLUDE_DIR}) set(CAIRO_LIBRARIES ${CAIRO_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(CAIRO DEFAULT_MSG CAIRO_LIBRARY CAIRO_INCLUDE_DIR) mark_as_advanced(CAIRO_LIBRARY CAIRO_INCLUDE_DIR) mapserver-6.4.1/cmake/FindGD.cmake0000644002461700001440000000572612261257215016503 0ustar tbonfortusers# - Find GD # Find the native GD includes and library # This module defines # GD_INCLUDE_DIR, where to find gd.h, etc. # GD_LIBRARIES, the libraries needed to use GD. # GD_FOUND, If false, do not try to use GD. # also defined, but not for general use are # GD_LIBRARY, where to find the GD library. # GD_SUPPORTS_PNG, GD_SUPPORTS_JPEG, GD_SUPPORTS_GIF, test # support for image formats in GD. FIND_PATH(GD_INCLUDE_DIR gd.h /usr/local/include /usr/include ) if(WIN32 AND NOT CYGWIN) SET(GD_NAMES ${GD_NAMES} bgd) else(WIN32) SET(GD_NAMES ${GD_NAMES} gd) endif(WIN32 AND NOT CYGWIN) FIND_LIBRARY(GD_LIBRARY NAMES ${GD_NAMES} PATHS /usr/lib64 /usr/lib /usr/local/lib ) IF (GD_LIBRARY AND GD_INCLUDE_DIR) SET(GD_LIBRARIES ${GD_LIBRARY}) SET(GD_FOUND "YES") ELSE (GD_LIBRARY AND GD_INCLUDE_DIR) SET(GD_FOUND "NO") ENDIF (GD_LIBRARY AND GD_INCLUDE_DIR) IF (GD_FOUND) IF (WIN32 AND NOT CYGWIN) SET(GD_SUPPORTS_PNG ON) SET(GD_SUPPORTS_JPEG ON) SET(GD_SUPPORTS_GIF ON) SET(GD_SUPPORTS_FREETYPE ON) get_filename_component(GD_LIBRARY_DIR ${GD_LIBRARY} PATH) ELSE (WIN32 AND NOT CYGWIN) INCLUDE(CheckLibraryExists) GET_FILENAME_COMPONENT(GD_LIB_PATH ${GD_LIBRARY} PATH) GET_FILENAME_COMPONENT(GD_LIB ${GD_LIBRARY} NAME) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImagePng" "${GD_LIB_PATH}" GD_SUPPORTS_PNG) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageJpeg" "${GD_LIB_PATH}" GD_SUPPORTS_JPEG) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageGif" "${GD_LIB_PATH}" GD_SUPPORTS_GIF) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdFontCacheSetup" "${GD_LIB_PATH}" GD_SUPPORTS_FREETYPE) # Trim the list of include directories SET(GDINCTRIM) FOREACH(GD_DIR ${GD_INCLUDE_DIR}) SET(GD_TMP_FOUND OFF) FOREACH(GD_TRIMMED ${GDINCTRIM}) IF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}") SET(GD_TMP_FOUND ON) ENDIF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}") ENDFOREACH(GD_TRIMMED ${GDINCTRIM}) IF (NOT GD_TMP_FOUND) SET(GDINCTRIM "${GDINCTRIM}" "${GD_DIR}") ENDIF (NOT GD_TMP_FOUND) ENDFOREACH(GD_DIR ${GD_INCLUDE_DIR}) SET(GD_INCLUDE_DIR ${GDINCTRIM}) SET(GD_LIBRARY_DIR) # Generate trimmed list of library directories and list of libraries FOREACH(GD_LIB ${GD_LIBRARIES}) GET_FILENAME_COMPONENT(GD_NEXTLIBDIR ${GD_LIB} PATH) SET(GD_TMP_FOUND OFF) FOREACH(GD_LIBDIR ${GD_LIBRARY_DIR}) IF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}") SET(GD_TMP_FOUND ON) ENDIF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}") ENDFOREACH(GD_LIBDIR ${GD_LIBRARIES}) IF (NOT GD_TMP_FOUND) SET(GD_LIBRARY_DIR "${GD_LIBRARY_DIR}" "${GD_NEXTLIBDIR}") ENDIF (NOT GD_TMP_FOUND) ENDFOREACH(GD_LIB ${GD_LIBRARIES}) ENDIF (WIN32 AND NOT CYGWIN) ENDIF (GD_FOUND) IF (!GD_FOUND) IF (GD_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find GD library") ENDIF (GD_FIND_REQUIRED) ENDIF (!GD_FOUND) MARK_AS_ADVANCED( GD_LIBRARY GD_LIBRARIES GD_INCLUDE_DIR GD_LIBRARY_DIR GD_SUPPORTS_PNG GD_SUPPORTS_JPEG GD_SUPPORTS_GIF GD_SUPPORTS_FREETYPE ) mapserver-6.4.1/cmake/FindAPACHE.cmake0000644002461700001440000000163012261257215017120 0ustar tbonfortusers# # APACHE_FOUND - System has APACHE # APACHE_INCLUDE_DIR - The APACHE include directory # # APACHE_LOCATION # setting this enables search for apache libraries / headers in this location # # Include directories # find_path(APACHE_INCLUDE_DIR NAMES httpd.h PATH_SUFFIXES httpd apache apache2 ) find_program(APXS_BIN NAMES apxs apxs2 PATH_SUFFIXES httpd apache apache2 ) find_program(HTTPD_EXECUTABLE NAMES httpd PATHS /usr/sbin PATH_SUFFIXES httpd apache apache2 ) if(APXS_BIN) EXEC_PROGRAM(${APXS_BIN} ARGS -q LIBEXECDIR OUTPUT_VARIABLE APACHE_MODULE_DIR ) endif(APXS_BIN) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set APACHE_FOUND to TRUE if # all listed variables are TRUE find_package_handle_standard_args(APACHE DEFAULT_MSG APACHE_INCLUDE_DIR ) mark_as_advanced(APACHE_INCLUDE_DIR) mapserver-6.4.1/cmake/FindFreetype.cmake0000644002461700001440000000664212261257215017772 0ustar tbonfortusers# - Locate FreeType library # This module defines # FREETYPE_LIBRARIES, the library to link against # FREETYPE_FOUND, if false, do not try to link to FREETYPE # FREETYPE_INCLUDE_DIR, where to find headers. # This is the concatenation of the paths: # FREETYPE_INCLUDE_DIR_ft2build # FREETYPE_INCLUDE_DIR_freetype2 # # $FREETYPE_DIR is an environment variable that would # correspond to the ./configure --prefix=$FREETYPE_DIR # used in building FREETYPE. #============================================================================= # Copyright 2007-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distributed this file outside of CMake, substitute the full # License text for the above reference.) # Created by Eric Wing. # Modifications by Alexander Neundorf. # This file has been renamed to "FindFreetype.cmake" instead of the correct # "FindFreeType.cmake" in order to be compatible with the one from KDE4, Alex. # Ugh, FreeType seems to use some #include trickery which # makes this harder than it should be. It looks like they # put ft2build.h in a common/easier-to-find location which # then contains a #include to a more specific header in a # more specific location (#include ). # Then from there, they need to set a bunch of #define's # so you can do something like: # #include FT_FREETYPE_H # Unfortunately, using CMake's mechanisms like INCLUDE_DIRECTORIES() # wants explicit full paths and this trickery doesn't work too well. # I'm going to attempt to cut out the middleman and hope # everything still works. FIND_PATH(FREETYPE_INCLUDE_DIR_ft2build ft2build.h HINTS $ENV{FREETYPE_DIR} PATH_SUFFIXES include include/freetype2 PATHS /usr/local/X11R6/include /usr/local/X11/include /usr/X11/include /sw/include /opt/local/include /usr/freeware/include ) FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h config/ftheader.h HINTS $ENV{FREETYPE_DIR}/include/freetype2 PATHS /usr/local/X11R6/include /usr/local/X11/include /usr/X11/include /sw/include /opt/local/include /usr/freeware/include PATH_SUFFIXES freetype freetype2 ) set(FREETYPE_NAMES ${FREETYPE_NAMES} freetype libfreetype freetype219 freetype239 freetype241MT_D freetype2411) FIND_LIBRARY(FREETYPE_LIBRARY NAMES ${FREETYPE_NAMES} HINTS $ENV{FREETYPE_DIR} PATH_SUFFIXES lib64 lib x86_64-linux-gnu i386-linux-gnu PATHS /usr/local/X11R6 /usr/local/X11 /usr/X11 /sw /usr/freeware ) # set the user variables IF(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_INCLUDE_DIR "${FREETYPE_INCLUDE_DIR_ft2build};${FREETYPE_INCLUDE_DIR_freetype2}") ENDIF(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_LIBRARIES "${FREETYPE_LIBRARY}") # handle the QUIETLY and REQUIRED arguments and set FREETYPE_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Freetype DEFAULT_MSG FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR) MARK_AS_ADVANCED(FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR_freetype2 FREETYPE_INCLUDE_DIR_ft2build) mapserver-6.4.1/cmake/FindMySQL.cmake0000644002461700001440000000236612261257215017153 0ustar tbonfortusers# - Find mysqlclient # Find the native MySQL includes and library # # MYSQL_INCLUDE_DIR - where to find mysql.h, etc. # MYSQL_LIBRARIES - List of libraries when using MySQL. # MYSQL_FOUND - True if MySQL found. IF (MYSQL_INCLUDE_DIR) # Already in cache, be silent SET(MYSQL_FIND_QUIETLY TRUE) ENDIF (MYSQL_INCLUDE_DIR) FIND_PATH(MYSQL_INCLUDE_DIR mysql.h /usr/local/include/mysql /usr/include/mysql PATH_SUFFIXES mysql ) SET(MYSQL_NAMES mysqlclient mysqlclient_r libmysqlclient) FIND_LIBRARY(MYSQL_LIBRARY NAMES ${MYSQL_NAMES} PATHS /usr/lib /usr/local/lib PATH_SUFFIXES mysql ) IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) SET(MYSQL_FOUND TRUE) SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} ) ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) SET(MYSQL_FOUND FALSE) SET( MYSQL_LIBRARIES ) ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) IF (MYSQL_FOUND) IF (NOT MYSQL_FIND_QUIETLY) MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}") ENDIF (NOT MYSQL_FIND_QUIETLY) ELSE (MYSQL_FOUND) IF (MYSQL_FIND_REQUIRED) MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.") MESSAGE(FATAL_ERROR "Could NOT find MySQL library") ENDIF (MYSQL_FIND_REQUIRED) ENDIF (MYSQL_FOUND) MARK_AS_ADVANCED( MYSQL_LIBRARY MYSQL_INCLUDE_DIR ) mapserver-6.4.1/cmake/FindPerlLibs.cmake0000644002461700001440000002261212261257215017716 0ustar tbonfortusers# - Find Perl libraries # This module finds if PERL is installed and determines where the include files # and libraries are. It also determines what the name of the library is. This # code sets the following variables: # # PERLLIBS_FOUND = True if perl.h & libperl were found # PERL_INCLUDE_PATH = path to where perl.h is found # PERL_LIBRARY = path to libperl # PERL_EXECUTABLE = full path to the perl binary # # The minimum required version of Perl can be specified using the # standard syntax, e.g. find_package(PerlLibs 6.0) # # The following variables are also available if needed # (introduced after CMake 2.6.4) # # PERL_SITEARCH = path to the sitearch install dir # PERL_SITELIB = path to the sitelib install directory # PERL_VENDORARCH = path to the vendor arch install directory # PERL_VENDORLIB = path to the vendor lib install directory # PERL_ARCHLIB = path to the arch lib install directory # PERL_PRIVLIB = path to the priv lib install directory # PERL_EXTRA_C_FLAGS = Compilation flags used to build perl # #============================================================================= # Copyright 2004-2009 Kitware, Inc. # Copyright 2008 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # find the perl executable include(FindPerl) if (PERL_EXECUTABLE) if(NOT DEFINED PERL_VERSION_STRING) ### PERL_VERSION execute_process( COMMAND ${PERL_EXECUTABLE} -V:version OUTPUT_VARIABLE PERL_VERSION_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VERSION_RESULT_VARIABLE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT PERL_VERSION_RESULT_VARIABLE AND NOT PERL_VERSION_OUTPUT_VARIABLE MATCHES "^version='UNKNOWN'") string(REGEX REPLACE "version='([^']+)'.*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE}) else() execute_process( COMMAND ${PERL_EXECUTABLE} -v OUTPUT_VARIABLE PERL_VERSION_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VERSION_RESULT_VARIABLE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT PERL_VERSION_RESULT_VARIABLE AND PERL_VERSION_OUTPUT_VARIABLE MATCHES "This is perl.*[ \\(]v([0-9\\._]+)[ \\)]") string(REGEX REPLACE ".*This is perl.*[ \\(]v([0-9\\._]+)[ \\)].*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE}) elseif(NOT PERL_VERSION_RESULT_VARIABLE AND PERL_VERSION_OUTPUT_VARIABLE MATCHES "This is perl, version ([0-9\\._]+) +") string(REGEX REPLACE ".*This is perl, version ([0-9\\._]+) +.*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE}) endif() endif() endif() ### PERL_PREFIX execute_process( COMMAND ${PERL_EXECUTABLE} -V:prefix OUTPUT_VARIABLE PERL_PREFIX_OUTPUT_VARIABLE RESULT_VARIABLE PERL_PREFIX_RESULT_VARIABLE ) if (NOT PERL_PREFIX_RESULT_VARIABLE) string(REGEX REPLACE "prefix='([^']+)'.*" "\\1" PERL_PREFIX ${PERL_PREFIX_OUTPUT_VARIABLE}) endif () ### PERL_ARCHNAME execute_process( COMMAND ${PERL_EXECUTABLE} -V:archname OUTPUT_VARIABLE PERL_ARCHNAME_OUTPUT_VARIABLE RESULT_VARIABLE PERL_ARCHNAME_RESULT_VARIABLE ) if (NOT PERL_ARCHNAME_RESULT_VARIABLE) string(REGEX REPLACE "archname='([^']+)'.*" "\\1" PERL_ARCHNAME ${PERL_ARCHNAME_OUTPUT_VARIABLE}) endif () ### PERL_EXTRA_C_FLAGS execute_process( COMMAND ${PERL_EXECUTABLE} -V:cppflags OUTPUT_VARIABLE PERL_CPPFLAGS_OUTPUT_VARIABLE RESULT_VARIABLE PERL_CPPFLAGS_RESULT_VARIABLE ) if (NOT PERL_CPPFLAGS_RESULT_VARIABLE) string(REGEX REPLACE "cppflags='([^']+)'.*" "\\1" PERL_EXTRA_C_FLAGS ${PERL_CPPFLAGS_OUTPUT_VARIABLE}) endif () ### PERL_SITEARCH execute_process( COMMAND ${PERL_EXECUTABLE} -V:installsitearch OUTPUT_VARIABLE PERL_SITEARCH_OUTPUT_VARIABLE RESULT_VARIABLE PERL_SITEARCH_RESULT_VARIABLE ) if (NOT PERL_SITEARCH_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_SITEARCH ${PERL_SITEARCH_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_SITEARCH}" PERL_SITEARCH) endif () ### PERL_SITELIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:installsitelib OUTPUT_VARIABLE PERL_SITELIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_SITELIB_RESULT_VARIABLE ) if (NOT PERL_SITELIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_SITELIB ${PERL_SITELIB_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_SITELIB}" PERL_SITELIB) endif () ### PERL_VENDORARCH execute_process( COMMAND ${PERL_EXECUTABLE} -V:installvendorarch OUTPUT_VARIABLE PERL_VENDORARCH_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VENDORARCH_RESULT_VARIABLE ) if (NOT PERL_VENDORARCH_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_VENDORARCH ${PERL_VENDORARCH_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_VENDORARCH}" PERL_VENDORARCH) endif () ### PERL_VENDORLIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:installvendorlib OUTPUT_VARIABLE PERL_VENDORLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VENDORLIB_RESULT_VARIABLE ) if (NOT PERL_VENDORLIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_VENDORLIB ${PERL_VENDORLIB_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_VENDORLIB}" PERL_VENDORLIB) endif () macro(perl_adjust_darwin_lib_variable varname) string( TOUPPER PERL_${varname} FINDPERL_VARNAME ) string( TOLOWER install${varname} PERL_VARNAME ) if (NOT PERL_MINUSV_OUTPUT_VARIABLE) execute_process( COMMAND ${PERL_EXECUTABLE} -V OUTPUT_VARIABLE PERL_MINUSV_OUTPUT_VARIABLE RESULT_VARIABLE PERL_MINUSV_RESULT_VARIABLE ) endif() if (NOT PERL_MINUSV_RESULT_VARIABLE) string(REGEX MATCH "(${PERL_VARNAME}.*points? to the Updates directory)" PERL_NEEDS_ADJUSTMENT ${PERL_MINUSV_OUTPUT_VARIABLE}) if (PERL_NEEDS_ADJUSTMENT) string(REGEX REPLACE "(.*)/Updates/" "/System/\\1/" ${FINDPERL_VARNAME} ${${FINDPERL_VARNAME}}) endif () endif () endmacro() ### PERL_ARCHLIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:archlib OUTPUT_VARIABLE PERL_ARCHLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_ARCHLIB_RESULT_VARIABLE ) if (NOT PERL_ARCHLIB_RESULT_VARIABLE) string(REGEX REPLACE "[a-z]+='([^']+)'.*" "\\1" PERL_ARCHLIB ${PERL_ARCHLIB_OUTPUT_VARIABLE}) perl_adjust_darwin_lib_variable( ARCHLIB ) file(TO_CMAKE_PATH "${PERL_ARCHLIB}" PERL_ARCHLIB) endif () ### PERL_PRIVLIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:installprivlib OUTPUT_VARIABLE PERL_PRIVLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_PRIVLIB_RESULT_VARIABLE ) if (NOT PERL_PRIVLIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_PRIVLIB ${PERL_PRIVLIB_OUTPUT_VARIABLE}) perl_adjust_darwin_lib_variable( PRIVLIB ) file(TO_CMAKE_PATH "${PERL_PRIVLIB}" PERL_PRIVLIB) endif () ### PERL_POSSIBLE_LIBRARY_NAMES execute_process( COMMAND ${PERL_EXECUTABLE} -V:libperl OUTPUT_VARIABLE PERL_LIBRARY_OUTPUT_VARIABLE RESULT_VARIABLE PERL_LIBRARY_RESULT_VARIABLE ) if (NOT PERL_LIBRARY_RESULT_VARIABLE) string(REGEX REPLACE "libperl='([^']+)'.*" "\\1" PERL_POSSIBLE_LIBRARY_NAMES ${PERL_LIBRARY_OUTPUT_VARIABLE}) else () set(PERL_POSSIBLE_LIBRARY_NAMES perl${PERL_VERSION_STRING} perl) endif () ### PERL_INCLUDE_PATH find_path(PERL_INCLUDE_PATH NAMES perl.h PATHS ${PERL_ARCHLIB}/CORE /System/${PERL_ARCHLIB}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/CORE ) ### PERL_LIBRARY find_library(PERL_LIBRARY NAMES ${PERL_POSSIBLE_LIBRARY_NAMES} perl perl${PERL_VERSION_STRING} perl_i perl${PERL_VERSION_STRING}_i PATHS ${PERL_ARCHLIB}/CORE /System/${PERL_ARCHLIB}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/CORE ) endif () # handle the QUIETLY and REQUIRED arguments and set PERLLIBS_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PerlLibs REQUIRED_VARS PERL_LIBRARY PERL_INCLUDE_PATH) # Introduced after CMake 2.6.4 to bring module into compliance set(PERL_INCLUDE_DIR ${PERL_INCLUDE_PATH}) set(PERL_INCLUDE_DIRS ${PERL_INCLUDE_PATH}) set(PERL_LIBRARIES ${PERL_LIBRARY}) # For backward compatibility with CMake before 2.8.8 set(PERL_VERSION ${PERL_VERSION_STRING}) mark_as_advanced( PERL_INCLUDE_PATH PERL_LIBRARY ) mapserver-6.4.1/cmake/FindGEOS.cmake0000644002461700001440000000210612261257215016733 0ustar tbonfortusers# Find the native GEOS(Geometry Engine - Open Source) includes and libraries. # # This module defines: # # GEOS_INCLUDE_DIR, where to find geos.h, etc. # GEOS_LIBRARY, libraries to link against to use GEOS, using the geos_c library # GEOS_FOUND, True if found, false if one of the above are not found. #--- # Find include path: # Note: Version < 3.3.0 do not have geos.h in the geos sub directory; hence, # the check for both "geos/geos.h" and "geos.h". #--- find_path( GEOS_INCLUDE_DIR geos_c.h PATHS /usr/include /usr/local/include SUFFIXES geos) # Find GEOS C library: find_library( GEOS_LIBRARY NAMES geos_c geos_c_i PATHS /usr/lib64 /usr/lib /usr/local/lib ) set(GEOS_INCLUDE_DIRS ${GEOS_INCLUDE_DIR}) set(GEOS_LIBRARIES ${GEOS_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( GEOS DEFAULT_MSG GEOS_LIBRARY GEOS_INCLUDE_DIR ) MARK_AS_ADVANCED(GEOS_LIBRARY GEOS_INCLUDE_DIR) mapserver-6.4.1/cmake/FindPostgreSQL.cmake0000644002461700001440000000323012261257215020200 0ustar tbonfortusers# - Find PostgreSQL # Find the PostgreSQL includes and client library # This module defines # POSTGRESQL_INCLUDE_DIR, where to find POSTGRESQL.h # POSTGRESQL_LIBRARY, the libraries needed to use POSTGRESQL. # POSTGRESQL_FOUND, If false, do not try to use PostgreSQL. # # Copyright (c) 2013 Thomas Bonfort, Andy Colson # find_program(PG_CONFIG NAMES pg_config PATHS $ENV{ProgramFiles}/PostgreSQL/*/bin $ENV{SystemDrive}/PostgreSQL/*/bin ) if (PG_CONFIG) exec_program( ${PG_CONFIG} ARGS "--includedir" OUTPUT_VARIABLE PG_INC_PATH ) exec_program( ${PG_CONFIG} ARGS "--libdir" OUTPUT_VARIABLE PG_LIB_PATH ) else() message(WARNING "pg_config not found, will try some defaults") endif() find_path(POSTGRESQL_INCLUDE_DIR libpq-fe.h ${PG_INC_PATH} /usr/include/server /usr/include/postgresql /usr/include/pgsql/server /usr/local/include/pgsql/server /usr/include/postgresql/server /usr/include/postgresql/*/server /usr/local/include/postgresql/server /usr/local/include/postgresql/*/server $ENV{ProgramFiles}/PostgreSQL/*/include/server $ENV{SystemDrive}/PostgreSQL/*/include/server ) find_library(POSTGRESQL_LIBRARY NAMES pq libpq PATHS ${PG_LIB_PATH} /usr/lib /usr/local/lib /usr/lib/postgresql /usr/lib64 /usr/local/lib64 /usr/lib64/postgresql $ENV{ProgramFiles}/PostgreSQL/*/lib/ms $ENV{SystemDrive}/PostgreSQL/*/lib/ms ) set(POSTGRESQL_INCLUDE_DIRS ${POSTGRESQL_INCLUDE_DIR}) set(POSTGRESQL_LIBRARIES ${POSTGRESQL_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(POSTGRESQL DEFAULT_MSG POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR) mark_as_advanced(POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR) mapserver-6.4.1/cmake/FindODBC.cmake0000644002461700001440000000335612261257215016715 0ustar tbonfortusers# # Find the ODBC driver manager includes and library. # # ODBC is an open standard for connecting to different databases in a # semi-vendor-independent fashion. First you install the ODBC driver # manager. Then you need a driver for each separate database you want # to connect to (unless a generic one works). VTK includes neither # the driver manager nor the vendor-specific drivers: you have to find # those yourself. # # This module defines # ODBC_INCLUDE_DIRECTORIES, where to find sql.h # ODBC_LIBRARIES, the libraries to link against to use ODBC # ODBC_FOUND. If false, you cannot build anything that requires MySQL. # also defined, but not for general use is # ODBC_LIBRARY, where to find the ODBC driver manager library. set(ODBC_FOUND FALSE) find_path(ODBC_INCLUDE_DIR sql.h /usr/include /usr/include/odbc /usr/local/include /usr/local/include/odbc /usr/local/odbc/include "C:/Program Files/ODBC/include" "C:/Program Files/Microsoft SDKs/Windows/v7.0A/include" "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/include" "C:/Program Files/Microsoft SDKs/Windows/v6.0a/include" "C:/ODBC/include" DOC "Specify the directory containing sql.h." ) find_library(ODBC_LIBRARY NAMES iodbc odbc odbcinst odbc32 PATHS /usr/lib /usr/lib/odbc /usr/local/lib /usr/local/lib/odbc /usr/local/odbc/lib "C:/Program Files/ODBC/lib" "C:/ODBC/lib/debug" "C:/Program Files/Microsoft SDKs/Windows/v7.0A/Lib" "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" DOC "Specify the ODBC driver manager library here." ) if(ODBC_LIBRARY) if(ODBC_INCLUDE_DIR) set( ODBC_FOUND 1 ) endif() endif() set(ODBC_LIBRARIES ${ODBC_LIBRARY}) mark_as_advanced(ODBC_FOUND ODBC_LIBRARY ODBC_EXTRA_LIBRARIES ODBC_INCLUDE_DIR) mapserver-6.4.1/cmake/FindFCGI.cmake0000644002461700001440000000061012261257215016704 0ustar tbonfortusers# Look for the header file. find_path(FCGI_INCLUDE_DIR NAMES fastcgi.h) # Look for the library. find_library(FCGI_LIBRARY NAMES fcgi libfcgi) set(FCGI_INCLUDE_DIRS ${FCGI_INCLUDE_DIR}) set(FCGI_LIBRARIES ${FCGI_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FCGI DEFAULT_MSG FCGI_LIBRARY FCGI_INCLUDE_DIR) mark_as_advanced(FCGI_LIBRARY FCGI_INCLUDE_DIR) mapserver-6.4.1/cmake/FindSVGCairo.cmake0000644002461700001440000000266712261257215017627 0ustar tbonfortusers# - Find LibSVG and LibSVG-Cairo # # Following variables are provided: # SVG_FOUND # True if libsvg has been found # SVG_INCLUDE_DIR # The include directories of libsvg # SVG_LIBRARY # libsvg library list # Following variables are provided: # SVGCAIRO_FOUND # True if libsvg-cairo has been found # SVGCAIRO_INCLUDE_DIR # The include directories of libsvg-cairo # SVGCAIRO_LIBRARY # libsvg-cairo library list find_package(PkgConfig) pkg_check_modules(PC_SVG QUIET libsvg>=0.1.4) pkg_check_modules(PC_SVGCAIRO QUIET libsvg-cairo>=0.1.6) find_path(SVG_INCLUDE_DIR NAMES svg.h HINTS ${PC_SVG_INCLUDE_DIR} ${PC_SVG_INCLUDE_DIRS} ) find_library(SVG_LIBRARY NAME svg HINTS ${PC_SVG_LIBDIR} ${PC_SVG_LIBRARY_DIRS} ) find_path(SVGCAIRO_INCLUDE_DIR NAMES svg-cairo.h HINTS ${PC_SVGCAIRO_INCLUDE_DIR} ${PC_SVGCAIRO_INCLUDE_DIRS} ) find_library(SVGCAIRO_LIBRARY NAME svg-cairo HINTS ${PC_SVGCAIRO_LIBDIR} ${PC_SVGCAIRO_LIBRARY_DIRS} ) include(FindPackageHandleStandardArgs) set(SVG_INCLUDE_DIRS ${SVG_INCLUDE_DIR}) set(SVG_LIBRARIES ${SVG_LIBRARY}) find_package_handle_standard_args(SVG DEFAULT_MSG SVG_LIBRARY SVG_INCLUDE_DIR) mark_as_advanced(SVG_LIBRARY SVG_INCLUDE_DIR) set(SVGCAIRO_INCLUDE_DIRS ${SVGCAIRO_INCLUDE_DIR}) set(SVGCAIRO_LIBRARIES ${SVGCAIRO_LIBRARY}) find_package_handle_standard_args(SVGCAIRO DEFAULT_MSG SVGCAIRO_LIBRARY SVGCAIRO_INCLUDE_DIR) mark_as_advanced(SVGCAIRO_LIBRARY SVGCAIRO_INCLUDE_DIR) mapserver-6.4.1/cmake/FindRSVG.cmake0000644002461700001440000000176212261257215016766 0ustar tbonfortusers# - Find Rsvg # Find the Rsvg includes and libraries # # Following variables are provided: # RSVG_FOUND # True if Rsvg has been found # RSVG_INCLUDE_DIRS # The include directories of Rsvg # RSVG_LIBRARIES # Rsvg library list find_package(PkgConfig) pkg_check_modules(RSVG QUIET librsvg-2.0>=2.32.0) pkg_check_modules(GOBJECT QUIET gobject-2.0>=2.32.0) find_path(RSVG_INCLUDE_DIR NAMES rsvg-cairo.h HINTS ${RSVG_INCLUDE_DIRS} PATH_SUFFIXES librsvg ) find_library(RSVG_LIBRARY NAME rsvg-2 HINTS ${RSVG_LIBRARY_DIRS} ) find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${GOBJECT_INCLUDE_DIRS} ) find_library(GOBJECT_LIBRARY NAME gobject-2.0 HINTS ${GOBJECT_LIBRARY_DIRS} ) find_package_handle_standard_args(RSVG DEFAULT_MSG RSVG_LIBRARY RSVG_INCLUDE_DIR) find_package_handle_standard_args(GOBJECT DEFAULT_MSG GOBJECT_LIBRARY GOBJECT_INCLUDE_DIR) mark_as_advanced(RSVG_LIBRARY RSVG_INCLUDE_DIR RSVG_LIBRARIES RSVG_INCLUDE_DIRS GOBJECT_LIBRARY GOBJECT_INCLUDE_DIR)mapserver-6.4.1/cmake/FindExempi.cmake0000644002461700001440000000072412261257215017431 0ustar tbonfortusers# Look for the header file. find_path(LIBEXEMPI_INCLUDE_DIR NAMES xmp.h PATH_SUFFIXES exempi-2.0 exempi-2.0/exempi exempi ) find_library(LIBEXEMPI_LIBRARY NAMES exempi) set(LIBEXEMPI_LIBRARIES ${LIBEXEMPI_LIBRARY}) set(LIBEXEMPI_INCLUDE_DIRS ${LIBEXEMPI_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LIBEXEMPI DEFAULT_MSG LIBEXEMPI_LIBRARY LIBEXEMPI_INCLUDE_DIR) mark_as_advanced(LIBEXEMPI_INCLUDE_DIR LIBEXEMPI_LIBRARY) mapserver-6.4.1/cmake/FindICONV.cmake0000644002461700001440000000707012261257215017061 0ustar tbonfortusers# # Copyright (c) 2006, Peter Kümmel, # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) if (ICONV_INCLUDE_DIR) # Already in cache, be silent set(ICONV_FIND_QUIETLY TRUE) endif() find_path(ICONV_INCLUDE_DIR iconv.h PATHS /sw /opt/local ) set(POTENTIAL_ICONV_LIBS iconv libiconv libiconv2) find_library(ICONV_LIBRARY NAMES ${POTENTIAL_ICONV_LIBS} PATHS /sw /opt/local ) if(WIN32) set(ICONV_DLL_NAMES iconv.dll libiconv.dll libiconv2.dll) find_file(ICONV_DLL NAMES ${ICONV_DLL_NAMES} PATHS ENV PATH NO_DEFAULT_PATH) find_file(ICONV_DLL_HELP NAMES ${ICONV_DLL_NAMES} PATHS ENV PATH ${ICONV_INCLUDE_DIR}/../bin) if(ICONV_FIND_REQUIRED) if(NOT ICONV_DLL AND NOT ICONV_DLL_HELP) message(FATAL_ERROR "Could not find iconv.dll, please add correct your PATH environment variable") endif() if(NOT ICONV_DLL AND ICONV_DLL_HELP) get_filename_component(ICONV_DLL_HELP ${ICONV_DLL_HELP} PATH) message(STATUS) message(STATUS "Could not find iconv.dll in standard search path, please add ") message(STATUS "${ICONV_DLL_HELP}") message(STATUS "to your PATH environment variable.") message(STATUS) message(FATAL_ERROR "exit cmake") endif() endif() if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY AND ICONV_DLL) set(ICONV_FOUND TRUE) endif() else() include(CheckFunctionExists) check_function_exists(iconv HAVE_ICONV_IN_LIBC) if(ICONV_INCLUDE_DIR AND HAVE_ICONV_IN_LIBC) set(ICONV_FOUND TRUE) set(ICONV_LIBRARY CACHE TYPE STRING FORCE) endif() if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) set(ICONV_FOUND TRUE) endif() endif() if(ICONV_FOUND) if(NOT ICONV_FIND_QUIETLY) message(STATUS "Found iconv library: ${ICONV_LIBRARY}") #message(STATUS "Found iconv dll : ${ICONV_DLL}") endif() else() if(ICONV_FIND_REQUIRED) message(STATUS "Looked for iconv library named ${POTENTIAL_ICONV_LIBS}.") message(STATUS "Found no acceptable iconv library. This is fatal.") message(STATUS "iconv header: ${ICONV_INCLUDE_DIR}") message(STATUS "iconv lib : ${ICONV_LIBRARY}") message(FATAL_ERROR "Could NOT find iconv library") endif() endif() mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR) mapserver-6.4.1/cmake/FindOracle.cmake0000644002461700001440000000556312261257215017415 0ustar tbonfortusers############################################################################### # # CMake module to search for Oracle client library (OCI) # # On success, the macro sets the following variables: # ORACLE_FOUND = if the library found # ORACLE_LIBRARY = full path to the library # ORACLE_LIBRARIES = full path to the library # ORACLE_INCLUDE_DIR = where to find the library headers also defined, # but not for general use are # ORACLE_VERSION = version of library which was found, e.g. "1.2.5" # # Copyright (c) 2009-2013 Mateusz Loskot # # Developed with inspiration from Petr Vanek # who wrote similar macro for TOra - http://torasql.com/ # # Module source: http://github.com/mloskot/workshop/tree/master/cmake/ # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # ############################################################################### # If ORACLE_HOME not defined, assume Oracle libraries not available if(DEFINED ENV{ORACLE_HOME}) set(ORACLE_HOME $ENV{ORACLE_HOME}) message("ORACLE_HOME=${ORACLE_HOME}") find_path(ORACLE_INCLUDE_DIR NAMES oci.h PATHS ${ORACLE_HOME}/rdbms/public ${ORACLE_HOME}/include ${ORACLE_HOME}/sdk/include # Oracle SDK ${ORACLE_HOME}/OCI/include) # Oracle XE on Windows set(ORACLE_OCI_NAMES clntsh libclntsh oci) set(ORACLE_NNZ_NAMES nnz10 libnnz10 nnz11 libnnz11 ociw32) set(ORACLE_OCCI_NAMES libocci occi oraocci10 oraocci11) set(ORACLE_LIB_DIR ${ORACLE_HOME} ${ORACLE_HOME}/lib ${ORACLE_HOME}/sdk/lib # Oracle SDK ${ORACLE_HOME}/sdk/lib/msvc ${ORACLE_HOME}/OCI/lib/msvc) # Oracle XE on Windows find_library(ORACLE_OCI_LIBRARY NAMES ${ORACLE_OCI_NAMES} PATHS ${ORACLE_LIB_DIR}) find_library(ORACLE_OCCI_LIBRARY NAMES ${ORACLE_OCCI_NAMES} PATHS ${ORACLE_LIB_DIR}) if (NOT CMAKE_CL_64) find_library(ORACLE_NNZ_LIBRARY NAMES ${ORACLE_NNZ_NAMES} PATHS ${ORACLE_LIB_DIR}) endif() set(ORACLE_LIBRARY ${ORACLE_OCI_LIBRARY} ${ORACLE_OCCI_LIBRARY} ${ORACLE_NNZ_LIBRARY}) if(APPLE) set(ORACLE_OCIEI_NAMES libociei ociei) find_library(ORACLE_OCIEI_LIBRARY NAMES libociei ociei PATHS ${ORACLE_LIB_DIR}) if(ORACLE_OCIEI_LIBRARY) set(ORACLE_LIBRARY ${ORACLE_LIBRARY} ${ORACLE_OCIEI_LIBRARY}) else(ORACLE_OCIEI_LIBRARY) message(STATUS "libociei.dylib is not found. It may cause crash if you are building BUNDLE") endif() endif() set(ORACLE_LIBRARIES ${ORACLE_LIBRARY}) endif(DEFINED ENV{ORACLE_HOME}) # Handle the QUIETLY and REQUIRED arguments and set ORACLE_FOUND to TRUE # if all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(ORACLE DEFAULT_MSG ORACLE_LIBRARY ORACLE_INCLUDE_DIR) mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY) mapserver-6.4.1/cmake/FindFriBiDi.cmake0000644002461700001440000000152712261257215017454 0ustar tbonfortusers# - Find Fribidi # Find the Fribidi includes and libraries # # Following variables are provided: # FRIBIDI_FOUND # True if Fribidi has been found # FRIBIDI_INCLUDE_DIR # The include directories of Fribidi # FRIBIDI_LIBRARY # Fribidi library list find_package(PkgConfig) pkg_check_modules(PC_FRIBIDI QUIET fribidi>=0.19.0) find_path(FRIBIDI_INCLUDE_DIR NAMES fribidi.h HINTS ${PC_FRIBIDI_INCLUDE_DIR} ${PC_FRIBIDI_INCLUDE_DIRS} PATH_SUFFIXES fribidi ) find_library(FRIBIDI_LIBRARY NAME fribidi HINTS ${PC_FRIBIDI_LIBDIR} ${PC_FRIBIDI_LIBRARY_DIRS} ) set(FRIBIDI_INCLUDE_DIRS ${FRIBIDI_INCLUDE_DIR}) set(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FRIBIDI DEFAULT_MSG FRIBIDI_LIBRARY FRIBIDI_INCLUDE_DIR) mark_as_advanced(FRIBIDI_LIBRARY FRIBIDI_INCLUDE_DIR) mapserver-6.4.1/cmake/FindProj.cmake0000644002461700001440000000074512261257215017117 0ustar tbonfortusers# Find Proj # # If it's found it sets PROJ_FOUND to TRUE # and following variables are set: # PROJ_INCLUDE_DIR # PROJ_LIBRARY FIND_PATH(PROJ_INCLUDE_DIR proj_api.h) FIND_LIBRARY(PROJ_LIBRARY NAMES proj proj_i) set(PROJ_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) set(PROJ_LIBRARIES ${PROJ_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PROJ DEFAULT_MSG PROJ_LIBRARY PROJ_INCLUDE_DIR) mark_as_advanced(PROJ_LIBRARY PROJ_INCLUDE_DIR) mapserver-6.4.1/cmake/FindAPR.cmake0000644002461700001440000000460312261257215016624 0ustar tbonfortusers# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # - Find Apache Portable Runtime # Find the APR includes and libraries # This module defines # APR_INCLUDE_DIR and APRUTIL_INCLUDE_DIR, where to find apr.h, etc. # APR_LIBRARIES and APRUTIL_LIBRARIES, the libraries needed to use APR. # APR_FOUND and APRUTIL_FOUND, If false, do not try to use APR. # also defined, but not for general use are # APR_LIBRARY and APRUTIL_LIBRARY, where to find the APR library. # APR first. FIND_PROGRAM(APR_CONFIG_BIN NAMES apr-config apr-1-config ) if(APR_CONFIG_BIN) execute_process( COMMAND ${APR_CONFIG_BIN} --includedir OUTPUT_VARIABLE HINT_APR_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND ${APR_CONFIG_BIN} --cppflags OUTPUT_VARIABLE APR_CPPFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) endif(APR_CONFIG_BIN) FIND_PATH(APR_INCLUDE_DIR NAMES apr.h HINTS ${HINT_APR_INCLUDE_DIR} PATH_SUFFIXES apr-1 apr-1.0 apr ) FIND_LIBRARY(APR_LIBRARY NAMES apr-1 apr PATH_SUFFIXES apr-1 apr-1.0 apr ) set(APR_INCLUDE_DIRS ${APR_INCLUDE_DIR}) set(APR_LIBRARIES ${APR_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(APR DEFAULT_MSG APR_LIBRARY APR_INCLUDE_DIR) mark_as_advanced(APR_LIBRARY APR_INCLUDE_DIR) # Next, APRUTIL. FIND_PATH(APU_INCLUDE_DIR NAMES apu.h PATH_SUFFIXES apr-1 apr-1.0 apr ) FIND_LIBRARY(APU_LIBRARY NAMES aprutil-1 aprutil PATH_SUFFIXES apr-1 apr-1.0 apr ) set(APU_INCLUDE_DIRS ${APU_INCLUDE_DIR}) set(APU_LIBRARIES ${APU_LIBRARY}) find_package_handle_standard_args(APU DEFAULT_MSG APU_LIBRARY APU_INCLUDE_DIR) mark_as_advanced(APU_LIBRARY APU_INCLUDE_DIR) mapserver-6.4.1/cmake/FindSDE.cmake0000644002461700001440000000300512261257215016610 0ustar tbonfortusers# Find ESRI SDE # # If it's found it sets SDE_FOUND to TRUE # and following variables are set: # SDE_INCLUDE_DIRS # SDE_LIBRARIES FIND_PATH(SDE_INCLUDE_DIR sdetype.h PATHS ${SDE_DIR} PATH_SUFFIXES include arcsde/coverages/include ) if(SDE_VERSION STREQUAL "91") FIND_LIBRARY(SDE_LIBRARY NAMES sde91 PATHS ${SDE_DIR} PATH_SUFFIXES lib lib64) FIND_LIBRARY(PE_LIBRARY NAMES pe91 PATHS ${SDE_DIR} PATH_SUFFIXES lib lib64) FIND_LIBRARY(SG_LIBRARY NAMES sg91 PATHS ${SDE_DIR} PATH_SUFFIXES lib lib64) else(SDE_VERSION STREQUAL "91") FIND_LIBRARY(SDE_LIBRARY NAMES sde PATHS ${SDE_DIR} PATH_SUFFIXES lib lib64) FIND_LIBRARY(PE_LIBRARY NAMES pe PATHS ${SDE_DIR} PATH_SUFFIXES lib lib64) FIND_LIBRARY(SG_LIBRARY NAMES sg PATHS ${SDE_DIR} PATH_SUFFIXES lib lib64) endif(SDE_VERSION STREQUAL "91") FIND_LIBRARY(SDE_DL_LIBRARY NAMES dl) FIND_LIBRARY(SDE_SOCKET_LIBRARY NAMES socket) FIND_LIBRARY(SDE_PTHREAD_LIBRARY NAMES pthread) set(SDE_LIBRARIES ${SDE_LIBRARY} ${PE_LIBRARY} ${SG_LIBRARY}) if(SDE_DL_LIBRARY) set(SDE_LIBRARIES ${SDE_LIBRARIES} dl) endif(SDE_DL_LIBRARY) if(SDE_SOCKET_LIBRARY) set(SDE_LIBRARIES ${SDE_LIBRARIES} socket) endif(SDE_SOCKET_LIBRARY) if(SDE_PTHREAD_LIBRARY) set(SDE_LIBRARIES ${SDE_LIBRARIES} pthread) endif(SDE_PTHREAD_LIBRARY) set(SDE_INCLUDE_DIRS ${SDE_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SDE DEFAULT_MSG SDE_LIBRARIES SDE_INCLUDE_DIRS) mark_as_advanced(SDE_LIBRARIES SDE_INCLUDE_DIRS) mapserver-6.4.1/mapgeomtransform.c0000644002461700001440000002312012261257215017037 0ustar tbonfortusers/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: RFC48 implementation of geometry transformations for styling * Author: Thomas Bonfort , Camptocamp (thomas.bonfort at camptocamp.com) * ****************************************************************************** * Copyright (c) 1996-2005 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. *****************************************************************************/ #include "mapserver.h" #include "mapthread.h" extern int yyparse(parseObj *p); void msStyleSetGeomTransform(styleObj *s, char *transform) { msFree(s->_geomtransform.string); if (!transform) { s->_geomtransform.type = MS_GEOMTRANSFORM_NONE; s->_geomtransform.string = NULL; return; } s->_geomtransform.string = msStrdup(transform); if(!strncasecmp("start",transform,5)) { s->_geomtransform.type = MS_GEOMTRANSFORM_START; } else if(!strncasecmp("end",transform,3)) { s->_geomtransform.type = MS_GEOMTRANSFORM_END; } else if(!strncasecmp("vertices",transform,8)) { s->_geomtransform.type = MS_GEOMTRANSFORM_VERTICES; } else if(!strncasecmp("bbox",transform,4)) { s->_geomtransform.type = MS_GEOMTRANSFORM_BBOX; } else if(!strncasecmp("labelpnt",transform,8)) { s->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; } else if(!strncasecmp("labelpoly",transform,9)) { s->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOLY; } else if(!strncasecmp("centroid",transform,8)) { s->_geomtransform.type = MS_GEOMTRANSFORM_CENTROID; } else { s->_geomtransform.type = MS_GEOMTRANSFORM_NONE; msSetError(MS_MISCERR,"unknown transform expression","msStyleSetGeomTransform()"); msFree(s->_geomtransform.string); s->_geomtransform.string = NULL; } } /* * return a copy of the geometry transform expression * returned char* must be freed by the caller */ char *msStyleGetGeomTransform(styleObj *s) { return msStrdup(s->_geomtransform.string); } double calcOrientation(pointObj *p1, pointObj *p2) { double theta; theta = atan2(p2->x - p1->x,p2->y - p1->y); return MS_RAD_TO_DEG*(theta-MS_PI2); } double calcMidAngle(pointObj *p1, pointObj *p2, pointObj *p3) { double theta1,theta2; theta1 = atan2(p1->x-p2->x,p1->y-p2->y); if(theta1<0) theta1 += MS_2PI; theta2 = atan2(p3->x-p2->x,p3->y-p2->y); if(theta2<0) theta2 += MS_2PI; return MS_RAD_TO_DEG*((theta1+theta2)/2.0); } /* * RFC48 implementation: * - transform the original shapeobj * - use the styleObj to render the transformed shapeobj */ int msDrawTransformedShape(mapObj *map, symbolSetObj *symbolset, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor) { int type = style->_geomtransform.type; int i,j; switch(type) { case MS_GEOMTRANSFORM_END: /*render point on last vertex only*/ for(j=0; jnumlines; j++) { lineObj *line = &(shape->line[j]); pointObj *p = &(line->point[line->numpoints-1]); if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE && line->numpoints>1) { style->angle = calcOrientation(&(line->point[line->numpoints-2]),p); } msDrawMarkerSymbol(symbolset,image,p,style,scalefactor); } break; case MS_GEOMTRANSFORM_START: /*render point on first vertex only*/ for(j=0; jnumlines; j++) { lineObj *line = &(shape->line[j]); pointObj *p = &(line->point[0]); /*skip if outside image*/ if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE && line->numpoints>1) { style->angle = calcOrientation(p,&(line->point[1])); } msDrawMarkerSymbol(symbolset,image,p,style,scalefactor); } break; case MS_GEOMTRANSFORM_VERTICES: for(j=0; jnumlines; j++) { lineObj *line = &(shape->line[j]); for(i=1; inumpoints-1; i++) { pointObj *p = &(line->point[i]); /*skip points outside image*/ if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE) { style->angle = calcMidAngle(&(line->point[i-1]),&(line->point[i]),&(line->point[i+1])); } msDrawMarkerSymbol(symbolset,image,p,style,scalefactor); } } break; case MS_GEOMTRANSFORM_BBOX: { shapeObj bbox; lineObj bbox_line; pointObj bbox_points[5]; int padding = MS_MAX(style->width,style->size)+3; /* so clipped shape does not extent into image */ /*create a shapeObj representing the bounding box (clipped by the image size)*/ bbox.numlines = 1; bbox.line = &bbox_line; bbox.line->numpoints = 5; bbox.line->point = bbox_points; msComputeBounds(shape); bbox_points[0].x=bbox_points[4].x=bbox_points[1].x = (shape->bounds.minx < -padding) ? -padding : shape->bounds.minx; bbox_points[2].x=bbox_points[3].x = (shape->bounds.maxx > image->width+padding) ? image->width+padding : shape->bounds.maxx; bbox_points[0].y=bbox_points[4].y=bbox_points[3].y = (shape->bounds.miny < -padding) ? -padding : shape->bounds.miny; bbox_points[1].y=bbox_points[2].y = (shape->bounds.maxy > image->height+padding) ? image->height+padding : shape->bounds.maxy; msDrawShadeSymbol(symbolset, image, &bbox, style, scalefactor); } break; case MS_GEOMTRANSFORM_CENTROID: { double unused; /*used by centroid function*/ pointObj centroid; if(MS_SUCCESS == msGetPolygonCentroid(shape,¢roid,&unused,&unused)) { msDrawMarkerSymbol(symbolset,image,¢roid,style,scalefactor); } } break; case MS_GEOMTRANSFORM_EXPRESSION: { int status; shapeObj *tmpshp; parseObj p; p.shape = shape; /* set a few parser globals (hence the lock) */ p.expr = &(style->_geomtransform); p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_SHAPE; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msDrawTransformedShape", style->_geomtransform.string); return MS_FAILURE; } tmpshp = p.result.shpval; switch (tmpshp->type) { case MS_SHAPE_POINT: case MS_SHAPE_POLYGON: msDrawShadeSymbol(symbolset, image, tmpshp, style, scalefactor); break; case MS_SHAPE_LINE: msDrawLineSymbol(symbolset, image, tmpshp, style, scalefactor); break; } msFreeShape(tmpshp); msFree(tmpshp); } break; case MS_GEOMTRANSFORM_LABELPOINT: case MS_GEOMTRANSFORM_LABELPOLY: break; default: msSetError(MS_MISCERR, "unknown geomtransform", "msDrawTransformedShape()"); return MS_FAILURE; } return MS_SUCCESS; } /* * RFC89 implementation: * - transform directly the shapeobj */ int msGeomTransformShape(mapObj *map, layerObj *layer, shapeObj *shape) { int i; expressionObj *e = &layer->_geomtransform; switch(e->type) { case MS_GEOMTRANSFORM_EXPRESSION: { int status; shapeObj *tmpshp; parseObj p; p.shape = shape; /* set a few parser globals (hence the lock) */ p.expr = e; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_SHAPE; p.dblval = map->cellsize * (msInchesPerUnit(map->units,0)/msInchesPerUnit(layer->units,0)); p.dblval2 = 0; /* data_cellsize is only set with contour layer */ if (layer->connectiontype == MS_CONTOUR) { char *value = msLookupHashTable(&layer->metadata, "__data_cellsize__"); if (value) p.dblval2 = atof(value); } status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msGeomTransformShape()", e->string); return MS_FAILURE; } tmpshp = p.result.shpval; for (i= 0; i < shape->numlines; i++) free(shape->line[i].point); shape->numlines = 0; if (shape->line) free(shape->line); for(i=0; inumlines; i++) msAddLine(shape, &(tmpshp->line[i])); /* copy each line */ msFreeShape(tmpshp); msFree(tmpshp); } break; default: msSetError(MS_MISCERR, "unknown geomtransform", "msGeomTransformShape()"); return MS_FAILURE; } return MS_SUCCESS; } mapserver-6.4.1/nmake.opt0000644002461700001440000010234412261257215015137 0ustar tbonfortusers######################################################################## # nmake.opt - MapServer 4.x configuration for MSVC++ ######################################################################## # This VC++ configuration is used in building MAPSERVER.LIB, # MAPSERVER_I.LIB MAPSERV.EXE, and the other # MapServer command-line programs. # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # # Contents: # Section I: Mapserver Compilation Options # Section II: MapServer Rendering Options # Section III: MapServer Data Input Options # Section IV: MapServer OGC Options # Section V: MapScript Configuration Options # Section VI: Support Libraries # Section VII: Variable Setup # Section VIII: UMN GIS System Support # Section IX: Collect compiler flags # # The easiest way to get going is to use MSVC 2003 and the MapServer # buildkit that is available at # http://mapserver.gis.umn.edu/docs/howto/buildkit # This will provide a full set of libraries to build MapServer will almost # all of its options enabled. If you are building everything from # scratch, start by commenting out most of the options and adding them # in incrementally. ######################################################################## # Section I: Mapserver Compilation Options ######################################################################## #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Check for external options file to include # nmake -f makefile.vc EXT_NMAKE_OPT=mynmake.opt #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !IFDEF EXT_NMAKE_OPT !INCLUDE $(EXT_NMAKE_OPT) !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Uncomment the following if you are building for 64-bit windows # (x64). You'll need to have PATH, INCLUDE and LIB set up for 64-bit # compiles. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #WIN64=YES #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Check compiler version given in command line # nmake -f makefile.vc MSVC_VER=xxxx # 1310 = 7.1 (2003) 1400 = 8.0 (2005) 1500 = 9.0 (2008) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !IFNDEF MSVC_VER #assume msvc 9.0 MSVC_VER=1500 !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # File locations and where to install things # ---------------------------------------------------------------------- # If you are using the MapServer Build Kit, almost everything should be # relative to this directory throughout this option file. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Set the following to point to the directory adjacent to the dependent libs. !IFNDEF MS_BASE MS_BASE = f:\projects\mapserver-buildkit-2008\mapserver !ENDIF # Set the following to point to the current (mapserver) directory. !IFNDEF MS_CURRENT MS_CURRENT = $(MS_BASE) !ENDIF !IFNDEF BINDIR BINDIR = $(MS_BASE)\..\bin !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Optmization, debug, and related compile flags. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !IF $(MSVC_VER) >= 1400 !IFNDEF MS_DEBUG # Optimized, with using MSVCRT. OPTFLAGS = /nologo /Ox /MD $(WARNING_LEVEL) $(DEBUG) /EHsc /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE !ELSE # Debug with MSVCRT OPTFLAGS = /nologo /Zi /MD $(WARNING_LEVEL) $(DEBUG) /EHsc /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE #LDFLAGS = /NODEFAULTLIB:msvcrt /NODEFAULTLIB:libcd /DEBUG !ENDIF !ELSE !IFNDEF MS_DEBUG # Optimized, with using MSVCRT. OPTFLAGS = /nologo /Ox /MD $(WARNING_LEVEL) $(DEBUG) /EHsc !ELSE # Debug with MSVCRT OPTFLAGS = /nologo /Zi /MDd $(WARNING_LEVEL) $(DEBUG) /EHsc #LDFLAGS = /NODEFAULTLIB:msvcrt /NODEFAULTLIB:libcd /DEBUG !ENDIF !ENDIF # Uncomment the following to link mapserv.exe with a dll. In almost # all cases you will want to do this. DLLBUILD = 1 # Set the Warning level for the compiler (defaults to W1) WARNING_LEVEL=/W4 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Debugging Options # ---------------------------------------------------------------------- !IFDEF MS_DEBUG #NEED_NONBLOCKING_STDERR=-DNEED_NONBLOCKING_STDERR ENABLE_STDERR_DEBUG=-DENABLE_STDERR_DEBUG # Set the linker debug option LDEBUG=/debug # DEBUG Build flags # Set the DEBUG flag if you wish to make a debug build DEBUG=/DDEBUG !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # String methods # ---------------------------------------------------------------------- # Apparently these aren't as commonplace. Edit the # following line to reflect the missing functions on your platform. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #STRINGS=-DNEED_STRCASECMP -DNEED_STRNCASECMP -DNEED_STRDUP STRINGS=-DNEED_STRCASECMP -DNEED_STRNCASECMP -DNEED_STRLCAT -DNEED_STRRSTR -DNEED_STRCASESTR -DNEED_STRLCPY #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Threading # ---------------------------------------------------------------------- # Enable if you want thread safe locking, not needed for simple CGI. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ THREADS=-DUSE_THREAD #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Ignoring Missing Data # ---------------------------------------------------------------------- # If you want to ignore missing datafile errors uncomment the following # line. This is especially useful with large tiled datasets that may not # have complete data for each tile. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IGNORE_MISSING_DATA=-DIGNORE_MISSING_DATA #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Measures and Z values # ---------------------------------------------------------------------- # If you want to use shape Z and M parameter this option must be set. # It's OFF by default. #USE_POINT_Z_M=-DUSE_POINT_Z_M USE_POINT_Z_M= ######################################################################## # Section II: Mapserver Rendering Configuration ######################################################################## #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD Library # ---------------------------------------------------------------------- # Mapserver 4.x only supports GD 2.x and greater. # GD is a required support library for MapServer 4.x. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !IFNDEF GD_DIR GD_DIR=$(MS_BASE)\..\gd-2.0.35 GD_LIB=$(GD_DIR)/gd.lib !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD JPEG support # ---------------------------------------------------------------------- # If you wish to allow JPEG output maps, uncomment the following flag. # If not using a GD build with an internal copy of libjpeg, you will # also need to uncomment JPEG_DIR and point to it; however, with BGD.DLL # this is normally not necessary. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OUTPUT_JPEG=-DUSE_GD_JPEG JPEG_DIR=$(MS_BASE)\..\jpeg-6b #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD PNG support # ---------------------------------------------------------------------- # If you wish to allow PNG output maps, uncomment the following flag. # If not using a GD build with an internal copy of libpng, you will # also need to uncomment PNG_DIR and ZLIB_DIR and point to it; # however, with BGD.DLL this is normally not necessary. # See http://www.libpng.org/pub/png/libpng.html for support library. # See http://www.gzip.org/zlib/ for support library. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OUTPUT_PNG=-DUSE_GD_PNG !IFNDEF PNG_DIR PNG_DIR=$(MS_BASE)\..\libpng-1.2.35 !ENDIF ZLIB_DIR=$(MS_BASE)\..\zlib-1.2.3 ZLIB_INC=-I$(ZLIB_DIR) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD GIF support # ---------------------------------------------------------------------- # Historical defines to use GIF as a result of the old Unisys patent #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OUTPUT_GIF=-DUSE_GD_GIF -DGD_HAS_GDIMAGEGIFPTR #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD BMP support # ---------------------------------------------------------------------- # If you wish to allow Windows BMP output maps, # uncomment the following flag. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OUTPUT_WBMP=-DUSE_GD_WBMP #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD Bitmap Font support # ---------------------------------------------------------------------- # Bitmap font support (GD 2.0.22 and greater, # see Bug 969 for more details) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GD_HAS_GETBITMAPFONT=-DGD_HAS_GETBITMAPFONT # ---------------------------------------------------------------------- # used for curved text (keyword FOLLOW for angle in label object) # GD version 2.0.29 or higher # ---------------------------------------------------------------------- GD_HAS_FTEX_XSHOW=-DGD_HAS_FTEX_XSHOW #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD Antialiasing support # ---------------------------------------------------------------------- # If you want antialiasing (note that It requires gd2) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USE_GD_ANTIALIAS=-DUSE_GD_ANTIALIAS #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GD TrueType Font support # ---------------------------------------------------------------------- # If you wish to annotate your maps with true type fonts unccomment the # following flag. Provide the full path to the FreeType 2.x external # support library, unless it is provided within your GD build as is the # case with BGD.DLL. # See http://www.freetype.org for support library. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ANNOTATION_FT=-DUSE_GD_FT !IFNDEF FT_DIR FT_DIR=$(MS_BASE)\..\freetype-2.3.9 !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Optional RGBA palette png output # ---------------------------------------------------------------------- # Enable support for quantization of rgba pngs #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !IFDEF PNG_DIR RGBA_PNG_ENABLED=-DUSE_RGBA_PNG !ENDIF # If you wish to use AGG # The AGG (Ant-Grain Geometry) libraray http://www.antigrain.com/ #is used in Mapserver to putput high class rendering # AGG=-DUSE_AGG EXPAT_DIR = $(MS_BASE)\..\expat-2.0.1 # If you wish to use OpenGl # #OGL=-DUSE_OGL #FTGL_DIR=$(MS_BASE)\..\ftgl-2.1.3~rc5 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Cairo renderer support # ---------------------------------------------------------------------- # Uncomment the following to build with cairo renderer support #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #CAIRO=-DUSE_CAIRO #CAIRO_DIR=$(MS_BASE)\..\cairo-thamas #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # PDF (Acrobat PDF support) # ---------------------------------------------------------------------- # If you wish to have PDF output, uncomment the following flag and # provide the full path to the PDF support library project directory. # See http://www.pdflib.com/products/pdflib/download-source.html to # download the support library. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #PDF=-DUSE_PDF #PDF_DIR=$(MS_BASE)\..\PDFlib-Lite-7.0.4p1 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GEOS # ---------------------------------------------------------------------- # GEOS provides support for spatial predicates and overlay/buffer # operations. It can only be compiled on Windows with MSVC 7.0 or # greater (or the cygwin/mingw stack). #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #GEOS=-DUSE_GEOS #GEOS_DIR=$(MS_BASE)\..\geos-06232009 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ZLIB # ---------------------------------------------------------------------- # ZLIB is required for PNG and for SVG support to allow the output of # compressed files. If -DUSE_ZLIB is defined, you essentially have all # you need for SVG output support #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ZLIB=-DUSE_ZLIB ZLIB_DIR=$(MS_BASE)\..\zlib-1.2.3 ZLIB_INC=-I$(ZLIB_DIR) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ICONV # ---------------------------------------------------------------------- #libiconv support is used for to support double bytes (see bug 911). #uncomment the following to build with libiconv support. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #ICONV=-DUSE_ICONV #ICONV_DIR=$(MS_BASE)\..\libiconv-1.9.1 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GIFLIB # ---------------------------------------------------------------------- # Uncomment the following to build with giflib support #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #GIF=-DUSE_GIF #GIFLIB_DIR=$(MS_BASE)\..\giflib-4.1.4 #GIFLIB_INC=-I$(GIFLIB_DIR)\include ######################################################################## # Section III: Mapserver Data Input Configuration ######################################################################## #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GDAL # ---------------------------------------------------------------------- # The lite version of mapserver 4.x supports only GIF, PNG and JPEG data # for input. If you wish to support many geospatial raster formats # for input you will need the GDAL support library from # http://www.gdal.org/. Once built, enable the GDAL flag, and point # GDAL_DIR to the directory where GDAL was built. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #GDAL=-DUSE_GDAL #GDAL_DIR=$(MS_BASE)\..\gdal_1_7_0 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # OGR # ---------------------------------------------------------------------- # The OGR library (part of GDAL) supports a variety of geospatial vector # formats including mapinfo, Arc/Info binary coverages, S-57, SDTS, # Microstation DGN (pre-v7), TIGER, UK .NTF. It also include support # for treating non-spatial tablular data from ODBC, CSV, MySQL, # Oracle Spatial, and PostgreSQL as spatial table with use of the # VRT (virtual) driver. # # NOTE: Both -DUSE_OGR and -DUSE_GDAL need to be defined if you # want to use GDAL/OGR for both raster and vector support, but GDAL_DIR # needs only be defined once. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #OGR=-DUSE_OGR #GDAL_DIR=$(MS_BASE)\..\gdal_1_7_0 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # JPEG Input # ---------------------------------------------------------------------- # JPEG input for raster layers is also available through GDAL, If you wish # to build support for JPEG without GDAL, uncomment the following flag # and provide the full path to the jpeg support library project directory. # See http://www.ijg.org/ for support library. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JPEG=-DUSE_JPEG JPEG_DIR=$(MS_BASE)\..\jpeg-6b JPEG_INC = -I$(JPEG_DIR) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Direct connectivity to Postgresql PostGIS. # ---------------------------------------------------------------------- # To turn on direct connectivity to Postgresql PostGIS uncomment the following # flag and set the full path name to the project directory for the # Postgresql native Win32 client library. # See http://www.postgresql.org for support library. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #POSTGIS =-DUSE_POSTGIS #POSTGIS_DIR =$(MS_BASE)\..\postgresql-8.3.7 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Direct connectivity to Oracle Spatial. # ---------------------------------------------------------------------- # Point this to where your ORACLE_HOME directory lives. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #ORACLE_DIR = $(MS_BASE)\..\oracle-11.1.0.7.0 #ORACLE=-DUSE_ORACLESPATIAL #ORACLE=-DUSE_ORACLE_PLUGIN #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Direct connectivity to ESRI ArcSDE. # ---------------------------------------------------------------------- # To turn on direct connectivity to ArcSDE uncomment the following # flags and set the full path name to the project directory for ArcSDE. # The support library for ArcSDE (the ArcSDE C API/SDK) is typically # only available for those with a full license of ArcSDE. It is not # available for download. # Either set USE_SDE or USE_SDE_PLUGIN, not both. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #SDE_OPT=-DUSE_SDE #SDE_OPT= -DUSE_SDE_PLUGIN #SDE_VERSION = 91 #SDE_DIR = f:\projects\sde9.1 #SDE_INC = -I$(SDE_SDK)\include #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Direct connectivity to SQL Server # ---------------------------------------------------------------------- # To turn on direct connectivity to SQL Server uncomment the following # flag. You then need to set the ODBC_INC path later as well to the # Windows SDK include path. The SQL Server 2008 driver can only be # built and used as a plugin. See RFC 38 for more details. The ODBC # libs and includes must be set to be able to build the plugin. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #MSSQL2008 = YES #ODBC_DIR="C:\progra~1\micros~1.net\vc7\platformsdk" #ODBC_DIR="C:\Program Files\Microsoft SDKs\Windows\v6.0A" #ODBC_LIBS=$(ODBC_DIR)\lib\odbc32.lib $(ODBC_DIR)\lib\odbccp32.lib $(ODBC_DIR)\lib\user32.lib #ODBC_INC=-I$(ODBC_DIR)\include #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EPPL7 Support # ---------------------------------------------------------------------- # This activates ERDAS as well. It is included in the distribution. # Probably the best raster alternative if you've got EPPL7 laying # around. See http://www.lmic.state.mn.us/ for more information. # Uncomment out the following flag and set the full path name to the # epplib.obj file. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #EPPL=-DUSE_EPPL #EPPL_OBJ=c:/my_path/epplib.obj # ---------------------------------------------------------------------- # Use of fribidi # GNU FriBidi is an implementation of the Unicode Bidirectional Algorithm (bidi). # http://fribidi.freedesktop.org/wiki/ # Unncomment out the following flags to build with fribidi #--------------------------------------------------------------------- #FRIBIDI=-DUSE_FRIBIDI #FRIBIDI_DIR=$(MS_BASE)\..\fribidi-0.19.1 # ---------------------------------------------------------------------- # Enable KML support #---------------------------------------------------------------------- #KML=-DUSE_KML ######################################################################## # Section IV: Mapserver OGC Configuration ######################################################################## #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # WMS Server # ---------------------------------------------------------------------- #WMS=-DUSE_WMS_SVR #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # WMS Client # ---------------------------------------------------------------------- # Use this flag to compile with WMS Client support. WMS Client support # allows you to pull layers from other OGIS WMS servers on the interent and # incorporate them into your map. # To find out more about the OpenGIS Web Map Server Specification go to # http://www.opengis.org/ # you need the libcurl library from http://curl.haxx.se/library/c/ # Set the full path to the curl project directory. # You may also need to the full path to the windows socket library. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #WMSCLIENT= -DUSE_WMS_LYR #CURL=-DUSE_CURL #CURL_DIR=$(MS_BASE)\..\curl-7.19.4 #WINSOCK_LIB ="C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib\WS2_32.Lib" #WINSOCK_LIB ="C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\WS2_32.Lib" #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # WFS Client # ---------------------------------------------------------------------- # Use -DUSE_WFS_LYR to compile with WFS client support, requires libcurl #WFSCLIENT= -DUSE_WFS_LYR #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # WFS Server # ---------------------------------------------------------------------- # Use -DUSE_WFS_SVR to compile with WFS server # support, requires OGR and PROJ4 #WFS=-DUSE_WFS_SVR -DWFS_USE_LIBXML2 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # WCS Server # ---------------------------------------------------------------------- # Use -DUSE_WCS_SVR to compile with WCS server support, requires GDAL. #WCS=-DUSE_WCS_SVR #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # OGC SOS # ---------------------------------------------------------------------- # Use -DUSE_OGC_SOS to compile with SOS, needs USE_WMS_SVR or #USE_WFS_SVR enabled so the the gml functions to be enabled #It also needs ICONV support since the libxml windows binaries #are built with it #http://xmlsoft.org/index.html #SOS=-DUSE_SOS_SVR #XML2_ENABLED=-DUSE_LIBXML2 #LIBXML_DIR=$(MS_BASE)\..\libxml2-2.7.3.win32 ######################################################################## # Section V: MapScript Configuration Options. ######################################################################## #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # SWIG location # ---------------------------------------------------------------------- # SWIG is required to *generate* the C/C++ code that creates the # bindings to various languages. You can download a pre-built binary # for SWIG at http://www.swig.org. NOTE: The PHP bindings are *not* # generated with SWIG at this time. If you use this makefile to # make any MapScript bindings, eg. "nmake /f makefile.vc python", you # will need to have SWIG installed. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #SWIG = $(MS_BASE)\..\SWIG-1.3.39\swig #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Java MapScript # ---------------------------------------------------------------------- # Java MapScript very likely requires USE_THREAD to be defined. It is # known to work with both JDK 1.5 and JDK 1.4 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #JAVA_HOME = "C:\Progra~1\Java\jdk1.5.0" #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Python MapScript # ---------------------------------------------------------------------- # Python MapScript very likely requires USE_THREAD to be defined. # Python 2.2 and above are supported. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #PYTHON_HOME = "$(MS_BASE)\..\Python-2.6.2" #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # PHP MapScript # ---------------------------------------------------------------------- # The PHP_REGEX hack allows you to use PHP's regex system rather than # the normal GNU regex library. This should normally not be needed. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #PHP_HOME = $(MS_BASE)\..\php-5.3.1 #PHP_REGEX=1 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # .NET/C# MapScript # ---------------------------------------------------------------------- # .NET will of course only work with MSVC 7.0 and 7.1. Also note that # you will definitely want USE_THREAD defined. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #DOT_NET = YES ######################################################################## # Section VI: Support Libraries. ######################################################################## #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Proj.4 # ---------------------------------------------------------------------- # If you would like mapserver to be able to reproject data from one # geographic projection to another, uncomment the following flag # Proj.4 distribution (cartographic projection routines). PROJ.4 is # also required for all OGC services (WMS, WFS, and WCS). #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #PROJ=-DUSE_PROJ -DUSE_PROJ_API_H #PROJ_DIR=$(MS_BASE)\..\proj-svn-04222009 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # REGEX Libary # ---------------------------------------------------------------------- # VC++ does not include the REGEX library... so we must provide our one. # The following definitions will try to build GNU regex-0.12 located in the # regex-0.12 sub-directory. # If it was not included in the source distribution, then you can get it from: # ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz # Provide the full path to the REGEX project directory # You do not need this library if you are compiling for PHP mapscript. # In that case the PHP regex library will be used instead #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !IFNDEF PHP_REGEX !IFNDEF REGEX_DIR REGEX_DIR=$(MS_BASE)\..\regex-0.12 !ENDIF !ENDIF #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # FastCGI Support # ---------------------------------------------------------------------- # Uncomment, and update accordingly. #FCGIDEF=-DUSE_FASTCGI #FCGIDIR=$(MS_BASE)\..\fcgi-2.4.0 ######################################################################## # Section VII: Variable Setup ######################################################################## # Should not need to be updated. ######################################################################## MS_LIB = mapserver.lib MS_LIB_DLL = mapserver_i.lib # Proj.4 include and library !IFDEF PROJ_DIR PROJ_INC=-I$(PROJ_DIR)/src PROJ_LIB=$(PROJ_DIR)/src/proj_i.lib !ENDIF # CURL include and library !IFDEF WMSCLIENT CURL_INC = -I$(CURL_DIR)/include CURL_LIB = $(CURL_DIR)/lib/libcurl_imp.lib !ENDIF # LIBXML include and library !IFDEF SOS LIBXML_INC = -I$(LIBXML_DIR)/include LIBXML_LIB = $(LIBXML_DIR)/lib/libxml2.lib !ENDIF # Set the jpeg library !IFDEF JPEG_DIR JPEG_LIB=$(JPEG_DIR)/libjpeg.lib !ENDIF # Set the png support libaries !IFDEF PNG_DIR !IFNDEF PNG_LIB PNG_LIB=$(PNG_DIR)\projects\visualc71\Win32_LIB_Release\libpng.lib $(ZLIB_DIR)/zlib1.lib !ENDIF PNG_INC=-I$(PNG_DIR) !ENDIF !IFDEF GEOS_DIR GEOS_LIB=$(GEOS_DIR)/source/geos_c_i.lib GEOS_INC=-I$(GEOS_DIR)/source/headers -I$(GEOS_DIR)/capi -I$(GEOS_DIR)/source/capi !ENDIF # Set the FreeType library !IFDEF FT_DIR !IFNDEF FT_LIB FT_LIB=$(FT_DIR)/objs/win32/vc2008/freetype239.lib !ENDIF !ENDIF # GD include and library GD_INC= -I$(GD_DIR) GD_LIBS= $(GD_LIB) $(JPEG_LIB) $(PNG_LIB) $(FT_LIB) GD= -DUSE_GD $(OUTPUT_PNG) $(OUTPUT_JPEG) $(OUTPUT_WBMP) $(OUTPUT_GIF) $(ANNOTATION_FT) $(GD_HAS_GETBITMAPFONT) $(GD_HAS_FTEX_XSHOW) # Tiff library on input !IFDEF TIFF TIFF_INC=-I$(TIFF_DIR)/libtiff TIFF_LIB=$(TIFF_DIR)/libtiff/libtiff.lib !ENDIF # JPEG library on input !IFDEF JPEG_DIR JPEG_LIB=$(JPEG_DIR)/libjpeg.lib !ENDIF # Setup GDAL includes and libraries !IFDEF GDAL GDAL_INC = -I$(GDAL_DIR)/gcore -I$(GDAL_DIR)/alg -I$(GDAL_DIR)/ogr -I$(GDAL_DIR)/port GDAL_LIB = $(GDAL_DIR)/gdal_i.lib !ENDIF # Setup OGR includes and libraries !IFDEF OGR OGR_INC = -I$(GDAL_DIR)/ogr/ogrsf_frmts -I$(GDAL_DIR)/ogr -I$(GDAL_DIR)/port OGR_LIB = $(GDAL_DIR)/gdal_i.lib !ENDIF # Setup ESRI SDE support. !IFDEF SDE_OPT SDE_INC=-I$(SDE_DIR)/include !IF "$(SDE_OPT)" != "-DUSE_SDE_PLUGIN" SDE_LIB = $(SDE_DIR)\lib\pe$(SDE_VERSION).lib \ $(SDE_DIR)\lib\sde$(SDE_VERSION).lib \ $(SDE_DIR)\lib\sg$(SDE_VERSION).lib !ELSE SDE_LIB = !ENDIF !ENDIF # Setup REGEX object and includes !IFNDEF PHP_REGEX REGEX_OBJ=$(REGEX_DIR)\regex.obj REGEX_INC=-I$(REGEX_DIR) !ELSE REGEX_OBJ=$(PHP_HOME)\ext\ereg\regex\regcomp.obj $(PHP_HOME)\ext\ereg\regex\regerror.obj \ $(PHP_HOME)\ext\ereg\regex\regexec.obj $(PHP_HOME)\ext\ereg\regex\regfree.obj REGEX_INC=-I$(PHP_HOME)/ext/ereg/regex -DPHP_NO_ALIASES !ENDIF # REGEX needs some special flags... here they are for VC++ 6.0 REGEX_OPT=-DHAVE_STRING_H -DREGEX_MALLOC # Setup Postgesql PostGIS includes and libs !IFDEF POSTGIS !IFNDEF PHP_BUILD_CALL # If we're building PHP MapScript, there is a macro conflict POSTGIS_INC=-I$(POSTGIS_DIR)/src/interfaces/libpq -I$(POSTGIS_DIR)/src/include !ENDIF POSTGIS_LIB=$(POSTGIS_DIR)/src/interfaces/libpq/release/libpqdll.lib !ENDIF # Setup OGL !IFDEF OGL OGL_INC= -I$(FTGL_DIR)\src OGL_LIB= $(FTGL_DIR)\msvc\build\ftgl_static.lib opengl32.lib glu32.lib user32.lib gdi32.lib !ENDIF # Setup CAIRO !IFDEF CAIRO CAIRO_INC= -I$(CAIRO_DIR)\src CAIRO_LIB= $(CAIRO_DIR)\src\cairo.lib !ENDIF # Setup EXPAT !IFDEF EXPAT_DIR EXPAT_INC = -I$(EXPAT_DIR)\source\lib EXPAT_LIB = $(EXPAT_DIR)\bin\libexpat.lib !ENDIF # Set the GIFLIB library !IFDEF GIFLIB_DIR GIFLIB_LIB=$(GIFLIB_DIR)\lib\giflib.lib !ENDIF # Setup AGG !IFDEF AGG AGG_INC=-I$(FT_DIR)\include -Irenderers\agg\include AGG_OBJ=renderers\agg\src\agg_arc.obj renderers\agg\src\agg_curves.obj renderers\agg\src\agg_vcgen_contour.obj \ renderers\agg\src\agg_vcgen_dash.obj renderers\agg\src\agg_vcgen_stroke.obj renderers\agg\src\agg_image_filters.obj \ renderers\agg\src\agg_line_aa_basics.obj renderers\agg\src\agg_line_profile_aa.obj \ renderers\agg\src\agg_sqrt_tables.obj renderers\agg\src\agg_embedded_raster_fonts.obj \ renderers\agg\src\agg_trans_affine.obj renderers\agg\src\agg_vpgen_clip_polygon.obj \ renderers\agg\src\agg_vpgen_clip_polyline.obj renderers\agg\src\agg_font_freetype.obj \ renderers\agg\src\agg_svg_parser.obj renderers\agg\src\agg_svg_path_renderer.obj \ renderers\agg\src\agg_svg_path_tokenizer.obj renderers\agg\src\clipper.obj !ENDIF # Setup PDF includes and libs !IFDEF PDF PDF_LIB=$(PDF_DIR)/libs/pdflib/Release_DLL/pdflib.lib PDF_INC=-I$(PDF_DIR)/libs/pdflib !ENDIF # Oracle support. !IFDEF ORACLE ORACLE_INC=-I$(ORACLE_DIR)/include !IF "$(ORACLE)" != "-DUSE_ORACLE_PLUGIN" ORACLE_LIB=$(ORACLE_DIR)\lib\msvc\ociw32.lib $(ORACLE_DIR)/lib/msvc/oci.lib !ELSE ORACLE_LIB = !ENDIF !ENDIF #libiconv support !IFDEF ICONV ICONV_LIB=$(ICONV_DIR)\lib\iconv.lib ICONV_INC= -I$(ICONV_DIR)\include !ENDIF #fcgi support !IFDEF FCGIDEF FCGILIB=$(FCGIDIR)\libfcgi\Release\libfcgi.lib FCGIINC=-I$(FCGIDIR)\include !ENDIF #fribidi support !IFDEF FRIBIDI FRIBIDI_INC=-I$(FRIBIDI_DIR)\lib -I$(FRIBIDI_DIR)\charset FRIBIDI_LIB=$(FRIBIDI_DIR)\fribidi.lib !ENDIF ######################################################################## # Section VIII: UMN GIS System Support ######################################################################## # Should not need to be updated. ######################################################################## # # UofMN GIS/Image Processing Extension (very experimental) # #EGIS=-DUSE_EGIS !IFDEF EGIS ERR_DIR=c:/my_path_to/errLog ERR_OBJ=$(ERR_DIR)/errLog.o ERR_INC=-I$(ERR_DIR) ERR_LIB=-L$(ERR_DIR) -lerrLog IMGGEN_DIR=c:/my_path_to/imgSrc IMGGEN_OBJ=$(IMGGEN_DIR)/imgLib.o IMGGEN_INC=-I$(IMGGEN_DIR) IMGGEN_LIB=-L$(IMGGEN_DIR) -limgGEN !ENDIF ######################################################################## # Section IX: Collect compiler flags ######################################################################## # Should not need to be updated. ######################################################################## !IFNDEF EXTERNAL_LIBS EXTERNAL_LIBS=$(GD_LIBS) $(TIFF_LIB) $(JPEG_LIB) \ $(PROJ_LIB) $(OGR_LIB) $(GDAL_LIB)\ $(CURL_LIB) $(PDF_LIB) \ $(WINSOCK_LIB) $(POSTGIS_LIB) $(IMGGEN_LIB) $(ERR_LIB) \ $(ORACLE_LIB) $(SDE_LIB) $(ICONV_LIB) $(FCGILIB) $(GEOS_LIB) \ $(LIBXML_LIB) $(EXPAT_LIB) $(OGL_LIB) $(CAIRO_LIB) $(FRIBIDI_LIB) $(GIFLIB_LIB) !ENDIF LIBS=$(MS_LIB) $(EXTERNAL_LIBS) LIBS_DLL=$(MS_LIB_DLL) $(EXTERNAL_LIBS) !IFNDEF INCLUDES INCLUDES=$(GD_INC) $(TIFF_INC) $(JPEG_INC) \ $(PROJ_INC) $(REGEX_INC) $(GDAL_INC) $(OGR_INC) \ $(CURL_INC) $(PDF_INC) $(POSTGIS_INC) \ $(IMGGEN_INC) $(ERR_INC) $(ORACLE_INC) $(SDE_INC)\ $(ICONV_INC) $(FCGIINC) $(GEOS_INC) $(ZLIB_INC) $(LIBXML_INC) \ $(AGG_INC) $(EXPAT_INC) $(OGL_INC) $(CAIRO_INC) $(PNG_INC) $(FRIBIDI_INC) $(GIFLIB_INC) !ENDIF MS_DEFS = $(REGEX_OPT) $(STRINGS) $(POSTGIS) \ $(EPPL) $(PROJ) $(TIFF) $(JPEG) $(GD) $(OGR) $(WMS) $(THREADS) \ $(WMSCLIENT) $(IGNORE_MISSING_DATA) \ $(NEED_NONBLOCKING_STDERR) $(ENABLE_STDERR_DEBUG) \ $(USE_POINT_Z_M) $(GDAL) $(FCGIDEF) \ $(WFS) $(WFSCLIENT) $(WCS) $(PDF) $(EGIS) \ $(USE_GD_ANTIALIAS) $(ORACLE) \ $(SDE_OPT) $(ICONV) $(GEOS) $(ZLIB) $(SOS) $(XML2_ENABLED) $(AGG) \ $(OGL) $(CAIRO) $(RGBA_PNG_ENABLED) $(FRIBIDI) $(KML) $(GIF) $(CURL) !IFDEF WIN64 MS_CFLAGS=$(INCLUDES) $(MS_DEFS) -DWIN32 -D_WIN32 -DUSE_GENERIC_MS_NINT !ELSE MS_CFLAGS=$(INCLUDES) $(MS_DEFS) -DWIN32 -D_WIN32 !ENDIF mapserver-6.4.1/mapaxisorder.csv0000755002461700001440000002177412261257215016545 0ustar tbonfortusersepsg_code 4326 4258 31466 31467 31468 31469 2166 2167 2168 2036 2044 2045 2065 2081 2082 2083 2085 2086 2091 2092 2093 2096 2097 2098 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2193 2199 2200 2206 2207 2208 2209 2210 2211 2212 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2935 2936 2937 2938 2939 2940 2941 2953 2963 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3034 3035 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3058 3059 3068 3114 3115 3116 3117 3118 3120 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3146 3147 3150 3151 3152 3300 3301 3328 3329 3330 3331 3332 3333 3334 3335 3346 3350 3351 3352 3366 3386 3387 3388 3389 3390 3396 3397 3398 3399 3407 3414 3416 3764 3788 3789 3790 3791 3793 3795 3796 3819 3821 3823 3824 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3854 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3888 3889 3906 3907 3908 3909 3910 3911 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4040 4041 4042 4043 4044 4045 4046 4047 4052 4053 4054 4055 4074 4075 4080 4081 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4178 4179 4180 4181 4182 4183 4184 4185 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4322 4324 4327 4329 4339 4341 4343 4345 4347 4349 4351 4353 4355 4357 4359 4361 4363 4365 4367 4369 4371 4373 4375 4377 4379 4381 4383 4386 4388 4417 4434 4463 4466 4469 4470 4472 4475 4480 4482 4483 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4557 4558 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4839 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4883 4885 4887 4889 4891 4893 4895 4898 4900 4901 4902 4903 4904 4907 4909 4921 4923 4925 4927 4929 4931 4933 4935 4937 4939 4941 4943 4945 4947 4949 4951 4953 4955 4957 4959 4961 4963 4965 4967 4969 4971 4973 4975 4977 4979 4981 4983 4985 4987 4989 4991 4993 4995 4997 4999 5012 5013 5017 5048 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5132 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5224 5228 5229 5233 5245 5246 5251 5252 5253 5254 5255 5256 5257 5258 5259 5263 5264 5269 5270 5271 5272 5273 5274 5275 5323 5324 5340 5342 5343 5344 5345 5346 5347 5348 5349 5353 5354 5359 5360 5364 5365 5367 5370 5371 5372 5373 5380 5381 5392 5393 5451 5464 5467 5479 5480 5481 5482 5488 5489 5513 5515 5518 5519 5520 5524 5527 5545 5546 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5588 5592 5593 5632 5633 5634 5635 5636 5637 5638 5639 5651 5652 5653 5681 5801 5802 5803 5804 5808 5809 5810 5811 5812 5813 5814 5815 5816 5830 20004 20005 20006 20007 20008 20009 20010 20011 20012 20013 20014 20015 20016 20017 20018 20019 20020 20021 20022 20023 20024 20025 20026 20027 20028 20029 20030 20031 20032 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 20079 20080 20081 20082 20083 20084 20085 20086 20087 20088 20089 20090 20091 20092 21413 21414 21415 21416 21417 21418 21419 21420 21421 21422 21423 21453 21454 21455 21456 21457 21458 21459 21460 21461 21462 21463 21473 21474 21475 21476 21477 21478 21479 21480 21481 21482 21483 21896 21897 21898 21899 22171 22172 22173 22174 22175 22176 22177 22181 22182 22183 22184 22185 22186 22187 22191 22192 22193 22194 22195 22196 22197 25884 27205 27206 27207 27208 27209 27210 27211 27212 27213 27214 27215 27216 27217 27218 27219 27220 27221 27222 27223 27224 27225 27226 27227 27228 27229 27230 27231 27232 27391 27392 27393 27394 27395 27396 27397 27398 27492 28402 28403 28404 28405 28406 28407 28408 28409 28410 28411 28412 28413 28414 28415 28416 28417 28418 28419 28420 28421 28422 28423 28424 28425 28426 28427 28428 28429 28430 28431 28432 28462 28463 28464 28465 28466 28467 28468 28469 28470 28471 28472 28473 28474 28475 28476 28477 28478 28479 28480 28481 28482 28483 28484 28485 28486 28487 28488 28489 28490 28491 28492 29701 29702 30161 30162 30163 30164 30165 30166 30167 30168 30169 30170 30171 30172 30173 30174 30175 30176 30177 30178 30179 30800 31251 31252 31253 31254 31255 31256 31257 31258 31259 31275 31276 31277 31278 31279 31281 31282 31283 31284 31285 31286 31287 31288 31289 31290 31700 mapserver-6.4.1/mapogl.cpp0000644002461700001440000002114312261257215015300 0ustar tbonfortusers/****************************************************************************** * $id: mapogl.cpp 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 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. ****************************************************************************/ #include "mapserver.h" #ifdef USE_OGL #include #include #include "mapoglrenderer.h" #include "mapoglcontext.h" imageObj* createImageObjOgl(OglRenderer* renderer) { if (!renderer->isValid()) return NULL; imageObj* pNewImage = (imageObj*)calloc(1, sizeof(imageObj)); if (!pNewImage) return pNewImage; pNewImage->img.plugin = (void *) renderer; return pNewImage; } OglRenderer* getOglRenderer(imageObj* img) { return (OglRenderer*) img->img.plugin; } int msSaveImageOgl(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { rasterBufferObj data; OglRenderer* renderer = getOglRenderer(img); renderer->readRasterBuffer(&data); return msSaveRasterBuffer(NULL,&data,fp,img->format ); } int msDrawLineOgl(imageObj *img, shapeObj *p, strokeStyleObj *style) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolyline(p, style->color, style->width, style->patternlength, style->pattern); return MS_SUCCESS; } int msDrawPolygonOgl(imageObj *img, shapeObj *p, colorObj *color) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolygon(p, color, NULL, 0); return MS_SUCCESS; } //void msFreeTileOgl(imageObj *tile) //{ // delete (OglCache*)tile; //} int msDrawLineTiledOgl(imageObj *img, shapeObj *p, imageObj *tile) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolylineTile(p, getOglRenderer(tile)->getTexture()); return MS_SUCCESS; } int msDrawPolygonTiledOgl(imageObj *img, shapeObj *p, imageObj *tile) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolygon(p, NULL, NULL, 0.0, getOglRenderer(tile)->getTexture()); return MS_SUCCESS; } int msRenderPixmapOgl(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPixmap(symbol, x, y, style->rotation, style->scale); return MS_SUCCESS; } int msRenderVectorSymbolOgl (imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { OglRenderer* renderer = getOglRenderer(img); renderer->renderVectorSymbol(x, y, symbol, style->scale, style->rotation, style->color, style->outlinecolor, style->outlinewidth); return MS_SUCCESS; } int msRenderTruetypeSymbolOgl(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { OglRenderer* renderer = getOglRenderer(img); double size = style->scale*72.0; renderer->renderGlyphs(0, 0, style->color, style->outlinecolor, size, symbol->font, symbol->character, style->rotation, NULL, 0, 0); return MS_SUCCESS; } int msRenderTileOgl(imageObj *img, imageObj *tile, double x, double y) { OglRenderer* renderer = getOglRenderer(img); renderer->renderTile(getOglRenderer(tile)->getTexture(), x, y, 0.0); return MS_SUCCESS; } int msGetTruetypeTextBBoxOgl(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline) { if (OglRenderer::getStringBBox(fonts[0], size, string, rect, advances)) { return MS_SUCCESS; } else { return MS_FAILURE; } } int msRenderGlyphsOgl(imageObj *img, double x, double y, labelStyleObj *style, char *text) { OglRenderer* renderer = getOglRenderer(img); renderer->renderGlyphs(x, y, style->color, style->outlinecolor, style->size, style->fonts[0], text, style->rotation, NULL, 0.0, 0.0); return MS_SUCCESS; } int msMergeRasterBufferOgl(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { OglRenderer* renderer = getOglRenderer(dest); renderer->drawRasterBuffer(overlay, opacity, srcX, srcY, dstX, dstY, width, height); return MS_SUCCESS; } imageObj* msImageCreateOgl(int width, int height, outputFormatObj *format, colorObj* bg) { imageObj *pNewImage = NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode != MS_IMAGEMODE_RGBA) { msSetError( MS_OGLERR, "OpenGL driver only supports RGB or RGBA pixel models.", "msImageCreateOGL()"); return NULL; } return createImageObjOgl(new OglRenderer(width, height, bg)); } int msRenderEllipseOgl(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { OglRenderer* renderer = getOglRenderer(image); renderer->renderEllipse(x, y, style->rotation, symbol->sizex, symbol->sizey, style->color, style->outlinecolor, style->outlinewidth); return MS_SUCCESS; } int msFreeImageOgl(imageObj *img) { OglRenderer* renderer = getOglRenderer(img); if (renderer) { delete renderer; } img->img.plugin=NULL; return MS_SUCCESS; } int msStartLayerOgl(imageObj *img, mapObj *map, layerObj *layer) { getOglRenderer(img)->setTransparency((double)layer->opacity/100); return MS_SUCCESS; } int msEndLayerOgl(imageObj *img, mapObj *map, layerObj *layer) { getOglRenderer(img)->setTransparency(1.0); return MS_SUCCESS; } int msFreeSymbolOgl(symbolObj *s) { return MS_SUCCESS; } int msGetRasterBufferCopyOgl(imageObj *img, rasterBufferObj *rb) { getOglRenderer(img)->readRasterBuffer(rb); return MS_SUCCESS; } int msGetRasterBufferHandleOgl(imageObj *img, rasterBufferObj * rb) { getOglRenderer(img)->readRasterBuffer(rb); return MS_SUCCESS; } int msInitializeRasterBufferOgl(rasterBufferObj *rb, int width, int height, int mode) { OglRenderer::initializeRasterBuffer(rb, width, height, mode==MS_IMAGEMODE_RGBA); return MS_SUCCESS; } #endif /* USE_OGL */ int msPopulateRendererVTableOGL(rendererVTableObj *renderer) { #ifdef USE_OGL renderer->supports_transparent_layers = 1; renderer->supports_pixel_buffer = 1; renderer->supports_clipping = 0; renderer->use_imagecache = 0; renderer->supports_bitmap_fonts = 0; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; renderer->startLayer = msStartLayerOgl; renderer->endLayer = msEndLayerOgl; renderer->createImage=&msImageCreateOgl; renderer->saveImage=&msSaveImageOgl; renderer->renderLine=&msDrawLineOgl; renderer->renderPolygon=&msDrawPolygonOgl; renderer->renderGlyphs=&msRenderGlyphsOgl; renderer->renderEllipseSymbol = &msRenderEllipseOgl; renderer->renderVectorSymbol = &msRenderVectorSymbolOgl; renderer->renderPixmapSymbol = &msRenderPixmapOgl; renderer->renderTruetypeSymbol = &msRenderTruetypeSymbolOgl; renderer->renderTile = &msRenderTileOgl; renderer->renderPolygonTiled = &msDrawPolygonTiledOgl; renderer->renderLineTiled = &msDrawLineTiledOgl; renderer->getTruetypeTextBBox = &msGetTruetypeTextBBoxOgl; renderer->getRasterBufferHandle = msGetRasterBufferHandleOgl; renderer->getRasterBufferCopy = msGetRasterBufferCopyOgl; renderer->initializeRasterBuffer = msInitializeRasterBufferOgl; renderer->mergeRasterBuffer = msMergeRasterBufferOgl; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->freeSymbol = &msFreeSymbolOgl; renderer->freeImage=&msFreeImageOgl; return MS_SUCCESS; #else msSetError(MS_MISCERR,"OGL driver requested but it is not compiled in this release", "msPopulateRendererVTableOGL()"); return MS_FAILURE; #endif } mapserver-6.4.1/mapcontour.c0000644002461700001440000007246212261257215015662 0ustar tbonfortusers/********************************************************************** * $Id: mapcontour.c 12629 2011-10-06 18:06:34Z aboudreault $ * * Project: MapServer * Purpose: Contour Layer * Author: Alan Boudreault (aboudreault@mapgears.com) * Author: Daniel Morissette (dmorissette@mapgears.com) * ********************************************************************** * Copyright (c) 2011, Alan Boudreault, MapGears * * 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. **********************************************************************/ #include "mapserver.h" #include "mapcopy.h" #include "mapresample.h" #ifdef USE_GDAL #include "ogr_api.h" #include "ogr_srs_api.h" #include "gdal.h" #include "gdal_alg.h" #include "mapthread.h" #include "cpl_string.h" #define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y)) extern int InvGeoTransform(double *gt_in, double *gt_out); typedef struct { /* OGR DataSource */ layerObj ogrLayer; /* internal use */ GDALDatasetH hOrigDS; GDALDatasetH hDS; double *buffer; /* memory dataset buffer */ rectObj extent; /* original dataset extent */ OGRDataSourceH hOGRDS; double cellsize; } contourLayerInfo; static int msContourLayerInitItemInfo(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerInitItemInfo()"); return MS_FAILURE; } return msLayerInitItemInfo(&clinfo->ogrLayer); } static void msContourLayerFreeItemInfo(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerFreeItemInfo()"); return; } msLayerFreeItemInfo(&clinfo->ogrLayer); } static void msContourLayerInfoInitialize(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo != NULL) return; clinfo = (contourLayerInfo *) msSmallCalloc(1,sizeof(contourLayerInfo)); layer->layerinfo = clinfo; clinfo->hOrigDS = NULL; clinfo->hDS = NULL; clinfo->extent.minx = -1.0; clinfo->extent.miny = -1.0; clinfo->extent.maxx = -1.0; clinfo->extent.maxy = -1.0; initLayer(&clinfo->ogrLayer, layer->map); clinfo->ogrLayer.type = layer->type; clinfo->ogrLayer.debug = layer->debug; clinfo->ogrLayer.connectiontype = MS_OGR; clinfo->ogrLayer.name = msStrdup(layer->name); clinfo->ogrLayer.connection = (char*)msSmallMalloc(strlen(clinfo->ogrLayer.name)+13); sprintf(clinfo->ogrLayer.connection, "__%s_CONTOUR__", clinfo->ogrLayer.name); clinfo->ogrLayer.units = layer->units; } static void msContourLayerInfoFree(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) return; freeLayer(&clinfo->ogrLayer); free(clinfo); layer->layerinfo = NULL; } static int msContourLayerReadRaster(layerObj *layer, rectObj rect) { mapObj *map = layer->map; char **bands; char pointer[64], memDSPointer[128]; int band = 1; double adfGeoTransform[6], adfInvGeoTransform[6]; double llx, lly, urx, ury; rectObj copyRect, mapRect; int dst_xsize, dst_ysize; int virtual_grid_step_x, virtual_grid_step_y; int src_xoff, src_yoff, src_xsize, src_ysize; double map_cellsize_x, map_cellsize_y, dst_cellsize_x, dst_cellsize_y; GDALRasterBandH hBand = NULL; CPLErr eErr; contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerReadRaster().\n"); if (clinfo == NULL || clinfo->hOrigDS == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerReadRaster()"); return MS_FAILURE; } bands = CSLTokenizeStringComplex( CSLFetchNameValue(layer->processing,"BANDS"), " ,", FALSE, FALSE ); if (CSLCount(bands) > 0) { band = atoi(bands[0]); if (band < 1 || band > GDALGetRasterCount(clinfo->hOrigDS)) { msSetError( MS_IMGERR, "BANDS PROCESSING directive includes illegal band '%d', should be from 1 to %d.", "msContourLayerReadRaster()", band, GDALGetRasterCount(clinfo->hOrigDS)); CSLDestroy(bands); return MS_FAILURE; } } CSLDestroy(bands); hBand = GDALGetRasterBand(clinfo->hOrigDS, band); if (hBand == NULL) { msSetError(MS_IMGERR, "Band %d does not exist on dataset.", "msContourLayerReadRaster()", band); return MS_FAILURE; } if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { const char *wkt; wkt = GDALGetProjectionRef(clinfo->hOrigDS); if (wkt != NULL && strlen(wkt) > 0) { if (msOGCWKT2ProjectionObj(wkt, &(layer->projection), layer->debug) != MS_SUCCESS) { char msg[MESSAGELENGTH*2]; errorObj *ms_error = msGetErrorObj(); snprintf( msg, sizeof(msg), "%s\n" "PROJECTION AUTO cannot be used for this " "GDAL raster (`%s').", ms_error->message, layer->data); msg[MESSAGELENGTH-1] = '\0'; msSetError(MS_OGRERR, "%s","msDrawRasterLayer()", msg); return MS_FAILURE; } } } /* * Compute the georeferenced window of overlap, and read the source data * downsampled to match output resolution, or at full resolution if * output resolution is lower than the source resolution. * * A large portion of this overlap calculation code was borrowed from * msDrawRasterLayerGDAL(). * Would be possible to move some of this to a reusable function? * * Note: This code works only if no reprojection is involved. It would * need rework to support cases where output projection differs from source * data file projection. */ src_xsize = GDALGetRasterXSize(clinfo->hOrigDS); src_ysize = GDALGetRasterYSize(clinfo->hOrigDS); /* set the Dataset extent */ msGetGDALGeoTransform(clinfo->hOrigDS, map, layer, adfGeoTransform); clinfo->extent.minx = adfGeoTransform[0]; clinfo->extent.maxy = adfGeoTransform[3]; clinfo->extent.maxx = adfGeoTransform[0] + src_xsize * adfGeoTransform[1]; clinfo->extent.miny = adfGeoTransform[3] + src_ysize * adfGeoTransform[5]; if (layer->transform) { if (layer->debug) msDebug("msContourLayerReadRaster(): Entering transform.\n"); InvGeoTransform(adfGeoTransform, adfInvGeoTransform); mapRect = rect; map_cellsize_x = map_cellsize_y = map->cellsize; #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if (msProjectionsDiffer( &(map->projection), &(layer->projection))) { if ( msProjectRect(&map->projection, &layer->projection, &mapRect) != MS_SUCCESS ) { msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } map_cellsize_x = MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width); map_cellsize_y = MS_CELLSIZE(mapRect.miny, mapRect.maxy, map->height); /* if the projection failed to project the extent requested, we need to calculate the cellsize to preserve the initial map cellsize ratio */ if ( (mapRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize)) || (mapRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0)) || (mapRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize)) || (mapRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0)) ) { int src_unit, dst_unit; src_unit = GetMapserverUnitUsingProj(&map->projection); dst_unit = GetMapserverUnitUsingProj(&layer->projection); if (src_unit == -1 || dst_unit == -1) { msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } map_cellsize_x = MS_CONVERT_UNIT(src_unit, dst_unit, MS_CELLSIZE(rect.minx, rect.maxx, map->width)); map_cellsize_y = MS_CONVERT_UNIT(src_unit, dst_unit, MS_CELLSIZE(rect.miny, rect.maxy, map->height)); } } #endif if (map_cellsize_x == 0 || map_cellsize_y == 0) { if (layer->debug) msDebug("msContourLayerReadRaster(): Cellsize can't be 0.\n"); return MS_FAILURE; } /* Adjust MapServer pixel model to GDAL pixel model */ mapRect.minx -= map_cellsize_x*0.5; mapRect.maxx += map_cellsize_x*0.5; mapRect.miny -= map_cellsize_y*0.5; mapRect.maxy += map_cellsize_y*0.5; /* * If raw data cellsize (from geotransform) is larger than output map_cellsize * then we want to extract only enough data to match the output map resolution * which means that GDAL will automatically sample the data on read. * * To prevent bad contour effects on tile edges, we adjust the target cellsize * to align the extracted window with a virtual grid based on the origin of the * raw data and a virtual grid step size corresponding to an integer sampling step. * * If source data has a greater cellsize (i.e. lower res) that requested ouptut map * then we use the raw data cellsize as target cellsize since there is no point in * interpolating the data for contours in this case. */ virtual_grid_step_x = (int)floor(map_cellsize_x / ABS(adfGeoTransform[1])); if (virtual_grid_step_x < 1) virtual_grid_step_x = 1; /* Do not interpolate data if grid sampling step < 1 */ virtual_grid_step_y = (int)floor(map_cellsize_y / ABS(adfGeoTransform[5])); if (virtual_grid_step_y < 1) virtual_grid_step_y = 1; /* Do not interpolate data if grid sampling step < 1 */ /* target cellsize is a multiple of raw data cellsize based on grid step*/ dst_cellsize_x = ABS(adfGeoTransform[1]) * virtual_grid_step_x; dst_cellsize_y = ABS(adfGeoTransform[5]) * virtual_grid_step_y; /* Compute overlap between source and target views */ copyRect = mapRect; if (copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize)) copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize); if (copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0)) copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0); if (copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize)) copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize); if (copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0)) copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0); if (copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy) { if (layer->debug) msDebug("msContourLayerReadRaster(): No overlap.\n"); return MS_SUCCESS; } /* * Convert extraction window to raster coordinates */ llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny); lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny); urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy); ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy); /* * Align extraction window with virtual grid * (keep in mind raster coordinates origin is at upper-left) * We also add an extra buffer to fix tile boundarie issues when zoomed */ llx = floor(llx / virtual_grid_step_x) * virtual_grid_step_x - (virtual_grid_step_x*5); urx = ceil(urx / virtual_grid_step_x) * virtual_grid_step_x + (virtual_grid_step_x*5); ury = floor(ury / virtual_grid_step_y) * virtual_grid_step_y - (virtual_grid_step_x*5); lly = ceil(lly / virtual_grid_step_y) * virtual_grid_step_y + (virtual_grid_step_x*5); src_xoff = MAX(0,(int) floor(llx+0.5)); src_yoff = MAX(0,(int) floor(ury+0.5)); src_xsize = MIN(MAX(0,(int) (urx - llx + 0.5)), GDALGetRasterXSize(clinfo->hOrigDS) - src_xoff); src_ysize = MIN(MAX(0,(int) (lly - ury + 0.5)), GDALGetRasterYSize(clinfo->hOrigDS) - src_yoff); /* Update the geographic extent (buffer added) */ /* TODO: a better way to go the geo_trans */ copyRect.minx = GEO_TRANS(adfGeoTransform+0,src_xoff,0); copyRect.maxx = GEO_TRANS(adfGeoTransform+0,src_xoff+src_xsize,0); copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_yoff+src_ysize); copyRect.maxy = GEO_TRANS(adfGeoTransform+3,0,src_yoff); /* * If input window is to small then stop here */ if (src_xsize < 2 || src_ysize < 2) { if (layer->debug) msDebug("msContourLayerReadRaster(): input window too small, or no apparent overlap between map view and this window(1).\n"); return MS_SUCCESS; } /* Target buffer size */ dst_xsize = (int)ceil((copyRect.maxx - copyRect.minx) / dst_cellsize_x); dst_ysize = (int)ceil((copyRect.maxy - copyRect.miny) / dst_cellsize_y); if (dst_xsize == 0 || dst_ysize == 0) { if (layer->debug) msDebug("msContourLayerReadRaster(): no apparent overlap between map view and this window(2).\n"); return MS_SUCCESS; } if (layer->debug) msDebug( "msContourLayerReadRaster(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n", src_xoff, src_yoff, src_xsize, src_ysize, 0, 0, dst_xsize, dst_ysize ); } else { src_xoff = 0; src_yoff = 0; dst_xsize = src_xsize = MIN(map->width,src_xsize); dst_ysize = src_ysize = MIN(map->height,src_ysize); } /* -------------------------------------------------------------------- */ /* Allocate buffer, and read data into it. */ /* -------------------------------------------------------------------- */ clinfo->buffer = (double *) malloc(sizeof(double) * dst_xsize * dst_ysize); if (clinfo->buffer == NULL) { msSetError(MS_MEMERR, "Malloc(): Out of memory.", "msContourLayerReadRaster()"); return MS_FAILURE; } eErr = GDALRasterIO(hBand, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, clinfo->buffer, dst_xsize, dst_ysize, GDT_Float64, 0, 0); if (eErr != CE_None) { msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "msContourLayerReadRaster()", CPLGetLastErrorMsg() ); free(clinfo->buffer); return MS_FAILURE; } memset(pointer, 0, sizeof(pointer)); CPLPrintPointer(pointer, clinfo->buffer, sizeof(pointer)); sprintf(memDSPointer,"MEM:::DATAPOINTER=%s,PIXELS=%d,LINES=%d,BANDS=1,DATATYPE=Float64", pointer, dst_xsize, dst_ysize); clinfo->hDS = GDALOpen(memDSPointer, GA_ReadOnly); if (clinfo->hDS == NULL) { msSetError(MS_IMGERR, "Unable to open GDAL Memory dataset.", "msContourLayerReadRaster()"); free(clinfo->buffer); return MS_FAILURE; } adfGeoTransform[0] = copyRect.minx; adfGeoTransform[1] = dst_cellsize_x; adfGeoTransform[2] = 0; adfGeoTransform[3] = copyRect.maxy; adfGeoTransform[4] = 0; adfGeoTransform[5] = -dst_cellsize_y; clinfo->cellsize = MAX(dst_cellsize_x, dst_cellsize_y); { char buf[64]; sprintf(buf, "%lf", clinfo->cellsize); msInsertHashTable(&layer->metadata, "__data_cellsize__", buf); } GDALSetGeoTransform(clinfo->hDS, adfGeoTransform); return MS_SUCCESS; } static void msContourOGRCloseConnection(void *conn_handle) { OGRDataSourceH hDS = (OGRDataSourceH) conn_handle; msAcquireLock(TLOCK_OGR); OGR_DS_Destroy(hDS); msReleaseLock(TLOCK_OGR); } /* Function that parses multiple options in the a list. It also supports min/maxscaledenom checks. ie. "CONTOUR_INTERVAL=0,3842942:10" */ static char* msContourGetOption(layerObj *layer, const char *name) { int c, i, found = MS_FALSE; char **values, **tmp, **options; double maxscaledenom, minscaledenom; char *value = NULL; options = CSLFetchNameValueMultiple(layer->processing, name); c = CSLCount(options); /* First pass to find the value among options that have min/maxscaledenom */ /* specified */ for (i=0; imap->scaledenom <= 0 || (((maxscaledenom <= 0) || (layer->map->scaledenom <= maxscaledenom)) && ((minscaledenom <= 0) || (layer->map->scaledenom > minscaledenom)))) { value = msStrdup(values[1]); found = MS_TRUE; } } CSLDestroy(tmp); } CSLDestroy(values); } /* Second pass to find the value among options that do NOT have */ /* min/maxscaledenom specified */ for (i=0; ilayerinfo; OGRRegisterAll(); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerCreateOGRDataSource()"); return MS_FAILURE; } if (!clinfo->hDS) { /* no overlap */ return MS_SUCCESS; } hBand = GDALGetRasterBand(clinfo->hDS, 1); if (hBand == NULL) { msSetError(MS_IMGERR, "Band %d does not exist on dataset.", "msContourLayerGenerateContour()", 1); return MS_FAILURE; } /* Create the OGR DataSource */ hDriver = OGRGetDriverByName("Memory"); if (hDriver == NULL) { msSetError(MS_OGRERR, "Unable to get OGR driver 'Memory'.", "msContourLayerCreateOGRDataSource()"); return MS_FAILURE; } clinfo->hOGRDS = OGR_Dr_CreateDataSource(hDriver, NULL, NULL); if (clinfo->hOGRDS == NULL) { msSetError(MS_OGRERR, "Unable to create OGR DataSource.", "msContourLayerCreateOGRDataSource()"); return MS_FAILURE; } hLayer = OGR_DS_CreateLayer(clinfo->hOGRDS, clinfo->ogrLayer.name, NULL, wkbLineString, NULL ); hFld = OGR_Fld_Create("ID", OFTInteger); OGR_Fld_SetWidth(hFld, 8); OGR_L_CreateField(hLayer, hFld, FALSE); OGR_Fld_Destroy(hFld); /* Check if we have a coutour item specified */ elevItem = CSLFetchNameValue(layer->processing,"CONTOUR_ITEM"); if (elevItem && strlen(elevItem) > 0) { hFld = OGR_Fld_Create(elevItem, OFTReal); OGR_Fld_SetWidth(hFld, 12); OGR_Fld_SetPrecision(hFld, 3); OGR_L_CreateField(hLayer, hFld, FALSE); OGR_Fld_Destroy(hFld); } else { elevItem = NULL; } option = msContourGetOption(layer, "CONTOUR_INTERVAL"); if (option) { interval = atof(option); free(option); } option = msContourGetOption(layer, "CONTOUR_LEVELS"); if (option) { int i,c; char **levelsTmp; levelsTmp = CSLTokenizeStringComplex(option, ",", FALSE, FALSE); c = CSLCount(levelsTmp); for (i=0;iogrLayer, clinfo->hOGRDS, msContourOGRCloseConnection); return MS_SUCCESS; } int msContourLayerOpen(layerObj *layer) { char *decrypted_path; char szPath[MS_MAXPATHLEN]; contourLayerInfo *clinfo; if (layer->debug) msDebug("Entering msContourLayerOpen().\n"); /* If we don't have info, initialize an empty one now */ if (layer->layerinfo == NULL) msContourLayerInfoInitialize(layer); clinfo = (contourLayerInfo *) layer->layerinfo; GDALAllRegister(); /* Open the original Dataset */ msTryBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->data); decrypted_path = msDecryptStringTokens(layer->map, szPath); msAcquireLock(TLOCK_GDAL); if (decrypted_path) { clinfo->hOrigDS = GDALOpen(decrypted_path, GA_ReadOnly); msFree(decrypted_path); } else clinfo->hOrigDS = NULL; msReleaseLock(TLOCK_GDAL); if (clinfo->hOrigDS == NULL) { msSetError(MS_IMGERR, "Unable to open GDAL dataset.", "msContourLayerOpen()"); return MS_FAILURE; } /* Open the raster source */ if (msContourLayerReadRaster(layer, layer->map->extent) != MS_SUCCESS) return MS_FAILURE; /* Generate Contour Dataset */ if (msContourLayerGenerateContour(layer) != MS_SUCCESS) return MS_FAILURE; if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } /* Open our virtual ogr layer */ if (clinfo->hOGRDS && (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS)) return MS_FAILURE; return MS_SUCCESS; } int msContourLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return MS_TRUE; return MS_FALSE; } int msContourLayerClose(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerClose().\n"); if (clinfo) { if (clinfo->hOGRDS) msConnPoolRelease(&clinfo->ogrLayer, clinfo->hOGRDS); msLayerClose(&clinfo->ogrLayer); if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } if (clinfo->hOrigDS) { GDALClose(clinfo->hOrigDS); clinfo->hOrigDS = NULL; } msContourLayerInfoFree(layer); } return MS_SUCCESS; } int msContourLayerGetItems(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerGetItems()"); return MS_FAILURE; } return msContourLayerGetItems(&clinfo->ogrLayer); } int msContourLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i; rectObj newRect; contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerWhichShapes().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerWhichShapes()"); return MS_FAILURE; } newRect = rect; #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if (msProjectionsDiffer( &(layer->map->projection), &(layer->projection))) { if (msProjectRect(&layer->projection, &layer->map->projection, &newRect) != MS_SUCCESS ) { msDebug("msContourLayerWhichShapes(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } } #endif /* regenerate the raster io */ if (clinfo->hOGRDS) msConnPoolRelease(&clinfo->ogrLayer, clinfo->hOGRDS); msLayerClose(&clinfo->ogrLayer); /* Open the raster source */ if (msContourLayerReadRaster(layer, newRect) != MS_SUCCESS) return MS_FAILURE; /* Generate Contour Dataset */ if (msContourLayerGenerateContour(layer) != MS_SUCCESS) return MS_FAILURE; if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } if (!clinfo->hOGRDS) /* no overlap */ return MS_DONE; /* Open our virtual ogr layer */ if (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS) return MS_FAILURE; clinfo->ogrLayer.numitems = layer->numitems; clinfo->ogrLayer.items = (char **) msSmallMalloc(sizeof(char *)*layer->numitems); for (i=0; inumitems;++i) { clinfo->ogrLayer.items[i] = msStrdup(layer->items[i]); } return msLayerWhichShapes(&clinfo->ogrLayer, rect, isQuery); } int msContourLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerGetShape().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerGetShape()"); return MS_FAILURE; } return msLayerGetShape(&clinfo->ogrLayer, shape, record); } int msContourLayerNextShape(layerObj *layer, shapeObj *shape) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerNextShape().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerNextShape()"); return MS_FAILURE; } return msLayerNextShape(&clinfo->ogrLayer, shape); } /************************************************************************/ /* msContourLayerGetExtent() */ /* Simple copy of the maprasterquery.c file. might change in the future */ /************************************************************************/ int msContourLayerGetExtent(layerObj *layer, rectObj *extent) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerGetExtent().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerGetExtent()"); return MS_FAILURE; } MS_COPYRECT(extent, &clinfo->extent); return MS_SUCCESS; } int msContourLayerSetTimeFilter(layerObj *layer, const char *timestring, const char *timefield) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerSetTimeFilter().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerSetTimeFilter()"); return MS_FAILURE; } return msLayerSetTimeFilter(&clinfo->ogrLayer, timestring, timefield); } /************************************************************************/ /* msRASTERLayerInitializeVirtualTable() */ /************************************************************************/ int msContourLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msContourLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msContourLayerFreeItemInfo; layer->vtable->LayerOpen = msContourLayerOpen; layer->vtable->LayerIsOpen = msContourLayerIsOpen; layer->vtable->LayerWhichShapes = msContourLayerWhichShapes; layer->vtable->LayerNextShape = msContourLayerNextShape; layer->vtable->LayerGetShape = msContourLayerGetShape; layer->vtable->LayerClose = msContourLayerClose; layer->vtable->LayerGetItems = msContourLayerGetItems; layer->vtable->LayerGetExtent = msContourLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /*layer->vtable->LayerCloseConnection = msContourLayerClose;*/ /* we use backtics for proper tileindex shapefile functioning */ layer->vtable->LayerSetTimeFilter = msContourLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } #else int msContourLayerInitializeVirtualTable(layerObj *layer) { msSetError(MS_MISCERR, "Contour Layer needs GDAL support, but it it not compiled in", "msContourLayerInitializeVirtualTable()"); return MS_FAILURE; } #endif