You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ss...@apache.org on 2022/10/27 07:23:08 UTC

svn commit: r1904869 - in /xmlgraphics/fop-pdf-images/trunk: lib/ src/java/org/apache/fop/render/pdf/pdfbox/ test/java/org/apache/fop/render/pdf/

Author: ssteiner
Date: Thu Oct 27 07:23:08 2022
New Revision: 1904869

URL: http://svn.apache.org/viewvc?rev=1904869&view=rev
Log:
FOP-3102: Move composite glyphs to the end

Modified:
    xmlgraphics/fop-pdf-images/trunk/lib/fop.jar
    xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
    xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
    xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java

Modified: xmlgraphics/fop-pdf-images/trunk/lib/fop.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/lib/fop.jar?rev=1904869&r1=1904868&r2=1904869&view=diff
==============================================================================
Binary files - no diff available.

Modified: xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java?rev=1904869&r1=1904868&r2=1904869&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java Thu Oct 27 07:23:08 2022
@@ -130,11 +130,7 @@ public class FOPPDFMultiByteFont extends
         }
         if (mergeFonts instanceof MergeTTFonts) {
             mergeMaxp(ttf, ((MergeTTFonts)mergeFonts).maxp);
-            int sizeNoCompGlyphs = oldToNewGIMap.size();
             mergeFonts.readFont(ffr, null, null, oldToNewGIMap, true);
-            if (oldToNewGIMap.size() > sizeNoCompGlyphs) {
-                cidSet.mapChar(256 * 256, (char) 0);
-            }
         } else {
             mergeFonts.readFont(ffr, getEmbedFontName(), null, null, true);
         }

Modified: xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java?rev=1904869&r1=1904868&r2=1904869&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java Thu Oct 27 07:23:08 2022
@@ -16,10 +16,17 @@
  */
 package org.apache.fop.render.pdf.pdfbox;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 import org.apache.fop.fonts.truetype.FontFileReader;
@@ -30,19 +37,27 @@ import org.apache.fop.fonts.truetype.OFT
 import org.apache.fop.fonts.truetype.TTFSubSetFile;
 
 public class MergeTTFonts extends TTFSubSetFile implements MergeFonts {
-    private Map<Integer, Glyph> added = new TreeMap<Integer, Glyph>();
+    private Map<Integer, Glyph> added = new TreeMap<>();
     private int origIndexesLen;
     private int size;
     protected MaximumProfileTable maxp = new MaximumProfileTable();
     private Integer nhmtxDiff = null;
     private List<Cmap> cmap;
+    private Set<Integer> composedGlyphs = Collections.emptySet();
+    private Set<Integer> compositeGlyphs = Collections.emptySet();
 
     static class Glyph {
         final byte[] data;
         final OFMtxEntry mtx;
-        Glyph(byte[] d, OFMtxEntry m) {
-            data = d;
-            mtx = m;
+        final boolean composed;
+        final boolean composite;
+        final int origGlyphIndex;
+        Glyph(byte[] data, OFMtxEntry mtx, boolean composed, boolean composite, int origGlyphIndex) {
+            this.data = data;
+            this.mtx = mtx;
+            this.composed = composed;
+            this.composite = composite;
+            this.origGlyphIndex = origGlyphIndex;
         }
     }
 
@@ -77,7 +92,9 @@ public class MergeTTFonts extends TTFSub
                         (int)entry.getOffset() + glyphOffset,
                         glyphLength);
 
-                Glyph g = new Glyph(glyphData, mtxTab[origGlyphIndex]);
+                Glyph g = new Glyph(glyphData, mtxTab[origGlyphIndex],
+                        composedGlyphs.contains(origGlyphIndex),
+                        compositeGlyphs.contains(origGlyphIndex), origGlyphIndex);
                 if (!cid && (origIndexesLen == 0 || (glyphLength > 0 && i > 0))) {
                     added.put(i, g);
                 } else if (cid) {
@@ -248,7 +265,9 @@ public class MergeTTFonts extends TTFSub
         if (glyfTableInfo == null) {
             throw new IOException("Glyf table could not be found");
         }
-        new MergeGlyfTable(in, mtxTab, glyfTableInfo, subsetGlyphs);
+        MergeGlyfTable mergeGlyfTable = new MergeGlyfTable(in, mtxTab, glyfTableInfo, subsetGlyphs);
+        composedGlyphs = mergeGlyfTable.getComposedGlyphs();
+        compositeGlyphs = mergeGlyfTable.getCompositeGlyphs();
     }
 
     static class MergeGlyfTable extends GlyfTable {
@@ -258,6 +277,34 @@ public class MergeTTFonts extends TTFSub
             populateGlyphsWithComposites();
         }
 
+        protected void populateGlyphsWithComposites() throws IOException {
+            for (int indexInOriginal : subset.keySet()) {
+                scanGlyphsRecursively(indexInOriginal);
+            }
+            addAllComposedGlyphsToSubset();
+        }
+
+        private void scanGlyphsRecursively(int indexInOriginal) throws IOException {
+            if (!subset.containsKey(indexInOriginal)) {
+                composedGlyphs.add(indexInOriginal);
+            }
+            if (isComposite(indexInOriginal)) {
+                compositeGlyphs.add(indexInOriginal);
+                Set<Integer> composedGlyphs = retrieveComposedGlyphs(indexInOriginal);
+                for (Integer composedGlyph : composedGlyphs) {
+                    scanGlyphsRecursively(composedGlyph);
+                }
+            }
+        }
+
+        Set<Integer> getComposedGlyphs() {
+            return composedGlyphs;
+        }
+
+        Set<Integer> getCompositeGlyphs() {
+            return compositeGlyphs;
+        }
+
         @Override
         protected void addAllComposedGlyphsToSubset() {
             int newIndex = -1;
@@ -272,11 +319,66 @@ public class MergeTTFonts extends TTFSub
         }
     }
 
