summaryrefslogtreecommitdiff
path: root/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
Unidiff
Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/UnicodeMap.cc') (more/less context) (show whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/xpdf/UnicodeMap.cc260
1 files changed, 260 insertions, 0 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc b/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
new file mode 100644
index 0000000..ab823b1
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/UnicodeMap.cc
@@ -0,0 +1,260 @@
1//========================================================================
2//
3// UnicodeMap.cc
4//
5// Copyright 2001 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <string.h>
16#include "gmem.h"
17#include "gfile.h"
18#include "GString.h"
19#include "GList.h"
20#include "Error.h"
21#include "GlobalParams.h"
22#include "UnicodeMap.h"
23
24//------------------------------------------------------------------------
25
26#define maxExtCode 16
27
28struct UnicodeMapExt {
29 Unicode u; // Unicode char
30 char code[maxExtCode];
31 Guint nBytes;
32};
33
34//------------------------------------------------------------------------
35
36UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
37 FILE *f;
38 UnicodeMap *map;
39 UnicodeMapRange *range;
40 UnicodeMapExt *eMap;
41 int size, eMapsSize;
42 char buf[256];
43 int line, nBytes, i, x;
44 char *tok1, *tok2, *tok3;
45
46 if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
47 error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
48 encodingNameA->getCString());
49 return NULL;
50 }
51
52 map = new UnicodeMap(encodingNameA->copy());
53
54 size = 8;
55 map->ranges = (UnicodeMapRange *)gmalloc(size * sizeof(UnicodeMapRange));
56 eMapsSize = 0;
57
58 line = 1;
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"))) {
63 tok3 = tok2;
64 tok2 = tok1;
65 }
66 nBytes = strlen(tok3) / 2;
67 if (nBytes <= 4) {
68 if (map->len == size) {
69 size *= 2;
70 map->ranges = (UnicodeMapRange *)
71 grealloc(map->ranges, size * sizeof(UnicodeMapRange));
72 }
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;
78 ++map->len;
79 } else if (tok2 == tok1) {
80 if (map->eMapsLen == eMapsSize) {
81 eMapsSize += 16;
82 map->eMaps = (UnicodeMapExt *)
83 grealloc(map->eMaps, eMapsSize * sizeof(UnicodeMapExt));
84 }
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;
90 }
91 eMap->nBytes = nBytes;
92 ++map->eMapsLen;
93 } else {
94 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
95 line, encodingNameA->getCString());
96 }
97 } else {
98 error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
99 line, encodingNameA->getCString());
100 }
101 ++line;
102 }
103
104 return map;
105}
106
107UnicodeMap::UnicodeMap(GString *encodingNameA) {
108 encodingName = encodingNameA;
109 kind = unicodeMapUser;
110 ranges = NULL;
111 len = 0;
112 eMaps = NULL;
113 eMapsLen = 0;
114 refCnt = 1;
115}
116
117UnicodeMap::UnicodeMap(char *encodingNameA,
118 UnicodeMapRange *rangesA, int lenA) {
119 encodingName = new GString(encodingNameA);
120 kind = unicodeMapResident;
121 ranges = rangesA;
122 len = lenA;
123 eMaps = NULL;
124 eMapsLen = 0;
125 refCnt = 1;
126}
127
128UnicodeMap::UnicodeMap(char *encodingNameA, UnicodeMapFunc funcA) {
129 encodingName = new GString(encodingNameA);
130 kind = unicodeMapFunc;
131 func = funcA;
132 eMaps = NULL;
133 eMapsLen = 0;
134 refCnt = 1;
135}
136
137UnicodeMap::~UnicodeMap() {
138 delete encodingName;
139 if (kind == unicodeMapUser && ranges) {
140 gfree(ranges);
141 }
142 if (eMaps) {
143 gfree(eMaps);
144 }
145}
146
147void UnicodeMap::incRefCnt() {
148 ++refCnt;
149}
150
151void UnicodeMap::decRefCnt() {
152 if (--refCnt == 0) {
153 delete this;
154 }
155}
156
157GBool UnicodeMap::match(GString *encodingNameA) {
158 return !encodingName->cmp(encodingNameA);
159}
160
161int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
162 int a, b, m, n, i, j;
163 Guint code;
164
165 if (kind == unicodeMapFunc) {
166 return (*func)(u, buf, bufSize);
167 }
168
169 a = 0;
170 b = len;
171 if (u < ranges[a].start) {
172 return 0;
173 }
174 // invariant: ranges[a].start <= u < ranges[b].start
175 while (b - a > 1) {
176 m = (a + b) / 2;
177 if (u >= ranges[m].start) {
178 a = m;
179 } else if (u < ranges[m].start) {
180 b = m;
181 }
182 }
183 if (u <= ranges[a].end) {
184 n = ranges[a].nBytes;
185 if (n > bufSize) {
186 return 0;
187 }
188 code = ranges[a].code + (u - ranges[a].start);
189 for (i = n - 1; i >= 0; --i) {
190 buf[i] = (char)(code & 0xff);
191 code >>= 8;
192 }
193 return n;
194 }
195
196 for (i = 0; i < eMapsLen; ++i) {
197 if (eMaps[i].u == u) {
198 n = eMaps[i].nBytes;
199 for (j = 0; j < n; ++j) {
200 buf[j] = eMaps[i].code[j];
201 }
202 return n;
203 }
204 }
205
206 return 0;
207}
208
209//------------------------------------------------------------------------
210
211UnicodeMapCache::UnicodeMapCache() {
212 int i;
213
214 for (i = 0; i < unicodeMapCacheSize; ++i) {
215 cache[i] = NULL;
216 }
217}
218
219UnicodeMapCache::~UnicodeMapCache() {
220 int i;
221
222 for (i = 0; i < unicodeMapCacheSize; ++i) {
223 if (cache[i]) {
224 cache[i]->decRefCnt();
225 }
226 }
227}
228
229UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
230 UnicodeMap *map;
231 int i, j;
232
233 if (cache[0] && cache[0]->match(encodingName)) {
234 cache[0]->incRefCnt();
235 return cache[0];
236 }
237 for (i = 1; i < unicodeMapCacheSize; ++i) {
238 if (cache[i] && cache[i]->match(encodingName)) {
239 map = cache[i];
240 for (j = i; j >= 1; --j) {
241 cache[j] = cache[j - 1];
242 }
243 cache[0] = map;
244 map->incRefCnt();
245 return map;
246 }
247 }
248 if ((map = UnicodeMap::parse(encodingName))) {
249 if (cache[unicodeMapCacheSize - 1]) {
250 cache[unicodeMapCacheSize - 1]->decRefCnt();
251 }
252 for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
253 cache[j] = cache[j - 1];
254 }
255 cache[0] = map;
256 map->incRefCnt();
257 return map;
258 }
259 return NULL;
260}