Exemple #1
0
/*
** Merges rect b into rect a. Rect a changes, b does not.
*/
void msMergeRect(rectObj *a, rectObj *b)
{
  a->minx = MS_MIN(a->minx, b->minx);
  a->maxx = MS_MAX(a->maxx, b->maxx);
  a->miny = MS_MIN(a->miny, b->miny);
  a->maxy = MS_MAX(a->maxy, b->maxy);
}
Exemple #2
0
int agg2RenderLine(imageObj *img, shapeObj *p, strokeStyleObj *style)
{

  AGG2Renderer *r = AGG_RENDERER(img);
  line_adaptor lines = line_adaptor(p);

#ifdef AGG_ALIASED_ENABLED
  r->m_rasterizer_primitives.reset();
  r->m_renderer_primitives.line_color(aggColor(style->color));
  r->m_rasterizer_primitives.add_path(lines);
  return MS_SUCCESS;
#endif

  r->m_rasterizer_aa.reset();
  r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
  r->m_renderer_scanline.color(aggColor(style->color));

  if (style->patternlength <= 0) {
    mapserver::conv_stroke<line_adaptor> stroke(lines);
    stroke.width(style->width);
    if(style->width>1) {
      applyCJC(stroke, style->linecap, style->linejoin);
    } else {
      stroke.inner_join(mapserver::inner_bevel);
      stroke.line_join(mapserver::bevel_join);
    }
    r->m_rasterizer_aa.add_path(stroke);
  } else {
    mapserver::conv_dash<line_adaptor> dash(lines);
    mapserver::conv_stroke<mapserver::conv_dash<line_adaptor> > stroke_dash(dash);
    int patt_length = 0;
    for (int i = 0; i < style->patternlength; i += 2) {
      if (i < style->patternlength - 1) {
        dash.add_dash(MS_MAX(1,MS_NINT(style->pattern[i])),
                      MS_MAX(1,MS_NINT(style->pattern[i + 1])));
        if(style->patternoffset) {
          patt_length += MS_MAX(1,MS_NINT(style->pattern[i])) +
                         MS_MAX(1,MS_NINT(style->pattern[i + 1]));
        }
      }
    }
    if(style->patternoffset > 0) {
      dash.dash_start(patt_length - style->patternoffset);
    }
    stroke_dash.width(style->width);
    if(style->width>1) {
      applyCJC(stroke_dash, style->linecap, style->linejoin);
    } else {
      stroke_dash.inner_join(mapserver::inner_bevel);
      stroke_dash.line_join(mapserver::bevel_join);
    }
    r->m_rasterizer_aa.add_path(stroke_dash);
  }
  mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline);
  return MS_SUCCESS;
}
Exemple #3
0
/* {{{ proto int symbol.setpoints(array points)
   Set the points of the symbol ) */ 
PHP_METHOD(symbolObj, setPoints)
{
    zval *zpoints, **ppzval;
    HashTable *points_hash = NULL;
    zval *zobj = getThis();
    int index = 0, flag = 0, numelements = 0;
    php_symbol_object *php_symbol;

    PHP_MAPSCRIPT_ERROR_HANDLING(TRUE);
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a",
                              &zpoints) == FAILURE) {
        PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
        return;
    }
    PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
    
    php_symbol = (php_symbol_object *) zend_object_store_get_object(zobj TSRMLS_CC);
    points_hash = Z_ARRVAL_P(zpoints);

    numelements = zend_hash_num_elements(points_hash);
    if ((numelements == 0) || (numelements % 2 != 0))
    {
        mapscript_report_php_error(E_WARNING, 
                                   "symbol->setpoints : invalid array of %d element(s) as parameter." TSRMLS_CC, numelements);
        RETURN_LONG(MS_FAILURE);
        
    }

    for(zend_hash_internal_pointer_reset(points_hash); 
        zend_hash_has_more_elements(points_hash) == SUCCESS; 
        zend_hash_move_forward(points_hash))
    { 
        
        zend_hash_get_current_data(points_hash, (void **)&ppzval);
        if (Z_TYPE_PP(ppzval) != IS_DOUBLE)
            convert_to_double(*ppzval);
	     
        if (!flag)
        {
            php_symbol->symbol->points[index].x = Z_DVAL_PP(ppzval);
            php_symbol->symbol->sizex = MS_MAX(php_symbol->symbol->sizex, php_symbol->symbol->points[index].x);
        }
        else
        {
            php_symbol->symbol->points[index].y = Z_DVAL_PP(ppzval);
            php_symbol->symbol->sizey = MS_MAX(php_symbol->symbol->sizey, php_symbol->symbol->points[index].y);
            index++;
        }    
        flag = !flag;
    }

    php_symbol->symbol->numpoints = (numelements/2);

    RETURN_LONG(MS_SUCCESS);
}
Exemple #4
0
static void get_bbox(pointObj *poiList, int numpoints, double *minx, double *miny, double *maxx, double *maxy) {
  int j;

  *minx = *maxx = poiList[0].x;
  *miny = *maxy = poiList[0].y;
  for(j=1; j<numpoints; j++) {
    if ((poiList[j].x==-99.0) || (poiList[j].y==-99.0)) continue;
    *minx = MS_MIN(*minx, poiList[j].x);
    *maxx = MS_MAX(*maxx, poiList[j].x);
    *miny = MS_MIN(*miny, poiList[j].y);
    *maxy = MS_MAX(*maxy, poiList[j].y);
  }

  return;
}
Exemple #5
0
static void mshmet_endcod() {
  double   ttot,ttim[TIMEMAX];
  int      k,call[TIMEMAX];

  chrono(OFF,&mshmet_ctim[0]);
  for (k=0; k<TIMEMAX; k++) {
    call[k] = mshmet_ctim[k].call;
    ttim[k] = mshmet_ctim[k].call ? gttime(mshmet_ctim[k]) : 0.0;
  }
  ttot    = ttim[1]+ttim[2]+ttim[3]+ttim[4];
  ttim[0] = MS_MAX(ttim[0],ttot);

  if ( ttot > 0.01 ) {
    fprintf(stdout,"\n  -- CPU REQUIREMENTS\n");
    fprintf(stdout,"  in/out    %8.2f %%    %3d. calls,   %7.2f sec/call\n",
        100.*ttim[1]/ttim[0],call[1],ttim[1]/(float)call[1]);
    fprintf(stdout,"  analysis  %8.2f %%    %3d. calls,   %7.2f sec/call\n",
        100.*ttim[2]/ttim[0],call[2],ttim[2]/(float)call[2]);
    fprintf(stdout,"  metric    %8.2f %%    %3d. calls,   %7.2f sec/call\n",
        100.*ttim[3]/ttim[0],call[3],ttim[3]/(float)call[3]);
    fprintf(stdout,"  total     %8.2f %%    %3d. calls,   %7.2f sec/call\n",
        100.*ttot/ttim[0],call[0],ttot/(float)call[0]);
  }
  fprintf(stdout,"\n   ELAPSED TIME  %.2f SEC.  (%.2f)\n",ttim[0],ttot);
}
Exemple #6
0
void *msCreateTileEllipseCairo(double width, double height, double angle,
                               colorObj *c, colorObj *bc, colorObj *oc, double ow) {
    double s = (MS_MAX(width,height)+ow)*1.5;
    cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                                           s,s);
    cairo_t *cr = cairo_create(surface);
    //cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
    //cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
    if (bc && MS_VALID_COLOR(*bc)) {
        msCairoSetSourceColor(cr, bc);
        cairo_paint(cr);
    }
    cairo_save(cr);
    cairo_translate(cr,s/2,s/2);
    cairo_rotate(cr, -angle);
    cairo_scale(cr, width/2,height/2);
    cairo_arc(cr, 0, 0, 1, 0, 2 * MS_PI);
    cairo_restore(cr);
    if (c != NULL && MS_VALID_COLOR(*c)) {
        msCairoSetSourceColor(cr, c);
        cairo_fill_preserve(cr);
    }
    if (oc != NULL && MS_VALID_COLOR(*oc)) {
        cairo_set_line_width(cr, ow);
        msCairoSetSourceColor(cr, oc);
        cairo_stroke_preserve(cr);
    }
    cairo_new_path(cr);
    cairo_destroy(cr);
    return surface;

}
Exemple #7
0
void computeSymbolStyle(symbolStyleObj *s, styleObj *src, symbolObj *symbol, double scalefactor,
    double resolutionfactor)
{
  double default_size;
  double target_size;
  double style_size;

  default_size = msSymbolGetDefaultSize(symbol);
  style_size = (src->size==-1)?default_size:src->size;

  INIT_SYMBOL_STYLE(*s);
  if(symbol->type == MS_SYMBOL_PIXMAP) {
    s->color = s->outlinecolor = NULL;
  } else if(symbol->filled || symbol->type == MS_SYMBOL_TRUETYPE) {
    if(MS_VALID_COLOR(src->color))
      s->color = &src->color;
    if(MS_VALID_COLOR(src->outlinecolor))
      s->outlinecolor = &src->outlinecolor;
  } else {
    if(MS_VALID_COLOR(src->color))
      s->outlinecolor = &(src->color);
    else if(MS_VALID_COLOR(src->outlinecolor))
      s->outlinecolor = &(src->outlinecolor);
    s->color = NULL;
  }


  if(MS_VALID_COLOR(src->backgroundcolor)) {
    s->backgroundcolor = &(src->backgroundcolor);
  }

  target_size = style_size * scalefactor;
  target_size = MS_MAX(target_size, src->minsize*resolutionfactor);
  target_size = MS_MIN(target_size, src->maxsize*resolutionfactor);
  s->scale = target_size / default_size;
  s->gap = src->gap * target_size / style_size;

  if(s->outlinecolor) {
    s->outlinewidth =  src->width * scalefactor;
    s->outlinewidth = MS_MAX(s->outlinewidth, src->minwidth*resolutionfactor);
    s->outlinewidth = MS_MIN(s->outlinewidth, src->maxwidth*resolutionfactor);
  } else {
    s->outlinewidth = 0;
  }

  s->rotation = src->angle * MS_DEG_TO_RAD;
}
int msGetRasterTextBBox(rendererVTableObj *renderer, int size, char *string, rectObj *rect)
{
  if(renderer && renderer->supports_bitmap_fonts) {
    int num_lines=1, cur_line_length=0, max_line_length=0;
    char *stringPtr = string;
    fontMetrics *fontPtr;
    if((fontPtr=renderer->bitmapFontMetrics[size]) == NULL) {
      msSetError(MS_MISCERR, "selected renderer does not support bitmap font size %d", "msGetRasterTextBBox()",size);
      return MS_FAILURE;
    }
    while(*stringPtr) {
      if(*stringPtr=='\n') {
        max_line_length = MS_MAX(cur_line_length,max_line_length);
        num_lines++;
        cur_line_length=0;
      } else {
        if(*stringPtr!='\r')
          cur_line_length++;
      }
      stringPtr++;
    }
    max_line_length = MS_MAX(cur_line_length,max_line_length);
    rect->minx = 0;
    rect->miny = -fontPtr->charHeight;
    rect->maxx = fontPtr->charWidth * max_line_length;
    rect->maxy = fontPtr->charHeight * (num_lines-1);
    return MS_SUCCESS;
  } else if(!renderer) {
    int ret = MS_FAILURE;
    outputFormatObj *format = msCreateDefaultOutputFormat(NULL,"AGG/PNG","tmp");
    if(!format) {
      msSetError(MS_MISCERR, "failed to create default format", "msGetRasterTextBBox()");
      return MS_FAILURE;
    }
    msInitializeRendererVTable(format);
    renderer = format->vtable;
    ret = msGetRasterTextBBox(renderer,size,string,rect);
    msFreeOutputFormat(format);
    return ret;
  } else {
    msSetError(MS_MISCERR, "selected renderer does not support raster fonts", "msGetRasterTextBBox()");
    return MS_FAILURE;
  }
}
Exemple #9
0
static void msProjectGrowRect(projectionObj *in, projectionObj *out,
                              rectObj *prj_rect, int *rect_initialized,
                              pointObj *prj_point, int *failure )

