[mapserver-commits] r12878 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Sat Dec 10 07:09:44 EST 2011


Author: tbonfort
Date: 2011-12-10 04:09:44 -0800 (Sat, 10 Dec 2011)
New Revision: 12878

Modified:
   trunk/mapserver/HISTORY.TXT
   trunk/mapserver/mapagg.cpp
   trunk/mapserver/mapcairo.c
   trunk/mapserver/mapdummyrenderer.c
   trunk/mapserver/mapgd.c
   trunk/mapserver/mapkml.cpp
   trunk/mapserver/mapkmlrenderer.h
   trunk/mapserver/maplabel.c
   trunk/mapserver/mapogl.cpp
   trunk/mapserver/mapoglrenderer.cpp
   trunk/mapserver/mapoglrenderer.h
   trunk/mapserver/maprendering.c
   trunk/mapserver/mapserver.h
   trunk/mapserver/mapsymbol.c
   trunk/mapserver/maputil.c
Log:
add RFC80 font fallback


Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/HISTORY.TXT	2011-12-10 12:09:44 UTC (rev 12878)
@@ -14,6 +14,7 @@
 
 Current Version (SVN trunk, 6.1-dev, future 6.2): 
 -------------------------------------------------
+- Add RFC80 font fallback support (#4114)
 
 - Added POLAROFFSET style option for a different symbol transform (#4117)
 

Modified: trunk/mapserver/mapagg.cpp
===================================================================
--- trunk/mapserver/mapagg.cpp	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapagg.cpp	2011-12-10 12:09:44 UTC (rev 12878)
@@ -286,12 +286,13 @@
 int agg2RenderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text) {
    AGG2Renderer *r = AGG_RENDERER(img);
    aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img));
-   if (!cache->m_feng.load_font(style->font, 0, mapserver::glyph_ren_outline)) {
-      msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", style->font);
+   if (!cache->m_feng.load_font(style->fonts[0], 0, mapserver::glyph_ren_outline)) {
+      msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", style->fonts[0]);
       return MS_FAILURE;
    }
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
 
+   int curfontidx = 0;
    const mapserver::glyph_cache* glyph;
    int unicode;
    //cache->m_feng.hinting(true);
@@ -323,11 +324,38 @@
          continue;
       }
       utfptr += msUTF8ToUniChar(utfptr, &unicode);
+      if(curfontidx != 0) {
+         if (!cache->m_feng.load_font(style->fonts[0], 0, mapserver::glyph_ren_outline)) {
+            msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", style->fonts[0]);
+            return MS_FAILURE;
+         }
+         curfontidx = 0;
+      }
+
       glyph = cache->m_fman.glyph(unicode);
-      ;
+
+      if(!glyph || glyph->glyph_index == 0) {
+         int i;
+         for(i=1;i<style->numfonts;i++) {
+            if (!cache->m_feng.load_font(style->fonts[i], 0, mapserver::glyph_ren_outline)) {
+               msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", style->fonts[i]);
+               return MS_FAILURE;
+            }
+            curfontidx = i;
+            cache->m_feng.height(style->size);
+            cache->m_feng.resolution(96);
+            cache->m_feng.flip_y(true);
+            glyph = cache->m_fman.glyph(unicode);
+            if(glyph && glyph->glyph_index != 0) {
+               break;
+            }
+         }
+      }
+
+
       if (glyph) {
          //cache->m_fman.add_kerning(&fx, &fy);
-    	 cache->m_fman.init_embedded_adaptors(glyph, fx, fy);
+         cache->m_fman.init_embedded_adaptors(glyph, fx, fy);
          mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx);
          glyphs.concat_path(trans_c);
          fx += glyph->advance_x;
@@ -410,14 +438,15 @@
 int agg2RenderGlyphsLine(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text) {
    AGG2Renderer *r = AGG_RENDERER(img);
    aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img));
-   if (!cache->m_feng.load_font(style->font, 0, mapserver::glyph_ren_outline)) {
-      msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", style->font);
+   if (!cache->m_feng.load_font(style->fonts[0], 0, mapserver::glyph_ren_outline)) {
+      msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphsLine()", style->fonts[0]);
       return MS_FAILURE;
    }
    r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero);
 
    const mapserver::glyph_cache* glyph;
    int unicode;
