Пример #1
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;
}
Пример #2
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;
}