[XeTeX] XeTeX vertical text layout support (for Linux & win32 users)
Jjgod Jiang
gzjjgod at gmail.com
Sat Jun 17 17:12:57 CEST 2006
Hi all,
Recently I've been trying to add vertical text layout support to XeTeX (and
xdvipdfmx) Linux & win32 versions. Since it's a little bit complicated, I'll
describe what I've done step by step. (I'll try to fetch the trunk version of
xdvipdfmx and submit a patch if needed.)
1. Jonathan had already set up the ":vertical" notation and reserved
XDV_FLAG_VERTICAL in native font def flags stored in xdv file. So what
we should do it making use of it, which requires changes to XeTeX_ext.c,
XeTeXLayoutInterface.cpp, XeTeXLayoutInterface.h from XeTeX code and
dvi.c, fontmap.c, fontmap.h in xdvipdfmx code.
2. Let's start from XeTeX's code. First of all, we should handle the ":vertical"
notation, so loadOTfont() in XeTeX_ext.c has to be modified, what I've done
is:
1) add a local variable at the beginning of loadOTfont():
UInt32 extraFlags = 0x0000;
2) add "vertical" notation parsing after 'bad_option: ', most of the code is
copied from XeTeX_mac.c:
// not a name=value pair, or not recognized....
// check for plain "vertical" before complaining
if (strncmp(cp1, "vertical", 8) == 0) {
cp3 = cp2;
if (*cp3 == ';' || *cp3 == ':')
--cp3;
while (*cp3 == ' ' || *cp3 == '\t')
--cp3;
if (*cp3)
++cp3;
if (cp3 == cp1 + 8) {
extraFlags |= XDV_FLAG_VERTICAL;
goto next_option;
}
}
3) add an extra parameter to the call of createLayoutEngine
engine = createLayoutEngine(font, scriptTag, languageTag,
addFeatures, removeFeatures, rgbValue, extraFlags);
3. You see the last step requires changes to createLayoutEngine() in
XeTeXLayoutInterface.cpp (and XeTeXLayoutInterface.h, of coz):
XeTeXLayoutEngine createLayoutEngine(XeTeXFont font,
UInt32 scriptTag,
UInt32 languageTag,
UInt32* addFeatures,
UInt32* removeFeatures,
UInt32 rgbValue,
UInt32 extraFlags)
in this function, after result->rgbValue = rgbValue; I add a line:
result->extraFlags = extraFlags;
likewise, a getta funtion should be added in XeTeXLayoutInterface.cpp
(and it's prototype in XeTeXLayoutInterface.h):
UInt32 getExtraFlags(XeTeXLayoutEngine engine)
{
return engine->extraFlags;
}
4. Then we can make use of getExtraFlags() in XeTeX_ext.c, in makefontdef():
after rgba = getRgbValue(engine); I added:
extraFlags = getExtraFlags(engine);
if (extraFlags & XDV_FLAG_VERTICAL)
{
flags |= XDV_FLAG_VERTICAL;
}
Then all the modifications to XeTeX's code are done. Demaining sections are
about the modifications to xdvipdfmx.
5. First, we should add a new field to font_def structure, I called it
write_mode,
similar names like layout_dir might be better, I guess.
static struct font_def
{
long tex_id;
...
#ifdef XETEX
char write_mode;
in read_font_record():
#ifdef XETEX
def_fonts[num_def_fonts].write_mode = 0;
def_fonts[num_def_fonts].fam_name = NULL;
...
6. in read_native_font_record() of dvi.c, after
def_fonts[num_def_fonts].used = 0; I added:
if (flags & XDV_FLAG_VERTICAL)
def_fonts[num_def_fonts].write_mode = 1;
7. in do_fnt(), change the call to dvi_locate_native_font() to:
#ifdef XETEX
if (def_fonts[i].fam_name) {
font_id = dvi_locate_native_font(def_fonts[i].font_name,
def_fonts[i].fam_name,
def_fonts[i].sty_name,
def_fonts[i].point_size,
def_fonts[i].write_mode);
then change dvi_locate_native_font() to:
dvi_locate_native_font (const char *ps_name, const char *fam_name,
const char *sty_name, spt_t ptsize,
const char write_mode)
{
...
if (mrec == NULL) {
if (pdf_load_native_font(ps_name, fam_name,
sty_name, write_mode) == -1)
...
}
8. Then we should modify fontmap.h,
#ifdef XETEX
extern int pdf_load_native_font (const char *ps_name,
const char *fam_name, const char *sty_name, const char write_mode);
#endif
and fontmap.c:
pdf_load_native_font (const char *ps_name,
const char *fam_name, const char *sty_name,
const char write_mode)
{
...
if (!strcmp(name, ps_name)) {
error = pdf_insert_native_fontmap_record(ps_name, path,
index, face,
write_mode);
...
}
9. and finally
static int
pdf_insert_native_fontmap_record (const char *name, const char *path,
int index, FT_Face face, const char write_mode)
{
...
mrec->enc_name = mstrdup(write_mode ? "Identity-V"
: "Identity-H");
...
}
10. Done.
Comments are welcomed :)
J.
More information about the XeTeX
mailing list