+   int curfontidx = 0;
    //cache->m_feng.hinting(true);
    cache->m_feng.height(style->size);
    cache->m_feng.resolution(96);
@@ -433,7 +462,34 @@
       mtx *= mapserver::trans_affine_rotation(-labelpath->angles[i]);
       mtx *= mapserver::trans_affine_translation(labelpath->path.point[i].x,labelpath->path.point[i].y);
       text += msUTF8ToUniChar(text, &unicode);
+
+      if(curfontidx != 0) {
+         if (!cache->m_feng.load_font(style->fonts[0], 0, mapserver::glyph_ren_outline)) {
+            msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphsLine()", style->fonts[0]);
+            return MS_FAILURE;
+         }
+         curfontidx = 0;
+      }
+
       glyph = cache->m_fman.glyph(unicode);
+
+      if(!glyph || glyph->glyph_index == 0) {
+         int i;
+         for(i=1;i<style->numfonts;i++) {
+            if (!cache->m_feng.load_font(style->fonts[i], 0, mapserver::glyph_ren_outline)) {
+               msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphsLine()", style->fonts[i]);
+               return MS_FAILURE;
+            }
+            curfontidx = i;
+            cache->m_feng.height(style->size);
+            cache->m_feng.resolution(96);
+            cache->m_feng.flip_y(true);
+            glyph = cache->m_fman.glyph(unicode);
+            if(glyph && glyph->glyph_index != 0) {
+               break;
+            }
+         }
+      }
       if (glyph) {
          cache->m_fman.init_embedded_adaptors(glyph, labelpath->path.point[i].x,labelpath->path.point[i].y);
          mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx);
@@ -793,25 +849,55 @@
 /*...*/
 
 /* helper functions */
-int agg2GetTruetypeTextBBox(rendererVTableObj *renderer, char *font, double size, char *string,
+int agg2GetTruetypeTextBBox(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string,
         rectObj *rect, double **advances) {
    
    aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(renderer);
-   if (!cache->m_feng.load_font(font, 0, mapserver::glyph_ren_outline)) {
-      msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2GetTruetypeTextBBox()", font);
+   if (!cache->m_feng.load_font(fonts[0], 0, mapserver::glyph_ren_outline)) {
+      msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2GetTruetypeTextBBox()", fonts[0]);
       return MS_FAILURE;
    }
    cache->m_feng.hinting(true);
    cache->m_feng.height(size);
    cache->m_feng.resolution(96);
    cache->m_feng.flip_y(true);
+   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 (!cache->m_feng.load_font(fonts[0], 0, mapserver::glyph_ren_outline)) {
+         msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", fonts[0]);
+         return MS_FAILURE;
+      }
+      cache->m_feng.height(size);
+      cache->m_feng.resolution(96);
+      cache->m_feng.flip_y(true);
+      curfontidx = 0;
+   }
    glyph = cache->m_fman.glyph(unicode);
+   if(!glyph || glyph->glyph_index == 0) {
+      int i;
+      for(i=1;i<numfonts;i++) {
+         if (!cache->m_feng.load_font(fonts[i], 0, mapserver::glyph_ren_outline)) {
+            msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", fonts[i]);
+            return MS_FAILURE;
+         }
+         curfontidx = i;
+         cache->m_feng.height(size);
+         cache->m_feng.resolution(96);
+         cache->m_feng.flip_y(true);
+         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;
@@ -842,7 +928,34 @@
          continue;
       }
       string += msUTF8ToUniChar(string, &unicode);
+      if(curfontidx != 0) {
+         if (!cache->m_feng.load_font(fonts[0], 0, mapserver::glyph_ren_outline)) {
+            msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", fonts[0]);
+            return MS_FAILURE;
+         }
+         cache->m_feng.height(size);
+         cache->m_feng.resolution(96);
+         cache->m_feng.flip_y(true);
+         curfontidx = 0;
+      }
       glyph = cache->m_fman.glyph(unicode);
+      if(!glyph || glyph->glyph_index == 0) {
+         int i;
+         for(i=1;i<numfonts;i++) {
+            if (!cache->m_feng.load_font(fonts[i], 0, mapserver::glyph_ren_outline)) {
+               msSetError(MS_TTFERR, "AGG error loading font (%s)", "agg2RenderGlyphs()", fonts[i]);
+               return MS_FAILURE;
+            }
+            curfontidx = i;
+            cache->m_feng.height(size);
+            cache->m_feng.resolution(96);
+            cache->m_feng.flip_y(true);
+            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);

Modified: trunk/mapserver/mapcairo.c
===================================================================
--- trunk/mapserver/mapcairo.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapcairo.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -64,8 +64,9 @@
 };
 
 int freeFaceCache(faceCacheObj *fc) {
-    /* printf("***\nface has %d references\n***\n",cairo_font_face_get_reference_count(fc->face)); */
+    /* printf("***\nface %s has %d cairo references\n***\n",fc->path,cairo_font_face_get_reference_count(fc->face)); */
     cairo_font_face_destroy(fc->face);
+    FT_Done_Face(fc->ftface);
     free(fc->path);
     return MS_SUCCESS;
 }
@@ -166,7 +167,7 @@
     newface->face = cairo_ft_font_face_create_for_ft_face(newface->ftface, 0);
 
     cairo_font_face_set_user_data (newface->face, &newface->facekey,
-            &(newface->ftface), (cairo_destroy_func_t) FT_Done_Face);
+            &(newface->ftface), (cairo_destroy_func_t) NULL); // we call FT_Done_Face ourselves in freeFaceCache
 
     newface->path = msStrdup(font);
     return newface;
@@ -450,29 +451,27 @@
 
 #define CAIROLINESPACE 1.33
 
-int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char *font, double size, char *text, rectObj *rect, double **advances) {
-    
-    
+int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *text, rectObj *rect, double **advances) {
     cairoCacheData *cache = MS_RENDERER_CACHE(renderer);
-    faceCacheObj *face = getFontFace(cache,font);
+    faceCacheObj* face = getFontFace(cache,fonts[0]);
  
+    int curfontidx = 0;
     char *utfptr=text;
-    int i,has_kerning,unicode;
+    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;
+	  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));
     }
