Author: lehmi
Date: Mon Apr  9 16:05:55 2012
New Revision: 1311300

URL: http://svn.apache.org/viewvc?rev=1311300&view=rev
Log:
PDFBOX-490: improved TTFParser to read glyph information based on Apache Batik 
code

Added:
    
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeComp.java
    
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfDescript.java
    
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfSimpleDescript.java
    
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphDescription.java
Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java

Added: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeComp.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeComp.java?rev=1311300&view=auto
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeComp.java
 (added)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeComp.java
 Mon Apr  9 16:05:55 2012
@@ -0,0 +1,293 @@
+/*
+
+   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 org.apache.fontbox.ttf;
+
+import java.io.IOException;
+
+/**
+ * This class is based on code from Apache Batik a subproject of Apache 
XMLGraphics.
+ * see http://xmlgraphics.apache.org/batik/ for further details.
+ */
+public class GlyfCompositeComp 
+{
+
+    // Flags for composite glyphs.
+    
+    /**
+     * If set, the arguments are words; otherwise, they are bytes.
+     */
+    protected static final short ARG_1_AND_2_ARE_WORDS = 0x0001;
+    /**
+     * If set, the arguments are xy values; otherwise they are points.
+     */
+    protected static final short ARGS_ARE_XY_VALUES = 0x0002;
+    /**
+     * If set, xy values are rounded to those of the closest grid lines.
+     */
+    protected static final short ROUND_XY_TO_GRID = 0x0004;
+    /**
+     * If set, there is a simple scale; otherwise, scale = 1.0.
+     */
+    protected static final short WE_HAVE_A_SCALE = 0x0008;
+    /**
+     * Indicates at least one more glyph after this one.
+     */
+    protected static final short MORE_COMPONENTS = 0x0020;
+    /**
+     * The x direction will use a different scale from the y direction.
+     */
+    protected static final short WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
+    /**
+     * There is a 2 by2 transformation that will be used to scale the 
component.
+     */
+    protected static final short WE_HAVE_A_TWO_BY_TWO = 0x0080;
+    /**
+     * Following the last component are instructions for the composite 
character.
+     */
+    protected static final short WE_HAVE_INSTRUCTIONS = 0x0100;
+    /**
+     * If set, this forces the aw and lsb (and rsb) for the composite to be 
equal to
+     * those from this original glyph.
+     */
+    protected static final short USE_MY_METRICS = 0x0200;
+
+    private int firstIndex;
+    private int firstContour;
+    private short argument1;
+    private short argument2;
+    private short flags;
+    private int    glyphIndex;
+    private double xscale = 1.0;
+    private double yscale = 1.0;
+    private double scale01 = 0.0;
+    private double scale10 = 0.0;
+    private int xtranslate = 0;
+    private int ytranslate = 0;
+    private int point1 = 0;
+    private int point2 = 0;
+
+    /**
+     * Constructor.
+     * 
+     * @param bais the stream to be read
+     * @throws IOException is thrown if something went wrong
+     */
+    protected GlyfCompositeComp(TTFDataStream bais) throws IOException 
+    {
+        flags = bais.readSignedShort();
+        glyphIndex = bais.readSignedShort();
+
+        // Get the arguments as just their raw values
+        if ((flags & ARG_1_AND_2_ARE_WORDS) != 0) 
+        {
+            argument1 = bais.readSignedShort();
+            argument2 = bais.readSignedShort();
+        } 
+        else 
+        {
+            argument1 = (short) bais.read();
+            argument2 = (short) bais.read();
+        }
+
+        // Assign the arguments according to the flags
+        if ((flags & ARGS_ARE_XY_VALUES) != 0) 
+        {
+            xtranslate = argument1;
+            ytranslate = argument2;
+        } 
+        else 
+        {
+            point1 = argument1;
+            point2 = argument2;
+        }
+
+        // Get the scale values (if any)
+        if ((flags & WE_HAVE_A_SCALE) != 0) 
+        {
+            int i = bais.readSignedShort();
+            xscale = yscale = (double) i / (double) 0x4000;
+        } 
+        else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0) 
+        {
+            short i = bais.readSignedShort();
+            xscale = (double) i / (double) 0x4000;
+            i = bais.readSignedShort();
+            yscale = (double) i / (double) 0x4000;
+        } 
+        else if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0) 
+        {
+            int i = bais.readSignedShort();
+            xscale = (double) i / (double) 0x4000;
+            i = bais.readSignedShort();
+            scale01 = (double) i / (double) 0x4000;
+            i = bais.readSignedShort();
+            scale10 = (double) i / (double) 0x4000;
+            i = bais.readSignedShort();
+            yscale = (double) i / (double) 0x4000;
+        }
+    }
+
+    /**
+     * Sets the first index.
+     * @param idx the first index
+     */
+    public void setFirstIndex(int idx) 
+    {
+        firstIndex = idx;
+    }
+
+    /**
+     * Returns the first index.
+     * @return the first index.
+     */
+    public int getFirstIndex() 
+    {
+        return firstIndex;
+    }
+
+    /**
+     * Sets the index for the first contour.
+     * @param idx the index of the first contour
+     */
+    public void setFirstContour(int idx) 
+    {
+        firstContour = idx;
+    }
+
+    /**
+     * Returns the index of the first contour.
+     * @return the index of the first contour.
+     */
+    public int getFirstContour() 
+    {
+        return firstContour;
+    }
+
+    /**
+     * Returns argument 1.
+     * @return argument 1.
+     */
+    public short getArgument1() 
+    {
+        return argument1;
+    }
+
+    /**
+     * Returns argument 2.
+     * @return argument 2.
+     */
+    public short getArgument2() 
+    {
+        return argument2;
+    }
+
+    /**
+     * Returns the flags of the glyph.
+     * @return the flags.
+     */
+    public short getFlags() 
+    {
+        return flags;
+    }
+
+    /**
+     * Returns the index of the first contour.
+     * @return index of the first contour.
+     */
+    public int getGlyphIndex() 
+    {
+        return glyphIndex;
+    }
+
+    /**
+     * Returns the scale-01 value.
+     * @return the scale-01 value.
+     */
+    public double getScale01() 
+    {
+        return scale01;
+    }
+
+    /**
+     * Returns the scale-10 value.
+     * @return the scale-10 value.
+     */
+    public double getScale10() 
+    {
+        return scale10;
+    }
+
+    /**
+     * Returns the x-scaling value.
+     * @return the x-scaling value.
+     */
+    public double getXScale() 
+    {
+        return xscale;
+    }
+
+    /**
+     * Returns the y-scaling value.
+     * @return the y-scaling value.
+     */
+    public double getYScale() 
+    {
+        return yscale;
+    }
+
+    /**
+     * Returns the x-translation value.
+     * @return the x-translation value.
+     */
+    public int getXTranslate() 
+    {
+        return xtranslate;
+    }
+
+    /**
+     * Returns the y-translation value.
+     * @return the y-translation value.
+     */
+    public int getYTranslate() 
+    {
+        return ytranslate;
+    }
+
+    /**
+     * Transforms an x-coordinate of a point for this component.
+     * @param x The x-coordinate of the point to transform
+     * @param y The y-coordinate of the point to transform
+     * @return The transformed x-coordinate
+     */
+    public int scaleX(int x, int y) 
+    {
+        return Math.round((float)(x * xscale + y * scale10));
+    }
+
+    /**
+     * Transforms a y-coordinate of a point for this component.
+     * @param x The x-coordinate of the point to transform
+     * @param y The y-coordinate of the point to transform
+     * @return The transformed y-coordinate
+     */
+    public int scaleY(int x, int y) 
+    {
+        return Math.round((float)(x * scale01 + y * yscale));
+    }
+}

Added: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java?rev=1311300&view=auto
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java
 (added)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java
 Mon Apr  9 16:05:55 2012
@@ -0,0 +1,252 @@
+/*
+
+   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 org.apache.fontbox.ttf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * Glyph description for composite glyphs.  Composite glyphs are made up of one
+ * or more simple glyphs, usually with some sort of transformation applied to 
each.
+ *
+ * This class is based on code from Apache Batik a subproject of Apache 
XMLGraphics.
+ * see http://xmlgraphics.apache.org/batik/ for further details.
+ */
+public class GlyfCompositeDescript extends GlyfDescript 
+{
+
+    private List<GlyfCompositeComp> components = new 
ArrayList<GlyfCompositeComp>();
+    private GlyphData[] glyphs = null;
+    private boolean beingResolved = false;
+    private boolean resolved = false;
+
+    /**
+     * Constructor.
+     * 
+     * @param bais the stream to be read
+     * @param glyphTable the Glyphtable containing all glyphs
+     * @throws IOException is thrown if something went wrong
+     */
+    public GlyfCompositeDescript(TTFDataStream bais, GlyphTable glyphTable) 
throws IOException 
+    {
+        super((short) -1, bais);
+        
+        glyphs = glyphTable.getGlyphs();
+        
+        // Get all of the composite components
+        GlyfCompositeComp comp;
+        do 
+        {
+            comp = new GlyfCompositeComp(bais);
+            components.add(comp);
+        } 
+        while ((comp.getFlags() & GlyfCompositeComp.MORE_COMPONENTS) != 0);
+
+        // Are there hinting instructions to read?
+        if ((comp.getFlags() & GlyfCompositeComp.WE_HAVE_INSTRUCTIONS) != 0) 
+        {
+            readInstructions(bais, (bais.read()<<8 | bais.read()));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void resolve() 
+    {
+        if (resolved) 
+        {
+            return;
+        }
+        if (beingResolved) 
+        {
+            System.err.println("Circular reference in GlyfCompositeDesc");
+            return;
+        }
+        beingResolved = true;
+
+        int firstIndex = 0;
+        int firstContour = 0;
+
+        Iterator<GlyfCompositeComp> i = components.iterator();
+        while (i.hasNext()) 
+        {
+            GlyfCompositeComp comp = (GlyfCompositeComp)i.next();
+            comp.setFirstIndex(firstIndex);
+            comp.setFirstContour(firstContour);
+
+            GlyphDescription desc;
+            desc = getGlypDescription(comp.getGlyphIndex());
+            if (desc != null) 
+            {
+                desc.resolve();
+                firstIndex   += desc.getPointCount();
+                firstContour += desc.getContourCount();
+            }
+        }
+        resolved = true;
+        beingResolved = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getEndPtOfContours(int i) 
+    {
+        GlyfCompositeComp c = getCompositeCompEndPt(i);
+        if (c != null) 
+        {
+            GlyphDescription gd = getGlypDescription(c.getGlyphIndex());
+            return gd.getEndPtOfContours(i - c.getFirstContour()) + 
c.getFirstIndex();
+        }
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte getFlags(int i) 
+    {
+        GlyfCompositeComp c = getCompositeComp(i);
+        if (c != null) 
+        {
+            GlyphDescription gd = getGlypDescription(c.getGlyphIndex());
+            return gd.getFlags(i - c.getFirstIndex());
+        }
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public short getXCoordinate(int i) 
+    {
+        GlyfCompositeComp c = getCompositeComp(i);
+        if (c != null) 
+        {
+            GlyphDescription gd = getGlypDescription(c.getGlyphIndex());
+            int n = i - c.getFirstIndex();
+            int x = gd.getXCoordinate(n);
+            int y = gd.getYCoordinate(n);
+            short x1 = (short) c.scaleX(x, y);
+            x1 += c.getXTranslate();
+            return x1;
+        }
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public short getYCoordinate(int i) 
+    {
+        GlyfCompositeComp c = getCompositeComp(i);
+        if (c != null) 
+        {
+            GlyphDescription gd = getGlypDescription(c.getGlyphIndex());
+            int n = i - c.getFirstIndex();
+            int x = gd.getXCoordinate(n);
+            int y = gd.getYCoordinate(n);
+            short y1 = (short) c.scaleY(x, y);
+            y1 += c.getYTranslate();
+            return y1;
+        }
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isComposite() 
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getPointCount() 
+    {
+        if (!resolved)
+        {
+            System.err.println("getPointCount called on unresolved 
GlyfCompositeDescript");
+        }
+        GlyfCompositeComp c = (GlyfCompositeComp) 
components.get(components.size()-1);
+        return c.getFirstIndex() + 
getGlypDescription(c.getGlyphIndex()).getPointCount();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getContourCount() 
+    {
+        if (!resolved)
+        {
+            System.err.println("getContourCount called on unresolved 
GlyfCompositeDescript");
+        }
+        GlyfCompositeComp c = (GlyfCompositeComp) 
components.get(components.size()-1);
+        return c.getFirstContour() + 
getGlypDescription(c.getGlyphIndex()).getContourCount();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getComponentCount() 
+    {
+        return components.size();
+    }
+
+    private GlyfCompositeComp getCompositeComp(int i) 
+    {
+        GlyfCompositeComp c;
+        for (int n = 0; n < components.size(); n++) 
+        {
+            c = (GlyfCompositeComp) components.get(n);
+            GlyphDescription gd = getGlypDescription(c.getGlyphIndex());
+            if (c.getFirstIndex() <= i && i < (c.getFirstIndex() + 
gd.getPointCount())) 
+            {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    private GlyfCompositeComp getCompositeCompEndPt(int i) 
+    {
+        GlyfCompositeComp c;
+        for (int j = 0; j < components.size(); j++) 
+        {
+            c = (GlyfCompositeComp) components.get(j);
+            GlyphDescription gd = getGlypDescription(c.getGlyphIndex());
+            if (c.getFirstContour() <= i && i < (c.getFirstContour() + 
gd.getContourCount())) 
+            {
+                return c;
+            }
+        }
+        return null;
+    }
+    
+    private GlyphDescription getGlypDescription(int index)
+    {
+        return glyphs[index].getDescription();
+    }
+}

Added: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfDescript.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfDescript.java?rev=1311300&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfDescript.java 
(added)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfDescript.java 
Mon Apr  9 16:05:55 2012
@@ -0,0 +1,122 @@
+/*
+
+   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 org.apache.fontbox.ttf;
+
+import java.io.IOException;
+
+/**
+ * This class is based on code from Apache Batik a subproject of Apache 
XMLGraphics.
+ * see http://xmlgraphics.apache.org/batik/ for further details.
+ * 
+ */
+public abstract class GlyfDescript implements GlyphDescription 
+{
+
+    // Flags describing a coordinate of a glyph.
+    /**
+     * if set, the point is on the curve.
+     */
+    public static final byte ON_CURVE = 0x01;
+    /**
+     * if set, the x-coordinate is 1 byte long.
+     */
+    public static final byte X_SHORT_VECTOR = 0x02;
+    /**
+     * if set, the y-coordinate is 1 byte long.
+     */
+    public static final byte Y_SHORT_VECTOR = 0x04;
+    /**
+     * if set, the next byte specifies the number of additional 
+     * times this set of flags is to be repeated.
+     */
+    public static final byte REPEAT = 0x08;
+    /**
+     * This flag as two meanings, depending on how the
+     * x-short vector flags is set.
+     * If the x-short vector is set, this bit describes the sign
+     * of the value, with 1 equaling positive and 0 positive.
+     * If the x-short vector is not set and this bit is also not
+     * set, the current x-coordinate is a signed 16-bit delta vector.
+     */
+    public static final byte X_DUAL = 0x10;
+    /**
+     * This flag as two meanings, depending on how the
+     * y-short vector flags is set.
+     * If the y-short vector is set, this bit describes the sign
+     * of the value, with 1 equaling positive and 0 positive.
+     * If the y-short vector is not set and this bit is also not
+     * set, the current y-coordinate is a signed 16-bit delta vector.
+     */
+    public static final byte Y_DUAL = 0x20;
+
+    private short[] instructions;
+    private int contourCount;
+
+    /**
+     * Constructor.
+     * 
+     * @param numberOfContours the number of contours
+     * @param bais the stream to be read
+     * @throws IOException is thrown if something went wrong
+     */
+    protected GlyfDescript(short numberOfContours, TTFDataStream bais) throws 
IOException 
+    {
+        contourCount = numberOfContours;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void resolve() 
+    {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getContourCount() 
+    {
+        return contourCount;
+    }
+
+    /**
+     * Returns the hinting instructions.
+     * @return an array containing the hinting instructions.
+     */
+    public short[] getInstructions() 
+    {
+        return instructions;
+    }
+
+    /**
+     * Read the hinting instructions.
+     * @param bais the stream to be read
+     * @param count the number of instructions to be read 
+     * @throws IOException is thrown if something went wrong
+     */
+    protected void readInstructions(TTFDataStream bais, int count) throws 
IOException
+    {
+        instructions = new short[count];
+        for (int i = 0; i < count; i++) 
+        {
+            instructions[i] = (short) bais.read();
+        }
+    }
+
+}

Added: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfSimpleDescript.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfSimpleDescript.java?rev=1311300&view=auto
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfSimpleDescript.java
 (added)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfSimpleDescript.java
 Mon Apr  9 16:05:55 2012
@@ -0,0 +1,194 @@
+/*
+
+   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 org.apache.fontbox.ttf;
+
+import java.io.IOException;
+
+/**
+ * This class is based on code from Apache Batik a subproject of Apache 
XMLGraphics.
+ * see http://xmlgraphics.apache.org/batik/ for further details.
+ */
+public class GlyfSimpleDescript extends GlyfDescript 
+{
+
+    private int[] endPtsOfContours;
+    private byte[] flags;
+    private short[] xCoordinates;
+    private short[] yCoordinates;
+    private int pointCount;
+
+    /**
+     * Constructor.
+     * 
+     * @param numberOfContours number of contours
+     * @param bais the stream to be read
+     * @throws IOException is thrown if something went wrong 
+     */
+    public GlyfSimpleDescript(short numberOfContours, TTFDataStream bais) 
throws IOException
+    {
+        super(numberOfContours, bais);
+        
+        // Simple glyph description
+        endPtsOfContours = new int[numberOfContours];
+        for (int i = 0; i < numberOfContours; i++) 
+        {
+            endPtsOfContours[i] = bais.readSignedShort();
+        }
+
+        // The last end point index reveals the total number of points
+        pointCount = endPtsOfContours[numberOfContours-1] + 1;
+        flags = new byte[pointCount];
+        xCoordinates = new short[pointCount];
+        yCoordinates = new short[pointCount];
+
+        int instructionCount = bais.readSignedShort();
+        readInstructions(bais, instructionCount);
+        readFlags(pointCount, bais);
+        readCoords(pointCount, bais);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getEndPtOfContours(int i) 
+    {
+        return endPtsOfContours[i];
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public byte getFlags(int i) 
+    {
+        return flags[i];
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public short getXCoordinate(int i) 
+    {
+        return xCoordinates[i];
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public short getYCoordinate(int i) 
+    {
+        return yCoordinates[i];
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isComposite() 
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getPointCount() 
+    {
+        return pointCount;
+    }
+
+    /**
+     * The table is stored as relative values, but we'll store them as 
absolutes.
+     */
+    private void readCoords(int count, TTFDataStream bais) throws IOException
+    {
+        short x = 0;
+        short y = 0;
+        for (int i = 0; i < count; i++) 
+        {
+            if ((flags[i] & X_DUAL) != 0) 
+            {
+                if ((flags[i] & X_SHORT_VECTOR) != 0) 
+                {
+                    x += (short) bais.read();
+                }
+            } 
+            else 
+            {
+                if ((flags[i] & X_SHORT_VECTOR) != 0) 
+                {
+                    x += (short) -((short) bais.read());
+                } 
+                else 
+                {
+                    x += bais.readSignedShort();
+                }
+            }
+            xCoordinates[i] = x;
+        }
+
+        for (int i = 0; i < count; i++) 
+        {
+            if ((flags[i] & Y_DUAL) != 0) 
+            {
+                if ((flags[i] & Y_SHORT_VECTOR) != 0) 
+                {
+                    y += (short) bais.read();
+                }
+            } 
+            else 
+            {
+                if ((flags[i] & Y_SHORT_VECTOR) != 0) 
+                {
+                    y += (short) -((short) bais.read());
+                } 
+                else 
+                {
+                    y += bais.readSignedShort();
+                }
+            }
+            yCoordinates[i] = y;
+        }
+    }
+
+    /**
+     * The flags are run-length encoded.
+     */
+    private void readFlags(int flagCount, TTFDataStream bais) throws 
IOException
+    {
+        try 
+        {
+            for (int index = 0; index < flagCount; index++) 
+            {
+                flags[index] = (byte) bais.read();
+                if ((flags[index] & REPEAT) != 0) 
+                {
+                    int repeats = bais.read();
+                    for (int i = 1; i <= repeats; i++) 
+                    {
+                        flags[index + i] = flags[index];
+                    }
+                    index += repeats;
+                }
+            }
+        } 
+        catch (ArrayIndexOutOfBoundsException e) 
+        {
+            System.out.println("error: array index out of bounds");
+        }
+    }
+}

Modified: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java?rev=1311300&r1=1311299&r2=1311300&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java 
(original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java 
Mon Apr  9 16:05:55 2012
@@ -28,19 +28,13 @@ import org.apache.fontbox.util.BoundingB
  */
 public class GlyphData
 {
-    private static final int FLAG_ON_CURVE = 1;
-    private static final int FLAG_SHORT_X = 1<<1;
-    private static final int FLAG_SHORT_Y = 1<<2;
-    private static final int FLAG_X_MAGIC = 1<<3;
-    private static final int FLAG_Y_MAGIC = 1<<4;
-   
-    private BoundingBox boundingBox = new BoundingBox();
+    private short xMin;
+    private short yMin;
+    private short xMax;
+    private short yMax;
+    private BoundingBox boundingBox = null;
     private short numberOfContours;
-    private int[] endPointsOfContours;
-    private byte[] instructions;
-    private int[] flags;
-    private short[] xCoordinates;
-    private short[] yCoordinates;
+    private GlyfDescript glyphDescription = null;
     
     /**
      * This will read the required data from the stream.
@@ -52,32 +46,22 @@ public class GlyphData
     public void initData( TrueTypeFont ttf, TTFDataStream data ) throws 
IOException
     {
         numberOfContours = data.readSignedShort();
-        boundingBox.setLowerLeftX( data.readSignedShort() );
-        boundingBox.setLowerLeftY( data.readSignedShort() );
-        boundingBox.setUpperRightX( data.readSignedShort() );
-        boundingBox.setUpperRightY( data.readSignedShort() );
-        /**if( numberOfContours > 0 )
+        xMin = data.readSignedShort();
+        yMin = data.readSignedShort();
+        xMax = data.readSignedShort();
+        yMax = data.readSignedShort();
+        boundingBox = new BoundingBox(xMin, yMin, xMax, yMax);
+
+        if (numberOfContours >= 0) 
+        {
+            // create a simple glyph
+            glyphDescription = new GlyfSimpleDescript(numberOfContours, data);
+        }
+        else 
         {
-            endPointsOfContours = new int[ numberOfContours ];
-            for( int i=0; i<numberOfContours; i++ )
-            {
-                endPointsOfContours[i] = data.readUnsignedShort();
-            }
-            int instructionLength = data.readUnsignedShort();
-            instructions = data.read( instructionLength );
-            
-            //BJL It is possible to read some more information here but PDFBox
-            //does not need it at this time so just ignore it.
-            
-            //not sure if the length of the flags is the number of contours??
-            //flags = new int[numberOfContours];
-            //first read the flags, and just so the TTF can save a couples 
bytes
-            //we need to check some bit masks to see if there are more bytes 
or not.
-            //int currentFlagIndex = 0;
-            //int currentFlag = 
-            
-            
-        }*/
+            // create a composite glyph
+            glyphDescription = new GlyfCompositeDescript(data, ttf.getGlyph());
+        }
     }
     
     /**
@@ -108,4 +92,50 @@ public class GlyphData
     {
         this.numberOfContours = numberOfContoursValue;
     }
+   
+    /**
+     * Returns the description of the glyph.
+     * @return the glyph description
+     */
+    public GlyphDescription getDescription()
+    {
+        return glyphDescription;
+    }
+    
+    /**
+     * Returns the xMax value.
+     * @return the XMax value
+     */
+    public short getXMaximum() 
+    {
+        return xMax;
+    }
+
+    /**
+     * Returns the xMin value.
+     * @return the xMin value
+     */
+    public short getXMinimum() 
+    {
+        return xMin;
+    }
+
+    /**
+     * Returns the yMax value.
+     * @return the yMax value
+     */
+    public short getYMaximum() 
+    {
+        return yMax;
+    }
+
+    /**
+     * Returns the yMin value.
+     * @return the yMin value
+     */
+    public short getYMinimum() 
+    {
+        return yMin;
+    }
+
 }

Added: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphDescription.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphDescription.java?rev=1311300&view=auto
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphDescription.java 
(added)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphDescription.java 
Mon Apr  9 16:05:55 2012
@@ -0,0 +1,81 @@
+/*
+
+   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 org.apache.fontbox.ttf;
+
+/**
+ * Specifies access to glyph description classes, simple and composite.
+ * 
+ * This class is based on code from Apache Batik a subproject of Apache 
XMLGraphics.
+ * see http://xmlgraphics.apache.org/batik/ for further details.
+ * 
+ */
+public interface GlyphDescription 
+{
+    /** 
+     * Returns the index of the ending point of the given contour.
+     * 
+     * @param i the number of the contour
+     * @return the index of the ending point of the given contour
+     */
+    public int getEndPtOfContours(int i);
+    
+    /**
+     * Returns the flags of the given point.
+     * @param i the given point
+     * @return the flags value for the given point
+     */
+    public byte getFlags(int i);
+    
+    /**
+     * Returns the x coordinate of the given point.
+     * @param i the given point
+     * @return the x coordinate value for the given point
+     */
+    public short getXCoordinate(int i);
+
+    /**
+     * Returns the y coordinate of the given point.
+     * @param i the given point
+     * @return the y coordinate value for the given point
+     */
+    public short getYCoordinate(int i);
+
+    /**
+     * Returns whether this point is a composite or not.
+     * @return true if this point is a composite
+     */
+    public boolean isComposite();
+    
+    /**
+     * Returns the number of points.
+     * @return the number of points
+     */
+    public int getPointCount();
+    
+    /**
+     * Returns the number of contours.
+     * @return the number of contours
+     */
+    public int getContourCount();
+    
+    /**
+     * Resolve all parts of an composite glyph.
+     */
+    public void resolve(); 
+}

Modified: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java?rev=1311300&r1=1311299&r2=1311300&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java 
(original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java 
Mon Apr  9 16:05:55 2012
@@ -54,7 +54,17 @@ public class GlyphTable extends TTFTable
             glyph.initData( ttf, data );
             glyphs[i] = glyph;
         }
+        for( int i=0; i<numGlyphs-1; i++ )
+        {
+            GlyphData glyph = glyphs[i];
+            // resolve composite glyphs
+            if (glyph != null && glyph.getDescription().isComposite())
+            {
+                glyph.getDescription().resolve();
+            }
+        }
     }
+    
     /**
      * @return Returns the glyphs.
      */
@@ -62,11 +72,12 @@ public class GlyphTable extends TTFTable
     {
         return glyphs;
     }
+    
     /**
      * @param glyphsValue The glyphs to set.
      */
     public void setGlyphs(GlyphData[] glyphsValue)
     {
-        this.glyphs = glyphsValue;
+        glyphs = glyphsValue;
     }
 }


Reply via email to