texpackaging.h /size: 12 Kb    last modification: 2025-02-21 11:03
1/*
2    See license.txt in the root of this project.
3*/
4
5# ifndef LMT_PACKAGING_H
6# define LMT_PACKAGING_H
7
8# include "luametatex.h"
9
10/* We define some constants used when calling |hpack| to deal with font expansion. */
11
12typedef enum hpack_packing_modes {
13    packing_exactly,    /*tex a box dimension is pre-specified */
14    packing_additional, /*tex a box dimension is increased from the natural one */
15    packing_expanded,   /*tex calculate amount for font expansion after breaking paragraph into lines */
16    packing_substitute, /*tex substitute fonts */
17    packing_adapted, 
18    packing_linebreak,  /*tex signals that we need to take the frozen adjust properties */
19 // packing_trial, 
20} hpack_packing_modes;
21
22typedef enum box_codes {
23    box_code,      /*tex |chr_code| for |\box| */
24    copy_code,     /*tex |chr_code| for |\copy| */
25    unpack_code,
26    last_box_code, /*tex |chr_code| for |\lastbox| */
27    tsplit_code,   
28    vsplit_code,   /*tex |chr_code| for |\vsplit| */
29    dsplit_code,  
30 /* hsplit_code, */ 
31    tpack_code,    
32    vpack_code,    /*tex |chr_code| for |\vpack| */
33    dpack_code,
34    hpack_code,
35    vtop_code,     
36    vbox_code,     /*tex |chr_code| for |\vbox| */
37    dbox_code,
38    hbox_code,
39    vbalance_code,
40    vbalanced_box_code,
41    vbalanced_top_code,
42    vbalanced_insert_code,
43    vbalanced_discard_code,
44    vbalanced_deinsert_code,
45    vbalanced_reinsert_code,
46    flush_mvl_box_code,
47    insert_box_code,
48    insert_copy_code,
49    local_left_box_box_code,
50    local_right_box_box_code,
51    local_middle_box_box_code,
52    page_discards_code,
53    split_discards_code,
54    copy_split_discards_code,
55} box_codes;
56
57// typedef enum saved_full_spec_items {
58//     saved_full_spec_item_context     =  0,
59//     saved_full_spec_item_packaging   =  1,
60//     saved_full_spec_item_direction   =  2,
61//     saved_full_spec_item_attr_list   =  3,
62//     saved_full_spec_item_only_pack   =  4,
63//     saved_full_spec_item_orientation =  5,
64//     saved_full_spec_item_anchor      =  6,
65//     saved_full_spec_item_geometry    =  7,
66//     saved_full_spec_item_xoffset     =  8,
67//     saved_full_spec_item_yoffset     =  9,
68//     saved_full_spec_item_xmove       = 10,
69//     saved_full_spec_item_ymove       = 11,
70//     saved_full_spec_item_reverse     = 12,
71//     saved_full_spec_item_container   = 13,
72//     saved_full_spec_item_shift       = 14, /* cleaner than passing it as context */
73//     saved_full_spec_item_source      = 15,
74//     saved_full_spec_item_target      = 16,
75//     saved_full_spec_item_axis        = 17,
76//     saved_full_spec_item_class       = 18,
77//     saved_full_spec_item_state       = 19,
78//     saved_full_spec_item_retain      = 20,
79//     saved_full_spec_item_callback    = 21,
80//     saved_full_spec_n_of_items       = 22,
81// } saved_full_spec_items;
82
83typedef enum holding_migration_options {
84    holding_none_option    = 0x00,
85    holding_marks_option   = 0x01,
86    holding_inserts_option = 0x02,
87    holding_adjusts_option = 0x04,
88} holding_migration_options  ;  
89
90# define retain_marks(r)   (((r | holding_migrations_par) & holding_marks_option  ) == holding_marks_option  )
91# define retain_inserts(r) (((r | holding_migrations_par) & holding_inserts_option) == holding_inserts_option)
92# define retain_adjusts(r) (((r | holding_migrations_par) & holding_adjusts_option) == holding_adjusts_option)
93
94typedef struct packaging_state_info {
95    scaled   total_stretch[6];       /*tex with one for padding, the results are also used in alignments */
96    scaled   total_shrink[6];        /*tex glue found by |hpack| or |vpack|, the results are also used in alignments */
97    int      last_badness;           /*tex badness of the most recently packaged box */
98    scaled   last_overshoot;
99    halfword post_adjust_tail;       /*tex tail of adjustment list */
100    halfword pre_adjust_tail;
101    halfword post_migrate_tail;      /*tex tail of adjustment list */
102    halfword pre_migrate_tail;
103    halfword last_leftmost_char;
104    halfword last_rightmost_char;
105    int      pack_begin_line;
106    scaled   best_height_plus_depth; /*tex The height of the best box, without stretching or shrinking: */
107    halfword previous_char_ptr;
108    scaled   font_expansion_ratio;
109    halfword page_discards_tail;
110    halfword page_discards_head;
111    halfword split_discards_head;
112    scaled   split_last_height;
113    scaled   split_last_depth;
114    scaled   split_last_stretch;
115    scaled   split_last_shrink;
116    halfword except;
117} packaging_state_info;
118
119typedef enum box_limit_modes {
120    box_limit_none  = 0x00,
121    box_limit_hlist = 0x01,
122    box_limit_vlist = 0x02,
123    box_limit_line  = 0x04,
124} box_limit_modes;
125
126extern packaging_state_info lmt_packaging_state;
127
128extern scaled    tex_char_stretch          (halfword p);
129extern scaled    tex_char_shrink           (halfword p);
130/*     void      tex_get_char_expansion    (halfword p, halfword *stretch, halfword *shrink); */ /* no gain */
131extern scaled    tex_kern_stretch          (halfword p);
132extern scaled    tex_kern_shrink           (halfword p);
133extern scaled    tex_char_protrusion       (halfword p, int side);
134/*     void      tex_kern_protrusion       (halfword p, int side, halfword *stretch, halfword *shrink); */
135                                           
136extern scaled    tex_left_marginkern       (halfword p);
137extern scaled    tex_right_marginkern      (halfword p);
138                                           
139extern 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);
140extern 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, int *excess);
141                                           
142extern scaledwhd tex_natural_hsizes        (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
143extern scaledwhd tex_natural_vsizes        (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order, int inserts);
144extern scaledwhd tex_natural_msizes        (halfword p, int ignoreprime);
145extern halfword  tex_natural_width         (halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order);
146extern halfword  tex_natural_hsize         (halfword p, halfword *correction);
147extern halfword  tex_natural_vsize         (halfword p);
148                                           
149extern halfword  tex_hpack                 (halfword p, scaled w, int m, singleword d, int retain, int limit);
150extern halfword  tex_vpack                 (halfword p, scaled h, int m, scaled l, singleword d, int retain, int *excess);
151                                           
152extern void      tex_repack                (halfword p, scaled w, int m);
153extern void      tex_limit                 (halfword p);
154extern void      tex_freeze                (halfword p, int recurse, int limitate, halfword factor);
155extern void      tex_migrate               (halfword head, halfword *first, halfword *last, int inserts, int marks);
156
157extern scaled    tex_stretch               (halfword p);
158extern scaled    tex_shrink                (halfword p);
159                                           
160extern void      tex_package               (singleword nature);
161extern void      tex_run_unpackage         (void);
162                                           
163extern void      tex_append_to_vlist       (halfword b, int location, const line_break_properties *properties);
164                                           
165extern halfword  tex_prune_page_top        (halfword p, int s);
166extern halfword  tex_vert_break            (halfword p, scaled height, scaled depth, int callback, scaled extra);
167extern halfword  tex_vsplit                (halfword n, scaled h, int m);
168                                           
169extern void      tex_finish_vcenter_group  (void);
170extern void      tex_run_vcenter           (void);
171                                           
172extern void      tex_show_packaging_group  (const char *package);
173extern int       tex_show_packaging_record (void);
174
175extern int       tex_get_packaging_context (void);
176extern int       tex_get_packaging_shift   (void);
177
178extern int       tex_is_effectively_empty  (halfword n, halfword options); 
179
180typedef enum effective_empty_options {
181    effective_empty_option_par         = 0x0001,
182    effective_empty_option_dir         = 0x0002,
183    effective_empty_option_indent_list = 0x0004,
184    effective_empty_option_indent_glue = 0x0008,
185    effective_empty_option_all         = 0xFFFF,
186} effective_empty_options ;
187
188//# define vpack(A,B,C,D) tex_vpackage(A,B,C,max_dimension,D)
189
190# define first_un_box_code box_code
191# define last_un_box_code  unpack_code
192# define first_nu_box_code box_code
193# define last_nu_box_code  local_middle_box_box_code /*tex needs checking */
194
195/*tex
196
197    Now let's turn to the question of how |\hbox| is treated. We actually need to consider also a
198    slightly larger context, since constructions like
199
200    \starttyping
201    \setbox3={\\hbox...
202    \leaders\hbox...
203    \lower3.8pt\hbox...
204    \stoptyping
205
206    are supposed to invoke quite different actions after the box has been packaged. Conversely,
207    constructions like |\setbox 3 =| can be followed by a variety of different kinds of boxes, and
208    we would like to encode such things in an efficient way.
209
210    In other words, there are two problems: To represent the context of a box, and to represent its
211    type. The first problem is solved by putting a \quote {context code} on the |save_stack|, just
212    below the two entries that give the dimensions produced by |scan_spec|. The context code is
213    either a (signed) shift amount, or it is a large integer |>= box_flag|, where |box_flag = |
214    $2^{30}$. Codes |box_flag| through |box_flag + biggest_reg| represent |\setbox0| through
215    |\setbox biggest_reg|; codes |box_flag + biggest_reg + 1| through |box_flag + 2 * biggest_reg|
216    represent |\global \setbox 0| through |\global\setbox| |biggest_reg|; code |box_flag + 2 *
217    number_regs| represents |\shipout|; and codes |box_flag + 2 * number_regs + 1| through |box_flag
218    + 2 * number_regs + 3| represent |\leaders|, |\cleaders|, and |\xleaders|.
219
220    The second problem is solved by giving the command code |make_box| to all control sequences that
221    produce a box, and by using the following |chr_code| values to distinguish between them:
222    |box_code|, |copy_code|, |last_box_code|, |vsplit_code|, |vtop_code|, |vtop_code + vmode|, and
223    |vtop_code + hmode|, where the latter two are used denote |\vbox| and |\hbox|, respectively.
224
225    Originally the shift was encoded in the box context in case of a move. In fact even the local 
226    and global register assignments were in that property but this is no longer the case. This
227    actually makes implementing a |\boxspecdef| cleaner (a discarded experiment). The intermediate 
228    cleasned up flags can be found in the history. 
229
230*/
231
232# define biggest_reg 65535  /*tex This could be in |textypes.h|. */
233
234typedef enum box_flags {
235    direct_box_flag     = 0x00,
236 /* moved_box_flag      = 0x01, */
237 /* vcenter_box_flag    = 0x02, */ 
238    box_flag            = 0x02, /*tex context code for |\setbox0| */
239    global_box_flag     = 0x03, /*tex context code for |\global\setbox0| */
240    left_box_flag       = 0x04, /*tex context code for |\localleftbox| */
241    right_box_flag      = 0x05, /*tex context code for |\localrightbox| */
242    middle_box_flag     = 0x06, /*tex context code for |\localrightbox| */
243    shipout_flag        = 0x07, /*tex context code for |\shipout| */
244    lua_scan_flag       = 0x08, /*tex context code for |scan_list| */
245    a_leaders_flag      = 0x09, /*tex context code for |\leaders| */
246    c_leaders_flag      = 0x0A, /*tex context code for |\cleaders| */
247    x_leaders_flag      = 0x0B, /*tex context code for |\xleaders| */
248    g_leaders_flag      = 0x0C, /*tex context code for |\gleaders| */
249    u_leaders_flag      = 0x0D, /*tex context code for |\uleaders| */
250
251} box_flags;
252
253# define box_leaders_flag(f) (f >= a_leaders_flag && f <= u_leaders_flag)
254
255extern void tex_begin_box        (int boxcontext, scaled shift, halfword slot, halfword callback, halfword leaders);
256extern int  tex_ignore_math_skip (halfword p);
257
258static inline scaled tex_aux_checked_dimension1(halfword v)
259{
260    if (v > max_dimension) {
261        return max_dimension;
262    } else if (v < -max_dimension) {
263        return -max_dimension;
264    } else {
265        return v;
266    }
267}
268
269static inline scaled tex_aux_checked_dimension2(halfword v)
270{
271    if (v > max_dimension) {
272        return max_dimension;
273    } else if (v < 0) {
274        return 0;
275    } else {
276        return v;
277    }
278}
279
280# endif
281