+    private void reorderGlyphs() throws IOException {
+        Map<Integer, Integer> remap = new HashMap<>();
+        Map<Integer, Glyph> glyphMap = new TreeMap<>();
+        int i = 0;
+        for (Glyph glyph : added.values()) {
+            if (!glyph.composed) {
+                glyphMap.put(i, glyph);
+                remap.put(glyph.origGlyphIndex, i);
+                i++;
+            }
+        }
+        for (Glyph glyph : added.values()) {
+            if (glyph.composed) {
+                glyphMap.put(i, glyph);
+                remap.put(glyph.origGlyphIndex, i);
+                i++;
+            }
+        }
+        for (Glyph glyph : glyphMap.values()) {
+            if (glyph.composite && glyph.data.length > 0) {
+                remapComposite(glyph.data, remap);
+            }
+        }
+        added = glyphMap;
+    }
+
+    private void remapComposite(byte[] data, Map<Integer, Integer> remap) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        DataOutputStream dos = new DataOutputStream(bos);
+        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
+        byte[] header = new byte[10];
+        read(dis, header);
+        dos.write(header);
+        int flags;
+        do {
+            flags = dis.readShort();
+            dos.writeShort(flags);
+            int glyphIndex = dis.readShort();
+            int indexInSubset = remap.get(glyphIndex);
+            dos.writeShort(indexInSubset);
+            int skip = GlyfTable.GlyfFlags.getOffsetToNextComposedGlyf(flags);
+            byte[] rest = new byte[skip];
+            read(dis, rest);
+            dos.write(rest);
+        } while(GlyfTable.GlyfFlags.hasMoreComposites(flags));
+        System.arraycopy(bos.toByteArray(), 0, data, 0, bos.size());
+    }
+
+    private void read(DataInputStream dis, byte[] data) throws IOException {
+        int size = dis.read(data);
+        assert size == data.length;
+    }
+
     public byte[] getMergedFontSubset() throws IOException {
         int sgsize = added.size();
         if (sgsize == 1 && size == fontFile.getAllBytes().length) {
             return fontFile.getAllBytes();
         }
+        reorderGlyphs();
+
         output = new byte[size * 2];
         createDirectory();     // Create the TrueType header and directory
         if (!cid) {

Modified: xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java?rev=1904869&r1=1904868&r2=1904869&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java Thu Oct 27 07:23:08 2022
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -44,7 +45,9 @@ import static org.mockito.Mockito.when;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.fontbox.cff.CFFParser;
+import org.apache.fontbox.ttf.GlyphData;
 import org.apache.fontbox.ttf.TTFParser;
+import org.apache.fontbox.ttf.TrueTypeFont;
 import org.apache.fontbox.type1.Type1Font;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
@@ -105,6 +108,8 @@ public class PDFBoxAdapterTestCase {
     protected static final String TTSubset5 = "ttsubset5.pdf";
     protected static final String TTSubset6 = "ttsubset6.pdf";
     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 CFFCID1 = "cffcid1.pdf";
     protected static final String CFFCID2 = "cffcid2.pdf";
     protected static final String Type1Subset1 = "t1subset.pdf";
@@ -612,7 +617,9 @@ public class PDFBoxAdapterTestCase {
     @Test
     public void testErrorMsgToPDF() throws IOException {
         String msg = "";
-        PDFRenderingContext context = new PDFRenderingContext(null, null, null, null);
+        PDFDocument pdfdoc = new PDFDocument("");
+        PDFContentGenerator contentGenerator = new PDFContentGenerator(pdfdoc, null, null);
+        PDFRenderingContext context = new PDFRenderingContext(null, contentGenerator, null, null);
         ImagePDF imagePDF = new ImagePDF(new ImageInfo(ERROR, null), null);
         try {
             new PDFBoxImageHandler().handleImage(context, imagePDF, null);
@@ -734,4 +741,25 @@ public class PDFBoxAdapterTestCase {
         String msg = writeText(fi, TTSubset7);
         Assert.assertTrue(msg, msg.contains("( )Tj"));
     }
+
+    @Test
+    public void testReorderGlyphs() throws IOException {
+        FontInfo fontInfo = new FontInfo();
+        writeText(fontInfo, TTSubset8);
+        writeText(fontInfo, TTSubset9);
+        List<Integer> compositeList = new ArrayList<>();
+        for (Typeface font : fontInfo.getUsedFonts().values()) {
+            InputStream inputStream = ((CustomFont) font).getInputStream();
+            TTFParser parser = new TTFParser(true);
+            TrueTypeFont trueTypeFont = parser.parse(inputStream);
+            int i = 0;
+            for (GlyphData glyphData : trueTypeFont.getGlyph().getGlyphs()) {
+                if (glyphData != null && glyphData.getDescription().isComposite()) {
+                    compositeList.add(i);
+                }
+                i++;
+            }
+        }
+        Assert.assertEquals(compositeList, Arrays.asList(18, 19, 39, 42, 62, 63, 29));
+    }
 }



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