1 //========================================================================
5 // Copyright 2001-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
21 #include "GlobalParams.h"
22 #include "UnicodeMap.h"
24 //------------------------------------------------------------------------
28 struct UnicodeMapExt {
29 Unicode u; // Unicode char
30 char code[maxExtCode];
34 //------------------------------------------------------------------------
36 UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
39 UnicodeMapRange *range;
43 int line, nBytes, i, x;
44 char *tok1, *tok2, *tok3;
46 if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
47 error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
48 encodingNameA->getCString());
52 map = new UnicodeMap(encodingNameA->copy());
55 map->ranges = (UnicodeMapRange *)gmalloc(size * sizeof(UnicodeMapRange));
59 while (getLine(buf, sizeof(buf), f)) {
60 if ((tok1 = strtok(buf, " \t\r\n")) &&
61 (tok2 = strtok(NULL, " \t\r\n"))) {
62 if (!(tok3 = strtok(NULL, " \t\r\n"))) {
66 nBytes = strlen(tok3) / 2;
68 if (map->len == size) {
70 map->ranges = (UnicodeMapRange *)
71 grealloc(map->ranges, size * sizeof(UnicodeMapRange));
73 range = &map->ranges[map->len];
74 sscanf(tok1, "%x", &range->start);
75 sscanf(tok2, "%x", &range->end);
76 sscanf(tok3, "%x", &range->code);
77 range->nBytes = nBytes;
79 } else if (tok2 == tok1) {
80 if (map->eMapsLen == eMapsSize) {
82 map->eMaps = (UnicodeMapExt *)
83 grealloc(map->eMaps, eMapsSize * sizeof(UnicodeMapExt));
85 eMap = &map->eMaps[map->eMapsLen];
86 sscanf(tok1, "%x", &eMap->u);
87 for (i = 0; i < nBytes; ++i) {
88 sscanf(tok3 + i*2, "%2x", &x);
89 eMap->code[i] = (char)x;
91 eMap->nBytes = nBytes;
94 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
95 line, encodingNameA->getCString());
98 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
99 line, encodingNameA->getCString());
107 UnicodeMap::UnicodeMap(GString *encodingNameA) {
108 encodingName = encodingNameA;
109 kind = unicodeMapUser;
117 UnicodeMap::UnicodeMap(char *encodingNameA,
118 UnicodeMapRange *rangesA, int lenA) {
119 encodingName = new GString(encodingNameA);
120 kind = unicodeMapResident;
128 UnicodeMap::UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA) {
129 encodingName = new GString(encodingNameA);
130 kind = unicodeMapFunc;
137 UnicodeMap::~UnicodeMap() {
139 if (kind == unicodeMapUser && ranges) {
147 void UnicodeMap::incRefCnt() {
151 void UnicodeMap::decRefCnt() {
157 GBool UnicodeMap::match(GString *encodingNameA) {
158 return !encodingName->cmp(encodingNameA);
161 int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
162 int a, b, m, n, i, j;
165 if (kind == unicodeMapFunc) {
166 return (*func)(u, buf, bufSize);
171 if (u < ranges[a].start) {
174 // invariant: ranges[a].start <= u < ranges[b].start
177 if (u >= ranges[m].start) {
179 } else if (u < ranges[m].start) {
183 if (u <= ranges[a].end) {
184 n = ranges[a].nBytes;
188 code = ranges[a].code + (u - ranges[a].start);
189 for (i = n - 1; i >= 0; --i) {
190 buf[i] = (char)(code & 0xff);
196 for (i = 0; i < eMapsLen; ++i) {
197 if (eMaps[i].u == u) {
199 for (j = 0; j < n; ++j) {
200 buf[j] = eMaps[i].code[j];
209 //------------------------------------------------------------------------
211 UnicodeMapCache::UnicodeMapCache() {
214 for (i = 0; i < unicodeMapCacheSize; ++i) {
219 UnicodeMapCache::~UnicodeMapCache() {
222 for (i = 0; i < unicodeMapCacheSize; ++i) {
224 cache[i]->decRefCnt();
229 UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
233 if (cache[0] && cache[0]->match(encodingName)) {
234 cache[0]->incRefCnt();
237 for (i = 1; i < unicodeMapCacheSize; ++i) {
238 if (cache[i] && cache[i]->match(encodingName)) {
240 for (j = i; j >= 1; --j) {
241 cache[j] = cache[j - 1];
248 if ((map = UnicodeMap::parse(encodingName))) {
249 if (cache[unicodeMapCacheSize - 1]) {
250 cache[unicodeMapCacheSize - 1]->decRefCnt();
252 for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
253 cache[j] = cache[j - 1];