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];