1542 lines
49 KiB
Java
1542 lines
49 KiB
Java
|
/*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||
|
* contributor license agreements. See the NOTICE file distributed with
|
||
|
* this work for additional information regarding copyright ownership.
|
||
|
* The ASF licenses this file to You 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 java.awt;
|
||
|
|
||
|
import com.android.internal.awt.AndroidGraphics2D;
|
||
|
|
||
|
import java.awt.font.FontRenderContext;
|
||
|
import java.awt.font.GlyphVector;
|
||
|
import java.awt.font.LineMetrics;
|
||
|
import java.awt.font.TextAttribute;
|
||
|
import java.awt.font.TransformAttribute;
|
||
|
import java.awt.geom.AffineTransform;
|
||
|
import java.awt.geom.Rectangle2D;
|
||
|
import java.io.File;
|
||
|
import java.io.FileInputStream;
|
||
|
import java.io.BufferedInputStream;
|
||
|
import java.io.FileOutputStream;
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStream;
|
||
|
import java.io.Serializable;
|
||
|
import java.text.CharacterIterator;
|
||
|
import java.text.AttributedCharacterIterator.Attribute;
|
||
|
import java.util.Hashtable;
|
||
|
import java.util.Locale;
|
||
|
import java.util.Map;
|
||
|
import java.util.StringTokenizer;
|
||
|
|
||
|
import org.apache.harmony.awt.gl.font.AndroidGlyphVector;
|
||
|
import org.apache.harmony.awt.gl.font.CommonGlyphVector;
|
||
|
import org.apache.harmony.awt.gl.font.FontPeerImpl;
|
||
|
import org.apache.harmony.awt.gl.font.FontMetricsImpl;
|
||
|
import org.apache.harmony.awt.gl.font.LineMetricsImpl;
|
||
|
import org.apache.harmony.awt.internal.nls.Messages;
|
||
|
import org.apache.harmony.luni.util.NotImplementedException;
|
||
|
import org.apache.harmony.misc.HashCode;
|
||
|
|
||
|
/**
|
||
|
* The Font class represents fonts for rendering text. This class allow to map
|
||
|
* characters to glyphs.
|
||
|
* <p>
|
||
|
* A glyph is a shape used to render a character or a sequence of characters.
|
||
|
* For example one character of Latin writing system represented by one glyph,
|
||
|
* but in complex writing system such as South and South-East Asian there is
|
||
|
* more complicated correspondence between characters and glyphs.
|
||
|
* <p>
|
||
|
* The Font object is identified by two types of names. The logical font name is
|
||
|
* the name that is used to construct the font. The font name is the name of a
|
||
|
* particular font face (for example, Arial Bold). The family name is the font's
|
||
|
* family name that specifies the typographic design across several faces (for
|
||
|
* example, Arial). In all the Font is identified by three attributes: the
|
||
|
* family name, the style (such as bold or italic), and the size.
|
||
|
*
|
||
|
* @since Android 1.0
|
||
|
*/
|
||
|
public class Font implements Serializable {
|
||
|
|
||
|
/**
|
||
|
* The Constant serialVersionUID.
|
||
|
*/
|
||
|
private static final long serialVersionUID = -4206021311591459213L;
|
||
|
|
||
|
// Identity Transform attribute
|
||
|
/**
|
||
|
* The Constant IDENTITY_TRANSFORM.
|
||
|
*/
|
||
|
private static final TransformAttribute IDENTITY_TRANSFORM = new TransformAttribute(
|
||
|
new AffineTransform());
|
||
|
|
||
|
/**
|
||
|
* The Constant PLAIN indicates font's plain style.
|
||
|
*/
|
||
|
public static final int PLAIN = 0;
|
||
|
|
||
|
/**
|
||
|
* The Constant BOLD indicates font's bold style.
|
||
|
*/
|
||
|
public static final int BOLD = 1;
|
||
|
|
||
|
/**
|
||
|
* The Constant ITALIC indicates font's italic style.
|
||
|
*/
|
||
|
public static final int ITALIC = 2;
|
||
|
|
||
|
/**
|
||
|
* The Constant ROMAN_BASELINE indicated roman baseline.
|
||
|
*/
|
||
|
public static final int ROMAN_BASELINE = 0;
|
||
|
|
||
|
/**
|
||
|
* The Constant CENTER_BASELINE indicates center baseline.
|
||
|
*/
|
||
|
public static final int CENTER_BASELINE = 1;
|
||
|
|
||
|
/**
|
||
|
* The Constant HANGING_BASELINE indicates hanging baseline.
|
||
|
*/
|
||
|
public static final int HANGING_BASELINE = 2;
|
||
|
|
||
|
/**
|
||
|
* The Constant TRUETYPE_FONT indicates a font resource of type TRUETYPE.
|
||
|
*/
|
||
|
public static final int TRUETYPE_FONT = 0;
|
||
|
|
||
|
/**
|
||
|
* The Constant TYPE1_FONT indicates a font resource of type TYPE1.
|
||
|
*/
|
||
|
public static final int TYPE1_FONT = 1;
|
||
|
|
||
|
/**
|
||
|
* The Constant LAYOUT_LEFT_TO_RIGHT indicates that text is left to right.
|
||
|
*/
|
||
|
public static final int LAYOUT_LEFT_TO_RIGHT = 0;
|
||
|
|
||
|
/**
|
||
|
* The Constant LAYOUT_RIGHT_TO_LEFT indicates that text is right to left.
|
||
|
*/
|
||
|
public static final int LAYOUT_RIGHT_TO_LEFT = 1;
|
||
|
|
||
|
/**
|
||
|
* The Constant LAYOUT_NO_START_CONTEXT indicates that the text in the char
|
||
|
* array before the indicated start should not be examined.
|
||
|
*/
|
||
|
public static final int LAYOUT_NO_START_CONTEXT = 2;
|
||
|
|
||
|
/**
|
||
|
* The Constant LAYOUT_NO_LIMIT_CONTEXT indicates that text in the char
|
||
|
* array after the indicated limit should not be examined.
|
||
|
*/
|
||
|
public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
|
||
|
|
||
|
/**
|
||
|
* The Constant DEFAULT_FONT.
|
||
|
*/
|
||
|
static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12); //$NON-NLS-1$
|
||
|
|
||
|
/**
|
||
|
* The name of the Font.
|
||
|
*/
|
||
|
protected String name;
|
||
|
|
||
|
/**
|
||
|
* The style of the Font.
|
||
|
*/
|
||
|
protected int style;
|
||
|
|
||
|
/**
|
||
|
* The size of the Font.
|
||
|
*/
|
||
|
protected int size;
|
||
|
|
||
|
/**
|
||
|
* The point size of the Font.
|
||
|
*/
|
||
|
protected float pointSize;
|
||
|
|
||
|
// Flag if the Font object transformed
|
||
|
/**
|
||
|
* The transformed.
|
||
|
*/
|
||
|
private boolean transformed;
|
||
|
|
||
|
// Set of font attributes
|
||
|
/**
|
||
|
* The requested attributes.
|
||
|
*/
|
||
|
private Hashtable<Attribute, Object> fRequestedAttributes;
|
||
|
|
||
|
// font peer object corresponding to this Font
|
||
|
/**
|
||
|
* The font peer.
|
||
|
*/
|
||
|
private transient FontPeerImpl fontPeer;
|
||
|
|
||
|
// number of glyphs in this Font
|
||
|
/**
|
||
|
* The num glyphs.
|
||
|
*/
|
||
|
private transient int numGlyphs = -1;
|
||
|
|
||
|
// code for missing glyph for this Font
|
||
|
/**
|
||
|
* The missing glyph code.
|
||
|
*/
|
||
|
private transient int missingGlyphCode = -1;
|
||
|
|
||
|
/**
|
||
|
* Writes object to ObjectOutputStream.
|
||
|
*
|
||
|
* @param out
|
||
|
* ObjectOutputStream.
|
||
|
* @throws IOException
|
||
|
* Signals that an I/O exception has occurred.
|
||
|
*/
|
||
|
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
||
|
out.defaultWriteObject();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads object from ObjectInputStream object and set native platform
|
||
|
* dependent fields to default values.
|
||
|
*
|
||
|
* @param in
|
||
|
* ObjectInputStream object.
|
||
|
* @throws IOException
|
||
|
* Signals that an I/O exception has occurred.
|
||
|
* @throws ClassNotFoundException
|
||
|
* the class not found exception.
|
||
|
*/
|
||
|
private void readObject(java.io.ObjectInputStream in) throws IOException,
|
||
|
ClassNotFoundException {
|
||
|
in.defaultReadObject();
|
||
|
|
||
|
numGlyphs = -1;
|
||
|
missingGlyphCode = -1;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Instantiates a new Font with the specified attributes. The Font will be
|
||
|
* created with default attributes if the attribute's parameter is null.
|
||
|
*
|
||
|
* @param attributes
|
||
|
* the attributes to be assigned to the new Font, or null.
|
||
|
*/
|
||
|
public Font(Map<? extends Attribute, ?> attributes) {
|
||
|
Object currAttr;
|
||
|
|
||
|
// Default values are taken from the documentation of the Font class.
|
||
|
// See Font constructor, decode and getFont sections.
|
||
|
|
||
|
this.name = "default"; //$NON-NLS-1$
|
||
|
this.size = 12;
|
||
|
this.pointSize = 12;
|
||
|
this.style = Font.PLAIN;
|
||
|
|
||
|
if (attributes != null) {
|
||
|
|
||
|
fRequestedAttributes = new Hashtable<Attribute, Object>(attributes);
|
||
|
|
||
|
currAttr = attributes.get(TextAttribute.SIZE);
|
||
|
if (currAttr != null) {
|
||
|
this.pointSize = ((Float)currAttr).floatValue();
|
||
|
this.size = (int)Math.ceil(this.pointSize);
|
||
|
}
|
||
|
|
||
|
currAttr = attributes.get(TextAttribute.POSTURE);
|
||
|
if (currAttr != null && currAttr.equals(TextAttribute.POSTURE_OBLIQUE)) {
|
||
|
this.style |= Font.ITALIC;
|
||
|
}
|
||
|
|
||
|
currAttr = attributes.get(TextAttribute.WEIGHT);
|
||
|
if ((currAttr != null)
|
||
|
&& (((Float)currAttr).floatValue() >= (TextAttribute.WEIGHT_BOLD).floatValue())) {
|
||
|
this.style |= Font.BOLD;
|
||
|
}
|
||
|
|
||
|
currAttr = attributes.get(TextAttribute.FAMILY);
|
||
|
if (currAttr != null) {
|
||
|
this.name = (String)currAttr;
|
||
|
}
|
||
|
|
||
|
currAttr = attributes.get(TextAttribute.TRANSFORM);
|
||
|
if (currAttr != null) {
|
||
|
if (currAttr instanceof TransformAttribute) {
|
||
|
this.transformed = !((TransformAttribute)currAttr).getTransform().isIdentity();
|
||
|
} else if (currAttr instanceof AffineTransform) {
|
||
|
this.transformed = !((AffineTransform)currAttr).isIdentity();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
fRequestedAttributes = new Hashtable<Attribute, Object>(5);
|
||
|
fRequestedAttributes.put(TextAttribute.TRANSFORM, IDENTITY_TRANSFORM);
|
||
|
|
||
|
this.transformed = false;
|
||
|
|
||
|
fRequestedAttributes.put(TextAttribute.FAMILY, name);
|
||
|
|
||
|
fRequestedAttributes.put(TextAttribute.SIZE, new Float(this.size));
|
||
|
|
||
|
if ((this.style & Font.BOLD) != 0) {
|
||
|
fRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||
|
} else {
|
||
|
fRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
|
||
|
}
|
||
|
if ((this.style & Font.ITALIC) != 0) {
|
||
|
fRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
|
||
|
} else {
|
||
|
fRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Instantiates a new Font with the specified name, style and size.
|
||
|
*
|
||
|
* @param name
|
||
|
* the name of font.
|
||
|
* @param style
|
||
|
* the style of font.
|
||
|
* @param size
|
||
|
* the size of font.
|
||
|
*/
|
||
|
public Font(String name, int style, int size) {
|
||
|
|
||
|
this.name = (name != null) ? name : "Default"; //$NON-NLS-1$
|
||
|
this.size = (size >= 0) ? size : 0;
|
||
|
this.style = (style & ~0x03) == 0 ? style : Font.PLAIN;
|
||
|
this.pointSize = this.size;
|
||
|
|
||
|
fRequestedAttributes = new Hashtable<Attribute, Object>(5);
|
||
|
|
||
|
fRequestedAttributes.put(TextAttribute.TRANSFORM, IDENTITY_TRANSFORM);
|
||
|
|
||
|
this.transformed = false;
|
||
|
|
||
|
fRequestedAttributes.put(TextAttribute.FAMILY, this.name);
|
||
|
fRequestedAttributes.put(TextAttribute.SIZE, new Float(this.size));
|
||
|
|
||
|
if ((this.style & Font.BOLD) != 0) {
|
||
|
fRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||
|
} else {
|
||
|
fRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
|
||
|
}
|
||
|
if ((this.style & Font.ITALIC) != 0) {
|
||
|
fRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
|
||
|
} else {
|
||
|
fRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if this Font has a glyph for the specified character.
|
||
|
*
|
||
|
* @param c
|
||
|
* the character.
|
||
|
* @return true if this Font has a glyph for the specified character, false
|
||
|
* otherwise.
|
||
|
*/
|
||
|
public boolean canDisplay(char c) {
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
return peer.canDisplay(c);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the Font can display the characters of the the specified
|
||
|
* text from the specified start position to the specified limit position.
|
||
|
*
|
||
|
* @param text
|
||
|
* the text.
|
||
|
* @param start
|
||
|
* the start offset (in the character array).
|
||
|
* @param limit
|
||
|
* the limit offset (in the character array).
|
||
|
* @return the a character's position in the text that this Font can not
|
||
|
* display, or -1 if this Font can display all characters in this
|
||
|
* text.
|
||
|
*/
|
||
|
public int canDisplayUpTo(char[] text, int start, int limit) {
|
||
|
int st = start;
|
||
|
int result;
|
||
|
while ((st < limit) && canDisplay(text[st])) {
|
||
|
st++;
|
||
|
}
|
||
|
|
||
|
if (st == limit) {
|
||
|
result = -1;
|
||
|
} else {
|
||
|
result = st;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the Font can display the characters of the the specified
|
||
|
* CharacterIterator from the specified start position and the specified
|
||
|
* limit position.
|
||
|
*
|
||
|
* @param iter
|
||
|
* the CharacterIterator.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param limit
|
||
|
* the limit offset.
|
||
|
* @return the a character's position in the CharacterIterator that this
|
||
|
* Font can not display, or -1 if this Font can display all
|
||
|
* characters in this text.
|
||
|
*/
|
||
|
public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
|
||
|
int st = start;
|
||
|
char c = iter.setIndex(start);
|
||
|
int result;
|
||
|
|
||
|
while ((st < limit) && (canDisplay(c))) {
|
||
|
st++;
|
||
|
c = iter.next();
|
||
|
}
|
||
|
if (st == limit) {
|
||
|
result = -1;
|
||
|
} else {
|
||
|
result = st;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if this Font can display a specified String.
|
||
|
*
|
||
|
* @param str
|
||
|
* the String.
|
||
|
* @return the a character's position in the String that this Font can not
|
||
|
* display, or -1 if this Font can display all characters in this
|
||
|
* text.
|
||
|
*/
|
||
|
public int canDisplayUpTo(String str) {
|
||
|
char[] chars = str.toCharArray();
|
||
|
return canDisplayUpTo(chars, 0, chars.length);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a GlyphVector of associating characters to glyphs based on the
|
||
|
* Unicode map of this Font.
|
||
|
*
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @param chars
|
||
|
* the characters array.
|
||
|
* @return the GlyphVector of associating characters to glyphs based on the
|
||
|
* Unicode map of this Font.
|
||
|
*/
|
||
|
public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars) {
|
||
|
return new AndroidGlyphVector(chars, frc, this, 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a GlyphVector of associating characters contained in the
|
||
|
* specified CharacterIterator to glyphs based on the Unicode map of this
|
||
|
* Font.
|
||
|
*
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @param iter
|
||
|
* the CharacterIterator.
|
||
|
* @return the GlyphVector of associating characters contained in the
|
||
|
* specified CharacterIterator to glyphs based on the Unicode map of
|
||
|
* this Font.
|
||
|
*/
|
||
|
public GlyphVector createGlyphVector(FontRenderContext frc, CharacterIterator iter) {
|
||
|
throw new RuntimeException("Not implemented!"); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a GlyphVector of associating characters to glyphs based on the
|
||
|
* Unicode map of this Font.
|
||
|
*
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @param glyphCodes
|
||
|
* the specified integer array of glyph codes.
|
||
|
* @return the GlyphVector of associating characters to glyphs based on the
|
||
|
* Unicode map of this Font.
|
||
|
* @throws NotImplementedException
|
||
|
* if this method is not implemented by a subclass.
|
||
|
*/
|
||
|
public GlyphVector createGlyphVector(FontRenderContext frc, int[] glyphCodes)
|
||
|
throws org.apache.harmony.luni.util.NotImplementedException {
|
||
|
throw new RuntimeException("Not implemented!"); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a GlyphVector of associating characters to glyphs based on the
|
||
|
* Unicode map of this Font.
|
||
|
*
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @param str
|
||
|
* the specified String.
|
||
|
* @return the GlyphVector of associating characters to glyphs based on the
|
||
|
* Unicode map of this Font.
|
||
|
*/
|
||
|
public GlyphVector createGlyphVector(FontRenderContext frc, String str) {
|
||
|
return new AndroidGlyphVector(str.toCharArray(), frc, this, 0);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the font style constant value corresponding to one of the font
|
||
|
* style names ("BOLD", "ITALIC", "BOLDITALIC"). This method returns
|
||
|
* Font.PLAIN if the argument is not one of the predefined style names.
|
||
|
*
|
||
|
* @param fontStyleName
|
||
|
* font style name.
|
||
|
* @return font style constant value corresponding to the font style name
|
||
|
* specified.
|
||
|
*/
|
||
|
private static int getFontStyle(String fontStyleName) {
|
||
|
int result = Font.PLAIN;
|
||
|
|
||
|
if (fontStyleName.toUpperCase().equals("BOLDITALIC")) { //$NON-NLS-1$
|
||
|
result = Font.BOLD | Font.ITALIC;
|
||
|
} else if (fontStyleName.toUpperCase().equals("BOLD")) { //$NON-NLS-1$
|
||
|
result = Font.BOLD;
|
||
|
} else if (fontStyleName.toUpperCase().equals("ITALIC")) { //$NON-NLS-1$
|
||
|
result = Font.ITALIC;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Decodes the specified string which described the Font. The string should
|
||
|
* have the following format: fontname-style-pointsize. The style can be
|
||
|
* PLAIN, BOLD, BOLDITALIC, or ITALIC.
|
||
|
*
|
||
|
* @param str
|
||
|
* the string which describes the font.
|
||
|
* @return the Font from the specified string.
|
||
|
*/
|
||
|
public static Font decode(String str) {
|
||
|
// XXX: Documentation doesn't describe all cases, e.g. fonts face names
|
||
|
// with
|
||
|
// symbols that are suggested as delimiters in the documentation.
|
||
|
// In this decode implementation only ***-***-*** format is used with
|
||
|
// '-'
|
||
|
// as the delimiter to avoid unexpected parse results of font face names
|
||
|
// with spaces.
|
||
|
|
||
|
if (str == null) {
|
||
|
return DEFAULT_FONT;
|
||
|
}
|
||
|
|
||
|
StringTokenizer strTokens;
|
||
|
String delim = "-"; //$NON-NLS-1$
|
||
|
String substr;
|
||
|
|
||
|
int fontSize = DEFAULT_FONT.size;
|
||
|
int fontStyle = DEFAULT_FONT.style;
|
||
|
String fontName = DEFAULT_FONT.name;
|
||
|
|
||
|
strTokens = new StringTokenizer(str.trim(), delim);
|
||
|
|
||
|
// Font Name
|
||
|
if (strTokens.hasMoreTokens()) {
|
||
|
fontName = strTokens.nextToken(); // first token is the font name
|
||
|
}
|
||
|
|
||
|
// Font Style or Size (if the style is undefined)
|
||
|
if (strTokens.hasMoreTokens()) {
|
||
|
substr = strTokens.nextToken();
|
||
|
|
||
|
try {
|
||
|
// if second token is the font size
|
||
|
fontSize = Integer.parseInt(substr);
|
||
|
} catch (NumberFormatException e) {
|
||
|
// then second token is the font style
|
||
|
fontStyle = getFontStyle(substr);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Font Size
|
||
|
if (strTokens.hasMoreTokens()) {
|
||
|
try {
|
||
|
fontSize = Integer.parseInt(strTokens.nextToken());
|
||
|
} catch (NumberFormatException e) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new Font(fontName, fontStyle, fontSize);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Performs the specified affine transform to the Font and returns a new
|
||
|
* Font.
|
||
|
*
|
||
|
* @param trans
|
||
|
* the AffineTransform.
|
||
|
* @return the Font object.
|
||
|
* @throws IllegalArgumentException
|
||
|
* if affine transform parameter is null.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Font deriveFont(AffineTransform trans) {
|
||
|
|
||
|
if (trans == null) {
|
||
|
// awt.94=transform can not be null
|
||
|
throw new IllegalArgumentException(Messages.getString("awt.94")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>)fRequestedAttributes
|
||
|
.clone();
|
||
|
|
||
|
derivefRequestedAttributes.put(TextAttribute.TRANSFORM, new TransformAttribute(trans));
|
||
|
|
||
|
return new Font(derivefRequestedAttributes);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a new Font that is a copy of the current Font modified so that
|
||
|
* the size is the specified size.
|
||
|
*
|
||
|
* @param size
|
||
|
* the size of font.
|
||
|
* @return the Font object.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Font deriveFont(float size) {
|
||
|
Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>)fRequestedAttributes
|
||
|
.clone();
|
||
|
derivefRequestedAttributes.put(TextAttribute.SIZE, new Float(size));
|
||
|
return new Font(derivefRequestedAttributes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a new Font that is a copy of the current Font modified so that
|
||
|
* the style is the specified style.
|
||
|
*
|
||
|
* @param style
|
||
|
* the style of font.
|
||
|
* @return the Font object.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Font deriveFont(int style) {
|
||
|
Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>)fRequestedAttributes
|
||
|
.clone();
|
||
|
|
||
|
if ((style & Font.BOLD) != 0) {
|
||
|
derivefRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||
|
} else if (derivefRequestedAttributes.get(TextAttribute.WEIGHT) != null) {
|
||
|
derivefRequestedAttributes.remove(TextAttribute.WEIGHT);
|
||
|
}
|
||
|
|
||
|
if ((style & Font.ITALIC) != 0) {
|
||
|
derivefRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
|
||
|
} else if (derivefRequestedAttributes.get(TextAttribute.POSTURE) != null) {
|
||
|
derivefRequestedAttributes.remove(TextAttribute.POSTURE);
|
||
|
}
|
||
|
|
||
|
return new Font(derivefRequestedAttributes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a new Font that is a copy of the current Font modified to match
|
||
|
* the specified style and with the specified affine transform applied to
|
||
|
* its glyphs.
|
||
|
*
|
||
|
* @param style
|
||
|
* the style of font.
|
||
|
* @param trans
|
||
|
* the AffineTransform.
|
||
|
* @return the Font object.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Font deriveFont(int style, AffineTransform trans) {
|
||
|
|
||
|
if (trans == null) {
|
||
|
// awt.94=transform can not be null
|
||
|
throw new IllegalArgumentException(Messages.getString("awt.94")); //$NON-NLS-1$
|
||
|
}
|
||
|
Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>)fRequestedAttributes
|
||
|
.clone();
|
||
|
|
||
|
if ((style & BOLD) != 0) {
|
||
|
derivefRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||
|
} else if (derivefRequestedAttributes.get(TextAttribute.WEIGHT) != null) {
|
||
|
derivefRequestedAttributes.remove(TextAttribute.WEIGHT);
|
||
|
}
|
||
|
|
||
|
if ((style & ITALIC) != 0) {
|
||
|
derivefRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
|
||
|
} else if (derivefRequestedAttributes.get(TextAttribute.POSTURE) != null) {
|
||
|
derivefRequestedAttributes.remove(TextAttribute.POSTURE);
|
||
|
}
|
||
|
derivefRequestedAttributes.put(TextAttribute.TRANSFORM, new TransformAttribute(trans));
|
||
|
|
||
|
return new Font(derivefRequestedAttributes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a new Font that is a copy of the current Font modified so that
|
||
|
* the size and style are the specified size and style.
|
||
|
*
|
||
|
* @param style
|
||
|
* the style of font.
|
||
|
* @param size
|
||
|
* the size of font.
|
||
|
* @return the Font object.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Font deriveFont(int style, float size) {
|
||
|
Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>)fRequestedAttributes
|
||
|
.clone();
|
||
|
|
||
|
if ((style & BOLD) != 0) {
|
||
|
derivefRequestedAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||
|
} else if (derivefRequestedAttributes.get(TextAttribute.WEIGHT) != null) {
|
||
|
derivefRequestedAttributes.remove(TextAttribute.WEIGHT);
|
||
|
}
|
||
|
|
||
|
if ((style & ITALIC) != 0) {
|
||
|
derivefRequestedAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
|
||
|
} else if (derivefRequestedAttributes.get(TextAttribute.POSTURE) != null) {
|
||
|
derivefRequestedAttributes.remove(TextAttribute.POSTURE);
|
||
|
}
|
||
|
|
||
|
derivefRequestedAttributes.put(TextAttribute.SIZE, new Float(size));
|
||
|
return new Font(derivefRequestedAttributes);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a new Font object with a new set of font attributes.
|
||
|
*
|
||
|
* @param attributes
|
||
|
* the map of attributes.
|
||
|
* @return the Font.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Font deriveFont(Map<? extends Attribute, ?> attributes) {
|
||
|
Attribute[] avalAttributes = this.getAvailableAttributes();
|
||
|
|
||
|
Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>)fRequestedAttributes
|
||
|
.clone();
|
||
|
Object currAttribute;
|
||
|
for (Attribute element : avalAttributes) {
|
||
|
currAttribute = attributes.get(element);
|
||
|
if (currAttribute != null) {
|
||
|
derivefRequestedAttributes.put(element, currAttribute);
|
||
|
}
|
||
|
}
|
||
|
return new Font(derivefRequestedAttributes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Compares the specified Object with the current Font.
|
||
|
*
|
||
|
* @param obj
|
||
|
* the Object to be compared.
|
||
|
* @return true, if the specified Object is an instance of Font with the
|
||
|
* same family, size, and style as this Font, false otherwise.
|
||
|
*/
|
||
|
@Override
|
||
|
public boolean equals(Object obj) {
|
||
|
if (obj == this) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (obj != null) {
|
||
|
try {
|
||
|
Font font = (Font)obj;
|
||
|
|
||
|
return ((this.style == font.style) && (this.size == font.size)
|
||
|
&& this.name.equals(font.name) && (this.pointSize == font.pointSize) && (this
|
||
|
.getTransform()).equals(font.getTransform()));
|
||
|
} catch (ClassCastException e) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the map of font's attributes.
|
||
|
*
|
||
|
* @return the map of font's attributes.
|
||
|
*/
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public Map<TextAttribute, ?> getAttributes() {
|
||
|
return (Map<TextAttribute, ?>)fRequestedAttributes.clone();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the keys of all available attributes.
|
||
|
*
|
||
|
* @return the keys array of all available attributes.
|
||
|
*/
|
||
|
public Attribute[] getAvailableAttributes() {
|
||
|
Attribute[] attrs = {
|
||
|
TextAttribute.FAMILY, TextAttribute.POSTURE, TextAttribute.SIZE,
|
||
|
TextAttribute.TRANSFORM, TextAttribute.WEIGHT, TextAttribute.SUPERSCRIPT,
|
||
|
TextAttribute.WIDTH
|
||
|
};
|
||
|
return attrs;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the baseline for this character.
|
||
|
*
|
||
|
* @param c
|
||
|
* the character.
|
||
|
* @return the baseline for this character.
|
||
|
*/
|
||
|
public byte getBaselineFor(char c) {
|
||
|
// TODO: implement using TT BASE table data
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the family name of the Font.
|
||
|
*
|
||
|
* @return the family name of the Font.
|
||
|
*/
|
||
|
public String getFamily() {
|
||
|
if (fRequestedAttributes != null) {
|
||
|
fRequestedAttributes.get(TextAttribute.FAMILY);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the family name of this Font associated with the specified
|
||
|
* locale.
|
||
|
*
|
||
|
* @param l
|
||
|
* the locale.
|
||
|
* @return the family name of this Font associated with the specified
|
||
|
* locale.
|
||
|
*/
|
||
|
public String getFamily(Locale l) {
|
||
|
if (l == null) {
|
||
|
// awt.01='{0}' parameter is null
|
||
|
throw new NullPointerException(Messages.getString("awt.01", "Locale")); //$NON-NLS-1$ //$NON-NLS-2$
|
||
|
}
|
||
|
return getFamily();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a Font with the specified attribute set.
|
||
|
*
|
||
|
* @param attributes
|
||
|
* the attributes to be assigned to the new Font.
|
||
|
* @return the Font.
|
||
|
*/
|
||
|
public static Font getFont(Map<? extends Attribute, ?> attributes) {
|
||
|
Font fnt = (Font)attributes.get(TextAttribute.FONT);
|
||
|
if (fnt != null) {
|
||
|
return fnt;
|
||
|
}
|
||
|
return new Font(attributes);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a Font object from the system properties list with the specified
|
||
|
* name or returns the specified Font if there is no such property.
|
||
|
*
|
||
|
* @param sp
|
||
|
* the specified property name.
|
||
|
* @param f
|
||
|
* the Font.
|
||
|
* @return the Font object from the system properties list with the
|
||
|
* specified name or the specified Font if there is no such
|
||
|
* property.
|
||
|
*/
|
||
|
public static Font getFont(String sp, Font f) {
|
||
|
String pr = System.getProperty(sp);
|
||
|
if (pr == null) {
|
||
|
return f;
|
||
|
}
|
||
|
return decode(pr);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a Font object from the system properties list with the specified
|
||
|
* name.
|
||
|
*
|
||
|
* @param sp
|
||
|
* the system property name.
|
||
|
* @return the Font, or null if there is no such property with the specified
|
||
|
* name.
|
||
|
*/
|
||
|
public static Font getFont(String sp) {
|
||
|
return getFont(sp, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the font name.
|
||
|
*
|
||
|
* @return the font name.
|
||
|
*/
|
||
|
public String getFontName() {
|
||
|
if (fRequestedAttributes != null) {
|
||
|
fRequestedAttributes.get(TextAttribute.FAMILY);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the font name associated with the specified locale.
|
||
|
*
|
||
|
* @param l
|
||
|
* the locale.
|
||
|
* @return the font name associated with the specified locale.
|
||
|
*/
|
||
|
public String getFontName(Locale l) {
|
||
|
return getFamily();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a LineMetrics object created with the specified parameters.
|
||
|
*
|
||
|
* @param chars
|
||
|
* the chars array.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param end
|
||
|
* the end offset.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return the LineMetrics for the specified parameters.
|
||
|
*/
|
||
|
public LineMetrics getLineMetrics(char[] chars, int start, int end, FontRenderContext frc) {
|
||
|
if (frc == null) {
|
||
|
// awt.00=FontRenderContext is null
|
||
|
throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
// FontMetrics fm = AndroidGraphics2D.getInstance().getFontMetrics();
|
||
|
FontMetrics fm = new FontMetricsImpl(this);
|
||
|
float[] fmet = {
|
||
|
fm.getAscent(), fm.getDescent(), fm.getLeading()
|
||
|
};
|
||
|
return new LineMetricsImpl(chars.length, fmet, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a LineMetrics object created with the specified parameters.
|
||
|
*
|
||
|
* @param iter
|
||
|
* the CharacterIterator.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param end
|
||
|
* the end offset.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return the LineMetrics for the specified parameters.
|
||
|
*/
|
||
|
public LineMetrics getLineMetrics(CharacterIterator iter, int start, int end,
|
||
|
FontRenderContext frc) {
|
||
|
|
||
|
if (frc == null) {
|
||
|
// awt.00=FontRenderContext is null
|
||
|
throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
String resultString;
|
||
|
int iterCount;
|
||
|
|
||
|
iterCount = end - start;
|
||
|
if (iterCount < 0) {
|
||
|
resultString = ""; //$NON-NLS-1$
|
||
|
} else {
|
||
|
char[] chars = new char[iterCount];
|
||
|
int i = 0;
|
||
|
for (char c = iter.setIndex(start); c != CharacterIterator.DONE && (i < iterCount); c = iter
|
||
|
.next()) {
|
||
|
chars[i] = c;
|
||
|
i++;
|
||
|
}
|
||
|
resultString = new String(chars);
|
||
|
}
|
||
|
return this.getLineMetrics(resultString, frc);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a LineMetrics object created with the specified parameters.
|
||
|
*
|
||
|
* @param str
|
||
|
* the String.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return the LineMetrics for the specified parameters.
|
||
|
*/
|
||
|
public LineMetrics getLineMetrics(String str, FontRenderContext frc) {
|
||
|
// FontMetrics fm = AndroidGraphics2D.getInstance().getFontMetrics();
|
||
|
FontMetrics fm = new FontMetricsImpl(this);
|
||
|
float[] fmet = {
|
||
|
fm.getAscent(), fm.getDescent(), fm.getLeading()
|
||
|
};
|
||
|
// Log.i("FONT FMET", fmet.toString());
|
||
|
return new LineMetricsImpl(str.length(), fmet, null);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a LineMetrics object created with the specified parameters.
|
||
|
*
|
||
|
* @param str
|
||
|
* the String.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param end
|
||
|
* the end offset.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return the LineMetrics for the specified parameters.
|
||
|
*/
|
||
|
public LineMetrics getLineMetrics(String str, int start, int end, FontRenderContext frc) {
|
||
|
return this.getLineMetrics(str.substring(start, end), frc);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the logical bounds of the specified String in the specified
|
||
|
* FontRenderContext. The logical bounds contains the origin, ascent,
|
||
|
* advance, and height.
|
||
|
*
|
||
|
* @param ci
|
||
|
* the specified CharacterIterator.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param end
|
||
|
* the end offset.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return a Rectangle2D object.
|
||
|
*/
|
||
|
public Rectangle2D getStringBounds(CharacterIterator ci, int start, int end,
|
||
|
FontRenderContext frc) {
|
||
|
int first = ci.getBeginIndex();
|
||
|
int finish = ci.getEndIndex();
|
||
|
char[] chars;
|
||
|
|
||
|
if (start < first) {
|
||
|
// awt.95=Wrong start index: {0}
|
||
|
throw new IndexOutOfBoundsException(Messages.getString("awt.95", start)); //$NON-NLS-1$
|
||
|
}
|
||
|
if (end > finish) {
|
||
|
// awt.96=Wrong finish index: {0}
|
||
|
throw new IndexOutOfBoundsException(Messages.getString("awt.96", end)); //$NON-NLS-1$
|
||
|
}
|
||
|
if (start > end) {
|
||
|
// awt.97=Wrong range length: {0}
|
||
|
throw new IndexOutOfBoundsException(Messages.getString("awt.97", //$NON-NLS-1$
|
||
|
(end - start)));
|
||
|
}
|
||
|
|
||
|
if (frc == null) {
|
||
|
throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
chars = new char[end - start];
|
||
|
|
||
|
ci.setIndex(start);
|
||
|
for (int i = 0; i < chars.length; i++) {
|
||
|
chars[i] = ci.current();
|
||
|
ci.next();
|
||
|
}
|
||
|
|
||
|
return this.getStringBounds(chars, 0, chars.length, frc);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the logical bounds of the specified String in the specified
|
||
|
* FontRenderContext. The logical bounds contains the origin, ascent,
|
||
|
* advance, and height.
|
||
|
*
|
||
|
* @param str
|
||
|
* the specified String.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return a Rectangle2D object.
|
||
|
*/
|
||
|
public Rectangle2D getStringBounds(String str, FontRenderContext frc) {
|
||
|
char[] chars = str.toCharArray();
|
||
|
return this.getStringBounds(chars, 0, chars.length, frc);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the logical bounds of the specified String in the specified
|
||
|
* FontRenderContext. The logical bounds contains the origin, ascent,
|
||
|
* advance, and height.
|
||
|
*
|
||
|
* @param str
|
||
|
* the specified String.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param end
|
||
|
* the end offset.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return a Rectangle2D object.
|
||
|
*/
|
||
|
public Rectangle2D getStringBounds(String str, int start, int end, FontRenderContext frc) {
|
||
|
|
||
|
return this.getStringBounds((str.substring(start, end)), frc);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the logical bounds of the specified String in the specified
|
||
|
* FontRenderContext. The logical bounds contains the origin, ascent,
|
||
|
* advance, and height.
|
||
|
*
|
||
|
* @param chars
|
||
|
* the specified character array.
|
||
|
* @param start
|
||
|
* the start offset.
|
||
|
* @param end
|
||
|
* the end offset.
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return a Rectangle2D object.
|
||
|
*/
|
||
|
public Rectangle2D getStringBounds(char[] chars, int start, int end, FontRenderContext frc) {
|
||
|
if (start < 0) {
|
||
|
// awt.95=Wrong start index: {0}
|
||
|
throw new IndexOutOfBoundsException(Messages.getString("awt.95", start)); //$NON-NLS-1$
|
||
|
}
|
||
|
if (end > chars.length) {
|
||
|
// awt.96=Wrong finish index: {0}
|
||
|
throw new IndexOutOfBoundsException(Messages.getString("awt.96", end)); //$NON-NLS-1$
|
||
|
}
|
||
|
if (start > end) {
|
||
|
// awt.97=Wrong range length: {0}
|
||
|
throw new IndexOutOfBoundsException(Messages.getString("awt.97", //$NON-NLS-1$
|
||
|
(end - start)));
|
||
|
}
|
||
|
|
||
|
if (frc == null) {
|
||
|
throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
|
||
|
final int TRANSFORM_MASK = AffineTransform.TYPE_GENERAL_ROTATION
|
||
|
| AffineTransform.TYPE_GENERAL_TRANSFORM;
|
||
|
Rectangle2D bounds;
|
||
|
|
||
|
AffineTransform transform = getTransform();
|
||
|
|
||
|
// XXX: for transforms where an angle between basis vectors is not 90
|
||
|
// degrees Rectanlge2D class doesn't fit as Logical bounds.
|
||
|
if ((transform.getType() & TRANSFORM_MASK) == 0) {
|
||
|
int width = 0;
|
||
|
for (int i = start; i < end; i++) {
|
||
|
width += peer.charWidth(chars[i]);
|
||
|
}
|
||
|
// LineMetrics nlm = peer.getLineMetrics();
|
||
|
|
||
|
LineMetrics nlm = getLineMetrics(chars, start, end, frc);
|
||
|
|
||
|
bounds = transform.createTransformedShape(
|
||
|
new Rectangle2D.Float(0, -nlm.getAscent(), width, nlm.getHeight()))
|
||
|
.getBounds2D();
|
||
|
} else {
|
||
|
int len = end - start;
|
||
|
char[] subChars = new char[len];
|
||
|
System.arraycopy(chars, start, subChars, 0, len);
|
||
|
bounds = createGlyphVector(frc, subChars).getLogicalBounds();
|
||
|
}
|
||
|
return bounds;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the character's maximum bounds as defined in the specified
|
||
|
* FontRenderContext.
|
||
|
*
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @return the character's maximum bounds.
|
||
|
*/
|
||
|
public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
|
||
|
if (frc == null) {
|
||
|
// awt.00=FontRenderContext is null
|
||
|
throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
|
||
|
Rectangle2D bounds = peer.getMaxCharBounds(frc);
|
||
|
AffineTransform transform = getTransform();
|
||
|
// !! Documentation doesn't describe meaning of max char bounds
|
||
|
// for the fonts that have rotate transforms. For all transforms
|
||
|
// returned bounds are the bounds of transformed maxCharBounds
|
||
|
// Rectangle2D that corresponds to the font with identity transform.
|
||
|
// TODO: resolve this issue to return correct bounds
|
||
|
bounds = transform.createTransformedShape(bounds).getBounds2D();
|
||
|
|
||
|
return bounds;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a new GlyphVector object performing full layout of the text.
|
||
|
*
|
||
|
* @param frc
|
||
|
* the FontRenderContext.
|
||
|
* @param chars
|
||
|
* the character array to be layout.
|
||
|
* @param start
|
||
|
* the start offset of the text to use for the GlyphVector.
|
||
|
* @param count
|
||
|
* the count of characters to use for the GlyphVector.
|
||
|
* @param flags
|
||
|
* the flag indicating text direction: LAYOUT_RIGHT_TO_LEFT,
|
||
|
* LAYOUT_LEFT_TO_RIGHT.
|
||
|
* @return the GlyphVector.
|
||
|
*/
|
||
|
public GlyphVector layoutGlyphVector(FontRenderContext frc, char[] chars, int start, int count,
|
||
|
int flags) {
|
||
|
// TODO: implement method for bidirectional text.
|
||
|
// At the moment only LTR and RTL texts supported.
|
||
|
if (start < 0) {
|
||
|
// awt.95=Wrong start index: {0}
|
||
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.95", //$NON-NLS-1$
|
||
|
start));
|
||
|
}
|
||
|
|
||
|
if (count < 0) {
|
||
|
// awt.98=Wrong count value, can not be negative: {0}
|
||
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.98", //$NON-NLS-1$
|
||
|
count));
|
||
|
}
|
||
|
|
||
|
if (start + count > chars.length) {
|
||
|
// awt.99=Wrong [start + count] is out of range: {0}
|
||
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.99", //$NON-NLS-1$
|
||
|
(start + count)));
|
||
|
}
|
||
|
|
||
|
char[] out = new char[count];
|
||
|
System.arraycopy(chars, start, out, 0, count);
|
||
|
|
||
|
return new CommonGlyphVector(out, frc, this, flags);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the String representation of this Font.
|
||
|
*
|
||
|
* @return the String representation of this Font.
|
||
|
*/
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
String stl = "plain"; //$NON-NLS-1$
|
||
|
String result;
|
||
|
|
||
|
if (this.isBold() && this.isItalic()) {
|
||
|
stl = "bolditalic"; //$NON-NLS-1$
|
||
|
}
|
||
|
if (this.isBold() && !this.isItalic()) {
|
||
|
stl = "bold"; //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
if (!this.isBold() && this.isItalic()) {
|
||
|
stl = "italic"; //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
result = this.getClass().getName() + "[family=" + this.getFamily() + //$NON-NLS-1$
|
||
|
",name=" + this.name + //$NON-NLS-1$
|
||
|
",style=" + stl + //$NON-NLS-1$
|
||
|
",size=" + this.size + "]"; //$NON-NLS-1$ //$NON-NLS-2$
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the postscript name of this Font.
|
||
|
*
|
||
|
* @return the postscript name of this Font.
|
||
|
*/
|
||
|
public String getPSName() {
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
return peer.getPSName();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the logical name of this Font.
|
||
|
*
|
||
|
* @return the logical name of this Font.
|
||
|
*/
|
||
|
public String getName() {
|
||
|
return (this.name);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the peer of this Font.
|
||
|
*
|
||
|
* @return the peer of this Font.
|
||
|
* @deprecated Font rendering is platform independent now.
|
||
|
*/
|
||
|
@Deprecated
|
||
|
public java.awt.peer.FontPeer getPeer() {
|
||
|
if (fontPeer == null) {
|
||
|
fontPeer = (FontPeerImpl)Toolkit.getDefaultToolkit().getGraphicsFactory().getFontPeer(
|
||
|
this);
|
||
|
}
|
||
|
return fontPeer;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the transform acting on this Font (from the Font's attributes).
|
||
|
*
|
||
|
* @return the transformation of this Font.
|
||
|
*/
|
||
|
public AffineTransform getTransform() {
|
||
|
Object transform = fRequestedAttributes.get(TextAttribute.TRANSFORM);
|
||
|
|
||
|
if (transform != null) {
|
||
|
if (transform instanceof TransformAttribute) {
|
||
|
return ((TransformAttribute)transform).getTransform();
|
||
|
}
|
||
|
if (transform instanceof AffineTransform) {
|
||
|
return new AffineTransform((AffineTransform)transform);
|
||
|
}
|
||
|
} else {
|
||
|
transform = new AffineTransform();
|
||
|
}
|
||
|
return (AffineTransform)transform;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if this font is transformed or not.
|
||
|
*
|
||
|
* @return true, if this font is transformed, false otherwise.
|
||
|
*/
|
||
|
public boolean isTransformed() {
|
||
|
return this.transformed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if this font has plain style or not.
|
||
|
*
|
||
|
* @return true, if this font has plain style, false otherwise.
|
||
|
*/
|
||
|
public boolean isPlain() {
|
||
|
return (this.style == PLAIN);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if this font has italic style or not.
|
||
|
*
|
||
|
* @return true, if this font has italic style, false otherwise.
|
||
|
*/
|
||
|
public boolean isItalic() {
|
||
|
return (this.style & ITALIC) != 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if this font has bold style or not.
|
||
|
*
|
||
|
* @return true, if this font has bold style, false otherwise.
|
||
|
*/
|
||
|
public boolean isBold() {
|
||
|
return (this.style & BOLD) != 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if this Font has uniform line metrics.
|
||
|
*
|
||
|
* @return true if this Font has uniform line metrics, false otherwise.
|
||
|
*/
|
||
|
public boolean hasUniformLineMetrics() {
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
return peer.hasUniformLineMetrics();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns hash code of this Font object.
|
||
|
*
|
||
|
* @return the hash code of this Font object.
|
||
|
*/
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
HashCode hash = new HashCode();
|
||
|
|
||
|
hash.append(this.name);
|
||
|
hash.append(this.style);
|
||
|
hash.append(this.size);
|
||
|
|
||
|
return hash.hashCode();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the style of this Font.
|
||
|
*
|
||
|
* @return the style of this Font.
|
||
|
*/
|
||
|
public int getStyle() {
|
||
|
return this.style;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the size of this Font.
|
||
|
*
|
||
|
* @return the size of this Font.
|
||
|
*/
|
||
|
public int getSize() {
|
||
|
return this.size;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the number of glyphs for this Font.
|
||
|
*
|
||
|
* @return the number of glyphs for this Font.
|
||
|
*/
|
||
|
public int getNumGlyphs() {
|
||
|
if (numGlyphs == -1) {
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
this.numGlyphs = peer.getNumGlyphs();
|
||
|
}
|
||
|
return this.numGlyphs;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the glyphCode which is used as default glyph when this Font does not
|
||
|
* have a glyph for a specified Unicode.
|
||
|
*
|
||
|
* @return the missing glyph code.
|
||
|
*/
|
||
|
public int getMissingGlyphCode() {
|
||
|
if (missingGlyphCode == -1) {
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
this.missingGlyphCode = peer.getMissingGlyphCode();
|
||
|
}
|
||
|
return this.missingGlyphCode;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the float value of font's size.
|
||
|
*
|
||
|
* @return the float value of font's size.
|
||
|
*/
|
||
|
public float getSize2D() {
|
||
|
return this.pointSize;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the italic angle of this Font.
|
||
|
*
|
||
|
* @return the italic angle of this Font.
|
||
|
*/
|
||
|
public float getItalicAngle() {
|
||
|
FontPeerImpl peer = (FontPeerImpl)this.getPeer();
|
||
|
return peer.getItalicAngle();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates the font with the specified font format and font file.
|
||
|
*
|
||
|
* @param fontFormat
|
||
|
* the font format.
|
||
|
* @param fontFile
|
||
|
* the file object represented the input data for the font.
|
||
|
* @return the Font.
|
||
|
* @throws FontFormatException
|
||
|
* is thrown if fontFile does not contain the required font
|
||
|
* tables for the specified format.
|
||
|
* @throws IOException
|
||
|
* signals that an I/O exception has occurred.
|
||
|
*/
|
||
|
public static Font createFont(int fontFormat, File fontFile) throws FontFormatException,
|
||
|
IOException {
|
||
|
// ???AWT not supported
|
||
|
InputStream is = new FileInputStream(fontFile);
|
||
|
try {
|
||
|
return createFont(fontFormat, is);
|
||
|
} finally {
|
||
|
is.close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates the font with the specified font format and input stream.
|
||
|
*
|
||
|
* @param fontFormat
|
||
|
* the font format.
|
||
|
* @param fontStream
|
||
|
* the input stream represented input data for the font.
|
||
|
* @return the Font.
|
||
|
* @throws FontFormatException
|
||
|
* is thrown if fontFile does not contain the required font
|
||
|
* tables for the specified format.
|
||
|
* @throws IOException
|
||
|
* signals that an I/O exception has occurred.
|
||
|
*/
|
||
|
public static Font createFont(int fontFormat, InputStream fontStream)
|
||
|
throws FontFormatException, IOException {
|
||
|
|
||
|
// ???AWT not supported
|
||
|
|
||
|
BufferedInputStream buffStream;
|
||
|
int bRead = 0;
|
||
|
int size = 8192;
|
||
|
// memory page size, for the faster reading
|
||
|
byte buf[] = new byte[size];
|
||
|
|
||
|
if (fontFormat != TRUETYPE_FONT) { // awt.9A=Unsupported font format
|
||
|
throw new IllegalArgumentException(Messages.getString("awt.9A")); //$NON-NLS-1$
|
||
|
}
|
||
|
|
||
|
/* Get font file in system-specific directory */
|
||
|
|
||
|
File fontFile = Toolkit.getDefaultToolkit().getGraphicsFactory().getFontManager()
|
||
|
.getTempFontFile();
|
||
|
|
||
|
// BEGIN android-modified
|
||
|
buffStream = new BufferedInputStream(fontStream, 8192);
|
||
|
// END android-modified
|
||
|
FileOutputStream fOutStream = new FileOutputStream(fontFile);
|
||
|
|
||
|
bRead = buffStream.read(buf, 0, size);
|
||
|
|
||
|
while (bRead != -1) {
|
||
|
fOutStream.write(buf, 0, bRead);
|
||
|
bRead = buffStream.read(buf, 0, size);
|
||
|
}
|
||
|
|
||
|
buffStream.close();
|
||
|
fOutStream.close();
|
||
|
|
||
|
Font font = null;
|
||
|
|
||
|
font = Toolkit.getDefaultToolkit().getGraphicsFactory().embedFont(
|
||
|
fontFile.getAbsolutePath());
|
||
|
if (font == null) { // awt.9B=Can't create font - bad font data
|
||
|
throw new FontFormatException(Messages.getString("awt.9B")); //$NON-NLS-1$
|
||
|
}
|
||
|
return font;
|
||
|
}
|
||
|
|
||
|
}
|