OSDN Git Service

new header 'dpx.h'.
[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 "yandytex.h"\r
23 #include "dpx.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     //kpse_init_prog("", 600, NULL, NULL);\r
119     //kpse_set_program_enabled(kpse_pk_format, true, kpse_src_texmf_cnf);\r
120     //pdf_font_set_dpi(600);\r
121     //dpx_delete_old_cache(image_cache_life);\r
122     pdf_set_version(5);\r
123     pdf_set_compression(9);\r
124     pdf_init_fontmaps();\r
125     read_config_file("dvipdfmx.cfg");\r
126     pdf_doc_set_producer("Y&YTeX 2.3.0");\r
127     pdf_doc_set_creator("TeX");\r
128     pdf_files_init();\r
129     pdf_init_device(0.000015202, 2, 0);\r
130     pdf_open_document(pdf_file_name, 0, 595.0, 842.0, 0, 0, (1 << 4));\r
131     spc_exec_at_begin_document();\r
132   }\r
133 \r
134   page_loc = dvi_offset + dvi_ptr;\r
135   pdf_doc_begin_page(1.0, 72.0, 770.0);\r
136   spc_exec_at_begin_page();\r
137 \r
138   last_bop = page_loc;\r
139   cur_v = height(p) + v_offset;\r
140   temp_ptr = p;\r
141 \r
142   if (type(p) == vlist_node)\r
143     pdf_vlist_out();\r
144   else\r
145     pdf_hlist_out();\r
146 \r
147   spc_exec_at_end_page();\r
148   pdf_doc_end_page();\r
149   incr(total_pages);\r
150   cur_s = -1;\r
151 \r
152 done:\r
153   if (tracing_output <= 0)\r
154     print_char(']');\r
155 \r
156   dead_cycles = 0;\r
157   update_terminal();\r
158 \r
159 #ifdef STAT\r
160   if (tracing_stats > 1)\r
161   {\r
162     print_nl("Memory usage before: ");\r
163     print_int(var_used);\r
164     print_char('&');\r
165     print_int(dyn_used);\r
166     print_char(';');\r
167   }\r
168 #endif\r
169 \r
170   flush_node_list(p);\r
171 \r
172 #ifdef STAT\r
173   if (tracing_stats > 1)\r
174   {\r
175     prints(" after: ");\r
176     print_int(var_used);\r
177     print_char('&');\r
178     print_int(dyn_used);\r
179     prints("; still utouched: ");\r
180     print_int(hi_mem_min - lo_mem_max - 1);\r
181     print_ln();\r
182   }\r
183 #endif\r
184 }\r
185 \r
186 void pdf_synch_h (void)\r
187 {\r
188   if (cur_h != dvi_h)\r
189     dvi_h = cur_h;\r
190 }\r
191 \r
192 void pdf_synch_v (void)\r
193 {\r
194   if (cur_v != dvi_v)\r
195     dvi_v = cur_v;\r
196 }\r
197 \r
198 int pdf_get_font_id (internal_font_number f)\r
199 {\r
200   char * sbuf = malloc(length(font_name[f]) + 1);\r
201   int id;\r
202   memset(sbuf, 0, length(font_name[f]) + 1);\r
203   memcpy(sbuf, str_pool + str_start[font_name[f]], length(font_name[f]));    \r
204   id = dvi_locate_font(sbuf, font_size[f]);\r
205   free(sbuf);\r
206 \r
207   return id;\r
208 }\r
209 \r
210 void pdf_hlist_out (void)\r
211 {\r
212   scaled base_line;\r
213   scaled left_edge;\r
214   scaled save_h, save_v;\r
215   pointer this_box;\r
216   // glue_ord g_order;\r
217   int g_order;\r
218   // char g_sign;\r
219   int g_sign;\r
220   pointer p;\r
221   integer save_loc;\r
222   pointer leader_box;\r
223   scaled leader_wd;\r
224   scaled lx;\r
225   boolean outer_doing_leaders;\r
226   scaled edge;\r
227   real glue_temp;\r
228   real cur_glue;\r
229   scaled cur_g;\r
230 \r
231   cur_g = 0;\r
232   cur_glue = 0.0;\r
233   this_box = temp_ptr;\r
234   g_order = glue_order(this_box);\r
235   g_sign = glue_sign(this_box);\r
236   p = list_ptr(this_box);\r
237   incr(cur_s);\r
238 \r
239   if (cur_s > max_push)\r
240     max_push = cur_s;\r
241 \r
242   save_loc = dvi_offset + dvi_ptr;\r
243   base_line = cur_v;\r
244   left_edge = cur_h;\r
245 \r
246   while (p != 0)\r
247 reswitch:\r
248   if (is_char_node(p))\r
249   {\r
250     pdf_synch_h();\r
251     pdf_synch_v();\r
252 \r
253     do\r
254     {\r
255       f = font(p);\r
256       c = character(p);\r
257 \r
258       if (f != dvi_f)\r
259       {\r
260         if (!font_used[f])\r
261         {\r
262           font_used[f] = true;\r
263           font_id[f]   = pdf_get_font_id(f); \r
264         }\r
265 \r
266         dvi_f = f;\r
267       }\r
268 \r
269       char cbuf[2] = {c, 0};\r
270       pdf_dev_set_string(cur_h, -cur_v, cbuf, 1, char_width(f, char_info(f, c)), font_id[dvi_f], 1);\r
271       cur_h = cur_h + char_width(f, char_info(f, c));\r
272       p = link(p);\r
273     } while (!(!is_char_node(p)));\r
274 \r
275     dvi_h = cur_h;\r
276   }\r
277   else\r
278   {\r
279     switch (type(p))\r
280     {\r
281       case hlist_node:\r
282       case vlist_node:\r
283         if (list_ptr(p) == 0)\r
284           cur_h = cur_h + width(p);\r
285         else\r
286         {\r
287           save_h = dvi_h;\r
288           save_v = dvi_v;\r
289           cur_v = base_line + shift_amount(p);\r
290           temp_ptr = p;\r
291           edge = cur_h;\r
292 \r
293           if (type(p) == vlist_node)\r
294             pdf_vlist_out();\r
295           else\r
296             pdf_hlist_out();\r
297 \r
298           dvi_h = save_h;\r
299           dvi_v = save_v;\r
300           cur_h = edge + width(p);\r
301           cur_v = base_line;\r
302         }\r
303         break;\r
304 \r
305       case rule_node:\r
306       {\r
307         rule_ht = height(p);\r
308         rule_dp = depth(p);\r
309         rule_wd = width(p);\r
310         goto fin_rule;\r
311       }\r
312         break;\r
313 \r
314       case whatsit_node:\r
315         out_what(p);\r
316         break;\r
317 \r
318       case glue_node:\r
319       {\r
320         g = glue_ptr(p);\r
321         rule_wd = width(g) - cur_g;\r
322 \r
323         if (g_sign != normal)\r
324         {\r
325           if (g_sign == stretching)\r
326           {\r
327             if (stretch_order(g) == g_order)\r
328             {\r
329               cur_glue = cur_glue + stretch(g);\r
330               vet_glue(glue_set(this_box) * cur_glue);\r
331               cur_g = round(glue_temp);\r
332             }\r
333           }\r
334           else if (shrink_order(g) == g_order)\r
335           {\r
336             cur_glue = cur_glue - shrink(g);\r
337             vet_glue(glue_set(this_box) * cur_glue);\r
338             cur_g = round(glue_temp);\r
339           }\r
340         }\r
341 \r
342         rule_wd = rule_wd + cur_g;\r
343 \r
344         if (subtype(p) >= a_leaders)\r
345         {\r
346           leader_box = leader_ptr(p);\r
347 \r
348           if (type(leader_box) == rule_node)\r
349           {\r
350             rule_ht = height(leader_box);\r
351             rule_dp = depth(leader_box);\r
352             goto fin_rule;\r
353           }\r
354 \r
355           leader_wd = width(leader_box);\r
356 \r
357           if ((leader_wd > 0) && (rule_wd > 0))\r
358           {\r
359             rule_wd = rule_wd + 10;\r
360             edge = cur_h + rule_wd;\r
361             lx = 0;\r
362 \r
363             if (subtype(p) == a_leaders)\r
364             {\r
365               save_h = cur_h;\r
366               cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);\r
367 \r
368               if (cur_h < save_h)\r
369                 cur_h = cur_h + leader_wd;\r
370             }\r
371             else\r
372             {\r
373               lq = rule_wd / leader_wd;\r
374               lr = rule_wd % leader_wd;\r
375 \r
376               if (subtype(p) == c_leaders)\r
377                 cur_h = cur_h + (lr / 2);\r
378               else\r
379               {\r
380                 lx = (2 * lr + lq + 1) / (2 * lq + 2);\r
381                 cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);\r
382               }\r
383             }\r
384 \r
385             while (cur_h + leader_wd <= edge)\r
386             {\r
387               cur_v = base_line + shift_amount(leader_box);\r
388               pdf_synch_v();\r
389               save_v = dvi_v;\r
390               pdf_synch_h();\r
391               save_h = dvi_h;\r
392               temp_ptr = leader_box;\r
393               outer_doing_leaders = doing_leaders;\r
394               doing_leaders = true;\r
395 \r
396               if (type(leader_box) == vlist_node)\r
397                 pdf_vlist_out();\r
398               else\r
399                 pdf_hlist_out();\r
400 \r
401               doing_leaders = outer_doing_leaders;\r
402               dvi_v = save_v;\r
403               dvi_h = save_h;\r
404               cur_v = base_line;\r
405               cur_h = save_h + leader_wd + lx;\r
406             }\r
407 \r
408             cur_h = edge - 10;\r
409             goto next_p;\r
410           }\r
411         }\r
412 \r
413         goto move_past;\r
414       }\r
415         break;\r
416 \r
417       case kern_node:\r
418       case math_node:\r
419         cur_h = cur_h + width(p);\r
420         break;\r
421 \r
422       case ligature_node:\r
423       {\r
424         mem[lig_trick] = mem[lig_char(p)];\r
425         link(lig_trick) = link(p);\r
426         p = lig_trick;\r
427         goto reswitch;\r
428       }\r
429         break;\r
430 \r
431       default:\r
432         break;\r
433     }\r
434 \r
435     goto next_p;\r
436 \r
437 fin_rule:\r
438     if (is_running(rule_ht))\r
439       rule_ht = height(this_box);\r
440 \r
441     if (is_running(rule_dp))\r
442       rule_dp = depth(this_box);\r
443 \r
444     rule_ht = rule_ht + rule_dp;\r
445 \r
446     if ((rule_ht > 0) && (rule_wd > 0))\r
447     {\r
448       pdf_synch_h();\r
449       cur_v = base_line + rule_dp;\r
450       pdf_synch_v();\r
451       pdf_dev_set_rule(dvi_h, dvi_v, rule_wd, rule_ht);\r
452       cur_v = base_line;\r
453       dvi_h = dvi_h + rule_wd;\r
454     }\r
455 \r
456 move_past:\r
457     cur_h = cur_h + rule_wd;\r
458 \r
459 next_p:\r
460     p = link(p);\r
461   }\r
462 \r
463   prune_movements(save_loc);\r
464   decr(cur_s);\r
465 }\r
466 \r
467 void pdf_vlist_out (void)\r
468 {\r
469   scaled left_edge;\r
470   scaled top_edge;\r
471   scaled save_h, save_v;\r
472   pointer this_box;\r
473   // glue_ord g_order;\r
474   int g_order;\r
475   // char g_sign;\r
476   int g_sign;\r
477   pointer p;\r
478   integer save_loc;\r
479   pointer leader_box;\r
480   scaled leader_ht;\r
481   scaled lx;\r
482   boolean outer_doing_leaders;\r
483   scaled edge;\r
484   real glue_temp;\r
485   real cur_glue;\r
486   scaled cur_g;\r
487 \r
488   cur_g = 0;\r
489   cur_glue = 0.0;\r
490   this_box = temp_ptr;\r
491   g_order = glue_order(this_box);\r
492   g_sign = glue_sign(this_box);\r
493   p = list_ptr(this_box);\r
494   incr(cur_s);\r
495 \r
496   if (cur_s > max_push)\r
497     max_push = cur_s;\r
498 \r
499   save_loc = dvi_offset + dvi_ptr;\r
500   left_edge = cur_h;\r
501   cur_v = cur_v - height(this_box);\r
502   top_edge = cur_v;\r
503 \r
504   while (p != 0)\r
505   {\r
506     if (is_char_node(p))\r
507     {\r
508       confusion("vlistout");\r
509       return;\r
510     }\r
511     else\r
512     {\r
513       switch (type(p))\r
514       {\r
515         case hlist_node:\r
516         case vlist_node:\r
517           if (list_ptr(p) == 0)\r
518             cur_v = cur_v + height(p) + depth(p);\r
519           else\r
520           {\r
521             cur_v = cur_v + height(p);\r
522             pdf_synch_v();\r
523             save_h = dvi_h;\r
524             save_v = dvi_v;\r
525             cur_h = left_edge + shift_amount(p);\r
526             temp_ptr = p;\r
527 \r
528             if (type(p) == vlist_node)\r
529               pdf_vlist_out();\r
530             else\r
531               pdf_hlist_out();\r
532 \r
533             dvi_h = save_h;\r
534             dvi_v = save_v;\r
535             cur_v = save_v + depth(p);\r
536             cur_h = left_edge;\r
537           }\r
538           break;\r
539 \r
540         case rule_node:\r
541           {\r
542             rule_ht = height(p);\r
543             rule_dp = depth(p);\r
544             rule_wd = width(p);\r
545             goto fin_rule;\r
546           }\r
547           break;\r
548 \r
549         case whatsit_node:\r
550           out_what(p);\r
551           break;\r
552 \r
553         case glue_node:\r
554           {\r
555             g = glue_ptr(p);\r
556             rule_ht = width(g) - cur_g;\r
557 \r
558             if (g_sign != normal)\r
559             {\r
560               if (g_sign == stretching)\r
561               {\r
562                 if (stretch_order(g) == g_order)\r
563                 {\r
564                   cur_glue = cur_glue + stretch(g);\r
565                   vet_glue(glue_set(this_box) * cur_glue);\r
566                   cur_g = round(glue_temp);\r
567                 }\r
568               }\r
569               else if (shrink_order(g) == g_order)   /* BUG FIX !!! */\r
570               {\r
571                 cur_glue = cur_glue - shrink(g);\r
572                 vet_glue(glue_set(this_box) * cur_glue);\r
573                 cur_g = round(glue_temp);\r
574               }\r
575             }\r
576 \r
577             rule_ht = rule_ht + cur_g;\r
578 \r
579             if (subtype(p) >= a_leaders)\r
580             {\r
581               leader_box = leader_ptr(p);\r
582 \r
583               if (type(leader_box) == rule_node)\r
584               {\r
585                 rule_wd = width(leader_box);\r
586                 rule_dp = 0;\r
587                 goto fin_rule;\r
588               }\r
589 \r
590               leader_ht = height(leader_box) + depth(leader_box);\r
591 \r
592               if ((leader_ht > 0) && (rule_ht > 0))\r
593               {\r
594                 rule_ht = rule_ht + 10;\r
595                 edge = cur_v + rule_ht;\r
596                 lx = 0;\r
597 \r
598                 if (subtype(p) == a_leaders)\r
599                 {\r
600                   save_v = cur_v;\r
601                   cur_v = top_edge + leader_ht * ((cur_v - top_edge) / leader_ht);\r
602 \r
603                   if (cur_v < save_v)\r
604                     cur_v = cur_v + leader_ht;\r
605                 }\r
606                 else\r
607                 {\r
608                   lq = rule_ht / leader_ht;\r
609                   lr = rule_ht % leader_ht;\r
610 \r
611                   if (subtype(p) == c_leaders)\r
612                     cur_v = cur_v + (lr / 2);\r
613                   else\r
614                   {\r
615                     lx = (2 * lr + lq + 1) / (2 * lq + 2);\r
616                     cur_v = cur_v + ((lr - (lq - 1) * lx) / 2);\r
617                   }\r
618                 }\r
619 \r
620                 while (cur_v + leader_ht <= edge)\r
621                 {\r
622                   cur_h = left_edge + shift_amount(leader_box);\r
623                   pdf_synch_h();\r
624                   save_h = dvi_h;\r
625                   cur_v = cur_v + height(leader_box);\r
626                   pdf_synch_v();\r
627                   save_v = dvi_v;\r
628                   temp_ptr = leader_box;\r
629                   outer_doing_leaders = doing_leaders;\r
630                   doing_leaders = true;\r
631 \r
632                   if (type(leader_box) == vlist_node)\r
633                     pdf_vlist_out();\r
634                   else\r
635                     pdf_hlist_out();\r
636 \r
637                   doing_leaders = outer_doing_leaders;\r
638                   dvi_v = save_v;\r
639                   dvi_h = save_h;\r
640                   cur_h = left_edge;\r
641                   cur_v = save_v - height(leader_box) + leader_ht + lx;\r
642                 }\r
643 \r
644                 cur_v = edge - 10;\r
645                 goto next_p;\r
646               }\r
647             }\r
648 \r
649             goto move_past;\r
650           }\r
651           break;\r
652 \r
653         case kern_node:\r
654           cur_v = cur_v + width(p);\r
655           break;\r
656 \r
657         default:\r
658           break;\r
659       }\r
660 \r
661       goto next_p;\r
662 \r
663 fin_rule:\r
664       if (is_running(rule_wd))\r
665         rule_wd = width(this_box);\r
666 \r
667       rule_ht = rule_ht + rule_dp;\r
668       cur_v = cur_v + rule_ht;\r
669 \r
670       if ((rule_ht > 0) && (rule_wd > 0))\r
671       {\r
672         pdf_synch_h();\r
673         pdf_synch_v();\r
674         pdf_dev_set_rule(cur_h, -cur_v, rule_wd, rule_ht);\r
675       }\r
676 \r
677       goto next_p;\r
678 \r
679 move_past:\r
680       cur_v = cur_v + rule_ht;\r
681     }\r
682 \r
683 next_p:\r
684     p = link(p);\r
685   }\r
686 \r
687   prune_movements(save_loc);\r
688   decr(cur_s);\r
689 }\r