You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by ss...@apache.org on 2023/10/24 13:02:26 UTC

[xmlgraphics-fop-pdf-images] branch main updated: FOP-3155: Use format 12 for unicode cmap

This is an automated email from the ASF dual-hosted git repository.

ssteiner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/xmlgraphics-fop-pdf-images.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f3e456  FOP-3155: Use format 12 for unicode cmap
8f3e456 is described below

commit 8f3e456c57fb353be3af59fed9ca4a703f4370db
Author: Simon Steiner <ss...@apache.org>
AuthorDate: Tue Oct 24 14:02:13 2023 +0100

    FOP-3155: Use format 12 for unicode cmap
---
 .../apache/fop/render/pdf/pdfbox/MergeTTFonts.java |  82 +++++++++++++--------
 .../pdfbox/FOPPDFSingleMultiByteFontTestCase.java  |  23 ++++++
 .../render/pdf/pdfbox/PDFBoxAdapterTestCase.java   |   1 +
 .../apache/fop/render/pdf/pdfbox/ttsubset10.pdf    | Bin 0 -> 68997 bytes
 4 files changed, 77 insertions(+), 29 deletions(-)

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 ea25a3c..d0bcff6 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
@@ -453,34 +453,54 @@ public class MergeTTFonts extends TTFSubSetFile implements MergeFonts {
         }
 
         for (Cmap cmap : cmaps) {
-            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
+            if (cmap.platformId != 0) {
+                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);
+            } 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(0);
         }
 
         updateCheckSum(checksum, currentPos - cmapPos, OFTableName.CMAP);
@@ -509,8 +529,12 @@ public class MergeTTFonts extends TTFSubSetFile implements MergeFonts {
         int result = 0;
         for (int i = 0; i < index; i++) {
             Cmap curCmap = cmaps.get(i);
-            int segCount = curCmap.glyphIdToCharacterCode.size() + 1;
-            result += 16 + (segCount * 8); //length
+            if (curCmap.platformId != 0) {
+                int segCount = curCmap.glyphIdToCharacterCode.size() + 1;
+                result += 16 + (segCount * 8); //length
+            } else {
+                result += (curCmap.glyphIdToCharacterCode.size() * 12) + 16;
+            }
         }
         return result;
     }
diff --git a/test/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleMultiByteFontTestCase.java b/test/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleMultiByteFontTestCase.java
index 8710bda..bba1cf3 100644
--- a/test/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleMultiByteFontTestCase.java
+++ b/test/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleMultiByteFontTestCase.java
@@ -28,6 +28,7 @@ import org.junit.Test;
 import org.apache.commons.io.IOUtils;
 import org.apache.fontbox.cff.CFFFont;
 import org.apache.fontbox.cff.CFFParser;
+import org.apache.fontbox.ttf.CmapTable;
 import org.apache.fontbox.ttf.GlyphData;
 import org.apache.fontbox.ttf.GlyphTable;
 import org.apache.fontbox.ttf.TTFParser;
@@ -217,4 +218,26 @@ public class FOPPDFSingleMultiByteFontTestCase {
             return null;
         }
     }
+
+    @Test
+    public void testCmapFormat() throws Exception {
+        PDDocument doc = PDFBoxAdapterTestCase.load(PDFBoxAdapterTestCase.TTSubset10);
+        FOPPDFSingleByteFont sbfont = new FOPPDFSingleByteFont(getFont(doc, "F1"), "test");
+        byte[] bytes = IOUtils.toByteArray(sbfont.getInputStream());
+        TrueTypeFont trueTypeFont = new TTFParser().parse(new ByteArrayInputStream(bytes));
+        CmapTable ttfTable = (CmapTable) trueTypeFont.getTableMap().get("cmap");
+        Assert.assertEquals(ttfTable.getCmaps()[0].getPlatformId(), 0);
+        Assert.assertEquals(ttfTable.getCmaps()[1].getPlatformId(), 1);
+        Assert.assertEquals(ttfTable.getCmaps()[2].getPlatformId(), 3);
+        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+        bis.skip(ttfTable.getOffset() + 29);
+        Assert.assertEquals(bis.read(), 12); //subtableFormat
+        bis = new ByteArrayInputStream(bytes);
+        bis.skip(ttfTable.getOffset() + 465);
+        Assert.assertEquals(bis.read(), 4); //subtableFormat
+        bis = new ByteArrayInputStream(bytes);
+        bis.skip(ttfTable.getOffset() + 809);
+        Assert.assertEquals(bis.read(), 4); //subtableFormat
+        doc.close();
+    }
 }
diff --git a/test/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapterTestCase.java b/test/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapterTestCase.java
index 7721f4e..791ee25 100644
--- a/test/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapterTestCase.java
+++ b/test/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapterTestCase.java
@@ -112,6 +112,7 @@ public class PDFBoxAdapterTestCase {
     protected static final String TTSubset7 = "ttsubset7.pdf";
     protected static final String TTSubset8 = "ttsubset8.pdf";
     protected static final String TTSubset9 = "ttsubset9.pdf";
+    protected static final String TTSubset10 = "ttsubset10.pdf";
     protected static final String CFFCID1 = "cffcid1.pdf";
     protected static final String CFFCID2 = "cffcid2.pdf";
     protected static final String Type1Subset1 = "t1subset.pdf";
diff --git a/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset10.pdf b/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset10.pdf
new file mode 100644
index 0000000..637ea9a
Binary files /dev/null and b/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset10.pdf differ


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org