I started chasing down a font rendering issue in FlightGear on Sunday.
The original issue was a metrics bug in the afm2txf.pl font generator,
a script I wrote for plib a while back.  But fixing that didn't quite
solve all the problems, so I spent some time hunting around in the PUI
rendering code and fixing buglets.  The patch is attached.
Explanations:

There was a hard-coded assumption in fnt.cxx that when rendering
multi-line strings the interline distance was 1.333 * pointsize.  My
guess is that this was there as a workaround for an older bug
somewhere; pointsize is, of course, the very definition of interline
distance.

Likewise, puFont has a getStringHeight() with the same baked-in
constant.  I rewrote this to use the more common GUI convention that
the height of a single line of text is "ascender + descender", instead
of the full point size (which includes significant whitespace in many
fonts).

Once that was changed, it exposed some weirdness in the vertical
positioning code in puInput and puObject.  I'm honestly not sure what
the older formulas were trying to do.  I changed them all to adhere to
the line height convention above (i.e.: ascender + descender + (Nlines
- 1) * pointsize).  Vertical centering of text now looks significantly
better.

The dashed line rendered for the "default" button almost always cut
right through the button text.  I moved it out by three pixels, which
gives it one pixel of margin from the edge of the thickest widget
border.  I also changed the stipple to a simpler 1010 pattern from the
four-pixel dash pattern it originally had.  IMHO, the tighter pattern
is prettier.

The rendering code for the "default" line also had a coordinate
aliasing bug: when drawing GL_LINES, you have to use pixel center
coordinates or else the GL will see a value exactly on the edge of two
pixels and you'll get funny off-by-one artifacts.

I fixed a similar coordinate issue with the puInput caret rendering.
I also increased its height; most GUIs draw this from the bottom of
the descender to the baseline of the next line.

I tried this with a bunch of test code (and FlightGear, of course) and
it doesn't seem to break anything.

Andy
Index: src/fnt/fnt.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/fnt/fnt.cxx,v
retrieving revision 1.12
diff -u -r1.12 fnt.cxx
--- src/fnt/fnt.cxx	26 Oct 2002 14:24:59 -0000	1.12
+++ src/fnt/fnt.cxx	4 May 2004 18:41:15 -0000
@@ -235,7 +235,7 @@
     if (*s == '\n')
     {
       curpos[0]  = origx ;
-      curpos[1] -= pointsize * 1.333f ;
+      curpos[1] -= pointsize ;
     }
     else
       low_putch ( curpos, pointsize, italic, *s ) ;
Index: src/pui/pu.h
===================================================================
RCS file: /cvsroot/plib/plib/src/pui/pu.h,v
retrieving revision 1.147
diff -u -r1.147 pu.h
--- src/pui/pu.h	6 Apr 2004 12:53:16 -0000	1.147
+++ src/pui/pu.h	4 May 2004 18:41:15 -0000
@@ -62,9 +62,11 @@
     slant = sl ;
   }
 
+  float getPointSize ( ) const { return pointsize; }
+
   int getStringDescender ( void ) const ;
   int getStringHeight ( const char *str ) const ;
-  int getStringHeight ( void ) const { return getStringHeight ( "K" ) ; }
+  int getStringHeight ( void ) const { return getStringHeight ( "" ) ; }
 
   float getFloatStringWidth ( const char *str ) const ; 
   int   getStringWidth      ( const char *str ) const /* Deprecated ? */ 
Index: src/pui/puBox.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/pui/puBox.cxx,v
retrieving revision 1.10
diff -u -r1.10 puBox.cxx
--- src/pui/puBox.cxx	2 Sep 2002 06:05:45 -0000	1.10
+++ src/pui/puBox.cxx	4 May 2004 18:41:15 -0000
@@ -24,7 +24,7 @@
 
 #include "puLocal.h"
 
