Ejemplo n.º 1
0
bool OglContext::createPBuffer(ms_uint32 width, ms_uint32 height)
{
  int maxHeight, maxWidth;

  glXGetFBConfigAttrib(window, *configs, GLX_MAX_PBUFFER_WIDTH, &maxWidth);
  glXGetFBConfigAttrib(window, *configs, GLX_MAX_PBUFFER_HEIGHT, &maxHeight);

  ms_uint32 uMaxHeight = maxHeight, uMaxWidth = maxWidth;

  this->width = MS_MIN(width, uMaxWidth);
  this->height = MS_MIN(height, uMaxHeight);

  int iPbufferAttributes[] = {
    GLX_PBUFFER_WIDTH, this->width,
    GLX_PBUFFER_HEIGHT, this->height,
    GLX_LARGEST_PBUFFER, false,
    0, 0
  };

  pbuffer = glXCreatePbuffer(window, *configs, iPbufferAttributes);
  if (pbuffer == 0) {
    msSetError(MS_OGLERR, "glXCreatePbuffer failed. glError: %d", "OglContext::init()", glGetError());
    return false;
  }

  return true;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
int msQuantizeRasterBuffer(rgbaPixel *pixelsIn,int height,int width,
      unsigned int *reqcolors, rgbaPixel *palette,
      unsigned int *palette_scaling_maxval) 
{
    register rgbaPixel *pP;
    register int col;
    unsigned char newmaxval;
    acolorhist_vector achv, acolormap=NULL;
    int row;
    int colors;
    int newcolors = 0;
    int x;
    *palette_scaling_maxval = 255;
    int row_step = width*4;

    rgbaPixel **apixels=(rgbaPixel**)malloc(height*sizeof(rgbaPixel**));
    
    for(row=0;row<height;row++) {
        apixels[row]=(rgbaPixel*)(&(pixelsIn[row*width]));
    }

    /*
     ** Step 2: attempt to make a histogram of the colors, unclustered.
     ** If at first we don't succeed, lower maxval to increase color
     ** coherence and try again.  This will eventually terminate, with
     ** maxval at worst 15, since 32^3 is approximately MAXCOLORS.
                  [GRR POSSIBLE BUG:  what about 32^4 ?]
     */
    for ( ; ; ) {
        achv = pam_computeacolorhist(
                apixels, width, height, MAXCOLORS, &colors );
        if ( achv != (acolorhist_vector) 0 )
            break;
        newmaxval = *palette_scaling_maxval / 2;
        for ( row = 0; row < height; ++row )
            for ( col = 0, pP = apixels[row]; col < width; ++col, ++pP )
                PAM_DEPTH( *pP, *pP, *palette_scaling_maxval, newmaxval );
        *palette_scaling_maxval = newmaxval;
    }
    newcolors = MS_MIN(colors, *reqcolors);
    acolormap = mediancut(achv, colors, width*height, *palette_scaling_maxval, newcolors);
    pam_freeacolorhist(achv);
    
    
    *reqcolors = newcolors;

    for (x = 0; x < newcolors; ++x) {
       palette[x].r = acolormap[x].acolor.r;
       palette[x].g = acolormap[x].acolor.g;
       palette[x].b = acolormap[x].acolor.b;
       palette[x].a = acolormap[x].acolor.a;
    }
    
   free(acolormap);
   free(apixels);
   return MS_SUCCESS;
}
Ejemplo n.º 6
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);
    }
  }
}
Ejemplo n.º 7
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)++;
}
Ejemplo n.º 8
0
double msDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b)
{
  double l; /* length of line ab */
  double r,s;

  l = msDistancePointToPoint(a,b);

  if(l == 0.0) // a = b
    return( msDistancePointToPoint(a,p));

  r = ((a->y - p->y)*(a->y - b->y) - (a->x - p->x)*(b->x - a->x))/(l*l);

  if(r > 1) /* perpendicular projection of P is on the forward extention of AB */
    return(MS_MIN(msDistancePointToPoint(p, b),msDistancePointToPoint(p, a)));
  if(r < 0) /* perpendicular projection of P is on the backward extention of AB */
    return(MS_MIN(msDistancePointToPoint(p, b),msDistancePointToPoint(p, a)));

  s = ((a->y - p->y)*(b->x - a->x) - (a->x - p->x)*(b->y - a->y))/(l*l);

  return(fabs(s*l));
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
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;
  }
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
/*
** Returns the size, in pixels, of a marker symbol defined by a specific style and scalefactor. Used for annotation
** layer collision avoidance. A marker is made up of a number of styles so the calling code must either do the looping
** itself or call this function for the bottom style which should be the largest.
*/
int msGetMarkerSize(symbolSetObj *symbolset, styleObj *style, double *width, double *height, double scalefactor)
{
  rectObj rect;
  int size;
  symbolObj *symbol;
  *width = *height = 0; /* set a starting value */

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

  if(style->symbol == 0) { /* single point */
    *width = 1;
    *height = 1;
    return(MS_SUCCESS);
  }

  symbol = symbolset->symbol[style->symbol];
  if (symbol->type == MS_SYMBOL_PIXMAP && !symbol->pixmap_buffer) {
    if (MS_SUCCESS != msPreloadImageSymbol(MS_MAP_RENDERER(symbolset->map), symbol))
      return MS_FAILURE;
  }
  if(symbol->type == MS_SYMBOL_SVG && !symbol->renderer_cache) {
#ifdef USE_SVG_CAIRO
    if(MS_SUCCESS != msPreloadSVGSymbol(symbol))
      return MS_FAILURE;
#else
    msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msGetMarkerSize()");
    return MS_FAILURE;
#endif
  }
  if(style->size == -1) {
    size = ( msSymbolGetDefaultSize(symbol) * scalefactor );
  } else
    size = (style->size*scalefactor);
  size = MS_MAX(size, style->minsize);
  size = MS_MIN(size, style->maxsize);

  switch(symbol->type) {

    case(MS_SYMBOL_TRUETYPE):
      if(msGetTruetypeTextBBox(MS_MAP_RENDERER(symbolset->map),symbol->font,symbolset->fontset,size,symbol->character,&rect,NULL,0) != MS_SUCCESS)
        return(MS_FAILURE);

      *width = MS_MAX(*width, rect.maxx - rect.minx);
      *height = MS_MAX(*height, rect.maxy - rect.miny);

      break;

    case(MS_SYMBOL_PIXMAP):
      if(size == 1) {
        *width = MS_MAX(*width, symbol->pixmap_buffer->width);
        *height = MS_MAX(*height, symbol->pixmap_buffer->height);
      } else {
        *width = MS_MAX(*width, (((double)size/(double)symbol->pixmap_buffer->height) * symbol->pixmap_buffer->width));
        *height = MS_MAX(*height, size);
      }
      break;
    default: /* vector and ellipses, scalable */
      if(style->size > 0) {
        *width = MS_MAX(*width, ((size/symbol->sizey) * symbol->sizex));
        *height = MS_MAX(*height, size);
      } else { /* use symbol defaults */
        *width = MS_MAX(*width, symbol->sizex);
        *height = MS_MAX(*height, symbol->sizey);
      }
      break;
  }

  return(MS_SUCCESS);
}
Ejemplo n.º 15
0
/*
** 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);
}
Ejemplo n.º 16
0
/**
 * Compute a palette for the given RGBA rasterBuffer using a median cut quantization.
 * - rb: the rasterBuffer to quantize
 * - reqcolors: the desired number of colors the palette should contain. will be set
 *   with the actual number of entries in the computed palette
 * - forced_palette: entries that should appear in the computed palette
 * - num_forced_palette_entries: number of entries contained in "force_palette". if 0,
 *   "force_palette" can be NULL
 * - palette_scaling_maxval: the quantization process may have to reduce the image depth
 *   by iteratively dividing the pixels by 2. In case palette_scaling_maxval is set to
 *   something different than 255, the returned palette colors have to be scaled back up to
 *   255, and rb's pixels will have been scaled down to maxsize (see bug #3848)
 */
