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

org.jpedal.fonts.tt.CMAP 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-2016 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


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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.jpedal.fonts.StandardFonts;
import org.jpedal.utils.LogWriter;

public class CMAP extends Table {

    protected int[][] glyphIndexToChar;
    
    private boolean remapType4;
    
    private boolean hasFormatZero;

    private int[] glyphToIndex;

    //flag 6 and use if not able to map elsewhere
    private boolean hasSix;

    //flag 4 
    private boolean hasFormat4;
    private boolean hasFormat6;

    private int lastFormat4Found = -1;

    //used by format 6
    private int firstCode	=	-1;
    private int entryCount	=	-1;

    //used by format 4
    private int segCount;

    /**which type of mapping to use*/
    private int fontMapping;

    //used by format 4
    protected int[] endCode;
    protected int[] startCode;
    protected int[] idDelta;
    protected int[] idRangeOffset;
    protected int[] glyphIdArray;
    private int[] f6glyphIdArray;
    private int[] offset;

    //used by Format 12
    int nGroups;
    private int[] startCharCode;
    private int[] endCharCode;
    private int[] startGlyphCode;

    /**CMap format used -1 shows not set*/
    protected int[] CMAPformats,CMAPlength,CMAPlang,CMAPsegCount,CMAPsearchRange, CMAPentrySelector,CMAPrangeShift,CMAPreserved;

    /*Platform-specific ID list*/
//	private static String[] PlatformSpecificID={"Roman","Japanese","Traditional Chinese","Korean",
//			"Arabic","Hebrew","Greek","Russian",
//			"RSymbol","Devanagari","Gurmukhi","Gujarati",
//			"Oriya","Bengali","Tamil","Telugu",
//			"Kannada","Malayalam","Sinhalese","Burmese",
//			"Khmer","Thai","Laotian","Georgian",
//			"Armenian","Simplified Chinese","Tibetan","Mongolian",
//			"Geez","Slavic","Vietnamese","Sindhi","(Uninterpreted)"};
//
    /*Platform-specific ID list*/
    //private static String[] PlatformIDName={"Unicode","Macintosh","Reserved","Microsoft"};

    /**shows which encoding used*/
    protected int[] platformID;

    private static final Map exceptions;

    /*set up differences from Mac Roman*/
    static {

        exceptions=new HashMap();

        final String[] keys={"notequal","infinity","lessequal","greaterequal",
                "partialdiff","summation","product","pi",
                "integral","Omega","radical","approxequal",
                "Delta","lozenge","Euro","apple"};
         
        final int[] values={173,176,178,179,
                182,183,184,185,
                186,189,195,197,
                198,215,219,240};
        
         for(int i=0;i CMAPlength[j]) {
                CMAPlength[j] = CMAPlength[lastFormat4Found];
                CMAPsegCount[j] = CMAPsegCount[lastFormat4Found];
                CMAPsearchRange[j]=CMAPsearchRange[lastFormat4Found]; //searchrange
                CMAPentrySelector[j]=CMAPentrySelector[lastFormat4Found];//entrySelector
                CMAPrangeShift[j]=CMAPrangeShift[lastFormat4Found];//rangeShift
                return;
            } else if(CMAPlength[lastFormat4Found] < CMAPlength[j]){
                CMAPlength[lastFormat4Found] = CMAPlength[j] ;
                CMAPsegCount[lastFormat4Found] = CMAPsegCount[j] ;
                CMAPsearchRange[lastFormat4Found] = CMAPsearchRange[j]; //searchrange
                CMAPentrySelector[lastFormat4Found] = CMAPentrySelector[j];//entrySelector
                CMAPrangeShift[lastFormat4Found] = CMAPrangeShift[j];//rangeShift
            }
        }
        
        lastFormat4Found = j;
        hasFormat4= true;
        
        //read tables and initialise size of arrays
        endCode = new int[segCount];
        for (int i = 0; i < segCount; i++) {
            endCode[i] = currentFontFile.getNextUint16();
        }
        CMAPreserved[j]=currentFontFile.getNextUint16(); //reserved (should be zero)
        startCode = new int[segCount];
        for (int i = 0; i < segCount; i++) {
            startCode[i] = currentFontFile.getNextUint16();
        }
        idDelta = new int[segCount];
        for (int i = 0; i < segCount; i++) {
            idDelta[i] = currentFontFile.getNextUint16();
        }
        idRangeOffset = new int[segCount];
        for (int i = 0; i < segCount; i++) {
            idRangeOffset[i] = currentFontFile.getNextUint16();
        }
        /*create offsets*/
        offset = new int[segCount];
        int diff,cumulative=0;
        for (int i = 0; i < segCount; i++) {
      
            if(idDelta[i]==0){// && startCode[i]!=endCode[i]){
                offset[i]=cumulative;
                diff=1+endCode[i]-startCode[i];
                
                //fixes bug in mapping theSansOffice tff font
                if(startCode[i]==endCode[i] && idRangeOffset[i]==0) {
                    diff = 0;
                }
                
                cumulative += diff;
            }
        }
        
