source: trunk/poppler/mypoppler/poppler/UnicodeMap.cc @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

File size: 6.7 KB
Line 
1//========================================================================
2//
3// UnicodeMap.cc
4//
5// Copyright 2001-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2010 Jakub Wilk <ubanus@users.sf.net>
17//
18// To see a description of the changes please see the Changelog file that
19// came with your tarball or type make ChangeLog if you are building from git
20//
21//========================================================================
22
23#include <config.h>
24
25#ifdef USE_GCC_PRAGMAS
26#pragma implementation
27#endif
28
29#include <stdio.h>
30#include <string.h>
31#include "goo/gmem.h"
32#include "goo/gfile.h"
33#include "goo/GooString.h"
34#include "goo/GooList.h"
35#include "Error.h"
36#include "GlobalParams.h"
37#include "UnicodeMap.h"
38
39//------------------------------------------------------------------------
40
41#define maxExtCode 16
42
43struct UnicodeMapExt {
44  Unicode u;                    // Unicode char
45  char code[maxExtCode];
46  Guint nBytes;
47};
48
49//------------------------------------------------------------------------
50
51UnicodeMap *UnicodeMap::parse(GooString *encodingNameA) {
52  FILE *f;
53  UnicodeMap *map;
54  UnicodeMapRange *range;
55  UnicodeMapExt *eMap;
56  int size, eMapsSize;
57  char buf[256];
58  int line, nBytes, i, x;
59  char *tok1, *tok2, *tok3;
60  char *tokptr;
61
62  if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
63    error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
64          encodingNameA->getCString());
65    return NULL;
66  }
67
68  map = new UnicodeMap(encodingNameA->copy());
69
70  size = 8;
71  map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange));
72  eMapsSize = 0;
73
74  line = 1;
75  while (getLine(buf, sizeof(buf), f)) {
76    if ((tok1 = strtok_r(buf, " \t\r\n", &tokptr)) &&
77        (tok2 = strtok_r(NULL, " \t\r\n", &tokptr))) {
78      if (!(tok3 = strtok_r(NULL, " \t\r\n", &tokptr))) {
79        tok3 = tok2;
80        tok2 = tok1;
81      }
82      nBytes = strlen(tok3) / 2;
83      if (nBytes <= 4) {
84        if (map->len == size) {
85          size *= 2;
86          map->ranges = (UnicodeMapRange *)
87            greallocn(map->ranges, size, sizeof(UnicodeMapRange));
88        }
89        range = &map->ranges[map->len];
90        sscanf(tok1, "%x", &range->start);
91        sscanf(tok2, "%x", &range->end);
92        sscanf(tok3, "%x", &range->code);
93        range->nBytes = nBytes;
94        ++map->len;
95      } else if (tok2 == tok1) {
96        if (map->eMapsLen == eMapsSize) {
97          eMapsSize += 16;
98          map->eMaps = (UnicodeMapExt *)
99            greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt));
100        }
101        eMap = &map->eMaps[map->eMapsLen];
102        sscanf(tok1, "%x", &eMap->u);
103        for (i = 0; i < nBytes; ++i) {
104          sscanf(tok3 + i*2, "%2x", &x);
105          eMap->code[i] = (char)x;
106        }
107        eMap->nBytes = nBytes;
108        ++map->eMapsLen;
109      } else {
110        error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
111              line, encodingNameA->getCString());
112      }
113    } else {
114      error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
115            line, encodingNameA->getCString());
116    }
117    ++line;
118  }
119
120  fclose(f);
121
122  return map;
123}
124
125UnicodeMap::UnicodeMap(GooString *encodingNameA) {
126  encodingName = encodingNameA;
127  unicodeOut = gFalse;
128  kind = unicodeMapUser;
129  ranges = NULL;
130  len = 0;
131  eMaps = NULL;
132  eMapsLen = 0;
133  refCnt = 1;
134#if MULTITHREADED
135  gInitMutex(&mutex);
136#endif
137}
138
139UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
140                       UnicodeMapRange *rangesA, int lenA) {
141  encodingName = new GooString(encodingNameA);
142  unicodeOut = unicodeOutA;
143  kind = unicodeMapResident;
144  ranges = rangesA;
145  len = lenA;
146  eMaps = NULL;
147  eMapsLen = 0;
148  refCnt = 1;
149#if MULTITHREADED
150  gInitMutex(&mutex);
151#endif
152}
153
154UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA,
155                       UnicodeMapFunc funcA) {
156  encodingName = new GooString(encodingNameA);
157  unicodeOut = unicodeOutA;
158  kind = unicodeMapFunc;
159  func = funcA;
160  eMaps = NULL;
161  eMapsLen = 0;
162  refCnt = 1;
163#if MULTITHREADED
164  gInitMutex(&mutex);
165#endif
166}
167
168UnicodeMap::~UnicodeMap() {
169  delete encodingName;
170  if (kind == unicodeMapUser && ranges) {
171    gfree(ranges);
172  }
173  if (eMaps) {
174    gfree(eMaps);
175  }
176#if MULTITHREADED
177  gDestroyMutex(&mutex);
178#endif
179}
180
181void UnicodeMap::incRefCnt() {
182#if MULTITHREADED
183  gLockMutex(&mutex);
184#endif
185  ++refCnt;
186#if MULTITHREADED
187  gUnlockMutex(&mutex);
188#endif
189}
190
191void UnicodeMap::decRefCnt() {
192  GBool done;
193
194#if MULTITHREADED
195  gLockMutex(&mutex);
196#endif
197  done = --refCnt == 0;
198#if MULTITHREADED
199  gUnlockMutex(&mutex);
200#endif
201  if (done) {
202    delete this;
203  }
204}
205
206GBool UnicodeMap::match(GooString *encodingNameA) {
207  return !encodingName->cmp(encodingNameA);
208}
209
210int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
211  int a, b, m, n, i, j;
212  Guint code;
213
214  if (kind == unicodeMapFunc) {
215    return (*func)(u, buf, bufSize);
216  }
217
218  a = 0;
219  b = len;
220  if (u >= ranges[a].start) {
221    // invariant: ranges[a].start <= u < ranges[b].start
222    while (b - a > 1) {
223      m = (a + b) / 2;
224      if (u >= ranges[m].start) {
225        a = m;
226      } else if (u < ranges[m].start) {
227        b = m;
228      }
229    }
230    if (u <= ranges[a].end) {
231      n = ranges[a].nBytes;
232      if (n > bufSize) {
233        return 0;
234      }
235      code = ranges[a].code + (u - ranges[a].start);
236      for (i = n - 1; i >= 0; --i) {
237        buf[i] = (char)(code & 0xff);
238        code >>= 8;
239      }
240      return n;
241    }
242  }
243
244  for (i = 0; i < eMapsLen; ++i) {
245    if (eMaps[i].u == u) {
246      n = eMaps[i].nBytes;
247      for (j = 0; j < n; ++j) {
248        buf[j] = eMaps[i].code[j];
249      }
250      return n;
251    }
252  }
253
254  return 0;
255}
256
257//------------------------------------------------------------------------
258
259UnicodeMapCache::UnicodeMapCache() {
260  int i;
261
262  for (i = 0; i < unicodeMapCacheSize; ++i) {
263    cache[i] = NULL;
264  }
265}
266
267UnicodeMapCache::~UnicodeMapCache() {
268  int i;
269
270  for (i = 0; i < unicodeMapCacheSize; ++i) {
271    if (cache[i]) {
272      cache[i]->decRefCnt();
273    }
274  }
275}
276
277UnicodeMap *UnicodeMapCache::getUnicodeMap(GooString *encodingName) {
278  UnicodeMap *map;
279  int i, j;
280
281  if (cache[0] && cache[0]->match(encodingName)) {
282    cache[0]->incRefCnt();
283    return cache[0];
284  }
285  for (i = 1; i < unicodeMapCacheSize; ++i) {
286    if (cache[i] && cache[i]->match(encodingName)) {
287      map = cache[i];
288      for (j = i; j >= 1; --j) {
289        cache[j] = cache[j - 1];
290      }
291      cache[0] = map;
292      map->incRefCnt();
293      return map;
294    }
295  }
296  if ((map = UnicodeMap::parse(encodingName))) {
297    if (cache[unicodeMapCacheSize - 1]) {
298      cache[unicodeMapCacheSize - 1]->decRefCnt();
299    }
300    for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
301      cache[j] = cache[j - 1];
302    }
303    cache[0] = map;
304    map->incRefCnt();
305    return map;
306  }
307  return NULL;
308}
Note: See TracBrowser for help on using the repository browser.