Skip to content

Commit

Permalink
Fix ROS finding for CID Font detection
Browse files Browse the repository at this point in the history
  • Loading branch information
MaximPlusov committed Mar 20, 2024
1 parent 484d14b commit 7f7e009
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 27 deletions.
7 changes: 1 addition & 6 deletions src/main/java/org/verapdf/pd/font/cff/CFFCIDFontProgram.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,8 @@ public class CFFCIDFontProgram extends CFFFontBaseParser implements FontProgram
CFFCIDFontProgram(SeekableInputStream stream, CFFIndex definedNames, CFFIndex globalSubrs,
long topDictBeginOffset, long topDictEndOffset, CMap externalCMap,
boolean isSubset) {
super(stream);
this.definedNames = definedNames;
this.globalSubrs = globalSubrs;
this.topDictBeginOffset = topDictBeginOffset;
this.topDictEndOffset = topDictEndOffset;
super(stream, definedNames, globalSubrs, topDictBeginOffset, topDictEndOffset, isSubset);
this.externalCMap = externalCMap;
this.isSubset = isSubset;
}

/**
Expand Down
31 changes: 30 additions & 1 deletion src/main/java/org/verapdf/pd/font/cff/CFFFontBaseParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
*
* @author Sergey Shemyakov
*/
abstract class CFFFontBaseParser extends CFFFileBaseParser {
class CFFFontBaseParser extends CFFFileBaseParser {

private static final Logger LOGGER = Logger.getLogger(CFFFontBaseParser.class.getCanonicalName());

Expand Down Expand Up @@ -72,13 +72,39 @@ abstract class CFFFontBaseParser extends CFFFileBaseParser {
//Subrs
protected long subrsOffset = -1;

private boolean isContainsROS = false;

public CFFFontBaseParser(SeekableInputStream source) {
super(source);
stack = new ArrayList<>(48);
this.charStringType = 2;
this.charSetOffset = 0; // default
}

public CFFFontBaseParser(SeekableInputStream stream, CFFIndex definedNames, CFFIndex globalSubrs,
long topDictBeginOffset, long topDictEndOffset, boolean isSubset) {
this(stream);
this.definedNames = definedNames;
this.globalSubrs = globalSubrs;
this.topDictBeginOffset = topDictBeginOffset;
this.topDictEndOffset = topDictEndOffset;
this.isSubset = isSubset;
}

protected boolean isContainsROS() {
try {
this.source.seek(topDictBeginOffset);
while (this.source.getOffset() < topDictEndOffset) {
readTopDictUnit();
}
if (isContainsROS) {
return true;
}
} catch (IOException ignored) {
}
return false;
}

protected void readTopDictUnit() throws IOException {
try {
int next = this.source.peek();
Expand Down Expand Up @@ -125,6 +151,9 @@ protected void readTopDictUnit() throws IOException {
this.stack.get(this.stack.size() - 1).getInteger();
this.stack.clear();
break;
case 30:
this.isContainsROS = true;
break;
default:
readTopDictTwoByteOps(next);
}
Expand Down
25 changes: 11 additions & 14 deletions src/main/java/org/verapdf/pd/font/cff/CFFFontProgram.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void parseFont() throws IOException {
}
this.definedNames = this.readIndex();
CFFIndex globalSubrs = this.readIndex();
if (isCIDFont(top.get(0))) {
if (isCIDFont(top, globalSubrs, topOffset)) {
font = new CFFCIDFontProgram(this.source, this.definedNames, globalSubrs,
topOffset + top.getOffset(0) - 1 + top.getOffsetShift(),
topOffset + top.getOffset(1) - 1 + top.getOffsetShift(),
Expand All @@ -91,9 +91,10 @@ public void parseFont() throws IOException {
}
}

private boolean isCIDFont(byte[] topDict) {
private boolean isCIDFont(CFFIndex top, CFFIndex globalSubrs, long topOffset) {
try {
byte rosOffset;
byte[] topDict = top.get(0);
int supplementFirstByte = topDict[4] & 0xFF; // checking if first operator is really ROS
if (supplementFirstByte < 247 && supplementFirstByte > 31) {
rosOffset = 5;
Expand All @@ -104,27 +105,23 @@ private boolean isCIDFont(byte[] topDict) {
} else if (supplementFirstByte == 29) {
rosOffset = 9;
} else {
return isContainsROS(topDict);
return isContainsROS(top, globalSubrs, topOffset);
}
if (topDict[rosOffset] == 12 && topDict[rosOffset + 1] == 30) {
isCIDFont = true;
return true;
}
return isContainsROS(topDict);
return isContainsROS(top, globalSubrs, topOffset);
} catch (ArrayIndexOutOfBoundsException ex) {
return isContainsROS(topDict);
return isContainsROS(top, globalSubrs, topOffset);
}
}

private boolean isContainsROS(byte[] topDict) {
for (int rosOffset = 0; rosOffset < topDict.length - 2; rosOffset++) {
if (topDict[rosOffset] == 12 && topDict[rosOffset + 1] == 30) {
LOGGER.log(Level.WARNING, "The Top DICT does not begin with ROS operator");
isCIDFont = true;
return true;
}
}
return false;
private boolean isContainsROS(CFFIndex top, CFFIndex globalSubrs, long topOffset) {
return new CFFFontBaseParser(this.source, this.definedNames, globalSubrs,
topOffset + top.getOffset(0) - 1 + top.getOffsetShift(),
topOffset + top.getOffset(1) - 1 + top.getOffsetShift(),
this.isSubset).isContainsROS();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,10 @@ public class CFFType1FontProgram extends CFFFontBaseParser implements FontProgra
CFFType1FontProgram(SeekableInputStream stream, CFFIndex definedNames, CFFIndex globalSubrs,
long topDictBeginOffset, long topDictEndOffset,
CMap externalCMap, boolean isSubset) {
super(stream);
super(stream, definedNames, globalSubrs, topDictBeginOffset, topDictEndOffset, isSubset);
encodingOffset = 0;
encoding = new int[256];
this.definedNames = definedNames;
this.globalSubrs = globalSubrs;
this.topDictBeginOffset = topDictBeginOffset;
this.topDictEndOffset = topDictEndOffset;
this.externalCMap = externalCMap;
this.isSubset = isSubset;
fontMatrix = new float[6];
System.arraycopy(DEFAULT_FONT_MATRIX, 0, this.fontMatrix, 0,
DEFAULT_FONT_MATRIX.length);
Expand Down

0 comments on commit 7f7e009

Please sign in to comment.