{
  if( msProjectPoint(in, out, prj_point) == MS_SUCCESS ) {
    if( *rect_initialized ) {
      prj_rect->miny = MS_MIN(prj_rect->miny, prj_point->y);
      prj_rect->maxy = MS_MAX(prj_rect->maxy, prj_point->y);
      prj_rect->minx = MS_MIN(prj_rect->minx, prj_point->x);
      prj_rect->maxx = MS_MAX(prj_rect->maxx, prj_point->x);
    } else {
      prj_rect->minx = prj_rect->maxx = prj_point->x;
      prj_rect->miny = prj_rect->maxy = prj_point->y;
      *rect_initialized = MS_TRUE;
    }
  } else
    (*failure)++;
}
Exemple #10
0
void msComputeBounds(shapeObj *shape)
{
  int i, j;

  if(shape->numlines <= 0) return;
  if(shape->line[0].numpoints <= 0) return;

  shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x;
  shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y;

  for( i=0; i<shape->numlines; i++ ) {
    for( j=0; j<shape->line[i].numpoints; j++ ) {
      shape->bounds.minx = MS_MIN(shape->bounds.minx, shape->line[i].point[j].x);
      shape->bounds.maxx = MS_MAX(shape->bounds.maxx, shape->line[i].point[j].x);
      shape->bounds.miny = MS_MIN(shape->bounds.miny, shape->line[i].point[j].y);
      shape->bounds.maxy = MS_MAX(shape->bounds.maxy, shape->line[i].point[j].y);
    }
  }
}
Exemple #11
0
Fichier : mmgs1.c Projet : XL64/mmg
/* analyze triangles and split or collapse to match gradation */
static int adptri(pMesh mesh,pSol met) {
    int        it,nnc,nns,nnf,nnm,maxit,nc,ns,nf,nm;

    /* iterative mesh modifications */
    it = nnc = nns = nnf = nnm = 0;
    maxit = 10;
    do {
        ns = adpspl(mesh,met);
        if ( ns < 0 ) {
            fprintf(stdout,"  ## Unable to complete mesh. Exit program.\n");
            return(0);
        }

        nc = adpcol(mesh,met);
        if ( nc < 0 ) {
            fprintf(stdout,"  ## Unable to complete mesh. Exit program.\n");
            return(0);
        }
        nf = nm = 0;

        nf = swpmsh(mesh,met,2);
        if ( nf < 0 ) {
            fprintf(stdout,"  ## Unable to improve mesh. Exiting.\n");
            return(0);
        }

        nm = movtri(mesh,met,1);
        if ( nm < 0 ) {
            fprintf(stdout,"  ## Unable to improve mesh. Exiting.\n");
            return(0);
        }

        nnc += nc;
        nns += ns;
        nnf += nf;
        nnm += nm;
        if ( (abs(info.imprim) > 4 || info.ddebug) && ns+nc+nf+nm > 0 )
            fprintf(stdout,"     %8d splitted, %8d collapsed, %8d swapped, %8d moved\n",ns,nc,nf,nm);
        if ( ns < 10 && abs(nc-ns) < 3 )  break;
        else if ( it > 3 && abs(nc-ns) < 0.3 * MS_MAX(nc,ns) )  break;
    }
    while( ++it < maxit && nc+ns > 0 );

    nm = 0;
    nm = movtri(mesh,met,5);
    if ( nm < 0 ) {
        fprintf(stdout,"  ## Unable to improve mesh.\n");
        return(0);
    }
    nnm += nm;

    if ( abs(info.imprim) < 5 && (nnc > 0 || nns > 0) )
        fprintf(stdout,"     %8d splitted, %8d collapsed, %8d swapped, %8d moved, %d iter. \n",nns,nnc,nnf,nnm,it);
    return(1);
}
Exemple #12
0
int msIntersectSegments(const pointObj *a, const pointObj *b, const pointObj *c, const pointObj *d)   /* from comp.graphics.alogorithms FAQ */
{

  double r, s;
  double denominator, numerator;

  numerator = ((a->y-c->y)*(d->x-c->x) - (a->x-c->x)*(d->y-c->y));
  denominator = ((b->x-a->x)*(d->y-c->y) - (b->y-a->y)*(d->x-c->x));

  if((denominator == 0) && (numerator == 0)) { /* lines are coincident, intersection is a line segement if it exists */
    if(a->y == c->y) { /* coincident horizontally, check x's */
      if(((a->x >= MS_MIN(c->x,d->x)) && (a->x <= MS_MAX(c->x,d->x))) || ((b->x >= MS_MIN(c->x,d->x)) && (b->x <= MS_MAX(c->x,d->x))))
        return(MS_TRUE);
      else
        return(MS_FALSE);
    } else { /* test for y's will work fine for remaining cases */
      if(((a->y >= MS_MIN(c->y,d->y)) && (a->y <= MS_MAX(c->y,d->y))) || ((b->y >= MS_MIN(c->y,d->y)) && (b->y <= MS_MAX(c->y,d->y))))
        return(MS_TRUE);
      else
        return(MS_FALSE);
    }
  }

  if(denominator == 0) /* lines are parallel, can't intersect */
    return(MS_FALSE);

  r = numerator/denominator;

  if((r<0) || (r>1))
    return(MS_FALSE); /* no intersection */

  numerator = ((a->y-c->y)*(b->x-a->x) - (a->x-c->x)*(b->y-a->y));
  s = numerator/denominator;

  if((s<0) || (s>1))
    return(MS_FALSE); /* no intersection */

  return(MS_TRUE);
}
Exemple #13
0
Fichier : mmgs1.c Projet : XL64/mmg
/* analyze tetrahedra and split if needed */
static int anatri(pMesh mesh,pSol met,char typchk) {
    int     nc,ns,nf,nnc,nns,nnf,it,maxit;

    /* analyze tetras : initial splitting */
    nns = nnc = nnf = it = 0;
    maxit = 5;
    do {
        /* memory free */
        free(mesh->adja);
        mesh->adja = 0;

        /* analyze surface */
        ns = anaelt(mesh,met,typchk);
        if ( ns < 0 ) {
            fprintf(stdout,"  ## Unable to complete surface mesh. Exit program.\n");
            return(0);
        }

        if ( !hashTria(mesh) ) {
            fprintf(stdout,"  ## Hashing problem. Exit program.\n");
            return(0);
        }

        /* collapse short edges */
        nc = colelt(mesh,met,typchk);
        if ( nc < 0 ) {
            fprintf(stdout,"  ## Unable to collapse mesh. Exiting.\n");
            return(0);
        }

        /* attempt to swap */
        nf = swpmsh(mesh,met,typchk);
        if ( nf < 0 ) {
            fprintf(stdout,"  ## Unable to improve mesh. Exiting.\n");
            return(0);
        }

        nnc += nc;
        nns += ns;
        nnf += nf;
        if ( (abs(info.imprim) > 4 || info.ddebug) && ns+nc > 0 )
            fprintf(stdout,"     %8d splitted, %8d collapsed, %8d swapped\n",ns,nc,nf);
        if ( it > 3 && abs(nc-ns) < 0.1 * MS_MAX(nc,ns) )  break;
    }
    while ( ++it < maxit && ns+nc+nf > 0 );

    if ( (abs(info.imprim) < 5 || info.ddebug ) && nns+nnc > 0 )
        fprintf(stdout,"     %8d splitted, %8d collapsed, %8d swapped, %d iter.\n",nns,nnc,nnf,it);

    return(1);
}
Exemple #14
0
int agg2RenderBitmapGlyphs2(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow)
{
  int size = tp->glyph_size;
  size = MS_MAX(0,size);
  size = MS_MIN(4,size);
  AGG2Renderer *r = AGG_RENDERER(img);

  glyph_gen glyph(0);
  mapserver::renderer_raster_htext_solid<renderer_base, glyph_gen> rt(r->m_renderer_base, glyph);
  glyph.font(rasterfonts[size]);
  unsigned int cc_start = rasterfonts[size][2];
  unsigned int cc_end = cc_start + rasterfonts[size][3];
  unsigned int glyph_idx;
  if(oc) {
    rt.color(aggColor(oc));
    for(int n=0; n<tp->numglyphs; n++) {
      glyphObj *g = &tp->glyphs[n];
      /* do some unicode mapping, for now we just replace unsupported characters with "." */
      if(g->glyph->key.codepoint < cc_start || g->glyph->key.codepoint > cc_end) {
        glyph_idx = '.';
      } else {
        glyph_idx = g->glyph->key.codepoint;
      }
      for(int i=-1; i<=1; i++) {
        for(int j=-1; j<=1; j++) {
          if(i||j) {
            rt.render_glyph(g->pnt.x+i , g->pnt.y+j, glyph_idx, true);
          }
        }
      }

    }
  }
  if(c) {
    rt.color(aggColor(c));
    for(int n=0; n<tp->numglyphs; n++) {
      glyphObj *g = &tp->glyphs[n];
      /* do some unicode mapping, for now we just replace unsupported characters with "." */
      if(g->glyph->key.codepoint < cc_start || g->glyph->key.codepoint > cc_end) {
        glyph_idx = '.';
      } else {
        glyph_idx = g->glyph->key.codepoint;
      }
      rt.render_glyph(g->pnt.x , g->pnt.y, glyph_idx, true);
    }
  }
  return MS_SUCCESS;
}
gdImagePtr rotatePixmapGD(gdImagePtr img, double angle_rad)
{
    gdImagePtr rimg = NULL;
    double cos_a, sin_a;
    double x1 = 0.0, y1 = 0.0; /* destination rectangle */
    double x2 = 0.0, y2 = 0.0;
    double x3 = 0.0, y3 = 0.0;
    double x4 = 0.0, y4 = 0.0;

    long minx, miny, maxx, maxy;

    int width=0, height=0;
    /* int color; */

    sin_a = sin(angle_rad);
    cos_a = cos(angle_rad);

    /* compute distination rectangle (x1,y1 is known) */
    x1 = 0 ;
    y1 = 0 ;
    x2 = img->sy * sin_a;
    y2 = -img->sy * cos_a;
    x3 = (img->sx * cos_a) + (img->sy * sin_a);
    y3 = (img->sx * sin_a) - (img->sy * cos_a);
    x4 = (img->sx * cos_a);
    y4 = (img->sx * sin_a);

    minx = (long) MS_MIN(x1,MS_MIN(x2,MS_MIN(x3,x4)));
    miny = (long) MS_MIN(y1,MS_MIN(y2,MS_MIN(y3,y4)));
    maxx = (long) MS_MAX(x1,MS_MAX(x2,MS_MAX(x3,x4)));
    maxy = (long) MS_MAX(y1,MS_MAX(y2,MS_MAX(y3,y4)));

    width = (int)ceil(maxx-minx);
    height = (int)ceil(maxy-miny);

    /* create the new image based on the computed width/height */

    if (gdImageTrueColor(img)) {
        rimg = gdImageCreateTrueColor(width, height);
        gdImageAlphaBlending(rimg, 0);
        gdImageFilledRectangle(rimg, 0, 0, width, height, gdImageColorAllocateAlpha(rimg, 0, 0, 0, gdAlphaTransparent));
    } else {
        int tc = gdImageGetTransparent(img);
        rimg = gdImageCreate(width, height);
        if(tc != -1)
            gdImageColorTransparent(rimg, gdImageColorAllocate(rimg, gdImageRed(img, tc), gdImageGreen(img, tc), gdImageBlue(img, tc)));
    }
    if(!rimg) {
        msSetError(MS_GDERR,"failed to create rotated pixmap","rotatePixmapGD()");
        return NULL;
    }

    gdImageCopyRotated (rimg, img, width*0.5, height*0.5, 0, 0, gdImageSX(img), gdImageSY(img), angle_rad*MS_RAD_TO_DEG);
    return rimg;
}
Exemple #16
0
int agg2RenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style)
{
  AGG2Renderer *r = AGG_RENDERER(img);
  rasterBufferObj *pixmap = symbol->pixmap_buffer;
  assert(pixmap->type == MS_BUFFER_BYTE_RGBA);
  rendering_buffer b(pixmap->data.rgba.pixels,pixmap->width,pixmap->height,pixmap->data.rgba.row_step);
  pixel_format pf(b);

  r->m_rasterizer_aa.reset();
  r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
  if ( (style->rotation != 0 && style->rotation != MS_PI*2.)|| style->scale != 1) {
    mapserver::trans_affine image_mtx;
    image_mtx *= mapserver::trans_affine_translation(-(pf.width()/2.),-(pf.height()/2.));
    /*agg angles are antitrigonometric*/
    image_mtx *= mapserver::trans_affine_rotation(-style->rotation);
    image_mtx *= mapserver::trans_affine_scaling(style->scale);



    image_mtx *= mapserver::trans_affine_translation(x,y);
    image_mtx.invert();
    typedef mapserver::span_interpolator_linear<> interpolator_type;
    interpolator_type interpolator(image_mtx);
    mapserver::span_allocator<color_type> sa;

    // "hardcoded" bilinear filter
    //------------------------------------------
    typedef mapserver::span_image_filter_rgba_bilinear_clip<pixel_format, interpolator_type> span_gen_type;
    span_gen_type sg(pf, mapserver::rgba(0,0,0,0), interpolator);
    mapserver::path_storage pixmap_bbox;
    int ims_2 = MS_NINT(MS_MAX(pixmap->width,pixmap->height)*style->scale*1.415)/2+1;

    pixmap_bbox.move_to(x-ims_2,y-ims_2);
    pixmap_bbox.line_to(x+ims_2,y-ims_2);
    pixmap_bbox.line_to(x+ims_2,y+ims_2);
    pixmap_bbox.line_to(x-ims_2,y+ims_2);

    r->m_rasterizer_aa.add_path(pixmap_bbox);
    mapserver::render_scanlines_aa(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_base, sa, sg);
  } else {
    //just copy the image at the correct location (we place the pixmap on
    //the nearest integer pixel to avoid blurring)
    r->m_renderer_base.blend_from(pf,0,MS_NINT(x-pixmap->width/2.),MS_NINT(y-pixmap->height/2.));
  }
  return MS_SUCCESS;
}
Exemple #17
0
ms_uint32 OglContext::getTextureSize(GLuint dimension, ms_uint32 value)
{
  glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA,  value, value, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  GLint check = 0;
  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, dimension, &check);

  if (glGetError() != GL_NO_ERROR) {
    msSetError(MS_OGLERR, "glGetTexLevelParameteriv failed. glError: %d", "OglContext::getTextureSize()", glGetError());
  }

  if (check == 0) {
    return MS_MAX(MS_MIN(NextPowerOf2(value), OglContext::MAX_TEXTURE_SIZE), OglContext::MIN_TEXTURE_SIZE);
  } else {
    msSetError(MS_OGLERR, "Unable to create opengl texture of map size", "OglContext::getTextureSize()");
    return value;
  }
}
Exemple #18
0
int getBitmapGlyphMetrics(int size, unsigned int unicode, glyph_metrics *bounds) {
  size = MS_MAX(0,size);
  size = MS_MIN(4,size);
  unsigned int glyph_idx;

  /* do some unicode mapping, for now we just replace unsupported characters with "." */
  unsigned int cc_start = rasterfonts[size][2];
  unsigned int cc_end = cc_start + rasterfonts[size][3];
  if(unicode < cc_start || unicode > cc_end) {
    glyph_idx = '.';
  } else {
    glyph_idx = unicode;
  }

  glyph_gen glyph(0);
  glyph.font(rasterfonts[size]);

  bounds->minx = 0;
  bounds->miny = -glyph.base_line();
  bounds->maxx = glyph.glyph_width(glyph_idx);
  bounds->maxy = glyph.height() + bounds->miny;
  bounds->advance = bounds->maxx;
  return MS_SUCCESS;
}
Exemple #19
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;
}
/*
** Polygon fill. Based on "Concave Polygon Scan Conversion" by Paul
** Heckbert from "Graphics Gems", Academic Press, 1990.
**
*/
static void imageFilledPolygon(gdImagePtr im, shapeObj *p, int c)
{
    typedef struct {     /* a polygon edge */
        double x;          /* x coordinate of edge's intersection with current scanline */
        double dx;         /* change in x with respect to y */
        int i;             /* point index  */
        int l;             /* line number */
        int s;             /* scanline */
    } pEdge;

    pointObj *point1, *point2;

    int k, l, i, j, xl, xr, ymin, ymax, y, n,nvert, nact, m;
    int wrong_order;

    pEdge *edge, *temp;
    pEdge  **active;
    int *yhist, *edgeindex;

    if(p->numlines == 0) return;
    n=0;

    for(i=0; i<p->numlines; i++) {
        n += p->line[i].numpoints;
    }

    if(n == 0)   return;

    edge = (pEdge *) msSmallCalloc(n,sizeof(pEdge));           /* All edges in the polygon */
    edgeindex =  (int *) msSmallCalloc(n,sizeof(int));         /* Index to edges sorted by scanline */
    active = (pEdge **) msSmallCalloc(n,sizeof(pEdge*));       /* Pointers to active edges for current scanline */

    nvert=0;

    ymin= (int) ceil(p->line[0].point[0].y-0.5);
    ymax= (int) floor(p->line[0].point[0].y-0.5);

    /* populate the edge table */
    for(l=0; l<p->numlines; l++) {
        for(i=0; i < p->line[l].numpoints; i++) {
            j = i < p->line[l].numpoints -1 ? i+1 : 0;
            if (p->line[l].point[i].y  < p->line[l].point[j].y ) {
                point1 = &(p->line[l].point[i]);
                point2 = &(p->line[l].point[j]);
            } else {
                point2 = &(p->line[l].point[i]);
                point1 = &(p->line[l].point[j]);
            }

            edge[nvert].dx  = point2->y == point1->y ? 0 :  (point2->x - point1->x) / (point2->y - point1->y);
            edge[nvert].s = MS_NINT( p->line[l].point[i].y );  /* ceil( p->line[l].point[i].y  - 0.5 ); */
            edge[nvert].x = point1->x;
            edge[nvert].i = nvert;
            edge[nvert].l = l;

            ymin = MS_MIN(ymin,edge[nvert].s);
            ymax = MS_MAX(ymax,edge[nvert].s);

            nvert++;
        }
    }

    /* Use histogram sort to create a bucket-sorted edgeindex by scanline */
    yhist = (int*) msSmallCalloc(ymax - ymin + 2, sizeof(int));

    for(i=0; i<nvert; i++) {
        yhist[ edge[i].s - ymin + 1 ]++;
    }
    for(i=0; i<=(ymax - ymin); i++)  {/* Calculate starting point in edgeindex for each scanline */
        yhist[i+1] += yhist[i];
    }
    for(i=0; i<nvert; i++) { /* Bucket sort edges into edgeindex */
        y = edge[i].s;
        edgeindex[yhist[y-ymin]] = i;
        yhist[y-ymin]++;
    }
    free(yhist);

    k=0;
    nact=0;

    for (y=ymin; y<=ymax; y++) { /* step through scanlines */
        /* scanline y is at y+.5 in continuous coordinates */

        /* check vertices between previous scanline and current one, if any */
        for (; k<nvert && edge[edgeindex[k]].s <= y; k++) {
            i = edge[edgeindex[k]].i;

            /* vertex previous to i */
            if(i==0 || edge[i].l != edge[i-1].l)
                j = i +  p->line[edge[i].l].numpoints - 1;
            else
                j = i - 1;

            if (edge[j].s  <=  y  ) { /* old edge, remove from active list */
                for (m=0; m<nact && active[m]->i!=j; m++);
                if (m<nact) {
                    nact--;
                    active[m]=active[nact];
                }
            } else if (edge[j].s > y) { /* new edge,  insert into active list */
                active[nact]= & edge[j];
                nact++;
            }

            /* vertex next  after i */
            if(i==nvert-1 || edge[i].l != edge[i+1].l)
                j = i - p->line[edge[i].l].numpoints  + 1;
            else
                j = i + 1;

            if (edge[j].s  <=  y - 1 ) {     /* old edge, remove from active list */
                for (m=0; m<nact && active[m]->i!=i; m++);
                if (m<nact) {
                    nact--;
                    active[m]=active[nact];
                }
            } else if (edge[j].s > y ) { /* new edge, insert into active list */
                active[nact]= & edge[i];
                nact++;
            }
        }

        /* Sort active edges by x */
        do {
            wrong_order = 0;
            for(i=0; i < nact-1; i++) {
                if(active[i]->x > active[i+1]->x) {
                    wrong_order = 1;
                    SWAP(active[i], active[i+1], temp);
                }
            }
        } while(wrong_order);

        /* draw horizontal spans for scanline y */
        for (j=0; j<nact; j+=2) {
            /* j -> j+1 is inside,  j+1 -> j+2 is outside */
            xl = (int) MS_NINT(active[j]->x );
            xr = (int) (active[j+1]->x - 0.5) ;

            if(active[j]->x != active[j+1]->x)
                imageScanline(im, xl, xr, y, c);

            active[j]->x += active[j]->dx;  /* increment edge coords */
            active[j+1]->x += active[j+1]->dx;
        }
    }

    free(active);
    free(edgeindex);
    free(edge);
}
Exemple #21
0
int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
{
  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo;
  imageObj *image_tmp;
  outputFormatObj *outputformat = NULL;
  mapObj *map_tmp;
  double map_cellsize;
  unsigned int spacing;
  int width, height, u_src_off, v_src_off, i, x, y;
  char   **alteredProcessing = NULL, *saved_layer_mask;
  char **savedProcessing = NULL;

  
  if (layer->debug)
    msDebug("Entering msUVRASTERLayerWhichShapes().\n");

  if( uvlinfo == NULL )
    return MS_FAILURE;

  /* QUERY NOT SUPPORTED YET */
  if (isQuery == MS_TRUE) {
    msSetError( MS_MISCERR, "Query is not supported for UV layer.", "msUVRASTERLayerWhichShapes()" );
    return MS_FAILURE;
  }


  if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) {
    msSetError( MS_MISCERR, "BANDS processing option is required for UV layer. You have to specified 2 bands.",
                "msUVRASTERLayerWhichShapes()" );
    return MS_FAILURE;
  }
  
  /*
  ** Allocate mapObj structure
  */
  map_tmp = (mapObj *)msSmallCalloc(sizeof(mapObj),1);
  if(initMap(map_tmp) == -1) { /* initialize this map */
    msFree(map_tmp);
    return(MS_FAILURE);
  }

  /* -------------------------------------------------------------------- */
  /*      Determine desired spacing.  Default to 32 if not otherwise set  */
  /* -------------------------------------------------------------------- */
  spacing = 32;
  if( CSLFetchNameValue( layer->processing, "UV_SPACING" ) != NULL ) {
    spacing =
      atoi(CSLFetchNameValue( layer->processing, "UV_SPACING" ));
  }

  width = (int)ceil(layer->map->width/spacing);
  height = (int)ceil(layer->map->height/spacing);
  map_cellsize = MS_MAX(MS_CELLSIZE(rect.minx, rect.maxx,layer->map->width),
                        MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height));
  map_tmp->cellsize = map_cellsize*spacing;
  
  if (layer->debug)
    msDebug("msUVRASTERLayerWhichShapes(): width: %d, height: %d, cellsize: %g\n",
            width, height, map_tmp->cellsize);

  /* Initialize our dummy map */
  MS_INIT_COLOR(map_tmp->imagecolor, 255,255,255,255);
  map_tmp->resolution = layer->map->resolution;
  map_tmp->defresolution = layer->map->defresolution;

  outputformat = (outputFormatObj *) msSmallCalloc(1,sizeof(outputFormatObj));
  outputformat->bands = uvlinfo->band_count = 2;
  outputformat->name = NULL;
  outputformat->driver = NULL;
  outputformat->refcount = 0;
  outputformat->vtable = NULL;
  outputformat->device = NULL;
  outputformat->renderer = MS_RENDER_WITH_RAWDATA;
  outputformat->imagemode = MS_IMAGEMODE_FLOAT32;
  msAppendOutputFormat(map_tmp, outputformat);
  
  msCopyHashTable(&map_tmp->configoptions, &layer->map->configoptions);
  map_tmp->mappath = msStrdup(layer->map->mappath);
  map_tmp->shapepath = msStrdup(layer->map->shapepath);
  map_tmp->extent.minx = rect.minx-(0.5*map_cellsize)+(0.5*map_tmp->cellsize);
  map_tmp->extent.miny = rect.miny-(0.5*map_cellsize)+(0.5*map_tmp->cellsize);
  map_tmp->extent.maxx = map_tmp->extent.minx+((width-1)*map_tmp->cellsize);
  map_tmp->extent.maxy = map_tmp->extent.miny+((height-1)*map_tmp->cellsize);
  map_tmp->gt.rotation_angle = 0.0;

   msCopyProjection(&map_tmp->projection, &layer->projection);

  if (layer->debug == 5)
    msDebug("msUVRASTERLayerWhichShapes(): extent: %g %g %g %g\n",
            map_tmp->extent.minx, map_tmp->extent.miny,
            map_tmp->extent.maxx, map_tmp->extent.maxy);

  /* important to use that function, to compute map
     geotransform, used by the resampling*/
   msMapSetSize(map_tmp, width, height);

  if (layer->debug == 5)
    msDebug("msUVRASTERLayerWhichShapes(): geotransform: %g %g %g %g %g %g\n",
            map_tmp->gt.geotransform[0], map_tmp->gt.geotransform[1],
            map_tmp->gt.geotransform[2], map_tmp->gt.geotransform[3],
            map_tmp->gt.geotransform[4], map_tmp->gt.geotransform[5]);

  uvlinfo->extent = map_tmp->extent;

  image_tmp = msImageCreate(width, height, map_tmp->outputformatlist[0],
                            NULL, NULL, map_tmp->resolution, map_tmp->defresolution,
                            &(map_tmp->imagecolor));

  /* Default set to AVERAGE resampling */
  if( CSLFetchNameValue( layer->processing, "RESAMPLE" ) == NULL ) {
    alteredProcessing = CSLDuplicate( layer->processing );
    alteredProcessing =
      CSLSetNameValue( alteredProcessing, "RESAMPLE",
                       "AVERAGE");
    savedProcessing = layer->processing;
    layer->processing = alteredProcessing;
  }

  /* disable masking at this level: we don't want to apply the mask at the raster level,
   * it will be applied with the correct cellsize and image size in the vector rendering
   * phase.
   */
  saved_layer_mask = layer->mask;
  layer->mask = NULL;
  if (msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL ) == MS_FAILURE) {
    msSetError(MS_MISCERR, "Unable to draw raster data.", "msUVRASTERLayerWhichShapes()");
    layer->mask = saved_layer_mask;
    return MS_FAILURE;
  }

  /* restore layer mask */
  layer->mask = saved_layer_mask;

  /* restore the saved processing */
  if (alteredProcessing != NULL) {
    layer->processing = savedProcessing;
    CSLDestroy(alteredProcessing);
  }

  /* free old query arrays */
  if (uvlinfo->u) {
    for (i=0; i<uvlinfo->width; ++i) {
      free(uvlinfo->u[i]);
    }
    free(uvlinfo->u);
  }

  if (uvlinfo->v) {
    for (i=0; i<uvlinfo->height; ++i) {
      free(uvlinfo->v[i]);
    }
    free(uvlinfo->v);
  }

  /* Update our uv layer structure */
  uvlinfo->width = width;
  uvlinfo->height = height;
  uvlinfo->query_results = width*height;

  uvlinfo->u = (float **)msSmallMalloc(sizeof(float *)*width);
  uvlinfo->v = (float **)msSmallMalloc(sizeof(float *)*width);

  for (x = 0; x < width; ++x) {
    uvlinfo->u[x] = (float *)msSmallMalloc(height * sizeof(float));
    uvlinfo->v[x] = (float *)msSmallMalloc(height * sizeof(float));

    for (y = 0; y < height; ++y) {
      u_src_off = v_src_off = x + y * width;
      v_src_off += width*height;

      uvlinfo->u[x][y] = image_tmp->img.raw_float[u_src_off];
      uvlinfo->v[x][y] = image_tmp->img.raw_float[v_src_off];

      /* null vector? update the number of results  */
      if (uvlinfo->u[x][y] == 0 && uvlinfo->v[x][y] == 0)
        --uvlinfo->query_results;
    }
  }

  msFreeImage(image_tmp); /* we do not need the imageObj anymore */
  msFreeMap(map_tmp);

  uvlinfo->next_shape = 0;

  return MS_SUCCESS;
}
Exemple #22
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;
}
Exemple #23
0
static int 
msProjectRectAsPolygon(projectionObj *in, projectionObj *out, 
                       rectObj *rect) 
{
#ifdef USE_PROJ
  shapeObj polygonObj;
  lineObj  ring;
//  pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4];
  pointObj *ringPoints;
  int     ix, iy;

  double dx, dy;

  ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*4+4);
  ring.point = ringPoints;
  ring.numpoints = 0;

  msInitShape( &polygonObj );
  polygonObj.type = MS_SHAPE_POLYGON;

