/* 
______________________________________________________________________
*
* Copyright (c) 1996-2004 QUEST SOFTWARE INC.  All Rights Reserved.
* http://java.quest.com
*
* This software is the confidential and proprietary information of
* Quest Software Inc. ("Confidential Information").  You shall not disclose
* such Confidential Information and shall use it only in accordance with the
* terms of the license agreement you entered into with Quest Software.
*
* QUEST SOFTWARE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. QUEST SOFTWARE SHALL NOT BE LIABLE FOR ANY
* DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
* ______________________________________________________________________
*/

// RCSID -- $RCSfile: FontPCL.java,v $ $Revision: 1.2 $ $Date: 2006-03-17 21:13:25 $ $Locker:  $  Quest Software Inc.

package com.klg.jclass.page.pcl;

import java.awt.Font;
import java.awt.Rectangle;
import java.util.Enumeration;
import java.applet.Applet;
import java.io.InputStream;
import java.io.IOException;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.io.BufferedInputStream;
import com.klg.jclass.page.FontBase;
import com.klg.jclass.page.FontParser;
import com.klg.jclass.page.pcl.JCPCLFontMap;
import com.klg.jclass.page.JCUnit;
import java.util.MissingResourceException;
import java.util.ResourceBundle;




import java.awt.font.GlyphVector;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.util.Vector;
import java.util.Hashtable;


/**
 * Extends Font to provide PCL/TFM specific information.
 */
