package com.oddlabs.truetype; import java.io.InputStream; import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.awt.image.BufferedImage; import java.awt.Graphics2D; //import java.awt.Shape; import java.awt.RenderingHints; import java.awt.Font; import java.awt.font.TextLayout; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.image.DataBuffer; import java.text.AttributedString; import java.text.AttributedCharacterIterator; import java.awt.font.TextAttribute; import org.lwjgl.Sys; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.glu.GLU; import org.lwjgl.BufferUtils; import com.oddlabs.util.Utils; public final strictfp class Test { private final static int WIDTH = 1024; private final static int HEIGHT = 1024; private final static int DISPLAY_WIDTH = 1280; private final static int DISPLAY_HEIGHT = 1024; private final static float RENDER_SIZE = WIDTH*1f; private final static BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB); private final static Graphics2D g2d = (Graphics2D)image.getGraphics(); public final static void main(String[] args) { try { Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT)); Display.create(); initGL(); // Load font InputStream font_is = Utils.makeURL("/fonts/tahoma.ttf").openStream(); java.awt.Font src_font = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, font_is); java.awt.Font font = src_font.deriveFont(14f); // Load text InputStreamReader text_is = new InputStreamReader(Utils.makeURL("/test_text.txt").openStream()); StringBuffer str_buffer = new StringBuffer(); int c = text_is.read(); do { str_buffer.append((char)c); c = text_is.read(); } while (c != -1); String str = str_buffer.toString(); // Build texture int[] pixels = new int[WIDTH*HEIGHT]; // ByteBuffer pixel_data = ByteBuffer.wrap(pixels); // NEW // pixelDataFromString(WIDTH, HEIGHT, str, font, pixels); // NEW IntBuffer pixel_data = BufferUtils.createIntBuffer(WIDTH*HEIGHT); // OLD pixel_data.put(pixels); // OLD pixel_data.rewind(); int texture_handle = createTexture(WIDTH, HEIGHT, pixel_data); FontRenderContext frc = g2d.getFontRenderContext(); AttributedString att_str = new AttributedString(str); att_str.addAttribute(TextAttribute.FONT, font); AttributedCharacterIterator iterator = att_str.getIterator(); LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, frc); while (!Display.isCloseRequested()) { long start_time = System.currentTimeMillis(); for (int i = 0; i < 10; i++) { pixelDataFromString(WIDTH, HEIGHT, str, font, pixels, measurer); pixel_data.put(pixels); // OLD pixel_data.rewind(); //texture_handle = createTexture(WIDTH, HEIGHT, pixel_data); updateTexture(WIDTH, HEIGHT, pixel_data); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glLoadIdentity(); // Background /* GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glColor4f(.1f, .1f, .1f, 1f); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex3f(0f, DISPLAY_HEIGHT-RENDER_SIZE, 1f); GL11.glVertex3f(RENDER_SIZE, DISPLAY_HEIGHT-RENDER_SIZE, 1f); GL11.glVertex3f(RENDER_SIZE, DISPLAY_HEIGHT, 1f); GL11.glVertex3f(0f, DISPLAY_HEIGHT, 1f); GL11.glEnd(); */ // Text GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glColor4f(1f, 1f, 1f, 1f); GL11.glBegin(GL11.GL_QUADS); GL11.glTexCoord2f(0f, 1f); GL11.glVertex3f(0f, DISPLAY_HEIGHT-RENDER_SIZE, 1f); GL11.glTexCoord2f(1f, 1f); GL11.glVertex3f(RENDER_SIZE, DISPLAY_HEIGHT-RENDER_SIZE, 1f); GL11.glTexCoord2f(1f, 0f); GL11.glVertex3f(RENDER_SIZE, DISPLAY_HEIGHT, 1f); GL11.glTexCoord2f(0f, 0f); GL11.glVertex3f(0f, DISPLAY_HEIGHT, 1f); GL11.glEnd(); Display.update(); } long total_time = System.currentTimeMillis() - start_time; System.out.println("total_time = " + total_time); } Display.destroy(); } catch (Exception t) { t.printStackTrace(); } } private final static void pixelDataFromString(int width, int height, String str, java.awt.Font font, int[] pixels, LineBreakMeasurer measurer) { measurer.setPosition(0); g2d.clearRect(0, 0, width, height); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); float wrapping_width = width; float y = 0; int length = str.length(); while (measurer.getPosition() < length) { TextLayout layout = measurer.nextLayout(wrapping_width); y += (layout.getAscent()); float x = layout.isLeftToRight() ? 0 : (wrapping_width - layout.getAdvance()); layout.draw(g2d, x, y); y += layout.getDescent() + layout.getLeading(); } image.getRaster().getDataElements(0, 0, image.getWidth(), image.getHeight(), pixels); } private final static void initGL() { GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GLU.gluOrtho2D(0f, Display.getDisplayMode().getWidth(), 0f, Display.getDisplayMode().getHeight()); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glEnable(GL11.GL_BLEND); } private final static void updateTexture(int width, int height, IntBuffer pixel_data) { GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, width, height, GL11.GL_RGBA, GL12.GL_UNSIGNED_INT_8_8_8_8, pixel_data); } private final static int createTexture(int width, int height, IntBuffer pixel_data) { IntBuffer handle_buffer = BufferUtils.createIntBuffer(1); GL11.glGenTextures(handle_buffer); int tex_handle = handle_buffer.get(0); GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex_handle); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL12.GL_UNSIGNED_INT_8_8_8_8, pixel_data); return tex_handle; } }