Package org.jpedal.fonts.tt

Source Code of org.jpedal.fonts.tt.TTGlyph

/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info:  http://www.jpedal.org
* (C) Copyright 1997-2008, IDRsolutions and Contributors.
*
*   This file is part of JPedal
*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


*
* ---------------
* TTGlyph.java
* ---------------
*/
package org.jpedal.fonts.tt;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.HashSet;

import org.jpedal.color.PdfPaint;
import org.jpedal.fonts.glyph.PdfGlyph;
import org.jpedal.io.PathSerializer;
import org.jpedal.objects.GraphicsState;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.repositories.Vector_Double;
import org.jpedal.utils.repositories.Vector_Int;
import org.jpedal.utils.repositories.Vector_Object;
import org.jpedal.utils.repositories.Vector_Path;
import org.jpedal.utils.repositories.Vector_Short;

public class TTGlyph implements PdfGlyph, Serializable {


  public static boolean useHinting = false;
  /**/

    public static boolean redecodePage = false;
   
    static {
        String value = System.getProperty("org.jpedal.useTTFontHinting");
        if (value != null) {
            useHinting = value.toLowerCase().equals("true");
        }
    }

    private static HashSet testedFonts = new HashSet();


    private boolean containsBrokenGlyfData=false;

    private boolean ttHintingRequired=false;

  private short minX,minY,maxX,maxY;

    int BPoint1, BPoint2;

    int BP1x=-1,BP2x=-1,BP1y=-1,BP2y=-1;

    private short compMinX, compMinY, compMaxX, compMaxY;

    private int[] scaledX, scaledY;

  private short leftSideBearing;
  //private int advanceWidth;
 
  private Vector_Int xtranslateValues=new Vector_Int(5);
  private Vector_Int ytranslateValues=new Vector_Int(5);
  private Vector_Double xscaleValues=new Vector_Double(5);
  private Vector_Double yscaleValues=new Vector_Double(5);
  private Vector_Double scale01Values=new Vector_Double(5);
  private Vector_Double scale10Values=new Vector_Double(5);

  private int xtranslate,ytranslate;
 
  private double xscale=1,yscale=1,scale01=0,scale10=0;

    private int[] instructions;
    private int currentInstructionDepth=Integer.MAX_VALUE;
  private Vector_Object glyfX=new Vector_Object(5);
  private Vector_Object glyfY=new Vector_Object(5);
  private Vector_Object curves=new Vector_Object(5);
  private Vector_Object contours=new Vector_Object(5);
  private Vector_Int endPtIndices=new Vector_Int(5);

  private int contourCount=0;
 
  private float unitsPerEm=64;
 
  public boolean debug=false;
 
 
  /**paths for the letter, marked as transient so it wont be serialized */
  private transient Vector_Path paths=new Vector_Path(10);
 
  //used to track which glyf for complex glyph
  private int compCount=1;
 
  private boolean isComposite=false;
 
  String glyfName="";
    private double pixelSize;

  //private int idx;
 
  /**
   * method to set the paths after the object has be deserialized.
   *
   * NOT PART OF API and subject to change (DO NOT USE)
   *
   * @param vp - the Vector_Path to set
   */
  public void setPaths(Vector_Path vp){
    paths = vp;
  }
 
  /**
   * method to serialize all the paths in this object.  This method is needed because
   * GeneralPath does not implement Serializable so we need to serialize it ourself.
   * The correct usage is to first serialize this object, cached_current_path is marked
   * as transient so it will not be serilized, this method should then be called, so the
   * paths are serialized directly after the main object in the same ObjectOutput.
   *
   * NOT PART OF API and subject to change (DO NOT USE)
   *
   * @param os - ObjectOutput to write to
   * @throws IOException
   */
  public void writePathsToStream(ObjectOutput os) throws IOException {
    if((paths!=null)){
     
      GeneralPath[] generalPaths=paths.get();
     
      int count=0;
     
      /** find out how many items are in the collection */
      for (int i = 0; i < generalPaths.length; i++) {
        if(generalPaths[i]==null){
          count = i;
          break;
        }
      }
     
      /** write out the number of items are in the collection */
      os.writeObject(count);
     
      /** iterate throught the collection, and write out each path individualy */
      for (int i = 0; i < count; i++) {
        PathIterator pathIterator = generalPaths[i].getPathIterator(new AffineTransform());
        PathSerializer.serializePath(os, pathIterator);
      }
     
    }
  }
 
  public TTGlyph(){}



    /**
     * Unhinted constructor
     */
    public TTGlyph(String glyfName,boolean debug,Glyf currentGlyf,FontFile2 glyfTable,Hmtx currentHmtx,int idx,
                   float unitsPerEm, String baseFontName){

        //debug=idx==2246;
        this.debug=debug;

        this.glyfName=glyfName;
        //this.idx=idx;
        this.leftSideBearing =currentHmtx.getLeftSideBearing(idx);
        //this.advanceWidth = currentHmtx.getAdvanceWidth(idx);
        this.unitsPerEm=unitsPerEm;

        int p=currentGlyf.getCharString(idx);
        glyfTable.setPointer(p);

        readGlyph(currentGlyf,glyfTable);

        /**create glyphs the first time*/
        for(int i=0;i<this.compCount;i++){

            int[] pX=(int[]) glyfX.elementAt(i);
            int[] pY=(int[]) glyfY.elementAt(i);
            boolean[] onCurve=(boolean[]) curves.elementAt(i);
            boolean[] endOfContour=(boolean[])contours.elementAt(i);
            int endIndex=endPtIndices.elementAt(i);

            if(isComposite){
                xtranslate=xtranslateValues.elementAt(i);
                ytranslate=ytranslateValues.elementAt(i);
                xscale=xscaleValues.elementAt(i);
                yscale=yscaleValues.elementAt(i);
                scale01=scale01Values.elementAt(i);
                scale10=scale10Values.elementAt(i);

                //factor in BPoint where points overlap
                if(BPoint1!=-1 && BPoint2!=-1){
                    if(BP1x==-1 && BP2x==-1 && BP1y==-1 && BP2y==-1){ //first point
                        BP1x=pX[BPoint1];
                        BP1y=pY[BPoint1];

                    }else{ //second and reset

                        BP2x=pX[BPoint2];
                        BP2y=pY[BPoint2];

                        int xx=BP1x-BP2x;
                        int yy=BP1y-BP2y;

                        int count=pX.length;
                        for(int ii=0;ii<count;ii++){
                            pX[ii]=pX[ii]+xx;

                            if(debug)
                                System.out.println(pY[ii]+" "+yy+" BP1y="+BP1y+" BP1y="+BP1y);
                            pY[ii]=pY[ii]+yy;
                        }

                        //reset for next
                        BP1x=-1;
                        BP2x=-1;
                        BP1y=-1;
                        BP2y=-1;
                    }
                }
            }


//        drawGlyf(pX,pY,onCurve,endOfContour,endIndex,debug);
            createPaths(pX,pY,onCurve,endOfContour,endIndex,debug);
        }

         /**/
        if(debug){
            try{
                System.out.println("debugging"+idx);
                java.awt.image.BufferedImage img=new java.awt.image.BufferedImage(700,700, java.awt.image.BufferedImage.TYPE_INT_ARGB);

                Graphics2D gg2= img.createGraphics();

                for(int jj=0;jj<paths.size()-1;jj++){
                    if(jj==0)
                        gg2.setColor(java.awt.Color.red);
                    else
                        gg2.setColor(java.awt.Color.blue);

                    gg2.fill(paths.elementAt(jj));


                    gg2.draw(paths.elementAt(jj).getBounds());
                }
                //org.jpedal.gui.ShowGUIMessage.showGUIMessage("glyf "+ '/' +paths.size(),img,"glyf "+ '/' +paths.size()+ '/' +compCount);
            }catch(Exception ee){
                ee.printStackTrace();
            }
        }/***/


        //if(idx==2060)
        //ShowGUIMessage.showGUIMessage("done",img,"glyf done");

    }



