beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / vfpacket.w
blob32b5e6346725ced3142d6ce42abf3468d4bef2bf
1 % vfpacket.w
3 % Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4 % Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software; you can redistribute it and/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation; either version 2 of the License, or (at your
11 % option) any later version.
13 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
21 @ @c
24 #include "ptexlib.h"
26 @ Some macros for processing character packets.
28 #define packet_number(fw) { \
29 fw = *(vfp++); \
30 fw = fw * 256 + *(vfp++); \
31 fw = fw * 256 + *(vfp++); \
32 fw = fw * 256 + *(vfp++); \
35 #define packet_scaled(a, fs) { \
36 int fw; \
37 fw = *(vfp++); \
38 if (fw > 127) \
39 fw = fw - 256; \
40 fw = fw * 256 + *(vfp++); \
41 fw = fw * 256 + *(vfp++); \
42 fw = fw * 256 + *(vfp++); \
43 a = store_scaled_f(fw, fs); \
46 @ @c
47 vf_struct *new_vfstruct(void)
49 vf_struct *vp = (vf_struct *) xmalloc(sizeof(vf_struct));
50 vp->packet_stack_level = vp->packet_stack_minlevel = 0;
51 vp->packet_stack =
52 (packet_stack_record *) xmalloc(packet_stack_size *
53 sizeof(packet_stack_record));
54 vp->lf = 0;
55 vp->fs_f = 0;
56 vp->packet_cur_s = 0;
57 vp->refpos = NULL;
58 vp->vflua = false;
59 return vp;
62 @ Count the number of bytes in a command packet.
64 int vf_packet_bytes(charinfo * co)
66 eight_bits *vf_packets, *vfp;
67 unsigned k;
68 int cmd;
70 vfp = vf_packets = get_charinfo_packets(co);
71 if (vf_packets == NULL) {
72 return 0;
74 while ((cmd = *(vfp++)) != packet_end_code) {
75 switch (cmd) {
76 case packet_nop_code:
77 case packet_pop_code:
78 case packet_push_code:
79 break;
80 case packet_char_code:
81 case packet_down_code:
82 case packet_font_code:
83 case packet_image_code:
84 case packet_node_code:
85 case packet_right_code:
86 vfp += 4;
87 break;
88 case packet_rule_code:
89 vfp += 8;
90 break;
91 case packet_special_code:
92 packet_number(k); /* +4 */
93 vfp += (int) k;
94 break;
95 default:
96 normal_error("vf", "invalid DVI command (1)");
99 return (vfp - vf_packets);
102 @ Typeset the \.{DVI} commands in the character packet
103 for character |c| in current font |f|.
105 const char *packet_command_names[] = {
106 "char", "font", "pop", "push", "special", "image",
107 "right", "down", "rule", "node", "nop", "end", "scale", "lua", NULL
110 @ @c
111 static float packet_float(eight_bits ** vfpp)
113 unsigned int i;
114 union U {
115 float a;
116 eight_bits b[sizeof(float)];
117 } u;
118 eight_bits *vfp = *vfpp;
119 for (i = 0; i < sizeof(float); i++)
120 u.b[i] = *(vfp++);
121 *vfpp = vfp;
122 return u.a;
125 @ The |do_vf_packet| procedure is called in order to interpret the
126 character packet for a virtual character. Such a packet may contain
127 the instruction to typeset a character from the same or an other
128 virtual font; in such cases |do_vf_packet| calls itself
129 recursively. The recursion level, i.e., the number of times this has
130 happened, is kept in the global variable |packet_cur_s| and should
131 not exceed |packet_max_recursion|.
133 void do_vf_packet(PDF pdf, internal_font_number vf_f, int c, int ex_glyph)
135 eight_bits *vfp;
136 posstructure *save_posstruct, localpos;
137 vf_struct *save_vfstruct, localvfstruct, *vp;
138 int cmd, w;
139 unsigned k;
140 scaledpos size;
141 scaled i;
142 str_number s;
143 float f;
144 packet_stack_record *mat_p;
146 vfp = get_charinfo_packets(get_charinfo(vf_f, c));
147 assert(vfp != NULL);
149 save_posstruct = pdf->posstruct;
150 pdf->posstruct = &localpos; /* use local structure for recursion */
151 localpos.pos = save_posstruct->pos;
152 localpos.dir = dir_TLT; /* invariably for vf */
154 save_vfstruct = pdf->vfstruct;
155 vp = pdf->vfstruct = &localvfstruct;
156 localvfstruct = *save_vfstruct;
158 vp->packet_stack_minlevel = ++(vp->packet_stack_level);
159 vp->lf = 0;
160 vp->fs_f = font_size(vf_f);
161 vp->ex_glyph = ex_glyph;
162 vp->packet_cur_s++;
163 if (vp->packet_cur_s == packet_max_recursion)
164 overflow("max level recursion of virtual fonts", packet_max_recursion);
165 vp->refpos = save_posstruct;
166 vp->vflua = false;
168 mat_p = &(vp->packet_stack[vp->packet_stack_level]);
169 mat_p->c0 = 1.0;
170 mat_p->c1 = 0.0;
171 mat_p->c2 = 0.0;
172 mat_p->c3 = 1.0;
173 mat_p->pos.h = 0;
174 mat_p->pos.v = 0;
176 while ((cmd = *(vfp++)) != packet_end_code) {
177 #ifdef DEBUG
178 if (cmd > packet_end_code) {
179 fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n",
180 vf_f, c);
181 } else {
182 fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n", vf_f, c,
183 packet_command_names[cmd]);
185 #endif
186 switch (cmd) {
187 case packet_font_code:
188 packet_number(vp->lf);
189 break;
190 case packet_push_code:
191 vp->packet_stack_level++;
192 if (vp->packet_stack_level == packet_stack_size)
193 normal_error("vf", "packet_stack_level overflow");
194 vp->packet_stack[vp->packet_stack_level] = *mat_p;
195 mat_p = &(vp->packet_stack[vp->packet_stack_level]);
196 break;
197 case packet_pop_code:
198 if (vp->packet_stack_level == vp->packet_stack_minlevel)
199 normal_error("vf", "packet_stack_level underflow");
200 vp->packet_stack_level--;
201 mat_p = &(vp->packet_stack[vp->packet_stack_level]);
202 break;
203 case packet_char_code:
204 packet_number(k);
205 if (!char_exists(vp->lf, (int) k))
206 char_warning(vp->lf, (int) k);
207 else {
208 if (has_packet(vp->lf, (int) k))
209 do_vf_packet(pdf, vp->lf, (int) k, ex_glyph);
210 else
211 backend_out[glyph_node] (pdf, vp->lf, (int) k, ex_glyph);
213 w = char_width(vp->lf, (int) k);
214 mat_p->pos.h += round_xn_over_d(w, 1000 + ex_glyph, 1000);
215 break;
216 case packet_rule_code:
217 packet_scaled(size.v, vp->fs_f); /* height (where is depth?) */
218 packet_scaled(size.h, vp->fs_f);
219 if (size.h > 0 && size.v > 0)
220 backend_out[rule_node](pdf, 0, size); /* the 0 is unused */
221 mat_p->pos.h += size.h;
222 break;
223 case packet_right_code:
224 packet_scaled(i, vp->fs_f);
225 mat_p->pos.h += i;
226 break;
227 case packet_down_code:
228 packet_scaled(i, vp->fs_f);
229 mat_p->pos.v += i;
230 break;
231 case packet_special_code:
232 packet_number(k);
233 str_room(k);
234 while (k > 0) {
235 k--;
236 append_char(*(vfp++));
238 s = make_string();
239 pdf_literal(pdf, s, scan_special, false);
240 flush_str(s);
241 break;
242 case packet_lua_code:
243 packet_number(k);
244 vp->vflua = true;
245 if (luaL_loadbuffer
246 (Luas, (const char *) vfp, (size_t) k, "packet_lua_code")
247 || lua_pcall(Luas, 0, LUA_MULTRET, 0))
248 lua_error(Luas);
249 vp->vflua = false;
250 vfp += k;
251 break;
252 case packet_image_code:
253 packet_number(k);
254 vf_out_image(pdf, k);
255 break;
256 case packet_node_code:
257 packet_number(k);
258 hlist_out(pdf, (halfword) k, 0);
259 break;
260 case packet_nop_code:
261 break;
262 case packet_scale_code:
263 f = packet_float(&vfp);
264 mat_p->c0 = mat_p->c0 * f;
265 mat_p->c3 = mat_p->c3 * f;
266 /* pdf->pstruct->scale = f; *//* scale is still NOP */
267 pdf->pstruct->need_tm = true;
268 pdf->pstruct->need_tf = true;
269 break;
270 default:
271 normal_error("vf", "invalid DVI command (2)");
273 synch_pos_with_cur(&localpos, save_posstruct, mat_p->pos); /* trivial case, always TLT */
275 pdf->posstruct = save_posstruct;
276 pdf->vfstruct = save_vfstruct;
279 @ @c
280 int *packet_local_fonts(internal_font_number f, int *num)
282 int c, cmd, lf, k, l, i;
283 int localfonts[256] = { 0 };
284 int *lfs;
285 charinfo *co;
287 eight_bits *vf_packets, *vfp;
288 k = 0;
289 for (c = font_bc(f); c <= font_ec(f); c++) {
290 if (quick_char_exists(f, c)) {
291 co = get_charinfo(f, c);
292 vfp = vf_packets = get_charinfo_packets(co);
293 if (vf_packets == NULL)
294 continue;
295 while ((cmd = *(vfp++)) != packet_end_code) {
296 switch (cmd) {
297 case packet_font_code:
298 packet_number(lf);
299 for (l = 0; l < k; l++) {
300 if (localfonts[l] == lf) {
301 break;
304 if (l == k) {
305 localfonts[k++] = lf;
307 break;
308 case packet_nop_code:
309 case packet_pop_code:
310 case packet_push_code:
311 break;
312 case packet_char_code:
313 case packet_down_code:
314 case packet_image_code:
315 case packet_node_code:
316 case packet_right_code:
317 vfp += 4;
318 break;
319 case packet_rule_code:
320 vfp += 8;
321 break;
322 case packet_special_code:
323 packet_number(i);
324 vfp += i;
325 break;
326 default:
327 normal_error("vf", "invalid DVI command (3)");
332 *num = k;
333 if (k > 0) {
334 lfs = xmalloc((unsigned) ((unsigned) k * sizeof(int)));
335 memcpy(lfs, localfonts, (size_t) ((unsigned) k * sizeof(int)));
336 return lfs;
338 return NULL;
341 @ @c
342 void
343 replace_packet_fonts(internal_font_number f, int *old_fontid,
344 int *new_fontid, int count)
346 int c, cmd, lf, k, l;
347 charinfo *co;
348 eight_bits *vf_packets, *vfp;
350 for (c = font_bc(f); c <= font_ec(f); c++) {
351 if (quick_char_exists(f, c)) {
352 co = get_charinfo(f, c);
353 vfp = vf_packets = get_charinfo_packets(co);
354 if (vf_packets == NULL)
355 continue;
356 while ((cmd = *(vfp++)) != packet_end_code) {
357 switch (cmd) {
358 case packet_font_code:
359 packet_number(lf);
360 for (l = 0; l < count; l++) {
361 if (old_fontid[l] == lf) {
362 break;
365 if (l < count) {
366 k = new_fontid[l];
367 *(vfp - 4) = (eight_bits)
368 ((k & 0xFF000000) >> 24);
369 *(vfp - 3) = (eight_bits)
370 ((k & 0x00FF0000) >> 16);
371 *(vfp - 2) = (eight_bits)
372 ((k & 0x0000FF00) >> 8);
373 *(vfp - 1) = (eight_bits) (k & 0x000000FF);
375 break;
376 case packet_nop_code:
377 case packet_pop_code:
378 case packet_push_code:
379 break;
380 case packet_char_code:
381 case packet_down_code:
382 case packet_image_code:
383 case packet_node_code:
384 case packet_right_code:
385 vfp += 4;
386 break;
387 case packet_rule_code:
388 vfp += 8;
389 break;
390 case packet_special_code:
391 packet_number(k);
392 vfp += k;
393 break;
394 default:
395 normal_error("vf", "invalid DVI command (4)");