From 2687fd7279702afe8a77ddd35a8fbaef62e86f50 Mon Sep 17 00:00:00 2001
From: Sebastião Guerra <sebastiao.luiz.guerra@gmail.com>
Date: Thu, 8 Oct 2026 22:15:46 -0300
Subject: Fix CID mapping for name-keyed CFF fonts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Name-keyed CFF fonts embedded as PDF CIDFontType0 use GID-indexed
charstrings, but the conversion paths treated their charset SIDs as CIDs.
Build an identity CID-to-GID map for those fonts while preserving the
charset-based mapping for CID-keyed CFF fonts. Validate FDSelect before
using an FD in convertToCIDType0(), retaining the existing Type0 guard.

The mapping behavior is a local adaptation, not a verbatim code copy.
References:
- Poppler, fofi/FoFiType1C.cc, revision
  c17ec9cd8884747290984e82c97d444ebd22d376:
  https://skia.googlesource.com/third_party/poppler/+/c17ec9cd8884747290984e82c97d444ebd22d376/fofi/FoFiType1C.cc
- Xpdf 4.06, fofi/FoFiType1C.cc, source release revision xpdf-4.06:
  https://fossies.org/linux/xpdf/fofi/FoFiType1C.cc

Signed-off-by: Sebastião Guerra <sebastiao.luiz.guerra@gmail.com>
---
 kpdf/xpdf/fofi/FoFiType1C.cpp | 57 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 12 deletions(-)

diff --git a/kpdf/xpdf/fofi/FoFiType1C.cpp b/kpdf/xpdf/fofi/FoFiType1C.cpp
index d9be7613..f46da94b 100644
--- a/kpdf/xpdf/fofi/FoFiType1C.cpp
+++ b/kpdf/xpdf/fofi/FoFiType1C.cpp
@@ -444,26 +444,46 @@ void FoFiType1C::convertToCIDType0(char *psName,
   int gid, offset, n, i, j, k;
 
   // compute the CID count and build the CID-to-GID mapping
-  nCIDs = 0;
-  for (i = 0; i < nGlyphs; ++i) {
-    if (charset[i] >= nCIDs) {
-      nCIDs = charset[i] + 1;
+  if (topDict.firstOp == 0x0c1e) {
+    // In a CID-keyed CFF font, charset[] maps GIDs to CIDs.
+    nCIDs = 0;
+    for (i = 0; i < nGlyphs; ++i) {
+      if (charset[i] >= nCIDs) {
+        nCIDs = charset[i] + 1;
+      }
     }
+  } else {
+    // A name-keyed CFF embedded in a PDF CIDFontType0 has no CID charset.
+    // Its glyphs are addressed by GID, so use an identity CID-to-GID map.
+    nCIDs = nGlyphs;
   }
   cidMap = (int *)gmallocn(nCIDs, sizeof(int));
   for (i = 0; i < nCIDs; ++i) {
     cidMap[i] = -1;
   }
-  for (i = 0; i < nGlyphs; ++i) {
-    cidMap[charset[i]] = i;
+  if (topDict.firstOp == 0x0c1e) {
+    for (i = 0; i < nGlyphs; ++i) {
+      cidMap[charset[i]] = i;
+    }
+  } else {
+    for (i = 0; i < nCIDs; ++i) {
+      cidMap[i] = i;
+    }
   }
 
   // build the charstrings
+  if (!fdSelect) {
+    readFDSelect();
+  }
   charStrings = new GString();
   charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
   for (i = 0; i < nCIDs; ++i) {
     charStringOffsets[i] = charStrings->getLength();
     if ((gid = cidMap[i]) >= 0) {
+      if (fdSelect[gid] >= nFDs) {
+        cidMap[i] = -1;
+        continue;
+      }
       ok = gTrue;
       getIndexVal(&charStringsIdx, gid, &val, &ok);
       if (ok) {
@@ -768,18 +788,31 @@ void FoFiType1C::convertToType0(char *psName,
   int fd, i, j, k;
 
   // compute the CID count and build the CID-to-GID mapping
-  nCIDs = 0;
-  for (i = 0; i < nGlyphs; ++i) {
-    if (charset[i] >= nCIDs) {
-      nCIDs = charset[i] + 1;
+  if (topDict.firstOp == 0x0c1e) {
+    // In a CID-keyed CFF font, charset[] maps GIDs to CIDs.
+    nCIDs = 0;
+    for (i = 0; i < nGlyphs; ++i) {
+      if (charset[i] >= nCIDs) {
+        nCIDs = charset[i] + 1;
+      }
     }
+  } else {
+    // A name-keyed CFF embedded in a PDF CIDFontType0 has no CID charset.
+    // Its glyphs are addressed by GID, so use an identity CID-to-GID map.
+    nCIDs = nGlyphs;
   }
   cidMap = (int *)gmallocn(nCIDs, sizeof(int));
   for (i = 0; i < nCIDs; ++i) {
     cidMap[i] = -1;
   }
-  for (i = 0; i < nGlyphs; ++i) {
-    cidMap[charset[i]] = i;
+  if (topDict.firstOp == 0x0c1e) {
+    for (i = 0; i < nGlyphs; ++i) {
+      cidMap[charset[i]] = i;
+    }
+  } else {
+    for (i = 0; i < nCIDs; ++i) {
+      cidMap[i] = i;
+    }
   }
 
   // write the descendant Type 1 fonts
-- 
cgit v1.2.3

