Back to index

tetex-bin  3.0
writet3.c
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
00003 
00004 This file is part of pdfTeX.
00005 
00006 pdfTeX is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 pdfTeX is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with pdfTeX; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet3.c#9 $
00021 */
00022 
00023 #include "ptexlib.h"
00024 #include <kpathsea/tex-glyph.h>
00025 #include <kpathsea/magstep.h>
00026 
00027 #define T3_BUF_SIZE   1024
00028 
00029 static const char perforce_id[] = 
00030     "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet3.c#9 $";
00031 
00032 /* define t3_line_ptr, t3_line_array & t3_line_limit */
00033 typedef char t3_line_entry;
00034 define_array(t3_line);   
00035 
00036 FILE *t3_file;
00037 static boolean t3_image_used;
00038 
00039 static integer t3_char_procs[MAX_CHAR_CODE + 1];
00040 static float t3_char_widths[MAX_CHAR_CODE + 1];
00041 static int t3_glyph_num;
00042 static float t3_font_scale;
00043 static integer t3_b0, t3_b1, t3_b2, t3_b3;
00044 static boolean is_pk_font;
00045 
00046 #define t3_open()       \
00047     open_input(&t3_file, kpse_miscfonts_format, FOPEN_RBIN_MODE)
00048 #define t3_close()      xfclose(t3_file, cur_file_name)
00049 #define t3_getchar()    xgetc(t3_file)
00050 #define t3_eof()        feof(t3_file)
00051 #define t3_prefix(s)    (!strncmp(t3_line_array, s, strlen(s)))
00052 #define t3_putchar(c)   pdfout(c)
00053 
00054 #define t3_check_eof()                                     \
00055     if (t3_eof())                                          \
00056         pdftex_fail("unexpected end of file");
00057 
00058 static void t3_getline(void) 
00059 {
00060     int c;
00061 restart:
00062     t3_line_ptr = t3_line_array;
00063     c = t3_getchar();
00064     while (!t3_eof()) {
00065         alloc_array(t3_line, 1, T3_BUF_SIZE);
00066         append_char_to_buf(c, t3_line_ptr, t3_line_array, t3_line_limit);
00067         if (c == 10)
00068             break;
00069         c = t3_getchar();
00070     }
00071     alloc_array(t3_line, 2, T3_BUF_SIZE);
00072     append_eol(t3_line_ptr, t3_line_array, T3_BUF_SIZE);
00073     if (t3_line_ptr - t3_line_array < 2 || *t3_line_array == '%') {
00074         if (!t3_eof())
00075             goto restart;
00076     }
00077 }
00078 
00079 static void t3_putline(void)
00080 {
00081     char *p = t3_line_array;
00082     while (p < t3_line_ptr)
00083         t3_putchar(*p++);
00084 }
00085 
00086 static void update_bbox(integer llx, integer lly, integer urx, integer ury, boolean is_first_glyph)
00087 {
00088     if (is_first_glyph) {
00089         t3_b0 = llx;
00090         t3_b1 = lly;
00091         t3_b2 = urx;
00092         t3_b3 = ury;
00093     }
00094     else {
00095         if (llx < t3_b0)
00096             t3_b0 = llx;
00097         if (lly < t3_b1)
00098             t3_b1 = lly;
00099         if (urx > t3_b2)
00100             t3_b2 = urx;
00101         if (ury > t3_b3)
00102             t3_b3 = ury;
00103     }
00104 }
00105 
00106 static void t3_write_glyph(internalfontnumber f)
00107 {
00108     static char t3_begin_glyph_str[] = "\\pdfglyph";
00109     static char t3_end_glyph_str[] = "\\endglyph";
00110     int glyph_index;
00111     int width, height, depth, llx, lly, urx, ury;
00112     char *p;
00113     t3_getline();
00114     if (t3_prefix(t3_begin_glyph_str)) {
00115         if (sscanf(t3_line_array + strlen(t3_begin_glyph_str) + 1,
00116                    "%i %i %i %i %i %i %i %i =", &glyph_index,
00117                    &width, &height, &depth, &llx, &lly, &urx, &ury) != 8) {
00118             remove_eol(p, t3_line_array);
00119             pdftex_warn("invalid glyph preamble: `%s'", t3_line_array);
00120             return;
00121         }
00122         if (glyph_index < fontbc[f] || glyph_index > fontec[f])
00123             return;
00124     }
00125     else
00126         return;
00127     if (!pdfcharmarked(f, glyph_index)) {
00128         while (!t3_prefix(t3_end_glyph_str)) {
00129             t3_check_eof();
00130             t3_getline();
00131         }
00132         return;
00133     }
00134     update_bbox(llx, lly, urx, ury, t3_glyph_num == 0);
00135     t3_glyph_num++;
00136     pdfnewdict(0, 0);
00137     t3_char_procs[glyph_index] = objptr;
00138     if (width == 0) 
00139         t3_char_widths[glyph_index] = 
00140             (getcharwidth(f, glyph_index)/t3_font_scale) / pdffontsize[f];
00141     else
00142         t3_char_widths[glyph_index] = width;
00143     pdfbeginstream();
00144     t3_getline();
00145     pdf_printf("%i 0 %i %i %i %i d1\nq\n", 
00146                (int)t3_char_widths[glyph_index], (int)llx,
00147                (int)lly, (int)urx, (int)ury);
00148     while (!t3_prefix(t3_end_glyph_str)) {
00149         t3_check_eof();
00150         if (t3_prefix("BI"))
00151             t3_image_used = true;
00152         t3_putline();
00153         t3_getline();
00154     }
00155     pdf_puts("Q\n");
00156     pdfendstream();
00157 }
00158 
00159 static integer get_pk_font_scale(internalfontnumber f)
00160 {
00161     return 
00162         dividescaled(pkscalefactor, 
00163             dividescaled(pdffontsize[f], onehundredbp, fixeddecimaldigits + 2),
00164             0);
00165 }
00166 
00167 static integer pk_char_width(internalfontnumber f, scaled w)
00168 {
00169     return 
00170         dividescaled(dividescaled(w, pdffontsize[f], 7),
00171                      get_pk_font_scale(f), 0);
00172 }
00173 
00174 scaled getpkcharwidth(internalfontnumber f, scaled w)
00175 {
00176     return (get_pk_font_scale(f)/100000.0)*
00177            (pk_char_width(f, w)/100.0)*
00178            pdffontsize[f];
00179 }
00180 
00181 static boolean writepk(internalfontnumber f)
00182 {
00183     kpse_glyph_file_type font_ret;
00184     integer llx, lly, urx, ury;
00185     integer cw, rw, i, j;
00186     halfword *row;
00187     char *name;
00188     chardesc cd;
00189     boolean is_null_glyph, check_preamble;
00190     integer dpi;
00191     int e;
00192     dpi = kpse_magstep_fix(
00193              round(fixedpkresolution*(((float)pdffontsize[f])/fontdsize[f])),
00194              fixedpkresolution, NULL);
00195     cur_file_name = makecstring(fontname[f]);
00196     name = kpse_find_pk(cur_file_name, (unsigned)dpi, &font_ret);
00197     if (name == NULL ||
00198         !FILESTRCASEEQ(cur_file_name, font_ret.name) ||
00199         !kpse_bitmap_tolerance((float)font_ret.dpi, (float)dpi)) {
00200         pdftex_warn("Font %s at %i not found", cur_file_name, (int)dpi);
00201         cur_file_name = NULL;
00202         return false;
00203     }
00204     t3_file = xfopen(name, FOPEN_RBIN_MODE);
00205     t3_image_used = true;
00206     is_pk_font = true;
00207     tex_printf(" <%s", (char *)name);
00208     cd.rastersize = 256;
00209     cd.raster = xtalloc(cd.rastersize, halfword);
00210     check_preamble = true;
00211     while (readchar(check_preamble, &cd) != 0) {
00212         check_preamble = false;
00213         if (!pdfcharmarked(f, cd.charcode))
00214             continue;
00215         t3_char_widths[cd.charcode] = 
00216             pk_char_width(f, getcharwidth(f, cd.charcode));
00217         if (cd.cwidth < 1 || cd.cheight < 1) {
00218             cd.xescape = cd.cwidth = round(t3_char_widths[cd.charcode]/100.0);
00219             cd.cheight = 1;
00220             cd.xoff = 0;
00221             cd.yoff = 0;
00222             is_null_glyph = true;
00223         }
00224         else
00225             is_null_glyph = false;
00226         llx = -cd.xoff;
00227         lly = cd.yoff - cd.cheight + 1;
00228         urx = cd.cwidth + llx + 1;
00229         ury = cd.cheight + lly;
00230         update_bbox(llx, lly, urx, ury, t3_glyph_num == 0);
00231         t3_glyph_num++;
00232         pdfnewdict(0, 0);
00233         t3_char_procs[cd.charcode] = objptr;
00234         pdfbeginstream();
00235         pdfprintreal(t3_char_widths[cd.charcode], 2);
00236         pdf_printf(" 0 %i %i %i %i d1\n", 
00237                     (int)llx, (int)lly, (int)urx, (int)ury);
00238         if (is_null_glyph)
00239             goto end_stream;
00240         pdf_printf("q\n%i 0 0 %i %i %i cm\nBI\n", (int)cd.cwidth,
00241                    (int)cd.cheight, (int)llx, (int)lly);
00242         pdf_printf("/W %i\n/H %i\n", 
00243                    (int)cd.cwidth, (int)cd.cheight);
00244         pdf_puts("/IM true\n/BPC 1\n/D [1 0]\nID ");
00245         cw = (cd.cwidth + 7)/8;
00246         rw = (cd.cwidth + 15)/16;
00247         row = cd.raster;
00248         for (i = 0; i < cd.cheight; i++) {
00249             for (j = 0; j < rw - 1; j++) {
00250                 pdfout(*row/256);
00251                 pdfout(*row%256);
00252                 row++;
00253             }
00254             pdfout(*row/256);
00255             if (2*rw == cw)
00256                 pdfout(*row%256);
00257             row++;
00258         }
00259         pdf_puts("\nEI\nQ\n");
00260 end_stream:
00261         pdfendstream();
00262     }
00263     xfree(cd.raster);
00264     cur_file_name = NULL;
00265     return true;
00266 }
00267 
00268 void writet3(int objnum, internalfontnumber f)
00269 {
00270     static char t3_font_scale_str[] = "\\pdffontscale";
00271     int i, e;
00272     int first_char, last_char;
00273     integer pk_font_scale;
00274     boolean is_notdef;
00275     t3_glyph_num = 0;
00276     t3_image_used = false;
00277     for (i = 0; i <= MAX_CHAR_CODE; i++) {
00278         t3_char_procs[i] = 0;
00279         t3_char_widths[i] = 0;
00280     }
00281     packfilename(fontname[f], getnullstr(), maketexstring(".pgc"));
00282     cur_file_name = makecstring(makenamestring());
00283     is_pk_font = false;
00284     if (!t3_open()) {
00285         if (writepk(f))
00286             goto write_font_dict;
00287         else {
00288             cur_file_name = NULL;
00289             return;
00290         }
00291     }
00292     tex_printf("<%s", nameoffile + 1);
00293     t3_getline();
00294     if (!t3_prefix(t3_font_scale_str) ||
00295         sscanf(t3_line_array + strlen(t3_font_scale_str) + 1, "%g", &t3_font_scale) < 1 ||
00296         t3_font_scale <= 0 || t3_font_scale > 1000 ) {
00297         pdftex_warn("missing or invalid font scale");
00298         t3_close();
00299         cur_file_name = NULL;
00300         return;
00301     }
00302     while (!t3_eof())
00303         t3_write_glyph(f);
00304 write_font_dict:
00305     for (i = fontbc[f]; i <= fontec[f]; i++)
00306         if (pdfcharmarked(f, i))
00307             break;
00308     first_char = i;
00309     for (i = fontec[f]; i > first_char; i--)
00310         if (pdfcharmarked(f, i))
00311             break;
00312     last_char = i;
00313     pdfbegindict(objnum); /* Type 3 font dictionary */
00314     pdf_puts("/Type /Font\n/Subtype /Type3\n");
00315     pdf_printf("/Name /F%i\n", (int)f);
00316     if (pdffontattr[f] != getnullstr()) {
00317         pdfprint(pdffontattr[f]);
00318         pdf_puts("\n");
00319     }
00320     if (is_pk_font) {
00321         pk_font_scale = get_pk_font_scale(f);
00322         pdf_puts("/FontMatrix [");
00323         pdfprintreal(pk_font_scale, 5);
00324         pdf_puts(" 0 0 ");
00325         pdfprintreal(pk_font_scale, 5);
00326         pdf_puts(" 0 0]\n") ;
00327     }
00328     else
00329         pdf_printf("/FontMatrix [%g 0 0 %g 0 0]\n", 
00330                    (double)t3_font_scale, (double)t3_font_scale);
00331     pdf_printf("/%s [ %i %i %i %i ]\n", 
00332                font_keys[FONTBBOX1_CODE].pdfname, 
00333                (int)t3_b0, (int)t3_b1, 
00334                (int)t3_b2, (int)t3_b3);
00335     pdf_printf("/Resources << /ProcSet [ /PDF %s] >>\n", 
00336                t3_image_used ? "/ImageB " : "");
00337     pdf_printf("/FirstChar %i\n/LastChar %i\n", first_char, last_char);
00338     pdf_printf("/Widths %i 0 R\n/Encoding %i 0 R\n/CharProcs %i 0 R\n", 
00339                (int)(objptr + 1), (int)(objptr + 2),
00340                (int)(objptr + 3));
00341     pdfenddict();
00342     pdfnewobj(0, 0); /* chars width array */
00343     pdf_puts("[");
00344     if (is_pk_font)
00345         for (i = first_char; i <= last_char; i++) {
00346             pdfprintreal(t3_char_widths[i], 2);
00347             pdf_puts(" ");
00348         }
00349     else
00350         for (i = first_char; i <= last_char; i++)
00351             pdf_printf("%i ", (int)t3_char_widths[i]);
00352     pdf_puts("]\n");
00353     pdfendobj();
00354     pdfnewdict(0, 0); /* encoding dictionary */
00355     pdf_printf("/Type /Encoding\n/Differences [%i", first_char);
00356     if (t3_char_procs[first_char] == 0) {
00357         pdf_printf("/%s", notdef);
00358         is_notdef = true;
00359     }
00360     else {
00361         pdf_printf("/a%i", first_char);
00362         is_notdef = false;
00363     }
00364     for (i = first_char + 1; i <= last_char; i++) {
00365         if (t3_char_procs[i] == 0) {
00366             if (!is_notdef) {
00367                 pdf_printf(" %i/%s", i, notdef);
00368                 is_notdef = true;
00369             }
00370         }
00371         else {
00372             if (is_notdef) {
00373                 pdf_printf(" %i", i);
00374                 is_notdef = false;
00375             }
00376             pdf_printf("/a%i", i);
00377         }
00378     }
00379     pdf_puts("]\n");
00380     pdfenddict();
00381     pdfnewdict(0, 0); /* CharProcs dictionary */
00382     for (i = first_char; i <= last_char; i++)
00383         if (t3_char_procs[i] != 0)
00384             pdf_printf("/a%i %i 0 R\n", (int)i, (int)t3_char_procs[i]);
00385     pdfenddict();
00386     t3_close();
00387     tex_printf(">");
00388     cur_file_name = NULL;
00389 }