/* -------------------------------------------------------------------- */
/*      Build polygon as steps around the source rectangle.             */
/* -------------------------------------------------------------------- */
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;

  /* sample along top */
  if(dx != 0) {
    for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
    {
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
      ringPoints[ring.numpoints++].y = rect->miny;
    }
  }

  /* sample on along right side */
  if(dy != 0) {
    for(iy = 1; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
    {
      ringPoints[ring.numpoints].x = rect->maxx;
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
    }
  }

  /* sample along bottom */
  if(dx != 0) {
    for(ix = NUMBER_OF_SAMPLE_POINTS-1; ix >= 0; ix-- )
    {
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
      ringPoints[ring.numpoints++].y = rect->maxy;
    }
  }

  /* sample on along left side */
  if(dy != 0) {
    for(iy = NUMBER_OF_SAMPLE_POINTS-1; iy >= 0; iy-- )
    {
      ringPoints[ring.numpoints].x = rect->minx;
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
    }
  }

  msAddLineDirectly( &polygonObj, &ring );

/* -------------------------------------------------------------------- */
/*      Attempt to reproject.                                           */
/* -------------------------------------------------------------------- */
  msProjectShapeLine( in, out, &polygonObj, 0 );

  /* If no points reprojected, try a grid sampling */
  if( polygonObj.numlines == 0 || polygonObj.line[0].numpoints == 0 )
  {
      msFreeShape( &polygonObj );
      return msProjectRectGrid( in, out, rect );
  }

/* -------------------------------------------------------------------- */
/*      Collect bounds.                                                 */
/* -------------------------------------------------------------------- */
  rect->minx = rect->maxx = polygonObj.line[0].point[0].x;
  rect->miny = rect->maxy = polygonObj.line[0].point[0].y;
  
  for( ix = 1; ix < polygonObj.line[0].numpoints; ix++ )
  {
      pointObj  *pnt = polygonObj.line[0].point + ix;

      rect->minx = MS_MIN(rect->minx,pnt->x);
      rect->maxx = MS_MAX(rect->maxx,pnt->x);
      rect->miny = MS_MIN(rect->miny,pnt->y);
      rect->maxy = MS_MAX(rect->maxy,pnt->y);
  }

  msFreeShape( &polygonObj );

/* -------------------------------------------------------------------- */
/*      Special case to handle reprojection from "more than the         */
/*      whole world" projected coordinates that sometimes produce a     */
/*      region greater than 360 degrees wide due to various wrapping    */
/*      logic.                                                          */
/* -------------------------------------------------------------------- */
  if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj) 
      && rect->maxx - rect->minx > 360.0 )
  {
      rect->maxx = 180;
      rect->minx = -180;
  }

  return MS_SUCCESS;
