/** * Copyright 2012 Jason Sorensen (sorensenj@smert.net) * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package net.smert.frameworkgl.opengl.renderer; import net.smert.frameworkgl.Fw; import net.smert.frameworkgl.math.Vector2f; import net.smert.frameworkgl.opengl.GL; import net.smert.frameworkgl.opengl.TextureType; import net.smert.frameworkgl.opengl.constants.Primitives; import net.smert.frameworkgl.opengl.font.AngelCodeFont; import net.smert.frameworkgl.opengl.mesh.Mesh; import net.smert.frameworkgl.opengl.mesh.Segment; import net.smert.frameworkgl.opengl.mesh.SegmentMaterial; /** * * @author Jason Sorensen <sorensenj@smert.net> */ public class AngelCodeFontRenderer implements FontRenderer { private int extraFontAdvanceX; private AngelCodeFont angelCodeFont; private final Vector2f tempPosition; public AngelCodeFontRenderer() { extraFontAdvanceX = 0; tempPosition = new Vector2f(); } private void createGlyphRenderable(AngelCodeFont.Glyph glyph, TextHelperRenderer renderer) { if (glyph.renderable != null) { return; } int fontHeight = angelCodeFont.getFontScaleHeight(); int fontWidth = angelCodeFont.getFontScaleWidth(); int page = glyph.character.getPage(); String fontTextureFilename = angelCodeFont.getPage(page); // Calculate texture coordinates for the glyph float height = glyph.character.getHeight(); float maxX = (float) (glyph.character.getX() + glyph.character.getWidth()) / fontWidth; float minX = (float) (glyph.character.getX()) / fontWidth; float maxY = (float) (glyph.character.getY() + glyph.character.getHeight()) / fontHeight; float minY = (float) (glyph.character.getY()) / fontHeight; float width = glyph.character.getWidth(); float x = glyph.character.getXOffset(); float y = -glyph.character.getYOffset(); // Use tessellator to create a quad GL.tessellator.setConvertToTriangles(true); GL.tessellator.reset(); GL.tessellator.setLocalPosition(0, 0, 0); GL.tessellator.start(Primitives.QUADS); GL.tessellator.addTexCoord(minX, 1f - maxY); GL.tessellator.addVertex(x, y - height, 0); GL.tessellator.addTexCoord(maxX, 1f - maxY); GL.tessellator.addVertex(x + width, y - height, 0); GL.tessellator.addTexCoord(maxX, 1f - minY); GL.tessellator.addVertex(x + width, y, 0); GL.tessellator.addTexCoord(minX, 1f - minY); GL.tessellator.addVertex(x, y, 0); GL.tessellator.stop(); GL.tessellator.addSegment("Angel Code Font Renderer Quad"); // Create mesh Mesh mesh = Fw.graphics.createMesh(GL.tessellator); // Create segment material Segment segment = mesh.getSegment(0); SegmentMaterial segmentMaterial = segment.getMaterial(); if (segmentMaterial == null) { segmentMaterial = GL.meshFactory.createSegmentMaterial(); segment.setMaterial(segmentMaterial); } // Set the diffuse texture segmentMaterial.setTexture(TextureType.DIFFUSE, fontTextureFilename); // Create renderable from mesh glyph.renderable = renderer.createGlyphRenderable(); glyph.renderable.create(mesh); } private void drawString(String text, Vector2f position, float sizeX, float sizeY, TextHelperRenderer renderer) { renderer.pushMatrix(); renderer.translateText(position.getX(), position.getY()); for (int i = 0; i < text.length(); i++) { char currentChar = text.charAt(i); char nextChar = 0; if (i < text.length() - 1) { nextChar = text.charAt(i + 1); } int codePoint = text.codePointAt(i); int advanceX = angelCodeFont.getCharacterAdvance(currentChar, nextChar, sizeX); AngelCodeFont.Glyph glyph = angelCodeFont.getGlyph(codePoint); if (glyph == null) { continue; } createGlyphRenderable(glyph, renderer); renderer.colorText(renderer.getTextColor()); renderer.scaleText(sizeX, sizeY); renderer.renderGlyph(glyph.renderable); renderer.translateText(advanceX + extraFontAdvanceX, 0f); position.addX(glyph.character.getWidth() * sizeX + extraFontAdvanceX); } renderer.popMatrix(); } public AngelCodeFont getFont() { return angelCodeFont; } public void init(AngelCodeFont angelCodeFont) { this.angelCodeFont = angelCodeFont; } @Override public void drawString(String text, float x, float y, TextHelperRenderer renderer) { tempPosition.set(x, y); drawString(text, tempPosition, 1f, 1f, renderer); } @Override public void drawString(String text, float x, float y, float sizeX, float sizeY, TextHelperRenderer renderer) { tempPosition.set(x, y); drawString(text, tempPosition, sizeX, sizeY, renderer); } @Override public void drawString(String text, TextHelperRenderer renderer) { drawString(text, renderer.getTextPosition(), 1f, 1f, renderer); } @Override public int getExtraFontAdvanceX() { return extraFontAdvanceX; } @Override public void setExtraFontAdvanceX(int extraFontAdvanceX) { this.extraFontAdvanceX = extraFontAdvanceX; } @Override public void newHalfLine(TextHelperRenderer renderer, Vector2f position) { position.setX(renderer.getTextDefaultX()); position.addY(-angelCodeFont.getFontLineHeight() / 2); } @Override public void newLine(TextHelperRenderer renderer, Vector2f position) { position.setX(renderer.getTextDefaultX()); position.addY(-angelCodeFont.getFontLineHeight()); } @Override public void reset(TextHelperRenderer renderer, Vector2f position) { position.setX(renderer.getTextDefaultX()); position.setY(Fw.config.getCurrentHeight() - renderer.getTextDefaultY()); } }