Skip to content

Commit c62f83b

Browse files
committed
OTF: Support GposLookupType7 format (subtable format 2)
DEVSIX-4631
1 parent 5c136f5 commit c62f83b

17 files changed

+764
-129
lines changed

io/src/main/java/com/itextpdf/io/LogMessageConstant.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ public final class LogMessageConstant {
110110
public static final String FONT_SUBSET_ISSUE = "Font subset issue. Full font will be embedded.";
111111
public static final String FORBID_RELEASE_IS_SET = "ForbidRelease flag is set and release is called. Releasing will not be performed.";
112112
public static final String FORM_FIELD_WAS_FLUSHED = "A form field was flushed. There's no way to create this field in the AcroForm dictionary.";
113+
public static final String GPOS_LOOKUP_SUBTABLE_FORMAT_NOT_SUPPORTED =
114+
"Subtable format {0} of GPOS Lookup Type {1} is not supported yet";
113115
public static final String GRAPHICS_STATE_WAS_DELETED = "Graphics state is always deleted after event dispatching. If you want to preserve it in renderer info, use preserveGraphicsState method after receiving renderer info.";
114116
public static final String IF_PATH_IS_SET_VERTICES_SHALL_NOT_BE_PRESENT = "If Path key is set, Vertices key shall not be present. Remove Vertices key before setting Path";
115117
public static final String IMAGE_HAS_AMBIGUOUS_SCALE = "The image cannot be auto scaled and scaled by a certain parameter simultaneously";
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2020 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.io.font.otf;
24+
25+
public abstract class ContextualPositionRule extends ContextualRule {
26+
private static final long serialVersionUID = 1629646447219066484L;
27+
28+
/**
29+
* Retrieves the position lookup records. Each record specifies a position in the context glyph
30+
* sequence and a LookupListIndex to the position lookup that is applied at that position.
31+
*
32+
* @return an array of {@link PosLookupRecord}.
33+
*/
34+
public abstract PosLookupRecord[] getPosLookupRecords();
35+
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2020 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.io.font.otf;
24+
25+
public abstract class ContextualPositionTable extends ContextualTable<ContextualPositionRule> {
26+
private static final long serialVersionUID = -5767338869523894047L;
27+
28+
protected ContextualPositionTable(OpenTypeFontTableReader openReader, int lookupFlag) {
29+
super(openReader, lookupFlag);
30+
}
31+
32+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2020 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.io.font.otf;
24+
25+
import java.io.Serializable;
26+
27+
public abstract class ContextualRule implements Serializable {
28+
private static final long serialVersionUID = -9013175115747848532L;
29+
30+
/**
31+
* Gets the length of the context glyph sequence defined by this rule
32+
* @return length of the context
33+
*/
34+
public abstract int getContextLength();
35+
36+
/**
37+
* Checks if glyph line element matches element from input sequence of the rule.
38+
* <br><br>
39+
* NOTE: rules do not contain the first element of the input sequence, the first element is defined by rule
40+
* position in substitution table. Therefore atIdx shall not be 0.
41+
*
42+
* @param glyphId glyph code id
43+
* @param atIdx index in the rule sequence. Shall be: 0 &lt; atIdx &lt; {@link ContextualSubstRule#getContextLength}
44+
* @return {@code true} if glyph matches element
45+
*/
46+
public abstract boolean isGlyphMatchesInput(int glyphId, int atIdx);
47+
48+
/**
49+
* Gets the length of the lookahead context glyph sequence defined by this rule
50+
* @return length of the lookahead context
51+
*/
52+
public int getLookaheadContextLength() {
53+
return 0;
54+
}
55+
56+
/**
57+
* Gets the length of the backtrack context glyph sequence defined by this rule
58+
* @return length of the backtrack context
59+
*/
60+
public int getBacktrackContextLength() {
61+
return 0;
62+
}
63+
64+
/**
65+
* Checks if glyph line element matches element from lookahead sequence of the rule.
66+
*
67+
* @param glyphId glyph code id
68+
* @param atIdx index in rule sequence. Shall be: 0 &lt;= atIdx &lt; {@link ContextualSubstRule#getLookaheadContextLength()}
69+
* @return {@code true} if glyph matches element from lookahead sequence
70+
*/
71+
public boolean isGlyphMatchesLookahead(int glyphId, int atIdx) {
72+
return false;
73+
}
74+
75+
/**
76+
* Checks if glyph line element matches element from backtrack sequence of the rule.
77+
*
78+
* @param glyphId glyph code id
79+
* @param atIdx index in rule sequence. Shall be: 0 &lt;= atIdx &lt; {@link ContextualSubstRule#getBacktrackContextLength()}
80+
* @return {@code true} if glyph matches element from backtrack sequence
81+
*/
82+
public boolean isGlyphMatchesBacktrack(int glyphId, int atIdx) {
83+
return false;
84+
}
85+
}

io/src/main/java/com/itextpdf/io/font/otf/ContextualSubTable.java

Lines changed: 8 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -43,83 +43,23 @@ This file is part of the iText (R) project.
4343
*/
4444
package com.itextpdf.io.font.otf;
4545

46-
import java.io.Serializable;
47-
import java.util.List;
48-
49-
public abstract class ContextualSubTable implements Serializable {
46+
public abstract class ContextualSubTable extends ContextualTable<ContextualSubstRule> {
5047

5148
private static final long serialVersionUID = 1802216575331243298L;
52-
protected OpenTypeFontTableReader openReader;
53-
protected int lookupFlag;
5449

5550
protected ContextualSubTable(OpenTypeFontTableReader openReader, int lookupFlag) {
56-
this.openReader = openReader;
57-
this.lookupFlag = lookupFlag;
51+
super(openReader, lookupFlag);
5852
}
5953

60-
/**
61-
* Gets a most preferable context rule that matches the line at current position. If no matching context rule is found,
62-
* it returns null.
63-
* <br><br>
64-
* NOTE: if matching context rule is found, the <code>GlyphLine.start</code> and <code>GlyphLine.end</code> will be
65-
* changed in such way, that they will point at start and end of the matching context glyph sequence inside the glyph line.
66-
* @param line a line, which is to be checked if it matches some context.
67-
* @return matching context rule or null, if none was found.
68-
*/
54+
@Override
55+
// TODO DEVSIX-3814 Remove this dummy override. It's left only for binary backwards compatibility
6956
public ContextualSubstRule getMatchingContextRule(GlyphLine line) {
70-
if (line.idx >= line.end)
71-
return null;
72-
73-
Glyph g = line.get(line.idx);
74-
List<ContextualSubstRule> rules = getSetOfRulesForStartGlyph(g.getCode());
75-
for (ContextualSubstRule rule : rules) {
76-
int lastGlyphIndex = checkIfContextMatch(line, rule);
77-
if (lastGlyphIndex != -1) {
78-
line.start = line.idx;
79-
line.end = lastGlyphIndex + 1;
80-
return rule;
81-
}
82-
}
83-
84-
return null;
57+
return super.getMatchingContextRule(line);
8558
}
8659

87-
/**
88-
* Gets a set of rules, which start with given glyph id.
89-
*
90-
* @param startId id of the first glyph in the sequence
91-
* @return a list of {@link ContextualSubstRule} instances. The list will be empty if there are no rules
92-
* that start with a given glyph id
93-
*/
94-
protected abstract List<ContextualSubstRule> getSetOfRulesForStartGlyph(int startId);
95-
96-
/**
97-
* Checks if given glyph line matches given rule.
98-
*
99-
* @param line glyph line to be checked
100-
* @param rule rule to be compared with a given glyph line
101-
* @return either index which corresponds to the last glyph of the matching context inside the glyph line
102-
* if context matches, or -1 if context doesn't match
103-
*/
60+
@Override
61+
// TODO DEVSIX-3814 Remove this dummy override. It's left only for binary backwards compatibility
10462
protected int checkIfContextMatch(GlyphLine line, ContextualSubstRule rule) {
105-
int j;
106-
OpenTableLookup.GlyphIndexer gidx = new OpenTableLookup.GlyphIndexer();
107-
gidx.line = line;
108-
gidx.idx = line.idx;
109-
110-
//Note, that starting index shall be 1
111-
for (j = 1; j < rule.getContextLength(); ++j) {
112-
gidx.nextGlyph(openReader, lookupFlag);
113-
if (gidx.glyph == null || !rule.isGlyphMatchesInput(gidx.glyph.getCode(), j)) {
114-
break;
115-
}
116-
}
117-
118-
boolean isMatch = j == rule.getContextLength();
119-
if (isMatch) {
120-
return gidx.idx;
121-
} else {
122-
return -1;
123-
}
63+
return super.checkIfContextMatch(line, rule);
12464
}
12565
}

io/src/main/java/com/itextpdf/io/font/otf/ContextualSubstRule.java

Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -43,67 +43,15 @@ This file is part of the iText (R) project.
4343
*/
4444
package com.itextpdf.io.font.otf;
4545

46-
import java.io.Serializable;
47-
48-
public abstract class ContextualSubstRule implements Serializable {
46+
public abstract class ContextualSubstRule extends ContextualRule {
4947
private static final long serialVersionUID = -8640866820690910047L;
5048

5149
/**
52-
* @return length of the context glyph sequence defined by this rule
53-
*/
54-
public abstract int getContextLength();
55-
56-
/**
57-
* @return an array of <code>SubstLookupRecord</code>. Each record specifies a position in the context glyph
58-
* sequence and a LookupListIndex to the substitution lookup that is applied at that position
59-
*/
60-
public abstract SubstLookupRecord[] getSubstLookupRecords();
61-
62-
/**
63-
* Checks if glyph line element matches element from input sequence of the rule.
64-
* <br><br>
65-
* NOTE: rules do not contain the first element of the input sequence, the first element is defined by rule
66-
* position in substitution table. Therefore atIdx shall not be 0.
67-
*
68-
* @param glyphId glyph code id
69-
* @param atIdx index in the rule sequence. Shall be: 0 &lt; atIdx &lt; {@link ContextualSubstRule#getContextLength}
70-
* @return {@code true} if glyph matches element
71-
*/
72-
public abstract boolean isGlyphMatchesInput(int glyphId, int atIdx);
73-
74-
/**
75-
* @return length of the lookahead context glyph sequence defined by this rule
76-
*/
77-
public int getLookaheadContextLength() {
78-
return 0;
79-
}
80-
81-
/**
82-
* @return length of the backtrack context glyph sequence defined by this rule
83-
*/
84-
public int getBacktrackContextLength() {
85-
return 0;
86-
}
87-
88-
/**
89-
* Checks if glyph line element matches element from lookahead sequence of the rule.
50+
* Retrieves the substitution lookup records. Each record specifies a position in the context glyph
51+
* sequence and a LookupListIndex to the substitution lookup that is applied at that position.
9052
*
91-
* @param glyphId glyph code id
92-
* @param atIdx index in rule sequence. Shall be: 0 &lt;= atIdx &lt; {@link ContextualSubstRule#getLookaheadContextLength()}
93-
* @return {@code true} if glyph matches element from lookahead sequence
53+
* @return an array of {@link SubstLookupRecord}.
9454
*/
95-
public boolean isGlyphMatchesLookahead(int glyphId, int atIdx) {
96-
return false;
97-
}
55+
public abstract SubstLookupRecord[] getSubstLookupRecords();
9856

99-
/**
100-
* Checks if glyph line element matches element from backtrack sequence of the rule.
101-
*
102-
* @param glyphId glyph code id
103-
* @param atIdx index in rule sequence. Shall be: 0 &lt;= atIdx &lt; {@link ContextualSubstRule#getBacktrackContextLength()}
104-
* @return {@code true} if glyph matches element from backtrack sequence
105-
*/
106-
public boolean isGlyphMatchesBacktrack(int glyphId, int atIdx) {
107-
return false;
108-
}
10957
}

0 commit comments

Comments
 (0)