예제 #1
0
template<class VertexSource> int renderPolygonHatches(imageObj *img,VertexSource &clipper, colorObj *color)
{
  if(img->format->renderer == MS_RENDER_WITH_AGG) {
    AGG2Renderer *r = AGG_RENDERER(img);
    r->m_rasterizer_aa_gamma.reset();
    r->m_rasterizer_aa_gamma.filling_rule(mapserver::fill_non_zero);
    r->m_rasterizer_aa_gamma.add_path(clipper);
    r->m_renderer_scanline.color(aggColor(color));
    mapserver::render_scanlines(r->m_rasterizer_aa_gamma, r->sl_poly, r->m_renderer_scanline);
  } else {
    shapeObj shape;
    msInitShape(&shape);
    int allocated = 20;
    lineObj line;
    shape.line = &line;
    shape.numlines = 1;
    shape.line[0].point = (pointObj*)msSmallCalloc(allocated,sizeof(pointObj));
    shape.line[0].numpoints = 0;
    double x=0,y=0;
    unsigned int cmd;
    clipper.rewind(0);
    while((cmd = clipper.vertex(&x,&y)) != mapserver::path_cmd_stop) {
      switch(cmd) {
        case mapserver::path_cmd_line_to:
          if(shape.line[0].numpoints == allocated) {
            allocated *= 2;
            shape.line[0].point = (pointObj*)msSmallRealloc(shape.line[0].point, allocated*sizeof(pointObj));
          }
          shape.line[0].point[shape.line[0].numpoints].x = x;
          shape.line[0].point[shape.line[0].numpoints].y = y;
          shape.line[0].numpoints++;
          break;
        case mapserver::path_cmd_move_to:
          shape.line[0].point[0].x = x;
          shape.line[0].point[0].y = y;
          shape.line[0].numpoints = 1;
          break;
        case mapserver::path_cmd_end_poly|mapserver::path_flags_close:
          if(shape.line[0].numpoints > 2) {
            if(UNLIKELY(MS_FAILURE == MS_IMAGE_RENDERER(img)->renderPolygon(img,&shape,color))) {
              free(shape.line[0].point);
              return MS_FAILURE;
            }
          }
          break;
        default:
          assert(0); //WTF?
      }
    }
    free(shape.line[0].point);
  }
  return MS_SUCCESS;
}
예제 #2
0
int agg2RenderTruetypeSymbol(imageObj *img, double x, double y,
                             symbolObj *symbol, symbolStyleObj * style)
{
  AGG2Renderer *r = AGG_RENDERER(img);
  aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img));
  if(aggLoadFont(cache,symbol->full_font_path,style->scale) == MS_FAILURE)
    return MS_FAILURE;

  int unicode;
  font_curve_type m_curves(cache->m_fman.path_adaptor());

  msUTF8ToUniChar(symbol->character, &unicode);
  const mapserver::glyph_cache* glyph = cache->m_fman.glyph(unicode);
  double ox = (glyph->bounds.x1 + glyph->bounds.x2) / 2.;
  double oy = (glyph->bounds.y1 + glyph->bounds.y2) / 2.;

  mapserver::trans_affine mtx = mapserver::trans_affine_translation(-ox, -oy);
  if(style->rotation)
    mtx *= mapserver::trans_affine_rotation(-style->rotation);
  mtx *= mapserver::trans_affine_translation(x, y);

  mapserver::path_storage glyphs;

  cache->m_fman.init_embedded_adaptors(glyph, 0,0);
  mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx);
  glyphs.concat_path(trans_c);
  if (style->outlinecolor) {
    r->m_rasterizer_aa.reset();
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
    mapserver::conv_contour<mapserver::path_storage> cc(glyphs);
    cc.auto_detect_orientation(true);
    cc.width(style->outlinewidth + 1);
    r->m_rasterizer_aa.add_path(cc);
    r->m_renderer_scanline.color(aggColor(style->outlinecolor));
    mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  }

  if (style->color) {
    r->m_rasterizer_aa.reset();
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
    r->m_rasterizer_aa.add_path(glyphs);
    r->m_renderer_scanline.color(aggColor(style->color));
    mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  }
  return MS_SUCCESS;

}
예제 #3
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;
}
예제 #4
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 scale_independant, class_hittest *hittest)
{
  int i, type, hasmarkersymbol, ret=MS_SUCCESS;
  double offset;
  double polygon_contraction = 0.5; /* used to account for the width of a polygon's outline */
  shapeObj box, zigzag;
  lineObj box_line,zigzag_line;
  pointObj box_point[5], zigzag_point[4];
  pointObj marker;
  char szPath[MS_MAXPATHLEN];
  styleObj outline_style;
  imageObj *image_draw = image;
  int originalopacity = lp->opacity;
  rendererVTableObj *renderer;
  outputFormatObj *transFormat = NULL, *altFormat=NULL;
  const char *alternativeFormatString = NULL;

  if(!MS_RENDERER_PLUGIN(image->format)) {
    msSetError(MS_MISCERR,"unsupported image format","msDrawLegendIcon()");
    return MS_FAILURE;
  }

  alternativeFormatString = msLayerGetProcessingKey(lp, "RENDERER");
  if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFormatString!=NULL &&
      (altFormat=  msSelectOutputFormat(map, alternativeFormatString))) {
    msInitializeRendererVTable(altFormat);

    image_draw = msImageCreate(image->width, image->height,
                               altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor);
    renderer = MS_IMAGE_RENDERER(image_draw);
  } else {
    renderer = MS_IMAGE_RENDERER(image_draw);
    if (lp->opacity > 0 && lp->opacity < 100) {
      if (!renderer->supports_transparent_layers) {
        image_draw = msImageCreate(image->width, image->height,
                                   image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL);
        if (!image_draw) {
          msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.",
                     "msDrawLegendIcon()");
          return (MS_FAILURE);
        }
        /* set opacity to full, as the renderer should be rendering a fully opaque image */
        lp->opacity=100;
      }
    }
  }


  if(renderer->supports_clipping && MS_VALID_COLOR(map->legend.outlinecolor)) {
    /* keep GD specific code here for now as it supports clipping */
    rectObj clip;
    clip.maxx = dstX + width - 1;
    clip.maxy = dstY + height -1;
    clip.minx = dstX;
    clip.miny = dstY;
    renderer->setClip(image_draw,clip);
  }
  
  /* if the class has a keyimage, treat it as a point layer
   * (the keyimage will be treated there) */
  if(theclass->keyimage != NULL) {
    type = MS_LAYER_POINT;
  } else {
    /* some polygon layers may be better drawn using zigzag if there is no fill */
    type = lp->type;
    if(type == MS_LAYER_POLYGON) {
      type = MS_LAYER_LINE;
      for(i=0; i<theclass->numstyles; i++) {
        if(MS_VALID_COLOR(theclass->styles[i]->color)) { /* there is a fill */
          type = MS_LAYER_POLYGON;
        }
        if(MS_VALID_COLOR(theclass->styles[i]->outlinecolor)) { /* there is an outline */
          polygon_contraction = MS_MAX(polygon_contraction, theclass->styles[i]->width / 2.0);
        }
      }
    }
  }

  /* initialize the box used for polygons and for outlines */
  box.line = &box_line;
  box.numlines = 1;
  box.line[0].point = box_point;
  box.line[0].numpoints = 5;

  box.line[0].point[0].x = dstX + polygon_contraction;
  box.line[0].point[0].y = dstY + polygon_contraction;
  box.line[0].point[1].x = dstX + width - polygon_contraction;
  box.line[0].point[1].y = dstY + polygon_contraction;
  box.line[0].point[2].x = dstX + width - polygon_contraction;
  box.line[0].point[2].y = dstY + height - polygon_contraction;
  box.line[0].point[3].x = dstX + polygon_contraction;
  box.line[0].point[3].y = dstY + height - polygon_contraction;
  box.line[0].point[4].x = box.line[0].point[0].x;
  box.line[0].point[4].y = box.line[0].point[0].y;



  /*
  ** now draw the appropriate color/symbol/size combination
  */
  switch(type) {
    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;
        for(symbolNum=0; symbolNum<theclass->numstyles; symbolNum++)
        symbolNum = msAddImageSymbol(&(map->symbolset), msBuildPath(szPath, map->mappath, theclass->keyimage));
        if(symbolNum == -1) {
          msSetError(MS_IMGERR, "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;
        ret = msDrawMarkerSymbol(map ,image_draw,&marker,&imgStyle,lp->scalefactor * image_draw->resolutionfactor);
        if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
        /* 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++) {
          if(!scale_independant && map->scaledenom > 0) {
            styleObj *lp = theclass->styles[i];
            if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue;
            if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue;
          }
          if(hittest && hittest->stylehits[i].status == 0) continue;
          ret = msDrawMarkerSymbol(map, image_draw, &marker, theclass->styles[i], lp->scalefactor * image->resolutionfactor);
          if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
        }
      }
      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 = &zigzag_line;
      zigzag.numlines = 1;
      zigzag.line[0].point = zigzag_point;
      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++) {
        if(!scale_independant && map->scaledenom > 0) {
          styleObj *lp = theclass->styles[i];
          if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue;
          if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue;
        }
        if(hittest && hittest->stylehits[i].status == 0) continue;
        if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE ||
            theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT ||
            theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
          ret = msDrawLineSymbol(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
          if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
        }
        else {
          ret = msDrawTransformedShape(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
          if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
        }
      }

      break;
    case MS_LAYER_CIRCLE:
    case MS_LAYER_RASTER:
    case MS_LAYER_CHART:
    case MS_LAYER_POLYGON:
      for(i=0; i<theclass->numstyles; i++) {
        if(!scale_independant && map->scaledenom > 0) {
          styleObj *lp = theclass->styles[i];
          if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue;
          if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue;
        }
        if(hittest && hittest->stylehits[i].status == 0) continue;
        if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE ||
            theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT ||
            theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
          ret = msDrawShadeSymbol(map, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
          if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
        }
        else {
          ret = msDrawTransformedShape(map, image_draw, &box,
                                 theclass->styles[i], lp->scalefactor);
          if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
        }
      }
      break;
    default:
      return MS_FAILURE;
      break;
  } /* end symbol drawing */

  /* handle label styles */
  for(i=0; i<theclass->numlabels; i++) {
    labelObj *l = theclass->labels[i];
    if(!scale_independant && map->scaledenom > 0) {
      if(msScaleInBounds(map->scaledenom, l->minscaledenom, l->maxscaledenom)) {
        int j;
        for(j=0; j<l->numstyles; j++) {
          styleObj *s = l->styles[j];
          marker.x = dstX + MS_NINT(width / 2.0);
          marker.y = dstY + MS_NINT(height / 2.0);
          if(s->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) {
            ret = msDrawMarkerSymbol(map, image_draw, &marker, s, lp->scalefactor);
            if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
          }
        }
      }
    }
  }

  /* handle "pure" text layers, i.e. layers with no symbology */
  hasmarkersymbol = 0;
  if(theclass->numstyles == 0) {
    for(i=0; i<theclass->numlabels; i++) {
      labelObj *l = theclass->labels[i];
      if(!scale_independant && map->scaledenom > 0) {
        if(msScaleInBounds(map->scaledenom, l->minscaledenom, l->maxscaledenom)) {
          int j;
          for(j=0; j<l->numstyles; j++) {
            styleObj *s = l->styles[j];
            if(s->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) {
              hasmarkersymbol = 1;
            }
          }
        }
      }
    }
  } else {
    hasmarkersymbol = 1;
  }

  if(!hasmarkersymbol && theclass->numlabels>0) {
    textSymbolObj ts;
    pointObj textstartpt;
    marker.x = dstX + MS_NINT(width / 2.0);
    marker.y = dstY + MS_NINT(height / 2.0);
    initTextSymbol(&ts);
    msPopulateTextSymbolForLabelAndString(&ts,theclass->labels[0],msStrdup("Az"),lp->scalefactor*image_draw->resolutionfactor,image_draw->resolutionfactor, duplicate_always);
    ts.label->size = height - 1;
    ret = msComputeTextPath(map,&ts);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
    textstartpt = get_metrics(&marker,MS_CC,ts.textpath,0,0,0,0,NULL);
    ret = msDrawTextSymbol(map,image_draw, textstartpt, &ts);
    freeTextSymbol(&ts);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;

  }


  /* handle an outline if necessary */
  if(MS_VALID_COLOR(map->legend.outlinecolor)) {
    initStyle(&outline_style);
    outline_style.color = map->legend.outlinecolor;
    ret = msDrawLineSymbol(map, image_draw, &box, &outline_style, image_draw->resolutionfactor);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
    /* 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));

    ret = altrenderer->getRasterBufferHandle(image_draw,&rb);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
    ret = renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
    /*
     * 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;
        }
      }
    }

  } else if(image != image_draw) {
    rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw);
    rasterBufferObj rb;
    memset(&rb,0,sizeof(rasterBufferObj));

    lp->opacity = originalopacity;

    ret = renderer->getRasterBufferHandle(image_draw,&rb);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
    ret = renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height);
    if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;

    /* deref and possibly free temporary transparent output format.  */
    msApplyOutputFormat( &transFormat, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE );

  }

legend_icon_cleanup:
  if(image != image_draw) {
    msFreeImage(image_draw);
  }
  return ret;
}
예제 #5
0
int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
{

#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
  struct svg_symbol_cache *svg_cache;
  symbolStyleObj pixstyle;
  symbolObj pixsymbol;
  int status;

  if(MS_SUCCESS != msPreloadSVGSymbol(symbol))
    return MS_FAILURE;
  svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache;

  //already rendered at the right size and scale? return
  if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) {
    cairo_t *cr;
    cairo_surface_t *surface;
    unsigned char *pb;
    int width, height, surface_w, surface_h;
    /* need to recompute the pixmap */
    if(svg_cache->pixmap_buffer) {
      msFreeRasterBuffer(svg_cache->pixmap_buffer);
    } else {
      svg_cache->pixmap_buffer = msSmallCalloc(1,sizeof(rasterBufferObj));
    }

    //increase pixmap size to accomodate scaling/rotation
    if (style->scale != 1.0) {
      width = surface_w = (symbol->sizex * style->scale + 0.5);
      height = surface_h = (symbol->sizey * style->scale + 0.5);
    } else {
      width = surface_w = symbol->sizex;
      height = surface_h = symbol->sizey;
    }
    if (style->rotation != 0) {
      surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415);
    }

    surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h);
    cr = cairo_create(surface);

    if (style->rotation != 0) {
      cairo_translate(cr, surface_w / 2, surface_h / 2);
      cairo_rotate(cr, -style->rotation);
      cairo_translate(cr, -width / 2, -height / 2);
    }
    if (style->scale != 1.0) {
      cairo_scale(cr, style->scale, style->scale);
    }
#ifdef USE_SVG_CAIRO
    if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) {
      return MS_FAILURE;
    }