@@ -487,10 +486,31 @@
             previdx=0;
             continue;
         }
+
+	if(curfontidx != 0) {
+	    face = getFontFace(cache,fonts[0]);
+    	    cairo_set_font_face(cache->dummycr,face->face);
+            curfontidx = 0;
+        }
+
         glyph.index = FT_Get_Char_Index(face->ftface, unicode);
-        if( has_kerning && previdx ) {
+
+	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( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &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);
@@ -510,6 +530,7 @@
             (*advances)[i]=extents.x_advance;
         px += extents.x_advance;
         previdx=glyph.index;
+	prevface = face;
     }
     /*
     rect->minx = 0;
@@ -523,18 +544,20 @@
 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);
+    faceCacheObj* face = getFontFace(cache,style->fonts[0]);
 
+    int curfontidx = 0;
     char *utfptr=text;
-    int i,has_kerning,unicode;
+    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;
+          return MS_FAILURE;
     }
 
     cairo_set_font_face(r->cr,face->face);
@@ -545,7 +568,6 @@
     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;
@@ -556,16 +578,35 @@
             previdx=0;
             continue;
         }
+	if(curfontidx != 0) {
+	    face = getFontFace(cache,style->fonts[0]);
+    	    cairo_set_font_face(r->cr,face->face);
+            curfontidx = 0;
+        }
         glyph.index = FT_Get_Char_Index(face->ftface, unicode);
-        if( has_kerning && previdx ) {
+	if(glyph.index == 0) {
+	     int j;
+	     for(j=1;j<style->numfonts;j++) {
+		    curfontidx = j;
+		    face = getFontFace(cache,style->fonts[j]);
+        	    glyph.index = FT_Get_Char_Index(face->ftface, unicode);
+		    if(glyph.index != 0) {
+    	    	       cairo_set_font_face(r->cr,face->face);
+		       break;
+		    }
+	     }
+	}
+
+        if(  FT_HAS_KERNING((prevface->ftface)) && previdx ) {
             FT_Vector delta;
-            FT_Get_Kerning( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta );
+            FT_Get_Kerning( prevface->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;
+	prevface=face;
     }
 
     if (style->outlinewidth > 0) {

Modified: trunk/mapserver/mapdummyrenderer.c
===================================================================
--- trunk/mapserver/mapdummyrenderer.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapdummyrenderer.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -166,7 +166,7 @@
 /*...*/
 
 /* helper functions */
-int getTruetypeTextBBoxDummy(rendererVTableObj *renderer, char *font, double size, char *string,rectObj *rect, double **advances) {
+int getTruetypeTextBBoxDummy(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string,rectObj *rect, double **advances) {
     msSetError(MS_RENDERERERR,"getTruetypeTextBBox not implemented","getTruetypeTextBBox()");
     return MS_FAILURE;
 }

Modified: trunk/mapserver/mapgd.c
===================================================================
--- trunk/mapserver/mapgd.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapgd.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -411,23 +411,23 @@
    }
    
    if(style->outlinewidth > 0) { /* handle the outline color */
-      error = gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x, y-1, text);
+      error = gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x, y-1, text);
       if(error) {
          msSetError(MS_TTFERR, error, "msDrawTextGD()");
          return(MS_FAILURE);
       }
 
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x, y+1, text);
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x+1, y, text);
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x-1, y, text);
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x-1, y-1, text);      
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x-1, y+1, text);
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x+1, y-1, text);
-      gdImageStringFT(ip, bbox, oc, style->font, style->size, style->rotation, x+1, y+1, text);
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x, y+1, text);
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x+1, y, text);
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x-1, y, text);
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x-1, y-1, text);      
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x-1, y+1, text);
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x+1, y-1, text);
+      gdImageStringFT(ip, bbox, oc, style->fonts[0], style->size, style->rotation, x+1, y+1, text);
    }
    
    if(style->color)
-      gdImageStringFT(ip, bbox, c, style->font, style->size, style->rotation, x, y, text);
+      gdImageStringFT(ip, bbox, c, style->fonts[0], style->size, style->rotation, x, y, text);
    return MS_SUCCESS;
 }
 
@@ -833,7 +833,7 @@
 	return MS_SUCCESS;
 }
 
-int getTruetypeTextBBoxGD(rendererVTableObj *renderer, char *font, double size, char *string, rectObj *rect, double **advances) {
+int getTruetypeTextBBoxGD(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances) {
 #ifdef USE_GD_FT
    int bbox[8];
    char *error;
@@ -843,7 +843,7 @@
       int k;
       gdFTStringExtra strex;
       strex.flags = gdFTEX_XSHOW;
-      error = gdImageStringFTEx(NULL, bbox, 0, font, size, 0, 0, 0, string, &strex);
+      error = gdImageStringFTEx(NULL, bbox, 0, fonts[0], size, 0, 0, 0, string, &strex);
       if(error) {
          msSetError(MS_TTFERR, error, "gdImageStringFTEx()");
          return(MS_FAILURE);
@@ -873,7 +873,7 @@
       return(MS_FAILURE);
 #endif
    } else {
-      error = gdImageStringFT(NULL, bbox, 0, font, size, 0, 0, 0, string);
+      error = gdImageStringFT(NULL, bbox, 0, fonts[0], size, 0, 0, 0, string);
       if(error) {
          msSetError(MS_TTFERR, error, "msGetTruetypeTextBBox()");
          return(MS_FAILURE);

Modified: trunk/mapserver/mapkml.cpp
===================================================================
--- trunk/mapserver/mapkml.cpp	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapkml.cpp	2011-12-10 12:09:44 UTC (rev 12878)
@@ -138,7 +138,7 @@
 }
 
 
-int msGetTruetypeTextBBoxKml(rendererVTableObj *r,char *font, double size, char *string,
+int msGetTruetypeTextBBoxKml(rendererVTableObj *r,char** fonts, int numfonts, double size, char *string,
 		rectObj *rect, double **advances)
 {
    rect->minx=0.0;

Modified: trunk/mapserver/mapkmlrenderer.h
===================================================================
--- trunk/mapserver/mapkmlrenderer.h	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapkmlrenderer.h	2011-12-10 12:09:44 UTC (rev 12878)
@@ -167,7 +167,7 @@
     void renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
     void renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style);
 
-    int getTruetypeTextBBox(imageObj *img,char *font, double size, char *string, rectObj *rect, double **advances);
+    int getTruetypeTextBBox(imageObj *img,char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances);
     int mergeRasterBuffer(imageObj *image, rasterBufferObj *rb);
 };
 

Modified: trunk/mapserver/maplabel.c
===================================================================
--- trunk/mapserver/maplabel.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/maplabel.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -699,10 +699,14 @@
 #endif
 }
 
-int msGetTruetypeTextBBox(rendererVTableObj *renderer, char *font, double size, char *string, rectObj *rect, double **advances) {
-	if(renderer) {
-		return renderer->getTruetypeTextBBox(renderer,font,size,string,rect,advances);
-	} 
+int msGetTruetypeTextBBox(rendererVTableObj *renderer, char* fontstring, fontSetObj *fontset, double size, char *string, rectObj *rect, double **advances) {
+   const char *lookedUpFonts[MS_MAX_LABEL_FONTS];
+   int numfonts;
+   if(MS_FAILURE == msFontsetLookupFonts(fontstring, &numfonts, fontset, lookedUpFonts))
+      return MS_FAILURE;
+   if(renderer) {
+      return renderer->getTruetypeTextBBox(renderer,lookedUpFonts,numfonts,size,string,rect,advances);
+   } 
 #ifdef USE_GD_FT
 	else {
         int bbox[8];
@@ -713,9 +717,9 @@
             int k;
             gdFTStringExtra strex;
             strex.flags = gdFTEX_XSHOW;
-            error = gdImageStringFTEx(NULL, bbox, 0, font, size, 0, 0, 0, string, &strex);
+            error = gdImageStringFTEx(NULL, bbox, 0, lookedUpFonts[0], size, 0, 0, 0, string, &strex);
             if(error) {
-                msSetError(MS_TTFERR, error, "gdImageStringFTEx()");
+                msSetError(MS_TTFERR, "gdImageStringFT: %s (%s)", "msGetTruetypeTextBBox()", error, lookedUpFonts[0]);
                 return(MS_FAILURE);
             }
 
@@ -743,9 +747,9 @@
             return MS_FAILURE;
 #endif
         } else {
-            error = gdImageStringFT(NULL, bbox, 0, font, size, 0, 0, 0, string);
+            error = gdImageStringFT(NULL, bbox, 0, lookedUpFonts[0], size, 0, 0, 0, string);
             if(error) {
-                msSetError(MS_TTFERR, "gdImageStringFT: %s (%s)", "msGetTruetypeTextBBox()", error, font);
+                msSetError(MS_TTFERR, "gdImageStringFT: %s (%s)", "msGetTruetypeTextBBox()", error, lookedUpFonts[0]);
                 return(MS_FAILURE);
             }
 
@@ -808,6 +812,47 @@
 	}
 	return font;
 }
+
+int msFontsetLookupFonts(char* fontstring, int *numfonts, fontSetObj *fontset, const char **lookedUpFonts) {
+	char *start,*ptr;
+   *numfonts = 0;
+   start = ptr = fontstring;
+   while(*numfonts<MS_MAX_LABEL_FONTS) {
+      if(*ptr==',') {
+         if(start==ptr) { /*first char is a comma, or two successive commas*/
+            start = ++ptr;
+            continue;
+         }
+         *ptr = 0;
+         lookedUpFonts[*numfonts] = msLookupHashTable(&(fontset->fonts), start);
+         *ptr = ',';
+         if (!lookedUpFonts[*numfonts]) {
+            msSetError(MS_TTFERR, "Requested font (%s) not found.","msFontsetLookupFonts()", fontstring);
+            return MS_FAILURE;
+         }
+         start = ++ptr;
+         (*numfonts)++;
+      } else if(*ptr==0) {
+         if(start==ptr) { /* last char of string was a comma */
+            return MS_SUCCESS;
+         }
+         lookedUpFonts[*numfonts] = msLookupHashTable(&(fontset->fonts), start);
+         if (!lookedUpFonts[*numfonts]) {
+            msSetError(MS_TTFERR, "Requested font (%s) not found.","msFontsetLookupFonts()", fontstring);
+            return (MS_FAILURE);
+         }
+         (*numfonts)++;
+         return MS_SUCCESS;
+      } else {
+         ptr++;
+      }
+   }
+   msSetError(MS_TTFERR, "Requested font (%s) not has too many members (max is %d)",
+         "msFontsetLookupFonts()", fontstring, MS_MAX_LABEL_FONTS);
+   return MS_FAILURE;
+}
+
+
 /*
 ** Note: All these routines assume a reference point at the LL corner of the text. GD's
 ** bitmapped fonts use UL and this is compensated for. Note the rect is relative to the
@@ -825,12 +870,11 @@
   if (!renderer)
     return MS_FAILURE;
   if(label->type == MS_TRUETYPE) {
-    char *font=msFontsetLookupFont(&(map->fontset), label->font);
-    if(!font) {
-    	/* error message already set in fontset lookup */
-    	return MS_FAILURE;
-    }
-    return msGetTruetypeTextBBox(renderer,font,size,string,rect,advances);
+     if(!label->font) {
+        msSetError(MS_MISCERR, "label has no true type font", "msGetLabelSize()");
+        return MS_FAILURE;
+     }
+     return msGetTruetypeTextBBox(renderer,label->font,&(map->fontset),size,string,rect,advances);
   } else if(label->type == MS_BITMAP){
 	  if(renderer->supports_bitmap_fonts)
 		  return msGetRasterTextBBox(renderer,MS_NINT(label->size),string,rect);

Modified: trunk/mapserver/mapogl.cpp
===================================================================
--- trunk/mapserver/mapogl.cpp	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapogl.cpp	2011-12-10 12:09:44 UTC (rev 12878)
@@ -126,9 +126,9 @@
     return MS_SUCCESS;
 }
 
-int msGetTruetypeTextBBoxOgl(rendererVTableObj *renderer, char *font, double size, char *string, rectObj *rect, double **advances)
+int msGetTruetypeTextBBoxOgl(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances)
 {    
-    if (OglRenderer::getStringBBox(font, size, string, rect, advances))
+    if (OglRenderer::getStringBBox(fonts[0], size, string, rect, advances))
     {
         return MS_SUCCESS;
     }
@@ -142,7 +142,7 @@
             labelStyleObj *style, char *text)        
 {
     OglRenderer* renderer = getOglRenderer(img);
-    renderer->renderGlyphs(x, y, style->color, style->outlinecolor, style->size, style->font, text, style->rotation, NULL, 0.0, 0.0);
+    renderer->renderGlyphs(x, y, style->color, style->outlinecolor, style->size, style->fonts[0], text, style->rotation, NULL, 0.0, 0.0);
     return MS_SUCCESS;
 }
 

Modified: trunk/mapserver/mapoglrenderer.cpp
===================================================================
--- trunk/mapserver/mapoglrenderer.cpp	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapoglrenderer.cpp	2011-12-10 12:09:44 UTC (rev 12878)
@@ -579,7 +579,7 @@
 }
 
 void OglRenderer::renderGlyphs(double x, double y, colorObj *color,
-        colorObj *outlinecolor, double size, char* font, char *thechars, double angle,
+        colorObj *outlinecolor, double size, const char* font, char *thechars, double angle,
         colorObj *shadowcolor, double shdx, double shdy)
 {
     makeCurrent();    
@@ -734,7 +734,7 @@
     return true;
 }
 
