From 5aa35fb8b8f06ea4680cef7be0040371c6c7a451 Mon Sep 17 00:00:00 2001 From: "nathan.sweet" Date: Mon, 1 Nov 2010 00:08:33 +0000 Subject: [PATCH] [added] Native font rendering to Hiero. --- .../hiero/src/com/badlogic/gdx/hiero/Hiero.java | 81 ++++++++++++++++------ .../badlogic/gdx/hiero/unicodefont/GlyphPage.java | 20 ++++-- .../gdx/hiero/unicodefont/HieroSettings.java | 12 ++++ .../gdx/hiero/unicodefont/UnicodeFont.java | 24 ++++++- 4 files changed, 109 insertions(+), 28 deletions(-) diff --git a/extensions/hiero/src/com/badlogic/gdx/hiero/Hiero.java b/extensions/hiero/src/com/badlogic/gdx/hiero/Hiero.java index 99043e828..46738afc7 100644 --- a/extensions/hiero/src/com/badlogic/gdx/hiero/Hiero.java +++ b/extensions/hiero/src/com/badlogic/gdx/hiero/Hiero.java @@ -136,6 +136,8 @@ public class Hiero extends JFrame { JSpinner padAdvanceYSpinner; JCheckBox italicCheckBox; JCheckBox boldCheckBox; + JRadioButton javaRadio; + JRadioButton nativeRadio; JLabel glyphsTotalLabel; JLabel glyphPagesTotalLabel; JComboBox glyphPageHeightCombo; @@ -156,7 +158,7 @@ public class Hiero extends JFrame { File saveBmFontFile; public Hiero () { - super("Hiero v2.0 - Bitmap Font Tool"); + super("Hiero v3.0 - Bitmap Font Tool"); Splash splash = new Splash(this, "/splash.jpg", 2000); initialize(); splash.close(); @@ -262,6 +264,7 @@ public class Hiero extends JFrame { unicodeFont.setPaddingAdvanceY(((Integer)padAdvanceYSpinner.getValue()).intValue()); unicodeFont.setGlyphPageWidth(((Integer)glyphPageWidthCombo.getSelectedItem()).intValue()); unicodeFont.setGlyphPageHeight(((Integer)glyphPageHeightCombo.getSelectedItem()).intValue()); + unicodeFont.setNativeRendering(nativeRadio.isSelected()); for (Iterator iter = effectPanels.iterator(); iter.hasNext();) { EffectPanel panel = (EffectPanel)iter.next(); @@ -380,6 +383,8 @@ public class Hiero extends JFrame { boldCheckBox.addActionListener(listener); italicCheckBox.addActionListener(listener); resetCacheButton.addActionListener(listener); + javaRadio.addActionListener(listener); + nativeRadio.addActionListener(listener); sampleTextRadio.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent evt) { @@ -610,9 +615,27 @@ public class Hiero extends JFrame { GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0)); browseButton.setMargin(new Insets(0, 0, 0, 0)); } + { + fontPanel.add(new JLabel("Rendering:"), new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, + GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0)); + } + { + javaRadio = new JRadioButton("Java"); + fontPanel.add(javaRadio, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, + GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0)); + javaRadio.setSelected(true); + } + { + nativeRadio = new JRadioButton("Native"); + fontPanel.add(nativeRadio, new GridBagConstraints(2, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, + GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0)); + } ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(systemFontRadio); buttonGroup.add(fontFileRadio); + buttonGroup = new ButtonGroup(); + buttonGroup.add(javaRadio); + buttonGroup.add(nativeRadio); } { JPanel samplePanel = new JPanel(); @@ -694,18 +717,18 @@ public class Hiero extends JFrame { GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); } { - glyphPageWidthCombo = new JComboBox(new DefaultComboBoxModel(new Integer[] {new Integer(256), new Integer(512), - new Integer(1024), new Integer(2048)})); + glyphPageWidthCombo = new JComboBox(new DefaultComboBoxModel(new Integer[] {new Integer(32), new Integer(64), + new Integer(128), new Integer(256), new Integer(512), new Integer(1024), new Integer(2048)})); glyphCachePanel.add(glyphPageWidthCombo, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0)); - glyphPageWidthCombo.setSelectedIndex(1); + glyphPageWidthCombo.setSelectedIndex(4); } { - glyphPageHeightCombo = new JComboBox(new DefaultComboBoxModel(new Integer[] {new Integer(256), new Integer(512), - new Integer(1024), new Integer(2048)})); + glyphPageHeightCombo = new JComboBox(new DefaultComboBoxModel(new Integer[] {new Integer(32), new Integer(64), + new Integer(128), new Integer(256), new Integer(512), new Integer(1024), new Integer(2048)})); glyphCachePanel.add(glyphPageHeightCombo, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0)); - glyphPageHeightCombo.setSelectedIndex(1); + glyphPageHeightCombo.setSelectedIndex(4); } { resetCacheButton = new JButton("Reset Cache"); @@ -1155,8 +1178,7 @@ public class Hiero extends JFrame { newUnicodeFont = null; } - // BOZO - Fix no effects. - if (unicodeFont.loadGlyphs(25)) { + if (!unicodeFont.getEffects().isEmpty() && unicodeFont.loadGlyphs(25)) { glyphPageComboModel.removeAllElements(); int pageCount = unicodeFont.getGlyphPages().size(); int glyphCount = 0; @@ -1188,14 +1210,14 @@ public class Hiero extends JFrame { } if (sampleTextRadio.isSelected()) { - GL11.glColor4f(renderingBackgroundColor.r, renderingBackgroundColor.g, renderingBackgroundColor.b, + GL11.glClearColor(renderingBackgroundColor.r, renderingBackgroundColor.g, renderingBackgroundColor.b, renderingBackgroundColor.a); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); int offset = unicodeFont.getYOffset(sampleText); if (offset > 0) offset = 0; unicodeFont.drawString(0, -offset, sampleText, Color.WHITE, 0, sampleText.length()); } else { - GL11.glColor4f(1, 1, 1, 1); + GL11.glClearColor(1, 1, 1, 1); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); unicodeFont.addGlyphs(sampleText); // GL11.glColor4f(renderingBackgroundColor.r, renderingBackgroundColor.g, renderingBackgroundColor.b, @@ -1205,16 +1227,33 @@ public class Hiero extends JFrame { List pages = unicodeFont.getGlyphPages(); if (index >= 0 && index < pages.size()) { Texture texture = ((GlyphPage)pages.get(glyphPageCombo.getSelectedIndex())).getTexture(); - GL11.glBegin(GL11.GL_QUADS); - GL11.glTexCoord2f(0, 0); - GL11.glVertex3f(0, 0, 0); - GL11.glTexCoord2f(0, 1); - GL11.glVertex3f(0, texture.getHeight(), 0); - GL11.glTexCoord2f(1, 1); - GL11.glVertex3f(texture.getWidth(), texture.getHeight(), 0); - GL11.glTexCoord2f(1, 0); - GL11.glVertex3f(texture.getWidth(), 0, 0); - GL11.glEnd(); + + glDisable(GL_TEXTURE_2D); + glColor4f(renderingBackgroundColor.r, renderingBackgroundColor.g, renderingBackgroundColor.b, + renderingBackgroundColor.a); + glBegin(GL_QUADS); + glVertex3f(0, 0, 0); + glVertex3f(0, texture.getHeight(), 0); + glVertex3f(texture.getWidth(), texture.getHeight(), 0); + glVertex3f(texture.getWidth(), 0, 0); + glEnd(); + glEnable(GL_TEXTURE_2D); + + texture.bind(); + glColor4f(1, 1, 1, 1); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex3f(0, 0, 0); + + glTexCoord2f(0, 1); + glVertex3f(0, texture.getHeight(), 0); + + glTexCoord2f(1, 1); + glVertex3f(texture.getWidth(), texture.getHeight(), 0); + + glTexCoord2f(1, 0); + glVertex3f(texture.getWidth(), 0, 0); + glEnd(); } } } diff --git a/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/GlyphPage.java b/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/GlyphPage.java index cf8085844..c12703fab 100644 --- a/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/GlyphPage.java +++ b/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/GlyphPage.java @@ -2,6 +2,7 @@ package com.badlogic.gdx.hiero.unicodefont; import java.awt.AlphaComposite; +import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; @@ -27,6 +28,7 @@ import com.badlogic.gdx.graphics.Sprite; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.Texture.TextureWrap; +import com.badlogic.gdx.hiero.unicodefont.effects.ColorEffect; import com.badlogic.gdx.hiero.unicodefont.effects.Effect; /** @@ -139,10 +141,20 @@ public class GlyphPage { scratchGraphics.setComposite(AlphaComposite.Clear); scratchGraphics.fillRect(0, 0, MAX_GLYPH_SIZE, MAX_GLYPH_SIZE); scratchGraphics.setComposite(AlphaComposite.SrcOver); - scratchGraphics.setColor(java.awt.Color.white); - for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext();) - ((Effect)iter.next()).draw(scratchImage, scratchGraphics, unicodeFont, glyph); - glyph.setShape(null); // The shape will never be needed again. + if (unicodeFont.getNativeRendering()) { + for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext();) { + Effect effect = (Effect)iter.next(); + if (effect instanceof ColorEffect) scratchGraphics.setColor(((ColorEffect)effect).getColor()); + } + scratchGraphics.setColor(java.awt.Color.white); + scratchGraphics.setFont(unicodeFont.getFont()); + scratchGraphics.drawString("" + (char)glyph.getCodePoint(), 0, unicodeFont.getAscent()); + } else { + scratchGraphics.setColor(java.awt.Color.white); + for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext();) + ((Effect)iter.next()).draw(scratchImage, scratchGraphics, unicodeFont, glyph); + glyph.setShape(null); // The shape will never be needed again. + } WritableRaster raster = scratchImage.getRaster(); int[] row = new int[width]; diff --git a/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/HieroSettings.java b/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/HieroSettings.java index d93d9a120..90a9103df 100644 --- a/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/HieroSettings.java +++ b/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/HieroSettings.java @@ -27,6 +27,7 @@ public class HieroSettings { private int paddingTop, paddingLeft, paddingBottom, paddingRight, paddingAdvanceX, paddingAdvanceY; private int glyphPageWidth = 512, glyphPageHeight = 512; private final List effects = new ArrayList(); + private boolean nativeRendering; public HieroSettings () { } @@ -67,6 +68,8 @@ public class HieroSettings { glyphPageWidth = Integer.parseInt(value); } else if (name.equals("glyph.page.height")) { glyphPageHeight = Integer.parseInt(value); + } else if (name.equals("glyph.native.rendering")) { + nativeRendering = Boolean.parseBoolean(value); } else if (name.equals("effect.class")) { try { effects.add(Class.forName(value).newInstance()); @@ -261,6 +264,14 @@ public class HieroSettings { return effects; } + public boolean getNativeRendering () { + return nativeRendering; + } + + public void setNativeRendering (boolean nativeRendering) { + this.nativeRendering = nativeRendering; + } + /** * Saves the settings to a file. * @throws IOException if the file could not be saved. @@ -278,6 +289,7 @@ public class HieroSettings { out.println("pad.advance.x=" + paddingAdvanceX); out.println("pad.advance.y=" + paddingAdvanceY); out.println(); + out.println("glyph.native.rendering=" + nativeRendering); out.println("glyph.page.width=" + glyphPageWidth); out.println("glyph.page.height=" + glyphPageHeight); out.println(); diff --git a/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/UnicodeFont.java b/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/UnicodeFont.java index 3c632efd5..67b156756 100644 --- a/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/UnicodeFont.java +++ b/extensions/hiero/src/com/badlogic/gdx/hiero/unicodefont/UnicodeFont.java @@ -7,6 +7,7 @@ import java.awt.FontMetrics; import java.awt.Rectangle; import java.awt.font.GlyphVector; import java.awt.font.TextAttribute; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; @@ -41,6 +42,7 @@ public class UnicodeFont { static private final int PAGES = MAX_GLYPH_CODE / PAGE_SIZE; private Font font; + private FontMetrics metrics; private String ttfFileRef; private int ascent, descent, leading, spaceWidth; private final Glyph[][] glyphs = new Glyph[PAGES][]; @@ -51,6 +53,7 @@ public class UnicodeFont { private Glyph missingGlyph; private int glyphPageWidth = 512, glyphPageHeight = 512; private final DisplayList emptyDisplayList = new DisplayList(); + private boolean nativeRendering; private boolean displayListCaching = true; private int baseDisplayListID = -1; @@ -131,7 +134,7 @@ public class UnicodeFont { } font = baseFont.deriveFont(attributes); - FontMetrics metrics = GlyphPage.scratchGraphics.getFontMetrics(font); + metrics = GlyphPage.scratchGraphics.getFontMetrics(font); ascent = metrics.getAscent(); descent = metrics.getDescent(); leading = metrics.getLeading(); @@ -348,6 +351,7 @@ public class UnicodeFont { int extraX = 0, extraY = ascent; boolean startNewLine = false; Texture lastBind = null; + int offsetX = 0; for (int glyphIndex = 0, n = vector.getNumGlyphs(); glyphIndex < n; glyphIndex++) { int charIndex = vector.getGlyphCharIndex(glyphIndex); if (charIndex < startIndex) continue; @@ -356,6 +360,7 @@ public class UnicodeFont { int codePoint = text.codePointAt(charIndex); Rectangle bounds = getGlyphBounds(vector, glyphIndex, codePoint); + bounds.x += offsetX; Glyph glyph = getGlyph(vector.getGlyphCode(glyphIndex), codePoint, bounds, vector, glyphIndex); if (startNewLine && codePoint != '\n') { @@ -397,7 +402,8 @@ public class UnicodeFont { extraY += getLineHeight(); lines++; totalHeight = 0; - } + } else if (nativeRendering) + offsetX += bounds.width; } if (lastBind != null) GL11.glEnd(); @@ -455,7 +461,11 @@ public class UnicodeFont { } private Rectangle getGlyphBounds (GlyphVector vector, int index, int codePoint) { - Rectangle bounds = vector.getGlyphPixelBounds(index, GlyphPage.renderContext, 0, 0); + Rectangle bounds; + if (nativeRendering) + bounds = metrics.getStringBounds("" + (char)codePoint, GlyphPage.scratchGraphics).getBounds(); + else + bounds = vector.getGlyphPixelBounds(index, GlyphPage.renderContext, 0, 0); if (codePoint == ' ') bounds.width = spaceWidth; return bounds; } @@ -726,6 +736,14 @@ public class UnicodeFont { this.displayListCaching = displayListCaching; } + public void setNativeRendering (boolean nativeRendering) { + this.nativeRendering = nativeRendering; + } + + public boolean getNativeRendering () { + return nativeRendering; + } + /** * Returns the path to the TTF file for this UnicodeFont, or null. If this UnicodeFont was created without specifying the TTF * file, it will try to determine the path using Sun classes. If this fails, null is returned. -- 2.11.0