Revision: 4111
          http://vexi.svn.sourceforge.net/vexi/?rev=4111&view=rev
Author:   clrg
Date:     2011-04-19 13:04:32 +0000 (Tue, 19 Apr 2011)

Log Message:
-----------
Fix #47 - tweak glyph rendering and add [commented out] alternative rendering 
logic

Modified Paths:
--------------
    trunk/org.vexi-core.main/src/main/java/org/vexi/graphics/Font.java

Modified: trunk/org.vexi-core.main/src/main/java/org/vexi/graphics/Font.java
===================================================================
--- trunk/org.vexi-core.main/src/main/java/org/vexi/graphics/Font.java  
2011-04-15 00:55:53 UTC (rev 4110)
+++ trunk/org.vexi-core.main/src/main/java/org/vexi/graphics/Font.java  
2011-04-19 13:04:32 UTC (rev 4111)
@@ -47,6 +47,7 @@
         public int width = -1;                  ///< the width of the glyph
         public int height = -1;                 ///< the height of the glyph
         public byte[] data = null;              ///< the alpha channel samples 
for this font
+        public int widthadjust = 0;             ///< no kerning; adjust width 
according to sub-pixel alphas
         void render() {
             if (!isLoaded) {
                 try { font.renderGlyph(this); }
@@ -116,20 +117,53 @@
                 glyphs[c] = g = Platform.createGlyph(this, c);
             }
             g.render();
-            // avoid clipping first character
-            int ox = x + width;
-            if (i!=0 || g.bearingx>0) {
-                ox += g.bearingx;
+            
+            // useful glyph metrics for [visual] debugging
+            //System.out.println(c+" ("+((int)c)+") at "+this.pointsize+" 
("+threshold+"): "+g.bearingx+", "+g.width+", "+g.advance+", -- "+width);
+            
+            // SOLUTION 1 - simple; use glyph metrics [almost] without 
modification
+            if (g.bearingx<0) {
+                // neutralise negative bearingx to prevent first
+                // character clipping and also glyph sandwiching
+                width += -g.bearingx;
             }
+            int ox = x + width + g.bearingx;
+            width += g.advance;
+            
+//            // SOLUTION 2 - alternative placement algorithm
+//            // use pre-analysis of glyphs to be a bit smarter
+//            // PROBLEM: perhaps a bit too close as text layout
+//            // although consistent, is a bit too congested
+//            int ox;
+//            int threshold = pointsize>>1;
+//            if (i==0 && g.bearingx<0) {
+//                // neutralise negative bearingx for the first character
+//                // to avoid clipping characters such as 'J' in vera
+//                width += -g.bearingx;
+//            }
+//          
+//            // REMARK: at lower point sizes, as we are doing per-glyph
+//            // rendering and not using freetype's inbuilt kerning, we
+//            // have to do a bit of hackery to make the glyphs look a bit
+//            // better when side-by-side, otherwise some smaller glyphs
+//            // will touch pixels with others and others leave big gaps
+//            ox = x + width;
+//            width += g.advance-g.bearingx;
+//            if (g.width+g.bearingx>=g.advance && g.width<threshold-1)
+//                width += g.bearingx>0 ? g.bearingx : 1;
+//            if (g.width==g.advance && g.advance>=threshold)
+//                width ++;
+            
+            // VISUAL DEBUGGING
+            //if (buf != null) {
+            //    // places a marker by the drawing point of the glyph
+            //    buf.fillTrapezoid(ox, ox+1, y + g.font.max_ascent, ox, ox+1, 
y + g.font.max_ascent + 1, 0xffffff00);
+            //}
+            
             // render glyph and move on
             if (buf != null) {
                 buf.drawGlyph(g, ox, y + g.font.max_ascent - g.baseline, cx1, 
cy1, cx2, cy2, textcolor);
             }
-            width += g.advance;
-            // take into account clipping avoidance
-            if (i==0 && g.bearingx<0) {
-                width -= g.bearingx;
-            }
         }
     }
 
@@ -147,11 +181,37 @@
             }
             g.render();
             height = java.lang.Math.max(height, max_ascent + max_descent);
+
+            // SOLUTION 1 - simple; use glyph metrics [almost] without 
modification
+            if (g.bearingx<0) {
+                // neutralise negative bearingx to prevent first
+                // character clipping and also glyph sandwiching
+                width += -g.bearingx;
+            }
             width += g.advance;
