/* * Copyright 2006-2012 ICEsoft Technologies Inc. * * Licensed 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 org.icepdf.core.pobjects.fonts; import org.icepdf.core.pobjects.*; import org.icepdf.core.util.Library; import java.util.Hashtable; import java.util.Vector; import java.util.logging.Logger; import java.util.logging.Level; /** * This class represents a PDF <code>FontDescriptor</code>. A FontDescriptor object * holds extra information about a particular parent Font object. In particular * information on font widths, flags, to unicode and embedded font program streams. * * @see org.icepdf.core.pobjects.fonts.Font */ public class FontDescriptor extends Dictionary { private static final Logger logger = Logger.getLogger(FontDescriptor.class.toString()); private FontFile font; public static final String FONT_NAME = "FontName"; public static final String FONT_FAMILY = "FontFamily"; public static final String MISSING_Stretch = "FontStretch"; public static final String FONT_WEIGHT = "FontWeight"; public static final String FLAGS = "Flags"; public static final String FONT_BBOX = "FontBBox"; public static final String ITALIC_ANGLE = "ItalicAngle"; public static final String ASCENT = "Ascent"; public static final String DESCENT = "Descent"; public static final String LEADING = "Leading"; public static final String CAP_HEIGHT = "CapHeight"; public static final String X_HEIGHT = "XHeight"; public static final String STEM_V = "StemV"; public static final String STEM_H = "StemH"; public static final String AVG_WIDTH = "AvgWidth"; public static final String MAX_WIDTH = "MaxWidth"; public static final String MISSING_WIDTH = "MissingWidth"; private static final String FONT_FILE = "FontFile"; private static final String FONT_FILE_2 = "FontFile2"; private static final String FONT_FILE_3 = "FontFile3"; private static final String FONT_FILE_3_TYPE_1C = "Type1C"; private static final String FONT_FILE_3_CID_FONT_TYPE_0 = "CIDFontType0"; private static final String FONT_FILE_3_CID_FONT_TYPE_2 = "CIDFontType2"; private static final String FONT_FILE_3_CID_FONT_TYPE_0C = "CIDFontType0C"; private static final String FONT_FILE_3_OPEN_TYPE = "OpenType"; /** * Creates a new instance of a FontDescriptor. * * @param l Libaray of all objects in PDF * @param h hash of parsed FontDescriptor attributes */ public FontDescriptor(Library l, Hashtable h) { super(l, h); } /** * Utility method for creating a FontDescriptor based on the font metrics * of the <code>AFM</code> * * @param library document library * @param afm adobe font metrics data * @return new instance of a <code>FontDescriptor</code> */ public static FontDescriptor createDescriptor(Library library, AFM afm) { Hashtable<String, Object> properties = new Hashtable<String, Object>(5); properties.put(FONT_NAME, afm.getFontName()); properties.put(FONT_FAMILY, afm.getFamilyName()); properties.put(FONT_BBOX, afm.getFontBBox()); properties.put(ITALIC_ANGLE, afm.getItalicAngle()); properties.put(MAX_WIDTH, afm.getMaxWidth()); properties.put(AVG_WIDTH, afm.getAvgWidth()); properties.put(FLAGS, afm.getFlags()); return new FontDescriptor(library, properties); } /** * Returns the PostScript name of the font. * * @return PostScript name of font. */ public String getFontName() { Object value = library.getObject(entries, FONT_NAME); if (value instanceof Name) { return ((Name) value).getName(); } else if (value instanceof String) { return (String) value; } return null; } /** * Gets a string specifying the preferred font family name. For example, the font * "Time Bold Italic" would have a font family of Times. * * @return preferred font family name. */ public String getFontFamily() { Object value = library.getObject(entries, FONT_FAMILY); if (value instanceof StringObject) { StringObject familyName = (StringObject) value; return familyName.getDecryptedLiteralString(library.getSecurityManager()); } return FONT_NAME; } /** * Gets the weight (thickness) component of the fully-qualified font name or * font specifier. The default value is zero. * * @return the weight of the font name. */ public float getFontWeight() { Object value = library.getObject(entries, FONT_WEIGHT); if (value instanceof Number) { return ((Number) value).floatValue(); } return 0.0f; } /** * Gets the width to use for character codes whose widths are not specifed in * the font's dictionary. The default value is zero. * * @return width of non-specified characters. */ public float getMissingWidth() { Object value = library.getObject(entries, MISSING_WIDTH); if (value instanceof Number) { return ((Number) value).floatValue(); } return 0.0f; } /** * Gets the average width of glyphs in the font. The default value is zero. * * @return average width of glyphs. */ public float getAverageWidth() { Object value = library.getObject(entries, AVG_WIDTH); if (value instanceof Number) { return ((Number) value).floatValue(); } return 0.0f; } /** * Gets the maximum width of glyphs in the font. The default value is zero. * * @return maximum width of glyphs. */ public float getMaxWidth() { Object value = library.getObject(entries, MAX_WIDTH); if (value instanceof Number) { return ((Number) value).floatValue(); } return 0.0f; } /** * Gets the ascent of glyphs in the font. The default value is zero. * * @return ascent of glyphs. */ public float getAscent() { Object value = library.getObject(entries, ASCENT); if (value instanceof Number) { return ((Number) value).floatValue(); } return 0.0f; } /** * Gets the descent of glyphs in the font. The default value is zero. * * @return descent of glyphs. */ public float getDescent() { Object value = library.getObject(entries, DESCENT); if (value instanceof Number) { return ((Number) value).floatValue(); } return 0.0f; } /** * Gets the embeddedFont if any. * * @return embedded font; null, if there is no valid embedded font. */ public FontFile getEmbeddedFont() { return font; } /** * Gets the fonts bounding box. * * @return bounding box in PDF coordinate space. */ public PRectangle getFontBBox() { Object value = library.getObject(entries, FONT_BBOX); if (value instanceof Vector) { Vector rectangle = (Vector) value; return new PRectangle(rectangle); } return null; } /** * Gets the font flag value, which is a collection of various characteristics * that describe the font. * * @return int value representing the flags; bits must be looked at to get * attribute values. */ public int getFlags() { Object value = library.getObject(entries, FLAGS); if (value instanceof Number) { return ((Number) value).intValue(); } return 0; } /** * Initiate the Font Descriptor object. Reads embedded font programs * or CMap streams. */ public void init() { /** * FontFile1 = A stream containing a Type 1 font program * FontFile2 = A stream containing a TrueType font program * FontFile3 = A stream containing a font program other than Type 1 or * TrueType. The format of the font program is specified by the Subtype entry * in the stream dictionary */ try { // get an instance of our font factory FontFactory fontFactory = FontFactory.getInstance(); if (entries.containsKey(FONT_FILE)) { Stream fontStream = (Stream) library.getObject(entries, FONT_FILE); if (fontStream != null) { font = fontFactory.createFontFile( fontStream, FontFactory.FONT_TYPE_1); } } if (entries.containsKey(FONT_FILE_2)) { Stream fontStream = (Stream) library.getObject(entries, FONT_FILE_2); if (fontStream != null) { font = fontFactory.createFontFile( fontStream, FontFactory.FONT_TRUE_TYPE); } } if (entries.containsKey(FONT_FILE_3)) { Stream fontStream = (Stream) library.getObject(entries, FONT_FILE_3); String subType = fontStream.getObject("Subtype").toString(); if (subType != null && (subType.equals(FONT_FILE_3_TYPE_1C) || subType.equals(FONT_FILE_3_CID_FONT_TYPE_0) || subType.equals(FONT_FILE_3_CID_FONT_TYPE_0C)) ) { font = fontFactory.createFontFile( fontStream, FontFactory.FONT_TYPE_1); } if (subType != null && subType.equals(FONT_FILE_3_OPEN_TYPE)) { // font = new NFontOpenType(fontStreamBytes); font = fontFactory.createFontFile( fontStream, FontFactory.FONT_OPEN_TYPE); } } } // catch everything, we can fall back to font substitution if a failure // occurs. catch (Throwable e) { logger.log(Level.FINE, "Error Reading Embedded Font ", e); } } /** * Return a string representation of the all the FontDescriptor object's * parsed attributes. * * @return all of FontDescriptors parsed attributes. */ public String toString() { String name = null; if (font != null) name = font.getName(); return super.getPObjectReference() + " FONTDESCRIPTOR= " + entries.toString() + " - " + name; } }