Skip to content

Commit 312859d

Browse files
committed
Refactor PdfType0Font#getToUnicode logic
DEVSIX-2780
1 parent f7907ae commit 312859d

File tree

11 files changed

+296
-348
lines changed

11 files changed

+296
-348
lines changed

io/src/main/java/com/itextpdf/io/font/CFFFontSubset.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,16 @@ public byte[] Process(String fontName) {
383383
}
384384
}
385385

386+
/**
387+
* The Process function extracts one font out of the CFF file and returns a
388+
* subset version of the original with the first name.
389+
*
390+
* @return The new font stream
391+
*/
392+
public byte[] Process() {
393+
return Process(getNames()[0]);
394+
}
395+
386396
/**
387397
* Function calcs bias according to the CharString type and the count
388398
* of the subrs

io/src/main/java/com/itextpdf/io/font/OpenTypeParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,9 @@ public byte[] readCffFont() throws java.io.IOException {
373373
}
374374
}
375375

376-
public byte[] getSubset(Set<Integer> glyphs, boolean subset) throws java.io.IOException {
376+
byte[] getSubset(Set<Integer> glyphs, boolean subset) throws java.io.IOException {
377377
TrueTypeFontSubset sb = new TrueTypeFontSubset(fileName,
378-
raf.createView(), glyphs, directoryOffset, true, !subset);
378+
raf.createView(), glyphs, directoryOffset, subset);
379379
return sb.process();
380380
}
381381

io/src/main/java/com/itextpdf/io/font/TrueTypeFont.java

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,14 @@ This file is part of the iText (R) project.
5555
import org.slf4j.LoggerFactory;
5656

5757
import com.itextpdf.io.util.MessageFormatUtil;
58+
59+
import java.util.ArrayList;
5860
import java.util.LinkedHashMap;
61+
import java.util.List;
5962
import java.util.Map;
6063
import java.util.Objects;
6164
import java.util.Set;
65+
import java.util.SortedSet;
6266

6367
public class TrueTypeFont extends FontProgram {
6468

@@ -85,32 +89,30 @@ public class TrueTypeFont extends FontProgram {
8589

8690
private byte[] fontStreamBytes;
8791

92+
private TrueTypeFont(OpenTypeParser fontParser) throws java.io.IOException {
93+
this.fontParser = fontParser;
94+
this.fontParser.loadTables(true);
95+
initializeFontProperties();
96+
}
97+
8898
protected TrueTypeFont() {
8999
fontNames = new FontNames();
90100
}
91101

92102
public TrueTypeFont(String path) throws java.io.IOException {
93-
fontParser = new OpenTypeParser(path);
94-
fontParser.loadTables(true);
95-
initializeFontProperties();
103+
this(new OpenTypeParser(path));
96104
}
97105

98106
public TrueTypeFont(byte[] ttf) throws java.io.IOException {
99-
fontParser = new OpenTypeParser(ttf);
100-
fontParser.loadTables(true);
101-
initializeFontProperties();
107+
this(new OpenTypeParser(ttf));
102108
}
103109

104110
TrueTypeFont(String ttcPath, int ttcIndex) throws java.io.IOException {
105-
fontParser = new OpenTypeParser(ttcPath, ttcIndex);
106-
fontParser.loadTables(true);
107-
initializeFontProperties();
111+
this(new OpenTypeParser(ttcPath, ttcIndex));
108112
}
109113

110114
TrueTypeFont(byte[] ttc, int ttcIndex) throws java.io.IOException {
111-
fontParser = new OpenTypeParser(ttc, ttcIndex);
112-
fontParser.loadTables(true);
113-
initializeFontProperties();
115+
this(new OpenTypeParser(ttc, ttcIndex));
114116
}
115117

116118
@Override
@@ -370,4 +372,61 @@ public void close() throws java.io.IOException {
370372
}
371373
fontParser = null;
372374
}
375+
376+
/**
377+
* The method will update usedGlyphs with additional range or with all glyphs if there is no subset.
378+
* usedGlyphs can be used for width array and ToUnicode CMAP.
379+
*
380+
* @param usedGlyphs used glyphs that will be updated if needed.
381+
* @param subset subset status
382+
* @param subsetRanges additional subset ranges
383+
*/
384+
public void updateUsedGlyphs(SortedSet<Integer> usedGlyphs, boolean subset, List<int[]> subsetRanges) {
385+
int[] compactRange;
386+
if (subsetRanges != null) {
387+
compactRange = toCompactRange(subsetRanges);
388+
} else if (!subset) {
389+
compactRange = new int[] {0, 0xFFFF};
390+
} else {
391+
compactRange = new int[] {};
392+
}
393+
394+
for (int k = 0; k < compactRange.length; k += 2) {
395+
int from = compactRange[k];
396+
int to = compactRange[k + 1];
397+
for (int glyphId = from; glyphId <= to; glyphId++) {
398+
if (getGlyphByCode(glyphId) != null) {
399+
usedGlyphs.add(glyphId);
400+
}
401+
}
402+
}
403+
}
404+
405+
private static int[] toCompactRange(List<int[]> ranges) {
406+
List<int[]> simp = new ArrayList<>();
407+
for (int[] range : ranges) {
408+
for (int j = 0; j < range.length; j += 2) {
409+
simp.add(new int[]{Math.max(0, Math.min(range[j], range[j + 1])), Math.min(0xffff, Math.max(range[j], range[j + 1]))});
410+
}
411+
}
412+
for (int k1 = 0; k1 < simp.size() - 1; ++k1) {
413+
for (int k2 = k1 + 1; k2 < simp.size(); ++k2) {
414+
int[] r1 = simp.get(k1);
415+
int[] r2 = simp.get(k2);
416+
if (r1[0] >= r2[0] && r1[0] <= r2[1] || r1[1] >= r2[0] && r1[0] <= r2[1]) {
417+
r1[0] = Math.min(r1[0], r2[0]);
418+
r1[1] = Math.max(r1[1], r2[1]);
419+
simp.remove(k2);
420+
--k2;
421+
}
422+
}
423+
}
424+
int[] s = new int[simp.size() * 2];
425+
for (int k = 0; k < simp.size(); ++k) {
426+
int[] r = simp.get(k);
427+
s[k * 2] = r[0];
428+
s[k * 2 + 1] = r[1];
429+
}
430+
return s;
431+
}
373432
}

0 commit comments

Comments
 (0)