You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2024/04/30 08:53:21 UTC
svn commit: r1917432 - in /pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf: ./ gsub/ table/gsub/
Author: tilman
Date: Tue Apr 30 08:53:21 2024
New Revision: 1917432
URL: http://svn.apache.org/viewvc?rev=1917432&view=rev
Log:
PDFBOX-5808: add support for GSUB lookup type 3, by Fabrice Calafat
Added:
pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/AlternateSetTable.java (with props)
pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/LookupTypeAlternateSubstitutionFormat1.java (with props)
Modified:
pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java
pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java
Modified: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java?rev=1917432&r1=1917431&r2=1917432&view=diff
==============================================================================
--- pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java (original)
+++ pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphSubstitutionTable.java Tue Apr 30 08:53:21 2024
@@ -27,7 +27,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.function.Predicate;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
@@ -46,8 +45,10 @@ import org.apache.fontbox.ttf.table.comm
import org.apache.fontbox.ttf.table.common.LookupTable;
import org.apache.fontbox.ttf.table.common.RangeRecord;
import org.apache.fontbox.ttf.table.common.ScriptTable;
+import org.apache.fontbox.ttf.table.gsub.AlternateSetTable;
import org.apache.fontbox.ttf.table.gsub.LigatureSetTable;
import org.apache.fontbox.ttf.table.gsub.LigatureTable;
+import org.apache.fontbox.ttf.table.gsub.LookupTypeAlternateSubstitutionFormat1;
import org.apache.fontbox.ttf.table.gsub.LookupTypeLigatureSubstitutionSubstFormat1;
import org.apache.fontbox.ttf.table.gsub.LookupTypeMultipleSubstitutionFormat1;
import org.apache.fontbox.ttf.table.gsub.LookupTypeSingleSubstFormat1;
@@ -289,6 +290,10 @@ public class GlyphSubstitutionTable exte
// Multiple Substitution Subtable
// https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-2-multiple-substitution-subtable
return readMultipleSubstitutionSubtable(data, offset);
+ case 3:
+ // Alternate Substitution Subtable
+ // https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-3-alternate-substitution-subtable
+ return readAlternateSubstitutionSubtable(data, offset);
case 4:
// Ligature Substitution Subtable
// https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#LS
@@ -345,6 +350,7 @@ public class GlyphSubstitutionTable exte
{
case 1:
case 2:
+ case 3:
case 4:
for (int i = 0; i < subTableCount; i++)
{
@@ -462,6 +468,49 @@ public class GlyphSubstitutionTable exte
return new LookupTypeMultipleSubstitutionFormat1(substFormat, coverageTable, sequenceTables);
}
+ private LookupSubTable readAlternateSubstitutionSubtable(TTFDataStream data, long offset) throws IOException
+ {
+ data.seek(offset);
+ int substFormat = data.readUnsignedShort();
+
+ if (substFormat != 1)
+ {
+ throw new IOException(
+ "The expected SubstFormat for AlternateSubstitutionTable is 1");
+ }
+
+ int coverage = data.readUnsignedShort();
+ int altSetCount = data.readUnsignedShort();
+
+ int[] alternateOffsets = new int[altSetCount];
+
+ for (int i = 0; i < altSetCount; i++)
+ {
+ alternateOffsets[i] = data.readUnsignedShort();
+ }
+
+ CoverageTable coverageTable = readCoverageTable(data, offset + coverage);
+
+ if (altSetCount != coverageTable.getSize())
+ {
+ throw new IOException(
+ "According to the OpenTypeFont specifications, the coverage count should be equal to the no. of AlternateSetTable");
+ }
+
+ AlternateSetTable[] alternateSetTables = new AlternateSetTable[altSetCount];
+
+ for (int i = 0; i < altSetCount; i++)
+ {
+ data.seek(offset + alternateOffsets[i]);
+ int glyphCount = data.readUnsignedShort();
+ int[] alternateGlyphIDs = data.readUnsignedShortArray(glyphCount);
+ alternateSetTables[i] = new AlternateSetTable(glyphCount, alternateGlyphIDs);
+ }
+
+ return new LookupTypeAlternateSubstitutionFormat1(substFormat, coverageTable,
+ alternateSetTables);
+ }
+
private LookupSubTable readLigatureSubstitutionSubtable(TTFDataStream data, long offset)
throws IOException
{
Modified: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java?rev=1917432&r1=1917431&r2=1917432&view=diff
==============================================================================
--- pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java (original)
+++ pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java Tue Apr 30 08:53:21 2024
@@ -47,6 +47,7 @@ public class TrueTypeFont implements Fon
private float version;
private int numberOfGlyphs = -1;
private int unitsPerEm = -1;
+ private boolean enableGsub = true;
protected final Map<String,TTFTable> tables = new HashMap<>();
private final TTFDataStream data;
private volatile Map<String, Integer> postScriptNames;
@@ -74,7 +75,7 @@ public class TrueTypeFont implements Fon
/**
* @return Returns the version.
*/
- public float getVersion()
+ public float getVersion()
{
return version;
}
@@ -87,7 +88,24 @@ public class TrueTypeFont implements Fon
{
version = versionValue;
}
-
+
+ /**
+ * @return Returns true if the GSUB table can be used for this font
+ */
+ public boolean isEnableGsub()
+ {
+ return enableGsub;
+ }
+
+ /**
+ * Enable or disable the GSUB table for this font.
+ * GSUB table is enabled by default.
+ */
+ public void setEnableGsub(boolean enableGsub)
+ {
+ this.enableGsub = enableGsub;
+ }
+
/**
* Add a table definition. Package-private, used by TTFParser only.
*
@@ -638,13 +656,17 @@ public class TrueTypeFont implements Fon
/**
* Returns the GSubData of the GlyphSubstitutionTable if present.
*
- * @return the GSubData of the GlyphSubstitutionTable or {@link GsubData#NO_DATA_FOUND} if either no GSUB data is
- * available or its scripts are not supported
- *
+ * @return the GSubData of the GlyphSubstitutionTable or {@link GsubData#NO_DATA_FOUND} if no GSUB data is
+ * available, its scripts are not supported or it was disabled for that font
* @throws IOException if the font data could not be read
*/
public GsubData getGsubData() throws IOException
{
+ if (!enableGsub)
+ {
+ return GsubData.NO_DATA_FOUND;
+ }
+
GlyphSubstitutionTable table = getGsub();
if (table == null)
{
Modified: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java?rev=1917432&r1=1917431&r2=1917432&view=diff
==============================================================================
--- pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java (original)
+++ pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GlyphSubstitutionDataExtractor.java Tue Apr 30 08:53:21 2024
@@ -36,8 +36,10 @@ import org.apache.fontbox.ttf.table.comm
import org.apache.fontbox.ttf.table.common.LookupSubTable;
import org.apache.fontbox.ttf.table.common.LookupTable;
import org.apache.fontbox.ttf.table.common.ScriptTable;
+import org.apache.fontbox.ttf.table.gsub.AlternateSetTable;
import org.apache.fontbox.ttf.table.gsub.LigatureSetTable;
import org.apache.fontbox.ttf.table.gsub.LigatureTable;
+import org.apache.fontbox.ttf.table.gsub.LookupTypeAlternateSubstitutionFormat1;
import org.apache.fontbox.ttf.table.gsub.LookupTypeLigatureSubstitutionSubstFormat1;
import org.apache.fontbox.ttf.table.gsub.LookupTypeMultipleSubstitutionFormat1;
import org.apache.fontbox.ttf.table.gsub.LookupTypeSingleSubstFormat1;
@@ -176,6 +178,11 @@ public class GlyphSubstitutionDataExtrac
extractDataFromLigatureSubstitutionSubstFormat1Table(glyphSubstitutionMap,
(LookupTypeLigatureSubstitutionSubstFormat1) lookupSubTable);
}
+ else if (lookupSubTable instanceof LookupTypeAlternateSubstitutionFormat1)
+ {
+ extractDataFromAlternateSubstitutionSubstFormat1Table(glyphSubstitutionMap,
+ (LookupTypeAlternateSubstitutionFormat1) lookupSubTable);
+ }
else if (lookupSubTable instanceof LookupTypeSingleSubstFormat1)
{
extractDataFromSingleSubstTableFormat1Table(glyphSubstitutionMap,
@@ -278,6 +285,47 @@ public class GlyphSubstitutionDataExtrac
}
}
+
+ /**
+ * Extracts data from the AlternateSubstitutionFormat1 (lookuptype) 3 table and puts it in the glyphSubstitutionMap
+ * This is added for Zola usage
+ *
+ * @param glyphSubstitutionMap the map to store the substitution data
+ * @param alternateSubstitutionFormat1 the alternate substitution format 1 table
+ */
+ private void extractDataFromAlternateSubstitutionSubstFormat1Table(
+ Map<List<Integer>, Integer> glyphSubstitutionMap,
+ LookupTypeAlternateSubstitutionFormat1 alternateSubstitutionFormat1)
+ {
+
+ CoverageTable coverageTable = alternateSubstitutionFormat1.getCoverageTable();
+
+ if (coverageTable.getSize() != alternateSubstitutionFormat1.getAlternateSetTables().length)
+ {
+ LOG.warn("The coverage table size (" + coverageTable.getSize() +
+ ") should be the same as the count of the atlternate set tables (" +
+ alternateSubstitutionFormat1.getAlternateSetTables().length + ")");
+ return;
+ }
+
+ for (int i = 0; i < coverageTable.getSize(); i++)
+ {
+ int coverageGlyphId = coverageTable.getGlyphId(i);
+ AlternateSetTable sequenceTable = alternateSubstitutionFormat1.getAlternateSetTables()[i];
+
+ // Loop through the substitute glyphs and pick the first one that is not the same as the coverage glyph
+ for (int alternateGlyphId : sequenceTable.getAlternateGlyphIDs())
+ {
+ if (alternateGlyphId != coverageGlyphId)
+ {
+ putNewSubstitutionEntry(glyphSubstitutionMap, alternateGlyphId,
+ Collections.singletonList(coverageGlyphId));
+ break;
+ }
+ }
+ }
+
+ }
private void extractDataFromLigatureTable(Map<List<Integer>, Integer> glyphSubstitutionMap,
LigatureTable ligatureTable)
Added: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/AlternateSetTable.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/AlternateSetTable.java?rev=1917432&view=auto
==============================================================================
--- pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/AlternateSetTable.java (added)
+++ pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/AlternateSetTable.java Tue Apr 30 08:53:21 2024
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fontbox.ttf.table.gsub;
+
+import java.util.Arrays;
+
+/**
+ * LookupType 3: Alternate Substitution Subtable
+ * as described in OpenType spec: <a href="https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1">...</a>
+ */
+public class AlternateSetTable
+{
+ private final int glyphCount;
+ private final int[] alternateGlyphIDs;
+
+ public AlternateSetTable(int glyphCount, int[] alternateGlyphIDs)
+ {
+ this.glyphCount = glyphCount;
+ this.alternateGlyphIDs = alternateGlyphIDs;
+ }
+
+ public int getGlyphCount()
+ {
+ return glyphCount;
+ }
+
+ public int[] getAlternateGlyphIDs()
+ {
+ return alternateGlyphIDs;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "AlternateSetTable{" + "glyphCount=" + glyphCount + ", alternateGlyphIDs=" + Arrays.toString(alternateGlyphIDs) + '}';
+ }
+}
Propchange: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/AlternateSetTable.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/LookupTypeAlternateSubstitutionFormat1.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/LookupTypeAlternateSubstitutionFormat1.java?rev=1917432&view=auto
==============================================================================
--- pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/LookupTypeAlternateSubstitutionFormat1.java (added)
+++ pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/LookupTypeAlternateSubstitutionFormat1.java Tue Apr 30 08:53:21 2024
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fontbox.ttf.table.gsub;
+
+import org.apache.fontbox.ttf.table.common.CoverageTable;
+import org.apache.fontbox.ttf.table.common.LookupSubTable;
+
+/**
+ * Lookup Type 3: Alternate Substitution Subtable
+ * as described in OpenType spec: <a href="https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1">...</a>
+ */
+public class LookupTypeAlternateSubstitutionFormat1 extends LookupSubTable {
+ private final AlternateSetTable[] alternateSetTables;
+
+ public LookupTypeAlternateSubstitutionFormat1(
+ int substFormat, CoverageTable coverageTable, AlternateSetTable[] alternateSetTables) {
+ super(substFormat, coverageTable);
+ this.alternateSetTables = alternateSetTables;
+ }
+
+ public AlternateSetTable[] getAlternateSetTables() {
+ return alternateSetTables;
+ }
+
+ @Override
+ public int doSubstitution(int gid, int coverageIndex) {
+ throw new UnsupportedOperationException("not applicable");
+ }
+}
Propchange: pdfbox/branches/3.0/fontbox/src/main/java/org/apache/fontbox/ttf/table/gsub/LookupTypeAlternateSubstitutionFormat1.java
------------------------------------------------------------------------------
svn:eol-style = native