1 //========================================================================
5 // Copyright 2001-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
23 #include "GlobalParams.h"
24 #include "PSTokenizer.h"
27 //------------------------------------------------------------------------
29 struct CMapVectorEntry
{
32 CMapVectorEntry
*vector
;
37 //------------------------------------------------------------------------
39 static int getCharFromFile(void *data
) {
40 return fgetc((FILE *)data
);
43 //------------------------------------------------------------------------
45 CMap
*CMap::parse(CMapCache
*cache
, GString
*collectionA
,
50 char tok1
[256], tok2
[256], tok3
[256];
54 if (!(f
= globalParams
->findCMapFile(collectionA
, cMapNameA
))) {
56 // Check for an identity CMap.
57 if (!cMapNameA
->cmp("Identity") || !cMapNameA
->cmp("Identity-H")) {
58 return new CMap(collectionA
->copy(), cMapNameA
->copy(), 0);
60 if (!cMapNameA
->cmp("Identity-V")) {
61 return new CMap(collectionA
->copy(), cMapNameA
->copy(), 1);
64 error(-1, "Couldn't find '%s' CMap file for '%s' collection",
65 cMapNameA
->getCString(), collectionA
->getCString());
69 cmap
= new CMap(collectionA
->copy(), cMapNameA
->copy());
71 pst
= new PSTokenizer(&getCharFromFile
, f
);
72 pst
->getToken(tok1
, sizeof(tok1
), &n1
);
73 while (pst
->getToken(tok2
, sizeof(tok2
), &n2
)) {
74 if (!strcmp(tok2
, "usecmap")) {
76 cmap
->useCMap(cache
, tok1
+ 1);
78 pst
->getToken(tok1
, sizeof(tok1
), &n1
);
79 } else if (!strcmp(tok1
, "/WMode")) {
80 cmap
->wMode
= atoi(tok2
);
81 pst
->getToken(tok1
, sizeof(tok1
), &n1
);
82 } else if (!strcmp(tok2
, "begincodespacerange")) {
83 while (pst
->getToken(tok1
, sizeof(tok1
), &n1
)) {
84 if (!strcmp(tok1
, "endcodespacerange")) {
87 if (!pst
->getToken(tok2
, sizeof(tok2
), &n2
) ||
88 !strcmp(tok2
, "endcodespacerange")) {
89 error(-1, "Illegal entry in codespacerange block in CMap");
92 if (tok1
[0] == '<' && tok2
[0] == '<' &&
93 n1
== n2
&& n1
>= 4 && (n1
& 1) == 0) {
94 tok1
[n1
- 1] = tok2
[n1
- 1] = '\0';
95 sscanf(tok1
+ 1, "%x", &start
);
96 sscanf(tok2
+ 1, "%x", &end
);
98 cmap
->addCodeSpace(cmap
->vector
, start
, end
, n1
);
101 pst
->getToken(tok1
, sizeof(tok1
), &n1
);
102 } else if (!strcmp(tok2
, "begincidrange")) {
103 while (pst
->getToken(tok1
, sizeof(tok1
), &n1
)) {
104 if (!strcmp(tok1
, "endcidrange")) {
107 if (!pst
->getToken(tok2
, sizeof(tok2
), &n2
) ||
108 !strcmp(tok2
, "endcidrange") ||
109 !pst
->getToken(tok3
, sizeof(tok3
), &n3
) ||
110 !strcmp(tok3
, "endcidrange")) {
111 error(-1, "Illegal entry in cidrange block in CMap");
114 if (tok1
[0] == '<' && tok2
[0] == '<' &&
115 n1
== n2
&& n1
>= 4 && (n1
& 1) == 0) {
116 tok1
[n1
- 1] = tok2
[n1
- 1] = '\0';
117 sscanf(tok1
+ 1, "%x", &start
);
118 sscanf(tok2
+ 1, "%x", &end
);
120 cmap
->addCIDs(start
, end
, n1
, (CID
)atoi(tok3
));
123 pst
->getToken(tok1
, sizeof(tok1
), &n1
);
135 CMap::CMap(GString
*collectionA
, GString
*cMapNameA
) {
138 collection
= collectionA
;
139 cMapName
= cMapNameA
;
141 vector
= (CMapVectorEntry
*)gmalloc(256 * sizeof(CMapVectorEntry
));
142 for (i
= 0; i
< 256; ++i
) {
143 vector
[i
].isVector
= gFalse
;
152 CMap::CMap(GString
*collectionA
, GString
*cMapNameA
, int wModeA
) {
153 collection
= collectionA
;
154 cMapName
= cMapNameA
;
163 void CMap::useCMap(CMapCache
*cache
, char *useName
) {
167 useNameStr
= new GString(useName
);
168 subCMap
= cache
->getCMap(collection
, useNameStr
);
173 copyVector(vector
, subCMap
->vector
);
174 subCMap
->decRefCnt();
177 void CMap::copyVector(CMapVectorEntry
*dest
, CMapVectorEntry
*src
) {
180 for (i
= 0; i
< 256; ++i
) {
181 if (src
[i
].isVector
) {
182 if (!dest
[i
].isVector
) {
183 dest
[i
].isVector
= gTrue
;
185 (CMapVectorEntry
*)gmalloc(256 * sizeof(CMapVectorEntry
));
186 for (j
= 0; j
< 256; ++j
) {
187 dest
[i
].vector
[j
].isVector
= gFalse
;
188 dest
[i
].vector
[j
].cid
= 0;
191 copyVector(dest
[i
].vector
, src
[i
].vector
);
193 if (dest
[i
].isVector
) {
194 error(-1, "Collision in usecmap");
196 dest
[i
].cid
= src
[i
].cid
;
202 void CMap::addCodeSpace(CMapVectorEntry
*vec
, Guint start
, Guint end
,
205 int startByte
, endByte
, i
, j
;
208 startByte
= (start
>> (8 * (nBytes
- 1))) & 0xff;
209 endByte
= (end
>> (8 * (nBytes
- 1))) & 0xff;
210 start2
= start
& ((1 << (8 * (nBytes
- 1))) - 1);
211 end2
= end
& ((1 << (8 * (nBytes
- 1))) - 1);
212 for (i
= startByte
; i
<= endByte
; ++i
) {
213 if (!vec
[i
].isVector
) {
214 vec
[i
].isVector
= gTrue
;
216 (CMapVectorEntry
*)gmalloc(256 * sizeof(CMapVectorEntry
));
217 for (j
= 0; j
< 256; ++j
) {
218 vec
[i
].vector
[j
].isVector
= gFalse
;
219 vec
[i
].vector
[j
].cid
= 0;
222 addCodeSpace(vec
[i
].vector
, start2
, end2
, nBytes
- 1);
227 void CMap::addCIDs(Guint start
, Guint end
, Guint nBytes
, CID firstCID
) {
228 CMapVectorEntry
*vec
;
234 for (i
= nBytes
- 1; i
>= 1; --i
) {
235 byte
= (start
>> (8 * i
)) & 0xff;
236 if (!vec
[byte
].isVector
) {
237 error(-1, "Invalid CID (%*x - %*x) in CMap",
238 2*nBytes
, start
, 2*nBytes
, end
);
241 vec
= vec
[byte
].vector
;
244 for (byte
= (int)(start
& 0xff); byte
<= (int)(end
& 0xff); ++byte
) {
245 if (vec
[byte
].isVector
) {
246 error(-1, "Invalid CID (%*x - %*x) in CMap",
247 2*nBytes
, start
, 2*nBytes
, end
);
259 freeCMapVector(vector
);
262 gDestroyMutex(&mutex
);
266 void CMap::freeCMapVector(CMapVectorEntry
*vec
) {
269 for (i
= 0; i
< 256; ++i
) {
270 if (vec
[i
].isVector
) {
271 freeCMapVector(vec
[i
].vector
);
277 void CMap::incRefCnt() {
283 gUnlockMutex(&mutex
);
287 void CMap::decRefCnt() {
293 done
= --refCnt
== 0;
295 gUnlockMutex(&mutex
);
302 GBool
CMap::match(GString
*collectionA
, GString
*cMapNameA
) {
303 return !collection
->cmp(collectionA
) && !cMapName
->cmp(cMapNameA
);
306 CID
CMap::getCID(char *s
, int len
, int *nUsed
) {
307 CMapVectorEntry
*vec
;
310 if (!(vec
= vector
)) {
316 return ((s
[0] & 0xff) << 8) + (s
[1] & 0xff);
325 if (!vec
[i
].isVector
) {
333 //------------------------------------------------------------------------
335 CMapCache::CMapCache() {
338 for (i
= 0; i
< cMapCacheSize
; ++i
) {
343 CMapCache::~CMapCache() {
346 for (i
= 0; i
< cMapCacheSize
; ++i
) {
348 cache
[i
]->decRefCnt();
353 CMap
*CMapCache::getCMap(GString
*collection
, GString
*cMapName
) {
357 if (cache
[0] && cache
[0]->match(collection
, cMapName
)) {
358 cache
[0]->incRefCnt();
361 for (i
= 1; i
< cMapCacheSize
; ++i
) {
362 if (cache
[i
] && cache
[i
]->match(collection
, cMapName
)) {
364 for (j
= i
; j
>= 1; --j
) {
365 cache
[j
] = cache
[j
- 1];
372 if ((cmap
= CMap::parse(this, collection
, cMapName
))) {
373 if (cache
[cMapCacheSize
- 1]) {
374 cache
[cMapCacheSize
- 1]->decRefCnt();
376 for (j
= cMapCacheSize
- 1; j
>= 1; --j
) {
377 cache
[j
] = cache
[j
- 1];