        // glyphIdArray at end
        final int count = (CMAPlength[j] -16-(segCount*8)) / 2;
        glyphIdArray = new int[count];
        for (int i = 0; i < count; i++){
            glyphIdArray[i] =currentFontFile.getNextUint16();
        }
    }

    private void readFormat6Table(final FontFile2 currentFontFile) {
        hasFormat6 = true;
        firstCode=currentFontFile.getNextUint16();
        entryCount=currentFontFile.getNextUint16();
        
        f6glyphIdArray = new int[firstCode+entryCount];
        for(int jj=0;jj255) {
                index = 0;
            }

            value= glyphIndexToChar[formatToUse][index];
            if(value==0 && index2!=-1) {
                value = glyphIndexToChar[formatToUse][index2];
            }

            

        }else if(format==4){

            value = getFormat4Value(index, value);

            //hack for odd value in customer file
            if(value==-1){

                if(index>0xf000) {
                    value = getFormat4Value(index - 0xf000, value);
                } else {
                    value = getFormat4Value(index + 0xf000, value);
                }

            }
          
            //see 18113 fixes ligatures on page
            if(value==-1){
                value = getFormat4Value(rawIndex+ 0xf000, value);
            }
        }else if(format==12){
            value = getFormat12Value(index, debugMapping, value);
        }

        //second attempt if no value found
        if(value==-1 && hasSix){
            index=rawIndex;
            format=6;
        }

        if(format==6){

            if(fontEncoding!=1){
                index=StandardFonts.lookupCharacterIndex(glyph,StandardFonts.MAC);
            }

            if(index>=f6glyphIdArray.length) {
                value = 0;
            } else {
                value = f6glyphIdArray[index];
            }
        }

        if(debugMapping) {
            System.out.println("returns " + value + ' ' + this);
        }

        return value;
    }

    /**
     * lookup tables similar to format 4
     * see https://developer.apple.com/fonts/TTRefMan/RM06/Chap6cmap.html
     */
    private int getFormat12Value(final int index, final boolean debugMapping, int value) {

        /*
         * cycle through tables and then add offset to Glyph start
         */
        for (int i = 0; i < nGroups ; i++) {

            if(debugMapping) {
                System.out.println("table=" + i + " start=" + startCharCode[i] + ' ' + index +
                        " end=" + endCharCode[i] + " glypgStartCode[i]=" + startGlyphCode[i]);
            }

            if (endCharCode[i] >= index && startCharCode[i] <= index){

                value=startGlyphCode[i]+index-startCharCode[i];
                i=nGroups; //exit loop
            }
        }

        return value;
    }

    private int getFormat4Value(final int index,int value) {

        final boolean debugMapping=false;
        for (int i = 0; i < segCount; i++) {

            if(debugMapping) {
                System.out.println("Segtable=" + i + " start=" + startCode[i] + ' ' + index +
                        " end=" + endCode[i] + " idRangeOffset[i]=" + idRangeOffset[i] +
                        " offset[i]=" + offset[i] + " idRangeOffset[i]=" + idRangeOffset[i] + " idDelta[i]=" + idDelta[i]);
            }

            if (endCode[i] >= index && startCode[i] <= index){

                final int idx ;
                if (idRangeOffset[i] == 0) {

                    if(debugMapping) {
                        System.out.println("xxx=" + (idDelta[i] + index));
                    }

                    value= (idDelta[i] + index) % 65536;

                    i=segCount;
                }else{

                    idx= offset[i]+(index - startCode[i]);
                    if (idx < glyphIdArray.length) {
                        value=glyphIdArray[idx];
                    }
                    
                    if(debugMapping) {
                        System.out.println("value=" + value + " idx=" +
                                idx + " glyphIdArrays=" + glyphIdArray[0] + ' ' +
                                glyphIdArray[1] + ' ' + glyphIdArray[2] + " offset[i]=" + offset[i] +
                                " index=" + index + " startCode[" + i + "]=" + startCode[i] + " i=" + i);
                    }

                    i=segCount;

                }
            }
        }

        return value;
    }

    /**
     * work out correct CMAP table to use.
     */
    public void setEncodingToUse(final boolean hasEncoding, final int fontEncoding, final boolean isCID) {

        final boolean encodingDebug=false;
       
        this.fontEncoding=fontEncoding;
        
        if(encodingDebug) {
            System.out.println(this + "hasEncoding=" + hasEncoding + " fontEncoding=" + fontEncoding + " isCID=" + isCID);
        }

        formatToUse=-1;

        final int count=platformID.length;

        /*case 1 */
        for(int i=0;i buildCharStringTable() {

        final Map glyfValues=new HashMap();
//      for(int i : glyphToIndex){

//      if(i>0){
//          glyfValues.put(glyphToIndex[i],i);
//      //System.out.println("i=" + i + " " + StandardFonts.getUnicodeChar(encodingToUse, i));
//      }
//  }        
        if(hasFormat4){
            final ArrayListlist4 = new ArrayList();
            for(int z=0;z "+f6glyphIdArray[firstCode+z]);
                glyfValues.put(firstCode+z,f6glyphIdArray[firstCode+z]);
            }
        }
        else{
            for(int z=0;z0){
                    glyfValues.put(glyphToIndex[z],z);
                }
            }
        }

        return glyfValues;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy