OSDN Git Service

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