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; }
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 msImageSetPenGD(gdImagePtr img, colorObj *color) { if(MS_VALID_COLOR(*color)) color->pen = gdImageColorResolve(img, color->red, color->green, color->blue); else color->pen = -1; return(MS_SUCCESS); }
/* ** GD driver-specific image handling functions. */ imageObj *createImageGD(int width, int height, outputFormatObj *format, colorObj* bg) { imageObj *img = NULL; gdImagePtr ip; img = (imageObj *) calloc(1, sizeof (imageObj)); MS_CHECK_ALLOC(img, sizeof (imageObj), NULL); /* we're only doing PC256 for the moment */ ip = gdImageCreate(width, height); if(bg && MS_VALID_COLOR(*bg)) { gdImageColorAllocate(ip, bg->red, bg->green, bg->blue); /* set the background color */ } else { gdImageColorAllocate(ip,117,17,91); /*random bg color (same one as picked in msResampleGDALToMap) */ } if(format->transparent || !bg || !MS_VALID_COLOR(*bg)) { gdImageColorTransparent(ip, 0); } img->img.plugin = (void *) ip; return img; }
int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbolObj *ts) { rendererVTableObj *renderer = image->format->vtable; colorObj *c = NULL, *oc = NULL; int ow; assert(ts->textpath); if(!ts->textpath->absolute) { int g; double cosa,sina; double x = labelPnt.x; double y = labelPnt.y; if(ts->rotation != 0) { cosa = cos(ts->rotation); sina = sin(ts->rotation); for(g=0;g<ts->textpath->numglyphs;g++) { double ox = ts->textpath->glyphs[g].pnt.x; double oy = ts->textpath->glyphs[g].pnt.y; ts->textpath->glyphs[g].pnt.x = ox * cosa + oy * sina + x; ts->textpath->glyphs[g].pnt.y = -ox * sina + oy * cosa + y; ts->textpath->glyphs[g].rot = ts->rotation; } } else { for(g=0;g<ts->textpath->numglyphs;g++) { ts->textpath->glyphs[g].pnt.x += x; ts->textpath->glyphs[g].pnt.y += y; } } } if(MS_VALID_COLOR(ts->label->color)) c = &ts->label->color; if(MS_VALID_COLOR(ts->label->outlinecolor)) oc = &ts->label->outlinecolor; ow = ts->label->outlinewidth * ts->scalefactor; if(!renderer->renderGlyphs) return MS_FAILURE; return renderer->renderGlyphs(image,ts->textpath,c,oc,ow); }
/* * generic function for drawing a legend icon. (added for bug #2348) * renderer specific drawing functions shouldn't be called directly, but through * this function */ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, int width, int height, imageObj *image, int dstX, int dstY) { int i, type, hasmarkersymbol; double offset; shapeObj box, zigzag; pointObj marker; char szPath[MS_MAXPATHLEN]; styleObj outline_style; imageObj *image_draw = image; int originalopacity = lp->opacity; rendererVTableObj *renderer; outputFormatObj *transFormat = NULL, *altFormat=NULL; const char *alternativeFormatString = NULL; if(!MS_RENDERER_PLUGIN(image->format)) { msSetError(MS_MISCERR,"unsupported image format","msDrawLegendIcon()"); return MS_FAILURE; } alternativeFormatString = msLayerGetProcessingKey(lp, "RENDERER"); if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFormatString!=NULL && (altFormat= msSelectOutputFormat(map, alternativeFormatString))) { msInitializeRendererVTable(altFormat); image_draw = msImageCreate(image->width, image->height, altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor); renderer = MS_IMAGE_RENDERER(image_draw); } else { renderer = MS_IMAGE_RENDERER(image_draw); if (lp->opacity > 0 && lp->opacity < 100) { if (!renderer->supports_transparent_layers) { image_draw = msImageCreate(image->width, image->height, image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!image_draw) { msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.", "msDrawLegendIcon()"); return (MS_FAILURE); } /* set opacity to full, as the renderer should be rendering a fully opaque image */ lp->opacity=100; } } } if(renderer->supports_clipping && MS_VALID_COLOR(map->legend.outlinecolor)) { /* keep GD specific code here for now as it supports clipping */ rectObj clip; clip.maxx = dstX + width - 1; clip.maxy = dstY + height -1; clip.minx = dstX; clip.miny = dstY; renderer->setClip(image_draw,clip); } /* initialize the box used for polygons and for outlines */ box.line = (lineObj *)msSmallMalloc(sizeof(lineObj)); box.numlines = 1; box.line[0].point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5); box.line[0].numpoints = 5; box.line[0].point[0].x = dstX + 0.5; box.line[0].point[0].y = dstY + 0.5; box.line[0].point[1].x = dstX + width - 0.5; box.line[0].point[1].y = dstY + 0.5; box.line[0].point[2].x = dstX + width - 0.5; box.line[0].point[2].y = dstY + height - 0.5; box.line[0].point[3].x = dstX + 0.5; box.line[0].point[3].y = dstY + height - 0.5; box.line[0].point[4].x = box.line[0].point[0].x; box.line[0].point[4].y = box.line[0].point[0].y; box.line[0].numpoints = 5; /* if the class has a keyimage, treat it as a point layer * (the keyimage will be treated there) */ if(theclass->keyimage != NULL) { type = MS_LAYER_POINT; } else { /* some polygon layers may be better drawn using zigzag if there is no fill */ type = lp->type; if(type == MS_LAYER_POLYGON) { type = MS_LAYER_LINE; for(i=0; i<theclass->numstyles; i++) { if(MS_VALID_COLOR(theclass->styles[i]->color)) { /* there is a fill */ type = MS_LAYER_POLYGON; break; } } } } /* ** now draw the appropriate color/symbol/size combination */ switch(type) { case MS_LAYER_ANNOTATION: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); hasmarkersymbol = 0; for(i=0; i<theclass->numstyles; i++) { if (theclass->styles[i]->symbol < map->symbolset.numsymbols && theclass->styles[i]->symbol > 0) { hasmarkersymbol = 1; break; } } if (hasmarkersymbol) { for(i=0; i<theclass->numstyles; i++) msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor); } else if (theclass->labels && theclass->numlabels > 0) { labelObj *label = theclass->labels[0]; /* use the first label definition */ double lsize = label->size; double langle = label->angle; int lpos = label->position; int loffsetx = label->offsetx; int loffsety = label->offsety; label->offsetx = 0; label->offsety = 0; label->angle = 0; label->position = MS_CC; if (label->type == MS_TRUETYPE) label->size = height; msDrawLabel(map, image_draw, marker, (char*)"Az", label,1.0); label->size = lsize; label->position = lpos; label->angle = langle; label->offsetx = loffsetx; label->offsety = loffsety; } break; case MS_LAYER_POINT: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); if(theclass->keyimage != NULL) { int symbolNum; styleObj imgStyle; symbolObj *symbol=NULL; symbolNum = msAddImageSymbol(&(map->symbolset), msBuildPath(szPath, map->mappath, theclass->keyimage)); if(symbolNum == -1) { msSetError(MS_GDERR, "Failed to open legend key image", "msCreateLegendIcon()"); return(MS_FAILURE); } symbol = map->symbolset.symbol[symbolNum]; initStyle(&imgStyle); /*set size so that symbol will be scaled properly #3296*/ if (width/symbol->sizex < height/symbol->sizey) imgStyle.size = symbol->sizey*(width/symbol->sizex); else imgStyle.size = symbol->sizey*(height/symbol->sizey); if (imgStyle.size > imgStyle.maxsize) imgStyle.maxsize = imgStyle.size; imgStyle.symbol = symbolNum; msDrawMarkerSymbol(&map->symbolset,image_draw,&marker,&imgStyle,lp->scalefactor); /* TO DO: we may want to handle this differently depending on the relative size of the keyimage */ } else { for(i=0; i<theclass->numstyles; i++) msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor); } break; case MS_LAYER_LINE: offset = 1; /* To set the offset, we only check the size/width parameter of the first style */ if (theclass->numstyles > 0) { if (theclass->styles[0]->symbol > 0 && theclass->styles[0]->symbol < map->symbolset.numsymbols && map->symbolset.symbol[theclass->styles[0]->symbol]->type != MS_SYMBOL_SIMPLE) offset = theclass->styles[0]->size/2; else offset = theclass->styles[0]->width/2; } zigzag.line = (lineObj *)msSmallMalloc(sizeof(lineObj)); zigzag.numlines = 1; zigzag.line[0].point = (pointObj *)msSmallMalloc(sizeof(pointObj)*4); zigzag.line[0].numpoints = 4; zigzag.line[0].point[0].x = dstX + offset; zigzag.line[0].point[0].y = dstY + height - offset; zigzag.line[0].point[1].x = dstX + MS_NINT(width / 3.0) - 1; zigzag.line[0].point[1].y = dstY + offset; zigzag.line[0].point[2].x = dstX + MS_NINT(2.0 * width / 3.0) - 1; zigzag.line[0].point[2].y = dstY + height - offset; zigzag.line[0].point[3].x = dstX + width - offset; zigzag.line[0].point[3].y = dstY + offset; for(i=0; i<theclass->numstyles; i++) msDrawLineSymbol(&map->symbolset, image_draw, &zigzag, theclass->styles[i], lp->scalefactor); free(zigzag.line[0].point); free(zigzag.line); break; case MS_LAYER_CIRCLE: case MS_LAYER_RASTER: case MS_LAYER_CHART: case MS_LAYER_POLYGON: for(i=0; i<theclass->numstyles; i++) msDrawShadeSymbol(&map->symbolset, image_draw, &box, theclass->styles[i], lp->scalefactor); break; default: return MS_FAILURE; break; } /* end symbol drawing */ /* handle an outline if necessary */ if(MS_VALID_COLOR(map->legend.outlinecolor)) { initStyle(&outline_style); outline_style.color = map->legend.outlinecolor; msDrawLineSymbol(&map->symbolset, image_draw, &box, &outline_style, 1.0); /* reset clipping rectangle */ if(renderer->supports_clipping) renderer->resetClip(image_draw); } if (altFormat) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rendererVTableObj *altrenderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); altrenderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height); /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; i<map->symbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == altrenderer) { altrenderer->freeSymbol(s); s->renderer = NULL; } } } msFreeImage(image_draw); } else if(image != image_draw) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); lp->opacity = originalopacity; renderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height); msFreeImage(image_draw); /* deref and possibly free temporary transparent output format. */ msApplyOutputFormat( &transFormat, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } free(box.line[0].point); free(box.line); return MS_SUCCESS; }
/* 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); }
/* * 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; }
imageObj* createImageCairo(int width, int height, outputFormatObj *format,colorObj* bg) { imageObj *image = NULL; cairo_renderer *r=NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode!= MS_IMAGEMODE_RGBA) { msSetError(MS_MISCERR, "Cairo driver only supports RGB or RGBA pixel models.","msImageCreateCairo()"); return image; } if (width > 0 && height > 0) { image = (imageObj *) calloc(1, sizeof(imageObj)); r = (cairo_renderer*)calloc(1,sizeof(cairo_renderer)); if(!strcasecmp(format->driver,"cairo/pdf")) { r->outputStream = (bufferObj*)malloc(sizeof(bufferObj)); msBufferInit(r->outputStream); r->surface = cairo_pdf_surface_create_for_stream( _stream_write_fn, r->outputStream, width,height); } else if(!strcasecmp(format->driver,"cairo/svg")) { r->outputStream = (bufferObj*)malloc(sizeof(bufferObj)); msBufferInit(r->outputStream); r->surface = cairo_svg_surface_create_for_stream( _stream_write_fn, r->outputStream, width,height); } else if(!strcasecmp(format->driver,"cairo/winGDI") && format->device) { #if CAIRO_HAS_WIN32_SURFACE r->outputStream = NULL; r->surface = cairo_win32_surface_create(format->device); #else msSetError(MS_RENDERERERR, "Cannot create cairo image. Cairo was not compiled with support for the win32 backend.", "msImageCreateCairo()"); #endif } else if(!strcasecmp(format->driver,"cairo/winGDIPrint") && format->device) { #if CAIRO_HAS_WIN32_SURFACE r->outputStream = NULL; r->surface = cairo_win32_printing_surface_create(format->device); #else msSetError(MS_RENDERERERR, "Cannot create cairo image. Cairo was not compiled with support for the win32 backend.", "msImageCreateCairo()"); #endif } else { r->outputStream = NULL; r->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); } r->cr = cairo_create(r->surface); if(format->transparent || !bg || !MS_VALID_COLOR(*bg)) { r->use_alpha = 1; cairo_set_source_rgba (r->cr, 0,0,0,0); } else { r->use_alpha = 0; msCairoSetSourceColor(r->cr,bg); } cairo_save (r->cr); cairo_set_operator (r->cr, CAIRO_OPERATOR_SOURCE); cairo_paint (r->cr); cairo_restore (r->cr); cairo_set_line_cap (r->cr,CAIRO_LINE_CAP_ROUND); cairo_set_line_join(r->cr,CAIRO_LINE_JOIN_ROUND); image->img.plugin = (void*)r; } else { msSetError(MS_RENDERERERR, "Cannot create cairo image of size %dx%d.", "msImageCreateCairo()", width, height); } return image; }
void msWriteErrorImage(mapObj *map, char *filename, int blank) { imageObj *img; rendererVTableObj *renderer; int font_index = 0; int width=400, height=300; int nMargin =5; int nTextLength = 0; int nUsableWidth = 0; int nMaxCharsPerLine = 0; int nLines = 0; int i = 0; int nStart = 0; int nEnd = 0; int nLength = 0; char **papszLines = NULL; int nXPos = 0; int nYPos = 0; int nWidthTxt = 0; outputFormatObj *format = NULL; char *errormsg = msGetErrorString("; "); fontMetrics *font = NULL; char *imagepath = NULL, *imageurl = NULL; labelStyleObj ls; colorObj labelcolor, labeloutlinecolor, imagecolor, *imagecolorptr=NULL; ls.color = &labelcolor; ls.outlinecolor = &labeloutlinecolor; if (map) { if( map->width > 0 && map->height > 0 ) { width = map->width; height = map->height; } format = map->outputformat; imagepath = map->web.imagepath; imageurl = map->web.imageurl; } /* Default to GIF if no suitable GD output format set */ if (format == NULL || !MS_RENDERER_PLUGIN(format) || !format->vtable->supports_bitmap_fonts) format = msCreateDefaultOutputFormat( NULL, "GD/PC256", "gif" ); if(!format->transparent) { if(map && MS_VALID_COLOR(map->imagecolor)) { imagecolorptr = &map->imagecolor; } else { MS_INIT_COLOR(imagecolor,255,255,255,255); imagecolorptr = &imagecolor; } } img = msImageCreate(width,height,format,imagepath,imageurl,MS_DEFAULT_RESOLUTION,MS_DEFAULT_RESOLUTION,imagecolorptr); renderer = MS_IMAGE_RENDERER(img); for(i=0; i<5; i++) { /* use the first font we find */ if((font = renderer->bitmapFontMetrics[font_index]) != NULL) { ls.size = i; MS_INIT_COLOR(*ls.color,0,0,0,255); MS_INIT_COLOR(*ls.outlinecolor,255,255,255,255); break; } } /* if no font found we can't do much. this shouldn't happen */ if(font) { nTextLength = strlen(errormsg); nWidthTxt = nTextLength * font->charWidth; nUsableWidth = width - (nMargin*2); /* Check to see if it all fits on one line. If not, split the text on several lines. */ if(!blank) { if (nWidthTxt > nUsableWidth) { nMaxCharsPerLine = nUsableWidth/font->charWidth; nLines = (int) ceil ((double)nTextLength / (double)nMaxCharsPerLine); if (nLines > 0) { papszLines = (char **)malloc(nLines*sizeof(char *)); for (i=0; i<nLines; i++) { papszLines[i] = (char *)malloc((nMaxCharsPerLine+1)*sizeof(char)); papszLines[i][0] = '\0'; } } for (i=0; i<nLines; i++) { nStart = i*nMaxCharsPerLine; nEnd = nStart + nMaxCharsPerLine; if (nStart < nTextLength) { if (nEnd > nTextLength) nEnd = nTextLength; nLength = nEnd-nStart; strncpy(papszLines[i], errormsg+nStart, nLength); papszLines[i][nLength] = '\0'; } } } else { nLines = 1; papszLines = (char **)malloc(nLines*sizeof(char *)); papszLines[0] = msStrdup(errormsg); } for (i=0; i<nLines; i++) { nYPos = (font->charHeight) * ((i*2) +1); nXPos = font->charWidth;; renderer->renderBitmapGlyphs(img, nXPos, nYPos, &ls, papszLines[i]); } if (papszLines) { for (i=0; i<nLines; i++) { free(papszLines[i]); } free(papszLines); } } } /* actually write the image */ if(!filename) { msIO_setHeader("Content-type","%s", MS_IMAGE_MIME_TYPE(format)); msIO_sendHeaders(); } msSaveImage(NULL,img,filename); msFreeImage(img); if (format->refcount == 0) msFreeOutputFormat(format); msFree(errormsg); }
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; }
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; }