OSDN Git Service

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