OSDN Git Service

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