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

org.jpedal.fonts.glyph.T1GlyphFactory Maven / Gradle / Ivy

/*
 * ===========================================
 * 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


 *
 * ---------------
 * T1GlyphFactory.java
 * ---------------
 */
package org.jpedal.fonts.glyph;

import java.awt.geom.GeneralPath;

import org.jpedal.external.ExternalHandlers;
import org.jpedal.fonts.tt.FontFile2;
import org.jpedal.fonts.tt.Glyf;
import org.jpedal.fonts.tt.Hmtx;
import org.jpedal.fonts.tt.hinting.TTVM;
import org.jpedal.utils.repositories.Vector_Float;
import org.jpedal.utils.repositories.Vector_Int;
import org.jpedal.utils.repositories.Vector_Path;

/**
 * decodes the T1 glyph into a set of paths wrapped around a glyph
 */
public class T1GlyphFactory implements GlyphFactory {

    private static JavaFXSupport javaFXSupport;


    public T1GlyphFactory(final boolean useFX) {
        this.useFX = useFX;

        if (useFX) {
            javaFXSupport = ExternalHandlers.getFXHandler();
        }
    }

    final boolean useFX;

    private static final float zero = 0f;

    /**
     * we tell user we have not used some shapes only ONCE
     */
    private Vector_Float shape_primitive_x2 = new Vector_Float(1000);
    private Vector_Float shape_primitive_y = new Vector_Float(1000);

    /**
     * store shape currently being assembled
     */
    private Vector_Int shape_primitives = new Vector_Int(1000);

    private Vector_Float shape_primitive_x3 = new Vector_Float(1000);
    private Vector_Float shape_primitive_y3 = new Vector_Float(1000);

    private Vector_Float shape_primitive_y2 = new Vector_Float(1000);
    private Vector_Float shape_primitive_x = new Vector_Float(1000);

    protected static final int H = 3;
    protected static final int L = 2;

    /**
     * flags for commands used
     */
    protected static final int M = 1;
    protected static final int C = 5;

    /**
     * vertical positioning and scaling
     */
    private float ymin;
    private int leftSideBearing;


    /* (non-Javadoc)
     * @see org.jpedal.fonts.GlyphFactory#getGlyph()
     */
    @Override
    public PdfGlyph getGlyph() {
        if (useFX) {
            return getFXGlyph();
        } else {
            return getSwingGlyph();
        }

    }

    /* (non-Javadoc)
     * @see org.jpedal.fonts.GlyphFactory#getGlyph()
     */
    private PdfGlyph getSwingGlyph() {

        //initialise cache
        final Vector_Path cached_current_path = new Vector_Path(100);

        //create the shape - we have to do it this way
        //because we get the WINDING RULE last and we need it
        //to initialise the shape
        GeneralPath current_path = new GeneralPath(GeneralPath.WIND_NON_ZERO);
        current_path.moveTo(0, 0);
        //init points
        final float[] x = shape_primitive_x.get();
        final float[] y = shape_primitive_y.get();
        final float[] x2 = shape_primitive_x2.get();
        final float[] y2 = shape_primitive_y2.get();
        final float[] x3 = shape_primitive_x3.get();
        final float[] y3 = shape_primitive_y3.get();
        int i = 0;
        final int end = shape_primitives.size() - 1;
        final int[] commands = shape_primitives.get();


        //loop through commands and add to glyph
        while (i < end) {

            //System.out.println(i+" "+x+" "+y);
            switch (commands[i]) {
                case L:
                    current_path.lineTo(x[i], y[i] - ymin);
                    break;
                case H:
                    current_path.closePath();
                    //save for later use
                    cached_current_path.addElement(current_path);
                    current_path = new GeneralPath(GeneralPath.WIND_NON_ZERO);
                    current_path.moveTo(0, 0);
                    break;
                case M:
                    current_path.moveTo(x[i], y[i] - ymin);
                    break;
                case C:
                    current_path.curveTo(x[i], y[i] - ymin,
                            x2[i], y2[i] - ymin,
                            x3[i], y3[i] - ymin);
                    break;
                default:
                    break;
            }

            i++;
        }

        //now garbage collect arrays as not needed
        shape_primitive_x2.reuse();
        shape_primitive_y.reuse();
        shape_primitives.reuse();
        shape_primitive_x3.reuse();
        shape_primitive_y3.reuse();
        shape_primitive_y2.reuse();
        shape_primitive_x.reuse();

        return new T1Glyph(cached_current_path);
    }