-FTFont* OglRenderer::getFTFont(char* font, double size)
+FTFont* OglRenderer::getFTFont(const char* font, double size)
 {
     FTFont** face = &fontCache[font][size];
     if (*face == NULL && ifstream(font))

Modified: trunk/mapserver/mapoglrenderer.h
===================================================================
--- trunk/mapserver/mapoglrenderer.h	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapoglrenderer.h	2011-12-10 12:09:44 UTC (rev 12878)
@@ -65,7 +65,7 @@
 
     void renderPolyline(shapeObj *p, colorObj *c, double width, int patternlength, double* pattern, int lineCap = MS_CJC_ROUND, int joinStyle = MS_CJC_ROUND, colorObj *outlinecolor = NULL, double outlinewidth = 0);
     void renderPolygon(shapeObj*, colorObj *color, colorObj *outlinecolor, double outlinewidth, const OglCachePtr& tile = OglCachePtr(), int lineCap=MS_CJC_ROUND, int joinStyle=MS_CJC_ROUND);
-    void renderGlyphs(double x, double y, colorObj *color, colorObj *outlinecolor, double size, char* font, char *thechars, double angle, colorObj *shadowcolor, double shdx, double shdy);
+    void renderGlyphs(double x, double y, colorObj *color, colorObj *outlinecolor, double size, const char* font, char *thechars, double angle, colorObj *shadowcolor, double shdx, double shdy);
     void renderPixmap(symbolObj *symbol, double x, double y, double angle, double scale);
     void renderEllipse(double x, double y, double angle, double w, double h, colorObj *color, colorObj *outlinecolor, double outlinewidth);
     void renderVectorSymbol(double x, double y, symbolObj *symbol, double scale, double angle, colorObj *c, colorObj *oc, double ow);
@@ -96,10 +96,10 @@
     GLsizei viewportWidth;
     GLsizei viewportHeight;
 
-    typedef std::map<char*,std::map<double,FTFont*> > fontCache_t;
+    typedef std::map<const char*,std::map<double,FTFont*> > fontCache_t;
     typedef std::map<symbolObj*,std::map<double,GLuint> > dashCache_t;
 
-    static FTFont* getFTFont(char* font, double size);
+    static FTFont* getFTFont(const char* font, double size);
     bool loadLine(shapeObj* shape, double width, int patternlength, double *pattern);
     double drawQuad(pointObj *p1, pointObj *p2, double width, double tilelength = 0.0, double textureStart = 0.0);
     double drawTriangles(pointObj *p1, pointObj *p2, double width, double tilelength = 0.0, double textureStart = 0.0);

Modified: trunk/mapserver/maprendering.c
===================================================================
--- trunk/mapserver/maprendering.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/maprendering.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -48,14 +48,12 @@
          return (MS_FAILURE);
       }
 
