Beispiel #1
0
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; i<shapefile->numshapes; i++) {
    if(msSHPReadBounds(shapefile->hSHP, i, &bounds) == MS_SUCCESS)
      treeAddShapeId(tree, i, bounds);
  }

  return tree;
}
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;
}
Beispiel #3
0
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; i<node->numshapes; 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; i<node->numsubnodes; i++ ) {
    if(node->subnode[i])
      writeTreeNode(disktree, node->subnode[i]);
  }


  return;

}
Beispiel #4
0
void msSetLimitedPatternsToUse(const 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<ntmp; i++) {
        for (j=0; j<MS_NUMTIMEFORMATS; j++) {
          if (strcasecmp( ms_timeFormats[j].userformat, patterns[i]) ==0) {
            limitedpatternindice[numpatterns] = j;
            numpatterns++;
            break;
          }
        }
      }
    }
    msFreeCharArray(patterns, ntmp);
  }

  if (numpatterns > 0) {
    for (i=0; i<numpatterns; i++)
      ms_limited_pattern[i] = limitedpatternindice[i];

    ms_num_limited_pattern = numpatterns;
  }
  free (limitedpatternindice);
}
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; i<numLineStyle; i++) {
    if (style->width == 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));
  }

}
Beispiel #6
0
int msParseTime(const char *string, struct tm *tm) {
  int i, indice = 0;
  int num_patterns = 0;
  
  /* if limited patterns are set, use then. Else use all the */
  /* patterns defined */
  if (ms_limited_pattern &&  ms_num_limited_pattern > 0)
    num_patterns = ms_num_limited_pattern;
  else
    num_patterns = MS_NUMTIMEFORMATS;

  for(i=0; i<num_patterns; i++) {
      if (ms_num_limited_pattern > 0)
        indice = ms_limited_pattern[i];
      else
        indice = i;

      if(!ms_timeFormats[indice].regex) { /* compile the expression */
      ms_timeFormats[indice].regex = (ms_regex_t *) msSmallMalloc(sizeof(ms_regex_t)); 
      if(ms_regcomp(ms_timeFormats[indice].regex, ms_timeFormats[indice].pattern, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) {
	msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msParseTime()", ms_timeFormats[indice].pattern);
	return(MS_FALSE);
      }
    }  

    /* test the expression against the string */
    if(ms_regexec(ms_timeFormats[indice].regex, string, 0, NULL, 0) == 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);
}
Beispiel #7
0
xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
                            int nWFSVersion, const char* validate_language)
{
  rectObj ext;

  xmlNodePtr psRootNode, psNode;
  const char *value    = NULL;
  char *valueToFree;
  char **tokens;
  int n=0,i=0;

  psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType");

  /* add namespace to layer name */
  value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix");

  /* FIXME? Should probably be applied to WFS 1.1 as well, but the addition */
  /* of the prefix can be disruptive for clients */
  if( value == NULL && nWFSVersion >= OWS_2_0_0 )
      value = MS_DEFAULT_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);

    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST valueToFree);
    msFree(valueToFree);
  } else {
    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name);
  }

  if (lp->name && strlen(lp->name) > 0 &&
      (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0])))
  {
    char szTmp[512];
    snprintf(szTmp, sizeof(szTmp),
             "WARNING: The layer name '%s' might contain spaces or "
             "invalid characters or may start with a number. This could lead to potential problems",
             lp->name);
    xmlAddSibling(psNode, xmlNewComment(BAD_CAST szTmp));
  }

  value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "title", validate_language);
  if (!value)
    value =(const char*)lp->name;

  psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value);


  value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "abstract", validate_language);
  if (value)
    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value);



  value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "keywordlist", validate_language);

  if(value)
    msLibXml2GenerateList(
        xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL),
        NULL, "Keyword", value, ',' );

  /*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) {
      if( nWFSVersion == OWS_1_1_0 )
        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]);
      else
        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultCRS", BAD_CAST tokens[0]);
      for (i=1; i<n; i++)
      {
        if( nWFSVersion == OWS_1_1_0 )
          psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);
        else
          psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherCRS", BAD_CAST tokens[i]);
      }

      msFreeCharArray(tokens, n);
    }
  } else
    xmlAddSibling(psNode,
                  xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context."));

  free(valueToFree);
  valueToFree = NULL;

  /*TODO: adevertize only gml3?*/
  psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats");
  xmlAddChild(psRootNode, psNode);

  {
    char *formats_list = msWFSGetOutputFormatList( map, lp, nWFSVersion );
    int iformat, n;
    char **tokens;

    n = 0;
    tokens = msStringSplit(formats_list, ',', &n);

    for( iformat = 0; iformat < n; iformat++ )
      xmlNewChild(psNode, NULL, BAD_CAST "Format",
                  BAD_CAST tokens[iformat] );
    msFree( formats_list );
    msFreeCharArray( tokens, n );
  }

  /*bbox*/
  if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) {
    /*convert to latlong*/
    if (lp->projection.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) {
    if( nWFSVersion >= OWS_2_0_0 )
    {
        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", NULL);
        xmlNewProp(psNode, BAD_CAST "xlink:href", BAD_CAST value);

        value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_about");
        if( value != NULL )
            xmlNewProp(psNode, BAD_CAST "about", BAD_CAST value);
    }
    else
    {
        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;
}
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) {
    encoded = msGetEncodedString(value, encoding);

    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; i<n; i++)
        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);

      msFreeCharArray(tokens, n);
    }
  } else
    xmlAddSibling(psNode,
                  xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context."));

  free(valueToFree);
  valueToFree = NULL;

  /*TODO: adevertize only gml3?*/
  psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats");
  xmlAddChild(psRootNode, psNode);

  {
    char *formats_list = msWFSGetOutputFormatList( map, lp, "1.1.0" );
    int iformat, n;
    char **tokens;

    n = 0;
    tokens = msStringSplit(formats_list, ',', &n);

    for( iformat = 0; iformat < n; iformat++ )
      xmlNewChild(psNode, NULL, BAD_CAST "Format",
                  BAD_CAST tokens[iformat] );
    msFree( formats_list );
    msFreeCharArray( tokens, n );
  }

  /*bbox*/
  if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) {
    /*convert to latlong*/
    if (lp->projection.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;
}
Beispiel #9
0
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")
      || strcmp(pszFilename+strlen(pszFilename)-4,".shx") ) {
    strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".dbf");
  } else if( strcmp(pszFilename+strlen(pszFilename)-4,".SHP")
             || strcmp(pszFilename+strlen(pszFilename)-4,".SHX") ) {
    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 )
    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 );
}
char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp)
{
  char *pszExpression = NULL;
  shapeObj *psQueryShape = NULL;
  double dfDistance = -1;
  int nUnit = -1, nLayerUnit = -1;
  char *pszWktText = NULL;
  char szBuffer[256];
  char *pszTmp=NULL;
  projectionObj sProjTmp;
  rectObj sQueryRect;
  shapeObj *psTmpShape=NULL;
  int bBBoxQuery = 0;
  int bAlreadyReprojected = 0;

  if (psNode == NULL || lp == NULL)
    return NULL;

  if (psNode->eType != FILTER_NODE_TYPE_SPATIAL)
    return NULL;

  /* get the shape */
  if (FLTIsBBoxFilter(psNode)) {
    char szPolygon[512];
    FLTGetBBOX(psNode, &sQueryRect);

    snprintf(szPolygon, sizeof(szPolygon),
             "POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))",
             sQueryRect.minx, sQueryRect.miny,
             sQueryRect.minx, sQueryRect.maxy,
             sQueryRect.maxx, sQueryRect.maxy,
             sQueryRect.maxx, sQueryRect.miny,
             sQueryRect.minx, sQueryRect.miny);

    psTmpShape = msShapeFromWKT(szPolygon);

    /* 
    ** This is a horrible hack to deal with world-extent requests and
    ** reprojection. msProjectRect() detects if reprojection from longlat to 
    ** projected SRS, and in that case it transforms the bbox to -1e-15,-1e-15,1e15,1e15
    ** to ensure that all features are returned.
    **
    ** Make wfs_200_cite_filter_bbox_world.xml and wfs_200_cite_postgis_bbox_world.xml pass
    */
    if (fabs(sQueryRect.minx - -180.0) < 1e-5 &&
        fabs(sQueryRect.miny - -90.0) < 1e-5 &&
        fabs(sQueryRect.maxx - 180.0) < 1e-5 &&
        fabs(sQueryRect.maxy - 90.0) < 1e-5)
    {
      if (lp->projection.numargs > 0) {
        if (psNode->pszSRS)
          msInitProjection(&sProjTmp);
        if (psNode->pszSRS) {
          /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */
          if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) {
            msProjectRect(&sProjTmp, &lp->projection, &sQueryRect);
          }
        } else if (lp->map->projection.numargs > 0)
          msProjectRect(&lp->map->projection, &lp->projection, &sQueryRect);
        if (psNode->pszSRS)
          msFreeProjection(&sProjTmp);
      }
      if (sQueryRect.minx <= -1e14) {
        msFreeShape(psTmpShape);
        msFree(psTmpShape);
        psTmpShape = (shapeObj*) msSmallMalloc(sizeof(shapeObj));
        msInitShape(psTmpShape);
        msRectToPolygon(sQueryRect, psTmpShape);
        bAlreadyReprojected = 1;
      }
    }

    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) {
      nLayerUnit = lp->units;
      if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->projection);
      if(nLayerUnit == -1) nLayerUnit = lp->map->units;
      if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->map->projection);

      if (nUnit >= 0 && nUnit != nLayerUnit)
        dfDistance *= msInchesPerUnit(nUnit,0)/msInchesPerUnit(nLayerUnit,0); /* target is layer units */
    }

    psTmpShape = psQueryShape;
  }

  if (psTmpShape) {

    /*
    ** target is layer projection
    */
    if (!bAlreadyReprojected && lp->projection.numargs > 0) {
      if (psNode->pszSRS)
        msInitProjection(&sProjTmp);
      if (psNode->pszSRS) {
        /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */
        if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) {
          msProjectShape(&sProjTmp, &lp->projection, psTmpShape);
        }
      } else if (lp->map->projection.numargs > 0)
        msProjectShape(&lp->map->projection, &lp->projection, psTmpShape);
      if (psNode->pszSRS)
        msFreeProjection(&sProjTmp);
    }

    /* function name */
    if (bBBoxQuery) {
      sprintf(szBuffer, "%s", "intersects");
    } else {
      if (strncasecmp(psNode->pszValue, "intersect", 9) == 0)
        sprintf(szBuffer, "%s", "intersects");
      else {
        pszTmp = msStrdup(psNode->pszValue);
        msStringToLower(pszTmp);
        sprintf(szBuffer, "%s", pszTmp);
        msFree(pszTmp);
      }
    }
    pszExpression = msStringConcatenate(pszExpression, szBuffer);
    pszExpression = msStringConcatenate(pszExpression, "(");

    /* geometry binding */
    sprintf(szBuffer, "%s", "[shape]");
    pszExpression = msStringConcatenate(pszExpression, szBuffer);
    pszExpression = msStringConcatenate(pszExpression, ",");

    /* filter geometry */
    pszWktText = msGEOSShapeToWKT(psTmpShape);
    sprintf(szBuffer, "%s", "fromText('");
    pszExpression = msStringConcatenate(pszExpression, szBuffer);
    pszExpression = msStringConcatenate(pszExpression, pszWktText);
    sprintf(szBuffer, "%s", "')");
    pszExpression = msStringConcatenate(pszExpression, szBuffer);
    msGEOSFreeWKT(pszWktText);

    /* (optional) beyond/dwithin distance, always 0.0 since we apply the distance as a buffer earlier */
    if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0)) {
      // pszExpression = msStringConcatenate(pszExpression, ",0.0");
      sprintf(szBuffer, ",%g", dfDistance);
      pszExpression = msStringConcatenate(pszExpression, szBuffer);      
    }

    /* terminate the function */
    pszExpression = msStringConcatenate(pszExpression, ") = TRUE");
  }

  /*
  ** Cleanup
  */
  if (bBBoxQuery) {
    msFreeShape(psTmpShape);
    msFree(psTmpShape);
  }

  return pszExpression;
}
Beispiel #11
0
int msPreloadSVGSymbol(symbolObj *symbol)
{
#ifdef USE_SVG_CAIRO
    int status;
    unsigned int svg_width, svg_height;
    struct svg_symbol_cache *cache;

    if(!symbol->renderer_cache) {
        cache = msSmallCalloc(1,sizeof(struct svg_symbol_cache));
    } else {
        cache = symbol->renderer_cache;
    }
    if(cache->svgc)
        return MS_SUCCESS;

    if (!symbol->svg_text) {
        FILE *stream;
        long int file_len;

        if ((stream = fopen(symbol->full_pixmap_path, "rb")) == NULL) {
            msSetError(MS_IOERR, "Could not open svg file %s", "msPreloadSVGSymbol()",symbol->full_pixmap_path);
            return (MS_FAILURE);
        }
        fseek(stream, 0, SEEK_END);
        file_len = ftell(stream);
        rewind(stream);
        symbol->svg_text = (char*) msSmallMalloc(sizeof (char) * file_len);
        if (1 != fread(symbol->svg_text, file_len, 1, stream)) {
            msSetError(MS_IOERR, "failed to read %d bytes from svg file %s", "loadSymbol()", file_len, symbol->full_pixmap_path);
            free(symbol->svg_text);
            return MS_FAILURE;
        }
        symbol->svg_text[file_len - 1] = '\0';
        fclose(stream);
    }

    status = svg_cairo_create(&cache->svgc);
    if (status) {
        msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()");
        return MS_FAILURE;
    }
    status = svg_cairo_parse_buffer(cache->svgc, symbol->svg_text, strlen(symbol->svg_text));
    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;
    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
}
Beispiel #12
0
int utfgridCleanData(imageObj *img)
{
  UTFGridRenderer *r = UTFGRID_RENDERER(img);
  unsigned char* usedChar;
  int i,bufferLength,itemFound,dataCounter;
  shapeData* updatedData;
  band_type utfvalue;

  bufferLength = (img->height/r->utfresolution) * (img->width/r->utfresolution);

  usedChar =(unsigned char*) msSmallMalloc(r->data->counter*sizeof(unsigned char));

  for(i=0;i<r->data->counter;i++){
    usedChar[i]=0;
  }

  itemFound=0;

  for(i=0;i<bufferLength;i++)
  {
    if(decodeRendered(r->buffer[i]) != 0 && usedChar[decodeRendered(r->buffer[i])-1]==0)
    {
      itemFound++;
      usedChar[decodeRendered(r->buffer[i])-1] = 1;
    }
  }

  updatedData = (shapeData*) msSmallMalloc(itemFound * sizeof(shapeData));
  dataCounter = 0;

  for(i=0; i< r->data->counter; i++){
    if(usedChar[decodeRendered(r->data->table[i].utfvalue)-1]==1){
        updatedData[dataCounter] = r->data->table[i];

        updatedData[dataCounter].serialid=dataCounter+1;

        utfvalue=encodeForRendering(dataCounter+1);

        utfgridUpdateChar(img,updatedData[dataCounter].utfvalue,utfvalue);
        updatedData[dataCounter].utfvalue = utfvalue;

      dataCounter++;
    }
    else {
      if(r->data->table[i].datavalues)
        msFree(r->data->table[i].datavalues);
      if(r->data->table[i].itemvalue)
        msFree(r->data->table[i].itemvalue);
    }
  }

  msFree(usedChar);

  msFree(r->data->table);

  r->data->table = updatedData;
  r->data->counter = dataCounter;
  r->data->size = dataCounter;

  return MS_SUCCESS;
}
/**
 * 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;
    }
  }
}
Beispiel #14
0
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<si;++i) {
    shapeObj initialShape;
    
    if (si > 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);
        newShape->line = NULL;
      }

      shape = &initialShape;
    }
    
    for (j=0;j<shape->numlines;++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;k<lw.index;++k) {
        coeff[lw.index+(k+1)] = coeff[lw.index-k]/2;
        coeff[lw.index-(k+1)] = coeff[lw.index+k]/2;    
      }
      
      
      while ((res = nextLineWindow(&lw)) != MS_DONE) {
        double sum_x=0, sum_y=0, sum = 0;
        pointObj point;
        int k = 0;        

        if (res == MS_FALSE) { /* invalid window */
          msAddPointToLine(&newShape->line[j],
                           lw.points[lw.index]);
          continue;
        }

        /* Apply Coefficient */
        p[lw.index] = *lw.points[lw.index];
        for (k=0; k<lw.index; ++k) {
          p[lw.index-(k+1)] = *lw.points[lw.index-(k+1)];
          p[lw.index-(k+1)].x *= coeff[lw.index-(k+1)];
          p[lw.index-(k+1)].y *= coeff[lw.index-(k+1)];
          p[lw.index+(k+1)] = *lw.points[lw.index+(k+1)];
          p[lw.index+(k+1)].x *= coeff[lw.index+(k+1)];
          p[lw.index+(k+1)].y *= coeff[lw.index+(k+1)];
        }
        
        for (k=0; k<lw.size; ++k) {
          sum += coeff[k];
          sum_x += p[k].x;
          sum_y += p[k].y;          
        }
      
        point.x = sum_x/sum;
        point.y = sum_y/sum;
        msAddPointToLine(&newShape->line[j],
                         &point);
      }

      freeLineWindow(&lw);      
    }
    
    if (i>0) {
      msFreeShape(shape);
      shape = newShape;
    }
    
  }
  
  free(p);
  free(coeff);
  
  return newShape;
}
Beispiel #15
0
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 );
}
Beispiel #16
0
/**********************************************************************
 *                          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<numRequests; i++) {
    if (pasReqInfo[i].nTimeout > 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; i<numRequests; i++) {
    CURL *http_handle;
    FILE *fp;

    if (pasReqInfo[i].pszGetUrl == NULL ) {
      msSetError(MS_HTTPERR, "URL or output file parameter missing.",
                 "msHTTPExecuteRequests()");
      return(MS_FAILURE);
    }

    if (pasReqInfo[i].debug) {
      msDebug("HTTP request: id=%d, %s\n",
              pasReqInfo[i].nLayerId, pasReqInfo[i].pszGetUrl);
    }

    /* Reset some members */
    pasReqInfo[i].nStatus = 0;
    if (pasReqInfo[i].pszContentType)
      free(pasReqInfo[i].pszContentType);
    pasReqInfo[i].pszContentType = NULL;

    /* Check local cache if requested */
    if (bCheckLocalCache && pasReqInfo[i].pszOutputFile != NULL ) {
      fp = fopen(pasReqInfo[i].pszOutputFile, "r");
      if (fp) {
        /* File already there, don't download again. */
        if (pasReqInfo[i].debug)
          msDebug("HTTP request: id=%d, found in cache, skipping.\n",
                  pasReqInfo[i].nLayerId);
        fclose(fp);
        pasReqInfo[i].nStatus = 242;
        pasReqInfo[i].pszContentType = msStrdup("unknown/cached");
        continue;
      }
    }

    /* Alloc curl handle */
    http_handle = curl_easy_init();
    if (http_handle == NULL) {
      msSetError(MS_HTTPERR, "curl_easy_init() failed.",
                 "msHTTPExecuteRequests()");
      return(MS_FAILURE);
    }

    pasReqInfo[i].curl_handle = http_handle;

    /* set URL, note that curl keeps only a ref to our string buffer */
    curl_easy_setopt(http_handle, CURLOPT_URL, pasReqInfo[i].pszGetUrl );

    /* Set User-Agent (auto-generate if not set by caller */
    if (pasReqInfo[i].pszUserAgent == NULL) {
      curl_version_info_data *psCurlVInfo;

      psCurlVInfo = curl_version_info(CURLVERSION_NOW);

      pasReqInfo[i].pszUserAgent = (char*)msSmallMalloc(100*sizeof(char));

      if (pasReqInfo[i].pszUserAgent) {
        sprintf(pasReqInfo[i].pszUserAgent,
                "MapServer/%s libcurl/%d.%d.%d",
                MS_VERSION,
                psCurlVInfo->version_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];
#ifdef USE_CURLOPT_PROXYAUTH
        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 /* CURLOPT_PROXYAUTH */

        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; nPos<strlen(pasReqInfo[i].pszHTTPCookieData); nPos++) {
        if(pasReqInfo[i].pszHTTPCookieData[nPos] == '\n') {
          msSetError(MS_HTTPERR, "Can't use cookie containing a newline character.",
                     "msHTTPExecuteRequests()");
          return(MS_FAILURE);
        }
      }

      /* Set the Curl option to send Cookie */
      curl_easy_setopt(http_handle, CURLOPT_COOKIE,
                       pasReqInfo[i].pszHTTPCookieData);
    }

    /* Add to multi handle */
    curl_multi_add_handle(multi_handle, http_handle);

  }

  if (debug) {
    msDebug("HTTP: Before download loop\n");
  }

  /* DOWNLOAD LOOP ... inspired from multi-double.c example */

  /* we start some action by calling perform right away */
  while(CURLM_CALL_MULTI_PERFORM ==
        curl_multi_perform(multi_handle, &still_running));

  while(still_running) {
    struct timeval timeout;
    int rc; /* select() return code */

    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd;

    FD_ZERO(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

    /* set a suitable timeout to play around with */
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000;

    /* get file descriptors from the transfers */
    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

    switch(rc) {
      case -1:
        /* select error */

        /* ==================================================================== */
        /*      On Windows the select function (just above) returns -1 when     */
        /*      it is called the second time and all the calls after            */
        /*      that. This causes an infinite loop.                             */
        /*      I do not really know why.                                       */
        /*      To sovle the problem the break frop case -1 has been removed.   */
        /* ==================================================================== */
#ifndef _WIN32
        break;
#endif
      case 0:
      default:
        /* timeout or readable/writable sockets */
        curl_multi_perform(multi_handle, &still_running);
        break;
    }
  }

  if (debug)
    msDebug("HTTP: After download loop\n");

  /* Scan message stack from CURL and report fatal errors*/

  while((curl_msg = curl_multi_info_read( multi_handle, &num_msgs)) != NULL) {
    httpRequestObj *psReq = NULL;

    if (curl_msg->msg == CURLMSG_DONE &&
        curl_msg->data.result != CURLE_OK) {
      /* Something went wrong with this transfer... report error */

      for (i=0; i<numRequests; i++) {
        if (pasReqInfo[i].curl_handle == curl_msg->easy_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; i<numRequests; i++) {
    httpRequestObj *psReq;
    CURL *http_handle;
    long lVal=0;

    psReq = &(pasReqInfo[i]);

    if (psReq->nStatus == 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 */

        if (psReq->debug)
          msDebug("HTTP: request failed with curl error "
                  "code %d (%s) for %s",
                  -psReq->nStatus, psReq->pszErrBuf,
                  psReq->pszGetUrl);

        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;
}
Beispiel #17
0
/*
 * 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 i, type, hasmarkersymbol;
  double offset;
  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);
  }

  /* initialize the box used for polygons and for outlines */
  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 + 0.5;
  box.line[0].point[0].y = dstY + 0.5;
  box.line[0].point[1].x = dstX + width - 0.5;
  box.line[0].point[1].y = dstY + 0.5;
  box.line[0].point[2].x = dstX + width - 0.5;
  box.line[0].point[2].y = dstY + height - 0.5;
  box.line[0].point[3].x = dstX + 0.5;
  box.line[0].point[3].y = dstY + height - 0.5;
  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;

  /* 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; i<theclass->numstyles; i++) {
        if(MS_VALID_COLOR(theclass->styles[i]->color)) { /* there is a fill */
          type = MS_LAYER_POLYGON;
          break;
        }
      }
    }
  }

  /*
  ** 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; i<theclass->numstyles; i++) {
          if (theclass->styles[i]->symbol < map->symbolset.numsymbols && theclass->styles[i]->symbol > 0) {
             hasmarkersymbol = 1;
             break;
          }
      }
      if (hasmarkersymbol) {
        for(i=0; i<theclass->numstyles; i++)
          msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor);
      } 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;

        label->offsetx = 0;
        label->offsety = 0;
        label->angle = 0;
        label->position = MS_CC;
        if (label->type == MS_TRUETYPE) label->size = height;
        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;
      }
      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);
        /* TO DO: we may want to handle this differently depending on the relative size of the keyimage */
      } else {
        for(i=0; i<theclass->numstyles; i++)
          msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor);
      }
      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;
      }
      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; i<theclass->numstyles; i++)
        msDrawLineSymbol(&map->symbolset, image_draw, &zigzag, theclass->styles[i], lp->scalefactor);

      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; i<theclass->numstyles; i++)
        msDrawShadeSymbol(&map->symbolset, image_draw, &box, theclass->styles[i], lp->scalefactor);
      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);
    /* 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; i<map->symbolset.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;
}
Beispiel #18
0
/**********************************************************************
 *                          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, "<ogc:Filter>\n"
             "<ogc:BBOX>\n"
             "<ogc:PropertyName>%s</ogc:PropertyName>\n"
             "<gml:Box>\n"
             "<gml:coordinates>%f,%f %f,%f</gml:coordinates>\n"
             "</gml:Box>\n"
             "</ogc:BBOX>\n"
             "</ogc:Filter>", pszGeometryName, bbox->minx, bbox->miny, bbox->maxx, bbox->maxy);
  }

  bufferSize = strlen(pszFilter)+500;
  pszPostReq = (char *)msSmallMalloc(bufferSize);
  if (psParams->nMaxFeatures > 0)
    snprintf(pszPostReq, bufferSize, "<?xml version=\"1.0\" ?>\n"
             "<wfs:GetFeature\n"
             "service=\"WFS\"\n"
             "version=\"1.0.0\"\n"
             "maxFeatures=\"%d\"\n"
             "outputFormat=\"GML2\"\n"
			 "xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:ogc=\"http://www.opengis.net/ogc\" xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:gml=\"http://www.opengis.net/gml\">\n"
             "<wfs:Query typeName=\"%s\">\n"
             "%s"
             "</wfs:Query>\n"
             "</wfs:GetFeature>\n", psParams->nMaxFeatures, psParams->pszTypeName, pszFilter);
  else
    snprintf(pszPostReq, bufferSize, "<?xml version=\"1.0\" ?>\n"
             "<wfs:GetFeature\n"
             "service=\"WFS\"\n"
             "version=\"1.0.0\"\n"
             "outputFormat=\"GML2\"\n"
             "xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:ogc=\"http://www.opengis.net/ogc\" xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:gml=\"http://www.opengis.net/gml\">\n"
             "<wfs:Query typeName=\"%s\">\n"
             "%s"
             "</wfs:Query>\n"
             "</wfs:GetFeature>\n", psParams->pszTypeName, pszFilter);
  if (psParams->pszFilter == NULL)
    free(pszFilter);


  return pszPostReq;
}
Beispiel #19
0
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; i<layer->numitems;++i) {
    clinfo->ogrLayer.items[i] = msStrdup(layer->items[i]);
  }

  return msLayerWhichShapes(&clinfo->ogrLayer, rect, isQuery);
}
Beispiel #20
0
/*
 * Print the renderer datas as a JSON.
 */
