1 /* packaging.h
2 
3    Copyright 2009 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 
21 #ifndef PACKAGING_H
22 #  define PACKAGING_H
23 
24 /* We define some constants used when calling |hpack| to deal with font expansion. */
25 
26 typedef enum {
27     exactly = 0,                /*a box dimension is pre-specified */
28     additional,                 /*a box dimension is increased from the natural one */
29     cal_expand_ratio,           /* calculate amount for font expansion after breaking
30                                    paragraph into lines */
31     subst_ex_font               /* substitute fonts */
32 } hpack_subtypes;
33 
34 #  define substituted 3         /* |subtype| of kern nodes that should be substituted */
35 
36 extern void scan_spec(group_code c);
37 extern void scan_full_spec(group_code c, int spec_direction);
38 
39 extern scaled total_stretch[5];
40 extern scaled total_shrink[5];  /* glue found by |hpack| or |vpack| */
41 extern int last_badness;        /* badness of the most recently packaged box */
42 extern halfword adjust_tail;    /* tail of adjustment list */
43 extern halfword pre_adjust_tail;
44 extern int font_expand_ratio;   /* current expansion ratio */
45 extern halfword last_leftmost_char;
46 extern halfword last_rightmost_char;
47 extern halfword next_char_p;    /* pointer to the next char of an implicit kern */
48 extern halfword prev_char_p;    /* pointer to the previous char of an implicit kern */
49 
50 extern void set_prev_char_p(halfword p);
51 extern scaled char_stretch(halfword p);
52 extern scaled char_shrink(halfword p);
53 extern scaled kern_stretch(halfword p);
54 extern scaled kern_shrink(halfword p);
55 extern void do_subst_font(halfword p, int ex_ratio);
56 extern scaled char_pw(halfword p, int side);
57 extern halfword new_margin_kern(scaled w, halfword p, int side);
58 
59 #  define update_adjust_list(A) do {					\
60 	if (A == null)							\
61 	    pdf_error("pre vadjust", "adjust_tail or pre_adjust_tail is null");	\
62 	vlink(A) = adjust_ptr(p);					\
63 	while (vlink(A) != null)					\
64 	    A = vlink(A);						\
65     } while (0)
66 
67 extern halfword hpack(halfword p, scaled w, int m, int d);
68 extern halfword filtered_hpack(halfword p, halfword qt, scaled w, int m,
69                                int grp, int d);
70 
71 extern scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult,
72                                 int g_sign, int g_order, int d);
73 
74 extern int pack_begin_line;
75 
76 #  define vpack(A,B,C,D) vpackage(A,B,C,max_dimen,D)    /* special case of unconstrained depth */
77 
78 extern halfword vpackage(halfword p, scaled h, int m, scaled l, int d);
79 extern halfword filtered_vpackage(halfword p, scaled h, int m, scaled l,
80                                   int grp, int d);
81 extern void finish_vcenter(void);
82 extern void package(int c);
83 extern void append_to_vlist(halfword b);
84 
85 extern halfword prune_page_top(halfword p, boolean s);
86 extern scaled active_height[10];        /* distance from first active node to~|cur_p| */
87 
88 #  define cur_height active_height[1]   /* the natural height */
89 #  define awful_bad 07777777777 /* more than a billion demerits */
90 #  define deplorable 100000     /* more than |inf_bad|, but less than |awful_bad| */
91 
92 extern scaled best_height_plus_depth;   /* height of the best box, without stretching or shrinking */
93 
94 extern halfword vert_break(halfword p, scaled h, scaled d);
95 extern halfword vsplit(halfword n, scaled h);   /* extracts a page of height |h| from box |n| */
96 
97 #  define box_code 0            /* |chr_code| for `\.{\\box}' */
98 #  define copy_code 1           /* |chr_code| for `\.{\\copy}' */
99 #  define last_box_code 2       /* |chr_code| for `\.{\\lastbox}' */
100 #  define vsplit_code 3         /* |chr_code| for `\.{\\vsplit}' */
101 #  define vtop_code 4           /* |chr_code| for `\.{\\vtop}' */
102 
103 #  define tail_page_disc disc_ptr[copy_code]    /* last item removed by page builder */
104 #  define page_disc disc_ptr[last_box_code]     /* first item removed by page builder */
105 #  define split_disc disc_ptr[vsplit_code]      /* first item removed by \.{\\vsplit} */
106 
107 extern halfword disc_ptr[(vsplit_code + 1)];    /* list pointers */
108 
109 /*
110 Now let's turn to the question of how \.{\\hbox} is treated. We actually
111 need to consider also a slightly larger context, since constructions like
112 `\.{\\setbox3=}\penalty0\.{\\hbox...}' and
113 `\.{\\leaders}\penalty0\.{\\hbox...}' and
114 `\.{\\lower3.8pt\\hbox...}'
115 are supposed to invoke quite
116 different actions after the box has been packaged. Conversely,
117 constructions like `\.{\\setbox3=}' can be followed by a variety of
118 different kinds of boxes, and we would like to encode such things in an
119 efficient way.
120 
121 In other words, there are two problems: To represent the context of a box,
122 and to represent its type.
123 
124 The first problem is solved by putting a ``context code'' on the |save_stack|,
125 just below the two entries that give the dimensions produced by |scan_spec|.
126 The context code is either a (signed) shift amount, or it is a large
127 integer |>=box_flag|, where |box_flag=@t$2^{30}$@>|. Codes |box_flag| through
128 |box_flag+biggest_reg| represent `\.{\\setbox0}' through
129 `\.{\\setbox}|biggest_reg|'; codes |box_flag+biggest_reg+1| through
130 |box_flag+2*biggest_reg| represent `\.{\\global\\setbox0}'
131 through `\.{\\global\\setbox}|biggest_reg|'; code |box_flag+2*number_regs|
132 represents `\.{\\shipout}'; and codes |box_flag+2*number_regs+1|
133 through |box_flag+2*number_regs+3| represent `\.{\\leaders}', `\.{\\cleaders}',
134 and `\.{\\xleaders}'.
135 
136 The second problem is solved by giving the command code |make_box| to all
137 control sequences that produce a box, and by using the following |chr_code|
138 values to distinguish between them: |box_code|, |copy_code|, |last_box_code|,
139 |vsplit_code|, |vtop_code|, |vtop_code+vmode|, and |vtop_code+hmode|,
140 where the latter two are used denote \.{\\vbox} and \.{\\hbox}, respectively.
141 */
142 
143 #  define box_flag 010000000000 /* context code for `\.{\\setbox0}' */
144 #  define global_box_flag (box_flag+number_regs)        /* context code for `\.{\\global\\setbox0}' */
145 #  define max_global_box_flag (global_box_flag+number_regs)
146 #  define ship_out_flag (max_global_box_flag+1) /* context code for `\.{\\shipout}' */
147 #  define leader_flag ship_out_flag+1   /* context code for `\.{\\leaders}' */
148 
149 extern void begin_box(int box_context);
150 
151 #endif
152