#else
  rsvg_handle_render_cairo(svg_cache->svgc, cr);
#endif
    pb = cairo_image_surface_get_data(surface);

    //set up raster
    initializeRasterBufferCairo(svg_cache->pixmap_buffer, surface_w, surface_h, 0);
    memcpy(svg_cache->pixmap_buffer->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char));
    svg_cache->scale = style->scale;
    svg_cache->rotation = style->rotation;
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
  }
  assert(svg_cache->pixmap_buffer->height && svg_cache->pixmap_buffer->width);

  pixstyle = *style;
  pixstyle.rotation = 0.0;
  pixstyle.scale = 1.0;

  pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer;
  pixsymbol.type = MS_SYMBOL_PIXMAP;

  status = MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle);
  MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol);
  return status;
#else
  msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo",
             "renderSVGSymbolCairo()");
  return MS_FAILURE;
#endif
}
예제 #6
0
void msWriteErrorImage(mapObj *map, char *filename, int blank) {
    imageObj *img;
    rendererVTableObj *renderer;
    int font_index = 0;
    int width=400, height=300;
    int nMargin =5;
    int nTextLength = 0;
    int nUsableWidth = 0;
    int nMaxCharsPerLine = 0;
    int nLines = 0;
    int i = 0;
    int nStart = 0;
    int nEnd = 0;
    int nLength = 0;
    char **papszLines = NULL;
    int nXPos = 0;
    int nYPos = 0;
    int nWidthTxt = 0;
    outputFormatObj *format = NULL;
    char *errormsg = msGetErrorString("; ");
    fontMetrics *font = NULL;
    char *imagepath = NULL, *imageurl = NULL;
    labelStyleObj ls;
    colorObj labelcolor, labeloutlinecolor, imagecolor, *imagecolorptr=NULL;
    ls.color = &labelcolor;
    ls.outlinecolor = &labeloutlinecolor;

    if (map) {
        if( map->width > 0 && map->height > 0 )
        {
            width = map->width;
            height = map->height;
        }
        format = map->outputformat;
        imagepath = map->web.imagepath;
        imageurl = map->web.imageurl;
    }

    /* Default to GIF if no suitable GD output format set */
    if (format == NULL || !MS_RENDERER_PLUGIN(format) || !format->vtable->supports_bitmap_fonts)
        format = msCreateDefaultOutputFormat( NULL, "GD/PC256", "gif" );

    if(!format->transparent) {
        if(map && MS_VALID_COLOR(map->imagecolor)) {
            imagecolorptr = &map->imagecolor;
        } else {
            MS_INIT_COLOR(imagecolor,255,255,255,255);
            imagecolorptr = &imagecolor;
        }
    }

    img = msImageCreate(width,height,format,imagepath,imageurl,MS_DEFAULT_RESOLUTION,MS_DEFAULT_RESOLUTION,imagecolorptr);
    renderer = MS_IMAGE_RENDERER(img);

    for(i=0; i<5; i++) {
        /* use the first font we find */
        if((font = renderer->bitmapFontMetrics[font_index]) != NULL) {
            ls.size = i;
            MS_INIT_COLOR(*ls.color,0,0,0,255);
            MS_INIT_COLOR(*ls.outlinecolor,255,255,255,255);
            break;
        }
    }
    /* if no font found we can't do much. this shouldn't happen */
    if(font) {

        nTextLength = strlen(errormsg);
        nWidthTxt  =  nTextLength * font->charWidth;
        nUsableWidth = width - (nMargin*2);

        /* Check to see if it all fits on one line. If not, split the text on several lines. */
        if(!blank) {
            if (nWidthTxt > nUsableWidth) {
                nMaxCharsPerLine =  nUsableWidth/font->charWidth;
                nLines = (int) ceil ((double)nTextLength / (double)nMaxCharsPerLine);
                if (nLines > 0) {
                    papszLines = (char **)malloc(nLines*sizeof(char *));
                    for (i=0; i<nLines; i++) {
                        papszLines[i] = (char *)malloc((nMaxCharsPerLine+1)*sizeof(char));
                        papszLines[i][0] = '\0';
                    }
                }
                for (i=0; i<nLines; i++) {
                    nStart = i*nMaxCharsPerLine;
                    nEnd = nStart + nMaxCharsPerLine;
                    if (nStart < nTextLength) {
                        if (nEnd > nTextLength)
                            nEnd = nTextLength;
                        nLength = nEnd-nStart;

                        strncpy(papszLines[i], errormsg+nStart, nLength);
                        papszLines[i][nLength] = '\0';
                    }
                }
            } else {
                nLines = 1;
                papszLines = (char **)malloc(nLines*sizeof(char *));
                papszLines[0] = msStrdup(errormsg);
            }
            for (i=0; i<nLines; i++) {
                nYPos = (font->charHeight) * ((i*2) +1);
                nXPos = font->charWidth;;
                renderer->renderBitmapGlyphs(img, nXPos, nYPos, &ls, papszLines[i]);
            }
            if (papszLines) {
                for (i=0; i<nLines; i++) {
                    free(papszLines[i]);
                }
                free(papszLines);
            }
        }
    }

    /* actually write the image */
    if(!filename) {
        msIO_setHeader("Content-type","%s", MS_IMAGE_MIME_TYPE(format));
        msIO_sendHeaders();
    }
    msSaveImage(NULL,img,filename);
    msFreeImage(img);

    if (format->refcount == 0)
        msFreeOutputFormat(format);
    msFree(errormsg);
}
예제 #7
0
int msImagePolylineMarkers(imageObj *image, shapeObj *p, symbolObj *symbol,
                           symbolStyleObj *style, double spacing,
                           double initialgap, int auto_angle)
{
  rendererVTableObj *renderer = MS_IMAGE_RENDERER(image);
  int i,j;
  pointObj point;
  double original_rotation = style->rotation;
  double symbol_width,symbol_height;
  glyph_element *glyphc = NULL;
  face_element *face;
  int ret = MS_SUCCESS;
  if(symbol->type != MS_SYMBOL_TRUETYPE) {
    symbol_width = MS_MAX(1,symbol->sizex*style->scale);
    symbol_height = MS_MAX(1,symbol->sizey*style->scale);
  } else {
    unsigned int unicode;
    msUTF8ToUniChar(symbol->character, &unicode);
    face = msGetFontFace(symbol->font, &image->map->fontset);
    if(UNLIKELY(!face)) return MS_FAILURE;
    unicode = msGetGlyphIndex(face,unicode);
    glyphc = msGetGlyphByIndex(face, style->scale, unicode);
    if(UNLIKELY(!glyphc)) return MS_FAILURE;
    symbol_width = glyphc->metrics.maxx - glyphc->metrics.minx;
    symbol_height = glyphc->metrics.maxy - glyphc->metrics.miny;
  }
  for(i=0; i<p->numlines; i++) {
    int line_in = 0;
    double line_length=0;
    double current_length;
    if(initialgap < 0) {
      current_length = spacing/2.0; /* initial padding for each line */
    } else {
      current_length = initialgap; /* initial padding for each line */
    }
    for(j=1; j<p->line[i].numpoints; j++) {
      double rx,ry,theta,length;
      length = sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2)));
      line_length += length;
      if(length==0)continue;
      rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length;
      ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length;

      if (auto_angle) {
        theta = asin(ry);
        if(rx < 0) {
          theta += MS_PI;
        } else theta = -theta;
        style->rotation = original_rotation + theta;
      }
      while (current_length <= length) {

        point.x = p->line[i].point[j - 1].x + current_length * rx;
        point.y = p->line[i].point[j - 1].y + current_length * ry;
        if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) {
          double ox, oy;
          ox = (0.5 - symbol->anchorpoint_x) * symbol_width;
          oy = (0.5 - symbol->anchorpoint_y) * symbol_height;
          if(style->rotation != 0) {
            double sina,cosa;
            double rox,roy;
            sina = sin(-style->rotation);
            cosa = cos(-style->rotation);
            rox = ox * cosa - oy * sina;
            roy = ox * sina + oy * cosa;
            point.x += rox;
            point.y += roy;
          } else {
            point.x += ox;
            point.y += oy;
          }
        }

        /* if the point is not in the map extent, skip it. (POLYLINE_NO_CLIP) */
        if ( (point.x < -(symbol_width) || point.x > (image->width+symbol_width)) ||
             (point.y < -(symbol_height) || point.y > (image->height+symbol_height)) ) {
          current_length += spacing;
          line_in=1;          
          continue;
        }
          
        switch (symbol->type) {
          case MS_SYMBOL_PIXMAP:
            ret = renderer->renderPixmapSymbol(image, point.x, point.y, symbol, style);
            break;
          case MS_SYMBOL_ELLIPSE:
            ret = renderer->renderEllipseSymbol(image, point.x, point.y, symbol, style);
            break;
          case MS_SYMBOL_VECTOR:
            ret = renderer->renderVectorSymbol(image, point.x, point.y, symbol, style);
            break;
          case MS_SYMBOL_TRUETYPE:
            ret = drawGlyphMarker(image, face, glyphc, point.x, point.y, style->scale, style->rotation,
                style->color, style->outlinecolor, style->outlinewidth);
            break;
          case (MS_SYMBOL_SVG):
#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
              if (renderer->supports_svg) {
                ret = renderer->renderSVGSymbol(image, point.x, point.y, symbol, style);
              } else {
                ret = msRenderRasterizedSVGSymbol(image,point.x,point.y,symbol, style);
              }
#else
              msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msImagePolylineMarkers()()");
              ret = MS_FAILURE;
#endif
              break;
        }
        if( ret != MS_SUCCESS)
          return ret;
        current_length += spacing;
        line_in=1;
      }

      current_length -= length;
    }

    /*
     * if we couldn't place a symbol on the line and no initialgap was
     * specified,  add one now we don't add the symbol if the line is shorter
     * than the length of the symbol itself
     */
    if(initialgap < 0 && !line_in && line_length>symbol_width) {

      /* total lengths of beginnning and end of current segment */
      double before_length=0,after_length=0;

      /*optimize*/
      line_length /= 2.0;

      for(j=1; j<p->line[i].numpoints; j++) {
        double length;
        length = sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2)));
        after_length += length;
        if(after_length>line_length) {
          double rx,ry,theta;
          /* offset where the symbol should be drawn on the current
           * segment */
          double offset = line_length - before_length;

          rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length;
          ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length;
          if (auto_angle) {
            theta = asin(ry);
            if(rx < 0) {
              theta += MS_PI;
            } else theta = -theta;
            style->rotation = original_rotation + theta;
          }

          point.x = p->line[i].point[j - 1].x + offset * rx;
          point.y = p->line[i].point[j - 1].y + offset * ry;
          switch (symbol->type) {
            case MS_SYMBOL_PIXMAP:
              ret = renderer->renderPixmapSymbol(image, point.x, point.y, symbol, style);
              break;
            case MS_SYMBOL_ELLIPSE:
              ret = renderer->renderEllipseSymbol(image, point.x, point.y, symbol, style);
              break;
            case MS_SYMBOL_VECTOR:
              ret = renderer->renderVectorSymbol(image, point.x, point.y, symbol, style);
              break;
            case MS_SYMBOL_TRUETYPE:
              ret = drawGlyphMarker(image, face, glyphc, point.x, point.y, style->scale, style->rotation,
                  style->color, style->outlinecolor, style->outlinewidth);
              break;
            case (MS_SYMBOL_SVG):
#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
              if (renderer->supports_svg) {
                ret = renderer->renderSVGSymbol(image, point.x, point.y, symbol, style);
              } else {
                ret = msRenderRasterizedSVGSymbol(image,point.x,point.y,symbol, style);
              }
#else
              msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msImagePolylineMarkers()()");
              ret = MS_FAILURE;
#endif
              break;
          }
          break; /* we have rendered the single marker for this line */
        }
        before_length += length;
      }
    }

  }
  return ret;
}
예제 #8
0
imageObj *getTile(imageObj *img, symbolObj *symbol,  symbolStyleObj *s, int width, int height,
                  int seamlessmode)
{
  tileCacheObj *tile;
  int status = MS_SUCCESS;
  rendererVTableObj *renderer = img->format->vtable;
  if(width==-1 || height == -1) {
    width=height=MS_MAX(symbol->sizex,symbol->sizey);
  }
  tile = searchTileCache(img,symbol,s,width,height);

  if(tile==NULL) {
    imageObj *tileimg;
    double p_x,p_y;
    tileimg = msImageCreate(width,height,img->format,NULL,NULL,img->resolution, img->resolution, NULL);
    if(UNLIKELY(!tileimg)) {
      return NULL;
    }
    if(!seamlessmode) {
      p_x = width/2.0;
      p_y = height/2.0;
      switch(symbol->type) {
        case (MS_SYMBOL_TRUETYPE):
        {
          unsigned int unicode;
          glyph_element *glyphc;
          face_element *face = msGetFontFace(symbol->font, &img->map->fontset);
          if(UNLIKELY(!face)) { status = MS_FAILURE; break; }
          msUTF8ToUniChar(symbol->character, &unicode);
          unicode = msGetGlyphIndex(face,unicode);
          glyphc = msGetGlyphByIndex(face, s->scale, unicode);
          if(UNLIKELY(!face)) { status = MS_FAILURE; break; }
          status = drawGlyphMarker(tileimg, face, glyphc, p_x, p_y, s->scale, s->rotation,
                s->color, s->outlinecolor, s->outlinewidth);
        }
          break;
        case (MS_SYMBOL_PIXMAP):
          status = msPreloadImageSymbol(renderer,symbol);
          if(UNLIKELY(status == MS_FAILURE)) { break; }
          status = renderer->renderPixmapSymbol(tileimg, p_x, p_y, symbol, s);
          break;
        case (MS_SYMBOL_ELLIPSE):
          status = renderer->renderEllipseSymbol(tileimg, p_x, p_y,symbol, s);
          break;
        case (MS_SYMBOL_VECTOR):
          status = renderer->renderVectorSymbol(tileimg, p_x, p_y, symbol, s);
          break;

        case (MS_SYMBOL_SVG):
#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
          status = msPreloadSVGSymbol(symbol);
          if(LIKELY(status == MS_SUCCESS)) {
            if (renderer->supports_svg) {
              status = renderer->renderSVGSymbol(tileimg, p_x, p_y, symbol, s);
            } else {
              status = msRenderRasterizedSVGSymbol(tileimg,p_x,p_y,symbol, s);
            }
          }
#else
          msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "getTile()");
          status = MS_FAILURE;
#endif
          break;
        default:
          msSetError(MS_SYMERR, "Unknown symbol type %d", "getTile()", symbol->type);
          status = MS_FAILURE;
          break;
      }
      if(UNLIKELY(status == MS_FAILURE)) {
        msFreeImage(tileimg);
        return NULL;
      }
    } else {
      /*
       * in seamless mode, we render the the symbol 9 times on a 3x3 grid to account for
       * antialiasing blending from one tile to the next. We finally keep the center tile
       */
      imageObj *tile3img = msImageCreate(width*3,height*3,img->format,NULL,NULL,
                                         img->resolution, img->resolution, NULL);
      int i,j;
      rasterBufferObj tmpraster;
      for(i=1; i<=3; i++) {
        p_x = (i+0.5)*width;
        for(j=1; j<=3; j++) {
          p_y = (j+0.5) * height;
          switch(symbol->type) {
            case (MS_SYMBOL_TRUETYPE):
            {
              unsigned int unicode;
              glyph_element *glyphc;
              face_element *face = msGetFontFace(symbol->font, &img->map->fontset);
              if(UNLIKELY(!face)) { status = MS_FAILURE; break; }
              msUTF8ToUniChar(symbol->character, &unicode);
              unicode = msGetGlyphIndex(face,unicode);
              glyphc = msGetGlyphByIndex(face, s->scale, unicode);
              if(UNLIKELY(!glyphc)) { status = MS_FAILURE; break; }
              status = drawGlyphMarker(tileimg, face, glyphc, p_x, p_y, s->scale, s->rotation,
                    s->color, s->outlinecolor, s->outlinewidth);
            }
              break;
            case (MS_SYMBOL_PIXMAP):
              status = msPreloadImageSymbol(renderer,symbol);
              if(UNLIKELY(status == MS_FAILURE)) { break; }
              status = renderer->renderPixmapSymbol(tile3img, p_x, p_y, symbol, s);
              break;
            case (MS_SYMBOL_ELLIPSE):
              status = renderer->renderEllipseSymbol(tile3img, p_x, p_y,symbol, s);
              break;
            case (MS_SYMBOL_VECTOR):
              status = renderer->renderVectorSymbol(tile3img, p_x, p_y, symbol, s);
              break;
            default:
              msSetError(MS_SYMERR, "BUG: Seamless mode is only for vector symbols", "getTile()");
              return NULL;
          }
          if(UNLIKELY(status == MS_FAILURE)) {
            msFreeImage(tile3img);
            return NULL;
          }
        }
      }
      if(UNLIKELY(status == MS_FAILURE)) {
        msFreeImage(tile3img);
        return NULL;
      }

      status = MS_IMAGE_RENDERER(tile3img)->getRasterBufferHandle(tile3img,&tmpraster);
      if(UNLIKELY(status == MS_FAILURE)) {
        msFreeImage(tile3img);
        return NULL;
      }
      status = renderer->mergeRasterBuffer(tileimg,
                                  &tmpraster,
                                  1.0,width,height,0,0,width,height
                                 );
      msFreeImage(tile3img);
    }
    if(UNLIKELY(status == MS_FAILURE)) {
      msFreeImage(tileimg);
      return NULL;
    }
    tile = addTileCache(img,tileimg,symbol,s,width,height);
  }
  return tile->image;
}
예제 #9
0
int agg2RenderGlyphsLine(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text)
{
  AGG2Renderer *r = AGG_RENDERER(img);
  aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img));
  if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE)
    return MS_FAILURE;
  r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);

  const mapserver::glyph_cache* glyph;
  int unicode;
  int curfontidx = 0;
  font_curve_type m_curves(cache->m_fman.path_adaptor());

  mapserver::path_storage glyphs;

  for (int i = 0; i < labelpath->path.numpoints; i++) {
    assert(text);
    mapserver::trans_affine mtx;
    mtx *= mapserver::trans_affine_translation(-labelpath->path.point[i].x,-labelpath->path.point[i].y);
    mtx *= mapserver::trans_affine_rotation(-labelpath->angles[i]);
    mtx *= mapserver::trans_affine_translation(labelpath->path.point[i].x,labelpath->path.point[i].y);
    text += msUTF8ToUniChar(text, &unicode);

    if(curfontidx != 0) {
      if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE)
        return MS_FAILURE;
      curfontidx = 0;
    }

    glyph = cache->m_fman.glyph(unicode);

    if(!glyph || glyph->glyph_index == 0) {
      int i;
      for(i=1; i<style->numfonts; i++) {
        if(aggLoadFont(cache,style->fonts[i],style->size) == MS_FAILURE)
          return MS_FAILURE;
        curfontidx = i;
        glyph = cache->m_fman.glyph(unicode);
        if(glyph && glyph->glyph_index != 0) {
          break;
        }
      }
    }
    if (glyph) {
      cache->m_fman.init_embedded_adaptors(glyph, labelpath->path.point[i].x,labelpath->path.point[i].y);
      mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx);
      glyphs.concat_path(trans_c);
    }
  }

  if (style->outlinewidth) {
    r->m_rasterizer_aa.reset();
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
    mapserver::conv_contour<mapserver::path_storage> cc(glyphs);
    cc.width(style->outlinewidth + 1);
    r->m_rasterizer_aa.add_path(cc);
    r->m_renderer_scanline.color(aggColor(style->outlinecolor));
    mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  }
  if (style->color) {
    r->m_rasterizer_aa.reset();
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
    r->m_rasterizer_aa.add_path(glyphs);
    r->m_renderer_scanline.color(aggColor(style->color));
    mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  }

  return MS_SUCCESS;
}
예제 #10
0
int agg2RenderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text)
{
  AGG2Renderer *r = AGG_RENDERER(img);
  aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img));
  if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE)
    return MS_FAILURE;
  r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);

  int curfontidx = 0;
  const mapserver::glyph_cache* glyph;
  int unicode;
  font_curve_type m_curves(cache->m_fman.path_adaptor());
  mapserver::trans_affine mtx;
  mtx *= mapserver::trans_affine_translation(-x, -y);
  /*agg angles are antitrigonometric*/
  mtx *= mapserver::trans_affine_rotation(-style->rotation);
  mtx *= mapserver::trans_affine_translation(x, y);

  double fx = x, fy = y;
  const char *utfptr = text;
  mapserver::path_storage glyphs;

  //first render all the glyphs to a path
  while (*utfptr) {
    if (*utfptr == '\r') {
      fx = x;
      utfptr++;
      continue;
    }
    if (*utfptr == '\n') {
      fx = x;
      fy += ceil(style->size * AGG_LINESPACE);
      utfptr++;
      continue;
    }
    utfptr += msUTF8ToUniChar(utfptr, &unicode);
    if(curfontidx != 0) {
      if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE)
        return MS_FAILURE;
      curfontidx = 0;
    }

    glyph = cache->m_fman.glyph(unicode);

    if(!glyph || glyph->glyph_index == 0) {
      int i;
      for(i=1; i<style->numfonts; i++) {
        if(aggLoadFont(cache,style->fonts[i],style->size) == MS_FAILURE)
          return MS_FAILURE;
        curfontidx = i;
        glyph = cache->m_fman.glyph(unicode);
        if(glyph && glyph->glyph_index != 0) {
          break;
        }
      }
    }


    if (glyph) {
      //cache->m_fman.add_kerning(&fx, &fy);
      cache->m_fman.init_embedded_adaptors(glyph, fx, fy);
      mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx);
      glyphs.concat_path(trans_c);
      fx += glyph->advance_x;
      fy += glyph->advance_y;
    }
  }

  if (style->outlinewidth) {
    r->m_rasterizer_aa.reset();
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
    mapserver::conv_contour<mapserver::path_storage> cc(glyphs);
    cc.width(style->outlinewidth + 1);
    r->m_rasterizer_aa.add_path(cc);
    r->m_renderer_scanline.color(aggColor(style->outlinecolor));
    mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  }
  if (style->color) {
    r->m_rasterizer_aa.reset();
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
    r->m_rasterizer_aa.add_path(glyphs);
    r->m_renderer_scanline.color(aggColor(style->color));
    mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  }

  return MS_SUCCESS;

}
예제 #11
0
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);
}
예제 #12
0
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);
}
예제 #13
0
/* {{{ proto void pasteImage(imageObj Src, int transparentColor [[,int dstx, int dsty], int angle])
   Pastes another imageObj on top of this imageObj. transparentColor is
   the color (0xrrggbb) from srcImg that should be considered transparent.
   Pass transparentColor=-1 if you don't want any transparent color.
   If optional dstx,dsty are provided then they define the position where the
   image should be copied (dstx,dsty = top-left corner position).
   The optional angle is a value between 0 and 360 degrees to rotate the
   source image counterclockwise.  Note that if a rotation is requested then
   the dstx and dsty coordinates specify the CENTER of the destination area.
   NOTE : this function only works for 8 bits GD images.
*/
PHP_METHOD(imageObj, pasteImage)
{
    long transparent=-1, dstx=0, dsty=0, angle=0;
    int angleSet=MS_FALSE;
    zval *zimage;
    zval *zobj = getThis();
    php_image_object *php_image, *php_imageSrc;
    /*int oldTransparentColor, newTransparentColor=-1, r, g, b;*/
    rendererVTableObj *renderer = NULL;
    rasterBufferObj rb;

    PHP_MAPSCRIPT_ERROR_HANDLING(TRUE);
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|lll",
                              &zimage, mapscript_ce_image, &transparent,
                              &dstx, &dsty, &angle) == FAILURE) {
        PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
        return;
    }
    PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);

    if  (ZEND_NUM_ARGS() == 3) {
        mapscript_report_php_error(E_WARNING, "dstX parameter given but not dstY" TSRMLS_CC);
    }
    else
        angleSet = MS_TRUE;

    php_image = (php_image_object *) zend_object_store_get_object(zobj TSRMLS_CC);
    php_imageSrc = (php_image_object *) zend_object_store_get_object(zimage TSRMLS_CC);

    if (!MS_RENDERER_PLUGIN(php_imageSrc->image->format) ||
 	!MS_RENDERER_PLUGIN(php_image->image->format))
        {
            mapscript_throw_exception("PasteImage function should only be used with renderer plugin drivers." TSRMLS_CC);
            return;
        }