#else
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
  return(MS_FAILURE);
#endif
}
Exemple #24
0
/*
 * RFC48 implementation:
 *  - transform the original shapeobj
 *  - use the styleObj to render the transformed shapeobj
 */
int msDrawTransformedShape(mapObj *map, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor)
{
  int type = style->_geomtransform.type;
  int i,j,status = MS_SUCCESS;
  switch(type) {
    case MS_GEOMTRANSFORM_END: /*render point on last vertex only*/
      for(j=0; j<shape->numlines; j++) {
        lineObj *line = &(shape->line[j]);
        pointObj *p = &(line->point[line->numpoints-1]);
        if(p->x<0||p->x>image->width||p->y<0||p->y>image->height)
          continue;
        if(style->autoangle==MS_TRUE && line->numpoints>1) {
          style->angle = calcOrientation(&(line->point[line->numpoints-2]),p);
        }
        status = msDrawMarkerSymbol(map,image,p,style,scalefactor);
      }
      break;
    case MS_GEOMTRANSFORM_START: /*render point on first vertex only*/
      for(j=0; j<shape->numlines; j++) {
        lineObj *line = &(shape->line[j]);
        pointObj *p = &(line->point[0]);
        /*skip if outside image*/
        if(p->x<0||p->x>image->width||p->y<0||p->y>image->height)
          continue;
        if(style->autoangle==MS_TRUE && line->numpoints>1) {
          style->angle = calcOrientation(p,&(line->point[1]));
        }
        status = msDrawMarkerSymbol(map,image,p,style,scalefactor);
      }
      break;
    case MS_GEOMTRANSFORM_VERTICES:
      for(j=0; j<shape->numlines; j++) {
        lineObj *line = &(shape->line[j]);
        for(i=1; i<line->numpoints-1; i++) {
          pointObj *p = &(line->point[i]);
          /*skip points outside image*/
          if(p->x<0||p->x>image->width||p->y<0||p->y>image->height)
            continue;
          if(style->autoangle==MS_TRUE) {
            style->angle = calcMidAngle(&(line->point[i-1]),&(line->point[i]),&(line->point[i+1]));
          }
          status = msDrawMarkerSymbol(map,image,p,style,scalefactor);
        }
      }
      break;
    case MS_GEOMTRANSFORM_BBOX: {
      shapeObj bbox;
      lineObj bbox_line;
      pointObj bbox_points[5];
      int padding = MS_MAX(style->width,style->size)+3; /* so clipped shape does not extent into image */

      /*create a shapeObj representing the bounding box (clipped by the image size)*/
      bbox.numlines = 1;
      bbox.line = &bbox_line;
      bbox.line->numpoints = 5;
      bbox.line->point = bbox_points;

      msComputeBounds(shape);
      bbox_points[0].x=bbox_points[4].x=bbox_points[1].x =
                                          (shape->bounds.minx < -padding) ? -padding : shape->bounds.minx;
      bbox_points[2].x=bbox_points[3].x =
                         (shape->bounds.maxx > image->width+padding) ? image->width+padding : shape->bounds.maxx;
      bbox_points[0].y=bbox_points[4].y=bbox_points[3].y =
                                          (shape->bounds.miny < -padding) ? -padding : shape->bounds.miny;
      bbox_points[1].y=bbox_points[2].y =
                         (shape->bounds.maxy > image->height+padding) ? image->height+padding : shape->bounds.maxy;
      status = msDrawShadeSymbol(map, image, &bbox, style, scalefactor);
    }
    break;
    case MS_GEOMTRANSFORM_CENTROID: {
      double unused; /*used by centroid function*/
      pointObj centroid;
      if(MS_SUCCESS == msGetPolygonCentroid(shape,&centroid,&unused,&unused)) {
        status = msDrawMarkerSymbol(map,image,&centroid,style,scalefactor);
      }
    }
    break;
    case MS_GEOMTRANSFORM_EXPRESSION: {
      int status;
      shapeObj *tmpshp;
      parseObj p;

      p.shape = shape; /* set a few parser globals (hence the lock) */
      p.expr = &(style->_geomtransform);

      if(p.expr->tokens == NULL) { /* this could happen if drawing originates from legend code (#5193) */
        status = msTokenizeExpression(p.expr, NULL, NULL);
        if(status != MS_SUCCESS) {
          msSetError(MS_MISCERR, "Unable to tokenize expression.", "msDrawTransformedShape()");
          return MS_FAILURE;
        }
      }

      p.expr->curtoken = p.expr->tokens; /* reset */
      p.type = MS_PARSE_TYPE_SHAPE;

      status = yyparse(&p);
      if (status != 0) {
        msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msDrawTransformedShape", style->_geomtransform.string);
        return MS_FAILURE;
      }
      tmpshp = p.result.shpval;

      switch (tmpshp->type) {
        case MS_SHAPE_POINT:
        case MS_SHAPE_POLYGON:        
          status = msDrawShadeSymbol(map, image, tmpshp, style, scalefactor);
          break;
        case MS_SHAPE_LINE:
          status = msDrawLineSymbol(map, image, tmpshp, style, scalefactor);
          break;
      }

      msFreeShape(tmpshp);
      msFree(tmpshp);
    }
    break;
    case MS_GEOMTRANSFORM_LABELPOINT:
    case MS_GEOMTRANSFORM_LABELPOLY:
      break;
    default:
      msSetError(MS_MISCERR, "unknown geomtransform", "msDrawTransformedShape()");
      return MS_FAILURE;
  }
  return status;
}
Exemple #25
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
}
Exemple #26
0
int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char *font, double size, char *text, rectObj *rect, double **advances) {
    
    
    cairoCacheData *cache = MS_RENDERER_CACHE(renderer);
    faceCacheObj *face = getFontFace(cache,font);
 
    char *utfptr=text;
    int i,has_kerning,unicode;
    unsigned long previdx=0;
    int numglyphs = msGetNumGlyphs(text);
    cairo_glyph_t glyph;
    cairo_text_extents_t extents;
    double px=0,py=0;

    if(face == NULL) {
        return MS_FAILURE;
    }

    cairo_set_font_face(cache->dummycr,face->face);
    cairo_set_font_size(cache->dummycr,size*96/72.0);

    has_kerning = FT_HAS_KERNING((face->ftface));

    if(advances != NULL) {
        *advances = (double*)malloc(numglyphs*sizeof(double));
    }

    for(i=0;i<numglyphs;i++) {
        utfptr+=msUTF8ToUniChar(utfptr, &unicode);
        glyph.x=px;
        glyph.y=py;
        if(unicode=='\n') {
            py += ceil(size*CAIROLINESPACE);
            px = 0;
            previdx=0;
            continue;
        }
        glyph.index = FT_Get_Char_Index(face->ftface, unicode);
        if( has_kerning && previdx ) {
            FT_Vector delta;
            FT_Get_Kerning( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta );
            px += delta.x / 64.;
        }
        cairo_glyph_extents(cache->dummycr,&glyph,1,&extents);
        
        if(i==0) {
            rect->minx = px+extents.x_bearing;
            rect->miny = py+extents.y_bearing;
            rect->maxx = px+extents.x_bearing+extents.width;
            rect->maxy = py+extents.y_bearing+extents.height;
        } else {
            rect->minx = MS_MIN(rect->minx,px+extents.x_bearing);
            rect->miny = MS_MIN(rect->miny,py+extents.y_bearing);
            rect->maxy = MS_MAX(rect->maxy,py+extents.y_bearing+extents.height);
            rect->maxx = MS_MAX(rect->maxx,px+extents.x_bearing+extents.width);
        }
        if(advances!=NULL)
            (*advances)[i]=extents.x_advance;
        px += extents.x_advance;
        previdx=glyph.index;
    }
    /*
    rect->minx = 0;
    rect->miny = 0;
    rect->maxx = 1;
    rect->maxy = 1;
    */
    return MS_SUCCESS;
}
Exemple #27
0
static int
msProjectRectAsPolygon(projectionObj *in, projectionObj *out,
                       rectObj *rect)
{
#ifdef USE_PROJ
  shapeObj polygonObj;
  lineObj  ring;
  /*  pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4]; */
  pointObj *ringPoints;
  int     ix, iy;

  double dx, dy;

  /* If projecting from longlat to projected */
  if( out && !pj_is_latlong(out->proj) && in && pj_is_latlong(in->proj) &&
      fabs(rect->minx - -180.0) < 1e-5 && fabs(rect->miny - -90.0) < 1e-5 &&
      fabs(rect->maxx - 180.0) < 1e-5 && fabs(rect->maxy - 90.0) < 1e-5) {
    rect->minx = -1e15;
    rect->miny = -1e15;
    rect->maxx = 1e15;
    rect->maxy = 1e15;
    return MS_SUCCESS;
  }

  /* -------------------------------------------------------------------- */
  /*      Build polygon as steps around the source rectangle.             */
  /* -------------------------------------------------------------------- */
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;

  if(dx==0 && dy==0) {
    pointObj foo;
    msDebug( "msProjectRect(): Warning: degenerate rect {%f,%f,%f,%f}\n",rect->minx,rect->miny,rect->minx,rect->miny );
    foo.x = rect->minx;
    foo.y = rect->miny;
    msProjectPoint(in,out,&foo);
    rect->minx=rect->maxx=foo.x;
    rect->miny=rect->maxy=foo.y;
    return MS_SUCCESS;
  }
  
  ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*4+4);
  ring.point = ringPoints;
  ring.numpoints = 0;

  msInitShape( &polygonObj );
  polygonObj.type = MS_SHAPE_POLYGON;

  /* sample along top */
  if(dx != 0) {
    for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) {
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
      ringPoints[ring.numpoints++].y = rect->miny;
    }
  }

  /* sample on along right side */
  if(dy != 0) {
    for(iy = 1; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) {
      ringPoints[ring.numpoints].x = rect->maxx;
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
    }
  }

  /* sample along bottom */
  if(dx != 0) {
    for(ix = NUMBER_OF_SAMPLE_POINTS-1; ix >= 0; ix-- ) {
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
      ringPoints[ring.numpoints++].y = rect->maxy;
    }
  }

  /* sample on along left side */
  if(dy != 0) {
    for(iy = NUMBER_OF_SAMPLE_POINTS-1; iy >= 0; iy-- ) {
      ringPoints[ring.numpoints].x = rect->minx;
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
    }
  }

  msAddLineDirectly( &polygonObj, &ring );

