package org.jnode.awt.font.bdf;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
import java.text.CharacterIterator;
import java.util.Locale;
import java.util.Map;
import org.jnode.awt.font.JNodeFontPeer;
import org.jnode.awt.font.TGlyphVector;
import org.jnode.font.bdf.BDFFontContainer;
import org.jnode.font.bdf.BDFGlyph;
import org.jnode.font.bdf.BDFMetrics;
import sun.font.CoreMetrics;
import sun.font.FontLineMetrics;
/**
* Specific implementation of {@link JNodeFontPeer} for BDF fonts
*
* @author fabien
*
*/
public class BDFFontPeer extends JNodeFontPeer<BDFFontProvider, BDFFont> {
/**
* this the char used to replace missing glyphs in BDFFont
*/
private static final char MISSING_GLYPH_CODE = '\u0020';
public BDFFontPeer(BDFFontProvider provider, String name, Map<?, ?> attrs) {
super(provider, name, attrs);
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#canDisplay(java.awt.Font, char)
*/
@Override
public boolean canDisplay(Font font, char c) {
BDFFont bdfFont = getCompatibleFont(font);
//TODO this is a temporary workaround : we should add a method to BDFFont
BDFGlyph spaceGlyph = bdfFont.getContainer().getGlyph(MISSING_GLYPH_CODE);
BDFGlyph characterGlyph = bdfFont.getContainer().getGlyph(c);
return (c == MISSING_GLYPH_CODE) || ((c != MISSING_GLYPH_CODE) && (characterGlyph != spaceGlyph));
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getBaselineFor(java.awt.Font,
* char)
*/
@Override
public byte getBaselineFor(Font font, char c) {
// TODO find proper value from the BDFFontContainer
// it should be one of Font.CENTER_BASELINE, Font.HANGING_BASELINE,
// Font.ROMAN_BASELINE
return Font.ROMAN_BASELINE;
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getFontMetrics(java.awt.Font)
*/
@Override
public FontMetrics getFontMetrics(Font font) {
return getCompatibleFont(font).getFontMetrics();
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getGlyphName(java.awt.Font, int)
*/
@Override
public String getGlyphName(Font font, int glyphIndex) {
return getCompatibleFont(font).getContainer().getGlyphs()[glyphIndex].getName();
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getLineMetrics(java.awt.Font,
* java.text.CharacterIterator, int, int,
* java.awt.font.FontRenderContext)
*/
@Override
public LineMetrics getLineMetrics(Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext rc) {
BDFFont bdfFont = getCompatibleFont(font);
BDFMetrics fm = bdfFont.getContainer().getFontMetrics();
float ascent = fm.getAscent();
float descent = fm.getDescent();
float leading = fm.getLeading();
float height = fm.getHeight();
// TODO find these metrics
int baselineIndex = 0;
float[] baselineOffsets = new float[]{0f};
float strikethroughOffset = 0;
float strikethroughThickness = 0;
float underlineOffset = 0;
float underlineThickness = 0;
float ssOffset = 0;
//
float italicAngle = getItalicAngle(font);
CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height, baselineIndex, baselineOffsets,
strikethroughOffset, strikethroughThickness, underlineOffset,
underlineThickness, ssOffset, italicAngle);
return new FontLineMetrics(limit - begin + 1, cm, rc);
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getMaxCharBounds(java.awt.Font,
* java.awt.font.FontRenderContext)
*/
@Override
public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc) {
BDFFont bdfFont = getCompatibleFont(font);
final Rectangle2D bounds = provider.getMaxCharBounds(bdfFont.getContainer());
transform(bounds, rc);
return bounds;
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getMissingGlyphCode(java.awt.Font)
*/
@Override
public int getMissingGlyphCode(Font font) {
//TODO this is a temporary workaround : we should add a method to BDFFont
return MISSING_GLYPH_CODE; // this the char used to replace missing glyphs in BDFFont
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getNumGlyphs(java.awt.Font)
*/
@Override
public int getNumGlyphs(Font font) {
return getCompatibleFont(font).getContainer().getGlyphs().length;
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getPostScriptName(java.awt.Font)
*/
@Override
public String getPostScriptName(Font font) {
return getCompatibleFont(font).getContainer().getName();
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#getStringBounds(java.awt.Font,
* java.text.CharacterIterator, int, int,
* java.awt.font.FontRenderContext)
*/
@Override
public Rectangle2D getStringBounds(Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext frc) {
BDFFont bdfFont = getCompatibleFont(font);
BDFFontContainer container = bdfFont.getContainer();
double width = 0;
double height = 0;
for (char c = ci.setIndex(begin); ci.getIndex() <= limit; c = ci.next()) {
if (c == CharacterIterator.DONE)
break;
BDFGlyph g = container.getGlyph(c);
if (g != null) {
width += g.getDWidth().width;
height = Math.max(g.getDWidth().height, height);
}
}
final Rectangle2D bounds = new Rectangle2D.Double(0, 0, width, height);
transform(bounds, frc);
return bounds;
}
/**
*
* @see gnu.java.awt.peer.ClasspathFontPeer#getSubFamilyName(java.awt.Font,
* java.util.Locale)
*/
@Override
public String getSubFamilyName(Font font, Locale locale) {
System.out.println("JNodeFontPeer.getSubFamilyName not implemented");
// TODO not implemented ... remove that while moving to openjdk
return "";
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#hasUniformLineMetrics(java.awt.Font)
*/
@Override
public boolean hasUniformLineMetrics(Font font) {
// We don't have "subfonts" (terms used in GNU Classpath javadoc)
// => returns true
return true;
}
/**
* @see gnu.java.awt.peer.ClasspathFontPeer#layoutGlyphVector(java.awt.Font,
* java.awt.font.FontRenderContext, char[], int, int, int)
*/
@Override
public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc,
char[] chars, int start, int limit, int flags) {
//TODO work only for latin fonts but not for hindi, arabic ... fonts
// see GNU Classpath javadoc
return new TGlyphVector(font, chars, start, limit, frc);
}
}