OSDN Git Service

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