#ifdef notdef
  FILE *wkt = fopen("/tmp/www-before.wkt","w");
  char *tmp = msShapeToWKT(&polygonObj);
  fprintf(wkt,"%s\n", tmp);
  free(tmp);
  fclose(wkt);
#endif

  /* -------------------------------------------------------------------- */
  /*      Attempt to reproject.                                           */
  /* -------------------------------------------------------------------- */
  msProjectShapeLine( in, out, &polygonObj, 0 );

  /* If no points reprojected, try a grid sampling */
  if( polygonObj.numlines == 0 || polygonObj.line[0].numpoints == 0 ) {
    msFreeShape( &polygonObj );
    return msProjectRectGrid( in, out, rect );
  }

#ifdef notdef
  wkt = fopen("/tmp/www-after.wkt","w");
  tmp = msShapeToWKT(&polygonObj);
  fprintf(wkt,"%s\n", tmp);
  free(tmp);
  fclose(wkt);
#endif

  /* -------------------------------------------------------------------- */
  /*      Collect bounds.                                                 */
  /* -------------------------------------------------------------------- */
  rect->minx = rect->maxx = polygonObj.line[0].point[0].x;
  rect->miny = rect->maxy = polygonObj.line[0].point[0].y;

  for( ix = 1; ix < polygonObj.line[0].numpoints; ix++ ) {
    pointObj  *pnt = polygonObj.line[0].point + ix;

    rect->minx = MS_MIN(rect->minx,pnt->x);
    rect->maxx = MS_MAX(rect->maxx,pnt->x);
    rect->miny = MS_MIN(rect->miny,pnt->y);
    rect->maxy = MS_MAX(rect->maxy,pnt->y);
  }

  msFreeShape( &polygonObj );

  /* -------------------------------------------------------------------- */
  /*      Special case to handle reprojection from "more than the         */
  /*      whole world" projected coordinates that sometimes produce a     */
  /*      region greater than 360 degrees wide due to various wrapping    */
  /*      logic.                                                          */
  /* -------------------------------------------------------------------- */
  if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj)
      && rect->maxx - rect->minx > 360.0 ) {
    rect->maxx = 180;
    rect->minx = -180;
  }

  return MS_SUCCESS;