-      if (!l->font) {
-         msSetError(MS_TTFERR, "No Trueype font defined.","msDrawText()");
+      if (!l->font || !(*l->font)) {
          return (MS_FAILURE);
       }
 
-      s->font = msLookupHashTable(&(fontset->fonts), l->font);
-      if (!s->font) {
-         return (MS_FAILURE);
+      if(MS_FAILURE == msFontsetLookupFonts(l->font,&s->numfonts,fontset,&s->fonts)) {
+         return MS_FAILURE;
       }
    }
    s->rotation = l->angle * MS_DEG_TO_RAD;
@@ -325,7 +323,7 @@
       symbol_height = MS_MAX(1,symbol->sizey*style->scale);
    } else {
       rectObj rect;
-      if(MS_SUCCESS != renderer->getTruetypeTextBBox(renderer,symbol->full_font_path,style->scale,
+      if(MS_SUCCESS != renderer->getTruetypeTextBBox(renderer,&symbol->full_font_path,1,style->scale,
             symbol->character,&rect,NULL))
          return MS_FAILURE;
       symbol_width=rect.maxx-rect.minx;

Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapserver.h	2011-12-10 12:09:44 UTC (rev 12878)
@@ -228,6 +228,7 @@
 #define MS_STYLE_ALLOCSIZE 4
 
 #define MS_MAX_LABEL_PRIORITY     10
+#define MS_MAX_LABEL_FONTS     5
 #define MS_DEFAULT_LABEL_PRIORITY 1
 
 /* General defines, not wrapable */
@@ -1990,9 +1991,10 @@
 MS_DLL_EXPORT int msInitFontSet(fontSetObj *fontset);
 MS_DLL_EXPORT int msFreeFontSet(fontSetObj *fontset);
 MS_DLL_EXPORT char *msFontsetLookupFont(fontSetObj *fontset, char *fontKey);
+MS_DLL_EXPORT int msFontsetLookupFonts(char* fontstring, int *numfonts, fontSetObj *fontset, const char **lookedUpFonts);
 
 MS_DLL_EXPORT char *msTransformLabelText(mapObj *map, imageObj* image, labelObj *label, char *text);
-MS_DLL_EXPORT int msGetTruetypeTextBBox(rendererVTableObj *renderer, char *font, double size, char *string, rectObj *rect, double **advances);
+MS_DLL_EXPORT int msGetTruetypeTextBBox(rendererVTableObj *renderer, char* fontstring, fontSetObj *fontset, double size, char *string, rectObj *rect, double **advances);
 
 MS_DLL_EXPORT int msGetLabelSize(mapObj *map, labelObj *label, char *string, double size, rectObj *rect, double **advances);
 MS_DLL_EXPORT int msAddLabel(mapObj *map, int layerindex, int classindex, shapeObj *shape, pointObj *point, labelPathObj *labelpath, char *string, double featuresize, labelObj *label);
@@ -2615,7 +2617,8 @@
  */
 typedef struct {
     /* full path to truetype font file */
-    char *font;
+    const char* fonts[MS_MAX_LABEL_FONTS];
+    int numfonts;
     double size;
     double rotation;
     colorObj *color;
@@ -2624,7 +2627,7 @@
     int antialias; /*only for GD*/
 } labelStyleObj;
 
-#define INIT_LABEL_STYLE(s) {(s).font=NULL; (s).size=0; (s).rotation=0; (s).color=NULL; (s).outlinewidth=0; (s).outlinecolor=NULL;}
+#define INIT_LABEL_STYLE(s) {memset(&(s),'\0',sizeof(labelStyleObj));}
 
 #ifndef SWIG
 MS_DLL_EXPORT int msInitializeDummyRenderer(rendererVTableObj *vtable);
@@ -2749,7 +2752,7 @@
 	/*...*/
 
 	/* helper functions */
-	int (*getTruetypeTextBBox)(rendererVTableObj *renderer, char *font, double size, char *string, rectObj *rect, double **advances);
+	int (*getTruetypeTextBBox)(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances);
 
 	int (*startLayer)(imageObj *img, mapObj *map, layerObj *layer);
 	int (*endLayer)(imageObj *img, mapObj *map, layerObj *layer);

Modified: trunk/mapserver/mapsymbol.c
===================================================================
--- trunk/mapserver/mapsymbol.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/mapsymbol.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -664,15 +664,7 @@
    
 #ifdef USE_GD_FT
   case(MS_SYMBOL_TRUETYPE):
-	if(!symbol->full_font_path) {
-		char *font = msLookupHashTable(&(symbolset->fontset->fonts),symbol->font);
-		if(!font) {
-			msSetError(MS_MISCERR,"font (%s) not found in fontset","msGetMarkerSize()",symbol->font);
-			return(MS_FAILURE);
-		}
-		symbol->full_font_path =  msStrdup(font);
-	}
-    if(msGetTruetypeTextBBox(MS_MAP_RENDERER(symbolset->map),symbol->full_font_path,size,symbol->character,&rect,NULL) != MS_SUCCESS) 
+    if(msGetTruetypeTextBBox(MS_MAP_RENDERER(symbolset->map),symbol->font,symbolset->fontset,size,symbol->character,&rect,NULL) != MS_SUCCESS) 
       return(MS_FAILURE);
 
     *width = (int) MS_MAX(*width, rect.maxx - rect.minx);

Modified: trunk/mapserver/maputil.c
===================================================================
--- trunk/mapserver/maputil.c	2011-12-10 09:29:20 UTC (rev 12877)
+++ trunk/mapserver/maputil.c	2011-12-10 12:09:44 UTC (rev 12878)
@@ -231,8 +231,10 @@
       }
 
       if(label->bindings[MS_LABEL_BINDING_FONT].index != -1) {
-        msFree(label->font);
-        label->font = msStrdup(shape->values[label->bindings[MS_LABEL_BINDING_FONT].index]);
+         if(strcmp(label->font,shape->values[label->bindings[MS_LABEL_BINDING_FONT].index])) {
+            msFree(label->font);
+            label->font = msStrdup(shape->values[label->bindings[MS_LABEL_BINDING_FONT].index]);
+         }
       }
 
       if(label->bindings[MS_LABEL_BINDING_PRIORITY].index != -1) {



More information about the mapserver-commits mailing list