1 /****************************************************************************\
2 Part of the XeTeX typesetting system
3 Copyright (c) 1994-2008 by SIL International
4 Copyright (c) 2009, 2011 by Jonathan Kew
5 Copyright (c) 2012-2015 by Khaled Hosny
6 Copyright (c) 2012, 2013 by Jiang Jiang
7
8 SIL Author(s): Jonathan Kew
9
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
25 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
26 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 Except as contained in this notice, the name of the copyright holders
30 shall not be used in advertising or otherwise to promote the sale,
31 use or other dealings in this Software without prior written
32 authorization from the copyright holders.
33 \****************************************************************************/
34
35 /* XeTeX_ext.c
36 * additional plain C extensions for XeTeX - mostly platform-neutral
37 */
38
39 #include <w2c/config.h>
40
41 #include <poppler-config.h>
42 #include <png.h>
43 #include <zlib.h>
44 #include <graphite2/Font.h>
45
46 #ifdef _MSC_VER
47 #undef timezone
48 #endif
49
50 #include <time.h> /* For `struct tm'. */
51 #if defined (HAVE_SYS_TIME_H)
52 #include <sys/time.h>
53 #elif defined (HAVE_SYS_TIMEB_H)
54 #include <sys/timeb.h>
55 #endif
56
57 #define EXTERN extern
58 #include "xetexd.h"
59
60 #include "XeTeX_ext.h"
61
62 #include <teckit/TECkit_Engine.h>
63
64 #include <kpathsea/c-ctype.h>
65 #include <kpathsea/line.h>
66 #include <kpathsea/readable.h>
67 #include <kpathsea/variable.h>
68 #include <kpathsea/absolute.h>
69 #if defined(WIN32)
70 #include <kpathsea/concatn.h>
71 #endif
72
73 #include <math.h> /* for fabs() */
74
75 #if defined(__STDC__)
76 #include <locale.h>
77 #endif
78
79 #include <signal.h> /* Catch interrupts. */
80
81 #include "XeTeXLayoutInterface.h"
82
83 #include "XeTeXswap.h"
84
85 #include <unicode/ubidi.h>
86 #include <unicode/ubrk.h>
87 #include <unicode/ucnv.h>
88
89 #include <assert.h>
90
91 /* for reading input files, we don't need the default locking routines
92 as xetex is a single-threaded program */
93 #ifdef WIN32
94 #ifdef __MINGW32__
95 /* MinGW (both 32- and 64-bit) has problems with _getc_nolock() and/or _ungetc_nolock() */
96 #define GETC(f) getc(f)
97 #define UNGETC(c,f) ungetc(c,f)
98 #else
99 #define GETC(f) _getc_nolock(f)
100 #define UNGETC(c,f) _ungetc_nolock(c,f)
101 #endif
102 #else
103 #define GETC(f) getc_unlocked(f)
104 #define UNGETC(c,f) ungetc(c,f)
105 #endif
106
107 /* tables/values used in UTF-8 interpretation -
108 code is based on ConvertUTF.[ch] sample code
109 published by the Unicode consortium */
110 const uint32_t
111 offsetsFromUTF8[6] = {
112 0x00000000UL,
113 0x00003080UL,
114 0x000E2080UL,
115 0x03C82080UL,
116 0xFA082080UL,
117 0x82082080UL
118 };
119
120 const uint8_t
121 bytesFromUTF8[256] = {
122 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
123 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
124 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
125 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
126 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
127 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
128 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
129 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
130 };
131
132 const uint8_t
133 firstByteMark[7] = {
134 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
135 };
136
137 const int halfShift = 10;
138 const uint32_t halfBase = 0x0010000UL;
139 const uint32_t halfMask = 0x3FFUL;
140 const uint32_t kSurrogateHighStart = 0xD800UL;
141 const uint32_t kSurrogateHighEnd = 0xDBFFUL;
142 const uint32_t kSurrogateLowStart = 0xDC00UL;
143 const uint32_t kSurrogateLowEnd = 0xDFFFUL;
144 const uint32_t byteMask = 0x000000BFUL;
145 const uint32_t byteMark = 0x00000080UL;
146
147
148 /* if the user specifies a paper size or output driver program */
149 const char *papersize;
150 const char *outputdriver = "xdvipdfmx -q -E"; /* default to portable xdvipdfmx driver */
151
152
initversionstring(char ** versions)153 void initversionstring(char **versions)
154 {
155 #ifndef XETEX_MAC
156 int fc_version = FcGetVersion();
157 #endif
158 FT_Int ftMajor, ftMinor, ftPatch;
159 int grMajor, grMinor, grBugfix;
160 UVersionInfo icuVersion;
161 char icu_version[U_MAX_VERSION_STRING_LENGTH] = "";
162
163 const_string fmt =
164 "Compiled with ICU version %s; using %s\n"
165 "Compiled with zlib version %s; using %s\n"
166 "Compiled with FreeType2 version %d.%d.%d; using %d.%d.%d\n"
167 "Compiled with Graphite2 version %d.%d.%d; using %d.%d.%d\n"
168 "Compiled with HarfBuzz version %s; using %s\n"
169 "Compiled with libpng version %s; using %s\n"
170 "Compiled with poppler version %s\n"
171 #ifdef XETEX_MAC
172 "Using Mac OS X Core Text and Cocoa frameworks\n"
173 #else
174 "Compiled with fontconfig version %d.%d.%d; using %d.%d.%d\n"
175 #endif
176 ;
177
178 int len = strlen(fmt)
179 + strlen(U_ICU_VERSION)
180 + strlen(icu_version)
181 + strlen(ZLIB_VERSION)
182 + strlen(zlib_version)
183 + strlen(HB_VERSION_STRING)
184 + strlen(hb_version_string())
185 + strlen(PNG_LIBPNG_VER_STRING)
186 + strlen(png_libpng_ver)
187 + strlen(POPPLER_VERSION)
188 #ifndef XETEX_MAC
189 + 6 * 3 /* for fontconfig version #s (won't really need 3 digits per field!) */
190 #endif
191 + 6 * 3 /* for graphite2 version #s (ditto) */
192 + 6 * 3; /* for freetype version #s (ditto) */
193
194 *versions = (char *) xmalloc(len + 1);
195 /* len will be more than enough, because of the placeholder chars in fmt
196 that get replaced by the arguments */
197
198 u_getVersion(icuVersion);
199 u_versionToString(icuVersion, icu_version);
200
201 if (gFreeTypeLibrary == 0 && FT_Init_FreeType(&gFreeTypeLibrary) != 0) {
202 fprintf(stderr, "FreeType initialization failed!\n");
203 exit(9);
204 }
205 FT_Library_Version(gFreeTypeLibrary, &ftMajor, &ftMinor, &ftPatch);
206
207 gr_engine_version(&grMajor, &grMinor, &grBugfix);
208
209 (void)sprintf(*versions, fmt,
210 U_ICU_VERSION, icu_version,
211 ZLIB_VERSION, zlib_version,
212 FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH,
213 ftMajor, ftMinor, ftPatch,
214 GR2_VERSION_MAJOR, GR2_VERSION_MINOR, GR2_VERSION_BUGFIX,
215 grMajor, grMinor, grBugfix,
216 HB_VERSION_STRING, hb_version_string(),
217 PNG_LIBPNG_VER_STRING, png_libpng_ver, POPPLER_VERSION
218 #ifndef XETEX_MAC
219 ,
220 FC_VERSION / 10000, (FC_VERSION % 10000) / 100, FC_VERSION % 100,
221 fc_version / 10000, (fc_version % 10000) / 100, fc_version % 100
222 #endif
223 );
224 }
225
226
227 void
setinputfileencoding(UFILE * f,integer mode,integer encodingData)228 setinputfileencoding(UFILE* f, integer mode, integer encodingData)
229 {
230 if ((f->encodingMode == ICUMAPPING) && (f->conversionData != NULL))
231 ucnv_close((UConverter*)(f->conversionData));
232 f->conversionData = 0;
233
234 switch (mode) {
235 case UTF8:
236 case UTF16BE:
237 case UTF16LE:
238 case RAW:
239 f->encodingMode = mode;
240 break;
241
242 case ICUMAPPING:
243 {
244 char* name = gettexstring(encodingData);
245 UErrorCode err = U_ZERO_ERROR;
246 UConverter* cnv = ucnv_open(name, &err);
247 if (cnv == NULL) {
248 begindiagnostic();
249 printnl('E');
250 printcstring("rror ");
251 printint(err);
252 printcstring(" creating Unicode converter for `");
253 printcstring(name);
254 printcstring("'; reading as raw bytes");
255 enddiagnostic(1);
256 f->encodingMode = RAW;
257 } else {
258 f->encodingMode = ICUMAPPING;
259 f->conversionData = cnv;
260 }
261 free(name);
262 }
263 break;
264 }
265 }
266
267 void
uclose(UFILE * f)268 uclose(UFILE* f)
269 {
270 if (f != 0) {
271 fclose(f->f);
272 if ((f->encodingMode == ICUMAPPING) && (f->conversionData != NULL))
273 ucnv_close((UConverter*)(f->conversionData));
274 free((void*)f);
275 }
276 }
277
278 static void
buffer_overflow()279 buffer_overflow()
280 {
281 fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n",
282 (unsigned) bufsize);
283 fputs ("Please increase buf_size in texmf.cnf.\n", stderr);
284 uexit (1);
285 }
286
287 static void
conversion_error(int errcode)288 conversion_error(int errcode)
289 {
290 begindiagnostic();
291 printnl('U');
292 printcstring("nicode conversion failed (ICU error code = ");
293 printint(errcode);
294 printcstring(") discarding any remaining text");
295 enddiagnostic(1);
296 }
297
298 #ifdef WORDS_BIGENDIAN
299 #define NATIVE_UTF32 kForm_UTF32BE
300 #else
301 #define NATIVE_UTF32 kForm_UTF32LE
302 #endif
303
304 static void
apply_normalization(uint32_t * buf,int len,int norm)305 apply_normalization(uint32_t* buf, int len, int norm)
306 {
307 static TECkit_Converter normalizers[2] = { NULL, NULL };
308
309 TECkit_Status status;
310 UInt32 inUsed, outUsed;
311 TECkit_Converter *normPtr = &normalizers[norm - 1];
312 if (*normPtr == NULL) {
313 status = TECkit_CreateConverter(NULL, 0, 1,
314 NATIVE_UTF32, NATIVE_UTF32 | (norm == 1 ? kForm_NFC : kForm_NFD),
315 &*normPtr);
316 if (status != kStatus_NoError) {
317 fprintf(stderr, "! Failed to create normalizer: error code = %d\n", (int)status);
318 uexit (1);
319 }
320 }
321
322 status = TECkit_ConvertBuffer(*normPtr, (Byte*)buf, len * sizeof(UInt32), &inUsed,
323 (Byte*)&buffer[first], sizeof(*buffer) * (bufsize - first), &outUsed, 1);
324 if (status != kStatus_NoError)
325 buffer_overflow();
326 last = first + outUsed / sizeof(*buffer);
327 }
328
329 #ifdef WORDS_BIGENDIAN
330 #define UCNV_UTF32_NativeEndian UCNV_UTF32_BigEndian
331 #else
332 #define UCNV_UTF32_NativeEndian UCNV_UTF32_LittleEndian
333 #endif
334
335 int
input_line(UFILE * f)336 input_line(UFILE* f)
337 {
338 static char* byteBuffer = NULL;
339 static uint32_t *utf32Buf = NULL;
340 int i, tmpLen;
341 int norm = getinputnormalizationstate();
342 #ifdef WIN32
343 const int fd = fileno(f->f);
344 if (fd == _fileno(stdin) && _isatty(fd)) {
345 f->encodingMode = WIN32CONSOLE;
346 }
347 #endif
348
349 last = first;
350
351 if (f->encodingMode == ICUMAPPING) {
352 uint32_t bytesRead = 0;
353 UConverter* cnv;
354 int outLen;
355 UErrorCode errorCode = U_ZERO_ERROR;
356
357 if (byteBuffer == NULL)
358 byteBuffer = (char*) xmalloc(bufsize + 1);
359
360 /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */
361 i = GETC(f->f);
362 if (f->skipNextLF) {
363 f->skipNextLF = 0;
364 if (i == '\n')
365 i = GETC(f->f);
366 }
367
368 if (i != EOF && i != '\n' && i != '\r')
369 byteBuffer[bytesRead++] = i;
370 if (i != EOF && i != '\n' && i != '\r')
371 while (bytesRead < bufsize && (i = GETC(f->f)) != EOF && i != '\n' && i != '\r')
372 byteBuffer[bytesRead++] = i;
373
374 if (i == EOF && errno != EINTR && bytesRead == 0)
375 return false;
376
377 if (i != EOF && i != '\n' && i != '\r')
378 buffer_overflow();
379
380 /* now apply the mapping to turn external bytes into Unicode characters in buffer */
381 cnv = (UConverter*)(f->conversionData);
382 switch (norm) {
383 case 1: // NFC
384 case 2: // NFD
385 if (utf32Buf == NULL)
386 utf32Buf = (uint32_t*) xcalloc(bufsize, sizeof(uint32_t));
387 tmpLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv,
388 (char*)utf32Buf, bufsize * sizeof(*utf32Buf),
389 byteBuffer, bytesRead, &errorCode);
390 if (errorCode != 0) {
391 conversion_error((int)errorCode);
392 return false;
393 }
394 apply_normalization(utf32Buf, tmpLen / sizeof(*utf32Buf), norm); // sets 'last' correctly
395 break;
396
397 default: // none
398 outLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv,
399 (char*)&buffer[first], sizeof(*buffer) * (bufsize - first),
400 byteBuffer, bytesRead, &errorCode);
401 if (errorCode != 0) {
402 conversion_error((int)errorCode);
403 return false;
404 }
405 outLen /= sizeof(*buffer);
406 last = first + outLen;
407 break;
408 }
409 } else {
410 /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */
411 i = get_uni_c(f);
412 if (f->skipNextLF) {
413 f->skipNextLF = 0;
414 if (i == '\n')
415 i = get_uni_c(f);
416 }
417
418 switch (norm) {
419 case 1: // NFC
420 case 2: // NFD
421 // read Unicode chars into utf32Buf as UTF32
422 if (utf32Buf == NULL)
423 utf32Buf = (uint32_t*) xcalloc(bufsize, sizeof(uint32_t));
424 tmpLen = 0;
425 if (i != EOF && i != '\n' && i != '\r')
426 utf32Buf[tmpLen++] = i;
427 if (i != EOF && i != '\n' && i != '\r')
428 while (tmpLen < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r')
429 utf32Buf[tmpLen++] = i;
430
431 if (i == EOF && errno != EINTR && tmpLen == 0)
432 return false;
433
434 /* We didn't get the whole line because our buffer was too small. */
435 if (i != EOF && i != '\n' && i != '\r')
436 buffer_overflow();
437 apply_normalization(utf32Buf, tmpLen, norm);
438 break;
439
440 default: // none
441 #ifdef WIN32
442 if (f->encodingMode == WIN32CONSOLE && i == 0x1a) /* Ctrl+Z */
443 return false;
444 #endif
445 if (last < bufsize && i != EOF && i != '\n' && i != '\r')
446 buffer[last++] = i;
447 if (i != EOF && i != '\n' && i != '\r')
448 while (last < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r')
449 buffer[last++] = i;
450
451 if (i == EOF && errno != EINTR && last == first)
452 return false;
453
454 /* We didn't get the whole line because our buffer was too small. */
455 if (i != EOF && i != '\n' && i != '\r')
456 buffer_overflow();
457 break;
458 }
459 }
460
461 /* If line ended with CR, remember to skip following LF. */
462 if (i == '\r')
463 f->skipNextLF = 1;
464
465 buffer[last] = ' ';
466 if (last >= maxbufstack)
467 maxbufstack = last;
468
469 /* Trim trailing whitespace. */
470 while (last > first && ISBLANK(buffer[last - 1]))
471 --last;
472
473 return true;
474 }
475
die(const_string s,int i)476 static void die(const_string s, int i)
477 {
478 fprintf(stderr, s, i);
479 fprintf(stderr, " - exiting\n");
480 exit(3);
481 }
482
483 static UBreakIterator* brkIter = NULL;
484 static int brkLocaleStrNum = 0;
485
486 void
linebreakstart(int f,integer localeStrNum,const uint16_t * text,integer textLength)487 linebreakstart(int f, integer localeStrNum, const uint16_t* text, integer textLength)
488 {
489 UErrorCode status = U_ZERO_ERROR;
490 char* locale = (char*)gettexstring(localeStrNum);
491
492 if (fontarea[f] == OTGR_FONT_FLAG && strcmp(locale, "G") == 0) {
493 XeTeXLayoutEngine engine = (XeTeXLayoutEngine) fontlayoutengine[f];
494 if (initGraphiteBreaking(engine, text, textLength))
495 /* user asked for Graphite line breaking and the font supports it */
496 return;
497 }
498
499 if ((localeStrNum != brkLocaleStrNum) && (brkIter != NULL)) {
500 ubrk_close(brkIter);
501 brkIter = NULL;
502 }
503
504 if (brkIter == NULL) {
505 brkIter = ubrk_open(UBRK_LINE, locale, NULL, 0, &status);
506 if (U_FAILURE(status)) {
507 begindiagnostic();
508 printnl('E');
509 printcstring("rror ");
510 printint(status);
511 printcstring(" creating linebreak iterator for locale `");
512 printcstring(locale);
513 printcstring("'; trying default locale `en_us'.");
514 enddiagnostic(1);
515 if (brkIter != NULL)
516 ubrk_close(brkIter);
517 status = U_ZERO_ERROR;
518 brkIter = ubrk_open(UBRK_LINE, "en_us", NULL, 0, &status);
519 }
520 free(locale);
521 brkLocaleStrNum = localeStrNum;
522 }
523
524 if (brkIter == NULL) {
525 die("! failed to create linebreak iterator, status=%d", (int)status);
526 }
527
528 ubrk_setText(brkIter, (UChar*) text, textLength, &status);
529 }
530
531 int
linebreaknext()532 linebreaknext()
533 {
534 if (brkIter != NULL)
535 return ubrk_next((UBreakIterator*)brkIter);
536 else
537 return findNextGraphiteBreak();
538 }
539
540 int
getencodingmodeandinfo(integer * info)541 getencodingmodeandinfo(integer* info)
542 {
543 /* \XeTeXinputencoding "enc-name"
544 * -> name is packed in |nameoffile| as a C string, starting at [1]
545 * Check if it's a built-in name; if not, try to open an ICU converter by that name
546 */
547 UErrorCode err = U_ZERO_ERROR;
548 UConverter* cnv;
549 char* name = (char*)nameoffile + 1;
550 *info = 0;
551 if (strcasecmp(name, "auto") == 0) {
552 return AUTO;
553 }
554 if (strcasecmp(name, "utf8") == 0) {
555 return UTF8;
556 }
557 if (strcasecmp(name, "utf16") == 0) { /* depends on host platform */
558 #ifdef WORDS_BIGENDIAN
559 return UTF16BE;
560 #else
561 return UTF16LE;
562 #endif
563 }
564 if (strcasecmp(name, "utf16be") == 0) {
565 return UTF16BE;
566 }
567 if (strcasecmp(name, "utf16le") == 0) {
568 return UTF16LE;
569 }
570 if (strcasecmp(name, "bytes") == 0) {
571 return RAW;
572 }
573
574 /* try for an ICU converter */
575 cnv = ucnv_open(name, &err);
576 if (cnv == NULL) {
577 begindiagnostic();
578 printnl('U'); /* ensure message starts on a new line */
579 printcstring("nknown encoding `");
580 printcstring(name);
581 printcstring("'; reading as raw bytes");
582 enddiagnostic(1);
583 return RAW;
584 } else {
585 ucnv_close(cnv);
586 *info = maketexstring(name);
587 return ICUMAPPING;
588 }
589 }
590
591 void
printutf8str(const unsigned char * str,int len)592 printutf8str(const unsigned char* str, int len)
593 {
594 while (len-- > 0)
595 printrawchar(*(str++), true); /* bypass utf-8 encoding done in print_char() */
596 }
597
598 void
printchars(const unsigned short * str,int len)599 printchars(const unsigned short* str, int len)
600 {
601 while (len-- > 0)
602 printchar(*(str++));
603 }
604
605 #ifdef WORDS_BIGENDIAN
606 #define UTF16_NATIVE kForm_UTF16BE
607 #else
608 #define UTF16_NATIVE kForm_UTF16LE
609 #endif
610
611 static void*
load_mapping_file(const char * s,const char * e,char byteMapping)612 load_mapping_file(const char* s, const char* e, char byteMapping)
613 {
614 char* mapPath;
615 TECkit_Converter cnv = 0;
616 char* buffer = (char*) xmalloc(e - s + 5);
617 strncpy(buffer, s, e - s);
618 buffer[e - s] = 0;
619 strcat(buffer, ".tec");
620 mapPath = kpse_find_file(buffer, kpse_miscfonts_format, 1);
621
622 if (mapPath) {
623 FILE* mapFile = fopen(mapPath, FOPEN_RBIN_MODE);
624 free(mapPath);
625 if (mapFile) {
626 uint32_t mappingSize;
627 Byte* mapping;
628 TECkit_Status status;
629 fseek(mapFile, 0, SEEK_END);
630 mappingSize = ftell(mapFile);
631 fseek(mapFile, 0, SEEK_SET);
632 mapping = (Byte*) xmalloc(mappingSize);
633 fread(mapping, 1, mappingSize, mapFile);
634 fclose(mapFile);
635 if (byteMapping != 0)
636 status = TECkit_CreateConverter(mapping, mappingSize,
637 false,
638 UTF16_NATIVE, kForm_Bytes,
639 &cnv);
640 else
641 status = TECkit_CreateConverter(mapping, mappingSize,
642 true,
643 UTF16_NATIVE, UTF16_NATIVE,
644 &cnv);
645 free(mapping);
646 }
647 if (cnv == NULL)
648 fontmappingwarning(buffer, strlen(buffer), 2); /* not loadable */
649 else if (gettracingfontsstate() > 1)
650 fontmappingwarning(buffer, strlen(buffer), 0); /* tracing */
651 } else {
652 fontmappingwarning(buffer, strlen(buffer), 1); /* not found */
653 }
654
655 free(buffer);
656
657 return cnv;
658 }
659
660 char *saved_mapping_name = NULL;
661 void
checkfortfmfontmapping()662 checkfortfmfontmapping()
663 {
664 char* cp = strstr((char*)nameoffile + 1, ":mapping=");
665 if (saved_mapping_name != NULL) {
666 free(saved_mapping_name);
667 saved_mapping_name = NULL;
668 }
669 if (cp != NULL) {
670 *cp = 0;
671 cp += 9;
672 while (*cp && *cp <= ' ')
673 ++cp;
674 if (*cp)
675 saved_mapping_name = xstrdup(cp);
676 }
677 }
678
679 void*
loadtfmfontmapping()680 loadtfmfontmapping()
681 {
682 void* rval = NULL;
683 if (saved_mapping_name != NULL) {
684 rval = load_mapping_file(saved_mapping_name,
685 saved_mapping_name + strlen(saved_mapping_name), 1);
686 free(saved_mapping_name);
687 saved_mapping_name = NULL;
688 }
689 return rval;
690 }
691
692 int
applytfmfontmapping(void * cnv,int c)693 applytfmfontmapping(void* cnv, int c)
694 {
695 UniChar in = c;
696 Byte out[2];
697 UInt32 inUsed, outUsed;
698 TECkit_Status status = TECkit_ConvertBuffer((TECkit_Converter)cnv,
699 (const Byte*)&in, sizeof(in), &inUsed, out, sizeof(out), &outUsed, 1);
700 if (outUsed < 1)
701 return 0;
702 else
703 return out[0];
704 }
705
706 double
read_double(const char ** s)707 read_double(const char** s)
708 {
709 int neg = 0;
710 double val = 0.0;
711 const char* cp = *s;
712
713 while (*cp == ' '|| *cp == '\t')
714 ++cp;
715 if (*cp == '-') {
716 neg = 1;
717 ++cp;
718 } else if (*cp == '+') {
719 ++cp;
720 }
721
722 while (*cp >= '0' && *cp <= '9') {
723 val = val * 10.0 + *cp - '0';
724 ++cp;
725 }
726 if (*cp == '.') {
727 double dec = 10.0;
728 ++cp;
729 while (*cp >= '0' && *cp <= '9') {
730 val = val + (*cp - '0') / dec;
731 ++cp;
732 dec = dec * 10.0;
733 }
734 }
735 *s = cp;
736
737 return neg ? -val : val;
738 }
739
740 static hb_tag_t
read_tag_with_param(const char * cp,int * param)741 read_tag_with_param(const char* cp, int* param)
742 {
743 const char* cp2;
744 hb_tag_t tag;
745
746 cp2 = cp;
747 while (*cp2 && (*cp2 != ':') && (*cp2 != ';') && (*cp2 != ',') && (*cp2 != '='))
748 ++cp2;
749
750 tag = hb_tag_from_string(cp, cp2 - cp);
751
752 cp = cp2;
753 if (*cp == '=') {
754 int neg = 0;
755 ++cp;
756 if (*cp == '-') {
757 ++neg;
758 ++cp;
759 }
760 while (*cp >= '0' && *cp <= '9') {
761 *param = *param * 10 + *cp - '0';
762 ++cp;
763 }
764 if (neg)
765 *param = -(*param);
766 }
767
768 return tag;
769 }
770
771 unsigned int
read_rgb_a(const char ** cp)772 read_rgb_a(const char** cp)
773 {
774 uint32_t rgbValue = 0;
775 uint32_t alpha = 0;
776 int i;
777 for (i = 0; i < 6; ++i) {
778 if ((**cp >= '0') && (**cp <= '9'))
779 rgbValue = (rgbValue << 4) + **cp - '0';
780 else if ((**cp >= 'A') && (**cp <= 'F'))
781 rgbValue = (rgbValue << 4) + **cp - 'A' + 10;
782 else if ((**cp >= 'a') && (**cp <= 'f'))
783 rgbValue = (rgbValue << 4) + **cp - 'a' + 10;
784 else
785 return 0x000000FF;
786 (*cp)++;
787 }
788 rgbValue <<= 8;
789 for (i = 0; i < 2; ++i) {
790 if ((**cp >= '0') && (**cp <= '9'))
791 alpha = (alpha << 4) + **cp - '0';
792 else if ((**cp >= 'A') && (**cp <= 'F'))
793 alpha = (alpha << 4) + **cp - 'A' + 10;
794 else if ((**cp >= 'a') && (**cp <= 'f'))
795 alpha = (alpha << 4) + **cp - 'a' + 10;
796 else
797 break;
798 (*cp)++;
799 }
800 if (i == 2)
801 rgbValue += alpha;
802 else
803 rgbValue += 0xFF;
804 return rgbValue;
805 }
806
807 int
readCommonFeatures(const char * feat,const char * end,float * extend,float * slant,float * embolden,float * letterspace,uint32_t * rgbValue)808 readCommonFeatures(const char* feat, const char* end, float* extend, float* slant, float* embolden, float* letterspace, uint32_t* rgbValue)
809 // returns 1 to go to next_option, -1 for bad_option, 0 to continue
810 {
811 const char* sep;
812 if (strncmp(feat, "mapping", 7) == 0) {
813 sep = feat + 7;
814 if (*sep != '=')
815 return -1;
816 loadedfontmapping = load_mapping_file(sep + 1, end, 0);
817 return 1;
818 }
819
820 if (strncmp(feat, "extend", 6) == 0) {
821 sep = feat + 6;
822 if (*sep != '=')
823 return -1;
824 ++sep;
825 *extend = read_double(&sep);
826 return 1;
827 }
828
829 if (strncmp(feat, "slant", 5) == 0) {
830 sep = feat + 5;
831 if (*sep != '=')
832 return -1;
833 ++sep;
834 *slant = read_double(&sep);
835 return 1;
836 }
837
838 if (strncmp(feat, "embolden", 8) == 0) {
839 sep = feat + 8;
840 if (*sep != '=')
841 return -1;
842 ++sep;
843 *embolden = read_double(&sep);
844 return 1;
845 }
846
847 if (strncmp(feat, "letterspace", 11) == 0) {
848 sep = feat + 11;
849 if (*sep != '=')
850 return -1;
851 ++sep;
852 *letterspace = read_double(&sep);
853 return 1;
854 }
855
856 if (strncmp(feat, "color", 5) == 0) {
857 const char* s;
858 sep = feat + 5;
859 if (*sep != '=')
860 return -1;
861 ++sep;
862 s = sep;
863 *rgbValue = read_rgb_a(&sep);
864 if ((sep == s+6) || (sep == s+8))
865 loadedfontflags |= FONT_FLAGS_COLORED;
866 else
867 return -1;
868 return 1;
869 }
870
871 return 0;
872 }
873
874 static bool
readFeatureNumber(const char * s,const char * e,hb_tag_t * f,int * v)875 readFeatureNumber(const char* s, const char* e, hb_tag_t* f, int* v)
876 /* s...e is a "id=setting" string; */
877 {
878 *f = 0;
879 *v = 0;
880 if (*s < '0' || *s > '9')
881 return false;
882 while (*s >= '0' && *s <= '9')
883 *f = *f * 10 + *s++ - '0';
884 while ((*s == ' ') || (*s == '\t'))
885 ++s;
886 if (*s++ != '=')
887 /* no setting was specified */
888 return false;
889
890 if (*s < '0' || *s > '9')
891 return false;
892 while (*s >= '0' && *s <= '9')
893 *v = *v * 10 + *s++ - '0';
894 while ((*s == ' ') || (*s == '\t'))
895 ++s;
896 if (s != e)
897 return false;
898 return true;
899 }
900
901 static void*
loadOTfont(PlatformFontRef fontRef,XeTeXFont font,Fixed scaled_size,const char * cp1)902 loadOTfont(PlatformFontRef fontRef, XeTeXFont font, Fixed scaled_size, const char* cp1)
903 {
904 XeTeXLayoutEngine engine;
905 hb_tag_t script = HB_TAG_NONE;
906 char * language = NULL;
907 hb_feature_t* features = NULL;
908 char** shapers = NULL; /* NULL-terminated array */
909 int nFeatures = 0;
910 int nShapers = 0;
911
912 const char* cp2;
913 const char* cp3;
914
915 hb_tag_t tag;
916
917 uint32_t rgbValue = 0x000000FF;
918
919 float extend = 1.0;
920 float slant = 0.0;
921 float embolden = 0.0;
922 float letterspace = 0.0;
923
924 int i;
925
926 char reqEngine = getReqEngine();
927
928 if (reqEngine == 'O' || reqEngine == 'G') {
929 shapers = (char**) xrealloc(shapers, (nShapers + 1) * sizeof(char *));
930 if (reqEngine == 'O')
931 shapers[nShapers] = "ot";
932 else if (reqEngine == 'G')
933 shapers[nShapers] = "graphite2";
934 nShapers++;
935 }
936
937 if (reqEngine == 'G') {
938 char* tmpShapers[] = {shapers[0]};
939 /* create a default engine so we can query the font for Graphite features;
940 * because of font caching, it's cheap to discard this and create the real one later */
941 engine = createLayoutEngine(fontRef, font, script, language,
942 features, nFeatures, tmpShapers, rgbValue, extend, slant, embolden);
943
944 if (engine == NULL)
945 return NULL;
946 }
947
948 /* scan the feature string (if any) */
949 if (cp1 != NULL) {
950 while (*cp1) {
951 if ((*cp1 == ':') || (*cp1 == ';') || (*cp1 == ','))
952 ++cp1;
953 while ((*cp1 == ' ') || (*cp1 == '\t')) /* skip leading whitespace */
954 ++cp1;
955 if (*cp1 == 0) /* break if end of string */
956 break;
957
958 cp2 = cp1;
959 while (*cp2 && (*cp2 != ':') && (*cp2 != ';') && (*cp2 != ','))
960 ++cp2;
961
962 if (strncmp(cp1, "script", 6) == 0) {
963 cp3 = cp1 + 6;
964 if (*cp3 != '=')
965 goto bad_option;
966 ++cp3;
967 script = hb_tag_from_string(cp3, cp2 - cp3);
968 goto next_option;
969 }
970
971 if (strncmp(cp1, "language", 8) == 0) {
972 cp3 = cp1 + 8;
973 if (*cp3 != '=')
974 goto bad_option;
975 ++cp3;
976 language = (char*)xmalloc(cp2 - cp3 + 1);
977 language[cp2 - cp3] = '\0';
978 memcpy(language, cp3, cp2 - cp3);
979 goto next_option;
980 }
981
982 if (strncmp(cp1, "shaper", 6) == 0) {
983 cp3 = cp1 + 6;
984 if (*cp3 != '=')
985 goto bad_option;
986 ++cp3;
987 shapers = (char**) xrealloc(shapers, (nShapers + 1) * sizeof(char *));
988 /* some dumb systems have no strndup() */
989 shapers[nShapers] = strdup(cp3);
990 shapers[nShapers][cp2 - cp3] = '\0';
991 nShapers++;
992 goto next_option;
993 }
994
995 i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue);
996 if (i == 1)
997 goto next_option;
998 else if (i == -1)
999 goto bad_option;
1000
1001 if (reqEngine == 'G') {
1002 int value = 0;
1003 if (readFeatureNumber(cp1, cp2, &tag, &value)
1004 || findGraphiteFeature(engine, cp1, cp2, &tag, &value)) {
1005 features = (hb_feature_t*) xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t));
1006 features[nFeatures].tag = tag;
1007 features[nFeatures].value = value;
1008 features[nFeatures].start = 0;
1009 features[nFeatures].end = (unsigned int) -1;
1010 nFeatures++;
1011 goto next_option;
1012 }
1013 }
1014
1015 if (*cp1 == '+') {
1016 int param = 0;
1017 tag = read_tag_with_param(cp1 + 1, ¶m);
1018 features = (hb_feature_t*) xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t));
1019 features[nFeatures].tag = tag;
1020 features[nFeatures].start = 0;
1021 features[nFeatures].end = (unsigned int) -1;
1022 // for backward compatibility with pre-0.9999 where feature
1023 // indices started from 0
1024 if (param >= 0)
1025 param++;
1026 features[nFeatures].value = param;
1027 nFeatures++;
1028 goto next_option;
1029 }
1030
1031 if (*cp1 == '-') {
1032 ++cp1;
1033 tag = hb_tag_from_string(cp1, cp2 - cp1);
1034 features = (hb_feature_t*) xrealloc(features, (nFeatures + 1) * sizeof(hb_feature_t));
1035 features[nFeatures].tag = tag;
1036 features[nFeatures].start = 0;
1037 features[nFeatures].end = (unsigned int) -1;
1038 features[nFeatures].value = 0;
1039 nFeatures++;
1040 goto next_option;
1041 }
1042
1043 if (strncmp(cp1, "vertical", 8) == 0) {
1044 cp3 = cp2;
1045 if (*cp3 == ';' || *cp3 == ':' || *cp3 == ',')
1046 --cp3;
1047 while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t')
1048 --cp3;
1049 if (*cp3)
1050 ++cp3;
1051 if (cp3 == cp1 + 8) {
1052 loadedfontflags |= FONT_FLAGS_VERTICAL;
1053 goto next_option;
1054 }
1055 }
1056
1057 bad_option:
1058 fontfeaturewarning((void*) cp1, cp2 - cp1, 0, 0);
1059
1060 next_option:
1061 cp1 = cp2;
1062 }
1063 }
1064
1065 if (shapers != NULL) {
1066 shapers = (char**) xrealloc(shapers, (nShapers + 1) * sizeof(char *));
1067 shapers[nShapers] = NULL;
1068 }
1069
1070 if (embolden != 0.0)
1071 embolden = embolden * Fix2D(scaled_size) / 100.0;
1072
1073 if (letterspace != 0.0)
1074 loadedfontletterspace = (letterspace / 100.0) * scaled_size;
1075
1076 if ((loadedfontflags & FONT_FLAGS_COLORED) == 0)
1077 rgbValue = 0x000000FF;
1078
1079 if ((loadedfontflags & FONT_FLAGS_VERTICAL) != 0)
1080 setFontLayoutDir(font, 1);
1081
1082 engine = createLayoutEngine(fontRef, font, script, language,
1083 features, nFeatures, shapers, rgbValue, extend, slant, embolden);
1084
1085 if (engine == 0) {
1086 // only free these if creation failed, otherwise the engine now owns them
1087 free(features);
1088 free(shapers);
1089 } else {
1090 nativefonttypeflag = OTGR_FONT_FLAG;
1091 }
1092
1093 return engine;
1094 }
1095
1096 static void
splitFontName(char * name,char ** var,char ** feat,char ** end,int * index)1097 splitFontName(char* name, char** var, char** feat, char** end, int* index)
1098 {
1099 *var = NULL;
1100 *feat = NULL;
1101 *index = 0;
1102 if (*name == '[') {
1103 int withinFileName = 1;
1104 #ifdef WIN32
1105 char* start = name + 1;
1106 #endif
1107 ++name;
1108 while (*name) {
1109 if (withinFileName && *name == ']') {
1110 withinFileName = 0;
1111 if (*var == NULL)
1112 *var = name;
1113 } else if (*name == ':') {
1114 if (withinFileName && *var == NULL
1115 #ifdef WIN32
1116 && !((name - start == 1) && isalpha(*start))
1117 #endif
1118 ) {
1119 *var = name;
1120 ++name;
1121 while (*name >= '0' && *name <= '9')
1122 *index = *index * 10 + *name++ - '0';
1123 --name;
1124 } else if (!withinFileName && *feat == NULL)
1125 *feat = name;
1126 }
1127 ++name;
1128 }
1129 *end = name;
1130 } else {
1131 while (*name) {
1132 if (*name == '/' && *var == NULL && *feat == NULL)
1133 *var = name;
1134 else if (*name == ':' && *feat == NULL)
1135 *feat = name;
1136 ++name;
1137 }
1138 *end = name;
1139 }
1140 if (*feat == NULL)
1141 *feat = name;
1142 if (*var == NULL)
1143 *var = *feat;
1144 }
1145
1146 void*
findnativefont(unsigned char * uname,integer scaled_size)1147 findnativefont(unsigned char* uname, integer scaled_size)
1148 /* scaled_size here is in TeX points, or is a negative integer for 'scaled' */
1149 {
1150 void* rval = NULL;
1151 char* nameString;
1152 char* var;
1153 char* feat;
1154 char* end;
1155 char* name = (char*)uname;
1156 char* varString = NULL;
1157 char* featString = NULL;
1158 PlatformFontRef fontRef;
1159 XeTeXFont font = NULL;
1160 int index = 0;
1161
1162 loadedfontmapping = NULL;
1163 loadedfontflags = 0;
1164 loadedfontletterspace = 0;
1165
1166 splitFontName(name, &var, &feat, &end, &index);
1167 nameString = (char*) xmalloc(var - name + 1);
1168 strncpy(nameString, name, var - name);
1169 nameString[var - name] = 0;
1170
1171 if (feat > var) {
1172 varString = (char*) xmalloc(feat - var);
1173 strncpy(varString, var + 1, feat - var - 1);
1174 varString[feat - var - 1] = 0;
1175 }
1176
1177 if (end > feat) {
1178 featString = (char*) xmalloc(end - feat);
1179 strncpy(featString, feat + 1, end - feat - 1);
1180 featString[end - feat - 1] = 0;
1181 }
1182
1183 // check for "[filename]" form, don't search maps in this case
1184 if (nameString[0] == '[') {
1185 char* path = kpse_find_file(nameString + 1, kpse_opentype_format, 0);
1186 if (path == NULL)
1187 path = kpse_find_file(nameString + 1, kpse_truetype_format, 0);
1188 if (path == NULL)
1189 path = kpse_find_file(nameString + 1, kpse_type1_format, 0);
1190 if (path != NULL) {
1191 if (scaled_size < 0) {
1192 font = createFontFromFile(path, index, 655360L);
1193 if (font != NULL) {
1194 Fixed dsize = D2Fix(getDesignSize(font));
1195 if (scaled_size == -1000)
1196 scaled_size = dsize;
1197 else
1198 scaled_size = zxnoverd(dsize, -scaled_size, 1000);
1199 deleteFont(font);
1200 }
1201 }
1202 font = createFontFromFile(path, index, scaled_size);
1203 if (font != NULL) {
1204 loadedfontdesignsize = D2Fix(getDesignSize(font));
1205
1206 /* This is duplicated in XeTeXFontMgr::findFont! */
1207 setReqEngine(0);
1208 if (varString) {
1209 if (strncmp(varString, "/AAT", 4) == 0)
1210 setReqEngine('A');
1211 else if ((strncmp(varString, "/OT", 3) == 0) || (strncmp(varString, "/ICU", 4) == 0))
1212 setReqEngine('O');
1213 else if (strncmp(varString, "/GR", 3) == 0)
1214 setReqEngine('G');
1215 }
1216
1217 rval = loadOTfont(0, font, scaled_size, featString);
1218 if (rval == NULL)
1219 deleteFont(font);
1220 if (rval != NULL && gettracingfontsstate() > 0) {
1221 begindiagnostic();
1222 zprintnl(' ');
1223 printcstring("-> ");
1224 printcstring(path);
1225 zenddiagnostic(0);
1226 }
1227 }
1228 }
1229 } else {
1230 fontRef = findFontByName(nameString, varString, Fix2D(scaled_size));
1231
1232 if (fontRef != 0) {
1233 /* update nameoffile to the full name of the font, for error messages during font loading */
1234 const char* fullName = getFullName(fontRef);
1235 namelength = strlen(fullName);
1236 if (featString != NULL)
1237 namelength += strlen(featString) + 1;
1238 if (varString != NULL)
1239 namelength += strlen(varString) + 1;
1240 free(nameoffile);
1241 nameoffile = xmalloc(namelength + 4); /* +2 would be correct: initial space, final NUL */
1242 nameoffile[0] = ' ';
1243 strcpy((char*)nameoffile + 1, fullName);
1244
1245 if (scaled_size < 0) {
1246 font = createFont(fontRef, scaled_size);
1247 if (font != NULL) {
1248 Fixed dsize = D2Fix(getDesignSize(font));
1249 if (scaled_size == -1000)
1250 scaled_size = dsize;
1251 else
1252 scaled_size = zxnoverd(dsize, -scaled_size, 1000);
1253 deleteFont(font);
1254 }
1255 }
1256
1257 font = createFont(fontRef, scaled_size);
1258 if (font != NULL) {
1259 #ifdef XETEX_MAC
1260 /* decide whether to use AAT or OpenType rendering with this font */
1261 if (getReqEngine() == 'A') {
1262 rval = loadAATfont(fontRef, scaled_size, featString);
1263 if (rval == NULL)
1264 deleteFont(font);
1265 } else {
1266 if (getReqEngine() == 'O' || getReqEngine() == 'G' ||
1267 getFontTablePtr(font, kGSUB) != NULL || getFontTablePtr(font, kGPOS) != NULL)
1268 rval = loadOTfont(fontRef, font, scaled_size, featString);
1269
1270 /* loadOTfont failed or the above check was false */
1271 if (rval == NULL)
1272 rval = loadAATfont(fontRef, scaled_size, featString);
1273
1274 if (rval == NULL)
1275 deleteFont(font);
1276 }
1277 #else
1278 rval = loadOTfont(fontRef, font, scaled_size, featString);
1279 if (rval == NULL)
1280 deleteFont(font);
1281 #endif
1282 }
1283
1284 /* append the style and feature strings, so that \show\fontID will give a full result */
1285 if (varString != NULL && *varString != 0) {
1286 strcat((char*)nameoffile + 1, "/");
1287 strcat((char*)nameoffile + 1, varString);
1288 }
1289 if (featString != NULL && *featString != 0) {
1290 strcat((char*)nameoffile + 1, ":");
1291 strcat((char*)nameoffile + 1, featString);
1292 }
1293 namelength = strlen((char*)nameoffile + 1);
1294 }
1295 }
1296
1297 if (varString != NULL)
1298 free(varString);
1299
1300 if (featString != NULL)
1301 free(featString);
1302
1303 free(nameString);
1304
1305 return rval;
1306 }
1307
1308 void
releasefontengine(void * engine,int type_flag)1309 releasefontengine(void* engine, int type_flag)
1310 {
1311 #ifdef XETEX_MAC
1312 if (type_flag == AAT_FONT_FLAG) {
1313 CFRelease((CFDictionaryRef)engine);
1314 } else
1315 #endif
1316 if (type_flag == OTGR_FONT_FLAG) {
1317 deleteLayoutEngine((XeTeXLayoutEngine)engine);
1318 }
1319 }
1320
1321 /* params are given as 'integer' in the header file, but are really TeX scaled integers */
1322 void
otgetfontmetrics(void * pEngine,scaled * ascent,scaled * descent,scaled * xheight,scaled * capheight,scaled * slant)1323 otgetfontmetrics(void* pEngine, scaled* ascent, scaled* descent, scaled* xheight, scaled* capheight, scaled* slant)
1324 {
1325 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1326 float a, d;
1327
1328 getAscentAndDescent(engine, &a, &d);
1329 *ascent = D2Fix(a);
1330 *descent = D2Fix(d);
1331
1332 *slant = D2Fix(Fix2D(getSlant(getFont(engine))) * getExtendFactor(engine)
1333 + getSlantFactor(engine));
1334
1335 /* get cap and x height from OS/2 table */
1336 getCapAndXHeight(engine, &a, &d);
1337 *capheight = D2Fix(a);
1338 *xheight = D2Fix(d);
1339
1340 /* fallback in case the font does not have OS/2 table */
1341 if (*xheight == 0) {
1342 int glyphID = mapCharToGlyph(engine, 'x');
1343 if (glyphID != 0) {
1344 getGlyphHeightDepth(engine, glyphID, &a, &d);
1345 *xheight = D2Fix(a);
1346 } else {
1347 *xheight = *ascent / 2; /* arbitrary figure if there's no 'x' in the font */
1348 }
1349 }
1350
1351 if (*capheight == 0) {
1352 int glyphID = mapCharToGlyph(engine, 'X');
1353 if (glyphID != 0) {
1354 getGlyphHeightDepth(engine, glyphID, &a, &d);
1355 *capheight = D2Fix(a);
1356 } else {
1357 *capheight = *ascent; /* arbitrary figure if there's no 'X' in the font */
1358 }
1359 }
1360 }
1361
1362 integer
otfontget(integer what,void * pEngine)1363 otfontget(integer what, void* pEngine)
1364 {
1365 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1366 XeTeXFont fontInst = getFont(engine);
1367 switch (what) {
1368 case XeTeX_count_glyphs:
1369 return countGlyphs(fontInst);
1370 break;
1371
1372 case XeTeX_count_features: /* ie Graphite features */
1373 return countGraphiteFeatures(engine);
1374 break;
1375
1376 case XeTeX_OT_count_scripts:
1377 return countScripts(fontInst);
1378 break;
1379 }
1380 return 0;
1381 }
1382
1383
1384 integer
otfontget1(integer what,void * pEngine,integer param)1385 otfontget1(integer what, void* pEngine, integer param)
1386 {
1387 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1388 XeTeXFont fontInst = getFont(engine);
1389 switch (what) {
1390 case XeTeX_OT_count_languages:
1391 return countLanguages(fontInst, param);
1392 break;
1393
1394 case XeTeX_OT_script_code:
1395 return getIndScript(fontInst, param);
1396 break;
1397
1398 /* for graphite fonts...*/
1399 case XeTeX_feature_code:
1400 return getGraphiteFeatureCode(engine, param);
1401 break;
1402 case XeTeX_is_exclusive_feature:
1403 return 1;
1404 break;
1405 case XeTeX_count_selectors:
1406 return countGraphiteFeatureSettings(engine, param);
1407 break;
1408 }
1409 return 0;
1410 }
1411
1412
1413 integer
otfontget2(integer what,void * pEngine,integer param1,integer param2)1414 otfontget2(integer what, void* pEngine, integer param1, integer param2)
1415 {
1416 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1417 XeTeXFont fontInst = getFont(engine);
1418 switch (what) {
1419 case XeTeX_OT_language_code:
1420 return getIndLanguage(fontInst, param1, param2);
1421 break;
1422
1423 case XeTeX_OT_count_features:
1424 return countFeatures(fontInst, param1, param2);
1425 break;
1426
1427 /* for graphite fonts */
1428 case XeTeX_selector_code:
1429 return getGraphiteFeatureSettingCode(engine, param1, param2);
1430 break;
1431 case XeTeX_is_default_selector:
1432 return getGraphiteFeatureDefaultSetting(engine, param1) == param2;
1433 break;
1434 }
1435
1436 return 0;
1437 }
1438
1439
1440 integer
otfontget3(integer what,void * pEngine,integer param1,integer param2,integer param3)1441 otfontget3(integer what, void* pEngine, integer param1, integer param2, integer param3)
1442 {
1443 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1444 XeTeXFont fontInst = getFont(engine);
1445 switch (what) {
1446 case XeTeX_OT_feature_code:
1447 return getIndFeature(fontInst, param1, param2, param3);
1448 break;
1449 }
1450
1451 return 0;
1452 }
1453
1454 void
grprintfontname(integer what,void * pEngine,integer param1,integer param2)1455 grprintfontname(integer what, void* pEngine, integer param1, integer param2)
1456 {
1457 char* name = NULL;
1458 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1459 switch (what) {
1460 case XeTeX_feature_name:
1461 name = getGraphiteFeatureLabel(engine, param1);
1462 break;
1463 case XeTeX_selector_name:
1464 name = getGraphiteFeatureSettingLabel(engine, param1, param2);
1465 break;
1466 }
1467
1468 if (name != NULL) {
1469 printcstring(name);
1470 gr_label_destroy(name);
1471 }
1472 }
1473
1474 integer
grfontgetnamed(integer what,void * pEngine)1475 grfontgetnamed(integer what, void* pEngine)
1476 {
1477 long rval = -1;
1478 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1479 switch (what) {
1480 case XeTeX_find_feature_by_name:
1481 rval = findGraphiteFeatureNamed(engine, (const char*)nameoffile + 1, namelength);
1482 break;
1483 }
1484 return rval;
1485 }
1486
1487 integer
grfontgetnamed1(integer what,void * pEngine,integer param)1488 grfontgetnamed1(integer what, void* pEngine, integer param)
1489 {
1490 long rval = -1;
1491 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)pEngine;
1492 switch (what) {
1493 case XeTeX_find_selector_by_name:
1494 rval = findGraphiteFeatureSettingNamed(engine, param, (const char*)nameoffile + 1, namelength);
1495 break;
1496 }
1497 return rval;
1498 }
1499
1500 #define XDV_FLAG_VERTICAL 0x0100
1501 #define XDV_FLAG_COLORED 0x0200
1502 #define XDV_FLAG_EXTEND 0x1000
1503 #define XDV_FLAG_SLANT 0x2000
1504 #define XDV_FLAG_EMBOLDEN 0x4000
1505
1506 #ifdef XETEX_MAC
1507 static UInt32
cgColorToRGBA32(CGColorRef color)1508 cgColorToRGBA32(CGColorRef color)
1509 {
1510 const CGFloat *components = CGColorGetComponents(color);
1511
1512 UInt32 rval = (UInt8)(components[0] * 255.0 + 0.5);
1513 rval <<= 8;
1514 rval += (UInt8)(components[1] * 255.0 + 0.5);
1515 rval <<= 8;
1516 rval += (UInt8)(components[2] * 255.0 + 0.5);
1517 rval <<= 8;
1518 rval += (UInt8)(components[3] * 255.0 + 0.5);
1519 return rval;
1520 }
1521 #endif
1522
1523 static int xdvBufSize = 0;
1524
1525 int
makeXDVGlyphArrayData(void * pNode)1526 makeXDVGlyphArrayData(void* pNode)
1527 {
1528 unsigned char* cp;
1529 uint16_t* glyphIDs;
1530 memoryword* p = (memoryword*) pNode;
1531 void* glyph_info;
1532 FixedPoint* locations;
1533 Fixed width;
1534 uint16_t glyphCount = native_glyph_count(p);
1535
1536 int i = glyphCount * native_glyph_info_size + 8; /* to guarantee enough space in the buffer */
1537 if (i > xdvBufSize) {
1538 if (xdvbuffer != NULL)
1539 free(xdvbuffer);
1540 xdvBufSize = ((i / 1024) + 1) * 1024;
1541 xdvbuffer = (char*) xmalloc(xdvBufSize);
1542 }
1543
1544 glyph_info = native_glyph_info_ptr(p);
1545 locations = (FixedPoint*)glyph_info;
1546 glyphIDs = (uint16_t*)(locations + glyphCount);
1547
1548 cp = (unsigned char*)xdvbuffer;
1549
1550 width = node_width(p);
1551 *cp++ = (width >> 24) & 0xff;
1552 *cp++ = (width >> 16) & 0xff;
1553 *cp++ = (width >> 8) & 0xff;
1554 *cp++ = width & 0xff;
1555
1556 *cp++ = (glyphCount >> 8) & 0xff;
1557 *cp++ = glyphCount & 0xff;
1558
1559 for (i = 0; i < glyphCount; ++i) {
1560 Fixed x = locations[i].x;
1561 Fixed y = locations[i].y;
1562 *cp++ = (x >> 24) & 0xff;
1563 *cp++ = (x >> 16) & 0xff;
1564 *cp++ = (x >> 8) & 0xff;
1565 *cp++ = x & 0xff;
1566 *cp++ = (y >> 24) & 0xff;
1567 *cp++ = (y >> 16) & 0xff;
1568 *cp++ = (y >> 8) & 0xff;
1569 *cp++ = y & 0xff;
1570 }
1571
1572 for (i = 0; i < glyphCount; ++i) {
1573 uint16_t g = glyphIDs[i];
1574 *cp++ = (g >> 8) & 0xff;
1575 *cp++ = g & 0xff;
1576 }
1577
1578 return ((char*)cp - xdvbuffer);
1579 }
1580
1581 int
makefontdef(integer f)1582 makefontdef(integer f)
1583 {
1584 uint16_t flags = 0;
1585 uint32_t rgba;
1586 Fixed size;
1587 const char* filename;
1588 uint32_t index;
1589 uint8_t filenameLen;
1590 int fontDefLength;
1591 char* cp;
1592 PlatformFontRef fontRef = 0;
1593 float extend = 1.0;
1594 float slant = 0.0;
1595 float embolden = 0.0;
1596
1597 #ifdef XETEX_MAC
1598 CFDictionaryRef attributes = NULL;
1599
1600 if (fontarea[f] == AAT_FONT_FLAG) {
1601 CTFontRef font;
1602 CGColorRef color;
1603 CGAffineTransform t;
1604 CFNumberRef emboldenNumber;
1605 CGFloat fSize;
1606
1607 attributes = (CFDictionaryRef) fontlayoutengine[f];
1608 font = CFDictionaryGetValue(attributes, kCTFontAttributeName);
1609
1610 filename = getFileNameFromCTFont(font, &index);
1611 assert(filename);
1612
1613 if (CFDictionaryGetValue(attributes, kCTVerticalFormsAttributeName))
1614 flags |= XDV_FLAG_VERTICAL;
1615
1616 color = (CGColorRef) CFDictionaryGetValue(attributes, kCTForegroundColorAttributeName);
1617 if (color)
1618 rgba = cgColorToRGBA32(color);
1619
1620 t = CTFontGetMatrix(font);
1621 extend = t.a;
1622 slant = t.c;
1623
1624 emboldenNumber = CFDictionaryGetValue(attributes, kXeTeXEmboldenAttributeName);
1625 if (emboldenNumber)
1626 CFNumberGetValue(emboldenNumber, kCFNumberFloatType, &embolden);
1627
1628 fSize = CTFontGetSize(font);
1629 size = D2Fix(fSize);
1630 } else
1631 #endif
1632 if (fontarea[f] == OTGR_FONT_FLAG) {
1633 XeTeXLayoutEngine engine;
1634
1635 engine = (XeTeXLayoutEngine)fontlayoutengine[f];
1636 fontRef = getFontRef(engine);
1637 filename = getFontFilename(engine, &index);
1638 assert(filename);
1639
1640 rgba = getRgbValue(engine);
1641 if ((fontflags[f] & FONT_FLAGS_VERTICAL) != 0)
1642 flags |= XDV_FLAG_VERTICAL;
1643
1644 extend = getExtendFactor(engine);
1645 slant = getSlantFactor(engine);
1646 embolden = getEmboldenFactor(engine);
1647
1648 size = D2Fix(getPointSize(engine));
1649 } else {
1650 fprintf(stderr, "\n! Internal error: bad native font flag in `make_font_def'\n");
1651 exit(3);
1652 }
1653
1654 filenameLen = strlen(filename);
1655
1656 /* parameters after internal font ID:
1657 // size[4]
1658 // flags[2]
1659 // l[1] n[l]
1660 // if flags & COLORED:
1661 // c[4]
1662 */
1663
1664 fontDefLength
1665 = 4 /* size */
1666 + 2 /* flags */
1667 + 1 /* name length */
1668 + filenameLen
1669 + 4 /* face index */;
1670
1671 if ((fontflags[f] & FONT_FLAGS_COLORED) != 0) {
1672 fontDefLength += 4; /* 32-bit RGBA value */
1673 flags |= XDV_FLAG_COLORED;
1674 }
1675
1676 if (extend != 1.0) {
1677 fontDefLength += 4;
1678 flags |= XDV_FLAG_EXTEND;
1679 }
1680 if (slant != 0.0) {
1681 fontDefLength += 4;
1682 flags |= XDV_FLAG_SLANT;
1683 }
1684 if (embolden != 0.0) {
1685 fontDefLength += 4;
1686 flags |= XDV_FLAG_EMBOLDEN;
1687 }
1688
1689 if (fontDefLength > xdvBufSize) {
1690 if (xdvbuffer != NULL)
1691 free(xdvbuffer);
1692 xdvBufSize = ((fontDefLength / 1024) + 1) * 1024;
1693 xdvbuffer = (char*) xmalloc(xdvBufSize);
1694 }
1695 cp = xdvbuffer;
1696
1697 *(Fixed*)cp = SWAP32(size);
1698 cp += 4;
1699
1700 *(uint16_t*)cp = SWAP16(flags);
1701 cp += 2;
1702
1703 *(uint8_t*)cp = filenameLen;
1704 cp += 1;
1705 memcpy(cp, filename, filenameLen);
1706 cp += filenameLen;
1707
1708 *(uint32_t*)cp = SWAP32(index);
1709 cp += 4;
1710
1711 if ((fontflags[f] & FONT_FLAGS_COLORED) != 0) {
1712 *(uint32_t*)cp = SWAP32(rgba);
1713 cp += 4;
1714 }
1715
1716 if (flags & XDV_FLAG_EXTEND) {
1717 Fixed f = D2Fix(extend);
1718 *(uint32_t*)(cp) = SWAP32(f);
1719 cp += 4;
1720 }
1721 if (flags & XDV_FLAG_SLANT) {
1722 Fixed f = D2Fix(slant);
1723 *(uint32_t*)(cp) = SWAP32(f);
1724 cp += 4;
1725 }
1726 if (flags & XDV_FLAG_EMBOLDEN) {
1727 Fixed f = D2Fix(embolden);
1728 *(uint32_t*)(cp) = SWAP32(f);
1729 cp += 4;
1730 }
1731
1732 free((char*) filename);
1733
1734 return fontDefLength;
1735 }
1736
1737 int
applymapping(void * pCnv,const uint16_t * txtPtr,int txtLen)1738 applymapping(void* pCnv, const uint16_t* txtPtr, int txtLen)
1739 {
1740 TECkit_Converter cnv = (TECkit_Converter)pCnv;
1741 UInt32 inUsed, outUsed;
1742 TECkit_Status status;
1743 static UInt32 outLength = 0;
1744
1745 /* allocate outBuffer if not big enough */
1746 if (outLength < txtLen * sizeof(UniChar) + 32) {
1747 if (mappedtext != 0)
1748 free(mappedtext);
1749 outLength = txtLen * sizeof(UniChar) + 32;
1750 mappedtext = xmalloc(outLength);
1751 }
1752
1753 /* try the mapping */
1754 retry:
1755 status = TECkit_ConvertBuffer(cnv,
1756 (Byte*)txtPtr, txtLen * sizeof(UniChar), &inUsed,
1757 (Byte*)mappedtext, outLength, &outUsed, true);
1758
1759 switch (status) {
1760 case kStatus_NoError:
1761 txtPtr = (const UniChar*)mappedtext;
1762 return outUsed / sizeof(UniChar);
1763
1764 case kStatus_OutputBufferFull:
1765 outLength += (txtLen * sizeof(UniChar)) + 32;
1766 free(mappedtext);
1767 mappedtext = xmalloc(outLength);
1768 goto retry;
1769
1770 default:
1771 return 0;
1772 }
1773 }
1774
1775 static void
snap_zone(scaled * value,scaled snap_value,scaled fuzz)1776 snap_zone(scaled* value, scaled snap_value, scaled fuzz)
1777 {
1778 scaled difference = *value - snap_value;
1779 if (difference <= fuzz && difference >= -fuzz)
1780 *value = snap_value;
1781 }
1782
1783 void
getnativecharheightdepth(integer font,integer ch,scaled * height,scaled * depth)1784 getnativecharheightdepth(integer font, integer ch, scaled* height, scaled* depth)
1785 {
1786 #define QUAD(f) fontinfo[6+parambase[f]].cint
1787 #define X_HEIGHT(f) fontinfo[5+parambase[f]].cint
1788 #define CAP_HEIGHT(f) fontinfo[8+parambase[f]].cint
1789
1790 float ht = 0.0;
1791 float dp = 0.0;
1792 Fixed fuzz;
1793
1794 #ifdef XETEX_MAC
1795 if (fontarea[font] == AAT_FONT_FLAG) {
1796 CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]);
1797 int gid = MapCharToGlyph_AAT(attributes, ch);
1798 GetGlyphHeightDepth_AAT(attributes, gid, &ht, &dp);
1799 } else
1800 #endif
1801 if (fontarea[font] == OTGR_FONT_FLAG) {
1802 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
1803 int gid = mapCharToGlyph(engine, ch);
1804 getGlyphHeightDepth(engine, gid, &ht, &dp);
1805 } else {
1806 fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_height_depth`\n");
1807 exit(3);
1808 }
1809
1810 *height = D2Fix(ht);
1811 *depth = D2Fix(dp);
1812
1813 /* snap to "known" zones for baseline, x-height, cap-height if within 4% of em-size */
1814 fuzz = QUAD(font) / 25;
1815 snap_zone(depth, 0, fuzz);
1816 snap_zone(height, 0, fuzz);
1817 snap_zone(height, X_HEIGHT(font), fuzz);
1818 snap_zone(height, CAP_HEIGHT(font), fuzz);
1819 }
1820
1821 scaled
getnativecharht(integer f,integer c)1822 getnativecharht(integer f, integer c)
1823 {
1824 scaled h, d;
1825 getnativecharheightdepth(f, c, &h, &d);
1826 return h;
1827 }
1828
1829 scaled
getnativechardp(integer f,integer c)1830 getnativechardp(integer f, integer c)
1831 {
1832 scaled h, d;
1833 getnativecharheightdepth(f, c, &h, &d);
1834 return d;
1835 }
1836
1837 void
getnativecharsidebearings(integer font,integer ch,scaled * lsb,scaled * rsb)1838 getnativecharsidebearings(integer font, integer ch, scaled* lsb, scaled* rsb)
1839 {
1840 float l, r;
1841
1842 #ifdef XETEX_MAC
1843 if (fontarea[font] == AAT_FONT_FLAG) {
1844 CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]);
1845 int gid = MapCharToGlyph_AAT(attributes, ch);
1846 GetGlyphSidebearings_AAT(attributes, gid, &l, &r);
1847 } else
1848 #endif
1849 if (fontarea[font] == OTGR_FONT_FLAG) {
1850 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
1851 int gid = mapCharToGlyph(engine, ch);
1852 getGlyphSidebearings(engine, gid, &l, &r);
1853 } else {
1854 fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_side_bearings'\n");
1855 exit(3);
1856 }
1857
1858 *lsb = D2Fix(l);
1859 *rsb = D2Fix(r);
1860 }
1861
1862 scaled
getglyphbounds(integer font,integer edge,integer gid)1863 getglyphbounds(integer font, integer edge, integer gid)
1864 {
1865 /* edge codes 1,2,3,4 => L T R B */
1866 float a, b;
1867
1868 #ifdef XETEX_MAC
1869 if (fontarea[font] == AAT_FONT_FLAG) {
1870 CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[font]);
1871 if (edge & 1)
1872 GetGlyphSidebearings_AAT(attributes, gid, &a, &b);
1873 else
1874 GetGlyphHeightDepth_AAT(attributes, gid, &a, &b);
1875 } else
1876 #endif
1877 if (fontarea[font] == OTGR_FONT_FLAG) {
1878 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
1879 if (edge & 1)
1880 getGlyphSidebearings(engine, gid, &a, &b);
1881 else
1882 getGlyphHeightDepth(engine, gid, &a, &b);
1883 } else {
1884 fprintf(stderr, "\n! Internal error: bad native font flag in `get_glyph_bounds'\n");
1885 exit(3);
1886 }
1887 return D2Fix((edge <= 2) ? a : b);
1888 }
1889
1890 scaled
getnativecharic(integer f,integer c)1891 getnativecharic(integer f, integer c)
1892 {
1893 scaled lsb, rsb;
1894 getnativecharsidebearings(f, c, &lsb, &rsb);
1895 if (rsb < 0)
1896 return fontletterspace[f] - rsb;
1897 else
1898 return fontletterspace[f];
1899 }
1900
1901 scaled
getnativecharwd(integer f,integer c)1902 getnativecharwd(integer f, integer c)
1903 {
1904 scaled wd = 0;
1905 #ifdef XETEX_MAC
1906 if (fontarea[f] == AAT_FONT_FLAG) {
1907 CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[f]);
1908 int gid = MapCharToGlyph_AAT(attributes, c);
1909 wd = D2Fix(GetGlyphWidth_AAT(attributes, gid));
1910 } else
1911 #endif
1912 if (fontarea[f] == OTGR_FONT_FLAG) {
1913 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f];
1914 int gid = mapCharToGlyph(engine, c);
1915 wd = D2Fix(getGlyphWidthFromEngine(engine, gid));
1916 } else {
1917 fprintf(stderr, "\n! Internal error: bad native font flag in `get_native_char_wd'\n");
1918 exit(3);
1919 }
1920 return wd;
1921 }
1922
1923 uint16_t
get_native_glyph(void * pNode,unsigned index)1924 get_native_glyph(void* pNode, unsigned index)
1925 {
1926 memoryword* node = (memoryword*)pNode;
1927 FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node);
1928 uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node));
1929 if (index >= native_glyph_count(node))
1930 return 0;
1931 else
1932 return glyphIDs[index];
1933 }
1934
1935 void
store_justified_native_glyphs(void * node)1936 store_justified_native_glyphs(void* node)
1937 {
1938 #ifdef XETEX_MAC /* this is only called for AAT fonts */
1939 (void)DoAATLayout(node, 1);
1940 #endif
1941 }
1942
1943 void
measure_native_node(void * pNode,int use_glyph_metrics)1944 measure_native_node(void* pNode, int use_glyph_metrics)
1945 {
1946 memoryword* node = (memoryword*)pNode;
1947 int txtLen = native_length(node);
1948 uint16_t* txtPtr = (uint16_t*)(node + native_node_size);
1949
1950 unsigned f = native_font(node);
1951
1952 #ifdef XETEX_MAC
1953 if (fontarea[f] == AAT_FONT_FLAG) {
1954 /* we're using this font in AAT mode, so fontlayoutengine[f] is actually a CFDictionaryRef */
1955 DoAATLayout(node, 0);
1956 } else
1957 #endif
1958 if (fontarea[f] == OTGR_FONT_FLAG) {
1959 /* using this font in OT Layout mode, so fontlayoutengine[f] is actually a XeTeXLayoutEngine */
1960
1961 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)(fontlayoutengine[f]);
1962
1963 FixedPoint* locations;
1964 uint16_t* glyphIDs;
1965 Fixed* glyphAdvances;
1966 int totalGlyphCount = 0;
1967
1968 /* need to find direction runs within the text, and call layoutChars separately for each */
1969
1970 UBiDiDirection dir;
1971 void* glyph_info = 0;
1972 static FloatPoint* positions = 0;
1973 static float* advances = 0;
1974 static uint32_t* glyphs = 0;
1975
1976 UBiDi* pBiDi = ubidi_open();
1977
1978 UErrorCode errorCode = U_ZERO_ERROR;
1979 ubidi_setPara(pBiDi, (const UChar*) txtPtr, txtLen, getDefaultDirection(engine), NULL, &errorCode);
1980
1981 dir = ubidi_getDirection(pBiDi);
1982 if (dir == UBIDI_MIXED) {
1983 /* we actually do the layout twice here, once to count glyphs and then again to get them;
1984 which is inefficient, but i figure that MIXED is a relatively rare occurrence, so i can't be
1985 bothered to deal with the memory reallocation headache of doing it differently
1986 */
1987 int nRuns = ubidi_countRuns(pBiDi, &errorCode);
1988 double width = 0;
1989 int i, runIndex;
1990 int32_t logicalStart, length;
1991 for (runIndex = 0; runIndex < nRuns; ++runIndex) {
1992 dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
1993 totalGlyphCount += layoutChars(engine, txtPtr, logicalStart, length, txtLen, (dir == UBIDI_RTL));
1994 }
1995
1996 if (totalGlyphCount > 0) {
1997 double x, y;
1998 glyph_info = xcalloc(totalGlyphCount, native_glyph_info_size);
1999 locations = (FixedPoint*)glyph_info;
2000 glyphIDs = (uint16_t*)(locations + totalGlyphCount);
2001 glyphAdvances = (Fixed*) xcalloc(totalGlyphCount, sizeof(Fixed));
2002 totalGlyphCount = 0;
2003
2004 x = y = 0.0;
2005 for (runIndex = 0; runIndex < nRuns; ++runIndex) {
2006 int nGlyphs;
2007 dir = ubidi_getVisualRun(pBiDi, runIndex, &logicalStart, &length);
2008 nGlyphs = layoutChars(engine, txtPtr, logicalStart, length, txtLen,
2009 (dir == UBIDI_RTL));
2010
2011 glyphs = (uint32_t*) xcalloc(nGlyphs, sizeof(uint32_t));
2012 positions = (FloatPoint*) xcalloc(nGlyphs + 1, sizeof(FloatPoint));
2013 advances = (float*) xcalloc(nGlyphs, sizeof(float));
2014
2015 getGlyphs(engine, glyphs);
2016 getGlyphAdvances(engine, advances);
2017 getGlyphPositions(engine, positions);
2018
2019 for (i = 0; i < nGlyphs; ++i) {
2020 glyphIDs[totalGlyphCount] = glyphs[i];
2021 locations[totalGlyphCount].x = D2Fix(positions[i].x + x);
2022 locations[totalGlyphCount].y = D2Fix(positions[i].y + y);
2023 glyphAdvances[totalGlyphCount] = D2Fix(advances[i]);
2024 ++totalGlyphCount;
2025 }
2026 x += positions[nGlyphs].x;
2027 y += positions[nGlyphs].y;
2028
2029 free(glyphs);
2030 free(positions);
2031 free(advances);
2032 }
2033 width = x;
2034 }
2035
2036 node_width(node) = D2Fix(width);
2037 native_glyph_count(node) = totalGlyphCount;
2038 native_glyph_info_ptr(node) = glyph_info;
2039 } else {
2040 double width = 0;
2041 totalGlyphCount = layoutChars(engine, txtPtr, 0, txtLen, txtLen, (dir == UBIDI_RTL));
2042
2043 glyphs = (uint32_t*) xcalloc(totalGlyphCount, sizeof(uint32_t));
2044 positions = (FloatPoint*) xcalloc(totalGlyphCount + 1, sizeof(FloatPoint));
2045 advances = (float*) xcalloc(totalGlyphCount, sizeof(float));
2046
2047 getGlyphs(engine, glyphs);
2048 getGlyphAdvances(engine, advances);
2049 getGlyphPositions(engine, positions);
2050
2051 if (totalGlyphCount > 0) {
2052 int i;
2053 glyph_info = xcalloc(totalGlyphCount, native_glyph_info_size);
2054 locations = (FixedPoint*)glyph_info;
2055 glyphIDs = (uint16_t*)(locations + totalGlyphCount);
2056 glyphAdvances = (Fixed*) xcalloc(totalGlyphCount, sizeof(Fixed));
2057 for (i = 0; i < totalGlyphCount; ++i) {
2058 glyphIDs[i] = glyphs[i];
2059 glyphAdvances[i] = D2Fix(advances[i]);
2060 locations[i].x = D2Fix(positions[i].x);
2061 locations[i].y = D2Fix(positions[i].y);
2062 }
2063 width = D2Fix(positions[totalGlyphCount].x);
2064 }
2065
2066 node_width(node) = width;
2067 native_glyph_count(node) = totalGlyphCount;
2068 native_glyph_info_ptr(node) = glyph_info;
2069
2070 free(glyphs);
2071 free(positions);
2072 free(advances);
2073 }
2074
2075 ubidi_close(pBiDi);
2076
2077
2078 if (fontletterspace[f] != 0) {
2079 Fixed lsDelta = 0;
2080 Fixed lsUnit = fontletterspace[f];
2081 int i;
2082 for (i = 0; i < totalGlyphCount; ++i) {
2083 if (glyphAdvances[i] == 0 && lsDelta != 0)
2084 lsDelta -= lsUnit;
2085 locations[i].x += lsDelta;
2086 lsDelta += lsUnit;
2087 }
2088 if (lsDelta != 0) {
2089 lsDelta -= lsUnit;
2090 node_width(node) += lsDelta;
2091 }
2092 }
2093 free(glyphAdvances);
2094 } else {
2095 fprintf(stderr, "\n! Internal error: bad native font flag in `measure_native_node'\n");
2096 exit(3);
2097 }
2098
2099 if (use_glyph_metrics == 0 || native_glyph_count(node) == 0) {
2100 /* for efficiency, height and depth are the font's ascent/descent,
2101 not true values based on the actual content of the word,
2102 unless use_glyph_metrics is non-zero */
2103 node_height(node) = heightbase[f];
2104 node_depth(node) = depthbase[f];
2105 } else {
2106 /* this iterates over the glyph data whether it comes from AAT or OT layout */
2107 FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node);
2108 uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node));
2109 float yMin = 65536.0;
2110 float yMax = -65536.0;
2111 int i;
2112 for (i = 0; i < native_glyph_count(node); ++i) {
2113 float ht, dp;
2114 float y = Fix2D(-locations[i].y); /* NB negative is upwards in locations[].y! */
2115
2116 GlyphBBox bbox;
2117 if (getCachedGlyphBBox(f, glyphIDs[i], &bbox) == 0) {
2118 #ifdef XETEX_MAC
2119 if (fontarea[f] == AAT_FONT_FLAG)
2120 GetGlyphBBox_AAT((CFDictionaryRef)(fontlayoutengine[f]), glyphIDs[i], &bbox);
2121 else
2122 #endif
2123 if (fontarea[f] == OTGR_FONT_FLAG)
2124 getGlyphBounds((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[i], &bbox);
2125
2126 cacheGlyphBBox(f, glyphIDs[i], &bbox);
2127 }
2128
2129 ht = bbox.yMax;
2130 dp = -bbox.yMin;
2131
2132 if (y + ht > yMax)
2133 yMax = y + ht;
2134 if (y - dp < yMin)
2135 yMin = y - dp;
2136 }
2137 node_height(node) = D2Fix(yMax);
2138 node_depth(node) = -D2Fix(yMin);
2139 }
2140 }
2141
2142 Fixed
get_native_italic_correction(void * pNode)2143 get_native_italic_correction(void* pNode)
2144 {
2145 memoryword* node = (memoryword*) pNode;
2146 unsigned f = native_font(node);
2147 unsigned n = native_glyph_count(node);
2148 if (n > 0) {
2149 FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node);
2150 uint16_t* glyphIDs = (uint16_t*)(locations + n);
2151
2152 #ifdef XETEX_MAC
2153 if (fontarea[f] == AAT_FONT_FLAG)
2154 return D2Fix(GetGlyphItalCorr_AAT((CFDictionaryRef)(fontlayoutengine[f]), glyphIDs[n-1]))
2155 + fontletterspace[f];
2156 #endif
2157 if (fontarea[f] == OTGR_FONT_FLAG)
2158 return D2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), glyphIDs[n-1]))
2159 + fontletterspace[f];
2160 }
2161
2162 return 0;
2163 }
2164
2165
2166 Fixed
get_native_glyph_italic_correction(void * pNode)2167 get_native_glyph_italic_correction(void* pNode)
2168 {
2169 memoryword* node = (memoryword*) pNode;
2170 uint16_t gid = native_glyph(node);
2171 unsigned f = native_font(node);
2172
2173 #ifdef XETEX_MAC
2174 if (fontarea[f] == AAT_FONT_FLAG)
2175 return D2Fix(GetGlyphItalCorr_AAT((CFDictionaryRef)(fontlayoutengine[f]), gid));
2176 #endif
2177 if (fontarea[f] == OTGR_FONT_FLAG)
2178 return D2Fix(getGlyphItalCorr((XeTeXLayoutEngine)(fontlayoutengine[f]), gid));
2179
2180 return 0; /* can't actually happen */
2181 }
2182
2183 void
measure_native_glyph(void * pNode,int use_glyph_metrics)2184 measure_native_glyph(void* pNode, int use_glyph_metrics)
2185 {
2186 memoryword* node = (memoryword*) pNode;
2187 uint16_t gid = native_glyph(node);
2188 unsigned f = native_font(node);
2189
2190 float ht = 0.0;
2191 float dp = 0.0;
2192
2193 #ifdef XETEX_MAC
2194 if (fontarea[f] == AAT_FONT_FLAG) {
2195 CFDictionaryRef attributes = (CFDictionaryRef)(fontlayoutengine[f]);
2196 node_width(node) = D2Fix(GetGlyphWidth_AAT(attributes, gid));
2197 if (use_glyph_metrics)
2198 GetGlyphHeightDepth_AAT(attributes, gid, &ht, &dp);
2199 } else
2200 #endif
2201 if (fontarea[f] == OTGR_FONT_FLAG) {
2202 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[f];
2203 XeTeXFont fontInst = getFont(engine);
2204 node_width(node) = D2Fix(getGlyphWidth(fontInst, gid));
2205 if (use_glyph_metrics)
2206 getGlyphHeightDepth(engine, gid, &ht, &dp);
2207 } else {
2208 fprintf(stderr, "\n! Internal error: bad native font flag in `measure_native_glyph'\n");
2209 exit(3);
2210 }
2211
2212 if (use_glyph_metrics) {
2213 node_height(node) = D2Fix(ht);
2214 node_depth(node) = D2Fix(dp);
2215 } else {
2216 node_height(node) = heightbase[f];
2217 node_depth(node) = depthbase[f];
2218 }
2219 }
2220
2221 integer
mapchartoglyph(integer font,integer ch)2222 mapchartoglyph(integer font, integer ch)
2223 {
2224 if (ch > 0x10ffff || ((ch >= 0xd800) && (ch <= 0xdfff)))
2225 return 0;
2226 #ifdef XETEX_MAC
2227 if (fontarea[font] == AAT_FONT_FLAG)
2228 return MapCharToGlyph_AAT((CFDictionaryRef)(fontlayoutengine[font]), ch);
2229 else
2230 #endif
2231 if (fontarea[font] == OTGR_FONT_FLAG)
2232 return mapCharToGlyph((XeTeXLayoutEngine)(fontlayoutengine[font]), ch);
2233 else {
2234 fprintf(stderr, "\n! Internal error: bad native font flag in `map_char_to_glyph'\n");
2235 exit(3);
2236 }
2237 }
2238
2239 integer
mapglyphtoindex(integer font)2240 mapglyphtoindex(integer font)
2241 /* glyph name is at nameoffile+1 */
2242 {
2243 #ifdef XETEX_MAC
2244 if (fontarea[font] == AAT_FONT_FLAG)
2245 return MapGlyphToIndex_AAT((CFDictionaryRef)(fontlayoutengine[font]), (const char*)nameoffile + 1);
2246 else
2247 #endif
2248 if (fontarea[font] == OTGR_FONT_FLAG)
2249 return mapGlyphToIndex((XeTeXLayoutEngine)(fontlayoutengine[font]), (const char*)nameoffile + 1);
2250 else {
2251 fprintf(stderr, "\n! Internal error: bad native font flag in `map_glyph_to_index'\n");
2252 exit(3);
2253 }
2254 }
2255
2256 integer
getfontcharrange(integer font,int first)2257 getfontcharrange(integer font, int first)
2258 {
2259 #ifdef XETEX_MAC
2260 if (fontarea[font] == AAT_FONT_FLAG)
2261 return GetFontCharRange_AAT((CFDictionaryRef)(fontlayoutengine[font]), first);
2262 else
2263 #endif
2264 if (fontarea[font] == OTGR_FONT_FLAG)
2265 return getFontCharRange((XeTeXLayoutEngine)(fontlayoutengine[font]), first);
2266 else {
2267 fprintf(stderr, "\n! Internal error: bad native font flag in `get_font_char_range'\n");
2268 exit(3);
2269 }
2270 }
2271
D2Fix(double d)2272 Fixed D2Fix(double d)
2273 {
2274 Fixed rval = (int)(d * 65536.0 + 0.5);
2275 return rval;
2276 }
2277
Fix2D(Fixed f)2278 double Fix2D(Fixed f)
2279 {
2280 double rval = f / 65536.0;
2281 return rval;
2282 }
2283
2284 /* these are here, not XeTeX_mac.c, because we need stubs on other platforms */
2285 void
aatgetfontmetrics(CFDictionaryRef attributes,integer * ascent,integer * descent,integer * xheight,integer * capheight,integer * slant)2286 aatgetfontmetrics(CFDictionaryRef attributes, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant)
2287 {
2288 #ifdef XETEX_MAC
2289 CTFontRef font = fontFromAttributes(attributes);
2290
2291 *ascent = D2Fix(CTFontGetAscent(font));
2292 *descent = D2Fix(CTFontGetDescent(font));
2293 *xheight = D2Fix(CTFontGetXHeight(font));
2294 *capheight = D2Fix(CTFontGetCapHeight(font));
2295 *slant = D2Fix(tan(-CTFontGetSlantAngle(font) * M_PI / 180.0));
2296 #endif
2297 }
2298
2299 int
aatfontget(int what,CFDictionaryRef attributes)2300 aatfontget(int what, CFDictionaryRef attributes)
2301 {
2302 int rval = -1;
2303
2304 #ifdef XETEX_MAC
2305 CTFontRef font = fontFromAttributes(attributes);
2306 CFArrayRef list;
2307
2308 switch (what) {
2309 case XeTeX_count_glyphs:
2310 rval = CTFontGetGlyphCount(font);
2311 break;
2312
2313 case XeTeX_count_features:
2314 list = CTFontCopyFeatures(font);
2315 if (list) {
2316 rval = CFArrayGetCount(list);
2317 CFRelease(list);
2318 }
2319 break;
2320 }
2321 #endif
2322 return rval;
2323 }
2324
2325 int
aatfontget1(int what,CFDictionaryRef attributes,int param)2326 aatfontget1(int what, CFDictionaryRef attributes, int param)
2327 {
2328 int rval = -1;
2329
2330 #ifdef XETEX_MAC
2331 CTFontRef font = fontFromAttributes(attributes);
2332
2333 switch (what) {
2334 case XeTeX_feature_code:
2335 {
2336 CFArrayRef features = CTFontCopyFeatures(font);
2337 if (features) {
2338 if (CFArrayGetCount(features) > param) {
2339 CFDictionaryRef feature = CFArrayGetValueAtIndex(features, param);
2340 CFNumberRef identifier = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey);
2341 if (identifier)
2342 CFNumberGetValue(identifier, kCFNumberIntType, &rval);
2343 }
2344 CFRelease(features);
2345 }
2346 break;
2347 }
2348
2349 case XeTeX_is_exclusive_feature:
2350 {
2351 CFArrayRef features = CTFontCopyFeatures(font);
2352 if (features) {
2353 CFBooleanRef value;
2354 CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param);
2355 Boolean found = CFDictionaryGetValueIfPresent(feature, kCTFontFeatureTypeExclusiveKey, (const void **)&value);
2356 if (found)
2357 rval = CFBooleanGetValue(value);
2358 CFRelease(features);
2359 }
2360 break;
2361 }
2362
2363 case XeTeX_count_selectors:
2364 {
2365 CFArrayRef features = CTFontCopyFeatures(font);
2366 if (features) {
2367 CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param);
2368 if (feature) {
2369 CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey);
2370 if (selectors)
2371 rval = CFArrayGetCount(selectors);
2372 }
2373 CFRelease(features);
2374 }
2375 break;
2376 }
2377 }
2378 #endif
2379
2380 return rval;
2381 }
2382
2383 int
aatfontget2(int what,CFDictionaryRef attributes,int param1,int param2)2384 aatfontget2(int what, CFDictionaryRef attributes, int param1, int param2)
2385 {
2386 int rval = -1;
2387
2388 #ifdef XETEX_MAC
2389 CTFontRef font = fontFromAttributes(attributes);
2390 CFArrayRef features = CTFontCopyFeatures(font);
2391 if (features) {
2392 CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param1);
2393 if (feature) {
2394 CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey);
2395 if (selectors) {
2396 CFDictionaryRef selector;
2397 switch (what) {
2398 case XeTeX_selector_code:
2399 if (CFArrayGetCount(selectors) > param2) {
2400 CFNumberRef identifier;
2401 selector = CFArrayGetValueAtIndex(selectors, param2);
2402 identifier = CFDictionaryGetValue(selector, kCTFontFeatureSelectorIdentifierKey);
2403 if (identifier)
2404 CFNumberGetValue(identifier, kCFNumberIntType, &rval);
2405 }
2406 break;
2407 case XeTeX_is_default_selector:
2408 selector = findDictionaryInArrayWithIdentifier(selectors, kCTFontFeatureSelectorIdentifierKey, param2);
2409 if (selector) {
2410 CFBooleanRef isDefault;
2411 Boolean found = CFDictionaryGetValueIfPresent(selector, kCTFontFeatureSelectorDefaultKey, (const void **)&isDefault);
2412 if (found)
2413 rval = CFBooleanGetValue(isDefault);
2414 }
2415 break;
2416 }
2417 }
2418 }
2419 CFRelease(features);
2420 }
2421 #endif
2422
2423 return rval;
2424 }
2425
2426 int
aatfontgetnamed(int what,CFDictionaryRef attributes)2427 aatfontgetnamed(int what, CFDictionaryRef attributes)
2428 {
2429 int rval = -1;
2430
2431 #ifdef XETEX_MAC
2432 if (what == XeTeX_find_feature_by_name)
2433 {
2434 CTFontRef font = fontFromAttributes(attributes);
2435 CFArrayRef features = CTFontCopyFeatures(font);
2436 if (features) {
2437 CFDictionaryRef feature = findDictionaryInArray(features, kCTFontFeatureTypeNameKey,
2438 (const char*)nameoffile + 1, namelength);
2439 if (feature) {
2440 CFNumberRef identifier = CFDictionaryGetValue(feature, kCTFontFeatureTypeIdentifierKey);
2441 CFNumberGetValue(identifier, kCFNumberIntType, &rval);
2442 }
2443 CFRelease(features);
2444 }
2445 }
2446 #endif
2447
2448 return rval;
2449 }
2450
2451 int
aatfontgetnamed1(int what,CFDictionaryRef attributes,int param)2452 aatfontgetnamed1(int what, CFDictionaryRef attributes, int param)
2453 {
2454 int rval = -1;
2455
2456 #ifdef XETEX_MAC
2457 CTFontRef font = fontFromAttributes(attributes);
2458
2459 if (what == XeTeX_find_selector_by_name) {
2460 CFArrayRef features = CTFontCopyFeatures(font);
2461 if (features) {
2462 CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features, kCTFontFeatureTypeIdentifierKey, param);
2463 if (feature) {
2464 CFNumberRef selector = findSelectorByName(feature, (const char*)nameoffile + 1, namelength);
2465 if (selector)
2466 CFNumberGetValue(selector, kCFNumberIntType, &rval);
2467 }
2468 CFRelease(features);
2469 }
2470 }
2471 #endif
2472
2473 return rval;
2474 }
2475
2476 void
aatprintfontname(int what,CFDictionaryRef attributes,int param1,int param2)2477 aatprintfontname(int what, CFDictionaryRef attributes, int param1, int param2)
2478 {
2479 #ifdef XETEX_MAC
2480 CFStringRef name = NULL;
2481 if (what == XeTeX_feature_name || what == XeTeX_selector_name) {
2482 CTFontRef font = fontFromAttributes(attributes);
2483 CFArrayRef features = CTFontCopyFeatures(font);
2484 if (features) {
2485 CFDictionaryRef feature = findDictionaryInArrayWithIdentifier(features,
2486 kCTFontFeatureTypeIdentifierKey,
2487 param1);
2488 if (feature) {
2489 if (what == XeTeX_feature_name)
2490 name = CFDictionaryGetValue(feature, kCTFontFeatureTypeNameKey);
2491 else {
2492 CFArrayRef selectors = CFDictionaryGetValue(feature, kCTFontFeatureTypeSelectorsKey);
2493 CFDictionaryRef selector = findDictionaryInArrayWithIdentifier(selectors,
2494 kCTFontFeatureSelectorIdentifierKey,
2495 param2);
2496 if (selector)
2497 name = CFDictionaryGetValue(selector, kCTFontFeatureSelectorNameKey);
2498 }
2499 }
2500 CFRelease(features);
2501 }
2502 }
2503
2504 if (name) {
2505 CFIndex len = CFStringGetLength(name);
2506 UniChar* buf = xcalloc(len, sizeof(UniChar));
2507 CFStringGetCharacters(name, CFRangeMake(0, len), buf);
2508 printchars(buf, len);
2509 free(buf);
2510 }
2511 #endif
2512 }
2513
2514 void
printglyphname(integer font,integer gid)2515 printglyphname(integer font, integer gid)
2516 {
2517 char* s;
2518 int len = 0;
2519 #ifdef XETEX_MAC
2520 if (fontarea[font] == AAT_FONT_FLAG) {
2521 s = GetGlyphNameFromCTFont(fontFromInteger(font), gid, &len);
2522 } else
2523 #endif
2524 if (fontarea[font] == OTGR_FONT_FLAG) {
2525 XeTeXLayoutEngine engine = (XeTeXLayoutEngine)fontlayoutengine[font];
2526 s = (char*)getGlyphName(getFont(engine), gid, &len);
2527 } else {
2528 fprintf(stderr, "\n! Internal error: bad native font flag in `print_glyph_name'\n");
2529 exit(3);
2530 }
2531 while (len-- > 0)
2532 printchar(*s++);
2533 }
2534
2535 int
u_open_in(unicodefile * f,integer filefmt,const_string fopen_mode,integer mode,integer encodingData)2536 u_open_in(unicodefile* f, integer filefmt, const_string fopen_mode, integer mode, integer encodingData)
2537 {
2538 boolean rval;
2539 *f = (unicodefile) xmalloc(sizeof(UFILE));
2540 (*f)->encodingMode = 0;
2541 (*f)->conversionData = 0;
2542 (*f)->savedChar = -1;
2543 (*f)->skipNextLF = 0;
2544 rval = open_input (&((*f)->f), filefmt, fopen_mode);
2545 if (rval) {
2546 int B1, B2;
2547 if (mode == AUTO) {
2548 /* sniff encoding form */
2549 B1 = GETC((*f)->f);
2550 B2 = GETC((*f)->f);
2551 if (B1 == 0xfe && B2 == 0xff)
2552 mode = UTF16BE;
2553 else if (B2 == 0xfe && B1 == 0xff)
2554 mode = UTF16LE;
2555 else if (B1 == 0 && B2 != 0) {
2556 mode = UTF16BE;
2557 rewind((*f)->f);
2558 } else if (B2 == 0 && B1 != 0) {
2559 mode = UTF16LE;
2560 rewind((*f)->f);
2561 } else if (B1 == 0xef && B2 == 0xbb) {
2562 int B3 = GETC((*f)->f);
2563 if (B3 == 0xbf)
2564 mode = UTF8;
2565 }
2566 if (mode == AUTO) {
2567 rewind((*f)->f);
2568 mode = UTF8;
2569 }
2570 }
2571
2572 setinputfileencoding(*f, mode, encodingData);
2573 }
2574 return rval;
2575 }
2576
2577 #if defined(WIN32)
2578 static int
Isspace(char c)2579 Isspace(char c)
2580 {
2581 return (c == ' ' || c == '\t');
2582 }
2583 #endif
2584
2585 int
open_dvi_output(FILE ** fptr)2586 open_dvi_output(FILE** fptr)
2587 {
2588 if (nopdfoutput) {
2589 return open_output(fptr, FOPEN_WBIN_MODE);
2590 } else {
2591 const char *p = (const char*)nameoffile+1;
2592 char *cmd, *q, *bindir = NULL;
2593 int len = strlen(p);
2594 while (*p)
2595 if (*p++ == '\"')
2596 ++len;
2597 len += strlen(outputdriver);
2598 #ifndef WIN32
2599 if (!kpse_absolute_p(outputdriver, true))
2600 bindir = kpse_var_value("SELFAUTOLOC");
2601 if (bindir)
2602 len += strlen(bindir) + 1;
2603 #endif
2604 if (output_directory)
2605 len += strlen(output_directory);
2606 len += 10; /* space for -o flag, quotes, NUL */
2607 for (p = (const char*)nameoffile+1; *p; p++)
2608 if (*p == '\"')
2609 ++len; /* allow extra space to escape quotes in filename */
2610 cmd = xmalloc(len);
2611 #ifdef WIN32
2612 strcpy(cmd, outputdriver);
2613 #else
2614 if (bindir) {
2615 strcpy(cmd, bindir);
2616 strcat(cmd, "/");
2617 strcat(cmd, outputdriver);
2618 } else {
2619 strcpy(cmd, outputdriver);
2620 }
2621 #endif
2622 strcat(cmd, " -o \"");
2623 if (output_directory) {
2624 len = strlen(output_directory);
2625 if (IS_DIR_SEP(output_directory[len-1]))
2626 output_directory[len-1] = '\0';
2627 strcat(cmd, output_directory);
2628 strcat(cmd, "/");
2629 }
2630 q = cmd + strlen(cmd);
2631 for (p = (const char*)nameoffile+1; *p; p++) {
2632 if (*p == '\"')
2633 *q++ = '\\';
2634 *q++ = *p;
2635 }
2636 *q++ = '\"';
2637 *q = '\0';
2638 if (papersize != 0) {
2639 char* cmd2 = concat3(cmd, " -p ", papersize);
2640 free(cmd);
2641 cmd = cmd2;
2642 }
2643 if (output_directory) {
2644 char *fullname = concat3(output_directory, "/", (const char*)nameoffile+1);
2645 free(nameoffile);
2646 namelength = strlen(fullname);
2647 nameoffile = (unsigned char*) xmalloc(namelength + 2);
2648 strcpy((char*)nameoffile+1, fullname);
2649 free(fullname);
2650 }
2651 #if defined(WIN32)
2652 {
2653 wchar_t *tmp1w;
2654 char *p, *pp, *fullcmd, *prgnam;
2655 bindir = kpse_var_value("SELFAUTOLOC");
2656 for(pp = bindir; *pp; pp++) {
2657 if(*pp == '/') *pp = '\\';
2658 }
2659 pp = cmd;
2660 while(Isspace(*pp))
2661 pp++;
2662 prgnam = xmalloc(strlen(cmd));
2663 p = prgnam;
2664 while(!Isspace(*pp)) {
2665 *p++ = *pp++;
2666 }
2667 *p = '\0';
2668 fullcmd = concatn("\"\"", bindir, "\\", prgnam, "\"", pp, "\"", NULL);
2669 tmp1w = get_wstring_from_mbstring(CP_UTF8, (const char *)fullcmd, tmp1w=NULL);
2670 *fptr = _wpopen(tmp1w, L"wb");
2671 free(bindir);
2672 free(prgnam);
2673 free(fullcmd);
2674 free(tmp1w);
2675 }
2676 #else
2677 *fptr = popen(cmd, "w");
2678 #endif
2679 free(cmd);
2680 return (*fptr != 0);
2681 }
2682 }
2683
2684 int
dviclose(FILE * fptr)2685 dviclose(FILE* fptr)
2686 {
2687 if (nopdfoutput) {
2688 if (fclose(fptr) != 0)
2689 return errno;
2690 } else {
2691 return pclose(fptr);
2692 }
2693 return 0;
2694 }
2695
2696 int
get_uni_c(UFILE * f)2697 get_uni_c(UFILE* f)
2698 {
2699 int rval;
2700 int c;
2701 #ifdef WIN32
2702 HANDLE hStdin;
2703 DWORD ret;
2704 wint_t wc[1];
2705 #endif
2706
2707 if (f->savedChar != -1) {
2708 rval = f->savedChar;
2709 f->savedChar = -1;
2710 return rval;
2711 }
2712
2713 switch (f->encodingMode) {
2714 case UTF8:
2715 c = rval = GETC(f->f);
2716 if (rval != EOF) {
2717 uint16_t extraBytes = bytesFromUTF8[rval];
2718 switch (extraBytes) { /* note: code falls through cases! */
2719 case 3: c = GETC(f->f);
2720 if (c < 0x80 || c >= 0xc0) goto bad_utf8;
2721 rval <<= 6; rval += c;
2722 case 2: c = GETC(f->f);
2723 if (c < 0x80 || c >= 0xc0) goto bad_utf8;
2724 rval <<= 6; rval += c;
2725 case 1: c = GETC(f->f);
2726 if (c < 0x80 || c >= 0xc0) goto bad_utf8;
2727 rval <<= 6; rval += c;
2728 case 0:
2729 break;
2730
2731 bad_utf8:
2732 if (c != EOF)
2733 UNGETC(c, f->f);
2734 case 5:
2735 case 4:
2736 badutf8warning();
2737 return 0xfffd; /* return without adjusting by offsetsFromUTF8 */
2738 };
2739 rval -= offsetsFromUTF8[extraBytes];
2740 }
2741 break;
2742
2743 case UTF16BE:
2744 rval = GETC(f->f);
2745 if (rval != EOF) {
2746 rval <<= 8;
2747 rval += GETC(f->f);
2748 if (rval >= 0xd800 && rval <= 0xdbff) {
2749 int lo = GETC(f->f);
2750 lo <<= 8;
2751 lo += GETC(f->f);
2752 if (lo >= 0xdc00 && lo <= 0xdfff)
2753 rval = 0x10000 + (rval - 0xd800) * 0x400 + (lo - 0xdc00);
2754 else {
2755 rval = 0xfffd;
2756 f->savedChar = lo;
2757 }
2758 } else if (rval >= 0xdc00 && rval <= 0xdfff)
2759 rval = 0xfffd;
2760 }
2761 break;
2762
2763 case UTF16LE:
2764 rval = GETC(f->f);
2765 if (rval != EOF) {
2766 rval += (GETC(f->f) << 8);
2767 if (rval >= 0xd800 && rval <= 0xdbff) {
2768 int lo = GETC(f->f);
2769 lo += (GETC(f->f) << 8);
2770 if (lo >= 0xdc00 && lo <= 0xdfff)
2771 rval = 0x10000 + (rval - 0xd800) * 0x400 + (lo - 0xdc00);
2772 else {
2773 rval = 0xfffd;
2774 f->savedChar = lo;
2775 }
2776 } else if (rval >= 0xdc00 && rval <= 0xdfff)
2777 rval = 0xfffd;
2778 }
2779 break;
2780
2781 #ifdef WIN32
2782 case WIN32CONSOLE:
2783 hStdin = GetStdHandle(STD_INPUT_HANDLE);
2784 if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) {
2785 rval = EOF;
2786 break;
2787 }
2788 rval = wc[0];
2789 if (rval >= 0xd800 && rval <= 0xdbff) {
2790 int lo;
2791 if (ReadConsoleW(hStdin, wc, 1, &ret, NULL) == 0) {
2792 rval = EOF;
2793 break;
2794 }
2795 lo = wc[0];
2796 if (lo >= 0xdc00 && lo <= 0xdfff)
2797 rval = 0x10000 + (rval - 0xd800) * 0x400 + (lo - 0xdc00);
2798 else {
2799 rval = 0xfffd;
2800 f->savedChar = lo;
2801 }
2802 } else if (rval >= 0xdc00 && rval <= 0xdfff)
2803 rval = 0xfffd;
2804 break;
2805 #endif
2806
2807 case RAW:
2808 rval = GETC(f->f);
2809 break;
2810
2811 default:
2812 /* this can't happen */
2813 fprintf(stderr, "! Internal error---file input mode=%d.\n", f->encodingMode);
2814 uexit(3);
2815 }
2816
2817 return rval;
2818 }
2819
2820 void
makeutf16name()2821 makeutf16name()
2822 {
2823 unsigned char* s = nameoffile + 1;
2824 uint32_t rval;
2825 uint16_t* t;
2826 static int name16len = 0;
2827 if (name16len <= namelength) {
2828 if (nameoffile16 != 0)
2829 free(nameoffile16);
2830 name16len = namelength + 10;
2831 nameoffile16 = (uint16_t*) xcalloc(name16len, sizeof(uint16_t));
2832 }
2833 t = nameoffile16;
2834 while (s <= nameoffile + namelength) {
2835 uint16_t extraBytes;
2836 rval = *(s++);
2837 extraBytes = bytesFromUTF8[rval];
2838 switch (extraBytes) { /* note: code falls through cases! */
2839 case 5: rval <<= 6; if (*s) rval += *(s++);
2840 case 4: rval <<= 6; if (*s) rval += *(s++);
2841 case 3: rval <<= 6; if (*s) rval += *(s++);
2842 case 2: rval <<= 6; if (*s) rval += *(s++);
2843 case 1: rval <<= 6; if (*s) rval += *(s++);
2844 case 0: ;
2845 };
2846 rval -= offsetsFromUTF8[extraBytes];
2847 if (rval > 0xffff) {
2848 rval -= 0x10000;
2849 *(t++) = 0xd800 + rval / 0x0400;
2850 *(t++) = 0xdc00 + rval % 0x0400;
2851 } else {
2852 *(t++) = rval;
2853 }
2854 }
2855 namelength16 = t - nameoffile16;
2856 }
2857
2858
get_native_word_cp(void * pNode,int side)2859 integer get_native_word_cp(void* pNode, int side)
2860 {
2861 memoryword* node = (memoryword*)pNode;
2862 FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node);
2863 uint16_t* glyphIDs = (uint16_t*)(locations + native_glyph_count(node));
2864 uint16_t glyphCount = native_glyph_count(node);
2865 integer f = native_font(node);
2866 uint16_t actual_glyph;
2867
2868 if (glyphCount == 0)
2869 return 0;
2870
2871 switch (side) {
2872 case LEFT_SIDE:
2873 actual_glyph = *glyphIDs;
2874 break;
2875 case RIGHT_SIDE:
2876 actual_glyph = glyphIDs[glyphCount - 1];
2877 break;
2878 default:
2879 assert(0); // we should not reach this point
2880 }
2881 return get_cp_code(f, actual_glyph, side);
2882 }
2883