#else
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
  return(MS_FAILURE);
#endif
}
Exemple #28
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;
}
Exemple #29
0
int msDrawLineSymbol(mapObj *map, imageObj *image, shapeObj *p,
                     styleObj *style, double scalefactor)
{
  int status = MS_SUCCESS;
  if (image) {
    if (MS_RENDERER_PLUGIN(image->format)) {
      rendererVTableObj *renderer = image->format->vtable;
      symbolObj *symbol;
      shapeObj *offsetLine = p;
      int i;
      double width;
      double finalscalefactor;

      if (p->numlines == 0)
        return MS_SUCCESS;

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

      symbol = map->symbolset.symbol[style->symbol];
      /* store a reference to the renderer to be used for freeing */
      symbol->renderer = renderer;

      width = style->width * scalefactor;
      width = MS_MIN(width,style->maxwidth*image->resolutionfactor);
      width = MS_MAX(width,style->minwidth*image->resolutionfactor);
      if(style->width != 0) {
        finalscalefactor = width / style->width;
      } else {
        finalscalefactor = 1.0;
      }

      if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) {
        offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_SINGLE_SIDED_OFFSET);
      } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) {
        offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET);
      } else if(style->offsetx!=0 || style->offsety!=0) {
        offsetLine = msOffsetPolyline(p, style->offsetx * finalscalefactor,
                                      style->offsety * finalscalefactor);
      }
      if(style->symbol == 0 || (symbol->type==MS_SYMBOL_SIMPLE)) {
        strokeStyleObj s;
        s.linecap = style->linecap;
        s.linejoin = style->linejoin;
        s.linejoinmaxsize = style->linejoinmaxsize;
        s.width = width;
        s.patternlength = style->patternlength;
        for(i=0; i<s.patternlength; i++)
          s.pattern[i] = style->pattern[i] * finalscalefactor;
        s.patternoffset = (style->initialgap<=0) ? 0 : (style->initialgap * finalscalefactor);

        if(MS_VALID_COLOR(style->color))
          s.color = &style->color;
        else if(MS_VALID_COLOR(style->outlinecolor))
          s.color = &style->outlinecolor;
        else {
          /* msSetError(MS_MISCERR,"no color defined for line styling","msDrawLineSymbol()");
           * not really an error */
          status = MS_SUCCESS;
          goto draw_line_cleanup;
        }
        status = renderer->renderLine(image,offsetLine,&s);
      } else {
        symbolStyleObj s;
        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;

        /* compute a markerStyle and use it on the line */
        if(style->gap<0) {
          /* special function that treats any other symbol used as a marker, not a brush */
          status = msImagePolylineMarkers(image,offsetLine,symbol,&s,-s.gap,
                                 style->initialgap * finalscalefactor, 1);
        } else if(style->gap>0) {
          status = msImagePolylineMarkers(image,offsetLine,symbol,&s,s.gap,
                                 style->initialgap * finalscalefactor,0);
        } else {
          if(renderer->renderLineTiled != NULL) {
            int pw,ph;
            imageObj* tile=NULL;
            if(s.scale != 1) {
              pw = MS_NINT(symbol->sizex * s.scale);
              ph = MS_NINT(symbol->sizey * s.scale);
            } else {
              pw = symbol->sizex;
              ph = symbol->sizey;
            }
            if(pw<1) pw=1;
            if(ph<1) ph=1;
            tile = getTile(image, symbol,&s,pw,ph,0);
            status = renderer->renderLineTiled(image, offsetLine, tile);
          } else {
            msSetError(MS_RENDERERERR, "renderer does not support brushed lines", "msDrawLineSymbol()");
            status = MS_FAILURE;
          }
        }
      }

draw_line_cleanup:
      if(offsetLine!=p) {
        msFreeShape(offsetLine);
        msFree(offsetLine);
      }
    } else if( MS_RENDERER_IMAGEMAP(image->format) )
      msDrawLineSymbolIM(map, image, p, style, scalefactor);
    else {
      msSetError(MS_RENDERERERR, "unsupported renderer", "msDrawShadeSymbol()");
      status = MS_FAILURE;
    }
  } else {
    status = MS_FAILURE;
  }
  return status;
}
Exemple #30
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;
}