FdSelect.java
4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* Decompiled with CFR 0_118.
*/
package com.adobe.fontengine.font.cff;
import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.Subset;
import com.adobe.fontengine.font.cff.CFFByteArray;
final class FdSelect {
protected final CFFByteArray data;
protected final int offset;
protected final int size;
public FdSelect(CFFByteArray data, int offset, int numGlyphs) throws InvalidFontException {
this.data = data;
this.offset = offset;
this.size = this.size(numGlyphs);
}
public static FdSelect singleFont(int numGlyphs) throws InvalidFontException {
CFFByteArray.CFFByteArrayBuilder bb = CFFByteArray.getCFFByteArrayBuilderInstance(8);
bb.addCard8(3);
bb.addCard16(1);
bb.addCard16(0);
bb.addCard8(0);
bb.addCard16(numGlyphs);
return new FdSelect(bb.toCFFByteArray(), 0, numGlyphs);
}
private static FdSelect format0Generator(FdSelect origSelect, Subset subset) throws InvalidFontException {
CFFByteArray.CFFByteArrayBuilder bb = CFFByteArray.getCFFByteArrayBuilderInstance(1 + subset.getNumGlyphs());
bb.addCard8(0);
for (int i = 0; i < subset.getNumGlyphs(); ++i) {
bb.addCard8(origSelect.componentOf(subset.getFullGid(i)));
}
return new FdSelect(bb.toCFFByteArray(), 0, subset.getNumGlyphs());
}
private static FdSelect format3Generator(FdSelect origSelect, Subset subset, int numRanges) throws InvalidFontException {
CFFByteArray.CFFByteArrayBuilder bb = CFFByteArray.getCFFByteArrayBuilderInstance(5 + numRanges * 3);
int fd = origSelect.componentOf(subset.getFullGid(0));
bb.addCard8(3);
bb.addCard16(numRanges);
bb.addCard16(0);
for (int i = 1; i < subset.getNumGlyphs(); ++i) {
int nextFD = origSelect.componentOf(subset.getFullGid(i));
if (fd == nextFD) continue;
bb.addCard8(fd);
bb.addCard16(i);
fd = nextFD;
}
bb.addCard8(fd);
bb.addCard16(subset.getNumGlyphs());
return new FdSelect(bb.toCFFByteArray(), 0, subset.getNumGlyphs());
}
public static FdSelect fdSelectFromSubset(FdSelect origSelect, Subset subset) throws InvalidFontException {
int format3Size;
int fd = origSelect.componentOf(subset.getFullGid(0));
int numRanges = 1;
for (int i = 1; i < subset.getNumGlyphs(); ++i) {
int nextFD = origSelect.componentOf(subset.getFullGid(i));
if (fd == nextFD) continue;
++numRanges;
fd = nextFD;
}
int format0Size = subset.getNumGlyphs();
if (format0Size <= (format3Size = 4 + numRanges * 3)) {
return FdSelect.format0Generator(origSelect, subset);
}
return FdSelect.format3Generator(origSelect, subset, numRanges);
}
public int componentOf(int gid) throws InvalidFontException {
int o = this.offset;
int format = this.data.getcard8(o);
++o;
switch (format) {
case 0: {
return this.data.getcard8(o + gid);
}
case 3: {
int nRanges = this.data.getcard16(o);
o += 2;
int min = 0;
int max = nRanges - 1;
while (min <= max) {
int s = (min + max) / 2;
int firstGid = this.data.getcard16(o + 3 * s);
int lastGid = this.data.getcard16(o + 3 * (s + 1));
if (gid < firstGid) {
max = s - 1;
continue;
}
if (lastGid <= gid) {
min = s + 1;
continue;
}
return this.data.getcard8(o + 3 * s + 2);
}
throw new InvalidFontException("invalid fdSelect at offset " + this.offset);
}
}
throw new InvalidFontException("invalid fdSelect format at " + this.offset);
}
int size(int numGlyphs) throws InvalidFontException {
int o = this.offset;
int format = this.data.getcard8(o);
++o;
switch (format) {
case 0: {
return 1 + numGlyphs;
}
case 3: {
int nRanges = this.data.getcard16(o);
return 3 + 3 * nRanges + 2;
}
}
throw new InvalidFontException("invalid fdSelect format at " + this.offset);
}
public void stream(CFFByteArray.CFFByteArrayBuilder bb) throws InvalidFontException {
bb.addBytes(this.data, this.offset, this.size);
}
}