Author: tilman
Date: Tue Nov 25 10:27:45 2025
New Revision: 1929971

Log:
PDFBOX-4213: add placeholder for Tamil

Added:
   
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForTamil.java
      - copied, changed from r1917762, 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForGujarati.java
   
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/ttf/gsub/GsubWorkerForTamilTest.java
      - copied, changed from r1917735, 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/ttf/gsub/GsubWorkerForDevanagariTest.java
   pdfbox/trunk/fontbox/src/test/resources/ttf/Lohit-Tamil.ttf   (contents, 
props changed)
Modified:
   
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerFactory.java
   pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/model/Language.java

Modified: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerFactory.java
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerFactory.java
       Tue Nov 25 10:23:32 2025        (r1929970)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerFactory.java
       Tue Nov 25 10:27:45 2025        (r1929971)
@@ -54,6 +54,8 @@ public class GsubWorkerFactory
             return new GsubWorkerForLatin(gsubData);
         case DFLT:
             return new GsubWorkerForDflt(gsubData);
+        case TAMIL:
+            //TODO implement me
         default:
             return new DefaultGsubWorker();
         }

Copied and modified: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForTamil.java
 (from r1917762, 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForGujarati.java)
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForGujarati.java
   Thu May 16 07:28:38 2024        (r1917762, copy source)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForTamil.java
      Tue Nov 25 10:27:45 2025        (r1929971)
@@ -31,30 +31,30 @@ import org.apache.logging.log4j.Logger;
 
 /**
  * 
- * Gujarati-specific implementation of GSUB system.
+ * Tamil-specific implementation of GSUB system.
  * 
- * @author JAVAUSER
+ * @author TODO
  *
  */
