summaryrefslogtreecommitdiffstats
path: root/awt/org/apache/harmony/awt/gl/font/CompositeFont.java
diff options
context:
space:
mode:
Diffstat (limited to 'awt/org/apache/harmony/awt/gl/font/CompositeFont.java')
-rw-r--r--awt/org/apache/harmony/awt/gl/font/CompositeFont.java486
1 files changed, 486 insertions, 0 deletions
diff --git a/awt/org/apache/harmony/awt/gl/font/CompositeFont.java b/awt/org/apache/harmony/awt/gl/font/CompositeFont.java
new file mode 100644
index 0000000..70cb334
--- /dev/null
+++ b/awt/org/apache/harmony/awt/gl/font/CompositeFont.java
@@ -0,0 +1,486 @@
+/*
+ * 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.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package org.apache.harmony.awt.gl.font;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineMetrics;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.harmony.awt.gl.font.FontPeerImpl;
+import org.apache.harmony.awt.gl.font.FontProperty;
+
+/**
+ * CompositeFont class is the implementation of logical font classes.
+ * Every logical font consists of several physical fonts that described
+ * in font.properties file according to the face name of this logical font.
+ */
+public class CompositeFont extends FontPeerImpl{
+
+ // a number of physical fonts that CompositeFont consist of
+ int numFonts;
+
+ // font family name
+ String family;
+
+ // font face name
+ String face;
+
+ String[] fontNames;
+
+ // an array of font properties applicable to this CompositeFont
+ FontProperty[] fontProperties;
+
+ // an array of font peers applicable to this CompositeFont
+ public FontPeerImpl[] fPhysicalFonts;
+
+ // missing glyph code field
+ int missingGlyphCode = -1;
+
+ // line metrics of this font
+ LineMetricsImpl nlm = null;
+
+ // cached num glyphs parameter of this font that is the sum of num glyphs of
+ // font peers composing this font
+ int cachedNumGlyphs = -1;
+ /**
+ * Creates CompositeFont object that is corresponding to the specified logical
+ * family name.
+ *
+ * @param familyName logical family name CompositeFont is to be created from
+ * @param faceName logical face name CompositeFont is to be created from
+ * @param _style style of the CompositeFont to be created
+ * @param _size size of the CompositeFont to be created
+ * @param fProperties an array of FontProperties describing physical fonts -
+ * parts of logical font
+ * @param physFonts an array of physical font peers related to the CompositeFont
+ * to be created
+ */
+ public CompositeFont(String familyName, String faceName, int _style, int _size, FontProperty[] fProperties, FontPeerImpl[] physFonts){
+ this.size = _size;
+ this.name = faceName;
+ this.family = familyName;
+ this.style = _style;
+ this.face = faceName;
+ this.psName = faceName;
+ this.fontProperties = fProperties;// !! Supposed that fProperties parameter != null
+ fPhysicalFonts = physFonts;
+ numFonts = fPhysicalFonts.length;
+ setDefaultLineMetrics("", null); //$NON-NLS-1$
+ this.uniformLM = false;
+ }
+
+ /**
+ * Returns the index of the FontPeer in array of physical fonts that is applicable
+ * for the given character. This font has to have the highest priority among fonts
+ * that can display this character and don't have exclusion range covering
+ * specified character. If there is no desired fonts -1 is returned.
+ *
+ * @param chr specified character
+ * @return index of the font from the array of physical fonts that will be used
+ * during processing of the specified character.
+ */
+ public int getCharFontIndex(char chr){
+ for (int i = 0; i < numFonts; i++){
+ if (fontProperties[i].isCharExcluded(chr)){
+ continue;
+ }
+ if (fPhysicalFonts[i].canDisplay(chr)){
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the index of the FontPeer in array of physical fonts that is applicable
+ * for the given character. This font has to have the highest priority among fonts
+ * that can display this character and don't have exclusion range covering
+ * specified character. If there is no desired fonts default value is returned.
+ *
+ * @param chr specified character
+ * @param defaultValue default index that is returned if the necessary font couldn't be found.
+ * @return index of the font from the array of physical fonts that will be used
+ * during processing of the specified character.
+ */
+ public int getCharFontIndex(char chr, int defaultValue){
+ for (int i = 0; i < numFonts; i++){
+ if (fontProperties[i].isCharExcluded(chr)){
+ continue;
+ }
+ if (fPhysicalFonts[i].canDisplay(chr)){
+ return i;
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * Returns true if one of the physical fonts composing this font CompositeFont
+ * can display specified character.
+ *
+ * @param chr specified character
+ */
+ @Override
+ public boolean canDisplay(char chr){
+ return (getCharFontIndex(chr) != -1);
+ }
+
+ /**
+ * Returns logical ascent (in pixels)
+ */
+ @Override
+ public int getAscent(){
+ return nlm.getLogicalAscent();
+ }
+
+ /**
+ * Returns LineMetrics instance scaled according to the specified transform.
+ *
+ * @param str specified String
+ * @param frc specified FontRenderContext
+ * @param at specified AffineTransform
+ */
+ @Override
+ public LineMetrics getLineMetrics(String str, FontRenderContext frc , AffineTransform at){
+ LineMetricsImpl lm = (LineMetricsImpl)(this.nlm.clone());
+ lm.setNumChars(str.length());
+
+ if ((at != null) && (!at.isIdentity())){
+ lm.scale((float)at.getScaleX(), (float)at.getScaleY());
+ }
+
+ return lm;
+ }
+
+ /**
+ * Returns cached LineMetrics instance for the null string or creates it if
+ * it wasn't cached yet.
+ */
+ @Override
+ public LineMetrics getLineMetrics(){
+ if (nlm == null){
+ setDefaultLineMetrics("", null); //$NON-NLS-1$
+ }
+
+ return this.nlm;
+ }
+
+ /**
+ * Creates LineMetrics instance and set cached LineMetrics field to it.
+ * Created LineMetrics has maximum values of the idividual metrics of all
+ * composing physical fonts. If there is only one physical font - it's
+ * LineMetrics object is returned.
+ *
+ * @param str specified String
+ * @param frc specified FontRenderContext
+ */
+ private void setDefaultLineMetrics(String str, FontRenderContext frc){
+ LineMetrics lm = fPhysicalFonts[0].getLineMetrics(str, frc, null);
+ float maxCharWidth = (float)fPhysicalFonts[0].getMaxCharBounds(frc).getWidth();
+
+ if (numFonts == 1) {
+ this.nlm = (LineMetricsImpl)lm;
+ return;
+ }
+
+ float[] baselineOffsets = lm.getBaselineOffsets();
+ int numChars = str.length();
+
+ // XXX: default value - common for all Fonts
+ int baseLineIndex = lm.getBaselineIndex();
+
+ float maxUnderlineThickness = lm.getUnderlineThickness();
+ float maxUnderlineOffset = lm.getUnderlineOffset();
+ float maxStrikethroughThickness = lm.getStrikethroughThickness();
+ float minStrikethroughOffset = lm.getStrikethroughOffset();
+ float maxLeading = lm.getLeading(); // External leading
+ float maxHeight = lm.getHeight(); // Height of the font ( == (ascent + descent + leading))
+ float maxAscent = lm.getAscent(); // Ascent of the font
+ float maxDescent = lm.getDescent(); // Descent of the font
+
+ for (int i = 1; i < numFonts; i++){
+ lm = fPhysicalFonts[i].getLineMetrics(str, frc, null);
+ if (maxUnderlineThickness < lm.getUnderlineThickness()){
+ maxUnderlineThickness = lm.getUnderlineThickness();
+ }
+
+ if (maxUnderlineOffset < lm.getUnderlineOffset()){
+ maxUnderlineOffset = lm.getUnderlineOffset();
+ }
+
+ if (maxStrikethroughThickness < lm.getStrikethroughThickness()){
+ maxStrikethroughThickness = lm.getStrikethroughThickness();
+ }
+
+ if (minStrikethroughOffset > lm.getStrikethroughOffset()){
+ minStrikethroughOffset = lm.getStrikethroughOffset();
+ }
+
+ if (maxLeading < lm.getLeading()){
+ maxLeading = lm.getLeading();
+ }
+
+ if (maxAscent < lm.getAscent()){
+ maxAscent = lm.getAscent();
+ }
+
+ if (maxDescent < lm.getDescent()){
+ maxDescent = lm.getDescent();
+ }
+
+ float width = (float)fPhysicalFonts[i].getMaxCharBounds(frc).getWidth();
+ if(maxCharWidth < width){
+ maxCharWidth = width;
+ }
+ for (int j =0; j < baselineOffsets.length; j++){
+ float[] offsets = lm.getBaselineOffsets();
+ if (baselineOffsets[j] > offsets[j]){
+ baselineOffsets[j] = offsets[j];
+ }
+ }
+
+ }
+ maxHeight = maxAscent + maxDescent + maxLeading;
+
+ this.nlm = new LineMetricsImpl(
+ numChars,
+ baseLineIndex,
+ baselineOffsets,
+ maxUnderlineThickness,
+ maxUnderlineOffset,
+ maxStrikethroughThickness,
+ minStrikethroughOffset,
+ maxLeading,
+ maxHeight,
+ maxAscent,
+ maxDescent,
+ maxCharWidth);
+
+ }
+
+ /**
+ * Returns the number of glyphs in this CompositeFont object.
+ */
+ @Override
+ public int getNumGlyphs(){
+ if (this.cachedNumGlyphs == -1){
+
+ this.cachedNumGlyphs = 0;
+
+ for (int i = 0; i < numFonts; i++){
+ this.cachedNumGlyphs += fPhysicalFonts[i].getNumGlyphs();
+ }
+ }
+
+ return this.cachedNumGlyphs;
+ }
+
+ /**
+ * Returns the italic angle of this object.
+ */
+ @Override
+ public float getItalicAngle(){
+ // !! only first physical font used to get this value
+ return fPhysicalFonts[0].getItalicAngle();
+ }
+
+ /**
+ * Returns rectangle that bounds the specified string in terms of composite line metrics.
+ *
+ * @param chars an array of chars
+ * @param start the initial offset in array of chars
+ * @param end the end offset in array of chars
+ * @param frc specified FontRenderContext
+ */
+ public Rectangle2D getStringBounds(char[] chars, int start, int end, FontRenderContext frc){
+
+ LineMetrics lm = getLineMetrics();
+ float minY = -lm.getAscent();
+ float minX = 0;
+ float height = lm.getHeight();
+ float width = 0;
+
+ for (int i = start; i < end; i++){
+ width += charWidth(chars[i]);
+ }
+
+ Rectangle2D rect2D = new Rectangle2D.Float(minX, minY, width, height);
+ return rect2D;
+
+ }
+
+ /**
+ * Returns maximum rectangle that encloses all maximum char bounds of
+ * physical fonts composing this CompositeFont.
+ *
+ * @param frc specified FontRenderContext
+ */
+ @Override
+ public Rectangle2D getMaxCharBounds(FontRenderContext frc){
+
+ Rectangle2D rect2D = fPhysicalFonts[0].getMaxCharBounds(frc);
+ float minY = (float)rect2D.getY();
+ float maxWidth = (float)rect2D.getWidth();
+ float maxHeight = (float)rect2D.getHeight();
+ if (numFonts == 1){
+ return rect2D;
+ }
+
+ for (int i = 1; i < numFonts; i++){
+ if (fPhysicalFonts[i] != null){
+ rect2D = fPhysicalFonts[i].getMaxCharBounds(frc);
+ float y = (float)rect2D.getY();
+ float mWidth = (float)rect2D.getWidth();
+ float mHeight = (float)rect2D.getHeight();
+ if (y < minY){
+ minY = y;
+ }
+ if (mWidth > maxWidth){
+ maxHeight = mWidth;
+ }
+
+ if (mHeight > maxHeight){
+ maxHeight = mHeight;
+ }
+ }
+ }
+
+ rect2D = new Rectangle2D.Float(0, minY, maxWidth, maxHeight);
+
+ return rect2D;
+ }
+
+ /**
+ * Returns font name.
+ */
+ @Override
+ public String getFontName(){
+ return face;
+ }
+
+ /**
+ * Returns font postscript name.
+ */
+ @Override
+ public String getPSName(){
+ return psName;
+ }
+
+ /**
+ * Returns font family name.
+ */
+ @Override
+ public String getFamily(){
+ return family;
+ }
+
+ /**
+ * Returns the code of the missing glyph.
+ */
+ @Override
+ public int getMissingGlyphCode(){
+ // !! only first physical font used to get this value
+ return fPhysicalFonts[0].getMissingGlyphCode();
+ }
+
+ /**
+ * Returns Glyph object corresponding to the specified character.
+ *
+ * @param ch specified char
+ */
+ @Override
+ public Glyph getGlyph(char ch){
+ for (int i = 0; i < numFonts; i++){
+ if (fontProperties[i].isCharExcluded(ch)){
+ continue;
+ }
+
+ /* Control symbols considered to be supported by the font peer */
+ if ((ch < 0x20) || fPhysicalFonts[i].canDisplay(ch)){
+ return fPhysicalFonts[i].getGlyph(ch);
+ }
+ }
+ return getDefaultGlyph();
+ }
+
+ /**
+ * Returns width of the char with specified index.
+ *
+ * @param ind specified index of the character
+ */
+ @Override
+ public int charWidth(int ind){
+ return charWidth((char)ind);
+ }
+
+ /**
+ * Returns width of the specified char.
+ *
+ * @param c specified character
+ */
+ @Override
+ public int charWidth(char c){
+ Glyph gl = this.getGlyph(c);
+ return (int)gl.getGlyphPointMetrics().getAdvanceX();
+ }
+
+ /**
+ * Returns debug information about this class.
+ */
+ @Override
+ public String toString(){
+ return new String(this.getClass().getName() +
+ "[name=" + this.name + //$NON-NLS-1$
+ ",style="+ this.style + //$NON-NLS-1$
+ ",fps=" + this.fontProperties + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Returns Glyph object corresponding to the default glyph.
+ */
+ @Override
+ public Glyph getDefaultGlyph(){
+ // !! only first physical font used to get this value
+ return fPhysicalFonts[0].getDefaultGlyph();
+ }
+
+ /**
+ * Returns FontExtraMetrics object with extra metrics
+ * related to this CompositeFont.
+ */
+ @Override
+ public FontExtraMetrics getExtraMetrics(){
+ // Returns FontExtraMetrics instanse of the first physical
+ // Font from the array of fonts.
+ return fPhysicalFonts[0].getExtraMetrics();
+ }
+
+ /**
+ * Disposes CompositeFont object's resources.
+ */
+ @Override
+ public void dispose() {
+ // Nothing to dispose
+ }
+}