Skip to content

Commit adddcf5

Browse files
author
obo
committed
code review
1 parent 388f0d7 commit adddcf5

File tree

2 files changed

+123
-72
lines changed

2 files changed

+123
-72
lines changed

openpdf/src/main/java/com/lowagie/text/pdf/FontDetails.java

Lines changed: 118 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -225,66 +225,7 @@ byte[] convertToBytes(String text, TextRenderingOptions options) {
225225
} else {
226226
//ivs font handler,Simply judge whether it is IVS font or not
227227
if (mayContainIVS(text)) {
228-
glyph = new char[len * 2];
229-
for (int k = 0; k < len; ) {
230-
int baseCp;
231-
int charCount;
232-
if (k < len - 1 && Character.isHighSurrogate(text.charAt(k))
233-
&& Character.isLowSurrogate(text.charAt(k + 1))) {
234-
baseCp = Character.toCodePoint(text.charAt(k), text.charAt(k + 1));
235-
charCount = 2;
236-
} else {
237-
baseCp = text.charAt(k);
238-
charCount = 1;
239-
}
240-
241-
int vsCp = -1;
242-
int vsCharCount = 0;
243-
int nextIndex = k + charCount;
244-
245-
if (nextIndex < len) {
246-
int potentialVs = text.charAt(nextIndex);
247-
if (isVariationSelector(potentialVs)) {
248-
vsCp = potentialVs;
249-
vsCharCount = 1;
250-
}
251-
else if (nextIndex < len - 1
252-
&& Character.isHighSurrogate(text.charAt(nextIndex))
253-
&& Character.isLowSurrogate(text.charAt(nextIndex + 1))) {
254-
int potentialVsPair = Character.toCodePoint(
255-
text.charAt(nextIndex), text.charAt(nextIndex + 1));
256-
if (isVariationSelector(potentialVsPair)) {
257-
vsCp = potentialVsPair;
258-
vsCharCount = 2;
259-
}
260-
}
261-
}
262-
263-
if (vsCp != -1) {
264-
int[] format14Metrics = this.ttu.getFormat14MetricsTT(baseCp, vsCp);
265-
if (format14Metrics != null) {
266-
int gl = format14Metrics[0];
267-
if (!this.longTag.containsKey(gl)) {
268-
this.longTag.put(gl, new int[]{gl, format14Metrics[1], baseCp, vsCp});
269-
}
270-
glyph[i++] = (char) gl;
271-
k += charCount + vsCharCount;
272-
continue;
273-
}
274-
}
275-
metrics = this.ttu.getMetricsTT(baseCp);
276-
if (metrics != null) {
277-
int gl = metrics[0];
278-
if (!this.longTag.containsKey(gl)) {
279-
this.longTag.put(gl, new int[]{gl, metrics[1], baseCp});
280-
}
281-
glyph[i++] = (char) gl;
282-
}
283-
284-
k += charCount;
285-
}
286-
glyph = Arrays.copyOfRange(glyph, 0, i);
287-
b = convertCharsToBytes(glyph);
228+
b = handleIvsText(text, len, i);
288229
break;
289230
}
290231
String fileName = ((TrueTypeFontUnicode) getBaseFont()).fileName;
@@ -482,4 +423,121 @@ public boolean isSubset() {
482423
public void setSubset(boolean subset) {
483424
this.subset = subset;
484425
}
426+
427+
/**
428+
* handle ivs text
429+
*/
430+
private byte[] handleIvsText(String text, int len, int startIndex) {
431+
char[] glyph = new char[len * 2];
432+
int glyphIndex = startIndex;
433+
int k = 0;
434+
435+
while (k < len) {
436+
CodePointInfo baseChar = parseCodePoint(text, k, len);
437+
CodePointInfo vsChar = parseVariationSelector(text, k + baseChar.charCount, len);
438+
int skipCount = baseChar.charCount;
439+
if (vsChar != null) {
440+
glyphIndex = addIvsGlyph(baseChar.codePoint, vsChar.codePoint, glyph, glyphIndex);
441+
skipCount += vsChar.charCount;
442+
} else {
443+
glyphIndex = addDefaultGlyph(baseChar.codePoint, glyph, glyphIndex);
444+
}
445+
k += skipCount;
446+
}
447+
448+
glyph = Arrays.copyOfRange(glyph, 0, glyphIndex);
449+
return convertCharsToBytes(glyph);
450+
}
451+
452+
private CodePointInfo parseCodePoint(String text, int index, int len) {
453+
if (index < len - 1
454+
&& Character.isHighSurrogate(text.charAt(index))
455+
&& Character.isLowSurrogate(text.charAt(index + 1))) {
456+
// Surrogate pair
457+
int codePoint = Character.toCodePoint(text.charAt(index), text.charAt(index + 1));
458+
return new CodePointInfo(codePoint, 2);
459+
} else {
460+
// BMP
461+
return new CodePointInfo(text.charAt(index), 1);
462+
}
463+
}
464+
465+
private CodePointInfo parseVariationSelector(String text, int index, int len) {
466+
if (index >= len) {
467+
return null;
468+
}
469+
470+
char currentChar = text.charAt(index);
471+
472+
// single char IVS
473+
if (isVariationSelector(currentChar)) {
474+
return new CodePointInfo(currentChar, 1);
475+
}
476+
477+
// surrogate pair IVS
478+
if (index < len - 1
479+
&& Character.isHighSurrogate(currentChar)
480+
&& Character.isLowSurrogate(text.charAt(index + 1))) {
481+
int codePoint = Character.toCodePoint(currentChar, text.charAt(index + 1));
482+
if (isVariationSelector(codePoint)) {
483+
return new CodePointInfo(codePoint, 2);
484+
}
485+
}
486+
487+
return null;
488+
}
489+
490+
private int addIvsGlyph(int baseCp, int vsCp, char[] glyph, int glyphIndex) {
491+
int[] format14Metrics = this.ttu.getFormat14MetricsTT(baseCp, vsCp);
492+
493+
if (format14Metrics != null) {
494+
int glyphId = format14Metrics[0];
495+
cacheGlyphMetrics(glyphId, format14Metrics[1], baseCp, vsCp);
496+
glyph[glyphIndex++] = (char) glyphId;
497+
return glyphIndex;
498+
}
499+
500+
// fallback
501+
return addDefaultGlyph(baseCp, glyph, glyphIndex);
502+
}
503+
504+
private int addDefaultGlyph(int codePoint, char[] glyph, int glyphIndex) {
505+
int[] metrics = this.ttu.getMetricsTT(codePoint);
506+
507+
if (metrics != null) {
508+
int glyphId = metrics[0];
509+
cacheGlyphMetrics(glyphId, metrics[1], codePoint);
510+
glyph[glyphIndex++] = (char) glyphId;
511+
}
512+
513+
return glyphIndex;
514+
}
515+
516+
/**
517+
* cache IVS glyph metrics info
518+
*/
519+
private void cacheGlyphMetrics(int glyphId, int width, int baseCp) {
520+
if (!this.longTag.containsKey(glyphId)) {
521+
this.longTag.put(glyphId, new int[]{glyphId, width, baseCp});
522+
}
523+
}
524+
525+
/**
526+
* cache IVS glyph metrics info
527+
*/
528+
private void cacheGlyphMetrics(int glyphId, int width, int baseCp, int vsCp) {
529+
if (!this.longTag.containsKey(glyphId)) {
530+
this.longTag.put(glyphId, new int[]{glyphId, width, baseCp, vsCp});
531+
}
532+
}
533+
534+
private static class CodePointInfo {
535+
final int codePoint;
536+
final int charCount;
537+
538+
CodePointInfo(int codePoint, int charCount) {
539+
this.codePoint = codePoint;
540+
this.charCount = charCount;
541+
}
542+
}
485543
}

openpdf/src/main/java/com/lowagie/text/pdf/TrueTypeFont.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -877,9 +877,8 @@ void readCMaps() throws DocumentException, IOException {
877877

878878
HashMap<String, int[]> readFormat14(int format14Location) throws IOException {
879879
HashMap<String, int[]> result = new HashMap<>();
880-
long startPosition = this.rf.getFilePointer() - 4; // 回退到读取 byteLength 之前的位置
881-
882-
int byteLength = this.rf.readInt();
880+
int startPosition = this.rf.getFilePointer() - 4; //reopen
881+
int byteLength = this.rf.readInt(); // byteLength
883882
int numVarSelectorRecords = this.rf.readInt();
884883

885884
if (numVarSelectorRecords < 0 || numVarSelectorRecords > 10000) {
@@ -895,7 +894,7 @@ HashMap<String, int[]> readFormat14(int format14Location) throws IOException {
895894
int defaultUVSOffset = this.rf.readInt();
896895
int nonDefaultUVSOffset = this.rf.readInt();
897896

898-
if (nonDefaultUVSOffset > 0) { // 只处理非零偏移
897+
if (nonDefaultUVSOffset > 0) {
899898
nonDefaultOffsetMap.put(selectorUnicodeValue, nonDefaultUVSOffset);
900899
}
901900
}
@@ -924,19 +923,13 @@ HashMap<String, int[]> readFormat14(int format14Location) throws IOException {
924923
return result;
925924
}
926925

927-
/**
928-
* 将大端序(Big-Endian)的字节数组转换为无符号整数(最多4字节)
929-
* @param data 输入字节数组
930-
* @param n 读取字节数(1~4)
931-
* @return 对应的非负整数值
932-
*/
933926
public int byte2int(byte[] data, int n) {
934927
if (data == null || n <= 0 || n > 4 || data.length < n) {
935928
return 0;
936929
}
937930
int result = 0;
938931
for (int i = 0; i < n; i++) {
939-
result = (result << 8) | (data[i] & 0xFF); // & 0xFF 确保无符号
932+
result = (result << 8) | (data[i] & 0xFF);
940933
}
941934
return result;
942935
}
@@ -945,7 +938,7 @@ public int[] getFormat14MetricsTT(int char1, int char2) {
945938
if (this.cmap05 != null) {
946939
return this.cmap05.get(char1 + "_" + char2);
947940
}
948-
return null;
941+
return new int[]{-1, -1};
949942
}
950943

951944
HashMap<Integer, int[]> readFormat12() throws IOException {

0 commit comments

Comments
 (0)