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 boolean pdf_doing_string;
23 boolean pdf_doing_text;
24 static integer ten_pow[10] =
38 integer pdf_font_sum = 0;
41 HPDF_Font yandy_font[1024];
43 mapping_table * gentbl;
45 #define mapping_size 31627
49 mapping_entry * entries[mapping_size];
59 unsigned int font_name_hash(const char * s)
62 unsigned int h = 0, g;
64 for (p = s; *p != '\0'; p++)
68 if ((g = h & 0xf0000000))
78 mapping_table * font_name_hash_init (void)
80 mapping_table * temp_table;
83 temp_table = (mapping_table *) malloc(sizeof(mapping_table));
85 for (i = 0; i < mapping_size; i++)
86 temp_table->entries[i] = NULL;
91 void font_name_hash_free (mapping_table * tbl)
94 mapping_entry *e, *next;
96 for (i = 0; i < mapping_size; i++)
97 for (e = tbl->entries[i]; e; e = next)
107 void font_name_hash_insert (mapping_table * tbl, const char *key, int val)
112 i = font_name_hash(key) % mapping_size;
113 e = (mapping_entry *) malloc(sizeof(mapping_entry));
114 e->next = tbl->entries[i];
115 e->key = (char *) strdup(key);
120 int font_name_hash_lookup (mapping_table * tbl, const char *key)
125 i = font_name_hash(key) % mapping_size;
127 for (e = tbl->entries[i]; e; e = e-> next)
128 if (!strcmp(key, e->key))
135 void pdf_error(const char * t, const char * p)
137 normalize_selector();
138 print_err("Y&Y TeX error");
152 char * pdf_char_to_string(unsigned char i)
159 // output one char: normal.
160 void pdf_out(unsigned char i)
162 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
163 HPDF_Stream_WriteChar(attr->stream, i);
165 // octal number: 032, 009 etc.
166 void pdf_print_octal(integer s)
168 char buf[HPDF_INT_LEN + 1];
169 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
170 sprintf(buf, "%03o", s);
171 HPDF_Stream_Write(attr->stream, (HPDF_BYTE *)buf, strlen(buf));
173 // output one char: normal or octal.
174 void pdf_print_char(unsigned char s)
176 // 32 = '', 92 = '\', 40 = '(', 41 = ')'
177 if ((s <= 32) || (s == 92) || (s == 40) || (s == 41) || (s > 127))
187 // equivlent: pdf_print in pdfTeX.
188 void pdf_print_string(char * s)
190 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
191 HPDF_Stream_WriteStr(attr->stream, s);
193 // print one integer value: signed or unsigned.
194 void pdf_print_int(int s)
196 char buf[HPDF_INT_LEN + 1];
197 HPDF_PageAttr attr = (HPDF_PageAttr) yandy_page->attr;
198 char* p = HPDF_IToA(buf, s, buf + HPDF_INT_LEN);
199 HPDF_Stream_Write(attr->stream, (HPDF_BYTE *)buf, (HPDF_UINT)(p - buf));
201 // translate sp to bp.
202 HPDF_REAL pdf_sp_to_bp(scaled s)
204 // 1 bp = 65781.76 sp
205 return (HPDF_REAL) s / 65781.76;
207 // divides scaled s by scaled m.
208 scaled divide_scaled(scaled s, scaled m, integer dd)
228 pdf_error("arithmetic", "divided by zero");
229 else if (m >= 0x7FFFFFFF / 10)
230 pdf_error("arithmetic", "number too big");
235 for (i = 1; i <= dd; i++)
237 q = 10 * q + (10 * r) / m;
247 scaled_out = sign * (s - (r / ten_pow[dd]));
250 scaled round_xn_over_d(scaled x, integer n, integer d)
253 nonnegative_integer t, u, v;
263 t = (x % 32767L) * n;
264 u = (x / 32768L) * n + (t / 32768L);
265 v = (u % d) * 32768L + (t % 32768L);
270 u = 32768L * (u / d) + (v / d);
282 // advance char width
283 void adv_char_width(internal_font_number f, eight_bits c)
288 w = char_width(f, char_info(f, c));
289 divide_scaled(w, font_size[f], 4);
290 pdf_delta_h = pdf_delta_h + scaled_out;
293 void pdf_print(integer m, integer d)
301 pdf_print_int(m / ten_pow[d]);
309 while (m < ten_pow[d])
321 // end the current string
322 void pdf_end_string(void)
324 if (pdf_doing_string)
326 pdf_print_string(")] TJ\012");
327 pdf_doing_string = false;
330 // begin to draw a string
331 void pdf_begin_string(internal_font_number f)
333 scaled s_out, v, v_out;
345 s = divide_scaled(cur_h - pdf_delta_h, font_size[f], 3);
348 if (abs(s) < 0100000)
350 s_out = divide_scaled(round_xn_over_d(cur_h - pdf_delta_h, 1000, 1000),
357 // if (cur_v - pdf_v >= )
359 // end a text section.
365 HPDF_Page_EndText(yandy_page);
366 pdf_doing_text = false;
370 void pdf_set_rule(scaled x, scaled y, scaled w, scaled h)
373 void pdf_error_handler (HPDF_STATUS error_no, HPDF_STATUS detail_no, void * user_data)
375 printf ("Y&Y TeX error: error_no=%04X, detail_no=%u\n",
377 (HPDF_UINT)detail_no);
378 longjmp(jumpbuffer, 1);
381 void pdf_font_def (internal_font_number f)
384 const char * fnt_name;
387 char * fnt_buffer = (char *) malloc(length(font_name[f]) + 1);
389 memcpy(fnt_buffer, (const char *) str_pool + str_start[font_name[f]], length(font_name[f]));
390 fnt_buffer[length(font_name[f])] = '\0';
392 k = font_name_hash_lookup(gentbl, fnt_buffer);
396 afm_name = kpse_find_file(fnt_buffer, kpse_afm_format, 1);
397 pfb_name = kpse_find_file(fnt_buffer, kpse_type1_format, 1);
399 if (afm_name != NULL && pfb_name != NULL)
401 font_name_hash_insert(gentbl, fnt_buffer, pdf_font_sum + 1);
403 fnt_name = HPDF_LoadType1FontFromFile (yandy_pdf, afm_name, pfb_name);
404 yandy_font[pdf_font_sum] = HPDF_GetFont(yandy_pdf, fnt_name, NULL);
405 HPDF_Page_SetFontAndSize(yandy_page, yandy_font[pdf_font_sum], (font_size[f] / 65535));
409 HPDF_Page_SetFontAndSize(yandy_page, yandy_font[0], (font_size[f] / 65535));
414 HPDF_Page_SetFontAndSize(yandy_page, yandy_font[k], (font_size[f] / 65535));
420 void pdf_ship_out(halfword p)
424 if (tracing_output > 0)
428 print_string("Completed box being shipped out");
431 if (term_offset > max_print_line - 9)
433 else if ((term_offset > 0) || (file_offset > 0))
439 while((count(j) == 0) && (j > 0))
442 for (k = 0; k <= j; k++)
454 if (tracing_output > 0)
459 end_diagnostic(true);
462 if ((height(p) > max_dimen) || (depth(p) > max_dimen) ||
463 (height(p) + depth(p) + v_offset > max_dimen) ||
464 (width(p) + h_offset > max_dimen))
466 print_err("Huge page cannot be shipped out");
467 help2("The page just created is more than 18 feet tall or",
468 "more than 18 feet wide, so I suspect something went wrong.");
471 if (tracing_output <= 0)
474 print_nl("The following box has been deleted:");
476 end_diagnostic(true);
482 if (height(p) + depth(p) + v_offset > max_v)
483 max_v = height(p) + depth(p) + v_offset;
485 if (width(p) + h_offset > max_h)
486 max_h = width(p) + h_offset;
493 if (output_file_name == 0)
498 pack_job_name(".pdf");
500 while(!b_open_out(pdf_file))
502 prompt_file_name("file name for output", ".pdf");
505 output_file_name = b_make_name_string(pdf_file);
508 if (total_pages == 0)
510 gentbl = font_name_hash_init();
511 yandy_pdf = HPDF_New (pdf_error_handler, NULL);
512 HPDF_SetCompressionMode (yandy_pdf, HPDF_COMP_ALL);
513 yandy_pdf -> pdf_version = HPDF_VER_17;
514 HPDF_SetInfoAttr(yandy_pdf, HPDF_INFO_PRODUCER, "Y&Y TeX");
515 yandy_font[0] = HPDF_GetFont (yandy_pdf, "Times-Roman", NULL);
518 yandy_page = HPDF_AddPage (yandy_pdf);
519 HPDF_Page_SetSize (yandy_page, HPDF_PAGE_SIZE_A4, HPDF_PAGE_PORTRAIT);
521 cur_v = height(p) + v_offset;
524 if (type(p) == vlist_node)
532 if (tracing_output <= 0)
545 void pdf_hlist_out (void)
549 scaled save_h, save_v;
557 boolean outer_doing_leaders;
566 g_order = glue_order(this_box);
567 g_sign = glue_sign(this_box);
568 p = list_ptr(this_box);
593 HPDF_Page_BeginText(yandy_page);
595 HPDF_Page_MoveTextPos(yandy_page, pdf_sp_to_bp(cur_h) + 72, (841.89 - (pdf_sp_to_bp(cur_v) + 72)));
596 HPDF_Page_ShowText(yandy_page, pdf_char_to_string(c));
597 HPDF_Page_EndText(yandy_page);
598 cur_h = cur_h + char_width(f, char_info(f, c));
601 while(((p >= hi_mem_min)));
611 if (list_ptr(p) == 0)
612 cur_h = cur_h + width(p);
617 cur_v = base_line + shift_amount(p);
621 if (type(p) == vlist_node)
628 cur_h = edge + width(p);
649 rule_wd = width(g) - cur_g;
651 if (g_sign != normal)
653 if (g_sign == stretching)
655 if (stretch_order(g) == g_order)
657 cur_glue = cur_glue + stretch(g);
658 glue_temp = glue_set(this_box) * cur_glue;
660 if (glue_temp > 1000000000.0)
661 glue_temp = 1000000000.0;
662 else if (glue_temp < -1000000000.0)
663 glue_temp = -1000000000.0;
665 cur_g = round(glue_temp);
668 else if (shrink_order(g) == g_order)
670 cur_glue = cur_glue - shrink(g);
671 glue_temp = glue_set(this_box) * cur_glue;
673 if (glue_temp > 1000000000.0)
674 glue_temp = 1000000000.0;
675 else if (glue_temp < -1000000000.0)
676 glue_temp = -1000000000.0;
678 cur_g = round(glue_temp);
682 rule_wd = rule_wd + cur_g;
684 if (subtype(p) >= a_leaders)
686 leader_box = leader_ptr(p);
688 if (type(leader_box) == rule_node)
690 rule_ht = height(leader_box);
691 rule_dp = depth(leader_box);
695 leader_wd = width(leader_box);
697 if ((leader_wd > 0) && (rule_wd > 0))
699 rule_wd = rule_wd + 10;
700 edge = cur_h + rule_wd;
703 if (subtype(p) == a_leaders)
706 cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);
709 cur_h = cur_h + leader_wd;
713 lq = rule_wd / leader_wd;
714 lr = rule_wd % leader_wd;
716 if (subtype(p) == c_leaders)
717 cur_h = cur_h + (lr / 2);
720 lx =(2 * lr + lq + 1) / (2 * lq + 2);
721 cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);
725 while (cur_h + leader_wd <= edge)
727 cur_v = base_line + shift_amount(leader_box);
734 temp_ptr = leader_box;
735 outer_doing_leaders = doing_leaders;
736 doing_leaders = true;
738 if (type(leader_box) == vlist_node)
743 doing_leaders = outer_doing_leaders;
747 cur_h = save_h + leader_wd + lx;
761 cur_h = cur_h + width(p);
766 mem[lig_trick] = mem[lig_char(p)];
767 link(lig_trick) = link(p);
779 if ((rule_ht == -1073741824L)) /* - 2^30 */
780 rule_ht = height(this_box);
782 if ((rule_dp == -1073741824L)) /* - 2^30 */
783 rule_dp = depth(this_box);
785 rule_ht = rule_ht + rule_dp;
787 if ((rule_ht > 0) && (rule_wd > 0))
789 cur_v = base_line + rule_dp;
790 HPDF_Page_SetLineWidth(yandy_page, rule_ht / 65535);
791 HPDF_Page_MoveTo (yandy_page, (cur_h / 65535 + 72), (841.89 - cur_v / 65535 - 72));
792 HPDF_Page_LineTo (yandy_page, (cur_h / 65535 + 72 + rule_wd / 65535), (841.89 - cur_v / 65535 - 72));
793 HPDF_Page_Stroke (yandy_page);
795 dvi_h = dvi_h + rule_wd;
798 cur_h = cur_h + rule_wd;
805 /* following needs access to dvi_buf=zdvibuf see coerce.h */
807 void pdf_vlist_out (void)
811 scaled save_h, save_v;
813 /* glue_ord g_order; */
814 int g_order; /* 95/Jan/7 */
816 int g_sign; /* 95/Jan/7 */
822 boolean outer_doing_leaders;
831 g_order = glue_order(this_box);
832 g_sign = glue_sign(this_box);
833 p = list_ptr(this_box);
837 cur_v = cur_v - height(this_box);
842 if ((p >= hi_mem_min))
844 confusion("vlistout");
845 return; // abort_flag set
853 if (list_ptr(p) == 0)
854 cur_v = cur_v + height(p) + depth(p);
857 cur_v = cur_v + height(p);
862 cur_h = left_edge + shift_amount(p);
865 if (type(p) == vlist_node)
872 cur_v = save_v + depth(p);
893 rule_ht = width(g) - cur_g;
895 if (g_sign != normal)
897 if (g_sign == stretching)
899 if (stretch_order(g) == g_order)
901 cur_glue = cur_glue + stretch(g);
902 glue_temp = glue_set(this_box) * cur_glue;
904 if (glue_temp > 1000000000.0)
905 glue_temp = 1000000000.0;
906 else if (glue_temp < -1000000000.0)
907 glue_temp = -1000000000.0;
909 cur_g = round(glue_temp);
912 else if (shrink_order(g) == g_order) /* BUG FIX !!! */
914 cur_glue = cur_glue - shrink(g);
915 glue_temp = glue_set(this_box) * cur_glue;
917 if (glue_temp > 1000000000.0)
918 glue_temp = 1000000000.0;
919 else if (glue_temp < -1000000000.0)
920 glue_temp = -1000000000.0;
922 cur_g = round(glue_temp);
926 rule_ht = rule_ht + cur_g;
928 if (subtype(p) >= a_leaders)
930 leader_box = leader_ptr(p);
932 if (type(leader_box) == rule_node)
934 rule_wd = width(leader_box);
939 leader_ht = height(leader_box) + depth(leader_box);
941 if ((leader_ht > 0) && (rule_ht > 0))
943 rule_ht = rule_ht + 10;
944 edge = cur_v + rule_ht;
947 if (subtype(p) == a_leaders)
950 cur_v = top_edge + leader_ht * ((cur_v - top_edge) / leader_ht);
953 cur_v = cur_v + leader_ht;
957 lq = rule_ht / leader_ht;
958 lr = rule_ht % leader_ht;
960 if (subtype(p) == c_leaders)
961 cur_v = cur_v + (lr / 2);
964 lx = (2 * lr + lq + 1) / (2 * lq + 2);
965 cur_v = cur_v + ((lr - (lq - 1) * lx) / 2);
969 while (cur_v + leader_ht <= edge)
971 cur_h = left_edge + shift_amount(leader_box);
975 cur_v = cur_v + height(leader_box);
979 temp_ptr = leader_box;
980 outer_doing_leaders = doing_leaders;
981 doing_leaders = true;
983 if (type(leader_box) == vlist_node)
988 doing_leaders = outer_doing_leaders;
992 cur_v = save_v - height(leader_box) + leader_ht + lx;
1005 cur_v = cur_v + width(p);
1013 if ((rule_wd == -1073741824L)) /* -2^30 */
1014 rule_wd = width(this_box);
1016 rule_ht = rule_ht + rule_dp;
1017 cur_v = cur_v + rule_ht;
1019 if ((rule_ht > 0) && (rule_wd > 0))
1021 HPDF_Page_SetLineWidth(yandy_page, rule_ht / 65535);
1022 HPDF_Page_MoveTo(yandy_page, (cur_h / 65535 + 72), (841.89 - cur_v / 65535 - 72));
1023 HPDF_Page_LineTo(yandy_page, (cur_h / 65535 + 72 + rule_wd / 65535), (841.89 - cur_v / 65535 - 72));
1024 HPDF_Page_Stroke(yandy_page);
1029 cur_v = cur_v + rule_ht;