  private void readGlyph(Glyf currentGlyf,FontFile2 currentFontFile){
   
    //LogWriter.writeMethod("{readGlyph}", 0);
   
    contourCount=currentFontFile.getNextUint16();

    //read the max/min co-ords
    minX=(short)currentFontFile.getNextUint16();
    minY=(short)currentFontFile.getNextUint16();
    maxX=(short)currentFontFile.getNextUint16();
    maxY=(short)currentFontFile.getNextUint16();

        if(debug){
            System.out.println("------------------------------------------------------------");
            System.out.println("min="+minX+ ' ' +minY+" max="+maxX+' '+maxY+" contourCount="+contourCount);
        }

        if(contourCount!=65535){
      readSimpleGlyph(currentFontFile);
    }else{

            compMinX=minX;
            compMinY=minY;
            compMaxX=maxX;
            compMaxY=maxY;

            if(debug)
            System.out.println("XXmain="+minX+ ' ' +minY+ ' ' +maxX+ ' ' +maxY);

            readComplexGlyph(currentGlyf,currentFontFile);
    }
   
   
  }

    //Track translations for recursion
    int existingXTranslate =0;
    int existingYTranslate =0;
    int depth = 0;

  final private void readComplexGlyph(Glyf currentGlyf,FontFile2 currentFontFile){

    isComposite=true;

        //Remove elements for the compound as it's only a container
        xtranslateValues.pull();
        ytranslateValues.pull();
        xscaleValues.pull();
        yscaleValues.pull();
        scale01Values.pull();
        scale10Values.pull();


        BPoint1=-1;
        BPoint2=-1;

        //LogWriter.writeMethod("{readComplexGlyph}", 0);

        boolean WE_HAVE_INSTRUCTIONS = false;

        int count=currentGlyf.getGlypfCount();

    while(true){
      int flag=currentFontFile.getNextUint16();
      int glyphIndex=currentFontFile.getNextUint16();

            if(debug)
            System.err.println("Index="+glyphIndex+" flag="+flag+ ' ' +count);

            //allow for bum data
            if(glyphIndex>=count){
                containsBrokenGlyfData=true;
                break;
            }


            //set flag options
      boolean ARG_1AND_2_ARE_WORDS= (flag & 1)==1;
      boolean ARGS_ARE_XY_VALUES= (flag & 2) ==2;
      boolean WE_HAVE_A_SCALE=(flag & 8) ==8;
      boolean WE_HAVE_AN_X_AND_Y_SCALE=(flag & 64) ==64;
      boolean WE_HAVE_A_TWO_BY_TWO=(flag & 128) ==128;
            WE_HAVE_INSTRUCTIONS = WE_HAVE_INSTRUCTIONS || (flag & 256) == 256;



      if (ARG_1AND_2_ARE_WORDS && ARGS_ARE_XY_VALUES){
          //1st short contains the value of e
          //2nd short contains the value of f
        xtranslate=currentFontFile.getNextInt16();
        ytranslate=currentFontFile.getNextInt16();
      }else if (!ARG_1AND_2_ARE_WORDS && ARGS_ARE_XY_VALUES){
          //1st byte contains the value of e
          //2nd byte contains the value of f
        xtranslate=currentFontFile.getNextint8();
        ytranslate=currentFontFile.getNextint8();
      }else if (ARG_1AND_2_ARE_WORDS && !ARGS_ARE_XY_VALUES){
          //1st short contains the index of matching point in compound being constructed
          //2nd short contains index of matching point in component
        BPoint1 =currentFontFile.getNextUint16();
        BPoint2 =currentFontFile.getNextUint16();
        xtranslate=0;
        ytranslate=0;

            }else if (!ARG_1AND_2_ARE_WORDS && !ARGS_ARE_XY_VALUES){
         // 1st byte containing index of matching point in compound being constructed
         // 2nd byte containing index of matching point in component
        BPoint1 =currentFontFile.getNextUint8();
        BPoint2 =currentFontFile.getNextUint8();
        xtranslate=0;
        ytranslate=0;

            }

      //set defaults
      xscale=1; //a
      scale01=0; //b
      scale10=0; //c
            yscale=1; //d

      /**workout scaling factors*/
      if((!WE_HAVE_A_SCALE)&&(!WE_HAVE_AN_X_AND_Y_SCALE)&&(!WE_HAVE_A_TWO_BY_TWO)){
        //uses defaults already set
       
      }else if((WE_HAVE_A_SCALE)&&(!WE_HAVE_AN_X_AND_Y_SCALE)&&(!WE_HAVE_A_TWO_BY_TWO)){

        xscale=currentFontFile.getF2Dot14(); //a
        scale01=0; //b
        scale10=0; //c
                yscale=xscale; //d
            }else if((!WE_HAVE_A_SCALE)&&(WE_HAVE_AN_X_AND_Y_SCALE)&&(!WE_HAVE_A_TWO_BY_TWO)){

        xscale=currentFontFile.getF2Dot14(); //a
        scale01=0; //b
        scale10=0; //c
                yscale=currentFontFile.getF2Dot14(); //d

      }else if((!WE_HAVE_A_SCALE)&&(!WE_HAVE_AN_X_AND_Y_SCALE)&&(WE_HAVE_A_TWO_BY_TWO)){

        xscale=currentFontFile.getF2Dot14(); //a
        scale01=currentFontFile.getF2Dot14(); //b
        scale10=currentFontFile.getF2Dot14(); //c
                yscale=currentFontFile.getF2Dot14(); //d
            }

            //store so we can remove later
            int localX = xtranslate;
            int localY = ytranslate;

            //Get total translation
            xtranslate += existingXTranslate;
            ytranslate += existingYTranslate;

      //save values
      xtranslateValues.addElement(xtranslate);
      ytranslateValues.addElement(ytranslate);
      xscaleValues.addElement(xscale);
      yscaleValues.addElement(yscale);
      scale01Values.addElement(scale01);
      scale10Values.addElement(scale10);

      //save location so we can restore
      int pointer=currentFontFile.getPointer();
     
      /**/
      //now read the simple glyphs
      int p=currentGlyf.getCharString(glyphIndex);

            if(p!=-1){
        if(p<0)
          p=-p;
        currentFontFile.setPointer( p);
                existingXTranslate = xtranslate;
                existingYTranslate = ytranslate;
                depth++;
        readGlyph(currentGlyf,currentFontFile);
                depth--;
                existingXTranslate -= localX;
                existingYTranslate -= localY;
      }else{
        System.err.println("Wrong value in complex");
      }
     
      currentFontFile.setPointer(pointer);

      //break out at end
      if((flag & 32) ==0) {

                if (WE_HAVE_INSTRUCTIONS) {
                    int instructionLength = currentFontFile.getNextUint16();
                    int[] instructions = new int[instructionLength];
                    for (int i=0; i< instructionLength; i++)
                        instructions[i] = currentFontFile.getNextUint8();
                    if (depth <= currentInstructionDepth) {
                        this.instructions = instructions;
                        currentInstructionDepth=depth;
                    }
                } else {
                    if (depth <= currentInstructionDepth) {
                        this.instructions = new int[]{};
                        currentInstructionDepth=depth;
                    }
                }

                break;
            }
     
      compCount++;
    }
  }
 
