All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.fonts.tt.TTGlyph Maven / Gradle / Ivy

There is a newer version: 20151002
Show newest version
/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2017 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
     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.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
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 org.jpedal.fonts.tt.hinting.TTVM;
import org.jpedal.io.PathSerializer;
import org.jpedal.objects.GraphicsState;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.repositories.Vector_Path;

public class TTGlyph extends BaseTTGlyph implements Serializable{

    /** only used for debugging so make static */
    static java.awt.image.BufferedImage img;

    Area glyphShape;
    
    private boolean hasEndCurve;

    /**
     * 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(final 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(final ObjectOutput os) throws IOException {
        if((paths!=null)){

            final 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++) {
                final PathIterator pathIterator = generalPaths[i].getPathIterator(new AffineTransform());
                PathSerializer.serializePath(os, pathIterator);
            }

        }
    }


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

        super(currentGlyf, glyfTable, currentHmtx, idx, unitsPerEm,  baseFontName);
        
        /**/
        if(debug){
            try{
                System.out.println("debugging"+idx);
                final java.awt.image.BufferedImage img=new java.awt.image.BufferedImage(700,700, java.awt.image.BufferedImage.TYPE_INT_ARGB);

                final Graphics2D gg2= img.createGraphics();

                for(int jj=0;jj1 || 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])) {    
                        hasEndCurve=true;
                        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;jjii) {
                newPos -= (ii - start + 1);
            }
            pX[oldPos]=old_pX[newPos];
            pY[oldPos]=old_pY[newPos];
            onCurve[oldPos]=old_onCurve[newPos];

        }
    }




    //	/**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));
    //        }
    //	}

    public void flushArea() {
        glyphShape=null;
    }

    @Override
    void clearPaths() {
        paths.clear();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy