1% directions.w
2%
3% Copyright 2009-2014 Taco Hoekwater <taco@@luatex.org>
4%
5% This file is part of LuaTeX.
6%
7% LuaTeX is free software; you can redistribute it and/or modify it under
8% the terms of the GNU General Public License as published by the Free
9% Software Foundation; either version 2 of the License, or (at your
10% option) any later version.
11%
12% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14% FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15% License for more details.
16%
17% You should have received a copy of the GNU General Public License along
18% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
19
20@ @c
21
22
23#include "ptexlib.h"
24
25@ @c
26void scan_direction(void)
27{
28    int save_cur_cmd = cur_cmd;
29    int save_cur_chr = cur_chr;
30    get_x_token();
31    if (cur_cmd == assign_dir_cmd) {
32        cur_val = eqtb[cur_chr].cint;
33        goto EXIT;
34    } else {
35        back_input();
36    }
37    if (scan_keyword("TLT")) {
38        cur_val = dir_TLT;
39    } else if (scan_keyword("TRT")) {
40        cur_val = dir_TRT;
41    } else if (scan_keyword("LTL")) {
42        cur_val = dir_LTL;
43    } else if (scan_keyword("RTT")) {
44        cur_val = dir_RTT;
45    } else {
46        tex_error("Bad direction", NULL);
47        cur_val = 0;
48    }
49    get_x_token();
50    if (cur_cmd != spacer_cmd)
51        back_input();
52  EXIT:
53    cur_cmd = save_cur_cmd;
54    cur_chr = save_cur_chr;
55}
56
57@ the next two are used by postlinebreak.c
58
59@c
60halfword do_push_dir_node(halfword p, halfword a)
61{
62    halfword n;
63    n = copy_node(a);
64    vlink(n) = p;
65    return n;
66}
67
68halfword do_pop_dir_node(halfword p)
69{
70    halfword n = vlink(p);
71    flush_node(p);
72    return n;
73}
74
75@ @c
76halfword dir_ptr;
77
78halfword text_dir_ptr;
79
80@ There is no need to do anything here at the moment.
81@c
82void initialize_directions(void)
83{
84}
85
86@ @c
87halfword new_dir(int s)
88{
89    halfword p;                 /* the new node */
90    p = new_node(whatsit_node, dir_node);
91    dir_dir(p) = s;
92    dir_dvi_ptr(p) = -1;
93    dir_level(p) = cur_level;
94    return p;
95}
96
97@ The global static array variable  |dir_strings| is also used
98by the lua nodelib interface, so it cannot be static. Putting
99it here instead of there avoid the nodelib having to know
100about the actual values of |dir_TRT| etc.
101
102@c
103const char *dir_strings[128] = {
104  "-TLT","???", "???", "???", "-TRT","???", "???", "???",
105  "???", "-LTL","???", "???", "???", "???", "???", "???",
106  "???", "???", "???", "???", "???", "???", "???", "???",
107  "-RTT","???", "???", "???", "???", "???", "???", "???",
108  "???", "???", "???", "???", "???", "???", "???", "???",
109  "???", "???", "???", "???", "???", "???", "???", "???",
110  "???", "???", "???", "???", "???", "???", "???", "???",
111  "???", "???", "???", "???", "???", "???", "???", "???",
112  "+TLT","???", "???", "???", "+TRT","???", "???", "???",
113  "???", "+LTL","???", "???", "???", "???", "???", "???",
114  "???", "???", "???", "???", "???", "???", "???", "???",
115  "+RTT","???", "???", "???", "???", "???", "???", "???",
116  "???", "???", "???", "???", "???", "???", "???", "???",
117  "???", "???", "???", "???", "???", "???", "???", "???",
118  "???", "???", "???", "???", "???", "???", "???", "???",
119  "???", "???", "???", "???", "???", "???", "???", "???" };
120
121const char *string_dir(int d)
122{
123    return (dir_strings[d+64]+1);
124}
125
126
127@ @c
128void print_dir(int d)
129{
130    /* hh-ls: todo: just fetch the string pt from the registry ... then the above can go */
131
132    tprint(string_dir(d));
133}
134
135@ @c
136scaled pack_width(int curdir, int pdir, halfword p, boolean isglyph)
137{
138    scaled wd = 0;
139    if (isglyph) {
140        if (textdir_parallel(curdir, pdir) == textglyphdir_orthogonal(pdir)) {
141            wd = glyph_width(p);
142            if (ex_glyph(p) != 0) {
143	      //wd = round_xn_over_d(wd, 1000 + ex_glyph(p)/1000, 1000);
144	      wd = ext_xn_over_d(wd, 1000000+ex_glyph(p), 1000000);
145
146	    }
147        } else {
148            wd = glyph_depth(p) + glyph_height(p);
149        }
150    } else {                    /* hlist, vlist, image, form, rule */
151        if (textdir_parallel(pdir, curdir))
152            wd = width(p);
153        else
154            wd = depth(p) + height(p);
155    }
156    return wd;
157}
158
159@ @c
160scaled_whd pack_width_height_depth(int curdir, int pdir, halfword p,
161                                   boolean isglyph)
162{
163    scaled_whd whd = { 0, 0, 0 };
164    whd.wd = pack_width(curdir, pdir, p, isglyph);
165    if (isglyph) {
166        if (is_rotated(curdir)) {
167            if (textdir_parallel(curdir, pdir))
168                whd.ht = whd.dp = (glyph_height(p) + glyph_depth(p)) / 2;
169            else
170                whd.ht = whd.dp = glyph_width(p) / 2;
171        } else {
172            if (is_rotated(pdir)) {
173                if (textdir_parallel(curdir, pdir))
174                    whd.ht = whd.dp = (glyph_height(p) + glyph_depth(p)) / 2;
175                else
176                    whd.ht = glyph_width(p);
177            } else {
178                if (glyphdir_eq(curdir, pdir)) {
179                    whd.ht = glyph_height(p);
180                    whd.dp = glyph_depth(p);
181                } else if (glyphdir_opposite(curdir, pdir)) {
182                    whd.ht = glyph_depth(p);
183                    whd.dp = glyph_height(p);
184                } else
185                    whd.ht = glyph_width(p);
186            }
187        }
188    } else {
189        if (is_rotated(curdir)) {
190            if (textdir_parallel(curdir, pdir))
191                whd.ht = whd.dp = (height(p) + depth(p)) / 2;
192            else
193                whd.ht = whd.dp = width(p) / 2;
194        } else {
195            if (pardir_eq(curdir, pdir)) {
196                whd.ht = height(p);
197                whd.dp = depth(p);
198            } else if (pardir_opposite(curdir, pdir)) {
199                whd.ht = depth(p);
200                whd.dp = height(p);
201            } else
202                whd.ht = width(p);
203        }
204    }
205    return whd;
206}
207
208@ @c
209void update_text_dir_ptr(int val)
210{
211    if (dir_level(text_dir_ptr) == cur_level) {
212        /* update */
213        dir_dir(text_dir_ptr) = val;
214    } else {
215        /* addition */
216        halfword text_dir_tmp = new_dir(val);
217        vlink(text_dir_tmp) = text_dir_ptr;
218        text_dir_ptr = text_dir_tmp;
219    }
220}
221