#ifdef undef //USE_AGG
    if( MS_RENDERER_AGG(php_imageSrc->image->format))
      msAlphaAGG2GD(php_imageSrc->image);
    if( MS_RENDERER_AGG(php_image->image->format))
      msAlphaAGG2GD(php_image->image);
#endif


    renderer = MS_IMAGE_RENDERER(php_image->image);
    memset(&rb,0,sizeof(rasterBufferObj));

    renderer->getRasterBufferHandle(php_imageSrc->image, &rb);
    renderer->mergeRasterBuffer(php_image->image, &rb, 1.0, 0, 0, dstx, dsty, rb.width, rb.height);

    /* Look for r,g,b in color table and make it transparent.
     * will return -1 if there is no exact match which will result in
     * no transparent color in the call to gdImageColorTransparent().
     */
/*    if (transparent != -1)
    {
        r = (transparent / 0x010000) & 0xff;
        g = (transparent / 0x0100) & 0xff;
        b = transparent & 0xff;
        newTransparentColor = gdImageColorExact(php_imageSrc->image->img.gd, r, g, b);
    }

    oldTransparentColor = gdImageGetTransparent(php_imageSrc->image->img.gd);
    gdImageColorTransparent(php_imageSrc->image->img.gd, newTransparentColor);

    if (!angleSet)
        gdImageCopy(php_image->image->img.gd, php_imageSrc->image->img.gd, dstx, dsty,
                    0, 0, php_imageSrc->image->img.gd->sx, php_imageSrc->image->img.gd->sy);
    else
        gdImageCopyRotated(php_image->image->img.gd, php_imageSrc->image->img.gd, dstx, dsty,
                           0, 0, php_imageSrc->image->img.gd->sx, php_imageSrc->image->img.gd->sy,
                           angle);

                           gdImageColorTransparent(php_imageSrc->image->img.gd, oldTransparentColor);*/

    RETURN_LONG(MS_SUCCESS);

}