author | sandman <sandman> | 2002-04-13 00:47:20 (UTC) |
---|---|---|
committer | sandman <sandman> | 2002-04-13 00:47:20 (UTC) |
commit | 98a1e3f36567639344f12932b629e526a8783aa8 (patch) (unidiff) | |
tree | 0433d296857faceeafc54f7deabddb621f45a933 /noncore/unsupported/qpdf/xpdf/UnicodeMap.cc | |
parent | 7e31b1fba119f69929d6744d7295555ff1727f4f (diff) | |
download | opie-98a1e3f36567639344f12932b629e526a8783aa8.zip opie-98a1e3f36567639344f12932b629e526a8783aa8.tar.gz opie-98a1e3f36567639344f12932b629e526a8783aa8.tar.bz2 |
CVS import of QPdf
Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/UnicodeMap.cc') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/unsupported/qpdf/xpdf/UnicodeMap.cc | 260 |
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 | |||
28 | struct UnicodeMapExt { | ||
29 | Unicode u; // Unicode char | ||
30 | char code[maxExtCode]; | ||
31 | Guint nBytes; | ||
32 | }; | ||
33 | |||
34 | //------------------------------------------------------------------------ | ||
35 | |||
36 | UnicodeMap *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 | |||
107 | UnicodeMap::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 | |||
117 | UnicodeMap::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 | |||
128 | UnicodeMap::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 | |||
137 | UnicodeMap::~UnicodeMap() { | ||
138 | delete encodingName; | ||
139 | if (kind == unicodeMapUser && ranges) { | ||
140 | gfree(ranges); | ||
141 | } | ||
142 | if (eMaps) { | ||
143 | gfree(eMaps); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | void UnicodeMap::incRefCnt() { | ||
148 | ++refCnt; | ||
149 | } | ||
150 | |||
151 | void UnicodeMap::decRefCnt() { | ||
152 | if (--refCnt == 0) { | ||
153 | delete this; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | GBool UnicodeMap::match(GString *encodingNameA) { | ||
158 | return !encodingName->cmp(encodingNameA); | ||
159 | } | ||
160 | |||
161 | int 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 | |||
211 | UnicodeMapCache::UnicodeMapCache() { | ||
212 | int i; | ||
213 | |||
214 | for (i = 0; i < unicodeMapCacheSize; ++i) { | ||
215 | cache[i] = NULL; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | UnicodeMapCache::~UnicodeMapCache() { | ||
220 | int i; | ||
221 | |||
222 | for (i = 0; i < unicodeMapCacheSize; ++i) { | ||
223 | if (cache[i]) { | ||
224 | cache[i]->decRefCnt(); | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
229 | UnicodeMap *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 | } | ||