Exemplo n.º 1
0
/* TODO : the will be msDrawScalebarGD */
imageObj *msDrawScalebar(mapObj *map)
{
    int status;
    char label[32];
    double i, msx;
    int j;
    int isx, sx, sy, ox, oy, state, dsx;
    pointObj p;
    rectObj r;
    imageObj      *image = NULL;
    double fontWidth, fontHeight;
    outputFormatObj *format = NULL;
    strokeStyleObj strokeStyle;
    shapeObj shape;
    lineObj line;
    pointObj points[5];
    rendererVTableObj *renderer;

    strokeStyle.patternlength=0;

    if(map->units == -1) {
        msSetError(MS_MISCERR, "Map units not set.", "msDrawScalebar()");
        return(NULL);
    }

    renderer = MS_MAP_RENDERER(map);
    if(!renderer || !MS_MAP_RENDERER(map)->supports_pixel_buffer) {
        msSetError(MS_MISCERR, "Outputformat not supported for scalebar", "msDrawScalebar()");
        return(NULL);
    }

    /*
     *  A string containing the ten decimal digits is rendered to compute an average cell size
     *  for each number, which is used later to place labels on the scalebar.
     */

    if(msGetLabelSize(map,&map->scalebar.label,"0123456789",map->scalebar.label.size,&r,NULL) != MS_SUCCESS) {
        return NULL;
    }
    fontWidth = (r.maxx-r.minx)/10.0;
    fontHeight = r.maxy -r.miny;

    map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height);
    status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom);
    if(status != MS_SUCCESS) {
        return(NULL);
    }
    dsx = map->scalebar.width - 2*HMARGIN;
    do {
        msx = (map->cellsize * dsx)/(msInchesPerUnit(map->scalebar.units,0)/msInchesPerUnit(map->units,0));
        i = roundInterval(msx/map->scalebar.intervals);
        snprintf(label, sizeof(label), "%g", map->scalebar.intervals*i); /* last label */
        isx = MS_NINT((i/(msInchesPerUnit(map->units,0)/msInchesPerUnit(map->scalebar.units,0)))/map->cellsize);
        sx = (map->scalebar.intervals*isx) + MS_NINT((1.5 + strlen(label)/2.0 + strlen(unitText[map->scalebar.units]))*fontWidth);

        if(sx <= (map->scalebar.width - 2*HMARGIN)) break; /* it will fit */

        dsx -= X_STEP_SIZE; /* change the desired size in hopes that it will fit in user supplied width */
    } while(1);

    sy = (2*VMARGIN) + MS_NINT(VSPACING*fontHeight) + fontHeight + map->scalebar.height - VSLOP;

    /*Ensure we have an image format representing the options for the scalebar.*/
    msApplyOutputFormat( &format, map->outputformat,
                         map->scalebar.transparent,
                         map->scalebar.interlace,
                         MS_NOOVERRIDE );

    if(map->scalebar.transparent == MS_OFF) {
        if(!MS_VALID_COLOR(map->scalebar.imagecolor))
            MS_INIT_COLOR(map->scalebar.imagecolor,255,255,255,255);
    }
    image = msImageCreate(map->scalebar.width, sy, format,
                          map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->scalebar.imagecolor);

    /* drop this reference to output format */
    msApplyOutputFormat( &format, NULL,
                         MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE );

    /* did we succeed in creating the image? */
    if(!image) {
        msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawScalebar()");
        return NULL;
    }

    switch(map->scalebar.align) {
    case(MS_ALIGN_LEFT):
        ox = HMARGIN;
        break;
    case(MS_ALIGN_RIGHT):
        ox = MS_NINT((map->scalebar.width - sx) + fontWidth);
        break;
    default:
        ox = MS_NINT((map->scalebar.width - sx)/2.0 + fontWidth/2.0); /* center the computed scalebar */
    }
    oy = VMARGIN;

    switch(map->scalebar.style) {
    case(0): {

        line.numpoints = 5;
        line.point = points;
        shape.line = &line;
        shape.numlines = 1;
        if(MS_VALID_COLOR(map->scalebar.color)) {
            INIT_STROKE_STYLE(strokeStyle);
            strokeStyle.color = &map->scalebar.outlinecolor;
            strokeStyle.color->alpha = 255;
            strokeStyle.width = 1;
        }
        map->scalebar.backgroundcolor.alpha = 255;
        map->scalebar.color.alpha = 255;
        state = 1; /* 1 means filled */
        for(j=0; j<map->scalebar.intervals; j++) {
            points[0].x = points[4].x = points[3].x = ox + j*isx + 0.5;
            points[0].y = points[4].y = points[1].y = oy + 0.5;
            points[1].x = points[2].x = ox + (j+1)*isx + 0.5;
            points[2].y = points[3].y = oy + map->scalebar.height + 0.5;
            if(state == 1 && MS_VALID_COLOR(map->scalebar.color))
                renderer->renderPolygon(image,&shape,&map->scalebar.color);
            else if(MS_VALID_COLOR(map->scalebar.backgroundcolor))
                renderer->renderPolygon(image,&shape,&map->scalebar.backgroundcolor);

            if(strokeStyle.color)
                renderer->renderLine(image,&shape,&strokeStyle);

            sprintf(label, "%g", j*i);
            map->scalebar.label.position = MS_CC;
            p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */
            p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight);
            msDrawLabel(map,image,p,label,&map->scalebar.label,1.0);
            state = -state;
        }
        sprintf(label, "%g", j*i);
        ox = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0);
        sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]);
        map->scalebar.label.position = MS_CR;
        p.x = ox; /* + MS_NINT(fontPtr->w/2); */
        p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight);
        msDrawLabel(map,image,p,label,&map->scalebar.label,1.0);

        break;
    }
    case(1): {
        line.numpoints = 2;
        line.point = points;
        shape.line = &line;
        shape.numlines = 1;
        if(MS_VALID_COLOR(map->scalebar.color)) {
            strokeStyle.width = 1;
            strokeStyle.color = &map->scalebar.color;
        }

        points[0].y = points[1].y = oy;
        points[0].x = ox;
        points[1].x = ox + isx*map->scalebar.intervals;
        renderer->renderLine(image,&shape,&strokeStyle);

        points[0].y = oy;
        points[1].y = oy + map->scalebar.height;
        p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight);
        for(j=0; j<=map->scalebar.intervals; j++) {
            points[0].x = points[1].x = ox + j*isx;
            renderer->renderLine(image,&shape,&strokeStyle);

            sprintf(label, "%g", j*i);
            if(j!=map->scalebar.intervals) {
                map->scalebar.label.position = MS_CC;
                p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */
            } else {
                sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]);
                map->scalebar.label.position = MS_CR;
                p.x = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0);
            }
            msDrawLabel(map,image,p,label,&map->scalebar.label,1.0);
        }
        break;
    }
    default:
        msSetError(MS_MISCERR, "Unsupported scalebar style.", "msDrawScalebar()");
        return(NULL);
    }
    return(image);

}
Exemplo n.º 2
0
int msDrawShadeSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor)
{
  int ret = MS_SUCCESS;
  symbolObj *symbol;
  if (!p)
    return MS_SUCCESS;
  if (p->numlines <= 0)
    return MS_SUCCESS;

  if (style->symbol >= map->symbolset.numsymbols || style->symbol < 0)
    return MS_SUCCESS; /* no such symbol, 0 is OK */
  symbol = map->symbolset.symbol[style->symbol];

  /*
   * if only an outlinecolor was defined, and not a color,
   * switch to the line drawing function
   *
   * this behavior is kind of a mapfile hack, and must be
   * kept for backwards compatibility
   */
  if (symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG ) {
    if (!MS_VALID_COLOR(style->color)) {
      if(MS_VALID_COLOR(style->outlinecolor))
        return msDrawLineSymbol(map, image, p, style, scalefactor);
      else {
        /* just do nothing if no color has been set */
        return MS_SUCCESS;
      }
    }
  }
  if (image) {
    if (MS_RENDERER_PLUGIN(image->format)) {
      rendererVTableObj *renderer = image->format->vtable;
      shapeObj *offsetPolygon = NULL;
      /* store a reference to the renderer to be used for freeing */
      if(style->symbol)
        symbol->renderer = renderer;

      if (style->offsetx != 0 || style->offsety != 0) {
        if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) {
          offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor, MS_STYLE_SINGLE_SIDED_OFFSET);
        } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) {
          offsetPolygon = msOffsetPolyline(p,style->offsetx * scalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET);
        } else {
          offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor,style->offsety*scalefactor);
        }
      } else {
        offsetPolygon=p;
      }
      /* simple polygon drawing, without any specific symbol.
       * also draws an optional outline */
      if(style->symbol == 0 || symbol->type == MS_SYMBOL_SIMPLE) {
        ret = renderer->renderPolygon(image,offsetPolygon,&style->color);
        if(ret != MS_SUCCESS) goto cleanup;
        if(MS_VALID_COLOR(style->outlinecolor)) {
          strokeStyleObj s;
          INIT_STROKE_STYLE(s);
          s.color = &style->outlinecolor;
          s.color->alpha = style->color.alpha;
          s.width = (style->width == 0)?scalefactor:style->width*scalefactor;
          s.width = MS_MIN(s.width, style->maxwidth);
          s.width = MS_MAX(s.width, style->minwidth);
          ret = renderer->renderLine(image,offsetPolygon,&s);
        }
        goto cleanup; /*finished plain polygon*/
      } else if(symbol->type == MS_SYMBOL_HATCH) {
        double width, spacing;
        double pattern[MS_MAXPATTERNLENGTH];
        int i;

        if(MS_VALID_COLOR(style->backgroundcolor)) {
          ret = renderer->renderPolygon(image,offsetPolygon, &style->backgroundcolor);
          if(ret != MS_SUCCESS) goto cleanup;
        }
        width = (style->width <= 0)?scalefactor:style->width*scalefactor;
        width = MS_MIN(width, style->maxwidth*image->resolutionfactor);
        width = MS_MAX(width, style->minwidth*image->resolutionfactor);
        spacing = (style->size <= 0)?scalefactor:style->size*scalefactor;
        spacing = MS_MIN(spacing, style->maxsize*image->resolutionfactor);
        spacing = MS_MAX(spacing, style->minsize*image->resolutionfactor);

        /* scale the pattern by the factor applied to the width */
        for(i=0; i<style->patternlength; i++) {
          pattern[i] = style->pattern[i]*width/style->width;
        }

        ret = msHatchPolygon(image,offsetPolygon,spacing,width,pattern,style->patternlength,style->angle, &style->color);
        goto cleanup;
      } else {
        symbolStyleObj s;
        int pw,ph;
        imageObj *tile;
        int seamless = 0;

        if(preloadSymbol(&map->symbolset,symbol,renderer) != MS_SUCCESS) {
          return MS_FAILURE;
        }

        INIT_SYMBOL_STYLE(s);
        computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor);
        s.style = style;

        if (!s.color && !s.outlinecolor && symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG) {
          ret = MS_SUCCESS; /* nothing to do (colors are required except for PIXMAP symbols */
          goto cleanup;
        }

        if(s.backgroundcolor) {
          ret = renderer->renderPolygon(image,offsetPolygon, s.backgroundcolor);
          if(ret != MS_SUCCESS) goto cleanup;
        }

        if(s.scale != 1) {
          if (s.gap > 0) {
            pw = MS_MAX(MS_NINT(s.gap),symbol->sizex * s.scale);
            ph = MS_MAX(MS_NINT(s.gap),symbol->sizey * s.scale);
          } else {
            pw = MS_NINT(symbol->sizex * s.scale);
            ph = MS_NINT(symbol->sizey * s.scale);
          }
        } else {
          if (s.gap > 0) {
            pw = MS_MAX(s.gap,symbol->sizex);
            ph = MS_MAX(s.gap,symbol->sizey);
          } else {
            pw = symbol->sizex;
            ph = symbol->sizey;
          }
        }
        if(pw<1) pw=1;
        if(ph<1) ph=1;

        /* if we're doing vector symbols with an antialiased pixel rendererer, we want to enable
         * seamless mode, i.e. comute a tile that accounts for the blending of neighbouring
         * tiles at the tile border
         */
        if(symbol->type == MS_SYMBOL_VECTOR && style->gap == 0 &&
            (image->format->renderer == MS_RENDER_WITH_AGG ||
             image->format->renderer == MS_RENDER_WITH_CAIRO_RASTER)) {
          seamless = 1;
        }
        tile = getTile(image,symbol,&s,pw,ph,seamless);
        ret = renderer->renderPolygonTiled(image,offsetPolygon, tile);
      }

cleanup:
      if (offsetPolygon != p) {
        msFreeShape(offsetPolygon);
        msFree(offsetPolygon);
      }
      return ret;
    } else if( MS_RENDERER_IMAGEMAP(image->format) )
      msDrawShadeSymbolIM(map, image, p, style, scalefactor);
  }
  return ret;
}