-            // take into account clipping avoidance
-            if (i==0 && g.bearingx<0) {
-                width -= g.bearingx;
-            }
+            
+//          // SOLUTION 2 - alternative placement algorithm
+//          // use pre-analysis of glyphs to be a bit smarter
+//          // PROBLEM: perhaps a bit too close as text layout
+//          // although consistent, is a bit too congested
+//          int ox;
+//          int threshold = pointsize>>1;
+//          if (i==0 && g.bearingx<0) {
+//              // neutralise negative bearingx for the first character
+//              // to avoid clipping characters such as 'J' in vera
+//              width += -g.bearingx;
+//          }
+//        
+//          // REMARK: at lower point sizes, as we are doing per-glyph
+//          // rendering and not using freetype's inbuilt kerning, we
+//          // have to do a bit of hackery to make the glyphs look a bit
+//          // better when side-by-side, otherwise some smaller glyphs
+//          // will touch pixels with others and others leave big gaps
+//          width += g.advance-g.bearingx;
+//          if (g.width+g.bearingx>=g.advance && g.width<threshold-1)
+//              width += g.bearingx>0 ? g.bearingx : 1;
+//          if (g.width==g.advance && g.advance>=threshold)
+//              width ++;
         }
         return ((((long)width) << 32) | (height & 0xffffffffL));
     }
@@ -247,6 +307,12 @@
             
             //long start = System.currentTimeMillis();
             
+            /*
+             * Stage 1:
+             *   Using FreeType, compiled as MIPS and executed by NestedVM,
+             *   we render a given font glyph at the specified pointsize.
+             *   This returns an alphamask as a byte array (byte & 0xff)
+             */
             rt.call("render",glyph.c,glyph.font.pointsize.intValue());
             rtCheck();
             
@@ -263,6 +329,51 @@
             int addr = rt.getUserInfo(0);
             rt.copyin(addr, glyph.data, glyph.width * glyph.height);
             
+            /*
+             * Stage 2: (SOLUTION 2 ONLY)
+             *   We render glyphs only once, contrary to the standard
+             *   freetype text rendering, so subpixel spacing between
+             *   characters is not implemented.  We must do placement
+             *   using only the given characteristics of each glyph,
+             *   but since these characteristics - especially at low
+             *   pointsizes - are rounded, they're inaccurate for our
+             *   purposes and thus, without analysis, if attempting to
+             *   place these rendered glyphs side-by-side, there will
+             *   be inconsistencies with the distances spanned between
+             *   some characters.
+             */
+//            if (glyph.width+glyph.bearingx>=glyph.advance && pointsize>>1 > 
glyph.advance) {
+//                final int darkness_threshold = 56;
+//                boolean above_threshold = false;
+//                for (int i=0; glyph.height>i; i++) {
+//                    // check the last column of the glyph to ensure
+//                    // it meets the visible alpha threshold
+//                    if ((glyph.data[i*glyph.width + (glyph.width-1)] & 0xff) 
> darkness_threshold) {
+//                        above_threshold = true;
+//                        break;
+//                    }
+//                }
+//                if (above_threshold) {
+//                    //System.out.println("advancing: "+glyph.c);
+//                    glyph.advance ++;
+//                }
+//            }
+            
+//            // console visualisation of the glyph
+//            // i.e. output alphas (number) array
+//            if (glyph.c == 'o' || glyph.c == 'w') {
+//                System.out.println(glyph.c+" at "+pointsize+", 
advance:"+glyph.advance+", width:"+glyph.width+", bearingx:"+glyph.bearingx);
+//                for (int i=0; glyph.height>i; i++) {
+//                    for (int j=0; glyph.width>j; j++) {
+//                        int b = glyph.data[i*glyph.width + j] & 0xff;
+//                        String out = ""+b;
+//                        while (out.length()<4) out = " "+out;
+//                        System.out.print(out+", ");
+//                    }
+//                    System.out.print('\n');
+//                }
+//            }
+            
             glyph.isLoaded = true;
         } catch (Exception e) {
             // FEATURE: Better error reporting (throw an exception?)


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload 
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve 
application availability and disaster protection. Learn more about boosting 
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
_______________________________________________
Vexi-svn mailing list
Vexi-svn@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vexi-svn

Reply via email to