OSDN Git Service

3a866dc991ae1d92fa8cb7b0a51a8e1f514df797
[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       {\r
268         pdf_rect rect;\r
269         pdf_dev_set_rect(&rect, cur_h, -dvi_v,\r
270           char_width (f, char_info(f, c)),\r
271           char_height(f, height_depth(char_info(f, c))),\r
272           char_depth (f, height_depth(char_info(f, c))));\r
273         pdf_doc_expand_box(&rect);\r
274       }\r
275       cur_h = cur_h + char_width(f, char_info(f, c));\r
276       p = link(p);\r
277     } while (!(!is_char_node(p)));\r
278 \r
279     dvi_h = cur_h;\r
280   }\r
281   else\r
282   {\r
283     switch (type(p))\r
284     {\r
285       case hlist_node:\r
286       case vlist_node:\r
287         if (list_ptr(p) == 0)\r
288           cur_h = cur_h + width(p);\r
289         else\r
290         {\r
291           save_h = dvi_h;\r
292           save_v = dvi_v;\r
293           cur_v = base_line + shift_amount(p);\r
294           temp_ptr = p;\r
295           edge = cur_h;\r
296 \r
297           if (type(p) == vlist_node)\r
298             pdf_vlist_out();\r
299           else\r
300             pdf_hlist_out();\r
301 \r
302           dvi_h = save_h;\r
303           dvi_v = save_v;\r
304           cur_h = edge + width(p);\r
305           cur_v = base_line;\r
306         }\r
307         break;\r
308 \r
309       case rule_node:\r
310       {\r
311         rule_ht = height(p);\r
312         rule_dp = depth(p);\r
313         rule_wd = width(p);\r
314         goto fin_rule;\r
315       }\r
316         break;\r
317 \r
318       case whatsit_node:\r
319         out_what(p);\r
320         break;\r
321 \r
322       case glue_node:\r
323       {\r
324         g = glue_ptr(p);\r
325         rule_wd = width(g) - cur_g;\r
326 \r
327         if (g_sign != normal)\r
328         {\r
329           if (g_sign == stretching)\r
330           {\r
331             if (stretch_order(g) == g_order)\r
332             {\r
333               cur_glue = cur_glue + stretch(g);\r
334               vet_glue(glue_set(this_box) * cur_glue);\r
335               cur_g = round(glue_temp);\r
336             }\r
337           }\r
338           else if (shrink_order(g) == g_order)\r
339           {\r
340             cur_glue = cur_glue - shrink(g);\r
341             vet_glue(glue_set(this_box) * cur_glue);\r
342             cur_g = round(glue_temp);\r
343           }\r
344         }\r
345 \r
346         rule_wd = rule_wd + cur_g;\r
347 \r
348         if (subtype(p) >= a_leaders)\r
349         {\r
350           leader_box = leader_ptr(p);\r
351 \r
352           if (type(leader_box) == rule_node)\r
353           {\r
354             rule_ht = height(leader_box);\r
355             rule_dp = depth(leader_box);\r
356             goto fin_rule;\r
357           }\r
358 \r
359           leader_wd = width(leader_box);\r
360 \r
361           if ((leader_wd > 0) && (rule_wd > 0))\r
362           {\r
363             rule_wd = rule_wd + 10;\r
364             edge = cur_h + rule_wd;\r
365             lx = 0;\r
366 \r
367             if (subtype(p) == a_leaders)\r
368             {\r
369               save_h = cur_h;\r
370               cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);\r
371 \r
372               if (cur_h < save_h)\r
373                 cur_h = cur_h + leader_wd;\r
374             }\r
375             else\r
376             {\r
377               lq = rule_wd / leader_wd;\r
378               lr = rule_wd % leader_wd;\r
379 \r
380               if (subtype(p) == c_leaders)\r
381                 cur_h = cur_h + (lr / 2);\r
382               else\r
383               {\r
384                 lx = (2 * lr + lq + 1) / (2 * lq + 2);\r
385                 cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);\r
386               }\r
387             }\r
388 \r
389             while (cur_h + leader_wd <= edge)\r
390             {\r
391               cur_v = base_line + shift_amount(leader_box);\r
392               pdf_synch_v();\r
393               save_v = dvi_v;\r
394               pdf_synch_h();\r
395               save_h = dvi_h;\r
396               temp_ptr = leader_box;\r
397               outer_doing_leaders = doing_leaders;\r
398               doing_leaders = true;\r
399 \r
400               if (type(leader_box) == vlist_node)\r
401                 pdf_vlist_out();\r
402               else\r
403                 pdf_hlist_out();\r
404 \r
405               doing_leaders = outer_doing_leaders;\r
406               dvi_v = save_v;\r
407               dvi_h = save_h;\r
408               cur_v = base_line;\r
409               cur_h = save_h + leader_wd + lx;\r
410             }\r
411 \r
412             cur_h = edge - 10;\r
413             goto next_p;\r
414           }\r
415         }\r
416 \r
417         goto move_past;\r
418       }\r
419         break;\r
420 \r
421       case kern_node:\r
422       case math_node:\r
423         cur_h = cur_h + width(p);\r
424         break;\r
425 \r
426       case ligature_node:\r
427       {\r
428         mem[lig_trick] = mem[lig_char(p)];\r
429         link(lig_trick) = link(p);\r
430         p = lig_trick;\r
431         goto reswitch;\r
432       }\r
433         break;\r
434 \r
435       default:\r
436         break;\r
437     }\r
438 \r
439     goto next_p;\r
440 \r
441 fin_rule:\r
442     if (is_running(rule_ht))\r
443       rule_ht = height(this_box);\r
444 \r
445     if (is_running(rule_dp))\r
446       rule_dp = depth(this_box);\r
447 \r
448     rule_ht = rule_ht + rule_dp;\r
449 \r
450     if ((rule_ht > 0) && (rule_wd > 0))\r
451     {\r
452       pdf_synch_h();\r
453       cur_v = base_line + rule_dp;\r
454       pdf_synch_v();\r
455       pdf_dev_set_rule(dvi_h, -dvi_v, rule_wd, rule_ht);\r
456       cur_v = base_line;\r
457       dvi_h = dvi_h + rule_wd;\r
458     }\r
459 \r
460 move_past:\r
461     cur_h = cur_h + rule_wd;\r
462 \r
463 next_p:\r
464     p = link(p);\r
465   }\r
466 \r
467   prune_movements(save_loc);\r
468   decr(cur_s);\r
469 }\r
470 \r
471 void pdf_vlist_out (void)\r
472 {\r
473   scaled left_edge;\r
474   scaled top_edge;\r
475   scaled save_h, save_v;\r
476   pointer this_box;\r
477   // glue_ord g_order;\r
478   int g_order;\r
479   // char g_sign;\r
480   int g_sign;\r
481   pointer p;\r
482   integer save_loc;\r
483   pointer leader_box;\r
484   scaled leader_ht;\r
485   scaled lx;\r
486   boolean outer_doing_leaders;\r
487   scaled edge;\r
488   real glue_temp;\r
489   real cur_glue;\r
490   scaled cur_g;\r
491 \r
492   cur_g = 0;\r
493   cur_glue = 0.0;\r
494   this_box = temp_ptr;\r
495   g_order = glue_order(this_box);\r
496   g_sign = glue_sign(this_box);\r
497   p = list_ptr(this_box);\r
498   incr(cur_s);\r
499 \r
500   if (cur_s > max_push)\r
501     max_push = cur_s;\r
502 \r
503   save_loc = dvi_offset + dvi_ptr;\r
504   left_edge = cur_h;\r
505   cur_v = cur_v - height(this_box);\r
506   top_edge = cur_v;\r
507 \r
508   while (p != 0)\r
509   {\r
510     if (is_char_node(p))\r
511     {\r
512       confusion("vlistout");\r
513       return;\r
514     }\r
515     else\r
516     {\r
517       switch (type(p))\r
518       {\r
519         case hlist_node:\r
520         case vlist_node:\r
521           if (list_ptr(p) == 0)\r
522             cur_v = cur_v + height(p) + depth(p);\r
523           else\r
524           {\r
525             cur_v = cur_v + height(p);\r
526             pdf_synch_v();\r
527             save_h = dvi_h;\r
528             save_v = dvi_v;\r
529             cur_h = left_edge + shift_amount(p);\r
530             temp_ptr = p;\r
531 \r
532             if (type(p) == vlist_node)\r
533               pdf_vlist_out();\r
534             else\r
535               pdf_hlist_out();\r
536 \r
537             dvi_h = save_h;\r
538             dvi_v = save_v;\r
539             cur_v = save_v + depth(p);\r
540             cur_h = left_edge;\r
541           }\r
542           break;\r
543 \r
544         case rule_node:\r
545           {\r
546             rule_ht = height(p);\r
547             rule_dp = depth(p);\r
548             rule_wd = width(p);\r
549             goto fin_rule;\r
550           }\r
551           break;\r
552 \r
553         case whatsit_node:\r
554           out_what(p);\r
555           break;\r
556 \r
557         case glue_node:\r
558           {\r
559             g = glue_ptr(p);\r
560             rule_ht = width(g) - cur_g;\r
561 \r
562             if (g_sign != normal)\r
563             {\r
564               if (g_sign == stretching)\r
565               {\r
566                 if (stretch_order(g) == g_order)\r
567                 {\r
568                   cur_glue = cur_glue + stretch(g);\r
569                   vet_glue(glue_set(this_box) * cur_glue);\r
570                   cur_g = round(glue_temp);\r
571                 }\r
572               }\r
573               else if (shrink_order(g) == g_order)   /* BUG FIX !!! */\r
574               {\r
575                 cur_glue = cur_glue - shrink(g);\r
576                 vet_glue(glue_set(this_box) * cur_glue);\r
577                 cur_g = round(glue_temp);\r
578               }\r
579             }\r
580 \r
581             rule_ht = rule_ht + cur_g;\r
582 \r
583             if (subtype(p) >= a_leaders)\r
584             {\r
585               leader_box = leader_ptr(p);\r
586 \r
587               if (type(leader_box) == rule_node)\r
588               {\r
589                 rule_wd = width(leader_box);\r
590                 rule_dp = 0;\r
591                 goto fin_rule;\r
592               }\r
593 \r
594               leader_ht = height(leader_box) + depth(leader_box);\r
595 \r
596               if ((leader_ht > 0) && (rule_ht > 0))\r
597               {\r
598                 rule_ht = rule_ht + 10;\r
599                 edge = cur_v + rule_ht;\r
600                 lx = 0;\r
601 \r
602                 if (subtype(p) == a_leaders)\r
603                 {\r
604                   save_v = cur_v;\r
605                   cur_v = top_edge + leader_ht * ((cur_v - top_edge) / leader_ht);\r
606 \r
607                   if (cur_v < save_v)\r
608                     cur_v = cur_v + leader_ht;\r
609                 }\r
610                 else\r
611                 {\r
612                   lq = rule_ht / leader_ht;\r
613                   lr = rule_ht % leader_ht;\r
614 \r
615                   if (subtype(p) == c_leaders)\r
616                     cur_v = cur_v + (lr / 2);\r
617                   else\r
618                   {\r
619                     lx = (2 * lr + lq + 1) / (2 * lq + 2);\r
620                     cur_v = cur_v + ((lr - (lq - 1) * lx) / 2);\r
621                   }\r
622                 }\r
623 \r
624                 while (cur_v + leader_ht <= edge)\r
625                 {\r
626                   cur_h = left_edge + shift_amount(leader_box);\r
627                   pdf_synch_h();\r
628                   save_h = dvi_h;\r
629                   cur_v = cur_v + height(leader_box);\r
630                   pdf_synch_v();\r
631                   save_v = dvi_v;\r
632                   temp_ptr = leader_box;\r
633                   outer_doing_leaders = doing_leaders;\r
634                   doing_leaders = true;\r
635 \r
636                   if (type(leader_box) == vlist_node)\r
637                     pdf_vlist_out();\r
638                   else\r
639                     pdf_hlist_out();\r
640 \r
641                   doing_leaders = outer_doing_leaders;\r
642                   dvi_v = save_v;\r
643                   dvi_h = save_h;\r
644                   cur_h = left_edge;\r
645                   cur_v = save_v - height(leader_box) + leader_ht + lx;\r
646                 }\r
647 \r
648                 cur_v = edge - 10;\r
649                 goto next_p;\r
650               }\r
651             }\r
652 \r
653             goto move_past;\r
654           }\r
655           break;\r
656 \r
657         case kern_node:\r
658           cur_v = cur_v + width(p);\r
659           break;\r
660 \r
661         default:\r
662           break;\r
663       }\r
664 \r
665       goto next_p;\r
666 \r
667 fin_rule:\r
668       if (is_running(rule_wd))\r
669         rule_wd = width(this_box);\r
670 \r
671       rule_ht = rule_ht + rule_dp;\r
672       cur_v = cur_v + rule_ht;\r
673 \r
674       if ((rule_ht > 0) && (rule_wd > 0))\r
675       {\r
676         pdf_synch_h();\r
677         pdf_synch_v();\r
678         pdf_dev_set_rule(dvi_h, -dvi_v, rule_wd, rule_ht);\r
679       }\r
680 \r
681       goto next_p;\r
682 \r
683 move_past:\r
684       cur_v = cur_v + rule_ht;\r
685     }\r
686 \r
687 next_p:\r
688     p = link(p);\r
689   }\r
690 \r
691   prune_movements(save_loc);\r
692   decr(cur_s);\r
693 }\r