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];
52
Guint start, end, code;
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, "begincidchar")) {
103
while (pst->getToken(tok1, sizeof(tok1), &n1)) {
104
if (!strcmp(tok1, "endcidchar")) {
107
if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
108
!strcmp(tok2, "endcidchar")) {
109
error(-1, "Illegal entry in cidchar block in CMap");
112
if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
113
n1 >= 4 && (n1 & 1) == 0)) {
114
error(-1, "Illegal entry in cidchar block in CMap");
118
if (sscanf(tok1 + 1, "%x", &code) != 1) {
119
error(-1, "Illegal entry in cidchar block in CMap");
123
cmap->addCIDs(code, code, n1, (CID)atoi(tok2));
125
pst->getToken(tok1, sizeof(tok1), &n1);
126
} else if (!strcmp(tok2, "begincidrange")) {
127
while (pst->getToken(tok1, sizeof(tok1), &n1)) {
128
if (!strcmp(tok1, "endcidrange")) {
131
if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
132
!strcmp(tok2, "endcidrange") ||
133
!pst->getToken(tok3, sizeof(tok3), &n3) ||
134
!strcmp(tok3, "endcidrange")) {
135
error(-1, "Illegal entry in cidrange block in CMap");
138
if (tok1[0] == '<' && tok2[0] == '<' &&
139
n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
140
tok1[n1 - 1] = tok2[n1 - 1] = '\0';
141
sscanf(tok1 + 1, "%x", &start);
142
sscanf(tok2 + 1, "%x", &end);
144
cmap->addCIDs(start, end, n1, (CID)atoi(tok3));
147
pst->getToken(tok1, sizeof(tok1), &n1);
159
CMap::CMap(GString *collectionA, GString *cMapNameA) {
162
collection = collectionA;
163
cMapName = cMapNameA;
165
vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
166
for (i = 0; i < 256; ++i) {
167
vector[i].isVector = gFalse;
176
CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
177
collection = collectionA;
178
cMapName = cMapNameA;
187
void CMap::useCMap(CMapCache *cache, char *useName) {
191
useNameStr = new GString(useName);
192
subCMap = cache->getCMap(collection, useNameStr);
197
copyVector(vector, subCMap->vector);
198
subCMap->decRefCnt();
201
void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
204
for (i = 0; i < 256; ++i) {
205
if (src[i].isVector) {
206
if (!dest[i].isVector) {
207
dest[i].isVector = gTrue;
209
(CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
210
for (j = 0; j < 256; ++j) {
211
dest[i].vector[j].isVector = gFalse;
212
dest[i].vector[j].cid = 0;
215
copyVector(dest[i].vector, src[i].vector);
217
if (dest[i].isVector) {
218
error(-1, "Collision in usecmap");
220
dest[i].cid = src[i].cid;
226
void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
229
int startByte, endByte, i, j;
232
startByte = (start >> (8 * (nBytes - 1))) & 0xff;
233
endByte = (end >> (8 * (nBytes - 1))) & 0xff;
234
start2 = start & ((1 << (8 * (nBytes - 1))) - 1);
235
end2 = end & ((1 << (8 * (nBytes - 1))) - 1);
236
for (i = startByte; i <= endByte; ++i) {
237
if (!vec[i].isVector) {
238
vec[i].isVector = gTrue;
240
(CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry));
241
for (j = 0; j < 256; ++j) {
242
vec[i].vector[j].isVector = gFalse;
243
vec[i].vector[j].cid = 0;
246
addCodeSpace(vec[i].vector, start2, end2, nBytes - 1);
251
void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
252
CMapVectorEntry *vec;
258
for (i = nBytes - 1; i >= 1; --i) {
259
byte = (start >> (8 * i)) & 0xff;
260
if (!vec[byte].isVector) {
261
error(-1, "Invalid CID (%0*x - %0*x) in CMap",
262
2*nBytes, start, 2*nBytes, end);
265
vec = vec[byte].vector;
268
for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) {
269
if (vec[byte].isVector) {
270
error(-1, "Invalid CID (%0*x - %0*x) in CMap",
271
2*nBytes, start, 2*nBytes, end);
283
freeCMapVector(vector);
286
gDestroyMutex(&mutex);
290
void CMap::freeCMapVector(CMapVectorEntry *vec) {
293
for (i = 0; i < 256; ++i) {
294
if (vec[i].isVector) {
295
freeCMapVector(vec[i].vector);
301
void CMap::incRefCnt() {
307
gUnlockMutex(&mutex);
311
void CMap::decRefCnt() {
317
done = --refCnt == 0;
319
gUnlockMutex(&mutex);
326
GBool CMap::match(GString *collectionA, GString *cMapNameA) {
327
return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA);
330
CID CMap::getCID(char *s, int len, int *nUsed) {
331
CMapVectorEntry *vec;
334
if (!(vec = vector)) {
340
return ((s[0] & 0xff) << 8) + (s[1] & 0xff);
349
if (!vec[i].isVector) {
357
//------------------------------------------------------------------------
359
CMapCache::CMapCache() {
362
for (i = 0; i < cMapCacheSize; ++i) {
367
CMapCache::~CMapCache() {
370
for (i = 0; i < cMapCacheSize; ++i) {
372
cache[i]->decRefCnt();
377
CMap *CMapCache::getCMap(GString *collection, GString *cMapName) {
381
if (cache[0] && cache[0]->match(collection, cMapName)) {
382
cache[0]->incRefCnt();
385
for (i = 1; i < cMapCacheSize; ++i) {
386
if (cache[i] && cache[i]->match(collection, cMapName)) {
388
for (j = i; j >= 1; --j) {
389
cache[j] = cache[j - 1];
396
if ((cmap = CMap::parse(this, collection, cMapName))) {
397
if (cache[cMapCacheSize - 1]) {
398
cache[cMapCacheSize - 1]->decRefCnt();
400
for (j = cMapCacheSize - 1; j >= 1; --j) {
401
cache[j] = cache[j - 1];