-public class GsubWorkerForGujarati implements GsubWorker
+public class GsubWorkerForTamil implements GsubWorker
 {
-    private static final Logger LOG = 
LogManager.getLogger(GsubWorkerForGujarati.class);
-    
-    private static final String RKRF_FEATURE = "rkrf";
-    private static final String VATU_FEATURE = "vatu";
+    private static final Logger LOG = 
LogManager.getLogger(GsubWorkerForTamil.class);
+
     
     /**
      * This sequence is very important. This has been taken from <a href=
-     * 
"https://docs.microsoft.com/en-us/typography/script-development/gujarati";>https://docs.microsoft.com/en-us/typography/script-development/gujarati</a>
+     * 
"https://docs.microsoft.com/en-us/typography/script-development/tamil";>https://docs.microsoft.com/en-us/typography/script-development/tamil</a>
      */
     private static final List<String> FEATURES_IN_ORDER = 
Arrays.asList("locl", "nukt", "akhn",
-            "rphf", RKRF_FEATURE,"blwf", "half", VATU_FEATURE, "cjct", "pres", 
"abvs", "blws",
+            "rphf", "pref", "half", "pres", "abvs", "blws",
             "psts", "haln", "calt");
-    
+
+    //TODO adjust all below this line. The existing code has been copied from 
Gujarati
+
     // Reph glyphs
-    private static final char[] REPH_CHARS = {'\u0AB0', '\u0ACD'};
+    private static final char[] REPH_CHARS = {'\u0BB0','\u0BCD'};
     // Glyphs to precede reph
-    private static final char[] BEFORE_REPH_CHARS={'\u0ABE','\u0AC0'};
+    private static final char[] BEFORE_REPH_CHARS= {'\u0BB8','\u0BCD'};
     
     // Gujarati vowel sign I
     private static final char BEFORE_HALF_CHAR = '\u0ABF';
@@ -66,7 +66,7 @@ public class GsubWorkerForGujarati imple
     private final List<Integer> beforeRephGlyphIds;
     private final List<Integer> beforeHalfGlyphIds;
 
-    GsubWorkerForGujarati(CmapLookup cmapLookup, GsubData gsubData)
+    GsubWorkerForTamil(CmapLookup cmapLookup, GsubData gsubData)
     {
         this.cmapLookup = cmapLookup;
         this.gsubData = gsubData;
@@ -84,13 +84,6 @@ public class GsubWorkerForGujarati imple
         {
             if (!gsubData.isFeatureSupported(feature))
             {
-                if (feature.equals(RKRF_FEATURE) && 
gsubData.isFeatureSupported(VATU_FEATURE))
-                {
-                    // Create your own rkrf feature from vatu feature
-                    intermediateGlyphsFromGsub = applyRKRFFeature(
-                            gsubData.getFeature(VATU_FEATURE),
-                            intermediateGlyphsFromGsub);
-                }
                 LOG.debug("the feature {} was not found", feature);
                 continue;
             }
@@ -102,49 +95,6 @@ public class GsubWorkerForGujarati imple
         return Collections.unmodifiableList(intermediateGlyphsFromGsub);
     }
 
-    private List<Integer> applyRKRFFeature(ScriptFeature 
rkrfGlyphsForSubstitution,
-            List<Integer> originalGlyphIds)
-    {
-        Set<List<Integer>> rkrfGlyphIds = 
rkrfGlyphsForSubstitution.getAllGlyphIdsForSubstitution();
-        if (rkrfGlyphIds.isEmpty())
-        {
-            LOG.debug("Glyph substitution list for {} is empty.", 
rkrfGlyphsForSubstitution.getName());
-            return originalGlyphIds;
-        }
-
-        // Replace this with better implementation to get second GlyphId from 
rkrfGlyphIds
-        int rkrfReplacement = 0;
-        for (List<Integer> firstList : rkrfGlyphIds)
-        {
-            if (firstList.size() > 1)
-            {
-                rkrfReplacement = firstList.get(1);
-                break;
-            }
-        }
-        if (rkrfReplacement == 0)
-        {
-            LOG.debug("Cannot find rkrf candidate. The rkrfGlyphIds doesn't 
contain lists of two elements.");
-            return originalGlyphIds;
-        }
-
-        List<Integer> rkrfList = new ArrayList<>(originalGlyphIds);
-        for (int index = originalGlyphIds.size() - 1; index > 1; index--)
-        {
-            int raGlyph = originalGlyphIds.get(index);
-            if (raGlyph == rephGlyphIds.get(0))
-            {
-                int viramaGlyph = originalGlyphIds.get(index - 1);
-                if (viramaGlyph == rephGlyphIds.get(1))
-                {
-                    rkrfList.set(index - 1, rkrfReplacement);
-                    rkrfList.remove(index);
-                }
-            }
-        }
-        return rkrfList;
-    }
-
     private List<Integer> repositionGlyphs(List<Integer> originalGlyphIds)
     {
         List<Integer> repositionedGlyphIds = new ArrayList<>(originalGlyphIds);
@@ -183,6 +133,7 @@ public class GsubWorkerForGujarati imple
             int viramaGlyph = originalGlyphIds.get(index + 1);
             if (raGlyph == rephGlyphIds.get(0) && viramaGlyph == 
rephGlyphIds.get(1))
             {
+                // reph virama cons => cons reph virama
                 int nextConsonantGlyph = originalGlyphIds.get(index + 2);
                 rephAdjustedList.set(index, nextConsonantGlyph);
                 rephAdjustedList.set(index + 1, raGlyph);
@@ -190,6 +141,7 @@ public class GsubWorkerForGujarati imple
 
                 if (index + 3 < originalGlyphIds.size())
                 {
+                    // reph virama cons matra => cons matra reph virama
                     int matraGlyph = originalGlyphIds.get(index + 3);
                     if (beforeRephGlyphIds.contains(matraGlyph))
                     {

Modified: 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/model/Language.java
==============================================================================
--- 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/model/Language.java   
    Tue Nov 25 10:23:32 2025        (r1929970)
+++ 
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/model/Language.java   
    Tue Nov 25 10:27:45 2025        (r1929971)
@@ -35,6 +35,7 @@ public enum Language
     BENGALI(new String[] { "bng2", "beng" }),
     DEVANAGARI(new String[] { "dev2", "deva" }),
     GUJARATI(new String[] { "gjr2", "gujr" }),
+    TAMIL(new String[] { "tml2", "taml" }),
     LATIN(new String[] { "latn" }),
     DFLT(new String[] { "DFLT" }),
 

Copied and modified: 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/ttf/gsub/GsubWorkerForTamilTest.java
 (from r1917735, 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/ttf/gsub/GsubWorkerForDevanagariTest.java)
==============================================================================
--- 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/ttf/gsub/GsubWorkerForDevanagariTest.java
     Wed May 15 08:07:36 2024        (r1917735, copy source)
+++ 
pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/ttf/gsub/GsubWorkerForTamilTest.java
  Tue Nov 25 10:27:45 2025        (r1929971)
@@ -17,263 +17,44 @@
 
 package org.apache.fontbox.ttf.gsub;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 
 import org.apache.fontbox.ttf.CmapLookup;
 import org.apache.fontbox.ttf.TTFParser;
 import org.apache.fontbox.ttf.TrueTypeFont;
 import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
- * Integration test for {@link GsubWorkerForDevanagari}. Has various 
combinations of glyphs to test
+ * Integration test for {@link GsubWorkerForTamil}. Has various combinations 
of glyphs to test
  * proper working of the GSUB system.
- * <p>
- * Not all tests are enabled at this time (12/2023). Please read the comment 
of 10/Dec/23 in
- * PDFBOX-5729.
- *
- * @author JAVAUSER
- *
  */
-class GsubWorkerForDevanagariTest
+class GsubWorkerForTamilTest
 {
-    private static final String LOHIT_DEVANAGARI_TTF =
-            "src/test/resources/ttf/Lohit-Devanagari.ttf";
+    private static final String LOHIT_TAMIL_TTF = 
"src/test/resources/ttf/Lohit-Tamil.ttf";
 
     private CmapLookup cmapLookup;
-    private GsubWorker gsubWorkerForDevanagari;
+    private GsubWorker gsubWorkerForTamil;
 
     @BeforeEach
     public void init() throws IOException
     {
-        try (TrueTypeFont ttf = new TTFParser().parse(new 
RandomAccessReadBufferedFile(LOHIT_DEVANAGARI_TTF)))
+        try (TrueTypeFont ttf = new TTFParser().parse(new 
RandomAccessReadBufferedFile(LOHIT_TAMIL_TTF)))
         {
             cmapLookup = ttf.getUnicodeCmapLookup();
-            gsubWorkerForDevanagari = new 
GsubWorkerFactory().getGsubWorker(cmapLookup, ttf.getGsubData());
+            gsubWorkerForTamil = new 
GsubWorkerFactory().getGsubWorker(cmapLookup, ttf.getGsubData());
         }
     }
-
-    @Test
-    void testApplyTransforms_locl()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(642);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("प्त"));
-        System.out.println("result: " + result);
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_nukt()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(400,396,393);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("य़ज़क़"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_akhn()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(520,521);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("क्षज्ञ"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_rphf()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(513);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("र्"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Disabled
-    @Test
-    void testApplyTransforms_rkrf()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(588,597,595,602);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("क्रब्रप्रह्र"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_blwf()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(602,336,516);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("ह्रट्र"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_half()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(558,557,546,537);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("ह्स्भ्त्"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_vatu()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(517,593,601,665);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("श्रत्रस्रघ्र"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Disabled
-    @Test
-    void testApplyTransforms_cjct()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(638,688,636,640,639);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("द्मद्ध्र्यब्दद्वद्य"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Test
-    void testApplyTransforms_pres()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(603,605,617,652);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("शृक्तज्जह्ण"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Disabled
-    @Test
-    void testApplyTransforms_abvs()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(353,512,353,675,353,673);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("र्रैंरौंर्रो"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Disabled
-    @Test
-    void testApplyTransforms_blws()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(660,663,336,584,336,583);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("दृहृट्रूट्रु"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
-    @Disabled
-    @Test
-    void testApplyTransforms_psts()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(326,704,326,582,661,662);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("किंर्कींरुरू"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
-    }
-
+    
     @Test
-    void testApplyTransforms_haln()
+    void testDummy()
     {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList(539);
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds("द्"));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);
+        System.out.println("GSUB worker: " + gsubWorkerForTamil);
+        assertTrue(gsubWorkerForTamil instanceof DefaultGsubWorker); // change 
to GsubWorkerForTamil when implemented
     }
 
-    @Disabled
-    void testApplyTransforms_calt()
-    {
-        // given
-        List<Integer> glyphsAfterGsub = Arrays.asList();
-
-        // when
-        List<Integer> result = 
gsubWorkerForDevanagari.applyTransforms(getGlyphIds(""));
-
-        // then
-        assertEquals(glyphsAfterGsub, result);   
-    }
-    
-    private List<Integer> getGlyphIds(String word)
-    {
-        List<Integer> originalGlyphIds = new ArrayList<>();
-
-        for (char unicodeChar : word.toCharArray())
-        {
-            int glyphId = cmapLookup.getGlyphId(unicodeChar);
-            assertTrue(glyphId > 0);
-            originalGlyphIds.add(glyphId);
-        }
-
-        return originalGlyphIds;
-    }
 
 }

Added: pdfbox/trunk/fontbox/src/test/resources/ttf/Lohit-Tamil.ttf
==============================================================================
Binary file. No diff available.

Reply via email to