[poppler] fofi/FoFiTrueType.cc fofi/FoFiTrueType.h poppler/CMap.cc poppler/CMap.h poppler/GfxFont.cc
Albert Astals Cid
aacid at kemper.freedesktop.org
Mon Dec 10 14:24:24 PST 2007
fofi/FoFiTrueType.cc | 33 +++++++++++++++++++---
fofi/FoFiTrueType.h | 2 -
poppler/CMap.cc | 34 +++++++++++++++++++++++
poppler/CMap.h | 4 ++
poppler/GfxFont.cc | 75 +++++++++++++++++++++++++++++++--------------------
5 files changed, 115 insertions(+), 33 deletions(-)
New commits:
commit f24259cddb9c5e02cf9d2071bfa0106f3e88bd59
Author: Koji Otani <sho at bbr.jp>
Date: Mon Dec 10 23:24:14 2007 +0100
Display characters outside of unicode BMP with TT font
diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc
index 77a7ad2..d702123 100644
--- a/fofi/FoFiTrueType.cc
+++ b/fofi/FoFiTrueType.cc
@@ -321,10 +321,10 @@ int FoFiTrueType::findCmap(int platform, int encoding) {
return -1;
}
-Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
+Gushort FoFiTrueType::mapCodeToGID(int i, Guint c) {
Gushort gid;
- int segCnt, segEnd, segStart, segDelta, segOffset;
- int cmapFirst, cmapLen;
+ Guint segCnt, segEnd, segStart, segDelta, segOffset;
+ Guint cmapFirst, cmapLen;
int pos, a, b, m;
GBool ok;
@@ -335,7 +335,7 @@ Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
pos = cmaps[i].offset;
switch (cmaps[i].fmt) {
case 0:
- if (c < 0 || c >= cmaps[i].len - 6) {
+ if (c >= cmaps[i].len - 6) {
return 0;
}
gid = getU8(cmaps[i].offset + 6 + c, &ok);
@@ -384,6 +384,31 @@ Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
}
gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
break;
+ case 12:
+ segCnt = getU32BE(pos + 12, &ok);
+ a = -1;
+ b = segCnt - 1;
+ segEnd = getU32BE(pos + 16 + 12*b+4, &ok);
+ if (c > segEnd) {
+ return 0;
+ }
+ // invariant: seg[a].end < code <= seg[b].end
+ while (b - a > 1 && ok) {
+ m = (a + b) / 2;
+ segEnd = getU32BE(pos + 16 + 12*m+4, &ok);
+ if (segEnd < c) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ segStart = getU32BE(pos + 16 + 12*b, &ok);
+ segDelta = getU32BE(pos + 16 + 12*b+8, &ok);
+ if (c < segStart) {
+ return 0;
+ }
+ gid = segDelta + (c-segStart);
+ break;
default:
return 0;
}
diff --git a/fofi/FoFiTrueType.h b/fofi/FoFiTrueType.h
index 2ef5ebc..af6dac2 100644
--- a/fofi/FoFiTrueType.h
+++ b/fofi/FoFiTrueType.h
@@ -54,7 +54,7 @@ public:
int findCmap(int platform, int encoding);
// Return the GID corresponding to <c> according to the <i>th cmap.
- Gushort mapCodeToGID(int i, int c);
+ Gushort mapCodeToGID(int i, Guint c);
// map gid to vertical glyph gid if exist.
// if not exist return original gid
diff --git a/poppler/CMap.cc b/poppler/CMap.cc
index 65f4766..c812404 100644
--- a/poppler/CMap.cc
+++ b/poppler/CMap.cc
@@ -354,6 +354,40 @@ CID CMap::getCID(char *s, int len, int *nUsed) {
}
}
+void CMap::setReverseMapVector(Guint startCode, CMapVectorEntry *vec,
+ Guint *rmap, Guint rmapSize, Guint ncand) {
+ int i;
+
+ if (vec == 0) return;
+ for (i = 0;i < 256;i++) {
+ if (vec[i].isVector) {
+ setReverseMapVector((startCode+i) << 8,
+ vec[i].vector,rmap,rmapSize,ncand);
+ } else {
+ Guint cid = vec[i].cid;
+
+ if (cid < rmapSize) {
+ int cand;
+
+ for (cand = 0;cand < ncand;cand++) {
+ Guint code = startCode+i;
+ Guint idx = cid*ncand+cand;
+ if (rmap[idx] == 0) {
+ rmap[idx] = code;
+ break;
+ } else if (rmap[idx] == code) {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void CMap::setReverseMap(Guint *rmap, Guint rmapSize, Guint ncand) {
+ setReverseMapVector(0,vector,rmap,rmapSize,ncand);
+}
+
//------------------------------------------------------------------------
CMapCache::CMapCache() {
diff --git a/poppler/CMap.h b/poppler/CMap.h
index 1652ccf..d65e434 100644
--- a/poppler/CMap.h
+++ b/poppler/CMap.h
@@ -55,6 +55,8 @@ public:
// Return the writing mode (0=horizontal, 1=vertical).
int getWMode() { return wMode; }
+ void setReverseMap(Guint *rmap, Guint rmapSize, Guint ncand);
+
private:
CMap(GooString *collectionA, GooString *cMapNameA);
@@ -65,6 +67,8 @@ private:
Guint nBytes);
void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
void freeCMapVector(CMapVectorEntry *vec);
+ void setReverseMapVector(Guint startCode, CMapVectorEntry *vec,
+ Guint *rmap, Guint rmapSize, Guint ncand);
GooString *collection;
GooString *cMapName;
diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc
index cce097f..1055df1 100644
--- a/poppler/GfxFont.cc
+++ b/poppler/GfxFont.cc
@@ -1588,33 +1588,44 @@ Gushort GfxCIDFont::mapCodeToGID(FoFiTrueType *ff, int cmapi,
Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
/* space characters */
+#define N_UCS_CANDIDATES 2
static unsigned long spaces[] = {
0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,
0x2008,0x2009,0x200A,0x00A0,0x200B,0x2060,0x3000,0xFEFF,
0
};
static char *adobe_cns1_cmaps[] = {
+ "UniCNS-UTF32-V",
"UniCNS-UCS2-V",
+ "UniCNS-UTF32-H",
"UniCNS-UCS2-H",
0
};
static char *adobe_gb1_cmaps[] = {
+ "UniGB-UTF32-V",
"UniGB-UCS2-V",
+ "UniGB-UTF32-H",
"UniGB-UCS2-H",
0
};
static char *adobe_japan1_cmaps[] = {
+ "UniJIS-UTF32-V",
"UniJIS-UCS2-V",
+ "UniJIS-UTF32-H",
"UniJIS-UCS2-H",
0
};
static char *adobe_japan2_cmaps[] = {
+ "UniHojo-UTF32-V",
"UniHojo-UCS2-V",
+ "UniHojo-UTF32-H",
"UniHojo-UCS2-H",
0
};
static char *adobe_korea1_cmaps[] = {
+ "UniKS-UTF32-V",
"UniKS-UCS2-V",
+ "UniKS-UTF32-H",
"UniKS-UCS2-H",
0
};
@@ -1680,8 +1691,17 @@ Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
for (i = 0; i < ff->getNumCmaps(); ++i) {
cmapPlatform = ff->getCmapPlatform(i);
cmapEncoding = ff->getCmapEncoding(i);
- if ((cmapPlatform == 3 && cmapEncoding == 1) || cmapPlatform == 0)
- cmap = i;
+ if (cmapPlatform == 3 && cmapEncoding == 10) {
+ /* UCS-4 */
+ cmap = i;
+ /* use UCS-4 cmap */
+ break;
+ } else if (cmapPlatform == 3 && cmapEncoding == 1) {
+ /* Unicode */
+ cmap = i;
+ } else if (cmapPlatform == 0 && cmap < 0) {
+ cmap = i;
+ }
}
if (cmap < 0)
return NULL;
@@ -1692,8 +1712,9 @@ Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
break;
}
}
- n = ctu->getLength();
- humap = new Unicode[n];
+ //n = ctu->getLength();
+ n = 65536;
+ humap = new Unicode[n*N_UCS_CANDIDATES];
if (lp->collection != 0) {
CharCodeToUnicode *tctu;
GooString tname(lp->toUnicodeMap);
@@ -1706,10 +1727,15 @@ Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
len = tctu->mapToUnicode(cid,ucodes,4);
if (len == 1) {
- humap[cid] = ucodes[0];
+ humap[cid*N_UCS_CANDIDATES] = ucodes[0];
+ for (i = 1;i < N_UCS_CANDIDATES;i++) {
+ humap[cid*N_UCS_CANDIDATES+i] = 0;
+ }
} else {
/* if not single character, ignore it */
- humap[cid] = 0;
+ for (i = 0;i < N_UCS_CANDIDATES;i++) {
+ humap[cid*N_UCS_CANDIDATES+i] = 0;
+ }
}
}
delete tctu;
@@ -1721,25 +1747,11 @@ Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
if ((cMap = globalParams->getCMap(getCollection(),&cname))
!= 0) {
- for (u = 0;u <= 65535;u++) {
- CID cid;
- char code[2];
-
- code[0] = (u >> 8) & 0xff;
- code[1] = u & 0xff;
- cid = cMap->getCID(code,2,&nUsed);
- if (cid != 0) {
if (cMap->getWMode()) {
- if (cid < n && vumap[cid] == 0) {
- vumap[cid] = u;
- }
+ cMap->setReverseMap(vumap,n,1);
} else {
- if (cid < n && humap[cid] == 0) {
- humap[cid] = u;
- }
+ cMap->setReverseMap(humap,n,N_UCS_CANDIDATES);
}
- }
- }
cMap->decRefCnt();
}
}
@@ -1754,7 +1766,10 @@ Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
Unicode ucode;
len = ctu->mapToUnicode(cid,&ucode,1);
- humap[cid] = ucode;
+ humap[cid*N_UCS_CANDIDATES] = ucode;
+ for (i = 1;i < N_UCS_CANDIDATES;i++) {
+ humap[cid*N_UCS_CANDIDATES+i] = 0;
+ }
}
ctu->decRefCnt();
}
@@ -1771,13 +1786,17 @@ Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
if (unicode != 0) {
gid = mapCodeToGID(ff,cmap,unicode,gTrue);
if (gid == 0 && humap != 0) {
- if (humap != 0) unicode = humap[code];
- if (unicode != 0) gid = mapCodeToGID(ff,cmap,unicode,gTrue);
+ for (i = 0;i < N_UCS_CANDIDATES
+ && gid == 0 && (unicode = humap[code*N_UCS_CANDIDATES+i]) != 0;i++) {
+ gid = mapCodeToGID(ff,cmap,unicode,gTrue);
+ }
}
}
- if (gid == 0) {
- if (humap != 0) unicode = humap[code];
- if (unicode != 0) gid = mapCodeToGID(ff,cmap,unicode,wmode);
+ if (gid == 0 && humap != 0) {
+ for (i = 0;i < N_UCS_CANDIDATES
+ && gid == 0 && (unicode = humap[code*N_UCS_CANDIDATES+i]) != 0;i++) {
+ gid = mapCodeToGID(ff,cmap,unicode,wmode);
+ }
}
if (gid == 0) {
/* special handling space characters */
More information about the poppler
mailing list