OSDN Git Service

updated Windows build.
[putex/putex.git] / src / texsourc / dpx.c
1 /* Copyright 2014 Clerk Ma\r
2 \r
3    This program is free software; you can redistribute it and/or modify\r
4    it under the terms of the GNU General Public License as published by\r
5    the Free Software Foundation; either version 2 of the License, or\r
6    (at your option) any later version.\r
7 \r
8    This program is distributed in the hope that it will be useful, but\r
9    WITHOUT ANY WARRANTY; without even the implied warranty of\r
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
11    General Public License for more details.\r
12 \r
13    You should have received a copy of the GNU General Public License\r
14    along with this program; if not, write to the Free Software\r
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
16    02110-1301 USA.  */\r
17 \r
18 /* Y&Y TeX's DVIPDFMX backend. */\r
19 \r
20 #define EXTERN extern\r
21 \r
22 #include "dpx.h"\r
23 #include "yandytex.h"\r
24 \r
25 void ensure_pdf_open(void)\r
26 {\r
27   if (output_file_name == 0)\r
28   {\r
29     if (job_name == 0)\r
30       open_log_file();\r
31 \r
32     pack_job_name(".pdf");\r
33 \r
34     while (!b_open_out(pdf_file))\r
35       prompt_file_name("file name for output", ".pdf");\r
36 \r
37     output_file_name = b_make_name_string(pdf_file);\r
38   }\r
39 }\r
40 \r
41 void pdf_ship_out (pointer p)\r
42 {\r
43   integer page_loc;\r
44   char j, k;\r
45   pool_pointer s;\r
46   char old_setting;\r
47 \r
48   if (tracing_output > 0)\r
49   {\r
50     print_nl("");\r
51     print_ln();\r
52     prints("Completed box being shipped out");\r
53   }\r
54 \r
55   if (term_offset > max_print_line - 9)\r
56     print_ln();\r
57   else if ((term_offset > 0) || (file_offset > 0))\r
58     print_char(' ');\r
59 \r
60   print_char('[');\r
61   j = 9;\r
62 \r
63   while ((count(j) == 0) && (j > 0))\r
64     decr(j);\r
65 \r
66   for (k = 0; k <= j; k++)\r
67   {\r
68     print_int(count(k));\r
69 \r
70     if (k < j)\r
71       print_char('.');\r
72   }\r
73 \r
74   update_terminal();\r
75 \r
76   if (tracing_output > 0)\r
77   {\r
78     print_char(']');\r
79     begin_diagnostic();\r
80     show_box(p);\r
81     end_diagnostic(true);\r
82   }\r
83 \r
84   if ((height(p) > max_dimen) || (depth(p) > max_dimen) ||\r
85     (height(p) + depth(p) + v_offset > max_dimen) ||\r
86     (width(p) + h_offset > max_dimen))\r
87   {\r
88     print_err("Huge page cannot be shipped out");\r
89     help2("The page just created is more than 18 feet tall or",\r
90       "more than 18 feet wide, so I suspect something went wrong.");\r
91     error();\r
92 \r
93     if (tracing_output <= 0)\r
94     {\r
95       begin_diagnostic();\r
96       print_nl("The following box has been deleted:");\r
97       show_box(p);\r
98       end_diagnostic(true);\r
99     }\r
100 \r
101     goto done;\r
102   }\r
103 \r
104   if (height(p) + depth(p) + v_offset > max_v)\r
105     max_v = height(p) + depth(p) + v_offset;\r
106 \r
107   if (width(p) + h_offset > max_h)\r
108     max_h = width(p) + h_offset;\r
109 \r
110   dvi_h = 0;\r
111   dvi_v = 0;\r
112   cur_h = h_offset;\r
113   dvi_f = null_font;\r
114   ensure_pdf_open();\r
115 \r
116   if (total_pages == 0)\r
117   {\r
118     pdf_set_version(5);\r
119     pdf_set_compression(9);\r
120     pdf_init_fontmaps();\r
121     read_config_file("dvipdfmx.cfg");\r
122     pdf_doc_set_producer("Y&YTeX 2.3.0");\r
123     pdf_doc_set_creator("TeX");\r
124     pdf_files_init();\r
125     pdf_init_device(0.000015202, 2, 0);\r
126     pdf_open_document(pdf_file_name, 0, 595.0, 842.0, 0, 0, (1 << 4));\r
127     spc_exec_at_begin_document();\r
128   }\r
129 \r
130   page_loc = dvi_offset + dvi_ptr;\r
131   pdf_doc_begin_page(1.0, 72.0, 770.0);\r
132   spc_exec_at_begin_page();\r
133 \r
134   last_bop = page_loc;\r
135   cur_v = height(p) + v_offset;\r
136   temp_ptr = p;\r
137 \r
138   if (type(p) == vlist_node)\r
139     pdf_vlist_out();\r
140   else\r
141     pdf_hlist_out();\r
142 \r
143   spc_exec_at_end_page();\r
144   pdf_doc_end_page();\r
145   incr(total_pages);\r
146   cur_s = -1;\r
147 \r
148 done:\r
149   if (tracing_output <= 0)\r
150     print_char(']');\r
151 \r
152   dead_cycles = 0;\r
153   update_terminal();\r
154 \r
155 #ifdef STAT\r
156   if (tracing_stats > 1)\r
157   {\r
158     print_nl("Memory usage before: ");\r
159     print_int(var_used);\r
160     print_char('&');\r
161     print_int(dyn_used);\r
162     print_char(';');\r
163   }\r
164 #endif\r
165 \r
166   flush_node_list(p);\r
167 \r
168 #ifdef STAT\r
169   if (tracing_stats > 1)\r
170   {\r
171     prints(" after: ");\r
172     print_int(var_used);\r
173     print_char('&');\r
174     print_int(dyn_used);\r
175     prints("; still utouched: ");\r
176     print_int(hi_mem_min - lo_mem_max - 1);\r
177     print_ln();\r
178   }\r
179 #endif\r
180 }\r
181 \r
182 void pdf_synch_h (void)\r
183 {\r
184   if (cur_h != dvi_h)\r
185     dvi_h = cur_h;\r
186 }\r
187 \r
188 void pdf_synch_v (void)\r
189 {\r
190   if (cur_v != dvi_v)\r
191     dvi_v = cur_v;\r
192 }\r
193 \r
194 int pdf_get_font_id (internal_font_number f)\r
195 {\r
196   char * sbuf = malloc(length(font_name[f]) + 1);\r
197   int id;\r
198   memset(sbuf, 0, length(font_name[f]) + 1);\r
199   memcpy(sbuf, str_pool + str_start[font_name[f]], length(font_name[f]));    \r
200   id = dvi_locate_font(sbuf, font_size[f]);\r
201   free(sbuf);\r
202 \r
203   return id;\r
204 }\r
205 \r
206 void pdf_hlist_out (void)\r
207 {\r
208   scaled base_line;\r
209   scaled left_edge;\r
210   scaled save_h, save_v;\r
211   pointer this_box;\r
212   // glue_ord g_order;\r
213   int g_order;\r
214   // char g_sign;\r
215   int g_sign;\r
216   pointer p;\r
217   integer save_loc;\r
218   pointer leader_box;\r
219   scaled leader_wd;\r
220   scaled lx;\r
221   boolean outer_doing_leaders;\r
222   scaled edge;\r
223   real glue_temp;\r
224   real cur_glue;\r
225   scaled cur_g;\r
226 \r
227   cur_g = 0;\r
228   cur_glue = 0.0;\r
229   this_box = temp_ptr;\r
230   g_order = glue_order(this_box);\r
231   g_sign = glue_sign(this_box);\r
232   p = list_ptr(this_box);\r
233   incr(cur_s);\r
234 \r
235   if (cur_s > max_push)\r
236     max_push = cur_s;\r
237 \r
238   save_loc = dvi_offset + dvi_ptr;\r
239   base_line = cur_v;\r
240   left_edge = cur_h;\r
241 \r
242   while (p != 0)\r
243 reswitch:\r
244   if (is_char_node(p))\r
245   {\r
246     pdf_synch_h();\r
247     pdf_synch_v();\r
248 \r
249     do\r
250     {\r
251       f = font(p);\r
252       c = character(p);\r
253 \r
254       if (f != dvi_f)\r
255       {\r
256         if (!font_used[f])\r
257         {\r
258           font_used[f] = true;\r
259           font_id[f]   = pdf_get_font_id(f); \r
260         }\r
261 \r
262         dvi_f = f;\r
263       }\r
264 \r
265       char cbuf[2] = {c, 0};\r
266       pdf_dev_set_string(cur_h, -cur_v, cbuf, 1, char_width(f, char_info(f, c)), font_id[dvi_f], 1);\r
267       cur_h = cur_h + char_width(f, char_info(f, c));\r
268       p = link(p);\r
269     } while (!(!is_char_node(p)));\r
270 \r
271     dvi_h = cur_h;\r
272   }\r
273   else\r
274   {\r
275     switch (type(p))\r
276     {\r
277       case hlist_node:\r
278       case vlist_node:\r
279         if (list_ptr(p) == 0)\r
280           cur_h = cur_h + width(p);\r
281         else\r
282         {\r
283           save_h = dvi_h;\r
284           save_v = dvi_v;\r
285           cur_v = base_line + shift_amount(p);\r
286           temp_ptr = p;\r
287           edge = cur_h;\r
288 \r
289           if (type(p) == vlist_node)\r
290             pdf_vlist_out();\r
291           else\r
292             pdf_hlist_out();\r
293 \r
294           dvi_h = save_h;\r
295           dvi_v = save_v;\r
296           cur_h = edge + width(p);\r
297           cur_v = base_line;\r
298         }\r
299         break;\r
300 \r
301       case rule_node:\r
302       {\r
303         rule_ht = height(p);\r
304         rule_dp = depth(p);\r
305         rule_wd = width(p);\r
306         goto fin_rule;\r
307       }\r
308         break;\r
309 \r
310       case whatsit_node:\r
311         out_what(p);\r
312         break;\r
313 \r
314       case glue_node:\r
315       {\r
316         g = glue_ptr(p);\r
317         rule_wd = width(g) - cur_g;\r
318 \r
319         if (g_sign != normal)\r
320         {\r
321           if (g_sign == stretching)\r
322           {\r
323             if (stretch_order(g) == g_order)\r
324             {\r
325               cur_glue = cur_glue + stretch(g);\r
326               vet_glue(glue_set(this_box) * cur_glue);\r
327               cur_g = round(glue_temp);\r
328             }\r
329           }\r
330           else if (shrink_order(g) == g_order)\r
331           {\r
332             cur_glue = cur_glue - shrink(g);\r
333             vet_glue(glue_set(this_box) * cur_glue);\r
334             cur_g = round(glue_temp);\r
335           }\r
336         }\r
337 \r
338         rule_wd = rule_wd + cur_g;\r
339 \r
340         if (subtype(p) >= a_leaders)\r
341         {\r
342           leader_box = leader_ptr(p);\r
343 \r
344           if (type(leader_box) == rule_node)\r
345           {\r
346             rule_ht = height(leader_box);\r
347             rule_dp = depth(leader_box);\r
348             goto fin_rule;\r
349           }\r
350 \r
351           leader_wd = width(leader_box);\r
352 \r
353           if ((leader_wd > 0) && (rule_wd > 0))\r
354           {\r
355             rule_wd = rule_wd + 10;\r
356             edge = cur_h + rule_wd;\r
357             lx = 0;\r
358 \r
359             if (subtype(p) == a_leaders)\r
360             {\r
361               save_h = cur_h;\r
362               cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);\r
363 \r
364               if (cur_h < save_h)\r
365                 cur_h = cur_h + leader_wd;\r
366             }\r
367             else\r
368             {\r
369               lq = rule_wd / leader_wd;\r
370               lr = rule_wd % leader_wd;\r
371 \r
372               if (subtype(p) == c_leaders)\r
373                 cur_h = cur_h + (lr / 2);\r
374               else\r
375               {\r
376                 lx = (2 * lr + lq + 1) / (2 * lq + 2);\r
377                 cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);\r
378               }\r
379             }\r
380 \r
381             while (cur_h + leader_wd <= edge)\r
382             {\r
383               cur_v = base_line + shift_amount(leader_box);\r
384               pdf_synch_v();\r
385               save_v = dvi_v;\r
386               pdf_synch_h();\r
387               save_h = dvi_h;\r
388               temp_ptr = leader_box;\r
389               outer_doing_leaders = doing_leaders;\r
390               doing_leaders = true;\r
391 \r
392               if (type(leader_box) == vlist_node)\r
393                 pdf_vlist_out();\r
394               else\r
395                 pdf_hlist_out();\r
396 \r
397               doing_leaders = outer_doing_leaders;\r
398               dvi_v = save_v;\r
399               dvi_h = save_h;\r
400               cur_v = base_line;\r
401               cur_h = save_h + leader_wd + lx;\r
402             }\r
403 \r
404             cur_h = edge - 10;\r
405             goto next_p;\r
406           }\r
407         }\r
408 \r
409         goto move_past;\r
410       }\r
411         break;\r
412 \r
413       case kern_node:\r
414       case math_node:\r
415         cur_h = cur_h + width(p);\r
416         break;\r
417 \r
418       case ligature_node:\r
419       {\r
420         mem[lig_trick] = mem[lig_char(p)];\r
421         link(lig_trick) = link(p);\r
422         p = lig_trick;\r
423         goto reswitch;\r
424       }\r
425         break;\r
426 \r
427       default:\r
428         break;\r
429     }\r
430 \r
431     goto next_p;\r
432 \r
433 fin_rule:\r
434     if (is_running(rule_ht))\r
435       rule_ht = height(this_box);\r
436 \r
437     if (is_running(rule_dp))\r
438       rule_dp = depth(this_box);\r
439 \r
440     rule_ht = rule_ht + rule_dp;\r
441 \r
442     if ((rule_ht > 0) && (rule_wd > 0))\r
443     {\r
444       pdf_synch_h();\r
445       cur_v = base_line + rule_dp;\r
446       pdf_synch_v();\r
447       pdf_dev_set_rule(dvi_h, dvi_v, rule_wd, rule_ht);\r
448       cur_v = base_line;\r
449       dvi_h = dvi_h + rule_wd;\r
450     }\r
451 \r
452 move_past:\r
453     cur_h = cur_h + rule_wd;\r
454 \r
455 next_p:\r
456     p = link(p);\r
457   }\r
458 \r
459   prune_movements(save_loc);\r
460   decr(cur_s);\r
461 }\r
462 \r
463 void pdf_vlist_out (void)\r
464 {\r
465   scaled left_edge;\r
466   scaled top_edge;\r
467   scaled save_h, save_v;\r
468   pointer this_box;\r
469   // glue_ord g_order;\r
470   int g_order;\r
471   // char g_sign;\r
472   int g_sign;\r
473   pointer p;\r
474   integer save_loc;\r
475   pointer leader_box;\r
476   scaled leader_ht;\r
477   scaled lx;\r
478   boolean outer_doing_leaders;\r
479   scaled edge;\r
480   real glue_temp;\r
481   real cur_glue;\r
482   scaled cur_g;\r
483 \r
484   cur_g = 0;\r
485   cur_glue = 0.0;\r
486   this_box = temp_ptr;\r
487   g_order = glue_order(this_box);\r
488   g_sign = glue_sign(this_box);\r
489   p = list_ptr(this_box);\r
490   incr(cur_s);\r
491 \r
492   if (cur_s > max_push)\r
493     max_push = cur_s;\r
494 \r
495   save_loc = dvi_offset + dvi_ptr;\r
496   left_edge = cur_h;\r
497   cur_v = cur_v - height(this_box);\r
498   top_edge = cur_v;\r
499 \r
500   while (p != 0)\r
501   {\r
502     if (is_char_node(p))\r
503     {\r
504       confusion("vlistout");\r
505       return;\r
506     }\r
507     else\r
508     {\r
509       switch (type(p))\r
510       {\r
511         case hlist_node:\r
512         case vlist_node:\r
513           if (list_ptr(p) == 0)\r
514             cur_v = cur_v + height(p) + depth(p);\r
515           else\r
516           {\r
517             cur_v = cur_v + height(p);\r
518             pdf_synch_v();\r
519             save_h = dvi_h;\r
520             save_v = dvi_v;\r
521             cur_h = left_edge + shift_amount(p);\r
522             temp_ptr = p;\r
523 \r
524             if (type(p) == vlist_node)\r
525               pdf_vlist_out();\r
526             else\r
527               pdf_hlist_out();\r
528 \r
529             dvi_h = save_h;\r
530             dvi_v = save_v;\r
531             cur_v = save_v + depth(p);\r
532             cur_h = left_edge;\r
533           }\r
534           break;\r
535 \r
536         case rule_node:\r
537           {\r
538             rule_ht = height(p);\r
539             rule_dp = depth(p);\r
540             rule_wd = width(p);\r
541             goto fin_rule;\r
542           }\r
543           break;\r
544 \r
545         case whatsit_node:\r
546           out_what(p);\r
547           break;\r
548 \r
549         case glue_node:\r
550           {\r
551             g = glue_ptr(p);\r
552             rule_ht = width(g) - cur_g;\r
553 \r
554             if (g_sign != normal)\r
555             {\r
556               if (g_sign == stretching)\r
557               {\r
558                 if (stretch_order(g) == g_order)\r
559                 {\r
560                   cur_glue = cur_glue + stretch(g);\r
561                   vet_glue(glue_set(this_box) * cur_glue);\r
562                   cur_g = round(glue_temp);\r
563                 }\r
564               }\r
565               else if (shrink_order(g) == g_order)   /* BUG FIX !!! */\r
566               {\r
567                 cur_glue = cur_glue - shrink(g);\r
568                 vet_glue(glue_set(this_box) * cur_glue);\r
569                 cur_g = round(glue_temp);\r
570               }\r
571             }\r
572 \r
573             rule_ht = rule_ht + cur_g;\r
574 \r
575             if (subtype(p) >= a_leaders)\r
576             {\r
577               leader_box = leader_ptr(p);\r
578 \r
579               if (type(leader_box) == rule_node)\r
580               {\r
581                 rule_wd = width(leader_box);\r
582                 rule_dp = 0;\r
583                 goto fin_rule;\r
584               }\r
585 \r
586               leader_ht = height(leader_box) + depth(leader_box);\r
587 \r
588               if ((leader_ht > 0) && (rule_ht > 0))\r
589               {\r
590                 rule_ht = rule_ht + 10;\r
591                 edge = cur_v + rule_ht;\r
592                 lx = 0;\r
593 \r
594                 if (subtype(p) == a_leaders)\r
595                 {\r
596                   save_v = cur_v;\r
597                   cur_v = top_edge + leader_ht * ((cur_v - top_edge) / leader_ht);\r
598 \r
599                   if (cur_v < save_v)\r
600                     cur_v = cur_v + leader_ht;\r
601                 }\r
602                 else\r
603                 {\r
604                   lq = rule_ht / leader_ht;\r
605                   lr = rule_ht % leader_ht;\r
606 \r
607                   if (subtype(p) == c_leaders)\r
608                     cur_v = cur_v + (lr / 2);\r
609                   else\r
610                   {\r
611                     lx = (2 * lr + lq + 1) / (2 * lq + 2);\r
612                     cur_v = cur_v + ((lr - (lq - 1) * lx) / 2);\r
613                   }\r
614                 }\r
615 \r
616                 while (cur_v + leader_ht <= edge)\r
617                 {\r
618                   cur_h = left_edge + shift_amount(leader_box);\r
619                   pdf_synch_h();\r
620                   save_h = dvi_h;\r
621                   cur_v = cur_v + height(leader_box);\r
622                   pdf_synch_v();\r
623                   save_v = dvi_v;\r
624                   temp_ptr = leader_box;\r
625                   outer_doing_leaders = doing_leaders;\r
626                   doing_leaders = true;\r
627 \r
628                   if (type(leader_box) == vlist_node)\r
629                     pdf_vlist_out();\r
630                   else\r
631                     pdf_hlist_out();\r
632 \r
633                   doing_leaders = outer_doing_leaders;\r
634                   dvi_v = save_v;\r
635                   dvi_h = save_h;\r
636                   cur_h = left_edge;\r
637                   cur_v = save_v - height(leader_box) + leader_ht + lx;\r
638                 }\r
639 \r
640                 cur_v = edge - 10;\r
641                 goto next_p;\r
642               }\r
643             }\r
644 \r
645             goto move_past;\r
646           }\r
647           break;\r
648 \r
649         case kern_node:\r
650           cur_v = cur_v + width(p);\r
651           break;\r
652 \r
653         default:\r
654           break;\r
655       }\r
656 \r
657       goto next_p;\r
658 \r
659 fin_rule:\r
660       if (is_running(rule_wd))\r
661         rule_wd = width(this_box);\r
662 \r
663       rule_ht = rule_ht + rule_dp;\r
664       cur_v = cur_v + rule_ht;\r
665 \r
666       if ((rule_ht > 0) && (rule_wd > 0))\r
667       {\r
668         pdf_synch_h();\r
669         pdf_synch_v();\r
670         pdf_dev_set_rule(cur_h, -cur_v, rule_wd, rule_ht);\r
671       }\r
672 \r
673       goto next_p;\r
674 \r
675 move_past:\r
676       cur_v = cur_v + rule_ht;\r
677     }\r
678 \r
679 next_p:\r
680     p = link(p);\r
681   }\r
682 \r
683   prune_movements(save_loc);\r
684   decr(cur_s);\r
685 }\r