summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHan The Thanh <hanthethanh@gmail.com>2010-06-05 07:28:22 +0000
committerHan The Thanh <hanthethanh@gmail.com>2010-06-05 07:28:22 +0000
commitfc6e759582a57b0d59398fb5e923157416fc0055 (patch)
tree4bab960903146ab1cc11d0666a9fa5d240f5d6d3
parent55524f8b6257bf114c5a49091a82b66225b4646e (diff)
added character protrusion for xetex; changed version string to 0.9997.1
git-svn-id: svn://tug.org/texlive/trunk@18754 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/texk/web2c/Makefile.in26
-rw-r--r--Build/source/texk/web2c/synctexdir/synctex.c5
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp5
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp18
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h3
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_ext.c36
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_ext.h7
-rw-r--r--Build/source/texk/web2c/xetexdir/XeTeX_mac.c70
-rw-r--r--Build/source/texk/web2c/xetexdir/am/xetex.am2
-rw-r--r--Build/source/texk/web2c/xetexdir/hz.cpp51
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex-hz.ch982
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.ch8
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.defines4
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.h3
14 files changed, 1203 insertions, 17 deletions
diff --git a/Build/source/texk/web2c/Makefile.in b/Build/source/texk/web2c/Makefile.in
index 3508316039c..45a8c811d24 100644
--- a/Build/source/texk/web2c/Makefile.in
+++ b/Build/source/texk/web2c/Makefile.in
@@ -442,7 +442,7 @@ am__libxetex_a_SOURCES_DIST = xetexdir/MathTable.h \
xetexdir/XeTeXOTMath.h xetexdir/XeTeX_ext.c \
xetexdir/XeTeX_ext.h xetexdir/XeTeXswap.h xetexdir/cmaps.cpp \
xetexdir/cmaps.h xetexdir/sfnt.h xetexdir/trans.c \
- xetexdir/trans.h xetexdir/xetex.h \
+ xetexdir/trans.h xetexdir/hz.cpp xetexdir/xetex.h \
xetexdir/XeTeXFontInst_Mac.cpp xetexdir/XeTeXFontInst_Mac.h \
xetexdir/XeTeX_mac.c xetexdir/XeTeXFontMgr_FC.cpp \
xetexdir/XeTeXFontMgr_FC.h xetexdir/XeTeX_pic.c \
@@ -473,8 +473,8 @@ am_libxetex_a_OBJECTS = libxetex_a-FontTableCache.$(OBJEXT) \
libxetex_a-XeTeXOTLayoutEngine.$(OBJEXT) \
libxetex_a-XeTeXOTMath.$(OBJEXT) \
libxetex_a-XeTeX_ext.$(OBJEXT) libxetex_a-cmaps.$(OBJEXT) \
- libxetex_a-trans.$(OBJEXT) $(am__objects_8) $(am__objects_9) \
- $(am__objects_10)
+ libxetex_a-trans.$(OBJEXT) libxetex_a-hz.$(OBJEXT) \
+ $(am__objects_8) $(am__objects_9) $(am__objects_10)
libxetex_a_OBJECTS = $(am_libxetex_a_OBJECTS)
libxetexmm_a_AR = $(AR) $(ARFLAGS)
libxetexmm_a_LIBADD =
@@ -2210,6 +2210,7 @@ xetex_web_srcs = \
$(xetex_ch_synctex) \
xetexdir/xetex.ch \
xetexdir/xetex-latex3.ch \
+ xetexdir/xetex-hz.ch \
$(xetex_post_ch_synctex)
libxetex_a_CPPFLAGS = $(xetex_cppflags)
@@ -2227,8 +2228,8 @@ libxetex_a_SOURCES = xetexdir/MathTable.h xetexdir/FontTableCache.cpp \
xetexdir/XeTeXOTMath.h xetexdir/XeTeX_ext.c \
xetexdir/XeTeX_ext.h xetexdir/XeTeXswap.h xetexdir/cmaps.cpp \
xetexdir/cmaps.h xetexdir/sfnt.h xetexdir/trans.c \
- xetexdir/trans.h xetexdir/xetex.h $(am__append_38) \
- $(am__append_39) $(am__append_40)
+ xetexdir/trans.h xetexdir/hz.cpp xetexdir/xetex.h \
+ $(am__append_38) $(am__append_39) $(am__append_40)
# We must create xetexd.h etc. before building the libxetex_a_OBJECTS.
libxetex_prereq = xetexd.h $(xetex_dependencies)
@@ -3030,6 +3031,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-XeTeX_pic.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-bmpimage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-cmaps.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-hz.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-jpegimage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-mfileio.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxetex_a-numbers.Po@am__quote@
@@ -7802,6 +7804,20 @@ libxetex_a-cmaps.obj: xetexdir/cmaps.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxetex_a_CPPFLAGS) $(CPPFLAGS) $(libxetex_a_CXXFLAGS) $(CXXFLAGS) -c -o libxetex_a-cmaps.obj `if test -f 'xetexdir/cmaps.cpp'; then $(CYGPATH_W) 'xetexdir/cmaps.cpp'; else $(CYGPATH_W) '$(srcdir)/xetexdir/cmaps.cpp'; fi`
+libxetex_a-hz.o: xetexdir/hz.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxetex_a_CPPFLAGS) $(CPPFLAGS) $(libxetex_a_CXXFLAGS) $(CXXFLAGS) -MT libxetex_a-hz.o -MD -MP -MF $(DEPDIR)/libxetex_a-hz.Tpo -c -o libxetex_a-hz.o `test -f 'xetexdir/hz.cpp' || echo '$(srcdir)/'`xetexdir/hz.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libxetex_a-hz.Tpo $(DEPDIR)/libxetex_a-hz.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='xetexdir/hz.cpp' object='libxetex_a-hz.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxetex_a_CPPFLAGS) $(CPPFLAGS) $(libxetex_a_CXXFLAGS) $(CXXFLAGS) -c -o libxetex_a-hz.o `test -f 'xetexdir/hz.cpp' || echo '$(srcdir)/'`xetexdir/hz.cpp
+
+libxetex_a-hz.obj: xetexdir/hz.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxetex_a_CPPFLAGS) $(CPPFLAGS) $(libxetex_a_CXXFLAGS) $(CXXFLAGS) -MT libxetex_a-hz.obj -MD -MP -MF $(DEPDIR)/libxetex_a-hz.Tpo -c -o libxetex_a-hz.obj `if test -f 'xetexdir/hz.cpp'; then $(CYGPATH_W) 'xetexdir/hz.cpp'; else $(CYGPATH_W) '$(srcdir)/xetexdir/hz.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libxetex_a-hz.Tpo $(DEPDIR)/libxetex_a-hz.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='xetexdir/hz.cpp' object='libxetex_a-hz.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxetex_a_CPPFLAGS) $(CPPFLAGS) $(libxetex_a_CXXFLAGS) $(CXXFLAGS) -c -o libxetex_a-hz.obj `if test -f 'xetexdir/hz.cpp'; then $(CYGPATH_W) 'xetexdir/hz.cpp'; else $(CYGPATH_W) '$(srcdir)/xetexdir/hz.cpp'; fi`
+
libxetex_a-XeTeXFontInst_Mac.o: xetexdir/XeTeXFontInst_Mac.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxetex_a_CPPFLAGS) $(CPPFLAGS) $(libxetex_a_CXXFLAGS) $(CXXFLAGS) -MT libxetex_a-XeTeXFontInst_Mac.o -MD -MP -MF $(DEPDIR)/libxetex_a-XeTeXFontInst_Mac.Tpo -c -o libxetex_a-XeTeXFontInst_Mac.o `test -f 'xetexdir/XeTeXFontInst_Mac.cpp' || echo '$(srcdir)/'`xetexdir/XeTeXFontInst_Mac.cpp
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libxetex_a-XeTeXFontInst_Mac.Tpo $(DEPDIR)/libxetex_a-XeTeXFontInst_Mac.Po
diff --git a/Build/source/texk/web2c/synctexdir/synctex.c b/Build/source/texk/web2c/synctexdir/synctex.c
index 67dc8d510bb..f531a5146bc 100644
--- a/Build/source/texk/web2c/synctexdir/synctex.c
+++ b/Build/source/texk/web2c/synctexdir/synctex.c
@@ -274,9 +274,12 @@ Latest Revision: Wed Jul 1 08:15:44 UTC 2009
/* For non-GCC compilation. */
# if !defined(__GNUC__) || (__GNUC__ < 2)
-# define __attribute__(A)
+# if !defined(__GNUC__) || (__GNUC__ < 2)
+# define __attribute__(A)
+# endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
# endif
+
/* In the header file below, TEX-OR-MF-OR-MP is replaced by the real name (tex, etex...)
* Some macros will be redefined and additional headers will be imported */
# include "synctex-TEX-OR-MF-OR-MP.h"
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp
index ef7d6fe2b55..33ee8336534 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst.cpp
@@ -311,9 +311,10 @@ XeTeXFontInst::getGlyphName(LEGlyphID gid, int& nameLen)
{
le_uint32 len;
const char *p = (const char*)readFontTable(LE_POST_TABLE_TAG, len);
- if (p != NULL) {
+ if (p != NULL)
return getGlyphNamePtr(p, len, gid, &nameLen);
- }
+ else
+ return NULL;
}
LEUnicode32
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp
index 60a54060799..4737c497b59 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.cpp
@@ -112,3 +112,21 @@ void XeTeXFontInst_Mac::getGlyphBounds(LEGlyphID gid, GlyphBBox* bbox)
{
GetGlyphBBox_AAT(fStyle, gid, bbox);
}
+
+LEGlyphID
+XeTeXFontInst_Mac::mapGlyphToIndex(const char* glyphName) const
+{
+ LEGlyphID rval = XeTeXFontInst::mapGlyphToIndex(glyphName);
+ if (rval)
+ return rval;
+ return GetGlyphIDFromCGFont(fFontRef, glyphName);
+}
+
+const char*
+XeTeXFontInst_Mac::getGlyphName(LEGlyphID gid, int& nameLen)
+{
+ const char* rval = XeTeXFontInst::getGlyphName(gid, nameLen);
+ if (rval)
+ return rval;
+ return GetGlyphNameFromCGFont(fFontRef, gid, &nameLen);
+}
diff --git a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h
index 575beb49ba7..5d26d417e35 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h
+++ b/Build/source/texk/web2c/xetexdir/XeTeXFontInst_Mac.h
@@ -61,6 +61,9 @@ public:
virtual void initialize(LEErrorCode &status);
virtual void getGlyphBounds(LEGlyphID gid, GlyphBBox* bbox);
+
+ virtual LEGlyphID mapGlyphToIndex(const char* glyphName) const;
+ virtual const char* getGlyphName(LEGlyphID gid, int& nameLen);
};
#endif
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
index 976e81319a1..c4f82e8fd72 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.c
@@ -98,6 +98,7 @@ authorization from the copyright holders.
#include "unicode/ubrk.h"
#include "unicode/ucnv.h"
+#include <assert.h>
/*
#include "sfnt.h"
doesn't work in plain C files :(
@@ -3182,3 +3183,38 @@ makeutf16name()
namelength16 = t - nameoffile16;
}
+
+int getcpcode(int fontNum, unsigned int code, int side)
+{
+ return get_cp_code(fontNum, code, side);
+}
+
+void setcpcode(int fontNum, unsigned int code, int side, int value)
+{
+ set_cp_code(fontNum, code, side, value);
+}
+
+integer get_native_word_cp(void* pNode, int side)
+{
+ memoryword* node = (memoryword*)pNode;
+ FixedPoint* locations = (FixedPoint*)native_glyph_info_ptr(node);
+ UInt16* glyphIDs = (UInt16*)(locations + native_glyph_count(node));
+ UInt16 glyphCount = native_glyph_count(node);
+ integer f = native_font(node);
+ UInt16 actual_glyph;
+
+ if (glyphCount == 0)
+ return 0;
+
+ switch (side) {
+ case LEFT_SIDE:
+ actual_glyph = *glyphIDs;
+ break;
+ case RIGHT_SIDE:
+ actual_glyph = glyphIDs[glyphCount - 1];
+ break;
+ default:
+ assert(0); // we should not reach this point
+ }
+ return get_cp_code(f, actual_glyph, side);
+}
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h
index 9dcfde35d24..527e803fbe6 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_ext.h
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_ext.h
@@ -315,8 +315,10 @@ typedef void* ATSUStyle; /* dummy declaration just so the stubs can compile */
void GetGlyphSidebearings_AAT(ATSUStyle style, UInt16 gid, float* lsb, float* rsb);
int MapCharToGlyph_AAT(ATSUStyle style, UInt32 ch);
int MapGlyphToIndex_AAT(ATSUStyle style, const char* glyphName);
+ int GetGlyphIDFromCGFont(ATSFontRef atsFontRef, const char* glyphName);
float GetGlyphItalCorr_AAT(ATSUStyle style, UInt16 gid);
char* GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len);
+ char* GetGlyphNameFromCGFont(ATSFontRef atsFontRef, UInt16 gid, int* len);
int GetFontCharRange_AAT(ATSUStyle style, int reqFirst);
ATSUFontVariationAxis find_axis_by_name(ATSUFontID fontID, const char* name, int nameLength);
ATSUFontFeatureType find_feature_by_name(ATSUFontID fontID, const char* name, int nameLength);
@@ -340,5 +342,8 @@ extern "C" {
#endif
#endif
-#endif /* __XETEX_EXT_H */
+// copied from xetex-hz.ch
+#define LEFT_SIDE 0
+#define RIGHT_SIDE 1
+#endif /* __XETEX_EXT_H */
diff --git a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
index 2bedefe6bc7..30a891b83f1 100644
--- a/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
+++ b/Build/source/texk/web2c/xetexdir/XeTeX_mac.c
@@ -471,18 +471,46 @@ int MapGlyphToIndex_AAT(ATSUStyle style, const char* glyphName)
ByteCount length;
OSStatus status = ATSFontGetTable(fontRef, kPost, 0, 0, 0, &length);
if (status != noErr)
- return 0;
+ goto ats_failed;
void* table = xmalloc(length);
status = ATSFontGetTable(fontRef, kPost, 0, length, table, &length);
if (status != noErr) {
free(table);
- return 0;
+ goto ats_failed;
}
int rval = findGlyphInPostTable(table, length, glyphName);
free(table);
+ if (rval)
+ return rval;
+
+ats_failed:
+ return GetGlyphIDFromCGFont(fontRef, glyphName);
+}
+
+int GetGlyphIDFromCGFont(ATSFontRef atsFontRef, const char* glyphName)
+{
+ if (&CGFontGetGlyphWithGlyphName == NULL)
+ return 0;
+
+ int rval = 0;
+ CFStringRef psname;
+ OSStatus status = ATSFontGetPostScriptName(atsFontRef, 0, &psname);
+ if ((status == noErr) && psname) {
+ CGFontRef cgfont = CGFontCreateWithFontName(psname);
+ CFRelease(psname);
+ if (cgfont) {
+ CFStringRef glyphname = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault,
+ glyphName,
+ kCFStringEncodingUTF8,
+ kCFAllocatorNull);
+ rval = CGFontGetGlyphWithGlyphName(cgfont, glyphname);
+ CFRelease(glyphname);
+ CGFontRelease(cgfont);
+ }
+ }
return rval;
}
@@ -500,15 +528,16 @@ GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len)
ByteCount length;
OSStatus status = ATSFontGetTable(fontRef, kPost, 0, 0, 0, &length);
if (status != noErr)
- return 0;
+ goto ats_failed;
void* table = xmalloc(length);
status = ATSFontGetTable(fontRef, kPost, 0, length, table, &length);
if (status != noErr) {
free(table);
- return 0;
+ goto ats_failed;
}
+ buffer[0] = 0;
namePtr = getGlyphNamePtr(table, length, gid, len);
if (*len > 255)
*len = 255;
@@ -519,6 +548,39 @@ GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len)
free(table);
+ if (buffer[0])
+ return &buffer[0];
+
+ats_failed:
+ return GetGlyphNameFromCGFont(fontRef, gid, len);
+}
+
+char*
+GetGlyphNameFromCGFont(ATSFontRef atsFontRef, UInt16 gid, int* len)
+{
+ *len = 0;
+ static char buffer[256];
+ buffer[0] = 0;
+
+ if (&CGFontCopyGlyphNameForGlyph == NULL)
+ return &buffer[0];
+
+ CFStringRef psname;
+ OSStatus status = ATSFontGetPostScriptName(atsFontRef, 0, &psname);
+ if ((status == noErr) && psname) {
+ CGFontRef cgfont = CGFontCreateWithFontName(psname);
+ CFRelease(psname);
+ if (cgfont && gid < CGFontGetNumberOfGlyphs(cgfont)) {
+ CFStringRef glyphname = CGFontCopyGlyphNameForGlyph(cgfont, gid);
+ if (glyphname) {
+ if (CFStringGetCString(glyphname, buffer, 256, kCFStringEncodingUTF8)) {
+ *len = strlen(buffer);
+ }
+ CFRelease(glyphname);
+ }
+ CGFontRelease(cgfont);
+ }
+ }
return &buffer[0];
}
diff --git a/Build/source/texk/web2c/xetexdir/am/xetex.am b/Build/source/texk/web2c/xetexdir/am/xetex.am
index cb8cc209c79..bd2cd0255e6 100644
--- a/Build/source/texk/web2c/xetexdir/am/xetex.am
+++ b/Build/source/texk/web2c/xetexdir/am/xetex.am
@@ -118,6 +118,7 @@ xetex_web_srcs = \
$(xetex_ch_synctex) \
xetexdir/xetex.ch \
xetexdir/xetex-latex3.ch \
+ xetexdir/xetex-hz.ch \
$(xetex_post_ch_synctex)
##
EXTRA_DIST += $(xetex_web_srcs) xetexdir/xetex.defines xetexdir/xetexextra.in
@@ -163,6 +164,7 @@ libxetex_a_SOURCES = \
xetexdir/sfnt.h \
xetexdir/trans.c \
xetexdir/trans.h \
+ xetexdir/hz.cpp \
xetexdir/xetex.h
## included by xetexdir/XeTeXLayoutInterface.cpp
diff --git a/Build/source/texk/web2c/xetexdir/hz.cpp b/Build/source/texk/web2c/xetexdir/hz.cpp
new file mode 100644
index 00000000000..badbd5a6981
--- /dev/null
+++ b/Build/source/texk/web2c/xetexdir/hz.cpp
@@ -0,0 +1,51 @@
+#include "XeTeX_ext.h"
+
+#include <map>
+#include <iostream>
+#include <assert.h>
+using namespace std;
+
+typedef pair<int, unsigned int> GlyphId;
+typedef map<GlyphId, int> ProtrusionFactor;
+ProtrusionFactor leftProt, rightProt;
+
+extern "C" {
+
+void set_cp_code(int fontNum, unsigned int code, int side, int value)
+{
+ GlyphId id(fontNum, code);
+ switch (side) {
+ case LEFT_SIDE:
+ leftProt[id] = value;
+ break;
+ case RIGHT_SIDE:
+ rightProt[id] = value;
+ break;
+ default:
+ assert(0); // we should not reach here
+ }
+}
+
+int get_cp_code(int fontNum, unsigned int code, int side)
+{
+ GlyphId id(fontNum, code);
+ ProtrusionFactor* container;
+ switch (side) {
+ case LEFT_SIDE:
+ container = &leftProt;
+ break;
+ case RIGHT_SIDE:
+ container = &rightProt;
+ break;
+ default:
+ assert(0); // we should not reach here
+ }
+ ProtrusionFactor::iterator it = container->find(id);
+ if (it == container->end())
+ return 0;
+ return it->second;
+}
+
+}
+
+
diff --git a/Build/source/texk/web2c/xetexdir/xetex-hz.ch b/Build/source/texk/web2c/xetexdir/xetex-hz.ch
new file mode 100644
index 00000000000..1cc4c4a9093
--- /dev/null
+++ b/Build/source/texk/web2c/xetexdir/xetex-hz.ch
@@ -0,0 +1,982 @@
+@x
+new_kern:=p;
+end;
+
+@y
+new_kern:=p;
+end;
+
+@ Some stuff for character protrusion.
+@# {memory structure for marginal kerns}
+@d margin_kern_node = 40
+@d margin_kern_node_size = 3
+@d margin_char(#) == info(# + 2) {unused for now; relevant for font expansion}
+
+@# {|subtype| of marginal kerns}
+@d left_side == 0
+@d right_side == 1
+
+@# {base for lp/rp codes starts from 2:
+ 0 for |hyphen_char|,
+ 1 for |skew_char|}
+@d lp_code_base == 2
+@d rp_code_base == 3
+
+@d max_hlist_stack = 512 {maximum fill level for |hlist_stack|}
+{maybe good if larger than |2 * max_quarterword|, so that box nesting level would overflow first}
+
+@<Glob...@>=
+@!last_leftmost_char: pointer;
+@!last_rightmost_char: pointer;
+@!hlist_stack:array[0..max_hlist_stack] of pointer; {stack for |find_protchar_left()| and |find_protchar_right()|}
+@!hlist_stack_level:0..max_hlist_stack; {fill level for |hlist_stack|}
+@!first_p: pointer; {to access the first node of the paragraph}
+@!prev_p: pointer; {make |prev_p| global}
+
+@z
+
+@x
+@<Search |hyph_list| for pointers to |p|@>;
+end;
+gubed
+
+@y
+@<Search |hyph_list| for pointers to |p|@>;
+end;
+gubed
+
+@ Some stuff for character protrusion.
+
+@d pdf_debug_on == true {change to |false| to suppress debugging info}
+@p
+procedure pdf_error(t, p: str_number);
+begin
+ normalize_selector;
+ print_err("Error");
+ if t <> 0 then begin
+ print(" (");
+ print(t);
+ print(")");
+ end;
+ print(": "); print(p);
+ succumb;
+end;
+
+procedure pdf_DEBUG(s: str_number);
+begin
+ if not pdf_debug_on then
+ return;
+ print_ln; print("DEBUG: "); print(s);
+end;
+
+procedure pdf_DEBUG_int(s: str_number; i: integer);
+begin
+ if not pdf_debug_on then
+ return;
+ print_ln; print("DEBUG: "); print(s); print_int(i);
+end;
+
+procedure pdf_DEBUG_str(s, s2: str_number);
+begin
+ if not pdf_debug_on then
+ return;
+ print_ln; print("DEBUG: "); print(s); print(s2);
+end;
+
+function prev_rightmost(s, e: pointer): pointer;
+{finds the node preceding the rightmost node |e|; |s| is some node
+before |e|}
+var p: pointer;
+begin
+ prev_rightmost := null;
+ p := s;
+ if p = null then
+ return;
+ while link(p) <> e do begin
+ p := link(p);
+ if p = null then
+ return;
+ end;
+ prev_rightmost := p;
+end;
+
+function round_xn_over_d(@!x:scaled; @!n,@!d:integer):scaled;
+var positive:boolean; {was |x>=0|?}
+@!t,@!u,@!v:nonnegative_integer; {intermediate quantities}
+begin if x>=0 then positive:=true
+else begin negate(x); positive:=false;
+ end;
+t:=(x mod @'100000)*n;
+u:=(x div @'100000)*n+(t div @'100000);
+v:=(u mod d)*@'100000 + (t mod @'100000);
+if u div d>=@'100000 then arith_error:=true
+else u:=@'100000*(u div d) + (v div d);
+v := v mod d;
+if 2*v >= d then
+ incr(u);
+if positive then
+ round_xn_over_d := u
+else
+ round_xn_over_d := -u;
+end;
+
+
+@z
+
+@x
+ kern_node: @<Display kern |p|@>;
+@y
+ kern_node: @<Display kern |p|@>;
+ margin_kern_node: begin
+ print_esc("kern");
+ print_scaled(width(p));
+ if subtype(p) = left_side then
+ print(" (left margin)")
+ else
+ print(" (right margin)");
+ end;
+@z
+
+@x
+show_node_list(p); {the show starts at |p|}
+print_ln;
+end;
+
+@y
+show_node_list(p); {the show starts at |p|}
+print_ln;
+end;
+
+procedure short_display_n(@!p, m:integer); {prints highlights of list |p|}
+begin
+ breadth_max := m;
+ depth_threshold:=pool_size-pool_ptr-1;
+ show_node_list(p); {the show starts at |p|}
+end;
+
+
+@z
+
+@x
+ kern_node,math_node,penalty_node:begin
+ free_node(p, medium_node_size);
+ goto done;
+ end;
+@y
+ kern_node,math_node,penalty_node:begin
+ free_node(p, medium_node_size);
+ goto done;
+ end;
+ margin_kern_node: begin
+{ free_avail(margin_char(p)); }
+ free_node(p, margin_kern_node_size);
+ goto done;
+ end;
+@z
+
+@x
+ words:=medium_node_size;
+ end;
+@y
+ words:=medium_node_size;
+ end;
+margin_kern_node: begin
+ r := get_node(margin_kern_node_size);
+{ fast_get_avail(margin_char(r)); }
+{ font(margin_char(r)) := font(margin_char(p)); }
+{ character(margin_char(r)) := character(margin_char(p)); }
+ words := small_node_size;
+ end;
+@z
+
+@x
+@d XeTeX_linebreak_penalty_code=etex_int_base+11 {penalty to use at locale-dependent linebreak locations}
+@d eTeX_state_code=etex_int_base+12 {\eTeX\ state variables}
+@y
+@d XeTeX_linebreak_penalty_code=etex_int_base+11 {penalty to use at locale-dependent linebreak locations}
+@d XeTeX_protrude_chars_code=etex_int_base+12 {protrude chars at left/right edge of paragraphs}
+@d eTeX_state_code=etex_int_base+13 {\eTeX\ state variables}
+@z
+
+@x
+@d XeTeX_linebreak_penalty==int_par(XeTeX_linebreak_penalty_code)
+@y
+@d XeTeX_linebreak_penalty==int_par(XeTeX_linebreak_penalty_code)
+@d XeTeX_protrude_chars==int_par(XeTeX_protrude_chars_code)
+@z
+
+@x
+XeTeX_linebreak_penalty_code:print_esc("XeTeXlinebreakpenalty");
+@y
+XeTeX_linebreak_penalty_code:print_esc("XeTeXlinebreakpenalty");
+XeTeX_protrude_chars_code:print_esc("XeTeXprotrudechars");
+@z
+
+@x
+primitive("XeTeXlinebreakpenalty",assign_int,int_base+XeTeX_linebreak_penalty_code);@/
+@y
+primitive("XeTeXlinebreakpenalty",assign_int,int_base+XeTeX_linebreak_penalty_code);@/
+primitive("XeTeXprotrudechars",assign_int,int_base+XeTeX_protrude_chars_code);@/
+@!@:XeTeX_protrude_chars_}{\.{\\XeTeXprotrudechars} primitive@>
+@z
+
+@x
+if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
+else scanned_result(skew_char[cur_val])(int_val);
+@y
+if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
+else if m=1 then scanned_result(skew_char[cur_val])(int_val)
+else begin
+ n := cur_val;
+ if is_native_font(n) then scan_glyph_number(n)
+ else scan_char_num;
+ k := cur_val;
+ case m of
+ lp_code_base: scanned_result(get_cp_code(n, k, left_side))(int_val);
+ rp_code_base: scanned_result(get_cp_code(n, k, right_side))(int_val);
+ end;
+end;
+@z
+
+@x
+|scan_something_internal|.
+
+@ @<Declare procedures that scan restricted classes of integers@>=
+@y
+|scan_something_internal|.
+
+@ @<Declare procedures that scan restricted classes of integers@>=
+
+procedure scan_glyph_number(f: internal_font_number);
+{ scan a glyph ID for native font |f|, identified by Unicode value or name or glyph number }
+begin
+ if scan_keyword("/") then {set cp value by glyph name}
+ begin
+ scan_and_pack_name; {result is in |nameoffile|}
+ scanned_result(map_glyph_to_index(f))(int_val);
+ end else if scan_keyword("u") then {set cp value by unicode}
+ begin
+ scan_char_num;
+ scanned_result(map_char_to_glyph(f,cur_val))(int_val);
+ end else
+ scan_int;
+end;
+
+@z
+
+@x
+@d XeTeX_glyph_name_code=10
+
+@d etex_convert_codes=XeTeX_glyph_name_code+1 {end of \eTeX's command codes}
+@d job_name_code=etex_convert_codes {command code for \.{\\jobname}}
+
+@<Put each...@>=
+primitive("number",convert,number_code);@/
+@!@:number_}{\.{\\number} primitive@>
+primitive("romannumeral",convert,roman_numeral_code);@/
+@!@:roman_numeral_}{\.{\\romannumeral} primitive@>
+primitive("string",convert,string_code);@/
+@!@:string_}{\.{\\string} primitive@>
+primitive("meaning",convert,meaning_code);@/
+@!@:meaning_}{\.{\\meaning} primitive@>
+primitive("fontname",convert,font_name_code);@/
+@!@:font_name_}{\.{\\fontname} primitive@>
+primitive("jobname",convert,job_name_code);@/
+@!@:job_name_}{\.{\\jobname} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+convert: case chr_code of
+ number_code: print_esc("number");
+ roman_numeral_code: print_esc("romannumeral");
+ string_code: print_esc("string");
+ meaning_code: print_esc("meaning");
+ font_name_code: print_esc("fontname");
+ pdf_strcmp_code: print_esc("strcmp");
+@y
+@d XeTeX_glyph_name_code=10
+
+@d left_margin_kern_code=11
+@d right_margin_kern_code=12
+
+@d etex_convert_codes=right_margin_kern_code+1 {end of \eTeX's command codes}
+@d job_name_code=etex_convert_codes {command code for \.{\\jobname}}
+
+@<Put each...@>=
+primitive("number",convert,number_code);@/
+@!@:number_}{\.{\\number} primitive@>
+primitive("romannumeral",convert,roman_numeral_code);@/
+@!@:roman_numeral_}{\.{\\romannumeral} primitive@>
+primitive("string",convert,string_code);@/
+@!@:string_}{\.{\\string} primitive@>
+primitive("meaning",convert,meaning_code);@/
+@!@:meaning_}{\.{\\meaning} primitive@>
+primitive("fontname",convert,font_name_code);@/
+@!@:font_name_}{\.{\\fontname} primitive@>
+primitive("jobname",convert,job_name_code);@/
+@!@:job_name_}{\.{\\jobname} primitive@>
+primitive("leftmarginkern",convert,left_margin_kern_code);@/
+@!@:left_margin_kern_}{\.{\\leftmarginkern} primitive@>
+primitive("rightmarginkern",convert,right_margin_kern_code);@/
+@!@:right_margin_kern_}{\.{\\rightmarginkern} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+convert: case chr_code of
+ number_code: print_esc("number");
+ roman_numeral_code: print_esc("romannumeral");
+ string_code: print_esc("string");
+ meaning_code: print_esc("meaning");
+ font_name_code: print_esc("fontname");
+ pdf_strcmp_code: print_esc("strcmp");
+ left_margin_kern_code: print_esc("leftmarginkern");
+ right_margin_kern_code: print_esc("rightmarginkern");
+@z
+
+@x
+@!i:small_number;
+@!quote_char:UTF16_code;
+@y
+@!i:small_number;
+@!quote_char:UTF16_code;
+p, q: pointer;
+@z
+
+@x
+@!edge:scaled; {right edge of sub-box or leader space}
+@!prev_p:pointer; {one step behind |p|}
+@y
+@!edge:scaled; {right edge of sub-box or leader space}
+@z
+
+@x
+@d is_native_word_node(#) == ((not is_char_node(#)) and (type(#) = whatsit_node) and (subtype(#) = native_word_node))
+@y
+@d is_native_word_node(#) == ((not is_char_node(#)) and (type(#) = whatsit_node) and (subtype(#) = native_word_node))
+@d is_glyph_node(#) == ((not is_char_node(#)) and (type(#) = whatsit_node) and (subtype(#) = glyph_node))
+@z
+
+@x
+glue_node: @<Move right or output leaders@>;
+@y
+glue_node: @<Move right or output leaders@>;
+margin_kern_node: begin
+{ if subtype(p) = right_side then }
+{ pdf_DEBUG_int("right margin kern:", width(p)) }
+{ else }
+{ pdf_DEBUG_int("left margin kern:", width(p)); }
+ cur_h:=cur_h+width(p);
+end;
+@z
+
+@x
+@ @<Set init...@>=adjust_tail:=null; last_badness:=0;
+
+@y
+@ @<Set init...@>=adjust_tail:=null; last_badness:=0;
+
+@ Some stuff for character protrusion.
+
+@d left_pw(#) == char_pw(#, left_side)
+@d right_pw(#) == char_pw(#, right_side)
+
+@p
+function char_pw(p: pointer; side: small_number): scaled;
+var f: internal_font_number;
+ c: integer;
+begin
+ char_pw := 0;
+ if side = left_side then
+ last_leftmost_char := null
+ else
+ last_rightmost_char := null;
+ if p = null then
+ return;
+
+ { native word }
+ if is_native_word_node(p) then begin
+ if native_glyph_info_ptr(p) <> null_ptr then begin
+ f := native_font(p);
+ char_pw := round_xn_over_d(quad(f), get_native_word_cp(p, side), 1000);
+ end;
+ return;
+ end;
+
+ { glyph node }
+ if is_glyph_node(p) then begin
+ f := native_font(p);
+ char_pw := round_xn_over_d(quad(f), get_cp_code(f, native_glyph(p), side), 1000);
+ return;
+ end;
+
+ { char node or ligature; same like pdftex }
+ if not is_char_node(p) then begin
+ if type(p) = ligature_node then
+ p := lig_char(p)
+ else
+ return;
+ end;
+ f := font(p);
+ c := get_cp_code(f, character(p), side);
+ case side of
+ left_side:
+ last_leftmost_char := p;
+ right_side:
+ last_rightmost_char := p;
+ endcases;
+ if c = 0 then
+ return;
+ char_pw :=
+ round_xn_over_d(quad(f), c, 1000);
+end;
+
+function new_margin_kern(w: scaled; p: pointer; side: small_number): pointer;
+var k: pointer;
+begin
+ k := get_node(margin_kern_node_size);
+ type(k) := margin_kern_node;
+ subtype(k) := side;
+ width(k) := w;
+{ if p = null then }
+{ pdf_error("margin kerning", "invalid pointer to marginal char node"); }
+{ fast_get_avail(margin_char(k)); }
+{ character(margin_char(k)) := character(p); }
+{ font(margin_char(k)) := font(p); }
+ new_margin_kern := k;
+end;
+
+
+
+@z
+
+@x
+ kern_node: x:=x+width(p);
+@y
+ kern_node: x:=x+width(p);
+ margin_kern_node: x:=x+width(p);
+@z
+
+@x
+@d deactivate=60 {go here when node |r| should be deactivated}
+
+@<Declare subprocedures for |line_break|@>=
+@y
+@d deactivate=60 {go here when node |r| should be deactivated}
+
+@d cp_skipable(#) == {skipable nodes at the margins during character protrusion}
+(
+ not is_char_node(#) and
+ (
+ (type(#) = ins_node)
+ or (type(#) = mark_node)
+ or (type(#) = adjust_node)
+ or (type(#) = penalty_node)
+ or ((type(#) = disc_node) and
+ (pre_break(#) = null) and
+ (post_break(#) = null) and
+ (replace_count(#) = 0)) {an empty |disc_node|}
+ or ((type(#) = math_node) and (width(#) = 0))
+ or ((type(#) = kern_node) and
+ ((width(#) = 0) or (subtype(#) = normal)))
+ or ((type(#) = glue_node) and (glue_ptr(#) = zero_glue))
+ or ((type(#) = hlist_node) and (width(#) = 0) and (height(#) = 0) and
+ (depth(#) = 0) and (list_ptr(#) = null))
+ )
+)
+
+@<Declare subprocedures for |line_break|@>=
+procedure push_node(p: pointer);
+begin
+ if hlist_stack_level > max_hlist_stack then
+ pdf_error("push_node", "stack overflow");
+ hlist_stack[hlist_stack_level] := p;
+ hlist_stack_level := hlist_stack_level + 1;
+end;
+
+function pop_node: pointer;
+begin
+ hlist_stack_level := hlist_stack_level - 1;
+ if hlist_stack_level < 0 then {would point to some bug}
+ pdf_error("pop_node", "stack underflow (internal error)");
+ pop_node := hlist_stack[hlist_stack_level];
+end;
+
+function find_protchar_left(l: pointer; d: boolean): pointer;
+{searches left to right from list head |l|, returns 1st non-skipable item}
+var t: pointer;
+ run: boolean;
+begin
+ if (link(l) <> null) and (type(l) = hlist_node) and (width(l) = 0)
+ and (height(l) = 0) and (depth(l) = 0) and (list_ptr(l) = null) then
+ l := link(l) {for paragraph start with \.{\\parindent = 0pt}}
+ else if d then
+ while (link(l) <> null) and (not (is_char_node(l) or non_discardable(l))) do
+ l := link(l); {std.\ discardables at line break, \TeX book, p 95}
+ hlist_stack_level := 0;
+ run := true;
+ repeat
+ t := l;
+ while run and (type(l) = hlist_node) and (list_ptr(l) <> null) do begin
+ push_node(l);
+ l := list_ptr(l);
+ end;
+ while run and cp_skipable(l) do begin
+ while (link(l) = null) and (hlist_stack_level > 0) do begin
+ l := pop_node; {don't visit this node again}
+ end;
+ if link(l) <> null then
+ l := link(l)
+ else if hlist_stack_level = 0 then run := false
+ end;
+ until t = l;
+ find_protchar_left := l;
+end;
+
+function find_protchar_right(l, r: pointer): pointer;
+{searches right to left from list tail |r| to head |l|, returns 1st non-skipable item}
+var t: pointer;
+ run: boolean;
+begin
+ find_protchar_right := null;
+ if r = null then return;
+ hlist_stack_level := 0;
+ run := true;
+ repeat
+ t := r;
+ while run and (type(r) = hlist_node) and (list_ptr(r) <> null) do begin
+ push_node(l);
+ push_node(r);
+ l := list_ptr(r);
+ r := l;
+ while link(r) <> null do
+ r := link(r);
+ end;
+ while run and cp_skipable(r) do begin
+ while (r = l) and (hlist_stack_level > 0) do begin
+ r := pop_node; {don't visit this node again}
+ l := pop_node;
+ end;
+ if (r <> l) and (r <> null) then
+ r := prev_rightmost(l, r)
+ else if (r = l) and (hlist_stack_level = 0) then run := false
+ end;
+ until t = r;
+ find_protchar_right := r;
+end;
+
+function total_pw(q, p: pointer): scaled;
+{returns the total width of character protrusion of a line;
+|cur_break(break_node(q))| and |p| is the leftmost resp. rightmost node in the
+horizontal list representing the actual line}
+var l, r: pointer;
+ n: integer;
+begin
+ if break_node(q) = null then
+ l := first_p
+ else
+ l := cur_break(break_node(q));
+ r := prev_rightmost(prev_p, p); {get |link(r)=p|}
+ {let's look at the right margin first}
+ if (p <> null) and (type(p) = disc_node) and (pre_break(p) <> null) then
+ {a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break|}
+ begin
+ r := pre_break(p);
+ while link(r) <> null do
+ r := link(r);
+ end else r := find_protchar_right(l, r);
+ {now the left margin}
+ if (l <> null) and (type(l) = disc_node) then begin
+ if post_break(l) <> null then begin
+ l := post_break(l); {protrude the first char}
+ goto done;
+ end else {discard |replace_count(l)| nodes}
+ begin
+ n := replace_count(l);
+ l := link(l);
+ while n > 0 do begin
+ if link(l) <> null then
+ l := link(l);
+ decr(n);
+ end;
+ end;
+ end;
+ l := find_protchar_left(l, true);
+done:
+ total_pw := left_pw(l) + right_pw(r);
+end;
+
+@z
+
+@x
+shortfall:=line_width-cur_active_width[1]; {we're this much too short}
+@y
+shortfall:=line_width-cur_active_width[1]; {we're this much too short}
+if XeTeX_protrude_chars > 1 then
+ shortfall := shortfall + total_pw(r, cur_p);
+@z
+
+@x
+@!auto_breaking:boolean; {is node |cur_p| outside a formula?}
+@!prev_p:pointer; {helps to determine when glue nodes are breakpoints}
+@y
+@!auto_breaking:boolean; {is node |cur_p| outside a formula?}
+@z
+
+@x
+ prev_p:=cur_p; {glue at beginning is not a legal breakpoint}
+@y
+ prev_p:=cur_p; {glue at beginning is not a legal breakpoint}
+ first_p := cur_p; {to access the first node of paragraph as the first active
+ node has |break_node=null|}
+@z
+
+@x
+var q,@!r,@!s:pointer; {temporary registers for list manipulation}
+@y
+var q,@!r,@!s:pointer; {temporary registers for list manipulation}
+ p, k: pointer;
+ w: scaled;
+ glue_break: boolean; {was a break at glue?}
+ ptmp: pointer;
+@z
+
+@x
+q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false;
+if q<>null then {|q| cannot be a |char_node|}
+ if type(q)=glue_node then
+ begin delete_glue_ref(glue_ptr(q));
+ glue_ptr(q):=right_skip;
+ subtype(q):=right_skip_code+1; add_glue_ref(right_skip);
+ goto done;
+ end
+ else begin if type(q)=disc_node then
+ @<Change discretionary to compulsory and set
+ |disc_break:=true|@>
+ else if type(q)=kern_node then width(q):=0
+ else if type(q)=math_node then
+ begin width(q):=0;
+ if TeXXeT_en then @<Adjust \(t)the LR stack for the |p...@>;
+ end;
+ end
+else begin q:=temp_head;
+ while link(q)<>null do q:=link(q);
+ end;
+@<Put the \(r)\.{\\rightskip} glue after node |q|@>;
+done:
+@y
+q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false;
+glue_break := false;
+if q<>null then {|q| cannot be a |char_node|}
+ if type(q)=glue_node then
+ begin delete_glue_ref(glue_ptr(q));
+ glue_ptr(q):=right_skip;
+ subtype(q):=right_skip_code+1; add_glue_ref(right_skip);
+ glue_break := true;
+ goto done;
+ end
+ else begin if type(q)=disc_node then
+ @<Change discretionary to compulsory and set
+ |disc_break:=true|@>
+ else if type(q)=kern_node then width(q):=0
+ else if type(q)=math_node then
+ begin width(q):=0;
+ if TeXXeT_en then @<Adjust \(t)the LR stack for the |p...@>;
+ end;
+ end
+else begin q:=temp_head;
+ while link(q)<>null do q:=link(q);
+ end;
+done:
+{at this point |q| is the rightmost breakpoint; the only exception is the case
+of a discretionary break with non-empty |pre_break|, then |q| has been changed
+to the last node of the |pre_break| list}
+if XeTeX_protrude_chars > 0 then begin
+{ short_display_n(q, 5); }
+ if disc_break and (is_char_node(q) or (type(q) <> disc_node))
+ {|q| has been reset to the last node of |pre_break|}
+ then begin
+ p := q;
+ ptmp := p;
+ end else begin
+ p := prev_rightmost(link(temp_head), q); {get |link(p) = q|}
+ ptmp := p;
+ p := find_protchar_right(link(temp_head), p);
+ end;
+{ short_display_n(p, 5); }
+ w := right_pw(p);
+ if w <> 0 then {we have found a marginal kern, append it after |ptmp|}
+ begin
+{ pdf_DEBUG_int("right margin:", w); }
+ k := new_margin_kern(-w, last_rightmost_char, right_side);
+ link(k) := link(ptmp);
+ link(ptmp) := k;
+ if (ptmp = q) then
+ q := link(q);
+ end;
+end;
+{if |q| was not a breakpoint at glue and has been reset to |rightskip| then
+ we append |rightskip| after |q| now}
+if not glue_break then begin
+ @<Put the \(r)\.{\\rightskip} glue after node |q|@>;
+end;
+@z
+
+@x
+r:=link(q); link(q):=null; q:=link(temp_head); link(temp_head):=r;
+@y
+r:=link(q); link(q):=null; q:=link(temp_head); link(temp_head):=r;
+{at this point |q| is the leftmost node; all discardable nodes have been discarded}
+if XeTeX_protrude_chars > 0 then begin
+ p := q;
+ p := find_protchar_left(p, false); {no more discardables}
+ w := left_pw(p);
+ if w <> 0 then begin
+ k := new_margin_kern(-w, last_leftmost_char, left_side);
+ link(k) := q;
+ q := k;
+ end;
+end;
+@z
+
+@x
+ {adjust top after page break}
+var prev_p:pointer; {lags one step behind |p|}
+@y
+ {adjust top after page break}
+var
+@z
+
+@x
+label done,not_found,update_heights;
+var prev_p:pointer; {if |p| is a glue node, |type(prev_p)| determines
+ whether |p| is a legal breakpoint}
+@y
+label done,not_found,update_heights;
+var
+@z
+
+@x
+var p,@!q,@!r,@!s:pointer; {nodes being examined and/or changed}
+@!prev_p:pointer; {predecessor of |p|}
+@y
+var p,@!q,@!r,@!s:pointer; {nodes being examined and/or changed}
+@z
+
+@x
+var p:pointer; {the box}
+@!c:box_code..copy_code; {should we copy?}
+begin if cur_chr>copy_code then @<Handle saved items and |goto done|@>;
+c:=cur_chr; scan_register_num; fetch_box(p);
+if p=null then return;
+if (abs(mode)=mmode)or((abs(mode)=vmode)and(type(p)<>vlist_node))or@|
+ ((abs(mode)=hmode)and(type(p)<>hlist_node)) then
+ begin print_err("Incompatible list can't be unboxed");
+@.Incompatible list...@>
+ help3("Sorry, Pandora. (You sneaky devil.)")@/
+ ("I refuse to unbox an \hbox in vertical mode or vice versa.")@/
+ ("And I can't open any boxes in math mode.");@/
+ error; return;
+ end;
+if c=copy_code then link(tail):=copy_node_list(list_ptr(p))
+else begin link(tail):=list_ptr(p); change_box(null);
+ free_node(p,box_node_size);
+ end;
+done:
+while link(tail)<>null do tail:=link(tail);
+@y
+var p:pointer; {the box}
+ r: pointer; {to remove marginal kern nodes}
+@!c:box_code..copy_code; {should we copy?}
+begin if cur_chr>copy_code then @<Handle saved items and |goto done|@>;
+c:=cur_chr; scan_register_num; fetch_box(p);
+if p=null then return;
+if (abs(mode)=mmode)or((abs(mode)=vmode)and(type(p)<>vlist_node))or@|
+ ((abs(mode)=hmode)and(type(p)<>hlist_node)) then
+ begin print_err("Incompatible list can't be unboxed");
+@.Incompatible list...@>
+ help3("Sorry, Pandora. (You sneaky devil.)")@/
+ ("I refuse to unbox an \hbox in vertical mode or vice versa.")@/
+ ("And I can't open any boxes in math mode.");@/
+ error; return;
+ end;
+if c=copy_code then link(tail):=copy_node_list(list_ptr(p))
+else begin link(tail):=list_ptr(p); change_box(null);
+ free_node(p,box_node_size);
+ end;
+done:
+while link(tail) <> null do begin
+ r := link(tail);
+ if not is_char_node(r) and (type(r) = margin_kern_node) then begin
+ link(tail) := link(r);
+{ free_avail(margin_char(r)); }
+ free_node(r, margin_kern_node_size);
+ end;
+ tail:=link(tail);
+end;
+@z
+
+@x
+kern_node: d:=width(p);
+@y
+kern_node: d:=width(p);
+margin_kern_node: d:=width(p);
+@z
+
+@x
+assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val;
+ scan_optional_equals; scan_int;
+ if n=0 then hyphen_char[f]:=cur_val@+else skew_char[f]:=cur_val;
+ end;
+
+@ @<Put each...@>=
+primitive("hyphenchar",assign_font_int,0);
+@!@:hyphen_char_}{\.{\\hyphenchar} primitive@>
+primitive("skewchar",assign_font_int,1);
+@!@:skew_char_}{\.{\\skewchar} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+assign_font_int: if chr_code=0 then print_esc("hyphenchar")
+ else print_esc("skewchar");
+@y
+assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val;
+ if n < lp_code_base then begin
+ scan_optional_equals; scan_int;
+ if n=0 then hyphen_char[f]:=cur_val@+else skew_char[f]:=cur_val;
+ end else begin
+ if is_native_font(f) then
+ scan_glyph_number(f) {for native fonts, the value is a glyph id}
+ else scan_char_num; {for |tfm| fonts it's the same like pdftex}
+ p := cur_val;
+ scan_optional_equals; scan_int;
+ case n of
+ lp_code_base: set_cp_code(f, p, left_side, cur_val);
+ rp_code_base: set_cp_code(f, p, right_side, cur_val);
+ endcases;
+ end;
+end;
+
+@ @<Put each...@>=
+primitive("hyphenchar",assign_font_int,0);
+@!@:hyphen_char_}{\.{\\hyphenchar} primitive@>
+primitive("skewchar",assign_font_int,1);
+@!@:skew_char_}{\.{\\skewchar} primitive@>
+primitive("lpcode",assign_font_int,lp_code_base);
+@!@:lp_code_}{\.{\\lpcode} primitive@>
+primitive("rpcode",assign_font_int,rp_code_base);
+@!@:rp_code_}{\.{\\rpcode} primitive@>
+
+@ @<Cases of |print_cmd_chr|...@>=
+assign_font_int: case chr_code of
+0: print_esc("hyphenchar");
+1: print_esc("skewchar");
+lp_code_base: print_esc("lpcode");
+rp_code_base: print_esc("rpcode");
+endcases;
+@z
+
+@x
+ flush_string;
+end;
+
+procedure pdf_error(t, p: str_number);
+begin
+ normalize_selector;
+ print_err("Error");
+ if t <> 0 then begin
+ print(" (");
+ print(t);
+ print(")");
+ end;
+ print(": "); print(p);
+ succumb;
+end;
+
+@y
+ flush_string;
+end;
+
+@z
+
+@x
+ not_native_font_error(convert, c, fnt);
+ end;
+
+@ @<Cases of `Print the result of command |c|'@>=
+eTeX_revision_code: print(eTeX_revision);
+pdf_strcmp_code: print_int(cur_val);
+XeTeX_revision_code: print(XeTeX_revision);
+
+XeTeX_variation_name_code:
+ if is_atsu_font(fnt) then
+ atsu_print_font_name(c, font_layout_engine[fnt], arg1, arg2);
+
+XeTeX_feature_name_code,
+XeTeX_selector_name_code:
+ if is_atsu_font(fnt) then
+ atsu_print_font_name(c, font_layout_engine[fnt], arg1, arg2)
+ else if is_gr_font(fnt) then
+ gr_print_font_name(c, font_layout_engine[fnt], arg1, arg2);
+
+XeTeX_glyph_name_code:
+ if is_native_font(fnt) then print_glyph_name(fnt, arg1);
+
+@y
+ not_native_font_error(convert, c, fnt);
+ end;
+
+left_margin_kern_code, right_margin_kern_code: begin
+ scan_register_num;
+ fetch_box(p);
+ if (p = null) or (type(p) <> hlist_node) then
+ pdf_error("marginkern", "a non-empty hbox expected")
+end;
+
+@ @<Cases of `Print the result of command |c|'@>=
+eTeX_revision_code: print(eTeX_revision);
+pdf_strcmp_code: print_int(cur_val);
+XeTeX_revision_code: print(XeTeX_revision);
+
+XeTeX_variation_name_code:
+ if is_atsu_font(fnt) then
+ atsu_print_font_name(c, font_layout_engine[fnt], arg1, arg2);
+
+XeTeX_feature_name_code,
+XeTeX_selector_name_code:
+ if is_atsu_font(fnt) then
+ atsu_print_font_name(c, font_layout_engine[fnt], arg1, arg2)
+ else if is_gr_font(fnt) then
+ gr_print_font_name(c, font_layout_engine[fnt], arg1, arg2);
+
+XeTeX_glyph_name_code:
+ if is_native_font(fnt) then print_glyph_name(fnt, arg1);
+
+left_margin_kern_code: begin
+ p := list_ptr(p);
+ while (p <> null) and
+ (cp_skipable(p) or
+ ((not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = left_skip_code + 1)))
+ do
+ p := link(p);
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = margin_kern_node) and (subtype(p) = left_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+
+right_margin_kern_code: begin
+ q := list_ptr(p);
+ p := prev_rightmost(q, null);
+ while (p <> null) and
+ (cp_skipable(p) or
+ ((not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = right_skip_code + 1)))
+ do
+ p := prev_rightmost(q, p);
+ if (p <> null) and (not is_char_node(p)) and
+ (type(p) = margin_kern_node) and (subtype(p) = right_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+@z
+
diff --git a/Build/source/texk/web2c/xetexdir/xetex.ch b/Build/source/texk/web2c/xetexdir/xetex.ch
index 5d342049485..a4c7c3ba4bf 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.ch
+++ b/Build/source/texk/web2c/xetexdir/xetex.ch
@@ -1,7 +1,7 @@
/****************************************************************************\
Part of the XeTeX typesetting system
- Copyright (c) 2009, 2010 by Jonathan Kew
- Copyright (c) 1994-2008 by SIL International
+ copyright (c) 1994-2008 by SIL International
+ copyright (c) 2009 by Jonathan Kew
Written by Jonathan Kew
@@ -66,8 +66,8 @@ authorization from the copyright holders.
@d eTeX_version_string=='-2.2' {current \eTeX\ version}
@d XeTeX_version=0
-@d XeTeX_revision==".9995"
-@d XeTeX_version_string=='-0.9995.3' {current \XeTeX\ version}
+@d XeTeX_revision==".9997"
+@d XeTeX_version_string=='-0.9997.1' {current \XeTeX\ version}
@z
@x
diff --git a/Build/source/texk/web2c/xetexdir/xetex.defines b/Build/source/texk/web2c/xetexdir/xetex.defines
index dbc2bd5b71c..c898223597e 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.defines
+++ b/Build/source/texk/web2c/xetexdir/xetex.defines
@@ -176,3 +176,7 @@ authorization from the copyright holders.
@define function wdField();
@define function htField();
@define function applymapping();
+
+@define procedure setcpcode();
+@define function getcpcode();
+@define function getnativewordcp();
diff --git a/Build/source/texk/web2c/xetexdir/xetex.h b/Build/source/texk/web2c/xetexdir/xetex.h
index 65be0c705c1..ce149b221f0 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.h
+++ b/Build/source/texk/web2c/xetexdir/xetex.h
@@ -58,6 +58,9 @@ authorization from the copyright holders.
#define makexdvglypharraydata(p) makeXDVGlyphArrayData(&(mem[p]))
#define xdvbufferbyte(i) xdvbuffer[i]
+#define getnativewordcp(p,s) get_native_word_cp(&(mem[p]), s)
+
+
void* getotassemblyptr(int f, int g, int horiz); /* function in XeTeXOTMath.cpp */
#define pic_node_size 8