    /* (non-Javadoc)
     * @see org.jpedal.fonts.GlyphFactory#getGlyph()
     */
    private PdfGlyph getFXGlyph() {

        //init points
        final float[] x = shape_primitive_x.get();
        final float[] y = shape_primitive_y.get();
        final float[] x2 = shape_primitive_x2.get();
        final float[] y2 = shape_primitive_y2.get();
        final float[] x3 = shape_primitive_x3.get();
        final float[] y3 = shape_primitive_y3.get();
        final int end = shape_primitives.size() - 1;
        final int[] commands = shape_primitives.get();
        
        /*reset - we need new object as it otherwise we will pass link
         to array we then flush*/
        shape_primitive_x2 = new Vector_Float(1000);
        shape_primitive_y = new Vector_Float(1000);
        shape_primitives = new Vector_Int(1000);

        shape_primitive_x3 = new Vector_Float(1000);
        shape_primitive_y3 = new Vector_Float(1000);

        shape_primitive_y2 = new Vector_Float(1000);
        shape_primitive_x = new Vector_Float(1000);

        if (javaFXSupport == null) {
            return null;
        } else {
            return javaFXSupport.getGlyph(x, y, x2, y2, x3, y3, ymin, end, commands);
        }
    }

    /////////////////////////////////////////////////////////////////////////

    /**
     * end a shape, storing info for later
     */
    @Override
    public final void closePath() {
        shape_primitives.addElement(H);

        //add empty values
        shape_primitive_x.addElement(0);
        shape_primitive_y.addElement(0);
        shape_primitive_x2.addElement(0);
        shape_primitive_y2.addElement(0);
        shape_primitive_x3.addElement(0);
        shape_primitive_y3.addElement(0);
    }
    //////////////////////////////////////////////////////////////////////////

    /**
     * add a curve to the shape
     */
    @Override
    public final void curveTo(final float x, final float y, final float x2, final float y2, final float x3, final float y3) {
        shape_primitives.addElement(C);
        shape_primitive_x.addElement(x);
        shape_primitive_y.addElement(y);

        //add empty values to keep in sync
        //add empty values
        shape_primitive_x2.addElement(x2);
        shape_primitive_y2.addElement(y2);
        shape_primitive_x3.addElement(x3);
        shape_primitive_y3.addElement(y3);
    }


    //////////////////////////////////////////////////////////////////////////

    /**
     * add a line to the shape
     */
    @Override
    public final void lineTo(final float x, final float y) {
        shape_primitives.addElement(L);
        shape_primitive_x.addElement(x);
        shape_primitive_y.addElement(y);

        //add empty values to keep in sync
        //add empty values

        shape_primitive_x2.addElement(zero);
        shape_primitive_y2.addElement(zero);
        shape_primitive_x3.addElement(zero);
        shape_primitive_y3.addElement(zero);
    }


    /**
     * start a shape by creating a shape object
     */
    @Override
    public final void moveTo(final float x, final float y) {
        shape_primitives.addElement(M);
        shape_primitive_x.addElement(x);
        shape_primitive_y.addElement(y);

        //add empty values
        shape_primitive_x2.addElement(0);
        shape_primitive_y2.addElement(0);
        shape_primitive_x3.addElement(0);
        shape_primitive_y3.addElement(0);
    }

    /**
     * set ymin - ie vertical kern
     */
    @Override
    public void setYMin(final float ymin) {

        this.ymin = ymin;
        //this.ymax=ymax;

    }

    @Override
    public int getLSB() {
        return leftSideBearing;
    }

    @Override
    public boolean useFX() {
        return useFX;
    }

    @Override
    public PdfGlyph getGlyph(final Glyf currentGlyf, final FontFile2 fontTable, final Hmtx currentHmtx, final int idx, final float unitsPerEm, final TTVM vm, final String baseFontName) {

        if (javaFXSupport != null) {
            return javaFXSupport.getGlyph(currentGlyf, fontTable, currentHmtx, idx, unitsPerEm, vm, baseFontName);
        } else {
            return null;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy