Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* NOTICE: This file has been changed by Plutext Pty Ltd for use in docx4j.
   * The package name has been changed; there may also be other changes.
   * 
   * This notice is included to meet the condition in clause 4(b) of the License. 
   */
  
   /*
   * 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.
  */
 
 /* $Id: PFMFile.java 679326 2008-07-24 09:35:34Z vhennebert $ */
 
 package org.docx4j.fonts.fop.fonts.type1;
 
 // Java
 import java.util.Map;
 
 
This class represents a PFM file (or parts of it) as a Java object.
 
 public class PFMFile {
 
     // Header stuff
     private String windowsName;
     private String postscriptName;
     private short dfItalic;
     private int dfWeight;
     private short dfCharSet;
     private short dfPitchAndFamily;
     private int dfAvgWidth;
     private int dfMaxWidth;
     private int dfMinWidth;
     private short dfFirstChar;
     private short dfLastChar;
 
     // Extension stuff
     // ---
 
     // Extend Text Metrics
     private int etmCapHeight;
     private int etmXHeight;
     private int etmLowerCaseAscent;
     private int etmLowerCaseDescent;
 
     // Extent table
     private int[] extentTable;
 
     private Map kerningTab = new java.util.HashMap();

    
logging instance
 
     protected Logger log = LoggerFactory.getLogger(PFMFile.class);

    
Parses a PFM file

Parameters:
inStream The stream from which to read the PFM file.
Throws:
java.io.IOException In case of an I/O problem
 
     public void load(InputStream inStreamthrows IOException {
         byte[] pfmBytes = IOUtils.toByteArray(inStream);
         InputStream bufin = inStream;
         bufin = new ByteArrayInputStream(pfmBytes);
         PFMInputStream in = new PFMInputStream(bufin);
         bufin.mark(512);
         short sh1 = in.readByte();
         short sh2 = in.readByte();
         if (sh1 == 128 && sh2 == 1) {
             //Found the first section header of a PFB file!
             throw new IOException("Cannot parse PFM file. You probably specified the PFB file"
                     + " of a Type 1 font as parameter instead of the PFM.");
         }
         bufin.reset();
         byte[] b = new byte[16];
         bufin.read(b);
         if (new String(b"US-ASCII").equalsIgnoreCase("StartFontMetrics")) {
            //Found the header of a AFM file!
            throw new IOException("Cannot parse PFM file. You probably specified the AFM file"
                    + " of a Type 1 font as parameter instead of the PFM.");
        }
        bufin.reset();
        final int version = in.readShort();
        if (version != 256) {
            .warn("PFM version expected to be '256' but got '" + version + "'."
                    + " Please make sure you specify the PFM as parameter"
                    + " and not the PFB or the AFM.");
        }
        //final long filesize = in.readInt();
        bufin.reset();
        loadHeader(in);
        loadExtension(in);
    }

    
Parses the header of the PFM file.

Parameters:
inStream The stream from which to read the PFM file.
Throws:
java.io.IOException In case of an I/O problem
    private void loadHeader(PFMInputStream inStreamthrows IOException {
        inStream.skip(80);
         = inStream.readByte();
        inStream.skip(2);
         = inStream.readShort();
         = inStream.readByte();
        inStream.skip(4);
         = inStream.readByte();
         = inStream.readShort();
         = inStream.readShort();
         = inStream.readByte();
         = inStream.readByte();
        inStream.skip(8);
        long faceOffset = inStream.readInt();
        inStream.reset();
        inStream.skip(faceOffset);
         = inStream.readString();
        inStream.reset();
        inStream.skip(117);
    }

    
Parses the extension part of the PFM file.

Parameters:
inStream The stream from which to read the PFM file.
    private void loadExtension(PFMInputStream inStreamthrows IOException {
        final int size = inStream.readShort();
        if (size != 30) {
            .warn("Size of extension block was expected to be "
                + "30 bytes, but was " + size + " bytes.");
        }
        final long extMetricsOffset = inStream.readInt();
        final long extentTableOffset = inStream.readInt();
        inStream.skip(4); //Skip dfOriginTable
        final long kernPairOffset = inStream.readInt();
        inStream.skip(4); //Skip dfTrackKernTable
        long driverInfoOffset = inStream.readInt();
        if (kernPairOffset > 0) {
            inStream.reset();
            inStream.skip(kernPairOffset);
            loadKernPairs(inStream);
        }
        inStream.reset();
        inStream.skip(driverInfoOffset);
         = inStream.readString();
        if (extMetricsOffset != 0) {
            inStream.reset();
            inStream.skip(extMetricsOffset);
            loadExtMetrics(inStream);
        }
        if (extentTableOffset != 0) {
            inStream.reset();
            inStream.skip(extentTableOffset);
            loadExtentTable(inStream);
        }
    }

    
Parses the kernPairs part of the pfm file

Parameters:
inStream The stream from which to read the PFM file.
    private void loadKernPairs(PFMInputStream inStreamthrows IOException {
        int i = inStream.readShort();
        if (.isTraceEnabled()) {
            .trace(i + " kerning pairs");
        }
        while (i > 0) {
            int g1 = (int)inStream.readByte();
            i--;
            int g2 = (int)inStream.readByte();
            int adj = inStream.readShort();
            if (adj > 0x8000) {
                adj = -(0x10000 - adj);
            }
            if (.isTraceEnabled()) {
                .trace("Char no: (" + g1 + ", " + g2 + ") kern: " + adj);
                final String glyph1 = .[g1];
                final String glyph2 = .[g2];
                .trace("glyphs: " + glyph1 + ", " + glyph2);
            }
            Map adjTab = (Map).get(new Integer(g1));
            if (adjTab == null) {
                adjTab = new java.util.HashMap();
            }
            adjTab.put(new Integer(g2), new Integer(adj));
            .put(new Integer(g1), adjTab);
        }
    }

    
Parses the extended metrics part of the PFM file.

Parameters:
inStream The stream from which to read the PFM file.
    private void loadExtMetrics(PFMInputStream inStreamthrows IOException {
        final int size = inStream.readShort();
        if (size != 52) {
            .warn("Size of extension block was expected to be "
                + "52 bytes, but was " + size + " bytes.");
        }
        inStream.skip(12); //Skip etmPointSize, etmOrientation, etmMasterHeight,
                           //etmMinScale, etmMaxScale, emtMasterUnits
         = inStream.readShort();
         = inStream.readShort();
         = inStream.readShort();
         = -(inStream.readShort());
        //Ignore the rest of the values
    }

    
Parses the extent table of the PFM file.

Parameters:
inStream The stream from which to read the PFM file.
    private void loadExtentTable(PFMInputStream inStreamthrows IOException {
         = new int[ -  + 1];
         = ;
        for (short i = i <= i++) {
            [i - ] = inStream.readShort();
            if ([i - ] < ) {
                 = [i - ];
            }
        }
    }

    
Returns the Windows name of the font.

Returns:
The Windows name.
    public String getWindowsName() {
        return ;
    }

    
Return the kerning table. The kerning table is a Map with strings with glyphnames as keys, containing Maps as value. The value map contains a glyph name string key and an Integer value

Returns:
A Map containing the kerning table
    public Map getKerning() {
        return ;
    }

    
Returns the Postscript name of the font.

Returns:
The Postscript name.
    public String getPostscriptName() {
        return ;
    }

    
Returns the charset used for the font.

Returns:
The charset (0=WinAnsi).
    public short getCharSet() {
        return ;
    }

    
Returns the charset of the font as a string.

Returns:
The name of the charset.
    public String getCharSetName() {
        //TODO Had to remove the detection for Expert(Subset) encoding. The PFM is not suitable
        //for detecting these character sets. We have to parse the AFM for that.
        switch () {
        case 0:
            return "WinAnsi"// AKA ISOAdobe
        case 2:
            if ("Symbol".equals(getPostscriptName())) {
                return "Symbol";
            }
            break;
        case 128:
            return "Shift-JIS (Japanese)";
        default:
            .warn("Unknown charset detected (" + 
                    + ", 0x" + Integer.toHexString()
                    + "). Trying fallback to WinAnsi.");
        }
        return "WinAnsi";
    }

    
Returns the number of the character that defines the first entry in the widths list.

Returns:
The number of the first character.
    public short getFirstChar() {
        return ;
    }

    
Returns the number of the character that defines the last entry in the widths list.

Returns:
The number of the last character.
    public short getLastChar() {
        return ;
    }

    
Returns the CapHeight parameter for the font (height of uppercase H).

Returns:
The CapHeight parameter.
    public int getCapHeight() {
        return ;
    }

    
Returns the XHeight parameter for the font (height of lowercase x).

Returns:
The CapHeight parameter.
    public int getXHeight() {
        return ;
    }

    
Returns the LowerCaseAscent parameter for the font (height of lowercase d).

Returns:
The LowerCaseAscent parameter.
    public int getLowerCaseAscent() {
        return ;
    }

    
Returns the LowerCaseDescent parameter for the font (height of lowercase p).

Returns:
The LowerCaseDescent parameter.
    public int getLowerCaseDescent() {
        return ;
    }

    
Tells whether the font has proportional character spacing.

Returns:
ex. true for Times, false for Courier.
    public boolean getIsProportional() {
        return (( & 1) == 1);
    }

    
Returns the bounding box for the font. Note: this value is just an approximation, it does not really exist in the PFM file.

Returns:
The calculated Font BBox.
    public int[] getFontBBox() {
        int[] bbox = new int[4];
        // Just guessing....
        if (!getIsProportional() && ( == )) {
            bbox[0] = -20;
        } else {
            bbox[0] = -100;
        }
        bbox[1] = getLowerCaseDescent() - 5;
        bbox[2] =  + 10;
        bbox[3] = getLowerCaseAscent() + 5;
        return bbox;
    }

    
Indicates whether the font is non-symbolic (Font uses the Adobe standard Latin character set or a subset of it).

Returns:
true if the font is non-symbolic
    public boolean isNonSymbolic() {
        return ( != 2); //!= Symbol fonts
    }

    
Returns the characteristics flags for the font as needed for a PDF font descriptor (See PDF specs).

Returns:
The characteristics flags.
    public int getFlags() {
        int flags = 0;
        if (!getIsProportional()) {
            flags |= 1; //bit 1: FixedPitch
        }
        if (isNonSymbolic()) {
            flags |= 32; //bit 6: Nonsymbolic
        } else {
            flags |= 4; //bit 3: Symbolic
        }
        //int serif = dfPitchAndFamily & 0xFFFE;
        if (( & 16) != 0) {
            flags |= 2; //bit 2: Serif
        }
        if (( & 64) != 0) {
            flags |= 8; //bit 4: Script
        }
        if ( != 0) {
            flags |= 64; //bit 7: Italic
        }
        return flags;
    }

    
Returns the width of the dominant vertical stems of the font. Note: this value is just an approximation, it does not really exist in the PFM file.

Returns:
The vertical stem width.
    public int getStemV() {
        // Just guessing....
        if ( != 0) {
            return (int)Math.round( * 0.25);
        } else {
            return (int)Math.round( * 0.6);
        }
    }

    
Returns the italic angle of the font. Note: this value is just an approximation, it does not really exist in the PFM file.

Returns:
The italic angle.
    public int getItalicAngle() {
        if ( != 0) {
            return -16;    // Just guessing....
        } else {
            return 0;
        }
    }

    
Returns the width of a character

Parameters:
which The number of the character for which the width is requested.
Returns:
The width of a character.
    public int getCharWidth(short which) {
        return [which - ];
    }
New to GrepCode? Check out our FAQ X