summaryrefslogtreecommitdiff
path: root/source/luametatex/source/tex/texpackaging.h
blob: dea884d0fb5d63bbef7965424ac673b3c4a59da2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
    See license.txt in the root of this project.
*/

# ifndef LMT_PACKAGING_H
# define LMT_PACKAGING_H

# include "luametatex.h"

/* We define some constants used when calling |hpack| to deal with font expansion. */

typedef enum hpack_subtypes {
    packing_exactly,    /*tex a box dimension is pre-specified */
    packing_additional, /*tex a box dimension is increased from the natural one */
    packing_expanded,   /*tex calculate amount for font expansion after breaking paragraph into lines */
    packing_substitute, /*tex substitute fonts */
    packing_adapted, 
    packing_linebreak,  /*tex signals that we need to take the frozen adjust properties */
} hpack_subtypes;

typedef enum box_codes {
    box_code,      /*tex |chr_code| for |\box| */
    copy_code,     /*tex |chr_code| for |\copy| */
    unpack_code,
    last_box_code, /*tex |chr_code| for |\lastbox| */
    tsplit_code,   
    vsplit_code,   /*tex |chr_code| for |\vsplit| */
    dsplit_code,   
 /* hsplit_code, */ 
    tpack_code,    
    vpack_code,    /*tex |chr_code| for |\vpack| */
    dpack_code,
    hpack_code,
    vtop_code,     
    vbox_code,     /*tex |chr_code| for |\vbox| */
    dbox_code,
    hbox_code,
    insert_box_code,
    insert_copy_code,
    local_left_box_box_code,
    local_right_box_box_code,
    local_middle_box_box_code
} box_codes;

// typedef enum saved_spec_items {
//     saved_spec_item_packaging = 0,
//     saved_spec_item_attribute = 1,
//     saved_spec_n_of_items     = 2,
// } saved_spec_items;

typedef enum saved_full_spec_items {
    saved_full_spec_item_context     =  0,
    saved_full_spec_item_packaging   =  1,
    saved_full_spec_item_direction   =  2,
    saved_full_spec_item_attr_list   =  3,
    saved_full_spec_item_only_pack   =  4,
    saved_full_spec_item_orientation =  5,
    saved_full_spec_item_anchor      =  6,
    saved_full_spec_item_geometry    =  7,
    saved_full_spec_item_xoffset     =  8,
    saved_full_spec_item_yoffset     =  9,
    saved_full_spec_item_xmove       = 10,
    saved_full_spec_item_ymove       = 11,
    saved_full_spec_item_reverse     = 12,
    saved_full_spec_item_container   = 13,
    saved_full_spec_item_shift       = 14, /* cleaner than passing it as context */
    saved_full_spec_item_source      = 15,
    saved_full_spec_item_target      = 16,
    saved_full_spec_item_axis        = 17,
    saved_full_spec_item_class       = 18,
    saved_full_spec_item_state       = 19,
    saved_full_spec_item_retain      = 20,
    saved_full_spec_n_of_items       = 21,
} saved_full_spec_items;

// typedef enum saved_align_spec_items {
//     saved_align_spec_item_attr_list   = 0,
//     saved_align_spec_item_orientation = 1,
//     saved_align_spec_item_anchor      = 2,
//     saved_align_spec_item_geometry    = 3,
//     saved_align_spec_item_xoffset     = 4,
//     saved_align_spec_item_yoffset     = 5,
//     saved_align_spec_item_shift       = 6,
//     saved_align_spec_item_source      = 7,
//     saved_align_spec_item_target      = 8,
//     saved_align_spec_n_of_items       = 9,
// } saved_align_spec_items;

typedef enum holding_migration_options {
    holding_none_option    = 0x00,
    holding_marks_option   = 0x01,
    holding_inserts_option = 0x02,
    holding_adjusts_option = 0x04,
} holding_migration_options  ;  

# define retain_marks(r)   (((r | holding_migrations_par) & holding_marks_option  ) == holding_marks_option  )
# define retain_inserts(r) (((r | holding_migrations_par) & holding_inserts_option) == holding_inserts_option)
# define retain_adjusts(r) (((r | holding_migrations_par) & holding_adjusts_option) == holding_adjusts_option)

typedef struct packaging_state_info {
    scaled   total_stretch[6];       /*tex with one for padding, the results are also used in alignments */
    scaled   total_shrink[6];        /*tex glue found by |hpack| or |vpack|, the results are also used in alignments */
    int      last_badness;           /*tex badness of the most recently packaged box */
    scaled   last_overshoot;
    halfword post_adjust_tail;       /*tex tail of adjustment list */
    halfword pre_adjust_tail;
    halfword post_migrate_tail;       /*tex tail of adjustment list */
    halfword pre_migrate_tail;
    halfword last_leftmost_char;
    halfword last_rightmost_char;
    int      pack_begin_line;
    scaled   best_height_plus_depth; /*tex The height of the best box, without stretching or shrinking: */
    halfword previous_char_ptr;
    scaled   font_expansion_ratio;
    halfword page_discards_tail;
    halfword page_discards_head;
    halfword split_discards_head;
    halfword padding;
} packaging_state_info;

extern packaging_state_info lmt_packaging_state;

extern scaled    tex_char_stretch         (halfword p);
extern scaled    tex_char_shrink          (halfword p);
/*     void      tex_get_char_expansion   (halfword p, halfword *stretch, halfword *shrink); */ /* no gain */
extern scaled    tex_kern_stretch         (halfword p);
extern scaled    tex_kern_shrink          (halfword p);
extern scaled    tex_char_protrusion      (halfword p, int side);
/*     void      tex_kern_protrusion      (halfword p, int side, halfword *stretch, halfword *shrink); */

