FOP-3089: Switch cmap format to support iPhone
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop-pdf-images/trunk@1903561 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java b/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
index e0dffd0..b7d5a54 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
@@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -352,54 +351,44 @@
}
for (Cmap cmap : cmaps) {
- if (cmap.platformId == 1 && cmaps.size() == 1) {
- writeUShort(6); //subtableFormat
- int firstCode = -1;
- int lastCode = -1;
- List<Integer> codes = new ArrayList<Integer>();
- for (Map.Entry<Integer, Integer> g : cmap.glyphIdToCharacterCode.entrySet()) {
- if (firstCode < 0) {
- firstCode = g.getKey();
- }
- while (lastCode > 0 && lastCode + 1 < g.getKey()) {
- codes.add(0);
- lastCode++;
- }
- codes.add(g.getValue());
- lastCode = g.getKey();
- }
- writeUShort((codes.size() * 2) + 6); //length
- writeUShort(0); //version
- writeUShort(firstCode); //firstCode
- writeUShort(codes.size()); //entryCount
- for (int i : codes) {
- writeUShort(i);
- }
- } else {
- writeUShort(12); //subtableFormat
- writeUShort(0);
- writeULong(currentPos, (cmap.glyphIdToCharacterCode.size() * 12) + 16);
- currentPos += 4;
- writeULong(currentPos, 0);
- currentPos += 4;
- writeULong(currentPos, cmap.glyphIdToCharacterCode.size());
- currentPos += 4;
-
- for (Map.Entry<Integer, Integer> g : cmap.glyphIdToCharacterCode.entrySet()) {
- writeULong(currentPos, g.getKey());
- currentPos += 4;
- writeULong(currentPos, g.getKey());
- currentPos += 4;
- writeULong(currentPos, g.getValue());
- currentPos += 4;
- }
+ writeUShort(4); //subtableFormat
+ int segCount = cmap.glyphIdToCharacterCode.size() + 1;
+ writeUShort(16 + (segCount * 8)); //length
+ writeUShort(0); //lang
+ writeUShort(segCount * 2); //segCountX2
+ double searchRange = Math.pow(2, Math.floor(logBase2(segCount))) * 2;
+ writeUShort((int) searchRange); //searchRange
+ double entrySelector = Math.floor(logBase2(segCount));
+ writeUShort((int) entrySelector); //entrySelector
+ double rangeShift = (segCount * 2) - searchRange;
+ writeUShort((int) rangeShift); //rangeShift
+ for (int c : cmap.glyphIdToCharacterCode.keySet()) {
+ writeUShort(c); //endCode
}
+ writeUShort(0xFFFF);
+ writeUShort(0); //reservedPad
+ for (int c : cmap.glyphIdToCharacterCode.keySet()) {
+ writeUShort(c); //startCode
+ }
+ writeUShort(0);
+ for (Map.Entry<Integer, Integer> entry : cmap.glyphIdToCharacterCode.entrySet()) {
+ writeUShort(entry.getValue() - entry.getKey()); //idDelta
+ }
+ writeUShort(0);
+ for (int g : cmap.glyphIdToCharacterCode.keySet()) {
+ writeUShort(0); //idRangeOffsets
+ }
+ writeUShort(0);
}
updateCheckSum(checksum, currentPos - cmapPos, OFTableName.CMAP);
realSize += currentPos - cmapPos;
}
+ private int logBase2(int n) {
+ return (int)(Math.log(n) / Math.log(2));
+ }
+
private void mergeUniCmap(List<Cmap> cmaps) {
Cmap uniCmap = null;
for (Cmap cmap : cmaps) {
@@ -418,7 +407,8 @@
int result = 0;
for (int i = 0; i < index; i++) {
Cmap curCmap = cmaps.get(i);
- result += (curCmap.glyphIdToCharacterCode.size() * 12) + 16;
+ int segCount = curCmap.glyphIdToCharacterCode.size() + 1;
+ result += 16 + (segCount * 8); //length
}
return result;
}
diff --git a/test/java/org/apache/fop/render/pdf/FOPPDFSingleMultiByteFontTestCase.java b/test/java/org/apache/fop/render/pdf/FOPPDFSingleMultiByteFontTestCase.java
index 78ed269..13877c7 100644
--- a/test/java/org/apache/fop/render/pdf/FOPPDFSingleMultiByteFontTestCase.java
+++ b/test/java/org/apache/fop/render/pdf/FOPPDFSingleMultiByteFontTestCase.java
@@ -16,6 +16,7 @@
*/
package org.apache.fop.render.pdf;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
@@ -29,6 +30,9 @@
import org.apache.fontbox.cff.CFFParser;
import org.apache.fontbox.ttf.GlyphData;
import org.apache.fontbox.ttf.GlyphTable;
+import org.apache.fontbox.ttf.TTFParser;
+import org.apache.fontbox.ttf.TTFTable;
+import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.fontbox.type1.Type1Font;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
@@ -137,7 +141,14 @@
Assert.assertEquals(name, "TimesNewRomanPSMT_TrueType");
Assert.assertEquals(mbfont.getFontName(), "TimesNewRomanPSMT_TrueType");
byte[] is = IOUtils.toByteArray(mbfont.getInputStream());
- Assert.assertEquals(is.length, 41112);
+ Assert.assertEquals(is.length, 41104);
+
+ TrueTypeFont trueTypeFont = new TTFParser().parse(new ByteArrayInputStream(is));
+ TTFTable ttfTable = trueTypeFont.getTableMap().get("cmap");
+ ByteArrayInputStream bis = new ByteArrayInputStream(is);
+ bis.skip(ttfTable.getOffset() + 21);
+ Assert.assertEquals(bis.read(), 4); //subtableFormat
+
doc.close();
doc2.close();
}