int msQuantizeRasterBuffer(rasterBufferObj *rb,
                           unsigned int *reqcolors, rgbaPixel *palette,
                           rgbaPixel *forced_palette, int num_forced_palette_entries,
                           unsigned int *palette_scaling_maxval)
{
  rgbaPixel **apixels=NULL; /* pointer to the start rows of truecolor pixels */

  register rgbaPixel *pP;
  register int col;

  unsigned char newmaxval;
  acolorhist_vector achv, acolormap=NULL;

  int row;
  int colors;
  int newcolors = 0;

  int x;
  /*  int channels;  */

  assert(rb->type == MS_BUFFER_BYTE_RGBA);

  *palette_scaling_maxval = 255;

  apixels=(rgbaPixel**)msSmallMalloc(rb->height*sizeof(rgbaPixel*));

  for(row=0; row<rb->height; row++) {
    apixels[row]=(rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step]));
  }

  /*
   ** Step 2: attempt to make a histogram of the colors, unclustered.
   ** If at first we don't succeed, lower maxval to increase color
   ** coherence and try again.  This will eventually terminate, with
   ** maxval at worst 15, since 32^3 is approximately MAXCOLORS.
                [GRR POSSIBLE BUG:  what about 32^4 ?]
   */
  for ( ; ; ) {
    achv = pam_computeacolorhist(
             apixels, rb->width, rb->height, MAXCOLORS, &colors );
    if ( achv != (acolorhist_vector) 0 )
      break;
    newmaxval = *palette_scaling_maxval / 2;
    for ( row = 0; row < rb->height; ++row )
      for ( col = 0, pP = apixels[row]; col < rb->width; ++col, ++pP )
        PAM_DEPTH( *pP, *pP, *palette_scaling_maxval, newmaxval );
    *palette_scaling_maxval = newmaxval;
  }
  newcolors = MS_MIN(colors, *reqcolors);
  acolormap = mediancut(achv, colors, rb->width*rb->height, *palette_scaling_maxval, newcolors);
  pam_freeacolorhist(achv);


  *reqcolors = newcolors;


  for (x = 0; x < newcolors; ++x) {
    palette[x].r = acolormap[x].acolor.r;
    palette[x].g = acolormap[x].acolor.g;
    palette[x].b = acolormap[x].acolor.b;
    palette[x].a = acolormap[x].acolor.a;
  }

  free(acolormap);
  free(apixels);
  return MS_SUCCESS;
}
Ejemplo n.º 17
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
}
Ejemplo n.º 18
0
static int msContourLayerReadRaster(layerObj *layer, rectObj rect)
{
  mapObj *map = layer->map;  
  char **bands;
  char pointer[64], memDSPointer[128];
  int band = 1;
  double adfGeoTransform[6], adfInvGeoTransform[6];
  double llx, lly, urx, ury;  
  rectObj copyRect, mapRect;
  int dst_xsize, dst_ysize;
  int virtual_grid_step_x, virtual_grid_step_y;
  int src_xoff, src_yoff, src_xsize, src_ysize;  
  double map_cellsize_x, map_cellsize_y, dst_cellsize_x, dst_cellsize_y;
  GDALRasterBandH hBand = NULL;
  CPLErr eErr;
  
  contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo;

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

  if (clinfo == NULL || clinfo->hOrigDS == NULL) {
    msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!",
               "msContourLayerReadRaster()");
    return MS_FAILURE;    
  }

  bands = CSLTokenizeStringComplex(
               CSLFetchNameValue(layer->processing,"BANDS"), " ,", FALSE, FALSE );
  if (CSLCount(bands) > 0) {
    band = atoi(bands[0]);
    if (band < 1 || band > GDALGetRasterCount(clinfo->hOrigDS)) {
      msSetError( MS_IMGERR,
                  "BANDS PROCESSING directive includes illegal band '%d', should be from 1 to %d.",
                  "msContourLayerReadRaster()",
                  band, GDALGetRasterCount(clinfo->hOrigDS));
      CSLDestroy(bands);
      return MS_FAILURE;
    }
  }
  CSLDestroy(bands);

  hBand = GDALGetRasterBand(clinfo->hOrigDS, band);
  if (hBand == NULL)
  {
    msSetError(MS_IMGERR,
               "Band %d does not exist on dataset.",
               "msContourLayerReadRaster()", band);
    return MS_FAILURE;
  }

  if (layer->projection.numargs > 0 &&
      EQUAL(layer->projection.args[0], "auto")) {
    const char *wkt;
    wkt = GDALGetProjectionRef(clinfo->hOrigDS);
    if (wkt != NULL && strlen(wkt) > 0) {
      if (msOGCWKT2ProjectionObj(wkt, &(layer->projection),
                                 layer->debug) != MS_SUCCESS) {
        char  msg[MESSAGELENGTH*2];
        errorObj *ms_error = msGetErrorObj();

        snprintf( msg, sizeof(msg),
                  "%s\n"
                  "PROJECTION AUTO cannot be used for this "
                  "GDAL raster (`%s').",
                  ms_error->message, layer->data);
        msg[MESSAGELENGTH-1] = '\0';

        msSetError(MS_OGRERR, "%s","msDrawRasterLayer()",
                   msg);
        return MS_FAILURE;
      }
    }
  }
  
  /*
   * Compute the georeferenced window of overlap, and read the source data
   * downsampled to match output resolution, or at full resolution if
   * output resolution is lower than the source resolution.
   *
   * A large portion of this overlap calculation code was borrowed from 
   * msDrawRasterLayerGDAL(). 
   * Would be possible to move some of this to a reusable function?
   *
   * Note: This code works only if no reprojection is involved. It would
   * need rework to support cases where output projection differs from source
   * data file projection.
   */
  
  src_xsize = GDALGetRasterXSize(clinfo->hOrigDS);
  src_ysize = GDALGetRasterYSize(clinfo->hOrigDS);

  /* set the Dataset extent */
  msGetGDALGeoTransform(clinfo->hOrigDS, map, layer, adfGeoTransform);  
  clinfo->extent.minx = adfGeoTransform[0];
  clinfo->extent.maxy = adfGeoTransform[3];
  clinfo->extent.maxx = adfGeoTransform[0] + src_xsize * adfGeoTransform[1];
  clinfo->extent.miny = adfGeoTransform[3] + src_ysize * adfGeoTransform[5];
  
  if (layer->transform) {
    if (layer->debug)
      msDebug("msContourLayerReadRaster(): Entering transform.\n");

    InvGeoTransform(adfGeoTransform, adfInvGeoTransform);

    mapRect = rect;
    map_cellsize_x = map_cellsize_y = map->cellsize;      
#ifdef USE_PROJ
    /* if necessary, project the searchrect to source coords */
    if (msProjectionsDiffer( &(map->projection), &(layer->projection)))  {
      if ( msProjectRect(&map->projection, &layer->projection, &mapRect)
          != MS_SUCCESS ) {
        msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name);
        return MS_FAILURE;
      }

      map_cellsize_x = MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width);
      map_cellsize_y = MS_CELLSIZE(mapRect.miny, mapRect.maxy, map->height);

      /* if the projection failed to project the extent requested, we need to
         calculate the cellsize to preserve the initial map cellsize ratio */
      if ( (mapRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize)) ||
           (mapRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0)) ||
           (mapRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize)) || 
           (mapRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0)) ) {

        int src_unit, dst_unit;
        src_unit = GetMapserverUnitUsingProj(&map->projection);
        dst_unit = GetMapserverUnitUsingProj(&layer->projection);
        if (src_unit == -1 || dst_unit == -1) {
          msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name);
          return MS_FAILURE;
        }

        map_cellsize_x =  MS_CONVERT_UNIT(src_unit, dst_unit,
                                          MS_CELLSIZE(rect.minx, rect.maxx, map->width)); 
        map_cellsize_y = MS_CONVERT_UNIT(src_unit, dst_unit,
                                         MS_CELLSIZE(rect.miny, rect.maxy, map->height));
      }       
    }
