[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