diff options
Diffstat (limited to 'Build/source/texk/web2c/pdftexdir/writet3.c')
-rw-r--r-- | Build/source/texk/web2c/pdftexdir/writet3.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/pdftexdir/writet3.c b/Build/source/texk/web2c/pdftexdir/writet3.c new file mode 100644 index 00000000000..5d5eb47729f --- /dev/null +++ b/Build/source/texk/web2c/pdftexdir/writet3.c @@ -0,0 +1,429 @@ +/* writet3.c: write a Type 3 (bitmap PK) font. +Copyright 1996-2019 Han The Thanh, <thanh@pdftex.org> + +This file is part of pdfTeX. + +pdfTeX is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +pdfTeX is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ptexlib.h" +#include <kpathsea/tex-glyph.h> +#include <kpathsea/magstep.h> +#include <string.h> + +#define T3_BUF_SIZE 1024 + +typedef char t3_line_entry; +define_array(t3_line); + +FILE *t3_file; +static boolean t3_image_used; + +static integer t3_char_procs[256]; +static float t3_char_widths[256]; +static int t3_glyph_num; +static float t3_font_scale; +static integer t3_b0, t3_b1, t3_b2, t3_b3; +static boolean is_pk_font; + +#define t3_open() \ + open_input(&t3_file, kpse_miscfonts_format, FOPEN_RBIN_MODE) +#define t3_close() xfclose(t3_file, cur_file_name) +#define t3_getchar() xgetc(t3_file) +#define t3_eof() feof(t3_file) +#define t3_prefix(s) str_prefix(t3_line_array, s) +#define t3_putchar(c) pdfout(c) + +#define t3_check_eof() \ + if (t3_eof()) \ + pdftex_fail("unexpected end of file"); + +static void t3_getline(void) +{ + int c; + restart: + t3_line_ptr = t3_line_array; + c = t3_getchar(); + while (!t3_eof()) { + alloc_array(t3_line, 1, T3_BUF_SIZE); + append_char_to_buf(c, t3_line_ptr, t3_line_array, t3_line_limit); + if (c == 10) + break; + c = t3_getchar(); + } + alloc_array(t3_line, 2, T3_BUF_SIZE); + append_eol(t3_line_ptr, t3_line_array, T3_BUF_SIZE); + if (t3_line_ptr - t3_line_array < 2 || *t3_line_array == '%') { + if (!t3_eof()) + goto restart; + } +} + +static void t3_putline(void) +{ + char *p = t3_line_array; + while (p < t3_line_ptr) + t3_putchar(*p++); +} + +static void update_bbox(integer llx, integer lly, integer urx, integer ury, + boolean is_first_glyph) +{ + if (is_first_glyph) { + t3_b0 = llx; + t3_b1 = lly; + t3_b2 = urx; + t3_b3 = ury; + } else { + if (llx < t3_b0) + t3_b0 = llx; + if (lly < t3_b1) + t3_b1 = lly; + if (urx > t3_b2) + t3_b2 = urx; + if (ury > t3_b3) + t3_b3 = ury; + } +} + +static void t3_write_glyph(internalfontnumber f) +{ + static char t3_begin_glyph_str[] = "\\pdfglyph"; + static char t3_end_glyph_str[] = "\\endglyph"; + int glyph_index; + int width, height, depth, llx, lly, urx, ury; + char *p; + t3_getline(); + if (t3_prefix(t3_begin_glyph_str)) { + if (sscanf(t3_line_array + strlen(t3_begin_glyph_str) + 1, + "%i %i %i %i %i %i %i %i =", &glyph_index, + &width, &height, &depth, &llx, &lly, &urx, &ury) != 8) { + remove_eol(p, t3_line_array); + pdftex_fail("invalid glyph preamble: `%s'", t3_line_array); + } + if (glyph_index < fontbc[f] || glyph_index > fontec[f]) + return; + } else + return; + if (!pdfcharmarked(f, glyph_index)) { + while (!t3_prefix(t3_end_glyph_str)) { + t3_check_eof(); + t3_getline(); + } + return; + } + update_bbox(llx, lly, urx, ury, t3_glyph_num == 0); + t3_glyph_num++; + pdfnewdict(0, 0, 0); + t3_char_procs[glyph_index] = objptr; + if (width == 0) + t3_char_widths[glyph_index] = + (getcharwidth(f, glyph_index) / t3_font_scale) / pdffontsize[f]; + else + t3_char_widths[glyph_index] = width; + pdfbeginstream(); + t3_getline(); + pdf_printf("%i 0 %i %i %i %i d1\nq\n", + (int) t3_char_widths[glyph_index], (int) llx, + (int) lly, (int) urx, (int) ury); + while (!t3_prefix(t3_end_glyph_str)) { + t3_check_eof(); + if (t3_prefix("BI")) + t3_image_used = true; + t3_putline(); + t3_getline(); + } + pdf_puts("Q\n"); + pdfendstream(); +} + +static integer get_pk_font_scale(internalfontnumber f) +{ + return + dividescaled(pkscalefactor, + dividescaled(pdffontsize[f], onehundredbp, + fixeddecimaldigits + 2), 0); +} + +static integer pk_char_width(internalfontnumber f, scaled w) +{ + return + dividescaled(dividescaled(w, pdffontsize[f], 7), + get_pk_font_scale(f), 0); +} + +scaled getpkcharwidth(internalfontnumber f, scaled w) +{ + return (get_pk_font_scale(f) / 100000.0) * + (pk_char_width(f, w) / 100.0) * pdffontsize[f]; +} + +static boolean writepk(internalfontnumber f) +{ + kpse_glyph_file_type font_ret; + integer llx, lly, urx, ury; + integer cw, rw, i, j; + halfword *row; + char *name; + chardesc cd; + boolean is_null_glyph, check_preamble; + integer dpi; + dpi = + kpse_magstep_fix(round + (fixedpkresolution * + (((float) pdffontsize[f]) / fontdsize[f])), + fixedpkresolution, NULL); + cur_file_name = makecstring(fontname[f]); + name = kpse_find_pk(cur_file_name, (unsigned) dpi, &font_ret); + if (name == NULL || + !FILESTRCASEEQ(cur_file_name, font_ret.name) || + !kpse_bitmap_tolerance((float) font_ret.dpi, (float) dpi)) { + pdftex_fail("Font %s at %i not found", cur_file_name, (int) dpi); + } + t3_file = xfopen(name, FOPEN_RBIN_MODE); + recorder_record_input(name); + t3_image_used = true; + is_pk_font = true; + tex_printf(" <%s", (char *) name); + cd.rastersize = 256; + cd.raster = xtalloc(cd.rastersize, halfword); + check_preamble = true; + while (readchar(check_preamble, &cd) != 0) { + check_preamble = false; + if (!pdfcharmarked(f, cd.charcode)) + continue; + t3_char_widths[cd.charcode] = + pk_char_width(f, getcharwidth(f, cd.charcode)); + if (cd.cwidth < 1 || cd.cheight < 1) { + cd.xescape = cd.cwidth = round(t3_char_widths[cd.charcode] / 100.0); + cd.cheight = 1; + cd.xoff = 0; + cd.yoff = 0; + is_null_glyph = true; + } else + is_null_glyph = false; + llx = -cd.xoff; + lly = cd.yoff - cd.cheight + 1; + urx = cd.cwidth + llx + 1; + ury = cd.cheight + lly; + update_bbox(llx, lly, urx, ury, t3_glyph_num == 0); + t3_glyph_num++; + pdfnewdict(0, 0, 0); + t3_char_procs[cd.charcode] = objptr; + pdfbeginstream(); + pdfprintreal(t3_char_widths[cd.charcode], 2); + pdf_printf(" 0 %i %i %i %i d1\n", + (int) llx, (int) lly, (int) urx, (int) ury); + if (is_null_glyph) + goto end_stream; + pdf_printf("q\n%i 0 0 %i %i %i cm\nBI\n", (int) cd.cwidth, + (int) cd.cheight, (int) llx, (int) lly); + pdf_printf("/W %i\n/H %i\n", (int) cd.cwidth, (int) cd.cheight); + pdf_puts("/IM true\n/BPC 1\n/D [1 0]\nID "); + cw = (cd.cwidth + 7) / 8; + rw = (cd.cwidth + 15) / 16; + row = cd.raster; + for (i = 0; i < cd.cheight; i++) { + for (j = 0; j < rw - 1; j++) { + pdfout(*row / 256); + pdfout(*row % 256); + row++; + } + pdfout(*row / 256); + if (2 * rw == cw) + pdfout(*row % 256); + row++; + } + pdf_puts("\nEI\nQ\n"); + end_stream: + pdfendstream(); + } + xfree(cd.raster); + cur_file_name = NULL; + return true; +} + +/* We must remove duplicate glyph names since the duplicates render the + output invalid. We give a warning, since this should only happen with + ill-defined .enc files that should get fixed. */ +static void remove_duplicate_glyph_names(char **g, const char *encname) +{ + struct avl_table *gl_tree; + char *aa; + int i; + gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator); + assert(gl_tree != NULL); + for (i = 0; i < 256; i++) { + if (g[i] == notdef) + continue; + aa = (char *) avl_find(gl_tree, g[i]); + if (aa == NULL) { + aa = (char *) avl_probe(gl_tree, g[i]); + assert(aa != NULL); + } else { + pdftex_warn("%s: duplicate glyph name at position %d: %s", + encname, i, g[i]); + xfree(g[i]); + g[i] = (char *) notdef; + } + } + avl_destroy(gl_tree, NULL); +} + +void writet3(fm_entry * fm, int objnum, internalfontnumber f) +{ + static char t3_font_scale_str[] = "\\pdffontscale"; + int i; + integer wptr, eptr, cptr; + int first_char, last_char; + integer pk_font_scale; + boolean is_notdef; + fe_entry *fe; + char **glyph_names; + integer tounicode_objnum; + t3_glyph_num = 0; + t3_image_used = false; + for (i = 0; i < 256; i++) { + t3_char_procs[i] = 0; + t3_char_widths[i] = 0; + } + fe = fm && fm->encname ? get_fe_entry(fm->encname) : NULL; + glyph_names = fe ? fe->glyph_names : NULL; + if (glyph_names) + remove_duplicate_glyph_names(glyph_names, fm->encname); + packfilename(fontname[f], getnullstr(), maketexstring(".pgc")); + cur_file_name = makecstring(makenamestring()); + is_pk_font = false; + if (!t3_open()) { + if (writepk(f)) + goto write_font_dict; + else { + cur_file_name = NULL; + return; + } + } + tex_printf("<%s", nameoffile + 1); + t3_getline(); + if (!t3_prefix(t3_font_scale_str) || + sscanf(t3_line_array + strlen(t3_font_scale_str) + 1, "%g", + &t3_font_scale) < 1 || t3_font_scale <= 0 + || t3_font_scale > 1000) { + pdftex_fail("missing or invalid font scale"); + } + while (!t3_eof()) + t3_write_glyph(f); + write_font_dict: + for (i = fontbc[f]; i <= fontec[f]; i++) + if (pdfcharmarked(f, i)) + break; + first_char = i; + for (i = fontec[f]; i > first_char; i--) + if (pdfcharmarked(f, i)) + break; + last_char = i; + /* write ToUnicode entry if we can */ + if (fixedgentounicode > 0 && !pdffontnobuiltintounicode[f] && fe != NULL) + tounicode_objnum = write_tounicode(glyph_names, fm->tfm_name, fe->name); + else + tounicode_objnum = 0; + pdfbegindict(objnum, 1); /* Type 3 font dictionary */ + pdf_puts("/Type /Font\n/Subtype /Type3\n"); + pdf_printf("/Name /F%i\n", (int) f); + if (pdffontattr[f] != getnullstr()) { + pdfprint(pdffontattr[f]); + pdf_puts("\n"); + } + if (is_pk_font) { + pk_font_scale = get_pk_font_scale(f); + pdf_puts("/FontMatrix ["); + pdfprintreal(pk_font_scale, 5); + pdf_puts(" 0 0 "); + pdfprintreal(pk_font_scale, 5); + pdf_puts(" 0 0]\n"); + } else + pdf_printf("/FontMatrix [%g 0 0 %g 0 0]\n", + (double) t3_font_scale, (double) t3_font_scale); + pdf_printf("/%s [ %i %i %i %i ]\n", + font_key[FONTBBOX1_CODE].pdfname, + (int) t3_b0, (int) t3_b1, (int) t3_b2, (int) t3_b3); + pdf_printf("/Resources << /ProcSet [ /PDF %s] >>\n", + t3_image_used ? "/ImageB " : ""); + pdf_printf("/FirstChar %i\n/LastChar %i\n", first_char, last_char); + wptr = pdfnewobjnum(); + eptr = pdfnewobjnum(); + cptr = pdfnewobjnum(); + pdf_printf("/Widths %i 0 R\n/Encoding %i 0 R\n/CharProcs %i 0 R\n", + (int) wptr, (int) eptr, (int) cptr); + if (tounicode_objnum != 0) + pdf_printf("/ToUnicode %i 0 R\n", (int) tounicode_objnum); + pdfenddict(); + pdfbeginobj(wptr, 1); /* chars width array */ + pdf_puts("["); + if (is_pk_font) + for (i = first_char; i <= last_char; i++) { + pdfprintreal(t3_char_widths[i], 2); + pdf_puts(" "); + } else + for (i = first_char; i <= last_char; i++) + pdf_printf("%i ", (int) t3_char_widths[i]); + pdf_puts("]\n"); + pdfendobj(); + pdfbegindict(eptr, 1); /* encoding dictionary */ + pdf_printf("/Type /Encoding\n/Differences [%i", first_char); + if (t3_char_procs[first_char] == 0) { + pdf_printf("/%s", notdef); + is_notdef = true; + } else { + if (glyph_names + && glyph_names[first_char] + && glyph_names[first_char] != notdef) + pdf_printf("/%s", glyph_names[first_char]); + else + pdf_printf("/a%i", first_char); + is_notdef = false; + } + for (i = first_char + 1; i <= last_char; i++) { + if (t3_char_procs[i] == 0) { + if (!is_notdef) { + pdf_printf(" %i/%s", i, notdef); + is_notdef = true; + } + } else { + if (is_notdef) { + pdf_printf(" %i", i); + is_notdef = false; + } + if (glyph_names && glyph_names[i] && glyph_names[i] != notdef) + pdf_printf("/%s", glyph_names[i]); + else + pdf_printf("/a%i", i); + } + } + pdf_puts("]\n"); + pdfenddict(); + pdfbegindict(cptr, 1); /* CharProcs dictionary */ + for (i = first_char; i <= last_char; i++) + if (t3_char_procs[i] != 0) { + if (glyph_names && glyph_names[i] && glyph_names[i] != notdef) + pdf_printf("/%s %i 0 R\n", glyph_names[i], + (int) t3_char_procs[i]); + else + pdf_printf("/a%i %i 0 R\n", (int) i, + (int) t3_char_procs[i]); + } + pdfenddict(); + t3_close(); + tex_printf(">"); + cur_file_name = NULL; +} |