-#define PU_DFLT_OFFSET        8
+#define PU_DFLT_OFFSET        5
 
 void puBox::extend ( puBox *bx )
 {
@@ -250,13 +250,13 @@
   if ( am_default )
   {
     glColor4fv ( colour [ PUCOL_BACKGROUND ] ) ;
-    glLineStipple ( 1, 0xF0F0 ) ;
+    glLineStipple ( 1, 0xaaaa ) ; // 0x1249 is not bad either
     glEnable ( GL_LINE_STIPPLE ) ;
     glBegin ( GL_LINE_LOOP ) ;
-      glVertex2i ( dx + min[0] + PU_DFLT_OFFSET, dy + min[1] + PU_DFLT_OFFSET ) ;
-      glVertex2i ( dx + min[0] + PU_DFLT_OFFSET, dy + max[1] - PU_DFLT_OFFSET ) ;
-      glVertex2i ( dx + max[0] - PU_DFLT_OFFSET, dy + max[1] - PU_DFLT_OFFSET ) ;
-      glVertex2i ( dx + max[0] - PU_DFLT_OFFSET, dy + min[1] + PU_DFLT_OFFSET ) ;
+      glVertex2f ( dx + min[0] + PU_DFLT_OFFSET + 0.5f, dy + min[1] + PU_DFLT_OFFSET + 0.5f ) ;
+      glVertex2f ( dx + min[0] + PU_DFLT_OFFSET + 0.5f, dy + max[1] - PU_DFLT_OFFSET - 0.5f ) ;
+      glVertex2f ( dx + max[0] - PU_DFLT_OFFSET - 0.5f, dy + max[1] - PU_DFLT_OFFSET - 0.5f ) ;
+      glVertex2f ( dx + max[0] - PU_DFLT_OFFSET - 0.5f, dy + min[1] + PU_DFLT_OFFSET + 0.5f ) ;
     glEnd () ;
     glDisable ( GL_LINE_STIPPLE ) ;
   }
Index: src/pui/puFont.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/pui/puFont.cxx,v
retrieving revision 1.23
diff -u -r1.23 puFont.cxx
--- src/pui/puFont.cxx	16 Feb 2004 13:49:03 -0000	1.23
+++ src/pui/puFont.cxx	4 May 2004 18:41:16 -0000
@@ -75,15 +75,21 @@
 
 int puFont::getStringHeight ( const char *s ) const
 {
-  /* Height *excluding* descender */
+    if (!s || !fnt_font_handle) return 0 ;
 
-  if ( s == NULL )
-    return 0 ;
-
-  if ( fnt_font_handle != NULL )
-    return int ( pointsize * ( 1.333f * count_lines ( s ) - 0.333f ) ) ;
-
-  return 0 ;
+    // The height of a single line is the ascender plus descender, not
+    // including whitespace above and below.  Each additional line
+    // adds one point size, of course.  Remember to round up to avoid
+    // overlapping artifacts. The bbox string is just a sample of
+    // "likely to be tall" glyphs.
+    float ascend;
+    fnt_font_handle -> getBBox ( "$lfKL", pointsize, slant, NULL, NULL, NULL, &ascend ) ;
+    float height = ascend + getStringDescender() ;
+    int lines = count_lines ( s ) ;
+    if(lines > 1)
+        height += ( lines - 1 ) * pointsize ;
+    return int ( height + 0.999 ) ;
+    // return int ( pointsize * count_lines ( s ) + 0.999 ) - getStringDescender();
 }
 
 
Index: src/pui/puFrame.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/pui/puFrame.cxx,v
retrieving revision 1.12
diff -u -r1.12 puFrame.cxx
--- src/pui/puFrame.cxx	2 Sep 2002 06:05:45 -0000	1.12
+++ src/pui/puFrame.cxx	4 May 2004 18:41:16 -0000
@@ -40,5 +40,3 @@
 
   draw_label ( dx, dy ) ;
 }
