
org.jpedal.fonts.tt.CMAP 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-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;i0){
// 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 - 2025 Weber Informatics LLC | Privacy Policy