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)
369 const char * fnt_name;
374 memcpy(buffer, (const char *) str_pool + str_start[font_name[f]], length(font_name[f]));
375 buffer[length(font_name[f])] = '\0';
377 k = get_font_index(buffer);
378 printf("DEF: %s--%d.\n", buffer, k);
382 afm_name = kpse_find_file(strcat(strdup(buffer), ".afm"), kpse_afm_format, 1);
383 printf("path: %s.\n", afm_name);
384 pfb_name = kpse_find_file(strcat(strdup(buffer), ".pfb"), kpse_type1_format, 1);
386 if (afm_name != NULL && pfb_name != NULL)
388 k = insert_font_index(buffer);
389 fnt_name = HPDF_LoadType1FontFromFile (yandy_pdf, afm_name, pfb_name);
390 yandy_font[k] = HPDF_GetFont(yandy_pdf, fnt_name, NULL);
394 HPDF_Page_SetFontAndSize(yandy_page, yandy_font[k], (font_size[f] / 65535));
397 void pdf_ship_out(halfword p)
401 if (tracing_output > 0)
405 print_string("Completed box being shipped out");
408 if (term_offset > max_print_line - 9)
410 else if ((term_offset > 0) || (file_offset > 0))
416 while((count(j) == 0) && (j > 0))
419 for (k = 0; k <= j; k++)
431 if (tracing_output > 0)
436 end_diagnostic(true);
439 if ((height(p) > max_dimen) || (depth(p) > max_dimen) ||
440 (height(p) + depth(p) + v_offset > max_dimen) ||
441 (width(p) + h_offset > max_dimen))
443 print_err("Huge page cannot be shipped out");
444 help2("The page just created is more than 18 feet tall or",
445 "more than 18 feet wide, so I suspect something went wrong.");
448 if (tracing_output <= 0)
451 print_nl("The following box has been deleted:");
453 end_diagnostic(true);
459 if (height(p) + depth(p) + v_offset > max_v)
460 max_v = height(p) + depth(p) + v_offset;
462 if (width(p) + h_offset > max_h)
463 max_h = width(p) + h_offset;
470 if (output_file_name == 0)
475 pack_job_name(".pdf");
477 while(!b_open_out(pdf_file))
479 prompt_file_name("file name for output", ".pdf");
482 output_file_name = b_make_name_string(pdf_file);
485 if (total_pages == 0)
488 yandy_pdf = HPDF_New (pdf_error_handler, NULL);
489 HPDF_SetCompressionMode (yandy_pdf, HPDF_COMP_ALL);
490 yandy_pdf -> pdf_version = HPDF_VER_17;
491 HPDF_SetInfoAttr(yandy_pdf, HPDF_INFO_PRODUCER, "Y&Y TeX");
492 yandy_font[0] = HPDF_GetFont (yandy_pdf, "Times-Roman", NULL);
495 yandy_page = HPDF_AddPage (yandy_pdf);
496 HPDF_Page_SetSize (yandy_page, HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);
498 cur_v = height(p) + v_offset;
501 if (type(p) == vlist_node)
509 if (tracing_output <= 0)
522 void pdf_hlist_out (void)
526 scaled save_h, save_v;
528 /* glue_ord g_order; */
529 int g_order; /* 95/Jan/7 */
531 int g_sign; /* 95/Jan/7 */
537 bool outer_doing_leaders;
546 g_order = glue_order(this_box);
547 g_sign = glue_sign(this_box);
548 p = list_ptr(this_box);
575 HPDF_Page_SetFontAndSize (yandy_page, yandy_font[dvi_f], 10);
576 HPDF_Page_BeginText(yandy_page);
577 HPDF_Page_MoveTextPos(yandy_page, pdf_sp_to_bp(cur_h) + 72, (841.89 - (pdf_sp_to_bp(cur_v) + 72)));
578 HPDF_Page_ShowText(yandy_page, pdf_char_to_string(c));
579 HPDF_Page_EndText(yandy_page);
580 cur_h = cur_h + char_width(f, char_info(f, c));
583 while(((p >= hi_mem_min)));
593 if (list_ptr(p) == 0)
594 cur_h = cur_h + width(p);
599 cur_v = base_line + shift_amount(p);
603 if (type(p) == vlist_node)
610 cur_h = edge + width(p);
631 rule_wd = width(g) - cur_g;
633 if (g_sign != normal)
635 if (g_sign == stretching)
637 if (stretch_order(g) == g_order)
639 cur_glue = cur_glue + stretch(g);
640 glue_temp = glue_set(this_box) * cur_glue;
642 if (glue_temp > 1000000000.0)
643 glue_temp = 1000000000.0;
644 else if (glue_temp < -1000000000.0)
645 glue_temp = -1000000000.0;
647 cur_g = round(glue_temp);
650 else if (shrink_order(g) == g_order)
652 cur_glue = cur_glue - shrink(g);
653 glue_temp = glue_set(this_box) * cur_glue;
655 if (glue_temp > 1000000000.0)
656 glue_temp = 1000000000.0;
657 else if (glue_temp < -1000000000.0)
658 glue_temp = -1000000000.0;
660 cur_g = round(glue_temp);
664 rule_wd = rule_wd + cur_g;
666 if (subtype(p) >= a_leaders)
668 leader_box = leader_ptr(p);
670 if (type(leader_box) == rule_node)
672 rule_ht = height(leader_box);
673 rule_dp = depth(leader_box);
677 leader_wd = width(leader_box);
679 if ((leader_wd > 0) && (rule_wd > 0))
681 rule_wd = rule_wd + 10;
682 edge = cur_h + rule_wd;
685 if (subtype(p) == a_leaders)
688 cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);
691 cur_h = cur_h + leader_wd;
695 lq = rule_wd / leader_wd;
696 lr = rule_wd % leader_wd;
698 if (subtype(p) == c_leaders)
699 cur_h = cur_h + (lr / 2);
702 lx =(2 * lr + lq + 1) / (2 * lq + 2);
703 cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);
707 while (cur_h + leader_wd <= edge)
709 cur_v = base_line + shift_amount(leader_box);
716 temp_ptr = leader_box;
717 outer_doing_leaders = doing_leaders;
718 doing_leaders = true;
720 if (type(leader_box) == vlist_node)
725 doing_leaders = outer_doing_leaders;
729 cur_h = save_h + leader_wd + lx;
743 cur_h = cur_h + width(p);
748 mem[lig_trick] = mem[lig_char(p)];
749 link(lig_trick) = link(p);
761 if ((rule_ht == -1073741824L)) /* - 2^30 */
762 rule_ht = height(this_box);
764 if ((rule_dp == -1073741824L)) /* - 2^30 */
765 rule_dp = depth(this_box);
767 rule_ht = rule_ht + rule_dp;
769 if ((rule_ht > 0) && (rule_wd > 0))
771 cur_v = base_line + rule_dp;
772 HPDF_Page_SetLineWidth(yandy_page, rule_ht / 65535);
773 HPDF_Page_MoveTo (yandy_page, (cur_h / 65535 + 72), (841.89 - cur_v / 65535 - 72));
774 HPDF_Page_LineTo (yandy_page, (cur_h / 65535 + 72 + rule_wd / 65535), (841.89 - cur_v / 65535 - 72));
775 HPDF_Page_Stroke (yandy_page);
777 dvi_h = dvi_h + rule_wd;
780 cur_h = cur_h + rule_wd;
787 /* following needs access to dvi_buf=zdvibuf see coerce.h */
789 void pdf_vlist_out (void)
793 scaled save_h, save_v;
795 /* glue_ord g_order; */
796 int g_order; /* 95/Jan/7 */
798 int g_sign; /* 95/Jan/7 */
804 bool outer_doing_leaders;
813 g_order = glue_order(this_box);
814 g_sign = glue_sign(this_box);
815 p = list_ptr(this_box);
819 cur_v = cur_v - height(this_box);
824 if ((p >= hi_mem_min))
826 confusion("vlistout");
827 return; // abort_flag set
835 if (list_ptr(p) == 0)
836 cur_v = cur_v + height(p) + depth(p);
839 cur_v = cur_v + height(p);
844 cur_h = left_edge + shift_amount(p);
847 if (type(p) == vlist_node)
854 cur_v = save_v + depth(p);
875 rule_ht = width(g) - cur_g;
877 if (g_sign != normal)
879 if (g_sign == stretching)
881 if (stretch_order(g) == g_order)
883 cur_glue = cur_glue + stretch(g);
884 glue_temp = glue_set(this_box) * cur_glue;
886 if (glue_temp > 1000000000.0)
887 glue_temp = 1000000000.0;
888 else if (glue_temp < -1000000000.0)
889 glue_temp = -1000000000.0;
891 cur_g = round(glue_temp);
894 else if (shrink_order(g) == g_order) /* BUG FIX !!! */
896 cur_glue = cur_glue - shrink(g);
897 glue_temp = glue_set(this_box) * cur_glue;
899 if (glue_temp > 1000000000.0)
900 glue_temp = 1000000000.0;
901 else if (glue_temp < -1000000000.0)
902 glue_temp = -1000000000.0;
904 cur_g = round(glue_temp);
908 rule_ht = rule_ht + cur_g;
910 if (subtype(p) >= a_leaders)
912 leader_box = leader_ptr(p);
914 if (type(leader_box) == rule_node)
916 rule_wd = width(leader_box);
921 leader_ht = height(leader_box) + depth(leader_box);
923 if ((leader_ht > 0) && (rule_ht > 0))
925 rule_ht = rule_ht + 10;
926 edge = cur_v + rule_ht;
929 if (subtype(p) == a_leaders)
932 cur_v = top_edge + leader_ht * ((cur_v - top_edge) / leader_ht);
935 cur_v = cur_v + leader_ht;
939 lq = rule_ht / leader_ht;
940 lr = rule_ht % leader_ht;
942 if (subtype(p) == c_leaders)
943 cur_v = cur_v + (lr / 2);
946 lx = (2 * lr + lq + 1) / (2 * lq + 2);
947 cur_v = cur_v + ((lr - (lq - 1) * lx) / 2);
951 while (cur_v + leader_ht <= edge)
953 cur_h = left_edge + shift_amount(leader_box);
957 cur_v = cur_v + height(leader_box);
961 temp_ptr = leader_box;
962 outer_doing_leaders = doing_leaders;
963 doing_leaders = true;
965 if (type(leader_box) == vlist_node)
970 doing_leaders = outer_doing_leaders;
974 cur_v = save_v - height(leader_box) + leader_ht + lx;
987 cur_v = cur_v + width(p);
995 if ((rule_wd == -1073741824L)) /* -2^30 */
996 rule_wd = width(this_box);
998 rule_ht = rule_ht + rule_dp;
999 cur_v = cur_v + rule_ht;
1001 if ((rule_ht > 0) && (rule_wd > 0))
1003 HPDF_Page_SetLineWidth(yandy_page, rule_ht / 65535);
1004 HPDF_Page_MoveTo(yandy_page, (cur_h / 65535 + 72), (841.89 - cur_v / 65535 - 72));
1005 HPDF_Page_LineTo(yandy_page, (cur_h / 65535 + 72 + rule_wd / 65535), (841.89 - cur_v / 65535 - 72));
1006 HPDF_Page_Stroke(yandy_page);
1011 cur_v = cur_v + rule_ht;