summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Build/source/texk/dvipdfm-x/ChangeLog6
-rw-r--r--Build/source/texk/dvipdfm-x/dvi.c266
-rw-r--r--Build/source/texk/dvipdfm-x/dvicodes.h1
-rw-r--r--Build/source/texk/dvipdfm-x/vf.c8
4 files changed, 243 insertions, 38 deletions
diff --git a/Build/source/texk/dvipdfm-x/ChangeLog b/Build/source/texk/dvipdfm-x/ChangeLog
index dcb1458091d..cca422e00d7 100644
--- a/Build/source/texk/dvipdfm-x/ChangeLog
+++ b/Build/source/texk/dvipdfm-x/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-22 Khaled Hosny <khaledhosny@eglug.org>
+
+ * src/dvi.c, src/dvicodes.h: Support DVI-IVD inspired text reflection
+ for XeTeX.
+ * src/vf.c: Adapt
+
2014-07-22 Karl Berry <karl@tug.org>
* Makefile.am (check-libutil-source-list): new target for manual
diff --git a/Build/source/texk/dvipdfm-x/dvi.c b/Build/source/texk/dvipdfm-x/dvi.c
index 4b2aa6ff8ad..edd61d3ad8f 100644
--- a/Build/source/texk/dvipdfm-x/dvi.c
+++ b/Build/source/texk/dvipdfm-x/dvi.c
@@ -2,6 +2,8 @@
Copyright (C) 2002-2014 by Jin-Hwan Cho and Shunsaku Hirata,
the dvipdfmx project team.
+
+ Copyright (C) 2012-2014 by Khaled Hosny <khaledhosny@eglug.org>
Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
@@ -104,6 +106,25 @@ double get_origin (int x)
return x ? dev_origin_x : dev_origin_y;
}
+#ifdef XETEX
+#define LTYPESETTING 0 /* typesetting from left to right */
+#define RTYPESETTING 1 /* typesetting from right to left */
+#define SKIMMING 2 /* skimming through reflected segment measuring its width */
+#define REVERSE(MODE) (LTYPESETTING + RTYPESETTING - MODE)
+
+struct dvi_lr
+{
+ int state, font;
+ unsigned long buf_index;
+};
+
+static struct dvi_lr lr_state; /* state at start of current skimming */
+static int lr_mode; /* current direction or skimming depth */
+static SIGNED_QUAD lr_width; /* total width of reflected segment */
+static SIGNED_QUAD lr_width_stack[DVI_STACK_DEPTH_MAX];
+static unsigned lr_width_stack_depth = 0;
+#endif
+
#define PHYSICAL 1
#define VIRTUAL 2
#define SUBFONT 3
@@ -1074,8 +1095,19 @@ static void do_moveto (SIGNED_QUAD x, SIGNED_QUAD y)
dvi_state.v = y;
}
+/* FIXME: dvi_forward() might be a better name */
void dvi_right (SIGNED_QUAD x)
{
+#ifdef XETEX
+ if (lr_mode >= SKIMMING) {
+ lr_width += x;
+ return;
+ }
+
+ if (lr_mode == RTYPESETTING)
+ x = -x;
+#endif
+
switch (dvi_state.d) {
case 0:
dvi_state.h += x; break;
@@ -1088,16 +1120,23 @@ void dvi_right (SIGNED_QUAD x)
void dvi_down (SIGNED_QUAD y)
{
- switch (dvi_state.d) {
- case 0:
- dvi_state.v += y; break;
- case 1:
- dvi_state.h -= y; break;
- case 3:
- dvi_state.h += y; break;
+#ifdef XETEX
+ if (lr_mode < SKIMMING) {
+#endif
+ switch (dvi_state.d) {
+ case 0:
+ dvi_state.v += y; break;
+ case 1:
+ dvi_state.h -= y; break;
+ case 3:
+ dvi_state.h += y; break;
+ }
+#ifdef XETEX
}
+#endif
}
+#if 0
/* Please remove this.
* Optimization for 8-bit encodings.
*/
@@ -1158,6 +1197,7 @@ do_string (unsigned char *s, int len)
dvi_state.v -= width; break;
}
}
+#endif
/* _FIXME_
* CMap decoder wants multibyte strings as input but
@@ -1186,6 +1226,16 @@ dvi_set (SIGNED_QUAD ch)
width = tfm_get_fw_width(font->tfm_id, ch);
width = sqxfw(font->size, width);
+#ifdef XETEX
+ if (lr_mode >= SKIMMING) {
+ lr_width += width;
+ return;
+ }
+
+ if (lr_mode == RTYPESETTING)
+ dvi_right(width);
+#endif
+
switch (font->type) {
case PHYSICAL:
if (!is_xetex && ch > 65535) { /* _FIXME_ */
@@ -1234,14 +1284,20 @@ dvi_set (SIGNED_QUAD ch)
vf_set_char(ch, font->font_id); /* push/pop invoked */
break;
}
- switch (dvi_state.d) {
- case 0:
- dvi_state.h += width; break;
- case 1:
- dvi_state.v += width; break;
- case 3:
- dvi_state.v -= width; break;
+#ifdef XETEX
+ if (lr_mode == LTYPESETTING) {
+#endif
+ switch (dvi_state.d) {
+ case 0:
+ dvi_state.h += width; break;
+ case 1:
+ dvi_state.v += width; break;
+ case 3:
+ dvi_state.v -= width; break;
+ }
+#ifdef XETEX
}
+#endif
}
void
@@ -1321,18 +1377,20 @@ dvi_put (SIGNED_QUAD ch)
void
dvi_rule (SIGNED_QUAD width, SIGNED_QUAD height)
{
- do_moveto(dvi_state.h, dvi_state.v);
+ if (width > 0 && height > 0) {
+ do_moveto(dvi_state.h, dvi_state.v);
- switch (dvi_state.d) {
- case 0:
- pdf_dev_set_rule(dvi_state.h, -dvi_state.v, width, height);
- break;
- case 1:
- pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width);
- break;
- case 3:
- pdf_dev_set_rule(dvi_state.h - height, -dvi_state.v , height, width);
- break;
+ switch (dvi_state.d) {
+ case 0:
+ pdf_dev_set_rule(dvi_state.h, -dvi_state.v, width, height);
+ break;
+ case 1:
+ pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width);
+ break;
+ case 3:
+ pdf_dev_set_rule(dvi_state.h - height, -dvi_state.v , height, width);
+ break;
+ }
}
}
@@ -1370,10 +1428,24 @@ do_setrule (void)
height = get_buffered_signed_quad();
width = get_buffered_signed_quad();
- if (width > 0 && height > 0) {
+#ifdef XETEX
+ switch (lr_mode) {
+ case LTYPESETTING:
dvi_rule(width, height);
+ dvi_right(width);
+ break;
+ case RTYPESETTING:
+ dvi_right(width);
+ dvi_rule(width, height);
+ break;
+ default:
+ lr_width += width;
+ break;
}
+#else
+ dvi_rule(width, height);
dvi_right(width);
+#endif
}
static void
@@ -1383,9 +1455,22 @@ do_putrule (void)
height = get_buffered_signed_quad ();
width = get_buffered_signed_quad ();
- if (width > 0 && height > 0) {
+#ifdef XETEX
+ switch (lr_mode) {
+ case LTYPESETTING:
dvi_rule(width, height);
+ break;
+ case RTYPESETTING:
+ dvi_right(width);
+ dvi_rule(width, height);
+ dvi_right(-width);
+ break;
+ default:
+ break;
}
+#else
+ dvi_rule(width, height);
+#endif
}
static void
@@ -1759,7 +1844,10 @@ do_fnt4 (void)
static void
do_xxx (UNSIGNED_QUAD size)
{
- dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size);
+#ifdef XETEX
+ if (lr_mode < SKIMMING)
+#endif
+ dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size);
dvi_page_buf_index += size;
}
@@ -1848,6 +1936,71 @@ do_dir (void)
#ifdef XETEX
static void
+lr_width_push (void)
+{
+ if (lr_width_stack_depth >= DVI_STACK_DEPTH_MAX)
+ ERROR("Segment width stack exceeded limit.");
+
+ lr_width_stack[lr_width_stack_depth++] = lr_width;
+}
+
+static void
+lr_width_pop (void)
+{
+ if (lr_width_stack_depth <= 0)
+ ERROR("Tried to pop an empty segment width stack.");
+
+ lr_width = lr_width_stack[--lr_width_stack_depth];
+}
+
+static void
+dvi_begin_reflect (void)
+{
+ if (lr_mode >= SKIMMING) {
+ ++lr_mode;
+ } else {
+ lr_state.buf_index = dvi_page_buf_index;
+ lr_state.font = current_font;
+ lr_state.state = lr_mode;
+ lr_mode = SKIMMING;
+ lr_width = 0;
+ }
+}
+
+static void
+dvi_end_reflect (void)
+{
+ switch (lr_mode) {
+ case SKIMMING:
+ current_font = lr_state.font;
+ dvi_page_buf_index = lr_state.buf_index;
+ lr_mode = REVERSE(lr_state.state); /* must precede dvi_right */
+ dvi_right(-lr_width);
+ lr_width_push();
+ break;
+ case LTYPESETTING:
+ case RTYPESETTING:
+ lr_width_pop();
+ dvi_right(-lr_width);
+ lr_mode = REVERSE(lr_mode);
+ break;
+ default: /* lr_mode > SKIMMING */
+ lr_mode--;
+ }
+}
+
+static void
+do_reflect (void)
+{
+ UNSIGNED_BYTE value;
+ value = get_buffered_unsigned_byte();
+ if (value == 0)
+ dvi_begin_reflect();
+ else
+ dvi_end_reflect();
+}
+
+static void
do_native_font_def (int scanning)
{
if (scanning) {
@@ -1879,6 +2032,19 @@ do_native_font_def (int scanning)
}
static void
+skip_glyph_array_glyphs (int yLocsPresent)
+{
+ unsigned int i, slen = 0;
+ slen = (unsigned int) get_buffered_unsigned_pair();
+ for (i = 0; i < slen; i++) {
+ get_buffered_signed_quad();
+ if (yLocsPresent)
+ get_buffered_signed_quad();
+ get_buffered_unsigned_pair();
+ }
+}
+
+static void
do_glyph_array (int yLocsPresent)
{
struct loaded_font *font;
@@ -1893,6 +2059,15 @@ do_glyph_array (int yLocsPresent)
width = get_buffered_signed_quad();
+ if (lr_mode >= SKIMMING) {
+ lr_width += width;
+ skip_glyph_array_glyphs(yLocsPresent);
+ return;
+ }
+
+ if (lr_mode == RTYPESETTING)
+ dvi_right(width);
+
slen = (unsigned int) get_buffered_unsigned_pair();
xloc = NEW(slen, spt_t);
yloc = NEW(slen, spt_t);
@@ -1947,10 +2122,12 @@ do_glyph_array (int yLocsPresent)
RELEASE(xloc);
RELEASE(yloc);
- if (!dvi_state.d) {
- dvi_state.h += width;
- } else {
- dvi_state.v += width;
+ if (lr_mode == LTYPESETTING) {
+ if (!dvi_state.d) {
+ dvi_state.h += width;
+ } else {
+ dvi_state.v += width;
+ }
}
return;
@@ -2025,8 +2202,10 @@ dvi_do_page (long n,
double hmargin, double vmargin)
{
unsigned char opcode;
+#if 0
unsigned char sbuf[SBUF_SIZE];
unsigned int slen = 0;
+#endif
/* before this is called, we have scanned the page for papersize specials
and the complete DVI data is now in dvi_page_buffer */
@@ -2038,6 +2217,7 @@ dvi_do_page (long n,
dvi_stack_depth = 0;
for (;;) {
+#if 0
/* The most likely opcodes are individual setchars.
* These are buffered for speed. */
slen = 0;
@@ -2050,6 +2230,13 @@ dvi_do_page (long n,
}
if (slen == SBUF_SIZE)
continue;
+#endif
+ opcode = get_buffered_unsigned_byte();
+
+ if (opcode <= SET_CHAR_127) {
+ dvi_set(opcode);
+ continue;
+ }
/* If we are here, we have an opcode that is something
* other than SET_CHAR.
@@ -2096,6 +2283,10 @@ dvi_do_page (long n,
case PUSH:
dvi_push();
+#ifdef XETEX
+ if (lr_mode >= SKIMMING)
+ lr_width_push();
+#endif
/* The following line needs to go here instead of in
* dvi_push() since logical structure of document is
* oblivous to virtual fonts. For example the last line on a
@@ -2108,6 +2299,10 @@ dvi_do_page (long n,
break;
case POP:
dvi_pop();
+#ifdef XETEX
+ if (lr_mode >= SKIMMING)
+ lr_width_pop();
+#endif
/* Above explanation holds for following line too */
dvi_mark_depth();
break;
@@ -2171,6 +2366,9 @@ dvi_do_page (long n,
#ifdef XETEX
/* XeTeX extension */
+ case XDV_REFLECT:
+ do_reflect();
+ break;
case XDV_GLYPH_STRING:
do_glyph_array(0);
break;
@@ -2674,6 +2872,10 @@ dvi_scan_specials (long page_no,
case FNT_DEF4: do_fntdef4(1); break;
#ifdef XETEX
+ case XDV_REFLECT:
+ get_and_buffer_unsigned_byte(fp);
+ break;
+
case XDV_GLYPH_STRING:
{
UNSIGNED_PAIR count;
diff --git a/Build/source/texk/dvipdfm-x/dvicodes.h b/Build/source/texk/dvipdfm-x/dvicodes.h
index 0fa83e30120..885479bb83a 100644
--- a/Build/source/texk/dvipdfm-x/dvicodes.h
+++ b/Build/source/texk/dvipdfm-x/dvicodes.h
@@ -118,6 +118,7 @@
#define PTEXDIR 255 /* Ascii pTeX DIR command */
/* XeTeX ".xdv" codes */
+#define XDV_REFLECT 250 /* begin/end (possiply recursive) reflected segment */
#define XDV_PIC_FILE 251 /* include graphic or PDF file */
#define XDV_NATIVE_FONT_DEF 252 /* fontdef for native platform font */
#define XDV_GLYPH_ARRAY 253 /* string of glyph IDs with X and Y positions */
diff --git a/Build/source/texk/dvipdfm-x/vf.c b/Build/source/texk/dvipdfm-x/vf.c
index 4db994c9b41..4787777c782 100644
--- a/Build/source/texk/dvipdfm-x/vf.c
+++ b/Build/source/texk/dvipdfm-x/vf.c
@@ -465,9 +465,7 @@ static void vf_putrule(unsigned char **start, unsigned char *end, spt_t ptsize)
SIGNED_QUAD width, height;
height = signed_quad (start, end);
width = signed_quad (start, end);
- if (width > 0 && height > 0) {
- dvi_rule (sqxfw(ptsize,width), sqxfw(ptsize, height));
- }
+ dvi_rule (sqxfw(ptsize,width), sqxfw(ptsize, height));
return;
}
@@ -477,9 +475,7 @@ static void vf_setrule(unsigned char **start, unsigned char *end, spt_t ptsize)
height = signed_quad (start, end);
width = signed_quad (start, end);
s_width = sqxfw(ptsize, width);
- if (width > 0 && height > 0) {
- dvi_rule (s_width, sqxfw(ptsize, height));
- }
+ dvi_rule (s_width, sqxfw(ptsize, height));
dvi_right (s_width);
return;
}