root/middleware-offline/trunk/_src/eidmw/pteid-poppler/poppler/UnicodeMap.cc @ 226

Revision 226, 6.7 KB (checked in by vsilva, 8 years ago)

Improve PDF native Signature

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(errSyntaxError, -1,
64          "Couldn't find unicodeMap file for the '{0:t}' encoding",
65          encodingNameA);
66    return NULL;
67  }
68
69  map = new UnicodeMap(encodingNameA->copy());
70
71  size = 8;
72  map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange));
73  eMapsSize = 0;
74
75  line = 1;
76  while (getLine(buf, sizeof(buf), f)) {
77    if ((tok1 = strtok_r(buf, " \t\r\n", &tokptr)) &&
78        (tok2 = strtok_r(NULL, " \t\r\n", &tokptr))) {
79      if (!(tok3 = strtok_r(NULL, " \t\r\n", &tokptr))) {
80        tok3 = tok2;
81        tok2 = tok1;
82      }
83      nBytes = strlen(tok3) / 2;
84      if (nBytes <= 4) {
85        if (map->len == size) {
86          size *= 2;
87          map->ranges = (UnicodeMapRange *)
88            greallocn(map->ranges, size, sizeof(UnicodeMapRange));
89        }
90        range = &map->ranges[map->len];
91        sscanf(tok1, "%x", &range->start);
92        sscanf(tok2, "%x", &range->end);
93        sscanf(tok3, "%x", &range->code);
94        range->nBytes = nBytes;
95        ++map->len;
96      } else if (tok2 == tok1) {
97        if (map->eMapsLen == eMapsSize) {
98          eMapsSize += 16;
99          map->eMaps = (UnicodeMapExt *)
100            greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt));
101        }
102        eMap = &map->eMaps[map->eMapsLen];
103        sscanf(tok1, "%x", &eMap->u);
104        for (i = 0; i < nBytes; ++i) {
105          sscanf(tok3 + i*2, "%2x", &x);
106          eMap->code[i] = (char)x;
107        }
108        eMap->nBytes = nBytes;
109        ++map->eMapsLen;
110      } else {
111        error(errSyntaxError, -1,
112              "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding",
113              line, encodingNameA);
114      }
115    } else {
116      error(errSyntaxError, -1,
117            "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding",
118            line, encodingNameA);
119    }
120    ++line;
121  }
122
123  fclose(f);
124
125  return map;
126}
127
128UnicodeMap::UnicodeMap(GooString *encodingNameA) {
129  encodingName = encodingNameA;
130  unicodeOut = gFalse;
131  kind = unicodeMapUser;
132  ranges = NULL;
133  len = 0;
134  eMaps = NULL;
135  eMapsLen = 0;
136  refCnt = 1;
137#if MULTITHREADED
138  gInitMutex(&mutex);
139#endif
140}
141
142UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
143                       UnicodeMapRange *rangesA, int lenA) {
144  encodingName = new GooString(encodingNameA);
145  unicodeOut = unicodeOutA;
146  kind = unicodeMapResident;
147  ranges = rangesA;
148  len = lenA;
149  eMaps = NULL;
150  eMapsLen = 0;
151  refCnt = 1;
152#if MULTITHREADED
153  gInitMutex(&mutex);
154#endif
155}
156
157UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
158                       UnicodeMapFunc funcA) {
159  encodingName = new GooString(encodingNameA);
160  unicodeOut = unicodeOutA;
161  kind = unicodeMapFunc;
162  func = funcA;
163  eMaps = NULL;
164  eMapsLen = 0;
165  refCnt = 1;
166#if MULTITHREADED
167  gInitMutex(&mutex);
168#endif
169}
170
171UnicodeMap::~UnicodeMap() {
172  delete encodingName;
173  if (kind == unicodeMapUser && ranges) {
174    gfree(ranges);
175  }
176  if (eMaps) {
177    gfree(eMaps);
178  }
179#if MULTITHREADED
180  gDestroyMutex(&mutex);
181#endif
182}
183
184void UnicodeMap::incRefCnt() {
185#if MULTITHREADED
186  gLockMutex(&mutex);
187#endif
188  ++refCnt;
189#if MULTITHREADED
190  gUnlockMutex(&mutex);
191#endif
192}
193
194void UnicodeMap::decRefCnt() {
195  GBool done;
196
197#if MULTITHREADED
198  gLockMutex(&mutex);
199#endif
200  done = --refCnt == 0;
201#if MULTITHREADED
202  gUnlockMutex(&mutex);
203#endif
204  if (done) {
205    delete this;
206  }
207}
208
209GBool UnicodeMap::match(GooString *encodingNameA) {
210  return !encodingName->cmp(encodingNameA);
211}
212
213int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
214  int a, b, m, n, i, j;
215  Guint code;
216
217  if (kind == unicodeMapFunc) {
218    return (*func)(u, buf, bufSize);
219  }
220
221  a = 0;
222  b = len;
223  if (u >= ranges[a].start) {
224    // invariant: ranges[a].start <= u < ranges[b].start
225    while (b - a > 1) {
226      m = (a + b) / 2;
227      if (u >= ranges[m].start) {
228        a = m;
229      } else if (u < ranges[m].start) {
230        b = m;
231      }
232    }
233    if (u <= ranges[a].end) {
234      n = ranges[a].nBytes;
235      if (n > bufSize) {
236        return 0;
237      }
238      code = ranges[a].code + (u - ranges[a].start);
239      for (i = n - 1; i >= 0; --i) {
240        buf[i] = (char)(code & 0xff);
241        code >>= 8;
242      }
243      return n;
244    }
245  }
246
247  for (i = 0; i < eMapsLen; ++i) {
248    if (eMaps[i].u == u) {
249      n = eMaps[i].nBytes;
250      for (j = 0; j < n; ++j) {
251        buf[j] = eMaps[i].code[j];
252      }
253      return n;
254    }
255  }
256
257  return 0;
258}
259
260//------------------------------------------------------------------------
261
262UnicodeMapCache::UnicodeMapCache() {
263  int i;
264
265  for (i = 0; i < unicodeMapCacheSize; ++i) {
266    cache[i] = NULL;
267  }
268}
269
270UnicodeMapCache::~UnicodeMapCache() {
271  int i;
272
273  for (i = 0; i < unicodeMapCacheSize; ++i) {
274    if (cache[i]) {
275      cache[i]->decRefCnt();
276    }
277  }
278}
279
280UnicodeMap *UnicodeMapCache::getUnicodeMap(GooString *encodingName) {
281  UnicodeMap *map;
282  int i, j;
283
284  if (cache[0] && cache[0]->match(encodingName)) {
285    cache[0]->incRefCnt();
286    return cache[0];
287  }
288  for (i = 1; i < unicodeMapCacheSize; ++i) {
289    if (cache[i] && cache[i]->match(encodingName)) {
290      map = cache[i];
291      for (j = i; j >= 1; --j) {
292        cache[j] = cache[j - 1];
293      }
294      cache[0] = map;
295      map->incRefCnt();
296      return map;
297    }
298  }
299  if ((map = UnicodeMap::parse(encodingName))) {
300    if (cache[unicodeMapCacheSize - 1]) {
301      cache[unicodeMapCacheSize - 1]->decRefCnt();
302    }
303    for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
304      cache[j] = cache[j - 1];
305    }
306    cache[0] = map;
307    map->incRefCnt();
308    return map;
309  }
310  return NULL;
311}
Note: See TracBrowser for help on using the browser.