fontenc.c revision d63fdb69
1/* 2Copyright (c) 1998-2001 by Juliusz Chroboczek 3 4Permission is hereby granted, free of charge, to any person obtaining a copy 5of this software and associated documentation files (the "Software"), to deal 6in the Software without restriction, including without limitation the rights 7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8copies of the Software, and to permit persons to whom the Software is 9furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20THE SOFTWARE. 21*/ 22 23/* $XdotOrg: xc/lib/font/fontfile/fontenc.c,v 1.3 2005/07/03 07:01:00 daniels Exp $ */ 24/* $XFree86: xc/lib/font/fontfile/fontenc.c,v 1.15 2003/02/20 03:25:19 dawes Exp $ */ 25 26/* Backend-independent encoding code */ 27 28#include <string.h> 29 30#if defined(__SCO__) || defined(__UNIXWARE__) 31#include <strings.h> 32#endif 33 34#ifndef FONTENC_NO_LIBFONT 35 36#include <X11/fonts/fontmisc.h> /* defines xalloc and friends */ 37#include <X11/fonts/fntfilst.h> 38 39#else 40 41#include <stdlib.h> 42#define xalloc(n) malloc(n) 43#define xrealloc(p, n) realloc(p, n) 44#define xfree(p) free(p) 45#define FALSE 0 46#define TRUE 1 47#define MAXFONTNAMELEN 1024 48#define MAXFONTFILENAMELEN 1024 49 50#endif /* FONTENC_NO_FONTFILE */ 51 52#include <X11/fonts/fontenc.h> 53#include "fontencI.h" 54 55/* Functions local to this file */ 56 57static FontEncPtr FontEncLoad(const char*, const char*); 58 59/* Early versions of this code only knew about hardwired encodings, 60 hence the following data. Now that the code knows how to load an 61 encoding from a file, most of these tables could go away. */ 62 63/* At any rate, no new hardcoded encodings will be added. */ 64 65static FontMapRec iso10646[]= 66{ 67 {FONT_ENCODING_UNICODE,0,0,NULL,NULL,NULL,NULL,NULL}, 68 {0,0,0,NULL,NULL,NULL,NULL,NULL} 69}; 70 71/* Notice that the Apple encodings do not have all the characters in 72 the corresponding ISO 8859, and therefore the table has some holes. 73 There's not much more we can do with fonts without a Unicode cmap 74 unless we are willing to combine cmaps (which we are not). */ 75 76static const unsigned short 77iso8859_1_apple_roman[]= 78{ 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x00, 0xA4, 79 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0x00, 0xA8, 0xF8, 80 0xA1, 0xB1, 0x00, 0x00, 0xAB, 0xB5, 0xA6, 0xE1, 81 0xFC, 0x00, 0xBC, 0xC8, 0x00, 0x00, 0x00, 0xC0, 82 0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82, 83 0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC, 84 0x00, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0x00, 85 0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0x00, 0x00, 0xA7, 86 0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D, 87 0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, 88 0x00, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6, 89 0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0x00, 0x00, 0xD8 }; 90 91/* Cannot use simple_recode because need to eliminate 0x80<=code<0xA0 */ 92static unsigned 93iso8859_1_to_apple_roman(unsigned isocode, void *client_data) 94{ 95 if(isocode<=0x80) 96 return isocode; 97 else if(isocode>=0xA0) 98 return iso8859_1_apple_roman[isocode-0xA0]; 99 else 100 return 0; 101} 102 103static FontMapRec iso8859_1[]= 104{ 105 {FONT_ENCODING_TRUETYPE,2,2,NULL,NULL,NULL,NULL,NULL}, /* ISO 8859-1 */ 106 {FONT_ENCODING_UNICODE,0,0,NULL,NULL,NULL,NULL,NULL}, /* ISO 8859-1 coincides with Unicode*/ 107 {FONT_ENCODING_TRUETYPE,1,0,iso8859_1_to_apple_roman,NULL,NULL,NULL,NULL}, 108 {0,0,0,NULL,NULL,NULL,NULL,NULL} 109}; 110 111static const unsigned short iso8859_2_tophalf[]= 112{ 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 113 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, 114 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 115 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, 116 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 117 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, 118 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 119 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 120 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 121 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, 122 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 123 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 }; 124 125static FontEncSimpleMapRec iso8859_2_to_unicode_map= 126{0x60, 0, 0xA0, iso8859_2_tophalf }; 127 128static const unsigned short iso8859_2_apple_centeuro[]= 129{ 0xCA, 0x84, 0x00, 0xFC, 0x00, 0xBB, 0xE5, 0xA4, 130 0xAC, 0xE1, 0x00, 0xE8, 0x8F, 0x00, 0xEB, 0xFB, 131 0xA1, 0x88, 0x00, 0xB8, 0x00, 0xBC, 0xE6, 0xFF, 132 0x00, 0xE4, 0x00, 0xE9, 0x90, 0x00, 0xEC, 0xFD, 133 0xD9, 0xE7, 0x00, 0x00, 0x80, 0xBD, 0x8C, 0x00, 134 0x89, 0x83, 0xA2, 0x00, 0x9D, 0xEA, 0x00, 0x91, 135 0x00, 0xC1, 0xC5, 0xEE, 0xEF, 0xCC, 0x85, 0x00, 136 0xDB, 0xF1, 0xF2, 0xF4, 0x86, 0xF8, 0x00, 0xA7, 137 0xDA, 0x87, 0x00, 0x00, 0x8A, 0xBE, 0x8D, 0x00, 138 0x8B, 0x8E, 0xAB, 0x00, 0x9E, 0x92, 0x00, 0x93, 139 0x00, 0xC4, 0xCB, 0x97, 0x99, 0xCE, 0x9A, 0xD6, 140 0xDE, 0xF3, 0x9C, 0xF5, 0x9F, 0xF9, 0x00, 0x00 }; 141 142static unsigned 143iso8859_2_to_apple_centeuro(unsigned isocode, void *client_data) 144{ 145 if(isocode<=0x80) 146 return isocode; 147 else if(isocode>=0xA0) 148 return iso8859_2_apple_centeuro[isocode-0xA0]; 149 else 150 return 0; 151} 152 153 154static FontMapRec iso8859_2[]= 155{ 156 {FONT_ENCODING_UNICODE,0,0, 157 FontEncSimpleRecode,NULL,&iso8859_2_to_unicode_map,NULL,NULL}, 158 {FONT_ENCODING_TRUETYPE,1,29,iso8859_2_to_apple_centeuro,NULL,NULL,NULL,NULL}, 159 {0,0,0,NULL,NULL,NULL,NULL,NULL} 160}; 161 162static const unsigned short iso8859_3_tophalf[]= 163{ 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7, 164 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B, 165 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 166 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C, 167 0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7, 168 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 169 0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 170 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, 171 0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7, 172 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 173 0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 174 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9}; 175 176static FontEncSimpleMapRec iso8859_3_to_unicode_map= 177{ 0x60, 0, 0xA0, iso8859_3_tophalf }; 178 179static FontMapRec iso8859_3[]= 180{ 181 {FONT_ENCODING_UNICODE,0,0, 182 FontEncSimpleRecode,NULL,&iso8859_3_to_unicode_map,NULL,NULL}, 183 {0,0,0,NULL,NULL,NULL,NULL,NULL} 184}; 185 186 187static const unsigned short iso8859_4_tophalf[]= 188{ 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 189 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, 190 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 191 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, 192 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 193 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, 194 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 195 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, 196 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 197 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, 198 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 199 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9, 200}; 201 202static FontEncSimpleMapRec iso8859_4_to_unicode_map= 203{ 0x60, 0, 0xA0, iso8859_4_tophalf }; 204 205static FontMapRec iso8859_4[]= 206{ 207 {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL, 208 &iso8859_4_to_unicode_map,NULL,NULL}, 209 {0,0,0,NULL,NULL,NULL,NULL,NULL} 210}; 211 212static const unsigned short iso8859_5_tophalf[]= 213{ 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 214 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, 215 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 216 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 217 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 218 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 219 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 220 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 221 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 222 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 223 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 224 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F}; 225 226static FontEncSimpleMapRec iso8859_5_to_unicode_map= 227{ 0x60, 0, 0xA0, iso8859_5_tophalf }; 228 229static const unsigned short 230iso8859_5_apple_cyrillic[]= 231{ 0xCA, 0xDD, 0xAB, 0xAE, 0xB8, 0xC1, 0xA7, 0xBA, 232 0xB7, 0xBC, 0xBE, 0xCB, 0xCD, 0x00, 0xD8, 0xDA, 233 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 234 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 235 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 236 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 237 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 238 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 239 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 240 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, 241 0xDC, 0xDE, 0xAC, 0xAF, 0xB9, 0xCF, 0xB4, 0xBB, 242 0xC0, 0xBD, 0xBF, 0xCC, 0xCE, 0xA4, 0xD9, 0xDB }; 243 244static unsigned 245iso8859_5_to_apple_cyrillic(unsigned isocode, void *client_data) 246{ 247 if(isocode<=0x80) 248 return isocode; 249 else if(isocode>=0xA0) 250 return iso8859_5_apple_cyrillic[isocode-0x80]; 251 else return 0; 252} 253 254static FontMapRec iso8859_5[]= 255{ 256 {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL, 257 &iso8859_5_to_unicode_map,NULL,NULL}, 258 {FONT_ENCODING_TRUETYPE,1,7,iso8859_5_to_apple_cyrillic,NULL,NULL,NULL,NULL}, 259 {0,0,0,NULL,NULL,NULL,NULL,NULL} 260}; 261 262/* ISO 8859-6 seems useless for serving fonts (not enough presentation 263 * forms). What do Arabic-speakers use? */ 264 265static unsigned 266iso8859_6_to_unicode(unsigned isocode, void *client_data) 267{ 268 if(isocode<=0xA0 || isocode==0xA4 || isocode==0xAD) 269 return isocode; 270 else if(isocode==0xAC || isocode==0xBB || 271 (isocode>=0xBF && isocode<=0xDA) || 272 (isocode>=0xE0 && isocode<=0xEF) || 273 (isocode>=0xF0 && isocode<=0xF2)) 274 return isocode-0xA0+0x0600; 275 else 276 return 0; 277} 278 279static FontMapRec iso8859_6[]= 280{ 281 {FONT_ENCODING_UNICODE,0,0,iso8859_6_to_unicode,NULL,NULL,NULL,NULL}, 282 {0,0,0,NULL,NULL,NULL,NULL,NULL} 283}; 284 285static unsigned 286iso8859_7_to_unicode(unsigned isocode, void *client_data) 287{ 288 if(isocode<=0xA0 || 289 (isocode>=0xA3 && isocode<=0xAD) || 290 (isocode>=0xB0 && isocode<=0xB3) || 291 isocode==0xB7 || isocode==0xBB || isocode==0xBD) 292 return isocode; 293 else if(isocode==0xA1) 294 return 0x02BD; 295 else if(isocode==0xA2) 296 return 0x02BC; 297 else if(isocode==0xAF) 298 return 0x2015; 299 else if(isocode>=0xB4) 300 return isocode-0xA0+0x0370; 301 else 302 return 0; 303} 304 305static FontMapRec iso8859_7[]= 306{ 307 {FONT_ENCODING_UNICODE,0,0,iso8859_7_to_unicode,NULL,NULL,NULL,NULL}, 308 {0,0,0,NULL,NULL,NULL,NULL,NULL} 309}; 310 311static unsigned 312iso8859_8_to_unicode(unsigned isocode, void *client_data) 313{ 314 if(isocode==0xA1) 315 return 0; 316 else if(isocode<0xBF) 317 return isocode; 318 else if(isocode==0xDF) 319 return 0x2017; 320 else if(isocode>=0xE0 && isocode<=0xFA) 321 return isocode+0x04F0; 322 else 323 return 0; 324} 325 326static FontMapRec iso8859_8[]= 327{ 328 {FONT_ENCODING_UNICODE,0,0,iso8859_8_to_unicode,NULL,NULL,NULL,NULL}, 329 {0,0,0,NULL,NULL,NULL,NULL,NULL} 330}; 331 332static unsigned 333iso8859_9_to_unicode(unsigned isocode, void *client_data) 334{ 335 switch(isocode) { 336 case 0xD0: return 0x011E; 337 case 0xDD: return 0x0130; 338 case 0xDE: return 0x015E; 339 case 0xF0: return 0x011F; 340 case 0xFD: return 0x0131; 341 case 0xFE: return 0x015F; 342 default: return isocode; 343 } 344} 345 346static FontMapRec iso8859_9[]= 347{ 348 {FONT_ENCODING_UNICODE,0,0,iso8859_9_to_unicode,NULL,NULL,NULL,NULL}, 349 {0,0,0,NULL,NULL,NULL,NULL,NULL} 350}; 351 352static const unsigned short iso8859_10_tophalf[]= 353{ 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 354 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, 355 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 356 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B, 357 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 358 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, 359 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 360 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 361 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 362 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, 363 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 364 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138}; 365 366static FontEncSimpleMapRec iso8859_10_to_unicode_map= 367{ 0x60, 0, 0xA0, iso8859_10_tophalf }; 368 369static FontMapRec iso8859_10[]= 370{ 371 {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL, 372 &iso8859_10_to_unicode_map,NULL,NULL}, 373 {0,0,0,NULL,NULL,NULL,NULL,NULL} 374}; 375 376static unsigned 377iso8859_15_to_unicode(unsigned isocode, void *client_data) 378{ 379 switch(isocode) { 380 case 0xA4: return 0x20AC; 381 case 0xA6: return 0x0160; 382 case 0xA8: return 0x0161; 383 case 0xB4: return 0x017D; 384 case 0xB8: return 0x017E; 385 case 0xBC: return 0x0152; 386 case 0xBD: return 0x0153; 387 case 0xBE: return 0x0178; 388 default: return isocode; 389 } 390} 391 392static FontMapRec iso8859_15[]= 393{ 394 {FONT_ENCODING_UNICODE,0,0,iso8859_15_to_unicode,NULL,NULL,NULL,NULL}, 395 {0,0,0,NULL,NULL,NULL,NULL,NULL} 396}; 397 398static const unsigned short koi8_r_tophalf[]= 399{ 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, 400 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, 401 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248, 402 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, 403 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, 404 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 405 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, 406 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9, 407 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 408 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 409 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 410 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, 411 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 412 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 413 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 414 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A}; 415 416static FontEncSimpleMapRec koi8_r_to_unicode_map= 417{ 0x80, 0, 0x80, koi8_r_tophalf }; 418 419 420static FontMapRec koi8_r[]= 421{ 422 {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL, 423 &koi8_r_to_unicode_map,NULL,NULL}, 424 {0,0,0,NULL,NULL,NULL,NULL,NULL} 425}; 426 427static unsigned 428koi8_ru_to_unicode(unsigned koicode, void *client_data) 429{ 430 switch(koicode) { 431 case 0x93: return 0x201C; 432 case 0x96: return 0x201D; 433 case 0x97: return 0x2014; 434 case 0x98: return 0x2116; 435 case 0x99: return 0x2122; 436 case 0x9B: return 0x00BB; 437 case 0x9C: return 0x00AE; 438 case 0x9D: return 0x00AB; 439 case 0x9F: return 0x00A4; 440 case 0xA4: return 0x0454; 441 case 0xA6: return 0x0456; 442 case 0xA7: return 0x0457; 443 case 0xAD: return 0x0491; 444 case 0xAE: return 0x045E; 445 case 0xB4: return 0x0404; 446 case 0xB6: return 0x0406; 447 case 0xB7: return 0x0407; 448 case 0xBD: return 0x0490; 449 case 0xBE: return 0x040E; 450 default: return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map); 451 } 452} 453 454static FontMapRec koi8_ru[]= 455{ 456 {FONT_ENCODING_UNICODE,0,0,koi8_ru_to_unicode,NULL,NULL,NULL,NULL}, 457 {0,0,0,NULL,NULL,NULL,NULL,NULL} 458}; 459 460/* koi8-e, ISO-IR-111 or ECMA-Cyrillic */ 461 462static const unsigned short koi8_e_A0_BF[]= 463{ 0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, 464 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00AD, 0x045E, 0x045F, 465 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, 466 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00A4, 0x040E, 0x040F }; 467 468static unsigned 469koi8_e_to_unicode(unsigned koicode, void *client_data) 470{ 471 if(koicode<0xA0) 472 return koicode; 473 else if(koicode<0xC0) 474 return koi8_e_A0_BF[koicode-0xA0]; 475 else 476 return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map); 477} 478 479static FontMapRec koi8_e[]= 480{ 481 {FONT_ENCODING_UNICODE,0,0,koi8_e_to_unicode,NULL,NULL,NULL,NULL}, 482 {0,0,0,NULL,NULL,NULL,NULL,NULL} 483}; 484 485/* Koi8 unified */ 486 487static const unsigned short koi8_uni_80_BF[]= 488{ 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, 489 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, 490 0x2591, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 491 0x00A9, 0x2122, 0x00A0, 0x00BB, 0x00AE, 0x00AB, 0x00B7, 0x00A4, 492 0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, 493 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x0491, 0x045E, 0x045F, 494 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, 495 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x0490, 0x040E, 0x040F }; 496 497static unsigned 498koi8_uni_to_unicode(unsigned koicode, void *client_data) 499{ 500 if(koicode<0x80) 501 return koicode; 502 else if(koicode<0xC0) 503 return koi8_uni_80_BF[koicode-0x80]; 504 else 505 return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map); 506} 507 508static FontMapRec koi8_uni[]= 509{ 510 {FONT_ENCODING_UNICODE,0,0,koi8_uni_to_unicode,NULL,NULL,NULL,NULL}, 511 {0,0,0,NULL,NULL,NULL,NULL,NULL} 512}; 513 514/* Ukrainian variant of Koi8-R; see RFC 2319 */ 515 516static unsigned 517koi8_u_to_unicode(unsigned koicode, void *client_data) 518{ 519 switch(koicode) { 520 case 0xA4: return 0x0454; 521 case 0xA6: return 0x0456; 522 case 0xA7: return 0x0457; 523 case 0xAD: return 0x0491; 524 case 0xB4: return 0x0404; 525 case 0xB6: return 0x0406; 526 case 0xB7: return 0x0407; 527 case 0xBD: return 0x0490; 528 default: return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map); 529 } 530} 531 532static FontMapRec koi8_u[]= 533{ 534 {FONT_ENCODING_UNICODE,0,0,koi8_u_to_unicode,NULL,NULL,NULL}, 535 {0,0,0,NULL,NULL,NULL,NULL,NULL} 536}; 537 538/* Microsoft Symbol, which is only meaningful for TrueType fonts, is 539 treated specially in ftenc.c, where we add usFirstCharIndex-0x20 to 540 the glyph index before applying the cmap. Lovely design. */ 541 542static FontMapRec microsoft_symbol[]= 543{{FONT_ENCODING_TRUETYPE,3,0,NULL,NULL,NULL,NULL,NULL}, 544 /* You never know */ 545 {FONT_ENCODING_TRUETYPE,3,1,NULL,NULL,NULL,NULL,NULL}, 546 {0,0,0,NULL,NULL,NULL,NULL,NULL}}; 547 548static FontMapRec apple_roman[]= 549{{FONT_ENCODING_TRUETYPE,1,0,NULL,NULL,NULL,NULL,NULL}, 550 {0,0,0,NULL,NULL,NULL,NULL,NULL}}; 551 552/* The data for recodings */ 553 554/* For compatibility with X11R6.4. Losers. */ 555static char *iso8859_15_aliases[2]={"fcd8859-15",NULL}; 556 557static FontEncRec initial_encodings[]= 558{ 559 {"iso10646-1",NULL,256*256,0,iso10646,NULL,0,0}, /* Unicode */ 560 {"iso8859-1",NULL,256,0,iso8859_1,NULL,0,0}, /* Latin 1 (West European) */ 561 {"iso8859-2",NULL,256,0,iso8859_2,NULL,0,0}, /* Latin 2 (East European) */ 562 {"iso8859-3",NULL,256,0,iso8859_3,NULL,0,0}, /* Latin 3 (South European) */ 563 {"iso8859-4",NULL,256,0,iso8859_4,NULL,0,0}, /* Latin 4 (North European) */ 564 {"iso8859-5",NULL,256,0,iso8859_5,NULL,0,0}, /* Cyrillic */ 565 {"iso8859-6",NULL,256,0,iso8859_6,NULL,0,0}, /* Arabic */ 566 {"iso8859-7",NULL,256,0,iso8859_7,NULL,0,0}, /* Greek */ 567 {"iso8859-8",NULL,256,0,iso8859_8,NULL,0,0}, /* Hebrew */ 568 {"iso8859-9",NULL,256,0,iso8859_9,NULL,0,0}, /* Latin 5 (Turkish) */ 569 {"iso8859-10",NULL,256,0,iso8859_10,NULL,0,0}, /* Latin 6 (Nordic) */ 570 {"iso8859-15",iso8859_15_aliases,256,0,iso8859_15,NULL,0,0}, /* Latin 9 */ 571 {"koi8-r",NULL,256,0,koi8_r,NULL,0,0}, /* Russian */ 572 {"koi8-ru",NULL,256,0,koi8_ru,NULL,0,0}, /* Ukrainian */ 573 {"koi8-uni",NULL,256,0,koi8_uni,NULL,0,0}, /* Russian/Ukrainian/Bielorussian */ 574 {"koi8-e",NULL,256,0,koi8_e,NULL,0,0}, /* ``European'' */ 575 {"koi8-u",NULL,256,0,koi8_u,NULL,0,0}, /* Ukrainian too */ 576 {"microsoft-symbol",NULL,256,0,microsoft_symbol,NULL,0,0}, 577 {"apple-roman",NULL,256,0,apple_roman,NULL,0,0}, 578 {NULL,NULL,0,0,NULL,NULL,0,0} 579}; 580 581static FontEncPtr font_encodings=NULL; 582 583static void 584define_initial_encoding_info(void) 585{ 586 FontEncPtr encoding; 587 FontMapPtr mapping; 588 589 font_encodings = initial_encodings; 590 for(encoding = font_encodings; ; encoding++) { 591 encoding->next = encoding + 1; 592 for(mapping = encoding->mappings; ; mapping++) { 593 mapping->next = mapping+1; 594 mapping->encoding = encoding; 595 if(mapping->next->type == 0) { 596 mapping->next = NULL; 597 break; 598 } 599 } 600 if(!encoding->next->name) { 601 encoding->next = NULL; 602 break; 603 } 604 } 605} 606 607 608char* 609FontEncFromXLFD(const char *name, int length) 610{ 611 const char *p; 612 char *q; 613 static char charset[MAXFONTNAMELEN]; 614 int len; 615 616 if(length > MAXFONTNAMELEN - 1) 617 return NULL; 618 619 if(name == NULL) 620 p = NULL; 621 else { 622 p = name + length - 1; 623 while(p > name && *p != '-') 624 p--; 625 p--; 626 while(p >= name && *p != '-') 627 p--; 628 if(p <= name) 629 p = NULL; 630 } 631 632 /* now p either is null or points at the '-' before the charset registry */ 633 634 if(p == NULL) 635 return NULL; 636 637 len = length - (p - name) - 1; 638 memcpy(charset, p+1, len); 639 charset[len] = 0; 640 641 /* check for a subset specification */ 642 if((q = strchr(charset, (int)'['))) 643 *q = 0; 644 645 return charset; 646} 647 648unsigned 649FontEncRecode(unsigned code, FontMapPtr mapping) 650{ 651 FontEncPtr encoding = mapping->encoding; 652 if(encoding && mapping->recode) { 653 if(encoding->row_size == 0) { 654 /* linear encoding */ 655 if(code < encoding->first || code>=encoding->size) 656 return 0; 657 } else { 658 /* matrix encoding */ 659 int row = code/0x100, col = code&0xFF; 660 if(row < encoding->first || row >= encoding->size || 661 col < encoding->first_col || col >= encoding->row_size) 662 return 0; 663 } 664 return (*mapping->recode)(code, mapping->client_data); 665 } else 666 return code; 667} 668 669char* 670FontEncName(unsigned code, FontMapPtr mapping) 671{ 672 FontEncPtr encoding = mapping->encoding; 673 if(encoding && mapping->name) { 674 if((encoding->row_size == 0 && code >= encoding->size) || 675 (encoding->row_size != 0 && 676 (code/0x100 >= encoding->size || 677 (code&0xFF) >= encoding->row_size))) 678 return NULL; 679 return (*mapping->name)(code, mapping->client_data); 680 } else 681 return NULL; 682} 683 684FontEncPtr 685FontEncFind(const char *encoding_name, const char *filename) 686{ 687 FontEncPtr encoding; 688 char **alias; 689 690 if(font_encodings == NULL) define_initial_encoding_info(); 691 692 for(encoding = font_encodings; encoding; encoding = encoding->next) { 693 if(!strcasecmp(encoding->name, encoding_name)) 694 return encoding; 695 if(encoding->aliases) 696 for(alias=encoding->aliases; *alias; alias++) 697 if(!strcasecmp(*alias, encoding_name)) 698 return encoding; 699 } 700 701 /* Unknown charset, try to load a definition file */ 702 return FontEncLoad(encoding_name, filename); 703} 704 705FontMapPtr 706FontMapFind(FontEncPtr encoding, int type, int pid, int eid) 707{ 708 FontMapPtr mapping; 709 if(encoding == NULL) 710 return NULL; 711 712 for(mapping = encoding->mappings; mapping; mapping = mapping->next) { 713 if(mapping->type != type) 714 continue; 715 if(pid > 0 && mapping->pid != pid) 716 continue; 717 if(eid > 0 && mapping->eid != eid) 718 continue; 719 return mapping; 720 } 721 return NULL; 722} 723 724FontMapPtr 725FontEncMapFind(const char *encoding_name, int type, int pid, int eid, 726 const char *filename) 727{ 728 FontEncPtr encoding; 729 FontMapPtr mapping; 730 731 encoding = FontEncFind(encoding_name, filename); 732 if(encoding == NULL) 733 return NULL; 734 mapping = FontMapFind(encoding, type, pid, eid); 735 return mapping; 736} 737 738static FontEncPtr 739FontEncLoad(const char *encoding_name, const char *filename) 740{ 741 FontEncPtr encoding; 742 743 encoding = FontEncReallyLoad(encoding_name, filename); 744 if (encoding == NULL) { 745 return NULL; 746 } else { 747 char **alias; 748 int found = 0; 749 750 /* Check whether the name is already known for this encoding */ 751 if(strcasecmp(encoding->name, encoding_name) == 0) { 752 found = 1; 753 } else { 754 if(encoding->aliases) { 755 for(alias=encoding->aliases; *alias; alias++) 756 if(!strcasecmp(*alias, encoding_name)) { 757 found = 1; 758 break; 759 } 760 } 761 } 762 763 if(!found) { 764 /* Add a new alias. This works because we know that this 765 particular encoding has been allocated dynamically */ 766 char **new_aliases; 767 char *new_name; 768 int numaliases = 0; 769 770 new_name = xalloc(strlen(encoding_name) + 1); 771 if(new_name == NULL) 772 return NULL; 773 strcpy(new_name, encoding_name); 774 if(encoding->aliases) { 775 for(alias = encoding->aliases; *alias; alias++) 776 numaliases++; 777 } 778 new_aliases = (char**)xalloc((numaliases+2)*sizeof(char*)); 779 if(new_aliases == NULL) { 780 xfree(new_name); 781 return NULL; 782 } 783 if(encoding->aliases) { 784 memcpy(new_aliases, encoding->aliases, numaliases*sizeof(char*)); 785 xfree(encoding->aliases); 786 } 787 new_aliases[numaliases] = new_name; 788 new_aliases[numaliases+1] = NULL; 789 encoding->aliases = new_aliases; 790 } 791 792 /* register the new encoding */ 793 encoding->next=font_encodings; 794 font_encodings=encoding; 795 796 return encoding; 797 } 798} 799 800unsigned 801FontEncSimpleRecode(unsigned code, void *client_data) 802{ 803 FontEncSimpleMapPtr map; 804 unsigned index; 805 806 map = client_data; 807 808 if(code > 0xFFFF || (map->row_size && (code&0xFF) >= map->row_size)) 809 return 0; 810 811 if(map->row_size) 812 index = (code&0xFF)+(code>>8)*map->row_size; 813 else 814 index = code; 815 816 if(map->map && index>=map->first && index<map->first+map->len) 817 return map->map[index-map->first]; 818 else 819 return code; 820} 821 822char * 823FontEncSimpleName(unsigned code, void *client_data) 824{ 825 FontEncSimpleNamePtr map; 826 827 map = client_data; 828 if(map && code >= map->first && code<map->first+map->len) 829 return map->map[code-map->first]; 830 else 831 return NULL; 832} 833 834unsigned 835FontEncUndefinedRecode(unsigned code, void *client_data) 836{ 837 return code; 838} 839 840char * 841FontEncUndefinedName(unsigned code, void *client_data) 842{ 843 return NULL; 844} 845 846#define FONTENC_SEGMENT_SIZE 256 847#define FONTENC_SEGMENTS 256 848#define FONTENC_INVERSE_CODES (FONTENC_SEGMENT_SIZE * FONTENC_SEGMENTS) 849 850static unsigned int 851reverse_reverse(unsigned i, void* data) 852{ 853 int s, j; 854 unsigned **map = (unsigned**)data; 855 856 if(i >= FONTENC_INVERSE_CODES) 857 return 0; 858 859 if(map == NULL) 860 return 0; 861 862 s = i / FONTENC_SEGMENT_SIZE; 863 j = i % FONTENC_SEGMENT_SIZE; 864 865 if(map[s] == NULL) 866 return 0; 867 else 868 return map[s][j]; 869} 870 871static int 872tree_set(unsigned int **map, unsigned int i, unsigned int j) 873{ 874 int s, c; 875 876 if(i >= FONTENC_INVERSE_CODES) 877 return FALSE; 878 879 s = i / FONTENC_SEGMENT_SIZE; 880 c = i % FONTENC_SEGMENT_SIZE; 881 882 if(map[s] == NULL) { 883 map[s] = calloc(FONTENC_SEGMENT_SIZE, sizeof(int)); 884 if(map[s] == NULL) 885 return FALSE; 886 } 887 888 map[s][c] = j; 889 return TRUE; 890} 891 892FontMapReversePtr 893FontMapReverse(FontMapPtr mapping) 894{ 895 FontEncPtr encoding = mapping->encoding; 896 FontMapReversePtr reverse = NULL; 897 unsigned int **map = NULL; 898 int i, j, k; 899 900 if(encoding == NULL) goto bail; 901 902 map = calloc(FONTENC_SEGMENTS, sizeof(int*)); 903 if(map == NULL) goto bail; 904 905 if(encoding->row_size == 0) { 906 for(i = encoding->first; i < encoding->size; i++) { 907 k = FontEncRecode(i, mapping); 908 if(k != 0) 909 if(!tree_set(map, k, i)) 910 goto bail; 911 } 912 } else { 913 for(i = encoding->first; i < encoding->size; i++) { 914 for(j = encoding->first_col; j < encoding->row_size; j++) { 915 k = FontEncRecode(i*256 + j, mapping); 916 if(k != 0) 917 if(!tree_set(map, k, i*256+j)) 918 goto bail; 919 } 920 } 921 } 922 923 reverse = malloc(sizeof(FontMapReverseRec)); 924 if(!reverse) goto bail; 925 926 reverse->reverse = reverse_reverse; 927 reverse->data = map; 928 return reverse; 929 930 bail: 931 if(map) 932 xfree(map); 933 if(reverse) 934 xfree(reverse); 935 return NULL; 936} 937 938void 939FontMapReverseFree(FontMapReversePtr delendum) 940{ 941 unsigned int **map = (unsigned int**)delendum; 942 int i; 943 944 if(map == NULL) 945 return; 946 947 for(i = 0; i < FONTENC_SEGMENTS; i++) 948 if(map[i] != NULL) 949 xfree(map[i]); 950 951 xfree(map); 952 return; 953} 954