org.jpedal.fonts.tt.CMAP Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenViewerFX Show documentation
Show all versions of OpenViewerFX Show documentation
An Open Source JavaFX PDF Viewer
/*
* ===========================================
* 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;
}
}