  private void readSimpleGlyph(FontFile2 currentFontFile){
   
    //LogWriter.writeMethod("{readSimpleGlyph}", 0);
   
    int flagCount=1;
   
    short x1  ;
   
    Vector_Int rawFlags=new Vector_Int(50);
    Vector_Int endPts=new Vector_Int(50);
    Vector_Short XX=new Vector_Short(50);
    Vector_Short Y=new Vector_Short(50);
   

   
    //all endpoints
        if(debug){
            System.out.println("endPoints");
            System.out.println("---------");
        }

        int lastPt=0;
            for(int i=0;i<contourCount;i++){


                lastPt=currentFontFile.getNextUint16();

                if(debug)
                    System.out.println(i+" "+lastPt);

                endPts.addElement(lastPt);

            }

        //allow for corrupted value with not enough entries
        //ie customers3/ICG3Q03.pdf
        if(currentFontFile.hasValuesLeft()){


    /**Don;t comment out !!!!!!!!!
     * needs to be read to advance pointer*/
    int instructionLength=currentFontFile.getNextUint16();
    int[] instructions=new int[instructionLength];
    for(int i=0;i<instructionLength;i++)
      instructions[i]=currentFontFile.getNextUint8();

        if (depth < currentInstructionDepth)
            this.instructions = instructions;

         if(debug){
            System.out.println("Instructions");
            System.out.println("------------");
            System.out.println("count="+instructionLength);
        }

        int count = lastPt+ 1;
    int flag;
   
    /**we read the flags (some can repeat)*/
    for (int i = 0; i < count; i++) {
      flag=currentFontFile.getNextUint8();
      rawFlags.addElement(flag)
      flagCount++;
     
      if ((flag & 8) == 8) { //repeating flags
        int repeatCount = currentFontFile.getNextUint8();
        for (int r = 1; r <= repeatCount; r++) {
          rawFlags.addElement(flag);
          flagCount++;
        }
        i += repeatCount;
      }
    }
   
    /**read the x values and set segment for complex glyph*/
    for(int i=0;i<count;i++){
      flag=rawFlags.elementAt(i);
     
      //boolean twoByteValue=((flag  & 2)==0);
      if ((flag & 16) != 0) { //
        if ((flag & 2) != 0) { //1 byte + value
          x1=(short)currentFontFile.getNextUint8();
          XX.addElement(x1);
        }else{ //2 byte value - same as previous - ??? same X coord or value
          XX.addElement((short)0);
        }
       
      } else {
        if ((flag  & 2) != 0){ //1 byte - value
          x1=(short)-currentFontFile.getNextUint8();
          XX.addElement(x1);
        }else{ //signed 16 bit delta vector
          x1=currentFontFile.getNextSignedInt16();     
          XX.addElement(x1)
        }
      }
    }
   
    /**read the y values*/
    for(int i=0;i<count;i++){
      flag=rawFlags.elementAt(i);
      if ((flag & 32) != 0) {
        if ((flag & 4) != 0) {
          Y.addElement((short)currentFontFile.getNextUint8());
        } else {
          Y.addElement((short)0);
        }
      } else {
        if ((flag & 4) != 0) {
          Y.addElement((short)-currentFontFile.getNextUint8());
        } else {
          short val=currentFontFile.getNextSignedInt16();
          Y.addElement(val);
        }
      }
    }
   
    /**
     * calculate the points
     */
    int endPtIndex = 0;
    int x=0,y=0;
   
        int[] flags=rawFlags.get();
   
    int[] endPtsOfContours=endPts.get();
    short[] XPoints=XX.get();
    short[] YPoints=Y.get();
    count=XPoints.length;

    int[] pX=new int[count+2];
    int[] pY=new int[count+2];
    boolean[] onCurve=new boolean[count+2];
    boolean[] endOfContour=new boolean[count+2];

        int endIndex=0;

        if(debug){
            System.out.println("Points");
            System.out.println("------");
        }
        for (int i = 0; i < count; i++) {
     
      boolean endPt = endPtsOfContours[endPtIndex] == i;
      if (endPt){
        endPtIndex++;
                endIndex=i+1;
            }
      x +=XPoints[i];
      y +=YPoints[i];

      pX[i]=x;
      pY[i]=y;

            onCurve[i] = i < flagCount && (flags[i] & 1) != 0;

            endOfContour[i]=endPt;

            if(debug)
                System.out.println(i+" "+pX[i]+ ' ' +pY[i]+ " on curve=" +onCurve[i]+" endOfContour[i]="+endOfContour[i]);

     
        }

        for (int i=0; i<pX.length; i++) {
            int lX = pX[i];
            int lY = pY[i];

            //Convert x
            //pX[i] = convertX(lX,lY);
            if(!isComposite) {
                if (!useHinting)
                    pX[i] = (int)(lX/unitsPerEm);
                else
                    pX[i] = lX;
            } else {
                if (!useHinting)
                    pX[i] = (int)((((lX * xscale) + (lY * scale10))+xtranslate)/unitsPerEm);
                else
                    pX[i] = (int)((((lX * xscale) + (lY * scale10))+xtranslate));
            }


            //Convert Y
            //pY[i] = convertY(lX,lY);
            if(!isComposite) {
                if (!useHinting)
                    pY[i] = (int)(lY/unitsPerEm);
                else
                    pY[i] = lY;
            } else {
                if (!useHinting)
                    pY[i] = (int)((((lX * scale01) + (lY * yscale))+ytranslate)/unitsPerEm);
                else
                    pY[i] = (int)((((lX * scale01) + (lY * yscale))+ytranslate));
            }
        }
   
    //store
    glyfX.addElement(pX);
    glyfY.addElement(pY);
    this.curves.addElement(onCurve);
    this.contours.addElement(endOfContour);
        this.endPtIndices.addElement(endIndex);

        // move back at end
    /**
    pX[count]=0;
    pY[count]=0;
    onCurve[count]=true;
    endOfContour[count]=true;
    pX[count+1]=advanceWidth;
    pY[count+1]=0;
    onCurve[count+1]=true;
    endOfContour[count+1]=true;
   
    /**
    debug=false;
   
    if(idx==92){
    //if(glyfName.equals("y")){
      ii++;
        if(ii>0){
          System.out.println(ii+"=============="+glyfName+"=====================");
         
          debug=true;
       
          img=new BufferedImage(1000,1000,BufferedImage.TYPE_INT_ARGB);
          Graphics2D g2=(Graphics2D) img.createGraphics();

         g2.setColor(Color.red);
         render(g2,debug);
         }
         }/**/
        }
    }

    //public void render(Graphics2D g2){}
    public void render(int type, Graphics2D g2, float scaling, boolean isFormGlyph){

        AffineTransform restore = g2.getTransform();
        BasicStroke oldStroke = (BasicStroke)g2.getStroke();

        float strokeWidth = oldStroke.getLineWidth();

        if (strokeWidth < 0)
            strokeWidth = -strokeWidth;

        if(useHinting){
            //Scale down glyph
            g2.scale(1 / 100d, 1 / 100d);

            //Widen stroke to compensate for scale
            strokeWidth = strokeWidth * 100;
        }

        g2.setStroke(new BasicStroke(strokeWidth,
                BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_ROUND,
                oldStroke.getMiterLimit(),
                oldStroke.getDashArray(),
                oldStroke.getDashPhase()));

        /**drawn the paths*/
        for(int jj=0;jj<paths.size()-1;jj++){

            if((type & GraphicsState.FILL)==GraphicsState.FILL){
                g2.fill(paths.elementAt(jj));
            }else if((type & GraphicsState.STROKE)==GraphicsState.STROKE){
                g2.draw(paths.elementAt(jj));
            }
        }

        if (useHinting) {
            //Restore stroke width and scaling
            g2.setStroke(oldStroke);
            g2.setTransform(restore);
        }
    }

    Area glyphShape=null;
 
  /**return outline of shape*/
  public Area getShape(){/**/
   
    if(glyphShape==null){
   
    /**drawn the paths*/
    GeneralPath path=paths.elementAt(0);
   
      for(int jj=1;jj<paths.size()-1;jj++)
        path.append(paths.elementAt(jj),false);     
   
    glyphShape=new Area(path);
   
    }

    return glyphShape;
   
  }

    //used by Type3 fonts
    public String getGlyphName() {
        return null;
    }

    /**create the actual shape
     * @param pX*/
  public void scaler(int[] pX,int[] pY){

        scaledX = new int[pX.length];
        scaledY = new int[pY.length];

        double scale = (pixelSize / (unitsPerEm*1000)) * 64;

        for (int i=0; i<pX.length; i++) {
            scaledX[i] = (int)((scale * pX[i])+0.5);
            scaledY[i] = (int)((scale * pY[i])+0.5);
        }

        scaledX[pX.length-2] = 0;
        scaledY[pY.length-2] = 0;
        scaledX[pX.length-1] = (int)((scale * leftSideBearing)+0.5);
        scaledY[pY.length-1] = 0;

    }


//    /**create the actual shape*/
//    public void drawGlyf(int[] pX,int[] pY,boolean[] onCurve,boolean[] endOfContour,int endIndex, boolean debug){
//
//        /**
//                * scan data and adjust glyfs after first if do not end in contour
//                */
//
//        int ptCount=endOfContour.length;
//
//        //sam2-start (copy whole loop)
//        int start=0, firstPt=-1;
//        for(int ii=0;ii<ptCount;ii++){
//
//            if(endOfContour[ii]){
//
//                if(firstPt!=-1 && (!onCurve[start] || !onCurve[ii]) ){ //last point not on curve and we have a first point
//
//                    int diff=firstPt-start,newPos=0;
//
//                    //make a deep copy of values
//                    int pXlength=pX.length;
//                    int[] old_pX=new int[pXlength];
//                    System.arraycopy(pX,0,old_pX,0,pXlength);
//
//                    int[] old_pY=new int[pXlength];
//                    System.arraycopy(pY,0,old_pY,0,pXlength);
//
//                    boolean[] old_onCurve=new boolean[pXlength];
//                    System.arraycopy(onCurve,0,old_onCurve,0,pXlength);
//
//                    //rotate values to ensure point at start
//                    for(int oldPos=start;oldPos<ii+1;oldPos++){
//
//                        newPos=oldPos+diff;
//                        if(newPos>ii)
//                        newPos=newPos-(ii-start+1);
//                        pX[oldPos]=old_pX[newPos];
//                        pY[oldPos]=old_pY[newPos];
//                        onCurve[oldPos]=old_onCurve[newPos];
//
//                    }
//                }
//
//                //reset values
//                start=ii+1;
//                firstPt=-1;
//
//            }else if(onCurve[ii] && firstPt==-1){ //track first point
//                firstPt=ii;
//            }
//
//        }
//        //sam2 -end
//
//        boolean isFirstDraw=true;
//
//        GeneralPath current_path =new GeneralPath(GeneralPath.WIND_NON_ZERO);
//
//        int c= pX.length,fc=-1;
//
//        //find first end contour
//        for(int jj=0;jj<c;jj++){
//            if(endOfContour[jj]){
//                fc=jj+1;
//                jj=c;
//            }
//        }
//
//        int x1=0,y1=0,x2=0,y2=0,x3=0,y3=0;
//        x1=convertX(pX[0],pY[0]);
//        y1=convertY(pX[0],pY[0]);
//
//        if(this.debug)
//            System.out.println(pX[0]+" "+pY[0]+" move to x1,y1="+x1+" "+y1);
//
//        current_path.moveTo(x1,y1);
//
//        if(this.debug){
//            System.out.println("first contour="+fc+"===================================="+pX[0]+ ' ' +pY[0]);
//            //System.out.println("start="+x1+ ' ' +y1+" unitsPerEm="+unitsPerEm);
//            //for (int i = 0; i <c-2; i++)
//            //System.out.println(i+" "+convertX(pX[i],pY[i])+ ' ' +convertY(pX[i],pY[i])+ ' ' +onCurve[i]+ ' ' +endOfContour[i]+" raw="+pX[i]+ ' ' +pY[i]);
//
//            //System.out.println("Move to "+x1+ ' ' +y1);
//
//        }
//
//        int xs=0,ys=0,lc=0;
//        boolean isEnd=false;
//
//        for (int j = 0; j <endIndex; j++) {
//
//            int p=j%fc;
//            int p1=(j+1)%fc;
//            int p2=(j+2)%fc;
//            int pm1=(j-1)%fc;
//
//            /**special cases
//             *
//             *round up to last point at end
//             *First point
//             */
//            if(j==0)
//                pm1=fc-1;
//            if(p1<lc)
//                p1=p1+lc;
//            if(p2<lc)
//                p2=p2+lc;
//
//            if(debug)
//                System.out.println(j+"=======points="+lc+ '/' +fc+ ' ' +pm1+ ' ' +p+ ' ' +p1+ ' ' +p2+" j="+j+" endOfContour[j]="+endOfContour[j]);
//
//            //allow for wrap around on contour
//            if(endOfContour[j]){
//                isEnd=true;
//
//                if(onCurve[fc]){
//                    xs=convertX(pX[fc],pY[fc]);
//                    ys=convertY(pX[fc],pY[fc]);
//                }else{
//                    xs=convertX(pX[j+1],pY[j+1]);
//                    ys=convertY(pX[j+1],pY[j+1]);
//                }
//
//                //remember start point
//                lc=fc;
//                //find next contour
//                for(int jj=j+1;jj<c;jj++){
//                    if(endOfContour[jj]){
//                        fc=jj+1;
//                        jj=c;
//                    }
//                }
//
//                if(debug)
//                    System.out.println("End of contour. next="+j+ ' ' +fc+ ' ' +lc);
//
//            }
//
//            //sam2-start
//            if(debug){
//                if(j>0)
//                    System.out.println("curves="+onCurve[p]+ ' ' +onCurve[p1]+ ' ' +onCurve[p2]+" EndOfContour j-1="+endOfContour[j-1]+" j="+endOfContour[j]+ " j+1=" +endOfContour[j+1]);
//                else
//                    System.out.println("curves="+onCurve[p]+ ' ' +onCurve[p1]+ ' ' +onCurve[p2]+" EndOfContour j="+endOfContour[j]+" j+1="+endOfContour[j+1]);
//            }
//            //sam2-end
//
//            if(lc==fc && onCurve[p]){
//                j=c;
//                if(debug)
//                    System.out.println("last 2 match");
//            }else{
//
//                if(debug)
//                    System.out.println("fc="+fc+" pm1="+pm1+ " p=" +p+ " p1=" +p1+ " p2=" +p2);
//
//                if(onCurve[p] && onCurve[p1]){ //straight line
//                    x3=convertX(pX[p1],pY[p1]);
//                    y3=convertY(pX[p1],pY[p1]);
//                    current_path.lineTo(x3,y3);
//                    if(debug)
//                        System.out.println(p+" pt,pt "+x3+ ' ' +y3+" (lineTo)");
//
//                    isFirstDraw=false;
//                    //curves
//                }else if(j<(c-3) &&((fc-lc)>1 || fc==lc)){
//
//                    boolean checkEnd=false;
//                    if(onCurve[p] && !onCurve[p1] && onCurve[p2] ){ //2 points + control
//
//                        x1=convertX(pX[p],pY[p]);
//                        y1=convertY(pX[p],pY[p]);
//                        x2=convertX(pX[p1],pY[p1]);
//                        y2=convertY(pX[p1],pY[p1]);
//                        x3=convertX(pX[p2],pY[p2]);
//                        y3=convertY(pX[p2],pY[p2]);
//                        j++;
//                        checkEnd=true;
//                        if(debug)
//                            System.out.println(p+" pt,cv,pt "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);
//
//                    }else if(onCurve[p] && !onCurve[p1] && !onCurve[p2]){ //1 point + 2 control
//
//                        x1=convertX(pX[p],pY[p]);
//                        y1=convertY(pX[p],pY[p]);
//                        x2=convertX(pX[p1],pY[p1]);
//                        y2=convertY(pX[p1],pY[p1]);
////                        x3=convertX(midPt(pX[p1], pX[p2]),midPt(pY[p1], pY[p2]));
////                        y3=convertY(midPt(pX[p1], pX[p2]),midPt(pY[p1], pY[p2]));
//                        x3=midPt(convertX(pX[p1], pY[p1]),convertX(pX[p2], pY[p2]));
//                        y3=midPt(convertY(pX[p1], pY[p1]),convertY(pX[p2], pY[p2]));
//                        j++;
//
//                        checkEnd=true;
//
//                        if(debug)
//                            System.out.println(p+" pt,cv,cv "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);
//
//                    }else if(!onCurve[p] && !onCurve[p1] && (!endOfContour[p2] ||fc-p2==1)){ // 2 control + 1 point (final check allows for last point to complete loop
//
////                        x1=convertX(midPt(pX[pm1], pX[p]),midPt(pY[pm1], pY[p]));
////                        y1=convertY(midPt(pX[pm1], pX[p]),midPt(pY[pm1], pY[p]));
//                        x1=midPt(convertX(pX[pm1], pY[pm1]),convertX(pX[p], pY[p]));
//                        y1=midPt(convertY(pX[pm1], pY[pm1]),convertY(pX[p], pY[p]));
//                        x2=convertX(pX[p],pY[p]);
//                        y2=convertY(pY[p],pY[p]);
//
////                        x3=convertX(midPt(pX[p], pX[p1]),midPt(pY[p], pY[p1]));
////                        y3=convertY(midPt(pX[p], pX[p1]),midPt(pY[p], pY[p1]));
//                        x3=midPt(convertX(pX[p], pY[p]),convertX(pX[p1], pY[p1]));
//                        y3=midPt(convertY(pX[p], pY[p]),convertY(pX[p1], pY[p1]));
//                        if(debug)
//                            System.out.println(p+" cv,cv2 "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);
//
//
//                    }else if(!onCurve[p] && onCurve[p1]){ // 1 control + 2 point
//
////                        x1=convertX(midPt(pX[pm1], pX[p]),midPt(pY[pm1], pY[p]));
////                        y1=convertY(midPt(pX[pm1], pX[p]),midPt(pY[pm1], pY[p]));
//                        x1=midPt(convertX(pX[pm1], pY[pm1]),convertX(pX[p], pY[p]));
//                        y1=midPt(convertY(pX[pm1], pY[pm1]),convertY(pX[p], pY[p]));
//                        x2=convertX(pX[p],pY[p]);
//                        y2=convertY(pX[p],pY[p]);
//                        x3=convertX(pX[p1],pY[p1]);
//                        y3=convertY(pX[p1],pY[p1]);
//                        if(debug)
//                            System.out.println(p+" cv,pt "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);
//                    }
//
//                    if(isFirstDraw){
//                        current_path.moveTo(x1,y1);
//                        isFirstDraw=false;
//
//                        if(debug)
//                            System.out.println("first draw move to "+x1+" "+y1);
//
//                    }
//
//                    current_path.curveTo(x1,y1,x2,y2,x3,y3);
//
//                    if(debug)
//                        System.out.println("curveto "+x1+" "+y1+" "+x2+" "+y2+" "+x3+" "+y3);
//
//                    /**if end after curve, roll back so we pick up the end*/
//                    if( checkEnd && endOfContour[j]){
//
//                        isEnd=true;
//
//                        xs=convertX(pX[fc],pY[fc]);
//                        ys=convertY(pX[fc],pY[fc]);
//                        //remmeber start point
//                        lc=fc;
//                        //find next contour
//                        for(int jj=j+1;jj<c;jj++){
//                            if(endOfContour[jj]){
//                                fc=jj+1;
//                                jj=c;
//                            }
//                        }
//
//                        if(debug)
//                            System.out.println("Curve");
//                    }
//                }
//
//                if(debug)
//                    System.out.println("x2 "+xs+ ' ' +ys+ ' ' +isEnd);
//
//
//                if(isEnd){
//                    current_path.moveTo(xs,ys);
//                    isEnd=false;
//                    if(debug)
//                        System.out.println("Move to "+xs+ ' ' +ys);
//                }
//
//                if(debug){
//                    try{
//                        if(img==null)
//                            img=new java.awt.image.BufferedImage(800,800, java.awt.image.BufferedImage.TYPE_INT_ARGB);
//
//                        Graphics2D g2= img.createGraphics();
//                        g2.setColor(java.awt.Color.black);
//                        g2.translate(0,50);
//                        g2.draw(current_path);
//
//                        final String key= String.valueOf(p);
//
//                        org.jpedal.gui.ShowGUIMessage.showGUIMessage(key,img,key);
//
//                    }catch(Exception e){
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }
//
//        /**
//         * store so we can draw glyf as set of paths
//         */
//        paths.addElement(current_path);
//
//        if(debug)
//            System.out.println("Ends at "+x1+ ' ' +y1+" x="+minX+","+maxX+" y="+minY+","+maxY+" glyph x="+compMinX+","+compMaxX+" y="+compMinY+","+compMaxY);
//
//    }



    /**create the actual shape*/
  public void createPaths(int[] pX,int[] pY,boolean[] onCurve,boolean[] endOfContour,int endIndex, boolean debug){

        //allow for bum data
        if(endOfContour==null)
            return;

        /**
         * scan data and adjust glyfs after first if do not end in contour
         */

        int ptCount=endOfContour.length;

        int start=0, firstPt=-1;
        for(int ii=0;ii<ptCount;ii++){

            if(endOfContour[ii]){

                if(firstPt!=-1 && (!onCurve[start] || !onCurve[ii]) ){ //last point not on curve and we have a first point

                    int diff=firstPt-start,newPos;

                    //make a deep copy of values
                    int pXlength=pX.length;
                    int[] old_pX=new int[pXlength];
                    System.arraycopy(pX,0,old_pX,0,pXlength);

                    int[] old_pY=new int[pXlength];
                    System.arraycopy(pY,0,old_pY,0,pXlength);

                    boolean[] old_onCurve=new boolean[pXlength];
                    System.arraycopy(onCurve,0,old_onCurve,0,pXlength);

                    //rotate values to ensure point at start
                    for(int oldPos=start;oldPos<ii+1;oldPos++){

                        newPos=oldPos+diff;
                        if(newPos>ii)
                            newPos=newPos-(ii-start+1);
                        pX[oldPos]=old_pX[newPos];
                        pY[oldPos]=old_pY[newPos];
                        onCurve[oldPos]=old_onCurve[newPos];

                    }
                }

                //reset values
                start=ii+1;
                firstPt=-1;

            }else if(onCurve[ii] && firstPt==-1){ //track first point
                firstPt=ii;
            }

        }

        boolean isFirstDraw=true;

        GeneralPath current_path =new GeneralPath(GeneralPath.WIND_NON_ZERO);

        int c= pX.length,fc=-1;

        //find first end contour
        for(int jj=0;jj<c;jj++){
            if(endOfContour[jj]){
                fc=jj+1;
                jj=c;
            }
        }

        int x1,y1,x2=0,y2=0,x3=0,y3=0;

        x1=pX[0];
        y1=pY[0];

        if(this.debug)
            System.out.println(pX[0]+" "+pY[0]+" move to x1,y1="+x1+ ' ' +y1);

        current_path.moveTo(x1,y1);

        if(this.debug){
            System.out.println("first contour="+fc+"===================================="+pX[0]+ ' ' +pY[0]);
            //System.out.println("start="+x1+ ' ' +y1+" unitsPerEm="+unitsPerEm);
            //for (int i = 0; i <c-2; i++)
            //System.out.println(i+" "+convertX(pX[i],pY[i])+ ' ' +convertY(pX[i],pY[i])+ ' ' +onCurve[i]+ ' ' +endOfContour[i]+" raw="+pX[i]+ ' ' +pY[i]);

            //System.out.println("Move to "+x1+ ' ' +y1);

        }

        int xs=0,ys=0,lc=0;
        boolean isEnd=false;

        for (int j = 0; j <endIndex; j++) {

            int p=j%fc;
            int p1=(j+1)%fc;
            int p2=(j+2)%fc;
            int pm1=(j-1)%fc;

            /**special cases
             *
             *round up to last point at end
             *First point
             */
            if(j==0)
                pm1=fc-1;
            if(p1<lc)
                p1=p1+lc;
            if(p2<lc)
                p2=p2+lc;

            if(debug)
                System.out.println("points="+lc+ '/' +fc+ ' ' +pm1+ ' ' +p+ ' ' +p1+ ' ' +p2+" j="+j+" endOfContour[j]="+endOfContour[j]);

            //allow for wrap around on contour
            if(endOfContour[j]){
                isEnd=true;

                if(onCurve[fc]){
                    xs=pX[fc];
                    ys=pY[fc];
                }else{
                    xs=pX[j+1];
                    ys=pY[j+1];
                }

                //remember start point
                lc=fc;
                //find next contour
                for(int jj=j+1;jj<c;jj++){
                    if(endOfContour[jj]){
                        fc=jj+1;
                        jj=c;
                    }
                }

                if(debug)
                    System.out.println("End of contour. next="+j+ ' ' +fc+ ' ' +lc);

            }

            if(debug){
                if(j>0)
                    System.out.println("curves="+onCurve[p]+ ' ' +onCurve[p1]+ ' ' +onCurve[p2]+" EndOfContour j-1="+endOfContour[j-1]+" j="+endOfContour[j]+ " j+1=" +endOfContour[j+1]);
                else
                    System.out.println("curves="+onCurve[p]+ ' ' +onCurve[p1]+ ' ' +onCurve[p2]+" EndOfContour j="+endOfContour[j]+" j+1="+endOfContour[j+1]);
            }

            if(lc==fc && onCurve[p]){
                j=c;
                if(debug)
                    System.out.println("last 2 match");
            }else{

                if(debug)
                    System.out.println(fc+" "+pm1+ ' ' +p+ ' ' +p1+ ' ' +p2);

                if(onCurve[p] && onCurve[p1]){ //straight line
                    x3=pX[p1];
                    y3=pY[p1];
                    current_path.lineTo(x3,y3);
                    if(debug)
                        System.out.println(p+" pt,pt "+x3+ ' ' +y3+" (lineTo)");

                    isFirstDraw=false;
                    //curves
                }else if(j<(c-3) &&((fc-lc)>1 || fc==lc)){
                    boolean checkEnd=false;
                    if(onCurve[p] && !onCurve[p1] && onCurve[p2] ){ //2 points + control

                        x1=pX[p];
                        y1=pY[p];
                        x2=pX[p1];
                        y2=pY[p1];
                        x3=pX[p2];
                        y3=pY[p2];
                        j++;
                        checkEnd=true;
                        if(debug)
                            System.out.println(p+" pt,cv,pt "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);

                    }else if(onCurve[p] && !onCurve[p1] && !onCurve[p2]){ //1 point + 2 control

                        x1=pX[p];
                        y1=pY[p];
                        x2=pX[p1];
                        y2=pY[p1];
                        x3=midPt(pX[p1], pX[p2]);
                        y3=midPt(pY[p1], pY[p2]);
                        j++;

                        checkEnd=true;

                        if(debug)
                            System.out.println(p+" pt,cv,cv "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);

                    }else if(!onCurve[p] && !onCurve[p1] && (!endOfContour[p2] ||fc-p2==1)){ // 2 control + 1 point (final check allows for last point to complete loop

                        x1=midPt(pX[pm1], pX[p]);
                        y1=midPt(pY[pm1], pY[p]);
                        x2=pX[p];
                        y2=pY[p];

                        x3=midPt(pX[p], pX[p1]);
                        y3=midPt(pY[p], pY[p1]);
                        if(debug)
                            System.out.println(p+" cv,cv1 "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);


                    }else if(!onCurve[p] && onCurve[p1]){ // 1 control + 2 point

                        x1=midPt(pX[pm1], pX[p]);
                        y1=midPt(pY[pm1], pY[p]);
                        x2=pX[p];
                        y2=pY[p];
                        x3=pX[p1];
                        y3=pY[p1];
                        if(debug)
                            System.out.println(p+" cv,pt "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);
                    }

                    if(isFirstDraw){
                        current_path.moveTo(x1,y1);
                        isFirstDraw=false;

                        if(debug)
                            System.out.println("first draw move to "+x1+ ' ' +y1);

                    }

                    if (!(endOfContour[p] && p > 0 && endOfContour[p-1]))
                        current_path.curveTo(x1,y1,x2,y2,x3,y3);

                    if(debug)
                        System.out.println("curveto "+x1+ ' ' +y1+ ' ' +x2+ ' ' +y2+ ' ' +x3+ ' ' +y3);

                    /**if end after curve, roll back so we pick up the end*/
                    if( checkEnd && endOfContour[j]){

                        isEnd=true;

                        xs=pX[fc];
                        ys=pY[fc];
                        //remmeber start point
                        lc=fc;
                        //find next contour
                        for(int jj=j+1;jj<c;jj++){
                            if(endOfContour[jj]){
                                fc=jj+1;
                                jj=c;
                            }
                        }

                        if(debug)
                            System.out.println("Curve");
                    }
                }

                if (endOfContour[p])
                    current_path.closePath();

                if(debug)
                    System.out.println("x2 "+xs+ ' ' +ys+ ' ' +isEnd);


                if(isEnd){
                    current_path.moveTo(xs,ys);
                    isEnd=false;
                    if(debug)
                        System.out.println("Move to "+xs+ ' ' +ys);
                }

                if(debug){
                    try{
                        if(img==null)
                            img=new java.awt.image.BufferedImage(800,800, java.awt.image.BufferedImage.TYPE_INT_ARGB);

                        Graphics2D g2= img.createGraphics();
                        g2.setColor(java.awt.Color.green);
                        g2.draw(current_path);

                        final String key= String.valueOf(p);

                        org.jpedal.gui.ShowGUIMessage.showGUIMessage(key,img,key);

                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }

        /**
         * store so we can draw glyf as set of paths
         */
        paths.addElement(current_path);

        if(debug)
            System.out.println("Ends at "+x1+ ' ' +y1+" x="+minX+ ',' +maxX+" y="+minY+ ',' +maxY+" glyph x="+compMinX+ ',' +compMaxX+" y="+compMinY+ ',' +compMaxY);

    }

    java.awt.image.BufferedImage img=null;


    static private int midPt(int a, int b) {
    return a + (b - a)/2;
  }
 
//  /**convert to 1000 size*/
//  final private int convertX(int x,int y){
//
//
//        if(!isComposite) {
//      if (!useHinting)
//                return (int)(x/unitsPerEm);
//            else
//                return x;
//        } else {
//            //This code seems to match the spec more closely, but doesn't seem to make any difference...
//            //It's also wildly inefficient, so rewrite it if you're going to turn it on!
////            double absA = xscale;
////            if (absA < 0)
////                absA = -absA;
////            double absB = scale01;
////            if (absB < 0)
////                absB = -absB;
////            double absC = scale10;
////            if (absC < 0)
////                absC = -absC;
////
////            double m = absA;
////            if (absB > m)
////                m = absB;
////            if (absA - absC <= 33d/65536 && absA - absC >= -33d/65536)
////                m = 2*m;
////
////      return (int)((m*(((x * (xscale/m)) + (y * (scale10/m)))+xtranslate))/unitsPerEm);
//            if (!useHinting)
//                return (int)((((x * xscale) + (y * scale10))+xtranslate)/unitsPerEm);
//            else
//                return (int)((((x * xscale) + (y * scale10))+xtranslate));
//        }
//  }
//
//  /**convert to 1000 size*/
//  final private int convertY(int x,int y){
//
//        if(!isComposite) {
//      if (!useHinting)
//                return (int)(y/unitsPerEm);
//            else
//                return y;
//        } else {
//            //This code seems to match the spec more closely, but doesn't seem to make any difference...
//            //It's also wildly inefficient, so rewrite it if you're going to turn it on!
////            double absC = scale10;
////            if (absC < 0)
////                absC = -absC;
////            double absD = yscale;
////            if (absD < 0)
////                absD = -absD;
////
////            double n = absC;
////            if (absD > n)
////                n = absD;
////            if (absC - absD <= 33d/65536 && absC - absD >= -33d/65536)
////                n = 2*n;
////
////            return (int)((n*(((x * (scale01/n)) + (y * (yscale/n)))+ytranslate))/unitsPerEm);//+30;
//            if (!useHinting)
//                return (int)((((x * scale01) + (y * yscale))+ytranslate)/unitsPerEm);
//            else
//                return (int)((((x * scale01) + (y * yscale))+ytranslate));
//        }
//  }


  /* (non-Javadoc)
   * @see org.jpedal.fonts.PdfGlyph#getWidth()
   */
  public float getmaxWidth() {
   
    return 0;
  }

  /* (non-Javadoc)
     * @see org.jpedal.fonts.PdfGlyph#getmaxHeight()
     */
    public int getmaxHeight() {
        return 0;
    }

  /* (non-Javadoc)
   * @see org.jpedal.fonts.PdfGlyph#lockColors(java.awt.Color, java.awt.Color)
   */
  public void lockColors(PdfPaint strokeColor, PdfPaint nonstrokeColor) {

  }

  /* (non-Javadoc)
   * @see org.jpedal.fonts.PdfGlyph#ignoreColors()
   */
  public boolean ignoreColors() {
    return false;
  }
 


  public void flushArea() {
    glyphShape=null;
  }

  public void setWidth(float width) {
   
  }

    public int getFontBB(int type) {

        if(isComposite){
        if(type== PdfGlyph.FontBB_X)
            return compMinX;
        else if(type== PdfGlyph.FontBB_Y)
            return compMinY;
        else if(type== PdfGlyph.FontBB_WIDTH)
            return compMaxX;
        else if(type== PdfGlyph.FontBB_HEIGHT)
            return compMaxY;
        else
            return 0;
        }else{
            if(type== PdfGlyph.FontBB_X)
            return minX;
        else if(type== PdfGlyph.FontBB_Y)
            return minY;
        else if(type== PdfGlyph.FontBB_WIDTH)
            return maxX;
        else if(type== PdfGlyph.FontBB_HEIGHT)
            return maxY;
        else
            return 0;
        }
    }

    public void setStrokedOnly(boolean b) {
        //not used here
    }

    //use by TT to handle broken TT fonts
    public boolean containsBrokenData() {
        return this.containsBrokenGlyfData; 
    }

}
TOP

Related Classes of org.jpedal.fonts.tt.TTGlyph

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.