-
-
Index: src/pui/puInput.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/pui/puInput.cxx,v
retrieving revision 1.34
diff -u -r1.34 puInput.cxx
--- src/pui/puInput.cxx	23 Feb 2004 04:16:52 -0000	1.34
+++ src/pui/puInput.cxx	4 May 2004 18:41:16 -0000
@@ -82,7 +82,8 @@
   else
   {
     int xx = legendFont.getStringWidth ( " " ) ;
-    int yy = ( abox.max[1] - abox.min[1] - legendFont.getStringHeight () ) / 2 ;
+    int yy = ( ( abox.max[1] - abox.min[1] - legendFont.getStringHeight () ) / 2
+               + legendFont.getStringDescender () ) ;
 
     int ncut ;
     char *s2 ;
@@ -150,20 +151,20 @@
       {
         s2 [ cursor_position-ncut ] = '\0' ;
 
-        int cpos = legendFont.getStringWidth ( s2 ) + xx + dx + abox.min[0] ;
-        int top = yy + legendFont.getStringHeight () ;
-        int bot = yy - legendFont.getStringDescender() ;
+        float cpos = 0.5f + legendFont.getStringWidth ( s2 ) + xx + dx + abox.min[0] ;
+        float top = 0.5f + dy + abox.min[1] + yy + legendFont.getPointSize () ;
+        float bot = 0.5f + dy + abox.min[1] + yy - legendFont.getStringDescender() ;
 
         glColor4fv ( colour [ PUCOL_MISC ] ) ;
         glBegin   ( GL_LINES ) ;
-        glVertex2i ( cpos    , dy + abox.min[1] + bot ) ;
-        glVertex2i ( cpos    , dy + abox.min[1] + top ) ;
-        glVertex2i ( cpos - 1, dy + abox.min[1] + bot ) ;
-        glVertex2i ( cpos - 1, dy + abox.min[1] + top ) ;
-        glVertex2i ( cpos - 4, dy + abox.min[1] + bot ) ;
-        glVertex2i ( cpos + 3, dy + abox.min[1] + bot ) ;
-        glVertex2i ( cpos - 4, dy + abox.min[1] + top ) ;
-        glVertex2i ( cpos + 3, dy + abox.min[1] + top ) ;
+        glVertex2f ( cpos    , bot ) ;
+        glVertex2f ( cpos    , top ) ;
+        glVertex2f ( cpos - 1, bot ) ;
+        glVertex2f ( cpos - 1, top ) ;
+        glVertex2f ( cpos - 3, bot ) ;
+        glVertex2f ( cpos + 3, bot ) ;
+        glVertex2f ( cpos - 3, top ) ;
+        glVertex2f ( cpos + 3, top ) ;
         glEnd      () ;
       }
     }
Index: src/pui/puObject.cxx
===================================================================
RCS file: /cvsroot/plib/plib/src/pui/puObject.cxx,v
retrieving revision 1.49
diff -u -r1.49 puObject.cxx
--- src/pui/puObject.cxx	19 Sep 2002 23:32:58 -0000	1.49
+++ src/pui/puObject.cxx	4 May 2004 18:41:16 -0000
@@ -337,9 +337,9 @@
   case PUPLACE_LOWER_LEFT        : /* Backwards compatibility to PUPLACE_LEFT */
   case PUPLACE_LOWER_RIGHT       : /* Backwards compatibility to PUPLACE_RIGHT */
   default :
-    yy = ( abox.max[1] - abox.min[1] +
-      legendFont.getStringHeight ( legend ) ) / 2 -
-      legendFont.getStringHeight () ;
+    yy = ( abox.max[1] - abox.min[1] 
+           - legendFont.getStringHeight ( legend ) ) / 2 
+      + legendFont.getStringDescender () ;
     break ;
 
   case PUPLACE_BOTTOM_LEFT     :
@@ -427,9 +427,9 @@
   case PUPLACE_CENTERED_LEFT  :
   case PUPLACE_CENTERED_RIGHT :
   default :
-    yy = ( bbox.max[1] - bbox.min[1] +
-      labelFont.getStringHeight ( label ) ) / 2 -
-      labelFont.getStringHeight () ;
+    yy = ( bbox.max[1] - bbox.min[1] -
+      labelFont.getStringHeight ( label ) ) / 2 +
+      labelFont.getStringDescender () ;
     break ;
 
   case PUPLACE_LOWER_LEFT  :
Index: tools/src/afm2txf/afm2txf.pl
===================================================================
RCS file: /cvsroot/plib/plib/tools/src/afm2txf/afm2txf.pl,v
retrieving revision 1.3
diff -u -r1.3 afm2txf.pl
--- tools/src/afm2txf/afm2txf.pl	15 Aug 2002 19:30:36 -0000	1.3
+++ tools/src/afm2txf/afm2txf.pl	4 May 2004 18:41:16 -0000
@@ -176,8 +176,8 @@
     # the downsampling.
     my $w = round($m->[3] * $LINEHGT * $TEXSIZ + 2*$PADDING);
     my $h = round($m->[4] * $LINEHGT * $TEXSIZ + 2*$PADDING);
-    my $xoff = -round($m->[1] * $LINEHGT * $TEXSIZ - $PADDING);
-    my $yoff = -round($m->[2] * $LINEHGT * $TEXSIZ - $PADDING);
+    my $xoff = -round($m->[1] * $LINEHGT * $TEXSIZ) - $PADDING;
+    my $yoff = -round($m->[2] * $LINEHGT * $TEXSIZ) - $PADDING;
     my $x = round($p->[0] * $TEXSIZ - $PADDING);
     my $y = round($p->[1] * $TEXSIZ - $PADDING);
 
_______________________________________________
Flightgear-devel mailing list
[EMAIL PROTECTED]
http://mail.flightgear.org/mailman/listinfo/flightgear-devel

Reply via email to