1 /* Copyright 2014 Clerk Ma
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.
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.
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
22 bool pdf_doing_string;
24 static integer ten_pow[10] =
40 HPDF_Font yandy_font[1024];
41 tree *avl_tree = NULL;
49 int tfm_cmp(void * a, void * b)
51 char * aa = ((struct tfm_map *) (a))->tfm_name;
52 char * bb = ((struct tfm_map *) (b))->tfm_name;
54 return (strcmp(aa, bb)) ;
57 void tfm_print(void *d)
59 struct tfm_map * dd = (struct tfm_map *) d;
62 printf("{ %s => %d }\n", dd->tfm_name, dd->key);
65 void tfm_delete(void *d)
67 struct tfm_map *dd = (struct tfm_map *) d;
75 void tfm_copy(void *src, void *dst)
77 struct tfm_map *s = (struct tfm_map *) src;
78 struct tfm_map *d = (struct tfm_map *) dst;
79 d->tfm_name = s->tfm_name;
83 void init_tfm_map(void)
85 avl_tree = init_dictionnary(tfm_cmp, tfm_print, tfm_delete, tfm_copy);
88 void free_tfm_map(void)
90 delete_tree(avl_tree);
93 int insert_font_index(char * name)
97 nn.key = avl_tree->count + 1;
99 return insert_elmt(avl_tree, &nn, sizeof(struct tfm_map));
102 int get_font_index(char * name)
109 if (is_present(avl_tree, &nn))
111 if (get_data(avl_tree, &nn, sizeof(struct tfm_map)))
120 void pdf_error(const char * t, const char * p)
122 normalize_selector();
123 print_err("Y&Y TeX error");
137 char * pdf_char_to_string(unsigned char i)
139 char * str = (char *) malloc(2);
144 // output one char: normal.
145 void pdf_out(unsigned char i)
147 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
148 HPDF_Stream_WriteChar(attr->stream, i);
150 // octal number: 032, 009 etc.
151 void pdf_print_octal(integer s)
153 char buf[HPDF_INT_LEN + 1];
154 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
155 sprintf(buf, "%03o", s);
156 HPDF_Stream_Write(attr->stream, (HPDF_BYTE *)buf, strlen(buf));
158 // output one char: normal or octal.
159 void pdf_print_char(unsigned char s)
161 // 32 = '', 92 = '\', 40 = '(', 41 = ')'
162 if ((s <= 32) || (s == 92) || (s == 40) || (s == 41) || (s > 127))
172 // equivlent: pdf_print in pdfTeX.
173 void pdf_print_string(char * s)
175 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
176 HPDF_Stream_WriteStr(attr->stream, s);
178 // print one integer value: signed or unsigned.
179 void pdf_print_int(int s)
181 char buf[HPDF_INT_LEN + 1];
182 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
183 char* p = HPDF_IToA(buf, s, buf + HPDF_INT_LEN);
184 HPDF_Stream_Write(attr->stream, (HPDF_BYTE *)buf, (HPDF_UINT)(p - buf));
186 // translate sp to bp.
187 HPDF_REAL pdf_sp_to_bp(scaled s)
189 // 1 bp = 65781.76 sp
190 return (HPDF_REAL) s / 65781.76;
192 // divides scaled s by scaled m.
193 scaled divide_scaled(scaled s, scaled m, integer dd)
213 pdf_error("arithmetic", "divided by zero");
214 else if (m >= 0x7FFFFFFF / 10)
215 pdf_error("arithmetic", "number too big");
220 for (i = 1; i <= dd; i++)
222 q = 10 * q + (10 * r) / m;
232 scaled_out = sign * (s - (r / ten_pow[dd]));
235 scaled round_xn_over_d(scaled x, integer n, integer d)
238 nonnegative_integer t, u, v;
248 t = (x % 32767L) * n;
249 u = (x / 32768L) * n + (t / 32768L);
250 v = (u % d) * 32768L + (t % 32768L);
255 u = 32768L * (u / d) + (v / d);
267 // advance char width
268 void adv_char_width(internal_font_number f, eight_bits c)
273 w = char_width(f, char_info(f, c));
274 divide_scaled(w, font_size[f], 4);
275 pdf_delta_h = pdf_delta_h + scaled_out;
278 void pdf_print(integer m, integer d)
286 pdf_print_int(m / ten_pow[d]);
294 while (m < ten_pow[d])
306 // end the current string
307 void pdf_end_string(void)
309 if (pdf_doing_string)
311 pdf_print_string(")] TJ\012");
312 pdf_doing_string = false;
315 // begin to draw a string
316 void pdf_begin_string(internal_font_number f)
318 scaled s_out, v, v_out;
330 s = divide_scaled(cur_h - pdf_delta_h, font_size[f], 3);
333 if (abs(s) < 0100000)
335 s_out = divide_scaled(round_xn_over_d(cur_h - pdf_delta_h, 1000, 1000),
342 // if (cur_v - pdf_v >= )
344 // end a text section.
350 HPDF_Page_EndText(yandy_page);
351 pdf_doing_text = false;
355 void pdf_set_rule(scaled x, scaled y, scaled w, scaled h)
358 void pdf_error_handler (HPDF_STATUS error_no, HPDF_STATUS detail_no, void * user_data)
360 printf ("Y&Y TeX error: error_no=%04X, detail_no=%u\n",
362 (HPDF_UINT)detail_no);
363 longjmp(jumpbuffer, 1);
366 void pdf_font_def(internal_font_number f)
370 const char * fnt_name;
375 memcpy(buffer, (const char *) str_pool + str_start[font_name[f]], length(font_name[f]));
376 buffer[length(font_name[f])] = '\0';
378 k = get_font_index(buffer);
379 printf("DEF: %s--%d.\n", buffer, k);
383 afm_name = kpse_find_file(strcat(strdup(buffer), ".afm"), kpse_afm_format, 1);
384 printf("path: %s.\n", afm_name);
385 pfb_name = kpse_find_file(strcat(strdup(buffer), ".pfb"), kpse_type1_format, 1);
387 if (afm_name != NULL && pfb_name != NULL)
389 k = insert_font_index(buffer);
390 fnt_name = HPDF_LoadType1FontFromFile (yandy_pdf, afm_name, pfb_name);
391 yandy_font[k] = HPDF_GetFont(yandy_pdf, fnt_name, NULL);
395 HPDF_Page_SetFontAndSize(yandy_page, yandy_font[0], (font_size[f] / 65535));
398 void pdf_ship_out(halfword p)
402 if (tracing_output > 0)
406 print_string("Completed box being shipped out");
409 if (term_offset > max_print_line - 9)
411 else if ((term_offset > 0) || (file_offset > 0))
417 while((count(j) == 0) && (j > 0))
420 for (k = 0; k <= j; k++)
432 if (tracing_output > 0)
437 end_diagnostic(true);
440 if ((height(p) > max_dimen) || (depth(p) > max_dimen) ||
441 (height(p) + depth(p) + v_offset > max_dimen) ||
442 (width(p) + h_offset > max_dimen))
444 print_err("Huge page cannot be shipped out");
445 help2("The page just created is more than 18 feet tall or",
446 "more than 18 feet wide, so I suspect something went wrong.");
449 if (tracing_output <= 0)
452 print_nl("The following box has been deleted:");
454 end_diagnostic(true);
460 if (height(p) + depth(p) + v_offset > max_v)
461 max_v = height(p) + depth(p) + v_offset;
463 if (width(p) + h_offset > max_h)
464 max_h = width(p) + h_offset;
471 if (output_file_name == 0)
476 pack_job_name(".pdf");
478 while(!b_open_out(pdf_file))
480 prompt_file_name("file name for output", ".pdf");
483 output_file_name = b_make_name_string(pdf_file);
486 if (total_pages == 0)
489 yandy_pdf = HPDF_New (pdf_error_handler, NULL);
490 HPDF_SetCompressionMode (yandy_pdf, HPDF_COMP_ALL);
491 yandy_pdf -> pdf_version = HPDF_VER_17;
492 HPDF_SetInfoAttr(yandy_pdf, HPDF_INFO_PRODUCER, "Y&Y TeX");
493 yandy_font[0] = HPDF_GetFont (yandy_pdf, "Times-Roman", NULL);
496 yandy_page = HPDF_AddPage (yandy_pdf);
497 HPDF_Page_SetFontAndSize(yandy_page, yandy_font[0], 10);
498 HPDF_Page_SetSize (yandy_page, HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);
500 cur_v = height(p) + v_offset;
503 if (type(p) == vlist_node)
511 if (tracing_output <= 0)
524 void pdf_hlist_out (void)
528 scaled save_h, save_v;
530 /* glue_ord g_order; */
531 int g_order; /* 95/Jan/7 */
533 int g_sign; /* 95/Jan/7 */
539 bool outer_doing_leaders;
548 g_order = glue_order(this_box);
549 g_sign = glue_sign(this_box);
550 p = list_ptr(this_box);
575 HPDF_Page_BeginText(yandy_page);HPDF_Page_SetFontAndSize(yandy_page, yandy_font[0], 10);
576 HPDF_Page_MoveTextPos(yandy_page, pdf_sp_to_bp(cur_h) + 72, (841.89 - (pdf_sp_to_bp(cur_v) + 72)));
577 HPDF_Page_ShowText(yandy_page, pdf_char_to_string(c));
578 HPDF_Page_EndText(yandy_page);
579 cur_h = cur_h + char_width(f, char_info(f, c));
582 while(((p >= hi_mem_min)));
592 if (list_ptr(p) == 0)
593 cur_h = cur_h + width(p);
598 cur_v = base_line + shift_amount(p);
602 if (type(p) == vlist_node)
609 cur_h = edge + width(p);
630 rule_wd = width(g) - cur_g;
632 if (g_sign != normal)
634 if (g_sign == stretching)
636 if (stretch_order(g) == g_order)
638 cur_glue = cur_glue + stretch(g);
639 glue_temp = glue_set(this_box) * cur_glue;
641 if (glue_temp > 1000000000.0)
642 glue_temp = 1000000000.0;
643 else if (glue_temp < -1000000000.0)
644 glue_temp = -1000000000.0;
646 cur_g = round(glue_temp);
649 else if (shrink_order(g) == g_order)
651 cur_glue = cur_glue - shrink(g);
652 glue_temp = glue_set(this_box) * cur_glue;
654 if (glue_temp > 1000000000.0)
655 glue_temp = 1000000000.0;
656 else if (glue_temp < -1000000000.0)
657 glue_temp = -1000000000.0;
659 cur_g = round(glue_temp);
663 rule_wd = rule_wd + cur_g;
665 if (subtype(p) >= a_leaders)
667 leader_box = leader_ptr(p);
669 if (type(leader_box) == rule_node)
671 rule_ht = height(leader_box);
672 rule_dp = depth(leader_box);
676 leader_wd = width(leader_box);
678 if ((leader_wd > 0) && (rule_wd > 0))
680 rule_wd = rule_wd + 10;
681 edge = cur_h + rule_wd;
684 if (subtype(p) == a_leaders)
687 cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);
690 cur_h = cur_h + leader_wd;
694 lq = rule_wd / leader_wd;
695 lr = rule_wd % leader_wd;
697 if (subtype(p) == c_leaders)
698 cur_h = cur_h + (lr / 2);
701 lx =(2 * lr + lq + 1) / (2 * lq + 2);
702 cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);
706 while (cur_h + leader_wd <= edge)
708 cur_v = base_line + shift_amount(leader_box);
715 temp_ptr = leader_box;
716 outer_doing_leaders = doing_leaders;
717 doing_leaders = true;
719 if (type(leader_box) == vlist_node)
724 doing_leaders = outer_doing_leaders;
728 cur_h = save_h + leader_wd + lx;
742 cur_h = cur_h + width(p);
747 mem[lig_trick] = mem[lig_char(p)];
748 link(lig_trick) = link(p);
760 if ((rule_ht == -1073741824L)) /* - 2^30 */
761 rule_ht = height(this_box);
763 if ((rule_dp == -1073741824L)) /* - 2^30 */
764 rule_dp = depth(this_box);
766 rule_ht = rule_ht + rule_dp;
768 if ((rule_ht > 0) && (rule_wd > 0))
770 cur_v = base_line + rule_dp;
771 HPDF_Page_SetLineWidth(yandy_page, rule_ht / 65535);
772 HPDF_Page_MoveTo (yandy_page, (cur_h / 65535 + 72), (841.89 - cur_v / 65535 - 72));
773 HPDF_Page_LineTo (yandy_page, (cur_h / 65535 + 72 + rule_wd / 65535), (841.89 - cur_v / 65535 - 72));
774 HPDF_Page_Stroke (yandy_page);
776 dvi_h = dvi_h + rule_wd;
779 cur_h = cur_h + rule_wd;
786 /* following needs access to dvi_buf=zdvibuf see coerce.h */
788 void pdf_vlist_out (void)
792 scaled save_h, save_v;
794 /* glue_ord g_order; */
795 int g_order; /* 95/Jan/7 */
797 int g_sign; /* 95/Jan/7 */
803 bool outer_doing_leaders;
812 g_order = glue_order(this_box);
813 g_sign = glue_sign(this_box);
814 p = list_ptr(this_box);
818 cur_v = cur_v - height(this_box);
823 if ((p >= hi_mem_min))
825 confusion("vlistout");
826 return; // abort_flag set
834 if (list_ptr(p) == 0)
835 cur_v = cur_v + height(p) + depth(p);
838 cur_v = cur_v + height(p);
843 cur_h = left_edge + shift_amount(p);
846 if (type(p) == vlist_node)
853 cur_v = save_v + depth(p);
874 rule_ht = width(g) - cur_g;
876 if (g_sign != normal)
878 if (g_sign == stretching)
880 if (stretch_order(g) == g_order)
882 cur_glue = cur_glue + stretch(g);
883 glue_temp = glue_set(this_box) * cur_glue;
885 if (glue_temp > 1000000000.0)
886 glue_temp = 1000000000.0;
887 else if (glue_temp < -1000000000.0)
888 glue_temp = -1000000000.0;
890 cur_g = round(glue_temp);
893 else if (shrink_order(g) == g_order) /* BUG FIX !!! */
895 cur_glue = cur_glue - shrink(g);
896 glue_temp = glue_set(this_box) * cur_glue;
898 if (glue_temp > 1000000000.0)
899 glue_temp = 1000000000.0;
900 else if (glue_temp < -1000000000.0)
901 glue_temp = -1000000000.0;
903 cur_g = round(glue_temp);
907 rule_ht = rule_ht + cur_g;
909 if (subtype(p) >= a_leaders)
911 leader_box = leader_ptr(p);
913 if (type(leader_box) == rule_node)
915 rule_wd = width(leader_box);
920 leader_ht = height(leader_box) + depth(leader_box);
922 if ((leader_ht > 0) && (rule_ht > 0))
924 rule_ht = rule_ht + 10;
925 edge = cur_v + rule_ht;
928 if (subtype(p) == a_leaders)
931 cur_v = top_edge + leader_ht * ((cur_v - top_edge) / leader_ht);
934 cur_v = cur_v + leader_ht;
938 lq = rule_ht / leader_ht;
939 lr = rule_ht % leader_ht;
941 if (subtype(p) == c_leaders)
942 cur_v = cur_v + (lr / 2);
945 lx = (2 * lr + lq + 1) / (2 * lq + 2);
946 cur_v = cur_v + ((lr - (lq - 1) * lx) / 2);
950 while (cur_v + leader_ht <= edge)
952 cur_h = left_edge + shift_amount(leader_box);
956 cur_v = cur_v + height(leader_box);
960 temp_ptr = leader_box;
961 outer_doing_leaders = doing_leaders;
962 doing_leaders = true;
964 if (type(leader_box) == vlist_node)
969 doing_leaders = outer_doing_leaders;
973 cur_v = save_v - height(leader_box) + leader_ht + lx;
986 cur_v = cur_v + width(p);
994 if ((rule_wd == -1073741824L)) /* -2^30 */
995 rule_wd = width(this_box);
997 rule_ht = rule_ht + rule_dp;
998 cur_v = cur_v + rule_ht;
1000 if ((rule_ht > 0) && (rule_wd > 0))
1002 HPDF_Page_SetLineWidth(yandy_page, rule_ht / 65535);
1003 HPDF_Page_MoveTo(yandy_page, (cur_h / 65535 + 72), (841.89 - cur_v / 65535 - 72));
1004 HPDF_Page_LineTo(yandy_page, (cur_h / 65535 + 72 + rule_wd / 65535), (841.89 - cur_v / 65535 - 72));
1005 HPDF_Page_Stroke(yandy_page);
1010 cur_v = cur_v + rule_ht;