diff options
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/XeTeX_ext.c')
-rw-r--r-- | Build/source/texk/web2c/xetexdir/XeTeX_ext.c | 296 |
1 files changed, 197 insertions, 99 deletions
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c index f12f2edd089..0e90547c385 100644 --- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c +++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c @@ -254,7 +254,14 @@ setinputfileencoding(UFILE* f, integer mode, integer encodingData) UErrorCode err = 0; UConverter* cnv = ucnv_open(name, &err); if (cnv == NULL) { - fprintf(stderr, "! Error %d creating Unicode converter for %s\n", err, name); + begindiagnostic(); + printnl('E'); + printcstring("rror "); + printint(err); + printcstring(" creating Unicode converter for `"); + printcstring(name); + printcstring("'; reading as raw bytes"); + enddiagnostic(1); f->encodingMode = RAW; } else { @@ -278,66 +285,185 @@ uclose(UFILE* f) } } -int -input_line_icu(UFILE* f) +static void +buffer_overflow() { -static char* byteBuffer = NULL; + fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n", + (unsigned) bufsize); + fputs ("Please increase buf_size in texmf.cnf.\n", stderr); + uexit (1); +} - UInt32 bytesRead = 0; - int i; - UConverter* cnv; - int outLen; - UErrorCode errorCode = 0; +static void +conversion_error(int errcode) +{ + begindiagnostic(); + printnl('U'); + printcstring("nicode conversion failed (ICU error code = "); + printint(errcode); + printcstring(") discarding any remaining text"); + enddiagnostic(1); +} - if (byteBuffer == NULL) - byteBuffer = xmalloc(bufsize + 1); +#ifdef WORDS_BIGENDIAN +#define NATIVE_UTF32 kForm_UTF32BE +#else +#define NATIVE_UTF32 kForm_UTF32LE +#endif - /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ - i = getc(f->f); - if (f->skipNextLF) { - f->skipNextLF = 0; - if (i == '\n') - i = getc(f->f); +static void +apply_normalization(UInt32* buf, int len, int norm) +{ + static TECkit_Converter normalizers[2] = { NULL, NULL }; + + TECkit_Status status; + UInt32 inUsed, outUsed; + TECkit_Converter *normPtr = &normalizers[norm - 1]; + if (*normPtr == NULL) { + status = TECkit_CreateConverter(NULL, 0, 1, + NATIVE_UTF32, NATIVE_UTF32 | (norm == 1 ? kForm_NFC : kForm_NFD), + &*normPtr); + if (status != kStatus_NoError) { + fprintf(stderr, "! Failed to create normalizer: error code = %d\n", (int)status); + uexit (1); + } } - if (i != EOF && i != '\n' && i != '\r') - byteBuffer[bytesRead++] = i; - if (i != EOF && i != '\n' && i != '\r') - while (bytesRead < bufsize && (i = getc(f->f)) != EOF && i != '\n' && i != '\r') + status = TECkit_ConvertBuffer(*normPtr, (Byte*)buf, len * sizeof(UInt32), &inUsed, + (Byte*)&buffer[first], sizeof(*buffer) * (bufsize - first), &outUsed, 1); + if (status != kStatus_NoError) + buffer_overflow(); + last = first + outUsed / sizeof(*buffer); +} + +#ifdef WORDS_BIGENDIAN +#define UCNV_UTF32_NativeEndian UCNV_UTF32_BigEndian +#else +#define UCNV_UTF32_NativeEndian UCNV_UTF32_LittleEndian +#endif + +int +input_line(UFILE* f) +{ +static char* byteBuffer = NULL; +static UInt32 *utf32Buf = NULL; + int i, tmpLen; + + int norm = getinputnormalizationstate(); + + if (f->encodingMode == ICUMAPPING) { + UInt32 bytesRead = 0; + UConverter* cnv; + int outLen; + UErrorCode errorCode = 0; + + if (byteBuffer == NULL) + byteBuffer = xmalloc(bufsize + 1); + + /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ + i = getc(f->f); + if (f->skipNextLF) { + f->skipNextLF = 0; + if (i == '\n') + i = getc(f->f); + } + + if (i != EOF && i != '\n' && i != '\r') byteBuffer[bytesRead++] = i; + if (i != EOF && i != '\n' && i != '\r') + while (bytesRead < bufsize && (i = getc(f->f)) != EOF && i != '\n' && i != '\r') + byteBuffer[bytesRead++] = i; + + if (i == EOF && errno != EINTR && last == first) + return false; + + if (i != EOF && i != '\n' && i != '\r') + buffer_overflow(); + + /* now apply the mapping to turn external bytes into Unicode characters in buffer */ + cnv = (UConverter*)(f->conversionData); + switch (norm) { + case 1: // NFC + case 2: // NFD + if (utf32Buf == NULL) + utf32Buf = (UInt32*)xmalloc(bufsize * sizeof(*utf32Buf)); + tmpLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, + (char*)utf32Buf, bufsize * sizeof(*utf32Buf), + byteBuffer, bytesRead, &errorCode); + if (errorCode != 0) { + conversion_error((int)errorCode); + return false; + } + apply_normalization(utf32Buf, tmpLen / sizeof(*utf32Buf), norm); // sets 'last' correctly + break; - if (i == EOF && errno != EINTR && last == first) - return false; - - if (i != EOF && i != '\n' && i != '\r') { - fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n", - (unsigned) bufsize); - fputs ("Please increase buf_size in texmf.cnf.\n", stderr); - uexit (1); + default: // none + outLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, + (char*)&buffer[first], sizeof(*buffer) * (bufsize - first), + byteBuffer, bytesRead, &errorCode); + if (errorCode != 0) { + conversion_error((int)errorCode); + return false; + } + outLen /= sizeof(*buffer); + last = first + outLen; + break; + } + } + else { + /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ + i = get_uni_c(f); + if (f->skipNextLF) { + f->skipNextLF = 0; + if (i == '\n') + i = get_uni_c(f); + } + + switch (norm) { + case 1: // NFC + case 2: // NFD + // read Unicode chars into utf32Buf as UTF32 + if (utf32Buf == NULL) + utf32Buf = xmalloc(bufsize * sizeof(*utf32Buf)); + tmpLen = 0; + if (i != EOF && i != '\n' && i != '\r') + utf32Buf[tmpLen++] = i; + if (i != EOF && i != '\n' && i != '\r') + while (tmpLen < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') + utf32Buf[tmpLen++] = i; + + if (i == EOF && errno != EINTR && last == first) + return false; + + /* We didn't get the whole line because our buffer was too small. */ + if (i != EOF && i != '\n' && i != '\r') + buffer_overflow(); + apply_normalization(utf32Buf, tmpLen, norm); + break; + + default: // none + last = first; + if (last < bufsize && i != EOF && i != '\n' && i != '\r') + buffer[last++] = i; + if (i != EOF && i != '\n' && i != '\r') + while (last < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') + buffer[last++] = i; + + if (i == EOF && errno != EINTR && last == first) + return false; + + /* We didn't get the whole line because our buffer was too small. */ + if (i != EOF && i != '\n' && i != '\r') + buffer_overflow(); + break; + } } /* If line ended with CR, remember to skip following LF. */ if (i == '\r') f->skipNextLF = 1; - /* now apply the mapping to turn external bytes into Unicode characters in buffer */ - cnv = (UConverter*)(f->conversionData); -#ifdef WORDS_BIGENDIAN -#define UCNV_UTF32_NativeEndian UCNV_UTF32_BigEndian -#else -#define UCNV_UTF32_NativeEndian UCNV_UTF32_LittleEndian -#endif - outLen = ucnv_toAlgorithmic(UCNV_UTF32_NativeEndian, cnv, - (char*)&buffer[first], sizeof(*buffer) * (bufsize - first), - byteBuffer, bytesRead, &errorCode); - if (errorCode != 0) { - fprintf(stderr, "! Unicode conversion failed: error code = %d\n", (int)errorCode); - return false; - } - outLen /= sizeof(*buffer); - last = first + outLen; buffer[last] = ' '; - if (last >= maxbufstack) maxbufstack = last; @@ -372,7 +498,14 @@ linebreakstart(integer localeStrNum, const UniChar* text, integer textLength) char* locale = (char*)gettexstring(localeStrNum); brkIter = ubrk_open(UBRK_LINE, locale, NULL, 0, &status); if (U_FAILURE(status)) { - fprintf(stderr, "\n! error %d creating linebreak iterator for locale \"%s\", trying default. ", status, locale); + begindiagnostic(); + printnl('E'); + printcstring("rror "); + printint(status); + printcstring(" creating linebreak iterator for locale `"); + printcstring(locale); + printcstring("'; trying default locale `en_us'."); + enddiagnostic(1); if (brkIter != NULL) ubrk_close(brkIter); status = 0; @@ -432,7 +565,12 @@ getencodingmodeandinfo(integer* info) /* try for an ICU converter */ cnv = ucnv_open(name, &err); if (cnv == NULL) { - fprintf(stderr, "! unknown encoding \"%s\"; reading as raw bytes\n", name); + begindiagnostic(); + printnl('U'); /* ensure message starts on a new line */ + printcstring("nknown encoding `"); + printcstring(name); + printcstring("'; reading as raw bytes"); + enddiagnostic(1); return RAW; } else { @@ -1981,8 +2119,13 @@ measure_native_node(void* pNode, int use_glyph_metrics) int i; OSStatus status = 0; nGlyphs = layoutChars(engine, (UniChar*)txtPtr, 0, txtLen, txtLen, (dir == UBIDI_RTL), 0.0, 0.0, &status); + float maxRhs = 0.0; +/* NO -- this is not valid in some Indic split-vowel situations + see http://sourceforge.net/tracker/index.php?func=detail&aid=1951292&group_id=194926&atid=951385 */ +#if 0 getGlyphPosition(engine, nGlyphs, &x, &y, &status); node_width(node) = X2Fix(x); +#endif if (nGlyphs >= maxGlyphs) { if (glyphs != 0) { @@ -2007,6 +2150,9 @@ measure_native_node(void* pNode, int use_glyph_metrics) realGlyphCount = 0; for (i = 0; i < nGlyphs; ++i) { if (glyphs[i] < 0xfffe) { + float rhs = positions[2*i] + getGlyphWidth(getFont(engine), glyphs[i]); + if (rhs > maxRhs) + maxRhs = rhs; glyphIDs[realGlyphCount] = glyphs[i]; locations[realGlyphCount].x = X2Fix(positions[2*i]); locations[realGlyphCount].y = X2Fix(positions[2*i+1]); @@ -2014,7 +2160,8 @@ measure_native_node(void* pNode, int use_glyph_metrics) } } } - + + node_width(node) = X2Fix(maxRhs); native_glyph_count(node) = realGlyphCount; native_glyph_info_ptr(node) = glyph_info; } @@ -2265,7 +2412,7 @@ double Fix2X(Fixed f) /* these are here, not XeTeX_mac.c, because we need stubs on other platforms */ void -atsugetfontmetrics(ATSUStyle style, Fixed* ascent, Fixed* descent, Fixed* xheight, Fixed* capheight, Fixed* slant) +atsugetfontmetrics(ATSUStyle style, integer* ascent, integer* descent, integer* xheight, integer* capheight, integer* slant) { #ifdef XETEX_MAC *ascent = *descent = *xheight = *capheight = *slant = 0; @@ -2865,55 +3012,6 @@ get_uni_c(UFILE* f) return rval; } -int -input_line(UFILE* f) -{ - int i; - - if (f->encodingMode == ICUMAPPING) - return input_line_icu(f); - - /* Recognize either LF or CR as a line terminator; skip initial LF if prev line ended with CR. */ - i = get_uni_c(f); - if (f->skipNextLF) { - f->skipNextLF = 0; - if (i == '\n') - i = get_uni_c(f); - } - - last = first; - if (last < bufsize && i != EOF && i != '\n' && i != '\r') - buffer[last++] = i; - if (i != EOF && i != '\n' && i != '\r') - while (last < bufsize && (i = get_uni_c(f)) != EOF && i != '\n' && i != '\r') - buffer[last++] = i; - - if (i == EOF && errno != EINTR && last == first) - return false; - - /* We didn't get the whole line because our buffer was too small. */ - if (i != EOF && i != '\n' && i != '\r') { - fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n", - (unsigned) bufsize); - fputs ("Please increase buf_size in texmf.cnf.\n", stderr); - uexit (1); - } - - buffer[last] = ' '; - if (last >= maxbufstack) - maxbufstack = last; - - /* If line ended with CR, remember to skip following LF. */ - if (i == '\r') - f->skipNextLF = 1; - - /* Trim trailing whitespace. */ - while (last > first && ISBLANK (buffer[last - 1])) - --last; - - return true; -} - void makeutf16name() { |