Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 234B4200CE1 for ; Thu, 31 Aug 2017 14:31:09 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 21A0916B09C; Thu, 31 Aug 2017 12:31:09 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 11BFD16B09B for ; Thu, 31 Aug 2017 14:31:07 +0200 (CEST) Received: (qmail 924 invoked by uid 500); 31 Aug 2017 12:31:07 -0000 Mailing-List: contact fop-commits-help@xmlgraphics.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: fop-dev@xmlgraphics.apache.org Delivered-To: mailing list fop-commits@xmlgraphics.apache.org Received: (qmail 915 invoked by uid 99); 31 Aug 2017 12:31:07 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 31 Aug 2017 12:31:07 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id E37D93A0098 for ; Thu, 31 Aug 2017 12:31:05 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1806787 - in /xmlgraphics/fop/trunk/fop-core/src: main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java Date: Thu, 31 Aug 2017 12:31:03 -0000 To: fop-commits@xmlgraphics.apache.org From: ssteiner@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20170831123105.E37D93A0098@svn01-us-west.apache.org> archived-at: Thu, 31 Aug 2017 12:31:09 -0000 Author: ssteiner Date: Thu Aug 31 12:31:03 2017 New Revision: 1806787 URL: http://svn.apache.org/viewvc?rev=1806787&view=rev Log: FOP-2699: Fix subsetting large number of glyphs Modified: xmlgraphics/fop/trunk/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java xmlgraphics/fop/trunk/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java Modified: xmlgraphics/fop/trunk/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java?rev=1806787&r1=1806786&r2=1806787&view=diff ============================================================================== --- xmlgraphics/fop/trunk/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java (original) +++ xmlgraphics/fop/trunk/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java Thu Aug 31 12:31:03 2017 @@ -172,11 +172,7 @@ public class OTFSubSetFile extends OTFSu //Keep offset of the topDICT so it can be updated once all data has been written int topDictOffset = currentPos; //Top DICT Index and Data - byte[] topDictIndex = cffReader.getTopDictIndex().getByteData(); - int offSize = topDictIndex[2]; - writeBytes(topDictIndex, 0, 3 + (offSize * 2)); - int topDictDataOffset = currentPos; - writeTopDICT(); + int topDictDataOffset = topDictOffset + writeTopDICT(); //Create the char string index data and related local / global subroutines if (cffReader.getFDSelect() == null) { @@ -251,27 +247,39 @@ public class OTFSubSetFile extends OTFSu return fontNameSIDs; } - protected void writeTopDICT() throws IOException { + protected int writeTopDICT() throws IOException { Map topDICT = cffReader.getTopDictEntries(); List topDictStringEntries = Arrays.asList("version", "Notice", "Copyright", "FullName", "FamilyName", "Weight", "PostScript"); + ByteArrayOutputStream dict = new ByteArrayOutputStream(); + int offsetExtra = 0; for (Map.Entry dictEntry : topDICT.entrySet()) { String dictKey = dictEntry.getKey(); DICTEntry entry = dictEntry.getValue(); //If the value is an SID, update the reference but keep the size the same - if (dictKey.equals("ROS")) { - writeROSEntry(entry); + entry.setOffset(entry.getOffset() + offsetExtra); + if (dictKey.equals("CharStrings") && entry.getOperandLength() == 3) { + byte[] extra = new byte[2]; + offsetExtra += extra.length; + dict.write(extra); + dict.write(entry.getByteData()); + entry.setOperandLength(5); + } else if (dictKey.equals("ROS")) { + dict.write(writeROSEntry(entry)); } else if (dictKey.equals("CIDCount")) { - writeCIDCount(entry); + dict.write(writeCIDCount(entry)); } else if (topDictStringEntries.contains(dictKey)) { - writeTopDictStringEntry(entry); + dict.write(writeTopDictStringEntry(entry)); } else { - writeBytes(entry.getByteData()); + dict.write(entry.getByteData()); } } + byte[] topDictIndex = cffReader.getTopDictIndex().getByteData(); + int offSize = topDictIndex[2]; + return writeIndex(Arrays.asList(dict.toByteArray()), offSize) - dict.size(); } - private void writeROSEntry(DICTEntry dictEntry) throws IOException { + private byte[] writeROSEntry(DICTEntry dictEntry) throws IOException { int sidA = dictEntry.getOperands().get(0).intValue(); if (sidA > 390) { stringIndexData.add(cffReader.getStringIndex().getValue(sidA - NUM_STANDARD_STRINGS)); @@ -289,17 +297,17 @@ public class OTFSubSetFile extends OTFSu dictEntry.getOperandLengths().get(1), sidBStringIndex); updateOffset(cidEntryByteData, dictEntry.getOperandLengths().get(0) + dictEntry.getOperandLengths().get(1), dictEntry.getOperandLengths().get(2), 0); - writeBytes(cidEntryByteData); + return cidEntryByteData; } - protected void writeCIDCount(DICTEntry dictEntry) throws IOException { + protected byte[] writeCIDCount(DICTEntry dictEntry) throws IOException { byte[] cidCountByteData = dictEntry.getByteData(); updateOffset(cidCountByteData, 0, dictEntry.getOperandLengths().get(0), subsetGlyphs.size()); - writeBytes(cidCountByteData); + return cidCountByteData; } - private void writeTopDictStringEntry(DICTEntry dictEntry) throws IOException { + private byte[] writeTopDictStringEntry(DICTEntry dictEntry) throws IOException { int sid = dictEntry.getOperands().get(0).intValue(); if (sid > 391) { stringIndexData.add(cffReader.getStringIndex().getValue(sid - 391)); @@ -307,7 +315,7 @@ public class OTFSubSetFile extends OTFSu byte[] newDictEntry = createNewRef(stringIndexData.size() + 390, dictEntry.getOperator(), dictEntry.getOperandLength(), true); - writeBytes(newDictEntry); + return newDictEntry; } private void writeStringIndex() throws IOException { @@ -906,17 +914,21 @@ public class OTFSubSetFile extends OTFSu } protected int writeIndex(List dataArray) { + int totLength = 1; + for (byte[] aDataArray1 : dataArray) { + totLength += aDataArray1.length; + } + int offSize = getOffSize(totLength); + return writeIndex(dataArray, offSize); + } + + protected int writeIndex(List dataArray, int offSize) { int hdrTotal = 3; //2 byte number of items this.writeCard16(dataArray.size()); //Offset Size: 1 byte = 256, 2 bytes = 65536 etc. //Offsets in the offset array are relative to the byte that precedes the object data. //Therefore the first element of the offset array is always 1. - int totLength = 1; - for (byte[] aDataArray1 : dataArray) { - totLength += aDataArray1.length; - } - int offSize = getOffSize(totLength); this.writeByte(offSize); //Count the first offset 1 hdrTotal += offSize; @@ -1126,11 +1138,15 @@ public class OTFSubSetFile extends OTFSu } protected void updateOffset(byte[] out, int position, int length, int replacement) { + if (length == 2 && replacement < 108 && replacement > -108) { + length = 1; + } switch (length) { case 1: out[position] = (byte)(replacement + 139); break; case 2: + assert replacement <= 1131; if (replacement <= -876) { out[position] = (byte)254; } else if (replacement <= -620) { @@ -1155,6 +1171,7 @@ public class OTFSubSetFile extends OTFSu } break; case 3: + assert replacement <= 32767; out[position] = (byte)28; out[position + 1] = (byte)((replacement >> 8) & 0xFF); out[position + 2] = (byte)(replacement & 0xFF); Modified: xmlgraphics/fop/trunk/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java?rev=1806787&r1=1806786&r2=1806787&view=diff ============================================================================== --- xmlgraphics/fop/trunk/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java (original) +++ xmlgraphics/fop/trunk/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java Thu Aug 31 12:31:03 2017 @@ -435,8 +435,8 @@ public class OTFSubSetFileTestCase exten @Test public void testFDSelect() throws IOException { - Assert.assertEquals(getSubset(1).length, 41); - Assert.assertEquals(getSubset(2).length, 48); + Assert.assertEquals(getSubset(1).length, 43); + Assert.assertEquals(getSubset(2).length, 50); } private byte[] getSubset(final int opLen) throws IOException { @@ -480,7 +480,7 @@ public class OTFSubSetFileTestCase exten when(cffReader.getHeader()).thenReturn(new byte[0]); when(cffReader.getTopDictIndex()).thenReturn(new CFFDataReader().new CFFIndexData() { public byte[] getByteData() throws IOException { - return new byte[3]; + return new byte[] {0, 0, 1}; } }); @@ -501,4 +501,19 @@ public class OTFSubSetFileTestCase exten super.updateFixedOffsets(topDICT, dataTopDictOffset, charsetOffset, charStringOffset, encodingOffset); } } + + @Test + public void testResizeOfOperand() throws IOException { + OTFSubSetFile otfSubSetFile = new OTFSubSetFile() { + protected void writeFDSelect() { + super.writeFDSelect(); + writeBytes(new byte[1024 * 100]); + } + }; + otfSubSetFile.readFont(sourceSansReader, "StandardOpenType", null, glyphs); + byte[] fontSubset = otfSubSetFile.getFontSubset(); + CFFDataReader cffReader = new CFFDataReader(fontSubset); + assertEquals(cffReader.getTopDictEntries().get("CharStrings").getOperandLength(), 5); + assertEquals(cffReader.getTopDictEntries().get("CharStrings").getByteData().length, 6); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org