#endif
    
    if (map_cellsize_x == 0 || map_cellsize_y == 0) {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): Cellsize can't be 0.\n");
      return MS_FAILURE;
    }
    
    /* Adjust MapServer pixel model to GDAL pixel model */
    mapRect.minx -= map_cellsize_x*0.5;
    mapRect.maxx += map_cellsize_x*0.5;
    mapRect.miny -= map_cellsize_y*0.5;
    mapRect.maxy += map_cellsize_y*0.5;


    /*
     * If raw data cellsize (from geotransform) is larger than output map_cellsize
     * then we want to extract only enough data to match the output map resolution
     * which means that GDAL will automatically sample the data on read.
     *
     * To prevent bad contour effects on tile edges, we adjust the target cellsize 
     * to align the extracted window with a virtual grid based on the origin of the 
     * raw data and a virtual grid step size corresponding to an integer sampling step.
     *
     * If source data has a greater cellsize (i.e. lower res) that requested ouptut map
     * then we use the raw data cellsize as target cellsize since there is no point in 
     * interpolating the data for contours in this case.
     */

    virtual_grid_step_x = (int)floor(map_cellsize_x / ABS(adfGeoTransform[1]));
    if (virtual_grid_step_x < 1)
      virtual_grid_step_x = 1; /* Do not interpolate data if grid sampling step < 1 */

    virtual_grid_step_y = (int)floor(map_cellsize_y / ABS(adfGeoTransform[5]));
    if (virtual_grid_step_y < 1)
      virtual_grid_step_y = 1; /* Do not interpolate data if grid sampling step < 1 */
    
    /* target cellsize is a multiple of raw data cellsize based on grid step*/
    dst_cellsize_x = ABS(adfGeoTransform[1]) * virtual_grid_step_x;
    dst_cellsize_y = ABS(adfGeoTransform[5]) * virtual_grid_step_y;

    /* Compute overlap between source and target views */

    copyRect = mapRect;

    if (copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize))
      copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize);
    if (copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0))
      copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0);
    if (copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize))
      copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize);
    if (copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0))
      copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0);
    
    if (copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy) {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): No overlap.\n");
      return MS_SUCCESS;
    }

    /*
     * Convert extraction window to raster coordinates
     */
    llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny);
    lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny);
    urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy);
    ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy);

    /* 
     * Align extraction window with virtual grid 
     * (keep in mind raster coordinates origin is at upper-left)
     * We also add an extra buffer to fix tile boundarie issues when zoomed
     */
    llx = floor(llx / virtual_grid_step_x) * virtual_grid_step_x - (virtual_grid_step_x*5);
    urx = ceil(urx / virtual_grid_step_x) * virtual_grid_step_x + (virtual_grid_step_x*5);
    ury = floor(ury / virtual_grid_step_y) * virtual_grid_step_y - (virtual_grid_step_x*5);
    lly = ceil(lly / virtual_grid_step_y) * virtual_grid_step_y + (virtual_grid_step_x*5);
    
    src_xoff = MS_MAX(0,(int) floor(llx+0.5));
    src_yoff = MS_MAX(0,(int) floor(ury+0.5));
    src_xsize = MS_MIN(MS_MAX(0,(int) (urx - llx + 0.5)),
                    GDALGetRasterXSize(clinfo->hOrigDS) - src_xoff);
    src_ysize = MS_MIN(MS_MAX(0,(int) (lly - ury + 0.5)),
                    GDALGetRasterYSize(clinfo->hOrigDS) - src_yoff);

    /* Update the geographic extent (buffer added) */
    /* TODO: a better way to go the geo_trans */
    copyRect.minx = GEO_TRANS(adfGeoTransform+0,src_xoff,0);
    copyRect.maxx = GEO_TRANS(adfGeoTransform+0,src_xoff+src_xsize,0);
    copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_yoff+src_ysize);
    copyRect.maxy = GEO_TRANS(adfGeoTransform+3,0,src_yoff);
    
    /* 
     * If input window is to small then stop here
     */
    if (src_xsize < 2 || src_ysize < 2)
    {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): input window too small, or no apparent overlap between map view and this window(1).\n");
      return MS_SUCCESS;
    }

    /* Target buffer size */
    dst_xsize = (int)ceil((copyRect.maxx - copyRect.minx) / dst_cellsize_x);
    dst_ysize = (int)ceil((copyRect.maxy - copyRect.miny) / dst_cellsize_y);

    if (dst_xsize == 0 || dst_ysize == 0) {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): no apparent overlap between map view and this window(2).\n");
      return MS_SUCCESS;
    }

    if (layer->debug)
      msDebug( "msContourLayerReadRaster(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n",
               src_xoff, src_yoff, src_xsize, src_ysize,
               0, 0, dst_xsize, dst_ysize );
  } else {
    src_xoff = 0;
    src_yoff = 0;
    dst_xsize = src_xsize = MS_MIN(map->width,src_xsize);
    dst_ysize = src_ysize = MS_MIN(map->height,src_ysize);
    copyRect.minx = copyRect.miny = 0;
    copyRect.maxx = map->width;
    copyRect.maxy = map->height;
    dst_cellsize_y = dst_cellsize_x = 1;
  }

  /* -------------------------------------------------------------------- */
  /*      Allocate buffer, and read data into it.                         */
  /* -------------------------------------------------------------------- */

  clinfo->buffer = (double *) malloc(sizeof(double) * dst_xsize * dst_ysize);
  if (clinfo->buffer == NULL) {
    msSetError(MS_MEMERR, "Malloc(): Out of memory.", "msContourLayerReadRaster()");
    return MS_FAILURE;
  }

  eErr = GDALRasterIO(hBand, GF_Read,
                      src_xoff, src_yoff, src_xsize, src_ysize,
                      clinfo->buffer, dst_xsize, dst_ysize, GDT_Float64,
                      0, 0);

  if (eErr != CE_None) {
    msSetError( MS_IOERR, "GDALRasterIO() failed: %s",
                "msContourLayerReadRaster()", CPLGetLastErrorMsg() );
    free(clinfo->buffer);
    return MS_FAILURE;
  }

  memset(pointer, 0, sizeof(pointer));
  CPLPrintPointer(pointer, clinfo->buffer, sizeof(pointer));
  sprintf(memDSPointer,"MEM:::DATAPOINTER=%s,PIXELS=%d,LINES=%d,BANDS=1,DATATYPE=Float64",
          pointer, dst_xsize, dst_ysize);
  clinfo->hDS = GDALOpen(memDSPointer,  GA_ReadOnly);
  if (clinfo->hDS == NULL) {
    msSetError(MS_IMGERR,
               "Unable to open GDAL Memory dataset.",
               "msContourLayerReadRaster()");
    free(clinfo->buffer);
    return MS_FAILURE;
  }

  adfGeoTransform[0] = copyRect.minx;
  adfGeoTransform[1] = dst_cellsize_x;
  adfGeoTransform[2] = 0;
  adfGeoTransform[3] = copyRect.maxy;
  adfGeoTransform[4] = 0;
  adfGeoTransform[5] = -dst_cellsize_y;

  clinfo->cellsize = MS_MAX(dst_cellsize_x, dst_cellsize_y);
  {
    char buf[64];
    sprintf(buf, "%lf", clinfo->cellsize);
    msInsertHashTable(&layer->metadata, "__data_cellsize__", buf);
  }
      
  GDALSetGeoTransform(clinfo->hDS, adfGeoTransform);
  return MS_SUCCESS;
}
Ejemplo n.º 19
0
int msDrawBarChart(mapObj *map, imageObj *image, pointObj *center,
                   float *values, styleObj **styles, int numvalues,
                   float width, float height, float *maxVal, float *minVal, float barWidth)
{

    float upperLimit,lowerLimit;
    float shapeMaxVal,shapeMinVal,pixperval;
    int c;
    float vertOrigin,vertOriginClipped,horizStart,y;
    float left,top,bottom; /*shortcut to pixel boundaries of the chart*/

    top=center->y-height/2.;
    bottom=center->y+height/2.;
    left=center->x-width/2.;

    shapeMaxVal=shapeMinVal=values[0];
    for(c=1; c<numvalues; c++)
    {
        if(maxVal==NULL || minVal==NULL) { /*compute bounds if not specified*/
            if(values[c]>shapeMaxVal)
                shapeMaxVal=values[c];
            if(values[c]<shapeMinVal)
                shapeMinVal=values[c];
        }
    }

    /*
     * use specified bounds if wanted
     * if not, always show the origin
     */
    upperLimit = (maxVal!=NULL)? *maxVal : MS_MAX(shapeMaxVal,0);
    lowerLimit = (minVal!=NULL)? *minVal : MS_MIN(shapeMinVal,0);
    if(upperLimit==lowerLimit) {
        /* treat the case where we would have an unspecified behavior */
        upperLimit+=0.5;
        lowerLimit-=0.5;
    }

    pixperval=(float)height/(upperLimit-lowerLimit);
    vertOrigin=bottom+lowerLimit*pixperval;
    vertOriginClipped=(vertOrigin<top) ? top :
                      (vertOrigin>bottom) ? bottom : vertOrigin;
    horizStart=left;
    /*
    color = gdImageColorAllocate(image->img.gd, 0,0,0);
    gdImageRectangle(image->img.gd, left-1,top-1, center.x+width/2.+1,bottom+1,color);
    */
    for(c=0; c<numvalues; c++)
    {
        int barHeight=values[c]*pixperval;
        /*clip bars*/
        y=((vertOrigin-barHeight)<top) ? top :
          (vertOrigin-barHeight>bottom) ? bottom : vertOrigin-barHeight;
        if(y!=vertOriginClipped) { /*don't draw bars of height == 0 (i.e. either values==0, or clipped)*/
            if(values[c]>0)
                drawRectangle(map, image, horizStart, y, horizStart+barWidth-1, vertOriginClipped, styles[c]);
            else
                drawRectangle(map,image, horizStart, vertOriginClipped, horizStart+barWidth-1 , y, styles[c]);
        }
        horizStart+=barWidth;
    }
    return MS_SUCCESS;
}
Ejemplo n.º 20
0
/* ------------------------------------------------------------------------- */
void msDrawMarkerSymbolIM(mapObj *map, imageObj* img, pointObj *p, styleObj *style, double scalefactor)
{
  symbolObj *symbol;
  int ox, oy;
  double size;

  DEBUG_IF printf("msDrawMarkerSymbolIM\n<BR>");

  /* skip this, we don't do text */



  if(!p) return;


  if(style->symbol > map->symbolset.numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */
  symbol = map->symbolset.symbol[style->symbol];
  ox = style->offsetx*scalefactor;
  oy = style->offsety*scalefactor;
  if(style->size == -1) {
    size = msSymbolGetDefaultSize( symbol );
    size = MS_NINT(size*scalefactor);
  } else
    size = MS_NINT(style->size*scalefactor);
  size = MS_MAX(size, style->minsize*img->resolutionfactor);
  size = MS_MIN(size, style->maxsize*img->resolutionfactor);

  if(size < 1) return; /* size too small */

  /* DEBUG_IF printf(".%d.%d.%d.", symbol->type, style->symbol, fc); */
  if(style->symbol == 0) { /* simply draw a single pixel of the specified color */

    if (dxf) {
      if (dxf==2)
        im_iprintf (&imgStr, "POINT\n%.0f %.0f\n%d\n",
                    p->x + ox, p->y + oy, matchdxfcolor(style->color));
      else
        im_iprintf (&imgStr,
                    "  0\nPOINT\n 10\n%f\n 20\n%f\n 30\n0.0\n"
                    " 62\n%6d\n  8\n%s\n",
                    p->x + ox, p->y + oy, matchdxfcolor(style->color), lname);
    } else {
      im_iprintf (&imgStr, "<area ");
      if (strcmp(symbolHrefFmt,"%.s")!=0) {
        im_iprintf (&imgStr, "href=\"");
        im_iprintf (&imgStr, symbolHrefFmt, lname);
        im_iprintf (&imgStr, "\" ");
      }
      if (strcmp(symbolMOverFmt,"%.s")!=0) {
        im_iprintf (&imgStr, "onMouseOver=\"");
        im_iprintf (&imgStr, symbolMOverFmt, lname);
        im_iprintf (&imgStr, "\" ");
      }
      if (strcmp(symbolMOutFmt,"%.s")!=0) {
        im_iprintf (&imgStr, "onMouseOut=\"");
        im_iprintf (&imgStr, symbolMOutFmt, lname);
        im_iprintf (&imgStr, "\" ");
      }
      im_iprintf (&imgStr, "shape=\"circle\" coords=\"%.0f,%.0f, 3\" />\n",
                  p->x + ox, p->y + oy);
    }

    /* point2 = &( p->line[j].point[i] ); */
    /* if(point1->y == point2->y) {} */
    return;
  }
  DEBUG_IF printf("A");
  switch(symbol->type) {
    case(MS_SYMBOL_TRUETYPE):
      DEBUG_IF printf("T");
      break;
    case(MS_SYMBOL_PIXMAP):
      DEBUG_IF printf("P");
      break;
    case(MS_SYMBOL_VECTOR):
      DEBUG_IF printf("V");
      {
        double d, offset_x, offset_y;

        d = size/symbol->sizey;
        offset_x = MS_NINT(p->x - d*.5*symbol->sizex + ox);
        offset_y = MS_NINT(p->y - d*.5*symbol->sizey + oy);

        /* For now I only render filled vector symbols in imagemap, and no */
        /* dxf support available yet.  */
        if(symbol->filled && !dxf /* && fc >= 0 */ ) {
          /* char *title=(p->numvalues) ? p->values[0] : ""; */
          char *title = "";
          int  j;

          im_iprintf (&imgStr, "<area ");
          if (strcmp(symbolHrefFmt,"%.s")!=0) {
            im_iprintf (&imgStr, "href=\"");
            im_iprintf (&imgStr, symbolHrefFmt, lname);
            im_iprintf (&imgStr, "\" ");
          }
          if (strcmp(symbolMOverFmt,"%.s")!=0) {
            im_iprintf (&imgStr, "onMouseOver=\"");
            im_iprintf (&imgStr, symbolMOverFmt, lname);
            im_iprintf (&imgStr, "\" ");
          }
          if (strcmp(symbolMOutFmt,"%.s")!=0) {
            im_iprintf (&imgStr, "onMouseOut=\"");
            im_iprintf (&imgStr, symbolMOutFmt, lname);
            im_iprintf (&imgStr, "\" ");
          }

          im_iprintf (&imgStr, "title=\"%s\" shape=\"poly\" coords=\"", title);

          for(j=0; j < symbol->numpoints; j++) {
            im_iprintf (&imgStr, "%s %d,%d", j == 0 ? "": ",",
                        MS_NINT(d*symbol->points[j].x + offset_x),
                        MS_NINT(d*symbol->points[j].y + offset_y) );
          }
          im_iprintf (&imgStr, "\" />\n");
        } /* end of imagemap, filled case. */
      }
      break;

    default:
      DEBUG_IF printf("DEF");
      break;
  } /* end switch statement */

  return;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
/* ------------------------------------------------------------------------- */
void msDrawShadeSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor)
{
  symbolObj *symbol;
  int i,j,l;
  char first = 1;
  double size;

  DEBUG_IF printf("msDrawShadeSymbolIM\n<BR>");
  if(!p) return;
  if(p->numlines <= 0) return;

  symbol = map->symbolset.symbol[style->symbol];
  if(style->size == -1) {
    size = msSymbolGetDefaultSize( symbol );
    size = MS_NINT(size*scalefactor);
  } else
    size = MS_NINT(style->size*scalefactor);
  size = MS_MAX(size, style->minsize*img->resolutionfactor);
  size = MS_MIN(size, style->maxsize*img->resolutionfactor);

  if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */
  if(style->symbol == 0) { /* simply draw a single pixel of the specified color //     */
    for(l=0,j=0; j<p->numlines; j++) {
      if (dxf == 2) {
        im_iprintf (&imgStr, "POLY\n%d\n", matchdxfcolor(style->color));
      } else if (dxf) {
        im_iprintf (&imgStr, "  0\nPOLYLINE\n 73\n     1\n 62\n%6d\n  8\n%s\n", matchdxfcolor(style->color), lname);
      } else {
        char *title=(p->numvalues) ? p->values[0] : "";
        first = 1;
        im_iprintf (&imgStr, "<area ");
        if (strcmp(polyHrefFmt,"%.s")!=0) {
          im_iprintf (&imgStr, "href=\"");
          im_iprintf (&imgStr, polyHrefFmt, title);
          im_iprintf (&imgStr, "\" ");
        }
        if (strcmp(polyMOverFmt,"%.s")!=0) {
          im_iprintf (&imgStr, "onMouseOver=\"");
          im_iprintf (&imgStr, polyMOverFmt, title);
          im_iprintf (&imgStr, "\" ");
        }
        if (strcmp(polyMOutFmt,"%.s")!=0) {
          im_iprintf (&imgStr, "onMouseOut=\"");
          im_iprintf (&imgStr, polyMOutFmt, title);
          im_iprintf (&imgStr, "\" ");
        }
        im_iprintf (&imgStr, "title=\"%s\" shape=\"poly\" coords=\"", title);
      }

      /* point1 = &( p->line[j].point[p->line[j].numpoints-1] ); */
      for(i=0; i < p->line[j].numpoints; i++,l++) {
        if (dxf == 2) {
          im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y);
        } else if (dxf) {
          im_iprintf (&imgStr, "  0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0);
        } else {
          im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y);
        }
        first = 0;

        /* point2 = &( p->line[j].point[i] ); */
        /* if(point1->y == point2->y) {} */
      }
      im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": "  0\nSEQEND\n") : "\" />\n");
    }

    return;
  }
  /* DEBUG_IF printf ("d"); */
  DEBUG_IF printf("-%d-",symbol->type);
  return;
}
Ejemplo n.º 24
0
int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char **fonts, int numfonts, double size,
                             char *text, rectObj *rect, double **advances, int bAdjustBaseline)
{
  cairoCacheData *cache = MS_RENDERER_CACHE(renderer);
  faceCacheObj* face = getFontFace(cache,fonts[0]);

  int curfontidx = 0;
  char *utfptr=text;
  int i,unicode;
  unsigned long previdx=0;
  faceCacheObj* prevface = face;
  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);

  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;
    }

    if (curfontidx != 0) {
      face = getFontFace(cache, fonts[0]);
      cairo_set_font_face(cache->dummycr, face->face);
      curfontidx = 0;
    }

    if (face->ftface->charmap &&
      face->ftface->charmap->encoding == FT_ENCODING_MS_SYMBOL)
      unicode |= 0xf000;

    glyph.index = FT_Get_Char_Index(face->ftface, unicode);

    if (glyph.index == 0) {
      int j;
      for (j = 1; j < numfonts; j++) {
        curfontidx = j;
        face = getFontFace(cache, fonts[j]);
        glyph.index = FT_Get_Char_Index(face->ftface, unicode);
        if (glyph.index != 0) {
          cairo_set_font_face(cache->dummycr, face->face);
          break;
        }
      }
    }

    if( FT_HAS_KERNING((prevface->ftface)) && previdx ) {
      FT_Vector delta;
      FT_Get_Kerning( prevface->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+(bAdjustBaseline?1:(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+(bAdjustBaseline?1:(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;
    prevface = face;
  }
  return MS_SUCCESS;
}
Ejemplo n.º 25
0
/* helper functions */
int agg2GetTruetypeTextBBox(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string,
                            rectObj *rect, double **advances,int bAdjustBaseline)
{

  aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(renderer);
  if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE)
    return MS_FAILURE;
  int curfontidx = 0;

  int unicode, curGlyph = 1, numglyphs = 0;
  if (advances) {
    numglyphs = msGetNumGlyphs(string);
  }
  const mapserver::glyph_cache* glyph;
  string += msUTF8ToUniChar(string, &unicode);

  if(curfontidx != 0) {
    if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE)
      return MS_FAILURE;
    curfontidx = 0;
  }
  glyph = cache->m_fman.glyph(unicode);
  if(!glyph || glyph->glyph_index == 0) {
    int i;
    for(i=1; i<numfonts; i++) {
      if(aggLoadFont(cache,fonts[i],size) == MS_FAILURE)
        return MS_FAILURE;
      curfontidx = i;
      glyph = cache->m_fman.glyph(unicode);
      if(glyph && glyph->glyph_index != 0) {
        break;
      }
    }
  }
  if (glyph) {
    rect->minx = glyph->bounds.x1;
    rect->maxx = glyph->bounds.x2;
    rect->miny = glyph->bounds.y1;
    rect->maxy = bAdjustBaseline?1:glyph->bounds.y2;
  } else
    return MS_FAILURE;
  if (advances) {
    *advances = (double*) malloc(numglyphs * sizeof (double));
    MS_CHECK_ALLOC(*advances, numglyphs * sizeof (double), MS_FAILURE);
    (*advances)[0] = glyph->advance_x;
  }
  double fx = glyph->advance_x, fy = glyph->advance_y;
  while (*string) {
    if (advances) {
      if (*string == '\r' || *string == '\n')
        (*advances)[curGlyph++] = -fx;
    }
    if (*string == '\r') {
      fx = 0;
      string++;
      continue;
    }
    if (*string == '\n') {
      fx = 0;
      fy += ceil(size * AGG_LINESPACE);
      string++;
      continue;
    }
    string += msUTF8ToUniChar(string, &unicode);
    if(curfontidx != 0) {
      if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE)
        return MS_FAILURE;
      curfontidx = 0;
    }
    glyph = cache->m_fman.glyph(unicode);
    if(!glyph || glyph->glyph_index == 0) {
      int i;
      for(i=1; i<numfonts; i++) {
        if(aggLoadFont(cache,fonts[i],size) == MS_FAILURE)
          return MS_FAILURE;
        curfontidx = i;
        glyph = cache->m_fman.glyph(unicode);
        if(glyph && glyph->glyph_index != 0) {
          break;
        }
      }
    }
    if (glyph) {
      rect->minx = MS_MIN(rect->minx, fx+glyph->bounds.x1);
      rect->miny = MS_MIN(rect->miny, fy+glyph->bounds.y1);
      rect->maxx = MS_MAX(rect->maxx, fx+glyph->bounds.x2);
      rect->maxy = MS_MAX(rect->maxy, fy+(bAdjustBaseline?1:glyph->bounds.y2));

      fx += glyph->advance_x;
      fy += glyph->advance_y;
      if (advances) {
        (*advances)[curGlyph++] = glyph->advance_x;
      }
    }
  }
  return MS_SUCCESS;
}
Ejemplo n.º 26
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
}
Ejemplo n.º 27
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;
}