public class FontPCL extends FontBase implements Cloneable {

protected TypeFacePCL typeface;
protected static Hashtable fonts		= new Hashtable();
protected static String defaultFontMap 	= "com.klg.jclass.page.pcl.JCPCLFontMap";
protected static String defaultJarLocation =
					"/com/klg/jclass/page/pcl/fonts.jar";
protected static String defaultFileExtension = ".tfm";
protected static boolean loaded			= false;
public String version;
public char processor;
	
protected static ResourceBundle userFontBundle;
protected static ResourceBundle defaultFontBundle;

//characters per inch -- only set if using fixed width fonts
//if using proportional fonts, this should stay negative
protected int cpi = -1;

/**
 * Constructor
 */
public FontPCL(String name, int style, int size, TypeFacePCL typeface) {
    super(name, style, size);
	this.typeface = typeface;
}

/**
 *
 * Make a copy of this font including its properties.
 *
 */
protected Object clone() {
	try {
		return (FontPCL)super.clone();
	} catch (CloneNotSupportedException e) {
		// can't happen
		throw new InternalError(e.toString());
	}
}

/**
 * Overrides Font method.
 * Gets the specified font using the name passed in.
 *
 * @param font string of the form
 * <pre>
 *		font name-style-size
 *		font name-style
 *		font name-size
 *		font name
 * </pre>
 * @return the Font or null if not found
 */
public static Font decode(String str) {

	// PENDING the only reason I create an awt font is so it will parse
	// the string for size and style. Should write a decode method.
	Font f = Font.decode(str);

	// get the key name in this format name-style, for example, Times-Bold
	
	String key = f.getName() + getStyleString(f.getStyle());
	
	


	// replace spaces with underscores
	key = key.replace(' ', REPLACEMENT_CHARACTER);

	// actual font to use
	String alias = null;
		
	// try user fontmap if not null; if null or mapping not found, try default
	try {
		if (userFontBundle != null) {
			alias = userFontBundle.getString(key);
		}
		else {
			throw new MissingResourceException("lets","try","default, then");
		}
	} catch (MissingResourceException e) {
		// otherwise use the default bundle
		try {
			alias = defaultFontBundle.getString(key);
		} catch (MissingResourceException e2) {
			// Substitute a default font for any missing fonts
			alias = new String("M Times New");
		}
	}

	// now retrieve the font
	FontPCL font = (FontPCL) fonts.get(alias);

	// and make it into the correct style
	return (Font) font.deriveFont(f.getStyle(), f.getSize());
}
	
/**
 * Overrid Font method.
 */
public Font deriveFont(int style, float size) {
	FontPCL fpcl	= (FontPCL) clone();
	fpcl.style		= style;
	fpcl.size		= (int) size;
	return fpcl;
}

/**
 * Overrides Font method.
 */
public String getFamily() {
	return typeface.getFamily();
}

/**
 * Overrides Font method
 * 
 */
public GlyphVector createGlyphVector(FontRenderContext frc, String string) {
	FontMetricsPCL metrics = new FontMetricsPCL(this);	
	return new GlyphVectorPCL(metrics, frc, string);
}

/**
 * Overrides Font method
 * 
 */
public Rectangle2D getStringBounds(String string, FontRenderContext frc) {

	

	
	Rectangle r     = new Rectangle(0, 0, 0, 0);
	

	if (string != null && string.length() > 0) {
		FontMetricsPCL m = new FontMetricsPCL(this);
	    int size        = m.getFont().getSize();
	    double width    = m.stringWidth(JCUnit.POINTS, size, string);
	    double x        = m.getLeadingSpace(JCUnit.POINTS, size, string) +
	                      m.getTrailingSpace(JCUnit.POINTS, size,string);
	    double y        =-m.getAscender(JCUnit.POINTS, size);
	    double height   = m.getHeight(JCUnit.POINTS, size);	    
	    r.setRect(x, y, width, height);
	}
    return r;
}	

	
/**
 * Return the typeface information.
 */
public TypeFacePCL getTypeface() {
	return typeface;
}

/**
 * Return the char metrics for this font.
 */
public CharSetEntryPCL getCharMetric(char c) {
    // return typeface.charMetrics.chars;
	return typeface.charMetrics.findEntryByCode((short) c);
}

/**
 * Get the x height.
 * @return xHeight an int
 */
public int getXHeight() {
	return typeface.getTypefaceMetrics().getXHeight();
}

/** 
 * Get the number of characters per inch for fixed width fonts.  If a 
 * negative value is returned, the font is proportional.
 */
public int getCharsPerInch() {
	int cpi = -1;
    if (!((typeface.getStyle()&
            TypeFacePCL.PCL_TYPEFACE_FLAGS_FIXEDWIDTH) == 0)) {

        /*
         * Compute the number of characters per inch at this point size,
         * based on the defined character spacing of the font
         */

        // This is a slightly optimised version of:
        //                       720 (decipoints/inch)
        //         -------------------------------------------------
        //             (typefaceMetrics.spacing * fontSize * 10)
        //             -----------------------------------------
        //                    typefaceMetrics.designUnits

        cpi = (int) (((72.0 * (double) typeface.typefaceMetrics.designUnits)
                 / (typeface.typefaceMetrics.spacing * getSize())) + 0.5);
    }
	return cpi;
}

/**
 *
 * Default font loading. Read fonts from the "fonts.jar" file
 *		"/com/klg/jclass/page/pcl/fonts.jar"
 * which is relative to this class.
 * File which end with the extension ".tfm" are parsed. 
 * A "fontmap" file is expected to be found in this jar as well.
 * This maps between fonts and their aliases (the real font to 
 * use).
 *
 */
public static Font[] getAllFonts() {
	TFMParser parser = new TFMParser();
	
	// user did not supply a font map so use default for both
	getFontBundles(defaultFontMap, defaultFontMap);

	// user didn't specify a font map so use default for both
	Font f[] = getFonts(parser, 
					defaultJarLocation, 
					defaultFileExtension,
					fonts,
					loaded);
	loaded = true;
	return f;
}

/**
 *
 * Load fonts from the specified jar file.
 * @param the FontParser to use to parse the afm files
 * @param the location of the jar file relative to this class
 * @param the the file extension of the afm files (normally .afm)
 *
 */
public static Font[] getAllFonts(FontParser parser, String jarLocation,
		String fileExtension, String userFontMap) {
			
	// 
	getFontBundles(defaultFontMap, userFontMap);

	// load the user-supplied fonts
	Font f[] =  getFonts(parser, 	
					jarLocation, 
					fileExtension,
					fonts,
					loaded);

	// load the default mappings, too
	getFonts(		parser,
					defaultJarLocation,
					defaultFileExtension,
					fonts,
					loaded);

	loaded = true;
	return f;
}

/**
 * PageLayout passes in awt Fonts, so we need to
 * get the equivalent native (ps or pcl) font.
 */
public static Font getNativeFont(Font font) {

	// Decode the font to get an equivalent FontPCL instance
    String nm   = font.getName();
    int st      = font.getStyle();
    int sz      = font.getSize();
    Font f		= decode(getDecodeString(nm, st, sz));

	
	return(f);
	
	

}

/**
 * Load both the default font map resoruce bundle and the
 * user assigned font map resource bundle.
 *
 * @param defaultBundleName the fully qualified default fontmap bundle
 *			name.
 * @param userBundleName the fully qualified default fontmap bundle name,
 * can be a class or a text file -- for example, specifying 
 * "com.klg.jclass.page.UserBundle" will cause the loading mechanism
 * to look first for the class "com.klg.jclass.page.UserBundle.class"
 * and if that's not found then the file "UserBundle.properties" in the
 * com/klg/jclass/page directory.
 */
 protected static void getFontBundles(String defaultBundleName, String userBundleName) {
	try {
		userFontBundle 		= ResourceBundle.getBundle(userBundleName);
	} catch (MissingResourceException e) { 
		// okay, we'll only use the default	
	}
	try {		
		defaultFontBundle 	= ResourceBundle.getBundle(defaultBundleName);
	} catch (MissingResourceException e2) { 
		System.out.println(e2.toString());
	}
}
	
}
