/*******************************************************************************
* Breakout Cave Survey Visualizer
*
* Copyright (C) 2014 James Edwards
*
* jedwards8 at fastmail dot fm
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*******************************************************************************/
package org.andork.jogl.awt;
import static com.jogamp.opengl.GL.GL_BGRA;
import static com.jogamp.opengl.GL.GL_CLAMP_TO_EDGE;
import static com.jogamp.opengl.GL.GL_LINEAR;
import static com.jogamp.opengl.GL.GL_LINEAR_MIPMAP_LINEAR;
import static com.jogamp.opengl.GL.GL_RGBA;
import static com.jogamp.opengl.GL.GL_TEXTURE0;
import static com.jogamp.opengl.GL.GL_TEXTURE_2D;
import static com.jogamp.opengl.GL.GL_TEXTURE_MAG_FILTER;
import static com.jogamp.opengl.GL.GL_TEXTURE_MIN_FILTER;
import static com.jogamp.opengl.GL.GL_TEXTURE_WRAP_S;
import static com.jogamp.opengl.GL.GL_TEXTURE_WRAP_T;
import static com.jogamp.opengl.GL.GL_UNSIGNED_BYTE;
import static com.jogamp.opengl.GL2ES2.GL_RED;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.andork.jogl.JoglManagedResource;
import org.andork.jogl.JoglResourceManager;
import com.jogamp.nativewindow.awt.DirectDataBufferInt;
import com.jogamp.opengl.GL2ES2;
public class GlyphPage extends JoglManagedResource {
public static void drawGlyphs(Graphics2D g, char startChar, int rows, int cols, int cellHeight, int cellWidth,
int cellBaseline) {
char[] chars = { startChar };
int y = cellBaseline;
for (int row = 0; row < rows; row++, y += cellHeight) {
int x = 0;
for (int col = 0; col < cols; col++, x += cellWidth, chars[0]++) {
g.drawChars(chars, 0, 1, x, y);
}
}
}
public final FontMetrics metrics;
BufferedImage image;
char startChar;
public final int cellHeight;
public final int cellWidth;
float texcoordCellHeight;
float texcoordCellWidth;
float texcoordMaxDescent;
float texcoordMaxAscent;
float texcoordWidthFactor;
int rows;
int cols;
int texture;
boolean initialized;
public GlyphPage(JoglResourceManager manager, FontMetrics fm, BufferedImage image, GlyphPagePainter painter,
char startChar) {
super(manager);
metrics = fm;
this.image = image;
this.startChar = startChar;
Graphics2D g2 = image.createGraphics();
g2.setFont(fm.getFont());
cellHeight = fm.getMaxAscent() + fm.getMaxDescent() + 1;
int cellBaseline = cellHeight - fm.getMaxDescent();
cellWidth = fm.getMaxAdvance() + 1;
texcoordCellHeight = (float) cellHeight / image.getHeight();
texcoordWidthFactor = 1f / image.getWidth();
texcoordCellWidth = cellWidth * texcoordWidthFactor;
texcoordMaxAscent = (float) fm.getMaxAscent() / image.getHeight();
texcoordMaxDescent = (float) fm.getMaxDescent() / image.getHeight();
cols = image.getWidth() / cellWidth;
rows = image.getHeight() / cellHeight;
g2.setBackground(new Color(0, 0, 0, 0));
g2.clearRect(0, 0, image.getWidth(), image.getHeight());
g2.setColor(Color.white);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
painter.drawGlyphs(g2, startChar, rows, cols, cellHeight, cellWidth, cellBaseline);
g2.dispose();
}
@Override
protected void doDispose(GL2ES2 gl) {
int[] temp = { texture };
gl.glDeleteTextures(1, temp, 0);
texture = -1;
}
@Override
protected void doInit(GL2ES2 gl) {
int[] temp = new int[1];
gl.glGenTextures(1, temp, 0);
texture = temp[0];
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_2D, texture);
gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if (image.getRaster().getDataBuffer() instanceof DirectDataBufferByte) {
ByteBuffer data = ((DirectDataBufferByte) image.getRaster().getDataBuffer()).getData();
data.position(0);
gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, image.getWidth(), image.getHeight(), 0, GL_RED, GL_UNSIGNED_BYTE,
data);
} else if (image.getRaster().getDataBuffer() instanceof DirectDataBufferInt) {
IntBuffer data = ((DirectDataBufferInt) image.getRaster().getDataBuffer()).getData();
data.position(0);
gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getWidth(), image.getHeight(), 0, GL_BGRA,
GL_UNSIGNED_BYTE, data);
}
gl.glGenerateMipmap(GL_TEXTURE_2D);
gl.glBindTexture(GL_TEXTURE_2D, 0);
}
public BufferedImage getImage() {
return image;
}
public void getTexcoordBounds(char c, float[] lrtb) {
int offs = c - startChar;
int row = offs / cols;
int col = offs % cols;
lrtb[0] = col * texcoordCellWidth;
lrtb[1] = lrtb[0] + metrics.charWidth(c) * texcoordWidthFactor;
lrtb[3] = (row + 1) * texcoordCellHeight;
lrtb[2] = lrtb[3] - texcoordMaxDescent - texcoordMaxAscent;
}
public int getTexture() {
return texture;
}
}