int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format)
{
  int row, col, i, imgheight, imgwidth;
  band_type pixelid;
  char* pszEscaped;

  utfgridCleanData(img);

  UTFGridRenderer *renderer = UTFGRID_RENDERER(img);

  if(renderer->layerwatch>1)
    return MS_FAILURE;

  imgheight = img->height/renderer->utfresolution;
  imgwidth = img->width/renderer->utfresolution;

  fprintf(fp,"{\"grid\":[");

  /* Print the buffer, also */
  for(row=0; row<imgheight; row++) {

    wchar_t *string = (wchar_t*) msSmallMalloc ((imgwidth + 1) * sizeof(wchar_t));
    wchar_t *stringptr;
    stringptr = string;
    /* Needs comma between each lines but JSON must not start with a comma. */
    if(row!=0)
      fprintf(fp,",");
    fprintf(fp,"\"");
    for(col=0; col<img->width/renderer->utfresolution; col++) {
      /* Get the datas from buffer. */
      pixelid = renderer->buffer[(row*imgwidth)+col];

      *stringptr = pixelid;
      stringptr++;
    }

    /* Convertion to UTF-8 encoding */
    *stringptr = '\0';
    char * utf8;
    utf8 = msConvertWideStringToUTF8 (string, "UCS-4LE");
    fprintf(fp,"%s", utf8);
    msFree(utf8);
    msFree(string);
    fprintf(fp,"\"");
  }

  fprintf(fp,"],\"keys\":[\"\"");

  /* Prints the key specified */
  for(i=0;i<renderer->data->counter;i++) {
      fprintf(fp,",");

    if(renderer->useutfitem)
    {
      pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue);
      fprintf(fp,"\"%s\"", pszEscaped);
      msFree(pszEscaped);
    }
    /* If no UTFITEM specified use the serial ID as the key */
    else
      fprintf(fp,"\"%i\"", renderer->data->table[i].serialid);
  }

  fprintf(fp,"],\"data\":{");

  /* Print the datas */
  if(renderer->useutfdata) {
    for(i=0;i<renderer->data->counter;i++) {
      if(i!=0)
        fprintf(fp,",");

      if(renderer->useutfitem)
      {
        pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue);
        fprintf(fp,"\"%s\":", pszEscaped);
        msFree(pszEscaped);
      }
      /* If no UTFITEM specified use the serial ID as the key */
      else
        fprintf(fp,"\"%i\":", renderer->data->table[i].serialid);

      fprintf(fp,"%s", renderer->data->table[i].datavalues);
    }
  }
  fprintf(fp,"}}");

  return MS_SUCCESS;
}
Beispiel #21
0
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", 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;
}
xmlNodePtr KmlRenderer::createDescriptionNode(shapeObj *shape)
{
  /*
    <description>
    <![CDATA[
    special characters here
    ]]>
    <description>
  */


  /*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; i<currentLayer->numitems; 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; i<currentLayer->numitems; i++) {
      int j=0,k=0;

      /*TODO optimize to calculate this only once per layer*/
      for (j=0; j<nIncludeItems; j++) {
        if (strcasecmp(currentLayer->items[i], papszLayerIncludeItems[j]) == 0)
          break;
      }
      if (j<nIncludeItems || bIncludeAll) {
        if (papszLayerExcludeItems && nExcludeItems > 0) {
          for (k=0; k<nExcludeItems; k++) {
            if (strcasecmp(currentLayer->items[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;
}
/**
 * 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; row<rb->height; 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;
}
Beispiel #24
0
/**
* 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
}
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; i<numlines; i++) {
    if(MS_SUCCESS != msGetLabelSize(map,label,textlines[i],label->size, &label_rect,NULL)) {
      msFreeCharArray(textlines,numlines);
      msFree(textlinelengths);
      msFree(numspacesforpadding);
      return text;
    }
    textlinelengths[i] = label_rect.maxx-label_rect.minx;
    if(maxlinelength<textlinelengths[i])
      maxlinelength=textlinelengths[i];
  }
  for(i=0; i<numlines; i++) {
    /* number of spaces to add so the current line is
     * as long as the longest line */
    double nfracspaces = (maxlinelength - textlinelengths[i])/spacewidth;

    if(label->align == 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; i<numlines; i++) {
    int j;
    /*padd beginning of line with needed spaces*/
    for(j=0; j<numspacesforpadding[i]; j++) {
      *(newtextptr++)=' ';
    }
    /*copy original line*/
    strcpy(newtextptr,textlines[i]);
    /*place pointer at the char right after the current line*/
    newtextptr+=strlen(textlines[i])+1;
    if(i!=numlines-1) {
      /*put the \n back in (was taken away by msStringSplit)*/
      *(newtextptr-1)='\n';
    }
  }
  /*free the original text*/
  free(text);
  for(i=0; i<numlines; i++) {
    free(textlines[i]);
  }
  free(textlines);
  free(textlinelengths);
  free(numspacesforpadding);

  /*return the aligned text. note that the terminating \0 was added by the last
   * call to strcpy */
  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; i<classPtr->numlabels; 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; i<classPtr->numlabels; 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 && (classPtr->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; i<classPtr->numstyles; 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; i<classPtr->numlabels; 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);
}
Beispiel #27
0
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");
    msSHPDiskTreeClose( disktree );
    return (MS_FALSE);
  }

  writeTreeNode(disktree, tree->root);

  msSHPDiskTreeClose( disktree );

  return(MS_TRUE);
}
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; i<label->numstyles; 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; i<classPtr->numstyles; 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);
}
Beispiel #29
0
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;

  
  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;
  }
  
  /*
  ** Allocate mapObj structure
  */
  map_tmp = (mapObj *)msSmallCalloc(sizeof(mapObj),1);
  if(initMap(map_tmp) == -1) { /* initialize this map */
    msFree(map_tmp);
    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; i<uvlinfo->width; ++i) {
      free(uvlinfo->u[i]);
    }
    free(uvlinfo->u);
  }

  if (uvlinfo->v) {
    for (i=0; i<uvlinfo->height; ++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;
}
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; i<nTokens; i++)
                {   
                    char *pszTmp = NULL;
                    int bufferSize = 0;	

                    if (i == 0)
                    {
                        if(FLTIsNumeric(tokens[0]) == MS_FALSE) 
                          bString = 1;
                    }
                    
                   
                    if (bString)
                    {   
                        bufferSize = 11+strlen(tokens[i])+strlen(pszAttribute)+1;
                        pszTmp = (char *)msSmallMalloc(bufferSize);
                        snprintf(pszTmp, bufferSize, "(\"[%s]\" ==\"%s\")" , pszAttribute, tokens[i]);
                    }
                    else
                    {   
                        bufferSize = 8+strlen(tokens[i])+strlen(pszAttribute)+1;
                        pszTmp = (char *)msSmallMalloc(bufferSize);
                        snprintf(pszTmp, bufferSize, "([%s] == %s)" , pszAttribute, tokens[i]);
                    }

                    if (pszExpression != NULL)
                      pszExpression = msStringConcatenate(pszExpression, " OR ");
                    else
                      pszExpression = msStringConcatenate(pszExpression, "(");
                    pszExpression = msStringConcatenate(pszExpression, pszTmp);
                    msFree(pszTmp);
                }

                msFreeCharArray(tokens, nTokens);
            }
        }   
        /*opening and closing brackets are needed for mapserver expressions*/
        if (pszExpression)
          pszExpression = msStringConcatenate(pszExpression, ")");
    }
#endif

    return pszExpression;
}