extern scaled    tex_left_marginkern      (halfword p);
extern scaled    tex_right_marginkern     (halfword p);

extern halfword  tex_filtered_hpack       (halfword p, halfword qt, scaled w, int m, int grp, halfword d, int just_pack, halfword attr, int state, int retain);
extern halfword  tex_filtered_vpack       (halfword p, scaled h, int m, scaled maxdepth, int grp, halfword direction, int just_pack, halfword attr, int state, int retain);

extern scaledwhd tex_natural_hsizes       (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
extern scaledwhd tex_natural_vsizes       (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
extern halfword  tex_natural_width        (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
extern halfword  tex_natural_hsize        (halfword p, halfword *correction);
extern halfword  tex_natural_vsize        (halfword p);

extern halfword  tex_hpack                (halfword p, scaled w, int m, singleword d, int retain);
extern halfword  tex_vpack                (halfword p, scaled h, int m, scaled l, singleword d, int retain);

extern void      tex_repack               (halfword p, scaled w, int m);
extern void      tex_freeze               (halfword p, int recurse);

extern void      tex_package              (singleword nature);
extern void      tex_run_unpackage        (void);

extern void      tex_append_to_vlist      (halfword b, int location, const line_break_properties *properties);

extern halfword  tex_prune_page_top       (halfword p, int s);
extern halfword  tex_vert_break           (halfword p, scaled h, scaled d);
extern halfword  tex_vsplit               (halfword n, scaled h, int m);

extern void      tex_finish_vcenter_group (void);
extern void      tex_run_vcenter          (void);

//# define vpack(A,B,C,D) tex_vpackage(A,B,C,max_dimen,D)

# define first_un_box_code box_code
# define last_un_box_code  unpack_code
# define first_nu_box_code box_code
# define last_nu_box_code  local_middle_box_box_code /*tex needs checking */

/*tex

    Now let's turn to the question of how |\hbox| is treated. We actually need to consider also a
    slightly larger context, since constructions like

    \starttyping
    \setbox3={\\hbox...
    \leaders\hbox...
    \lower3.8pt\hbox...
    \stoptyping

    are supposed to invoke quite different actions after the box has been packaged. Conversely,
    constructions like |\setbox 3 =| can be followed by a variety of different kinds of boxes, and
    we would like to encode such things in an efficient way.

    In other words, there are two problems: To represent the context of a box, and to represent its
    type. The first problem is solved by putting a \quote {context code} on the |save_stack|, just
    below the two entries that give the dimensions produced by |scan_spec|. The context code is
    either a (signed) shift amount, or it is a large integer |>= box_flag|, where |box_flag = |
    $2^{30}$. Codes |box_flag| through |box_flag + biggest_reg| represent |\setbox0| through
    |\setbox biggest_reg|; codes |box_flag + biggest_reg + 1| through |box_flag + 2 * biggest_reg|
    represent |\global \setbox 0| through |\global\setbox| |biggest_reg|; code |box_flag + 2 *
    number_regs| represents |\shipout|; and codes |box_flag + 2 * number_regs + 1| through |box_flag
    + 2 * number_regs + 3| represent |\leaders|, |\cleaders|, and |\xleaders|.

    The second problem is solved by giving the command code |make_box| to all control sequences that
    produce a box, and by using the following |chr_code| values to distinguish between them:
    |box_code|, |copy_code|, |last_box_code|, |vsplit_code|, |vtop_code|, |vtop_code + vmode|, and
    |vtop_code + hmode|, where the latter two are used denote |\vbox| and |\hbox|, respectively.

    Originally the shift was encoded in the box context in case of a move. In fact even the local 
    and global register assignments were in that property but this is no longer the case. This
    actually makes implementing a |\boxspecdef| cleaner (a discarded experiment). The intermediate 
    cleasned up flags can be found in the history. 

*/

# define biggest_reg 65535  /*tex This could be in |textypes.h|. */

typedef enum box_flags {
    direct_box_flag     = 0x00,
 /* moved_box_flag      = 0x01, */
 /* vcenter_box_flag    = 0x02, */ 
    box_flag            = 0x02, /*tex context code for |\setbox0| */
    global_box_flag     = 0x03, /*tex context code for |\global\setbox0| */
    left_box_flag       = 0x04, /*tex context code for |\localleftbox| */
    right_box_flag      = 0x05, /*tex context code for |\localrightbox| */
    middle_box_flag     = 0x06, /*tex context code for |\localrightbox| */
    shipout_flag        = 0x07, /*tex context code for |\shipout| */
    lua_scan_flag       = 0x08, /*tex context code for |scan_list| */
    a_leaders_flag      = 0x09, /*tex context code for |\leaders| */
    c_leaders_flag      = 0x0A, /*tex context code for |\cleaders| */
    x_leaders_flag      = 0x0B, /*tex context code for |\xleaders| */
    g_leaders_flag      = 0x0C, /*tex context code for |\gleaders| */
    u_leaders_flag      = 0x0D, /*tex context code for |\uleaders| */

} box_flags;

# define box_leaders_flag(f) (f >= a_leaders_flag && f <= u_leaders_flag)

extern void tex_begin_box        (int boxcontext, scaled shift, halfword slot);
extern int  tex_ignore_math_skip (halfword p);

inline static scaled tex_aux_checked_dimen1(halfword v)
{
    if (v > max_dimen) {
        return max_dimen;
    } else if (v < -max_dimen) {
        return -max_dimen;
    } else {
        return v;
    }
}

inline static scaled tex_aux_checked_dimen2(halfword v)
{
    if (v > max_dimen) {
        return max_dimen;
    } else if (v < 0) {
        return 0;
    } else {
        return v;
    }
}

# endif