/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.awt.font; import gnu.java.awt.peer.ClasspathFontPeer; 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.awt.peer.FontPeer; import java.text.CharacterIterator; import java.util.Locale; import java.util.Map; import sun.font.StandardGlyphVector; /** * @author vali */ public abstract class JNodeFontPeer<FP extends FontProvider<F>, F extends Font> extends ClasspathFontPeer implements FontPeer { protected final FP provider; /** * @param name * @param attrs */ public JNodeFontPeer(FP provider, String name, Map<?, ?> attrs) { super(name, attrs); this.provider = provider; } public abstract boolean canDisplay(Font font, char c); @Override public final int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit) { int upTo = -1; for (char c = i.setIndex(start); i.getIndex() <= limit; c = i.next()) { if (!canDisplay(font, c)) { upTo = i.getIndex(); break; } } return upTo; } @Override public final GlyphVector createGlyphVector(Font font, FontRenderContext frc, CharacterIterator ci) { return TGlyphVector.create(font, frc, ci); } @Override public final GlyphVector createGlyphVector(Font font, FontRenderContext ctx, int[] glyphCodes) { return new StandardGlyphVector(font, glyphCodes, ctx); } public abstract byte getBaselineFor(Font font, char c); public abstract FontMetrics getFontMetrics(Font font); public abstract String getGlyphName(Font font, int glyphIndex); public abstract LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin, int limit, FontRenderContext rc); public abstract Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc); public abstract int getMissingGlyphCode(Font font); public abstract int getNumGlyphs(Font font); public abstract String getPostScriptName(Font font); public abstract Rectangle2D getStringBounds(Font font, CharacterIterator ci, int begin, int limit, FontRenderContext frc); public abstract String getSubFamilyName(Font font, Locale locale); public abstract boolean hasUniformLineMetrics(Font font); public abstract GlyphVector layoutGlyphVector(Font font, FontRenderContext frc, char[] chars, int start, int limit, int flags); /** * Convert the given font to a Font whose type is F. * The font given as input might not be an instance of F * since {@link Font} class is public, not abstract and has a public constructor. * If that's the case, then we are trying to find the closest font that * this peer's provider provides. * * @param font any instance of {@link Font} (might not be an instance of F) * @return the Font */ protected final F getCompatibleFont(Font font) { return provider.getCompatibleFont(font); } protected final void transform(Rectangle2D bounds, FontRenderContext frc) { if (frc.getTransform() != null) { double[] srcPoints = new double[] {bounds.getMinX(), bounds.getMinY(), bounds.getMinX(), bounds.getMaxY(), bounds.getMaxX(), bounds.getMaxY(), bounds.getMaxX(), bounds.getMinY()}; double[] dstPoints = new double[srcPoints.length]; frc.getTransform().transform(srcPoints, 0, dstPoints, 0, srcPoints.length / 2); // compute the bounding box of the result double minX = dstPoints[0]; double minY = dstPoints[1]; double maxX = minX; double maxY = minY; for (int i = 2; i < dstPoints.length; i += 2) { double x = dstPoints[i]; minX = Math.min(minX, x); maxX = Math.max(maxX, x); double y = dstPoints[i + 1]; minY = Math.min(minY, y); maxY = Math.max(maxY, y); } bounds.setRect(minX, minY, maxX - minX + 1, maxY - minY + 1); } } }