Exemple #1
0
 int msGetTruetypeTextBBoxKml(rendererVTableObj *r,char** fonts, int numfonts, double size, char *string,
                              rectObj *rect, double **advances, int bAdjustBaseline)
 {
   rect->minx=0.0;
   rect->maxx=0.0;
   rect->miny=0.0;
   rect->maxy=0.0;
   if (advances) {
     int numglyphs = msGetNumGlyphs(string);
     *advances = (double*) msSmallMalloc(numglyphs * sizeof (double));
     for(int i=0; i<numglyphs; i++) {
       (*advances)[i] = size;
     }
   }
   return MS_SUCCESS;
 }
Exemple #2
0
int renderGlyphsCairo(imageObj *img,double x, double y, labelStyleObj *style, char *text) {
    cairo_renderer *r = CAIRO_RENDERER(img);
    cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img);
    faceCacheObj *face = getFontFace(cache,style->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(r->cr,face->face);
    cairo_set_font_size(r->cr,style->size*96/72.0);

    cairo_save(r->cr);
    cairo_translate(r->cr,MS_NINT(x),MS_NINT(y));
    if(style->rotation != 0.0)
       cairo_rotate(r->cr, -style->rotation);

    has_kerning = FT_HAS_KERNING((face->ftface));
    for(i=0;i<numglyphs;i++) {
        utfptr+=msUTF8ToUniChar(utfptr, &unicode);
        glyph.x=px;
        glyph.y=py;
        if(unicode=='\n') {
            py += ceil(style->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(r->cr,&glyph,1,&extents);
        cairo_glyph_path(r->cr,&glyph,1);
        px += extents.x_advance;
        previdx=glyph.index;
    }

    if (style->outlinewidth > 0) {
        cairo_save(r->cr);
        msCairoSetSourceColor(r->cr, style->outlinecolor);
        cairo_set_line_width(r->cr, style->outlinewidth + 1);
        cairo_stroke_preserve(r->cr);
        cairo_restore(r->cr);
    }
    if(style->color) {
        msCairoSetSourceColor(r->cr, style->color);
        cairo_fill(r->cr);
    }
    cairo_new_path(r->cr);
    cairo_restore(r->cr);
    return MS_SUCCESS;
}
Exemple #3
0
int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char *font, double size, char *text, rectObj *rect, double **advances) {
    
    
    cairoCacheData *cache = MS_RENDERER_CACHE(renderer);
    faceCacheObj *face = getFontFace(cache,font);
 
    char *utfptr=text;
    int i,has_kerning,unicode;
    unsigned long previdx=0;
    int numglyphs = msGetNumGlyphs(text);
    cairo_glyph_t glyph;
    cairo_text_extents_t extents;
    double px=0,py=0;

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

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

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

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

    for(i=0;i<numglyphs;i++) {
        utfptr+=msUTF8ToUniChar(utfptr, &unicode);
        glyph.x=px;
        glyph.y=py;
        if(unicode=='\n') {
            py += ceil(size*CAIROLINESPACE);
            px = 0;
            previdx=0;
            continue;
        }
        glyph.index = FT_Get_Char_Index(face->ftface, unicode);
        if( has_kerning && previdx ) {
            FT_Vector delta;
            FT_Get_Kerning( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta );
            px += delta.x / 64.;
        }
        cairo_glyph_extents(cache->dummycr,&glyph,1,&extents);
        
        if(i==0) {
            rect->minx = px+extents.x_bearing;
            rect->miny = py+extents.y_bearing;
            rect->maxx = px+extents.x_bearing+extents.width;
            rect->maxy = py+extents.y_bearing+extents.height;
        } else {
            rect->minx = MS_MIN(rect->minx,px+extents.x_bearing);
            rect->miny = MS_MIN(rect->miny,py+extents.y_bearing);
            rect->maxy = MS_MAX(rect->maxy,py+extents.y_bearing+extents.height);
            rect->maxx = MS_MAX(rect->maxx,px+extents.x_bearing+extents.width);
        }
        if(advances!=NULL)
            (*advances)[i]=extents.x_advance;
        px += extents.x_advance;
        previdx=glyph.index;
    }
    /*
    rect->minx = 0;
    rect->miny = 0;
    rect->maxx = 1;
    rect->maxy = 1;
    */
    return MS_SUCCESS;
}
Exemple #4
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;
}
/**
 * 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;
    }
  }
}
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;
}