示例#1
0
int agg2RenderBitmapGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text)
{
  typedef mapserver::glyph_raster_bin<color_type> glyph_gen;
  int size = MS_NINT(style->size);
  if(size<0 || size>4) {
    msSetError(MS_RENDERERERR,"invalid bitmap font size", "agg2RenderBitmapGlyphs()");
    return MS_FAILURE;
  }
  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]);
  int numlines=0;
  char **lines;
  /*masking out the out-of-range character codes*/
  int len;
  int cc_start = rasterfonts[size][2];
  int cc_end = cc_start + rasterfonts[size][3];
  if(msCountChars(text,'\n')) {
    if((lines = msStringSplit((const char*)text, '\n', &(numlines))) == NULL)
      return(-1);
  } else {
    lines = &text;
    numlines = 1;
  }
  y -= glyph.base_line();
  for(int n=0; n<numlines; n++) {
    len = strlen(lines[n]);
    for (int i = 0; i < len; i++)
      if (lines[n][i] < cc_start || lines[n][i] > cc_end)
        lines[n][i] = '.';
    if(style->outlinewidth > 0) {
      rt.color(aggColor(style->outlinecolor));
      for(int i=-1; i<=1; i++) {
        for(int j=-1; j<=1; j++) {
          if(i||j) {
            rt.render_text(x+i, y+j, lines[n], true);
          }
        }
      }
    }
    assert(style->color);
    rt.color(aggColor(style->color));
    rt.render_text(x, y, lines[n], true);
    y += glyph.height();
  }
  if(*lines != text)
    msFreeCharArray(lines, numlines);
  return MS_SUCCESS;
  return MS_SUCCESS;
}
示例#2
0
int renderBitmapGlyphsGD(imageObj *img, double x, double y, labelStyleObj *style, char *text)
{
    int size = MS_NINT(style->size);
    gdFontPtr fontPtr;
    gdImagePtr ip;
    int numlines=0,t;
    char **lines;
    if(!(ip = MS_IMAGE_GET_GDIMAGEPTR(img))) return MS_FAILURE;
    if(size<0 || size>4 || (fontPtr = msGetBitmapFont(size))==NULL) {
        msSetError(MS_RENDERERERR,"invalid bitmap font size", "renderBitmapGlyphsGD()");
        return MS_FAILURE;
    }

    SETPEN(ip, style->color);
    SETPEN(ip, style->outlinecolor);

    if(msCountChars(text,'\n')) {
        if((lines = msStringSplit((const char*)text, '\n', &(numlines))) == NULL)
            return(-1);
    } else {
        lines = &text;
        numlines = 1;
    }

    y -= fontPtr->h;
    for(t=0; t<numlines; t++) {
        if(style->outlinewidth > 0) {
            gdImageString(ip, fontPtr, x, y-1,   (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x, y+1,   (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x+1, y,   (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x-1, y,   (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x+1, y-1, (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x+1, y+1, (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x-1, y-1, (unsigned char *) lines[t], style->outlinecolor->pen);
            gdImageString(ip, fontPtr, x-1, y+1, (unsigned char *) lines[t], style->outlinecolor->pen);
        }
        if(style->color->pen != -1) {
            gdImageString(ip, fontPtr, x, y, (unsigned char *) lines[t], style->color->pen);
        }

        y += fontPtr->h; /* shift down */
    }


    if(lines != &text)
        msFreeCharArray(lines, numlines);
    return MS_SUCCESS;
}
示例#3
0
/**
 * replace wrap characters with \n , respecting maximal line length.
 *
 * returns a pointer to the newly allocated text. memory is controlled
 * inside this function, so the caller MUST use the pointer returned by
 * the function:
 * text = msWrapText(label,text);
 *
 * TODO/FIXME: function will produce erroneous/crashing? results
 * if the wrap character is encoded with multiple bytes
 *
 * see http://mapserver.org/development/rfc/ms-rfc-40.html
 * for a summary of how wrap/maxlength interact on the result
 * of the text transformation
 */
char *msWrapText(labelObj *label, char *text)
{
  char wrap;
  int maxlength;
  if(!text) /*not an error if no text*/
    return text;
  wrap = label->wrap;
  maxlength = label->maxlength;
  if(maxlength == 0) {
    if(wrap!='\0') {
      /* if maxlength = 0 *and* a wrap character was specified,
       * replace all wrap characters by \n
       * this is the traditional meaning of the wrap character
       */
      msReplaceChar(text, wrap, '\n');
    }
    /* if neither maxlength, nor wrap were specified,
     * don't transform this text */
    return text;
  } else if(maxlength>0) {
    if(wrap!='\0') {
      /* split input text at the wrap character, only if
       * the current line length is over maxlength */

      /* TODO: check if the wrap character is a valid byte
       * inside a multibyte utf8 glyph. if so, the msCountChars
       * will return an erroneous value */
      int numwrapchars = msCountChars(text,wrap);

      if(numwrapchars > 0) {
        if(label->encoding) {
          /* we have to use utf decoding functions here, so as not to
           * split a text line on a multibyte character */

          int num_cur_glyph_on_line = 0; /*count for the number of glyphs
                                                     on the current line*/
          char *textptr = text;
          char glyph[11]; /*storage for unicode fetching function*/
          int glyphlen = 0; /*size of current glyph in bytes*/
          while((glyphlen = msGetNextGlyph((const char**)&textptr,glyph))>0) {
            num_cur_glyph_on_line++;
            if(*glyph == wrap && num_cur_glyph_on_line>=(maxlength)) {
              /*FIXME (if wrap becomes something other than char):*/
              *(textptr-1)='\n'; /*replace wrap char with a \n*/
              num_cur_glyph_on_line=0; /*reset count*/
            }
          }
        } else {
          int cur_char_on_line = 0;
          char *textptr = text;
          while(*textptr != 0) {
            cur_char_on_line++;
            if(*textptr == wrap && cur_char_on_line>=maxlength) {
              *textptr='\n'; /*replace wrap char with a \n*/
              cur_char_on_line=0; /*reset count*/
            }
            textptr++;
          }
        }
        return text;
      } else {
        /*there are no characters available for wrapping*/
        return text;
      }
    } else {
      /* if no wrap character was specified, but a maxlength was,
       * don't draw this label if it is longer than the specified maxlength*/
      if(msGetNumGlyphs(text)>maxlength) {
        free(text);
        return NULL;
      } else {
        return text;
      }
    }
  } else {
    /* negative maxlength: we split lines unconditionally, i.e. without
    loooking for a wrap character*/
    int numglyphs,numlines;
    maxlength = -maxlength; /* use a positive value*/
    numglyphs = msGetNumGlyphs(text);
    numlines = (numglyphs-1) / maxlength + 1; /*count total number of lines needed
                                            after splitting*/
    if(numlines>1) {
      char *newtext = msSmallMalloc(strlen(text)+numlines+1);
      char *newtextptr = newtext;
      char *textptr = text;
      int glyphlen = 0, num_cur_glyph = 0;
      while((glyphlen = msGetNextGlyph((const char**)&textptr,newtextptr))>0) {
        num_cur_glyph++;
        newtextptr += glyphlen;
        if(num_cur_glyph%maxlength == 0 && num_cur_glyph != numglyphs) {
          /*we're at a split location, insert a newline*/
          *newtextptr = '\n';
          newtextptr++;
        }
      }
      free(text);
      return newtext;
    } else {
      /*no splitting needed, return the original*/
      return text;
    }
  }
}
示例#4
0
char *msAlignText(mapObj *map, labelObj *label, char *text)
{
  double spacewidth=0.0; /*size of a single space, in fractional pixels*/
  int numlines;
  char **textlines,*newtext,*newtextptr;
  int *textlinelengths,*numspacesforpadding;
  int numspacestoadd,maxlinelength,i;
  rectObj label_rect;
  if(!msCountChars(text,'\n'))
    return text; /*only one line*/

  /*split text into individual lines
   * TODO: check if splitting on \n is utf8 safe*/
  textlines = msStringSplit(text,'\n',&numlines);

  /*
   * label->space_size_10 contains a cache for the horizontal size of a single
   * 'space' character, at size 10 for the current label
   * FIXME: in case of attribute binding for the FONT of the label, this cache will
   * be wrong for labels where the attributed font is different than the first
   * computed font. This shouldn't happen too often, and hopefully the size of a
   * space character shouldn't vary too much between different fonts*/
  if(label->space_size_10 == 0.0) {
    /*if the cache hasn't been initialized yet, or with pixmap fonts*/

    /* compute the size of 16 adjacent spaces. we can't do this for just one space,
     * as the labelSize computing functions return integer bounding boxes. we assume
     * that the integer rounding for such a number of spaces will be negligeable
     * compared to the actual size of thoses spaces */
    if(msGetLabelSize(map,label,".              .",10.0,&label_rect,NULL) != MS_SUCCESS) {
      /*error computing label size, we can't continue*/

      /*free the previously allocated split text*/
      while(numlines--)
        free(textlines[numlines]);
      free(textlines);
      return text;
    }

    /* this is the size of a single space character. for truetype fonts,
     * it's the size of a 10pt space. For pixmap fonts, it's the size
     * for the current label */
    spacewidth = (label_rect.maxx-label_rect.minx)/16.0;
    if(label->type == MS_TRUETYPE) {
      label->space_size_10=spacewidth; /*cache the computed size*/

      /*size of a space for current label size*/
      spacewidth = spacewidth * (double)label->size/10.0;
    }
  } else {
    spacewidth = label->space_size_10 * (double)label->size/10.0;
  }
  spacewidth = MS_MAX(1,spacewidth);


  /*length in pixels of each line*/
  textlinelengths = (int*)msSmallMalloc(numlines*sizeof(int));

  /*number of spaces that need to be added to each line*/
  numspacesforpadding = (int*)msSmallMalloc(numlines*sizeof(int));

  /*total number of spaces that need to be added*/
  numspacestoadd=0;

  /*length in pixels of the longest line*/
  maxlinelength=0;
  for(i=0; i<numlines; i++) {
    if(MS_SUCCESS != msGetLabelSize(map,label,textlines[i],label->size, &label_rect,NULL)) {
      msFreeCharArray(textlines,numlines);
      msFree(textlinelengths);
      msFree(numspacesforpadding);
      return text;
    }
    textlinelengths[i] = label_rect.maxx-label_rect.minx;
    if(maxlinelength<textlinelengths[i])
      maxlinelength=textlinelengths[i];
  }
  for(i=0; i<numlines; i++) {
    /* number of spaces to add so the current line is
     * as long as the longest line */
    double nfracspaces = (maxlinelength - textlinelengths[i])/spacewidth;

    if(label->align == MS_ALIGN_CENTER) {
      numspacesforpadding[i]=MS_NINT(nfracspaces/2.0);
    } else {
      if(label->align == MS_ALIGN_RIGHT) {
        numspacesforpadding[i]=MS_NINT(nfracspaces);
      }
    }
    numspacestoadd+=numspacesforpadding[i];
  }

  /*allocate new text with room for the additional spaces needed*/
  newtext = (char*)msSmallMalloc(strlen(text)+1+numspacestoadd);
  newtextptr=newtext;
  for(i=0; i<numlines; i++) {
    int j;
    /*padd beginning of line with needed spaces*/
    for(j=0; j<numspacesforpadding[i]; j++) {
      *(newtextptr++)=' ';
    }
    /*copy original line*/
    strcpy(newtextptr,textlines[i]);
    /*place pointer at the char right after the current line*/
    newtextptr+=strlen(textlines[i])+1;
    if(i!=numlines-1) {
      /*put the \n back in (was taken away by msStringSplit)*/
      *(newtextptr-1)='\n';
    }
  }
  /*free the original text*/
  free(text);
  for(i=0; i<numlines; i++) {
    free(textlines[i]);
  }
  free(textlines);
  free(textlinelengths);
  free(numspacesforpadding);

  /*return the aligned text. note that the terminating \0 was added by the last
   * call to strcpy */
  return newtext;
}