[Fencommits] libvob: Add mosaic text.

Matti J. Katila majukati at cc.jyu.fi
Tue Mar 7 02:05:19 EET 2006


Tue Mar  7 01:07:52 EET 2006  Matti J. Katila <majukati at cc.jyu.fi>
  * Add mosaic text.

diff -rN -u libvob-old/org/nongnu/libvob/gl/impl/lwjgl/mosaictext/LWJGL_Text.java libvob-new/org/nongnu/libvob/gl/impl/lwjgl/mosaictext/LWJGL_Text.java
--- libvob-old/org/nongnu/libvob/gl/impl/lwjgl/mosaictext/LWJGL_Text.java	1970-01-01 02:00:00.000000000 +0200
+++ libvob-new/org/nongnu/libvob/gl/impl/lwjgl/mosaictext/LWJGL_Text.java	2006-03-07 01:34:37.000000000 +0200
@@ -0,0 +1,500 @@
+// (c): Matti J. Katila
+
+package org.nongnu.libvob.gl.impl.lwjgl.mosaictext;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Random;
+import java.util.StringTokenizer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.glu.GLU;
+import org.lwjgl.util.vector.Vector2f;
+import org.lwjgl.util.vector.Vector4f;
+import org.nongnu.libvob.AbstractVob;
+import org.nongnu.libvob.GraphicsAPI;
+import org.nongnu.libvob.TextStyle;
+import org.nongnu.libvob.Vob;
+import org.nongnu.libvob.VobScene;
+import org.nongnu.libvob.Vob.RenderInfo;
+import org.nongnu.libvob.gl.impl.lwjgl.CallGL;
+import org.nongnu.libvob.gl.impl.lwjgl.LWJGLRen;
+import org.nongnu.libvob.gl.impl.lwjgl.Transform;
+import org.nongnu.libvob.impl.lwjgl.LWJGL_SimpleVobTester;
+import org.nongnu.libvob.vobs.RectVob;
+import org.nongnu.libvob.vobs.SolidBackdropVob;
+import org.nongnu.libvob.vobs.TestSpotVob;
+import org.nongnu.libvob.vobs.TextVob;
+
+import com.sixlegs.image.png.PngImage;
+
+/** A class that can load a set of images which together form 
+ *  a mosaic texture of glyphs on specific font family. 
+ *  There are different size of images according to mipmap levels, e.g., 64x64, 128x128 or 256x256.
+ *  
+ * http://www.opengl.org/resources/code/rendering/mjktips/TexFont/TexFont.html
+ * 
+ * @author Matti J. Katila
+ */
+public class LWJGL_Text {
+
+    FloatBuffer bits = BufferUtils.createFloatBuffer(256*256);
+
+    ImageConsumer imgConsumer = new ImageConsumer(){
+	public void imageComplete(int status) {
+	}
+	public void setHints(int hintflags) {
+	}
+	public void setDimensions(int width, int height) {
+	}
+	public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) {
+	}
+	public void setPixels(int x, int y, int w, int h, ColorModel m, int[] pixels, int off, int scansize) {
+	    for (int i=0; i<w; i++) {
+		int p = pixels[i];
+		float r = m.getRed(p);
+		float g = m.getGreen(p);
+		float b = m.getBlue(p);
+		
+		float fl = 0;
+		fl = (r/256f+g/256f+b/256f);
+		fl = fl/3;
+//		bits.put((w-1-y)*scansize + i, fl);
+		bits.put(y*scansize + i, fl);
+	    }	    
+	}
+	public void setColorModel(ColorModel model) {
+	}
+	public void setProperties(Hashtable props) {
+	}
+    };
+    
+    public class TextStyleImpl extends TextStyle {
+
+	/** Reference size of the font */
+	float refSize;
+
+	float descent = 0;
+	
+	// reserve room for two ints.
+	IntBuffer textures = BufferUtils.createIntBuffer(2);
+	TextStyleImpl(IntBuffer textures, float size, float descent)
+	{
+	    this.textures = textures;
+	    this.refSize = size;
+	    this.descent = descent;
+	}
+	TextStyleImpl(float size) {
+	    this.refSize = size;
+	    System.out.println("refSize:: "+refSize);
+	    GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, textures.capacity());
+	    GL11.glGenTextures(textures);
+	    for (int i=0; i<textures.capacity(); i++) {
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, textures.get(i));
+		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
+		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
+		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+	    }
+	}
+	
+	void setTexture(String size, String descent, int nro, File f) {
+	    setTexture(Integer.parseInt(size), Integer.parseInt(descent), nro, f);
+	}
+	void setTexture(int size, int descent, int nro, File f) {
+	    int ind = 0;
+	    switch (size) {
+	    case 256: {
+		ind = 0;
+		this.descent = (descent * this.refSize)/(256f/8f);
+		break;
+	    }
+	    case 128: ind = 1; break;
+	    case 64: ind = 2; break;
+	    default: 
+		throw new Error();
+	    }
+	   
+	    try {
+		bits = BufferUtils.createFloatBuffer(size*size);
+		bits.limit(size*size);
+		bits.position(0);
+
+		PngImage png = new PngImage(new FileInputStream(f), true);
+		png.setFlushAfterNextProduction(true);
+		png.startProduction(imgConsumer);
+		png.removeConsumer(imgConsumer);	
+		bits.position(0);
+
+		
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, textures.get(nro));
+		System.out.println(nro+", "+ind+", "+size);
+		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, ind, GL11.GL_INTENSITY, size, size, 0, 
+			GL11.GL_LUMINANCE, GL11.GL_FLOAT ,bits);
+		bits.flip();
+//		CallGL.checkGlError("after text image");
+	    } catch (Exception e) { //FileNotFoundException e) {
+		e.printStackTrace();
+	    }
+	}
+	
+	public float getScaleByHeight(float h) {
+	    return 1; //h/refSize;
+	}	
+	public TextStyle getScaledStyle(float h) {
+	    if (true) return this;
+	    if (h == 1) return this;
+	    return new TextStyleImpl(textures, h*refSize, descent*h);
+	}
+	public float getWidth(String s, float scale) {
+	    return 100; //refSize*s.length()*scale;
+	}
+	public float getWidth(char[] chars, int offs, int len, float scale) {
+	    return 100; //refSize*scale*(len-offs);
+	}
+	public float getHeight(float scale) {
+	    return 100; //refSize * scale;
+	}
+	public float getAscent(float scale) {
+	    return 10; //(refSize - descent)*scale;
+	}
+	public float getDescent(float scale) {
+	    return 20; //descent * scale;
+	}
+	public float getLeading(float scale) {
+	    // TODO Auto-generated method stub
+	    return 0;
+	}
+	public Vob createVob(String text) {
+	    System.out.println("create");
+	    return new Text(text);
+	}
+	class Text extends AbstractVob implements LWJGLRen.Vob1 {
+
+	    protected String str;
+	    public Text(String text) { 
+		this.str = text != null? text: ""; 
+		System.out.println("Text: "+str+", "+refSize);
+		System.out.println(getDescent(1));
+		System.out.println(getAscent(1));
+		System.out.println(getWidth(str, 1));
+		System.out.println(getScaleByHeight(8));
+	    }
+	    public void render(Graphics g, boolean fast, RenderInfo info1, RenderInfo info2) {  }
+	    public void render(Transform t, int callList) {
+		CallGL.checkGlError("before call list coorder");
+		GL11.glPushMatrix();
+		if(t.performGL()) {
+		    Vector4f glyphCoords = new Vector4f();
+		    for (int i=0; i<str.length(); i++) {
+
+			    GL11.glEnable(GL11.GL_TEXTURE_2D);
+			    GL11.glAlphaFunc(GL11.GL_GREATER, 0.15f);
+			    GL11.glEnable(GL11.GL_ALPHA_TEST);
+			    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+			    GL11.glEnable(GL11.GL_BLEND);
+	
+			    int textureIndex = getGlyphSetIndex(str.charAt(i));
+			    GL11.glBindTexture(GL11.GL_TEXTURE_2D, textures.get(textureIndex));
+			    
+			    GL11.glBegin(GL11.GL_QUADS);
+			    
+			    getGlyphCoordsFor(str.charAt(i), textureIndex, glyphCoords);
+			    GL11.glTexCoord2f(glyphCoords.x, glyphCoords.y); GL11.glVertex3f(i, 0, 0.0f);
+			    GL11.glTexCoord2f(glyphCoords.x, glyphCoords.w); GL11.glVertex3f(i, 1f, 0.0f);
+			    GL11.glTexCoord2f(glyphCoords.z, glyphCoords.w); GL11.glVertex3f(i+1f, 1f, 0.0f);
+			    GL11.glTexCoord2f(glyphCoords.z, glyphCoords.y); GL11.glVertex3f(i+1f, 0, 0.0f);
+			    GL11.glEnd();
+
+		    }
+		} else {
+		    System.out.println("Error: CallistCoorded with non-glperformable.");
+//		    t.dump(std::cout);
+		}
+		GL11.glPopMatrix();
+		CallGL.checkGlError("After coorded calling list "+callList);
+
+	    }
+	    public int putGL(VobScene vs, int cs)
+	    {
+		return cs;
+	    }
+	}
+	public int getGlyphSetIndex(char c) {
+	    int ret = 0;
+	    if ("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(c) >= 0) 
+		ret = 0;
+	    else if ("?????????????????? !\"@#$%&/{([)]=}?\\+`\'^*<>|;,:._-".indexOf(c) >= 0)
+		ret = 1;
+	    return ret;
+	}
+	public void getGlyphCoordsFor(char c, int setInd, Vector4f gc) {
+	    gc.x = 0; gc.y=0; gc.z = 1; gc.w = 1;
+	    int ind = 0; 
+	    switch (setInd) {
+	    case 0: {
+		String s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+		ind = s.indexOf(c);
+		if (ind < 0) return;
+		break;
+	    }
+	    case 1: {
+		String s = "?????????????????? !\"@#$%&/{([)]=}?\\+`\'^*<>|;,:._-";
+		ind = s.indexOf(c);
+		if (ind < 0) return;
+		break;
+	    }
+	    }
+	    int row = ind / 8;
+	    int col = ind % 8;
+	    float d = 1f/8f;
+	    gc.x = col*d;
+	    gc.y = row*d;
+	    gc.z = gc.x + d;
+	    gc.w = gc.y + d;
+	}
+    }
+    
+    
+    
+    
+    
+    static private final Object NOT_LOADED = new Object();
+    static private LWJGL_Text instance = null;
+    
+    private File dir = null;
+    
+    /** Keys to TextStyles which contais int to texture bind. 
+     */
+    private HashMap loadedFonts = new HashMap();
+    
+    private LWJGL_Text() {}
+    static public LWJGL_Text getInstance() { 
+	if (instance == null)
+	    instance = new LWJGL_Text();
+	return instance;
+    }
+
+    
+    
+    
+    public void setImageDirectory(File dir) {
+	this.dir = dir;
+	// get all png images
+	File[] images = dir.listFiles(new FileFilter(){
+	    public boolean accept(File pathname) {
+		if (pathname.getName().endsWith("png"))
+		    return true;
+		return false;
+	    }
+	});
+
+	for (int i = 0; i < images.length; i++) {
+	    String name = images[i].getName();
+	    name = name.substring(0, name.indexOf('.'));
+	    StringTokenizer st = new StringTokenizer(name, "-");
+
+	    String family = null;
+	    boolean bold = false, italic = false;
+	    
+	    while (st.hasMoreTokens()) {
+		String token = st.nextToken();
+		if (family == null) family = token;
+		if (token.equals("bold=1")) bold = true;
+		if (token.equals("italic=1")) italic = true;
+	    }
+	    int style = Font.PLAIN;
+	    if (bold) style |= Font.BOLD;
+	    if (italic) style |= Font.ITALIC;
+//	    System.out.println(family+style);
+	    loadedFonts.put(family+style, NOT_LOADED);
+	}
+    }
+    
+    
+    
+    
+
+    // size is ignored
+    public synchronized TextStyle create(String family, int style, int size) {
+	if (family == null) 
+	    family = "sans";
+	
+	String key = family+style;
+
+	if (loadedFonts.containsKey(key)) {
+	    Object textStyle = loadedFonts.get(key);
+	    if (textStyle != NOT_LOADED)
+		return (TextStyle) textStyle;
+	    else {
+		TextStyle text = loadStyle(family, style, size);
+		loadedFonts.put(key, text);
+		return text;
+	    }
+	}
+	return null;
+    }
+
+    
+    private TextStyle loadStyle(String family, int style, float size_) {
+	// get all png images
+	File[] images = dir.listFiles(new FileFilter(){
+	    public boolean accept(File pathname) {
+		if (pathname.getName().endsWith("png"))
+		    return true;
+		return false;
+	    }
+	});
+
+	TextStyleImpl ret = new TextStyleImpl(size_);
+	for (int i = 0; i < images.length; i++) {
+	    String name = images[i].getName();
+	    name = name.substring(0, name.indexOf('.'));
+	    if (!name.substring(0, name.indexOf('-')).equals(family)) continue;
+	    
+	    StringTokenizer st = new StringTokenizer(name, "-");
+	    String desc = null, size = null;
+	    int nro = 0;
+	    boolean bold = false, italic = false;
+	    while (st.hasMoreTokens()) {
+		String token = st.nextToken();
+		if (token.equals("nro=1")) nro = 1;
+		if (token.equals("bold=1")) bold = true;
+		if (token.equals("italic=1")) italic = true;
+		if (token.startsWith("descent=")) desc = token;
+		if (token.startsWith("size=")) size = token;
+	    }
+	    int style_ = Font.PLAIN;
+	    if (bold) style_ |= Font.BOLD;
+	    if (italic) style_ |= Font.ITALIC;
+	    if (style != style_) continue;
+
+	    ret.setTexture(size.substring(size.lastIndexOf('x')+1), 
+		    desc.substring(desc.lastIndexOf('=')+1), nro, images[i]);
+	}
+	return ret;
+    }
+
+
+    public static void _main(String[] argv) {
+    
+	try {
+	    Display.setDisplayMode(new DisplayMode(500, 500));
+	    Display.setFullscreen(false);
+	    Display.create();
+	    Display.setTitle("Test text image textures.");
+	    Dimension d = new Dimension(500,500);
+
+	    GL11.glViewport(0, 0, d.width, d.height);
+	    GL11.glMatrixMode(GL11.GL_PROJECTION);
+	    GL11.glLoadIdentity();
+	    GLU.gluPerspective(60.0f, d.width/d.height, 1.0f, 30.0f);
+	    GL11.glMatrixMode(GL11.GL_MODELVIEW);
+	    GL11.glLoadIdentity();
+	    GL11.glTranslatef(0,0, -3.6f);
+
+	    GL11.glEnable(GL11.GL_TEXTURE_2D);
+	    GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
+
+
+	    File f = new File("./tmp/");
+	    LWJGL_Text.getInstance().setImageDirectory(f);
+	    TextStyleImpl impl = (TextStyleImpl)LWJGL_Text.getInstance().create("sans", Font.BOLD, 12);
+
+	    GL11.glClearColor(1, 1, 1, 1);
+	    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
+	    GL11.glColor4f(0, 0, 0, 1);
+
+
+	    GL11.glEnable(GL11.GL_TEXTURE_2D);
+	    GL11.glAlphaFunc(GL11.GL_GREATER, 0.15f);
+	    GL11.glEnable(GL11.GL_ALPHA_TEST);
+	    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+	    GL11.glEnable(GL11.GL_BLEND);
+
+	    GL11.glBindTexture(GL11.GL_TEXTURE_2D, impl.textures.get(0));
+	    
+	    GL11.glBegin(GL11.GL_QUADS);
+	    GL11.glTexCoord2f(0, 0); GL11.glVertex3f(-2.0f, -1.0f, 0.0f);
+	    GL11.glTexCoord2f(0, 1); GL11.glVertex3f(-2.0f, 1.20f, 0.0f);
+	    GL11.glTexCoord2f(1, 1); GL11.glVertex3f(0.0f, 1.20f, 0.0f);
+	    GL11.glTexCoord2f(1, 0); GL11.glVertex3f(0.0f, -1.0f, 0.0f);
+	    GL11.glEnd();
+
+	    GL11.glBindTexture(GL11.GL_TEXTURE_2D, impl.textures.get(1));
+	    
+	    GL11.glBegin(GL11.GL_QUADS);
+	    GL11.glTexCoord2f(0, 0); GL11.glVertex3f(0.1f, -1.0f, 0.0f);
+	    GL11.glTexCoord2f(0, 1); GL11.glVertex3f(0.1f, 1.20f, 0.0f);
+	    GL11.glTexCoord2f(1, 1); GL11.glVertex3f(2.0f, 1.20f, 0.0f);
+	    GL11.glTexCoord2f(1, 0); GL11.glVertex3f(2.0f, -1.0f, 0.0f);
+	    GL11.glEnd();
+	    CallGL.checkGlError("end");
+
+	    Display.update();
+	    
+	    Thread.sleep(12800);
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    
+    }
+    
+    
+    
+    public static void main(String[] args) {
+	if (false) {
+	    _main(args);
+	    return;
+	}
+	
+	LWJGL_SimpleVobTester test = new LWJGL_SimpleVobTester() {
+	    protected VobScene gen(VobScene vs) {
+		vs = super.gen(vs);
+		vs.put(new SolidBackdropVob(new Color(.9f, .8f, .5f)));
+		
+	        int cs = 0;
+	        cs = vs.translateCS(cs, "move", 10,50);
+
+//	        vs.put(new TestSpotVob(0,0,0, Color.MAGENTA), cs);
+	        cs = vs.scaleCS(cs, "scale for text", 9,9);
+
+//	        vs.put(new TestSpotVob(0,0,0, Color.WHITE), cs);
+//	        vs.put(new RectVob(Color.MAGENTA,2), cs);
+	        vs.put(new TextVob(GraphicsAPI.getInstance().getTextStyle("sans", 0,12), "0123456789"), cs);
+	        cs = vs.translateCS(cs, "move2", 0,1);
+	        vs.put(new TextVob(GraphicsAPI.getInstance().getTextStyle("sans", 0,12), "abcdefghijklmnopqrstuvxyz"), cs);
+	        cs = vs.translateCS(cs, "move2", 0,1);
+	        vs.put(new TextVob(GraphicsAPI.getInstance().getTextStyle("sans", 0,12), "abcdefghijklmnopqrstuvxyz".toUpperCase()), cs);
+	        cs = vs.translateCS(cs, "move2", 0,1);
+	        vs.put(new TextVob(GraphicsAPI.getInstance().getTextStyle("sans", 0,12), "??????L<>-:;,.-?=)"), cs);
+	        cs = vs.translateCS(cs, "move2", 0,1);
+	        vs.put(new TextVob(GraphicsAPI.getInstance().getTextStyle("sans", 0,12), "(/\\}{][@?$!\"#?%&"), cs);
+	        		        
+	        return vs;
+	    }
+	};
+	try {
+	    LWJGL_SimpleVobTester.main(test);
+	    Thread.sleep(15000);
+	    System.exit(0);
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+}    
+   
\ No newline at end of file




More information about the Fencommits mailing list